]> git.stg.codes - stg.git/blob - projects/stargazer/plugins/other/smux/smux.cpp
11fda6edbd10ce1baa00b14a0c3308e95a6a8837
[stg.git] / projects / stargazer / plugins / other / smux / smux.cpp
1 #include <sys/types.h>
2 #include <sys/socket.h>
3 #include <arpa/inet.h>
4
5 #include <cstring>
6 #include <cerrno>
7 #include <ctime>
8 #include <csignal>
9
10 #include <vector>
11 #include <algorithm>
12
13 #include "asn1/OpenPDU.h"
14 #include "asn1/ClosePDU.h"
15 #include "asn1/RReqPDU.h"
16 #include "asn1/GetRequest-PDU.h"
17 #include "asn1/GetResponse-PDU.h"
18 #include "asn1/VarBindList.h"
19 #include "asn1/VarBind.h"
20 #include "asn1/OBJECT_IDENTIFIER.h"
21 #include "asn1/ber_decoder.h"
22 #include "asn1/der_encoder.h"
23
24 #include "stg/common.h"
25
26 #include "smux.h"
27
28 bool WaitPackets(int sd);
29
30 std::string OI2String(OBJECT_IDENTIFIER_t * oi)
31 {
32 std::string res;
33
34 int arcs[1024];
35 int count = OBJECT_IDENTIFIER_get_arcs(oi, arcs, sizeof(arcs[0]), 1024);
36
37 if (count > 1024)
38     return "";
39
40 for (int i = 0; i < count; ++i)
41     {
42     res += ".";
43     std::string arc;
44     strprintf(&arc, "%d", arcs[i]);
45     res += arc;
46     }
47
48 return res;
49 }
50
51 bool String2OI(const std::string & str, OBJECT_IDENTIFIER_t * oi)
52 {
53 size_t left = 0, pos = 0, arcPos = 0;
54 int arcs[1024];
55 pos = str.find_first_of('.', left);
56 if (pos == 0)
57     {
58     left = 1;
59     pos = str.find_first_of('.', left);
60     }
61 while (pos != std::string::npos)
62     {
63     int arc = 0;
64     if (str2x(str.substr(left, left - pos), arc))
65         {
66         return false;
67         }
68     arcs[arcPos++] = arc;
69     left = pos + 1;
70     pos = str.find_first_of('.', left);
71     }
72 if (left < str.length())
73     {
74     int arc = 0;
75     if (str2x(str.substr(left, left - pos), arc))
76         {
77         return false;
78         }
79     arcs[arcPos++] = arc;
80     }
81 printfd(__FILE__, "String2OI() - arcPos: %d\n", arcPos);
82 OBJECT_IDENTIFIER_set_arcs(oi, arcs, sizeof(arcs[0]), arcPos);
83 return true;
84 }
85
86 class SMUX_CREATOR
87 {
88 private:
89     SMUX * smux;
90
91 public:
92     SMUX_CREATOR() : smux(new SMUX()) {}
93     ~SMUX_CREATOR() { delete smux; }
94
95     SMUX * GetPlugin() { return smux; }
96 };
97
98 SMUX_CREATOR sac;
99
100 PLUGIN * GetPlugin()
101 {
102 return sac.GetPlugin();
103 }
104
105 int SendOpenPDU(int fd)
106 {
107 const char * description = "Stg SMUX Plugin";
108 //int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1, 5, 2, 1, 1};
109 asn_enc_rval_t error;
110 OpenPDU_t msg;
111
112 memset(&msg, 0, sizeof(msg));
113
114 msg.present = OpenPDU_PR_simple;
115 asn_long2INTEGER(&msg.choice.simple.version, SimpleOpen__version_version_1);
116 if (!String2OI(".1.3.6.1.4.1.38313", &msg.choice.simple.identity))
117     {
118     printfd(__FILE__,
119             "SendOpenPDU() - failed to convert string to OBJECT_IDENTIFIER\n");
120     return -1;
121     }
122 OCTET_STRING_fromString(&msg.choice.simple.description, description);
123 OCTET_STRING_fromString(&msg.choice.simple.password, "");
124
125 char buffer[1024];
126 error = der_encode_to_buffer(&asn_DEF_OpenPDU, &msg, buffer, sizeof(buffer));
127
128 if (error.encoded == -1)
129     {
130     printfd(__FILE__, "Could not encode OpenPDU (at %s)\n",
131             error.failed_type ? error.failed_type->name : "unknown");
132     return -1;
133     }
134 else
135     {
136     write(fd, buffer, error.encoded);
137     printfd(__FILE__, "OpenPDU encoded successfully to %d bytes\n",
138             error.encoded);
139     }
140 return 0;
141 }
142
143 int SendClosePDU(int fd)
144 {
145 ClosePDU_t msg;
146
147 memset(&msg, 0, sizeof(msg));
148
149 asn_long2INTEGER(&msg, ClosePDU_goingDown);
150
151 char buffer[1024];
152 asn_enc_rval_t error;
153 error = der_encode_to_buffer(&asn_DEF_ClosePDU, &msg, buffer, sizeof(buffer));
154
155 if (error.encoded == -1)
156     {
157     printfd(__FILE__, "Could not encode ClosePDU (at %s)\n",
158             error.failed_type ? error.failed_type->name : "unknown");
159     return -1;
160     }
161 else
162     {
163     write(fd, buffer, error.encoded);
164     printfd(__FILE__, "ClosePDU encoded successfully\n");
165     }
166 return 0;
167 }
168
169 int SendRReqPDU(int fd)
170 {
171 int oid[] = {1, 3, 6, 1, 4, 1, 38313, 1};
172 asn_enc_rval_t error;
173 RReqPDU_t msg;
174
175 memset(&msg, 0, sizeof(msg));
176
177 msg.priority = 0;
178 asn_long2INTEGER(&msg.operation, RReqPDU__operation_readOnly);
179 OBJECT_IDENTIFIER_set_arcs(&msg.subtree,
180                            oid,
181                            sizeof(oid[0]),
182                            8);
183
184 char buffer[1024];
185 error = der_encode_to_buffer(&asn_DEF_RReqPDU, &msg, buffer, sizeof(buffer));
186
187 if (error.encoded == -1)
188     {
189     printfd(__FILE__, "Could not encode RReqPDU (at %s)\n",
190             error.failed_type ? error.failed_type->name : "unknown");
191     return -1;
192     }
193 else
194     {
195     write(fd, buffer, error.encoded);
196     printfd(__FILE__, "RReqPDU encoded successfully to %d bytes\n",
197             error.encoded);
198     }
199 return 0;
200 }
201
202 int SendGetResponsePDU(int fd, GetResponse_PDU_t * getResponse)
203 {
204 asn_enc_rval_t error;
205
206 char buffer[1024];
207 error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, getResponse, buffer,
208                              sizeof(buffer));
209
210 if (error.encoded == -1)
211     {
212     printfd(__FILE__, "Could not encode GetResponsePDU (at %s)\n",
213             error.failed_type ? error.failed_type->name : "unknown");
214     return -1;
215     }
216 else
217     {
218     write(fd, buffer, error.encoded);
219     printfd(__FILE__, "GetResponsePDU encoded successfully to %d bytes\n",
220             error.encoded);
221     }
222 return 0;
223 }
224
225 int SendGetResponseErrorPDU(int fd,
226                             const PDU_t * getRequest,
227                             int errorStatus,
228                             int errorIndex)
229 {
230 asn_enc_rval_t error;
231 GetResponse_PDU_t msg;
232
233 memset(&msg, 0, sizeof(msg));
234
235 msg.request_id = getRequest->request_id;
236 asn_long2INTEGER(&msg.error_status, errorStatus);
237 asn_long2INTEGER(&msg.error_index, errorIndex);
238
239 char buffer[1024];
240 error = der_encode_to_buffer(&asn_DEF_GetResponse_PDU, &msg, buffer,
241                              sizeof(buffer));
242
243 if (error.encoded == -1)
244     {
245     printfd(__FILE__, "Could not encode GetResponsePDU for error (at %s)\n",
246             error.failed_type ? error.failed_type->name : "unknown");
247     return -1;
248     }
249 else
250     {
251     write(fd, buffer, error.encoded);
252     printfd(__FILE__,
253             "GetResponsePDU for error encoded successfully to %d bytes\n",
254             error.encoded);
255     }
256 return 0;
257 }
258
259 SMUX_PDUs_t * RecvSMUXPDUs(int fd)
260 {
261 char buffer[1024];
262 SMUX_PDUs_t * pdus = NULL;
263
264 memset(buffer, 0, sizeof(buffer));
265
266 size_t length = read(fd, buffer, sizeof(buffer));
267 if (length < 1)
268     return NULL;
269 asn_dec_rval_t error;
270 error = ber_decode(0, &asn_DEF_SMUX_PDUs, (void **)&pdus, buffer, length);
271 if(error.code != RC_OK)
272     {
273     printfd(__FILE__, "Failed to decode PDUs at byte %ld\n",
274             (long)error.consumed);
275     return NULL;
276     }
277 return pdus;
278 }
279
280 int ParseIntInRange(const std::string & str,
281                     int min,
282                     int max,
283                     int * val)
284 {
285 if (str2x(str.c_str(), *val))
286     {
287     return -1;
288     }
289 if (*val < min || *val > max)
290     {
291     return -1;
292     }
293 return 0;
294 }
295
296 SMUX_SETTINGS::SMUX_SETTINGS()
297     : ip(0),
298       port(0)
299 {}
300
301 int SMUX_SETTINGS::ParseSettings(const MODULE_SETTINGS & s)
302 {
303 PARAM_VALUE pv;
304 std::vector<PARAM_VALUE>::const_iterator pvi;
305 int p;
306 ///////////////////////////
307 pv.param = "Port";
308 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
309 if (pvi == s.moduleParams.end())
310     {
311     errorStr = "Parameter \'Port\' not found.";
312     printfd(__FILE__, "Parameter 'Port' not found\n");
313     return -1;
314     }
315 if (ParseIntInRange(pvi->value[0], 2, 65535, &p))
316     {
317     errorStr = "Cannot parse parameter \'Port\': " + errorStr;
318     printfd(__FILE__, "Cannot parse parameter 'Port'\n");
319     return -1;
320     }
321 port = p;
322
323 pv.param = "Password";
324 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
325 if (pvi == s.moduleParams.end())
326     {
327     errorStr = "Parameter \'Password\' not found.";
328     printfd(__FILE__, "Parameter 'Password' not found\n");
329     password = "";
330     }
331 else
332     {
333     password = pvi->value[0];
334     }
335
336 pv.param = "Server";
337 pvi = std::find(s.moduleParams.begin(), s.moduleParams.end(), pv);
338 if (pvi == s.moduleParams.end())
339     {
340     errorStr = "Parameter \'Server\' not found.";
341     printfd(__FILE__, "Parameter 'Server' not found\n");
342     return -1;
343     }
344 ip = inet_strington(pvi->value[0]);
345
346 return 0;
347 }
348
349 SMUX::SMUX()
350     : PLUGIN(),
351       users(NULL),
352       tariffs(NULL),
353       running(false),
354       stopped(true),
355       sock(-1)
356 {
357 pthread_mutex_init(&mutex, NULL);
358
359 smuxHandlers[SMUX_PDUs_PR_close] = &SMUX::CloseHandler;
360 smuxHandlers[SMUX_PDUs_PR_registerResponse] = &SMUX::RegisterResponseHandler;
361 smuxHandlers[SMUX_PDUs_PR_pdus] = &SMUX::PDUsHandler;
362 smuxHandlers[SMUX_PDUs_PR_commitOrRollback] = &SMUX::CommitOrRollbackHandler;
363
364 pdusHandlers[PDUs_PR_get_request] = &SMUX::GetRequestHandler;
365 pdusHandlers[PDUs_PR_get_next_request] = &SMUX::GetNextRequestHandler;
366 pdusHandlers[PDUs_PR_set_request] = &SMUX::SetRequestHandler;
367 }
368
369 SMUX::~SMUX()
370 {
371 Sensors::iterator it;
372 for (it = sensors.begin(); it != sensors.end(); ++it)
373     delete it->second;
374 printfd(__FILE__, "SMUX::~SMUX()\n");
375 pthread_mutex_destroy(&mutex);
376 }
377
378 int SMUX::ParseSettings()
379 {
380 return smuxSettings.ParseSettings(settings);
381 }
382
383 int SMUX::Start()
384 {
385 if (PrepareNet())
386     return -1;
387
388 // Users
389 sensors[".1.3.6.1.4.1.38313.1.1.1"] = new TotalUsersSensor(*users);
390 sensors[".1.3.6.1.4.1.38313.1.1.2"] = new ConnectedUsersSensor(*users);
391 sensors[".1.3.6.1.4.1.38313.1.1.3"] = new AuthorizedUsersSensor(*users);
392 sensors[".1.3.6.1.4.1.38313.1.1.4"] = new AlwaysOnlineUsersSensor(*users);
393 sensors[".1.3.6.1.4.1.38313.1.1.5"] = new NoCashUsersSensor(*users);
394 sensors[".1.3.6.1.4.1.38313.1.1.7"] = new DisabledDetailStatsUsersSensor(*users);
395 sensors[".1.3.6.1.4.1.38313.1.1.8"] = new DisabledUsersSensor(*users);
396 sensors[".1.3.6.1.4.1.38313.1.1.9"] = new PassiveUsersSensor(*users);
397 sensors[".1.3.6.1.4.1.38313.1.1.10"] = new CreditUsersSensor(*users);
398 sensors[".1.3.6.1.4.1.38313.1.1.11"] = new FreeMbUsersSensor(*users);
399 sensors[".1.3.6.1.4.1.38313.1.1.12"] = new TariffChangeUsersSensor(*users);
400 // Tariffs
401 sensors[".1.3.6.1.4.1.38313.1.2.1"] = new TotalTariffsSensor(*tariffs);
402
403 if (!running)
404     {
405     if (pthread_create(&thread, NULL, Runner, this))
406         {
407         errorStr = "Cannot create thread.";
408         printfd(__FILE__, "Cannot create thread\n");
409         return -1;
410         }
411     }
412
413 return 0;
414 }
415
416 int SMUX::Stop()
417 {
418 printfd(__FILE__, "SMUX::Stop() - Before\n");
419 running = false;
420
421 if (!stopped)
422     {
423     //5 seconds to thread stops itself
424     for (int i = 0; i < 25 && !stopped; i++)
425         {
426         struct timespec ts = {0, 200000000};
427         nanosleep(&ts, NULL);
428         }
429
430     //after 5 seconds waiting thread still running. now killing it
431     if (!stopped)
432         {
433         printfd(__FILE__, "SMUX::Stop() - failed to stop thread, killing it\n");
434         if (pthread_kill(thread, SIGINT))
435             {
436             errorStr = "Cannot kill thread.";
437             printfd(__FILE__, "SMUX::Stop() - Cannot kill thread\n");
438             return -1;
439             }
440         printfd(__FILE__, "SMUX::Stop() -  killed Run\n");
441         }
442     }
443
444 pthread_join(thread, NULL);
445
446 close(sock);
447
448 printfd(__FILE__, "SMUX::Stop() - After\n");
449 return 0;
450 }
451
452 void * SMUX::Runner(void * d)
453 {
454 SMUX * smux = static_cast<SMUX *>(d);
455
456 smux->Run();
457
458 return NULL;
459 }
460
461 void SMUX::Run()
462 {
463 SendOpenPDU(sock);
464 SendRReqPDU(sock);
465 running = true;
466 stopped = false;
467 while(running)
468     {
469     if (WaitPackets(sock))
470         {
471         SMUX_PDUs_t * pdus = RecvSMUXPDUs(sock);
472         if (pdus)
473             DispatchPDUs(pdus);
474         }
475     if (!running)
476         break;
477     }
478 SendClosePDU(sock);
479 stopped = true;
480 }
481
482 bool SMUX::PrepareNet()
483 {
484 sock = socket(AF_INET, SOCK_STREAM, 0);
485
486 if (sock < 0)
487     {
488     errorStr = "Cannot create socket.";
489     printfd(__FILE__, "Cannot create socket\n");
490     return true;
491     }
492
493 struct sockaddr_in addr;
494
495 addr.sin_family = AF_INET;
496 addr.sin_port = htons(smuxSettings.GetPort());
497 addr.sin_addr.s_addr = smuxSettings.GetIP();
498
499 if (connect(sock, reinterpret_cast<struct sockaddr *>(&addr), sizeof(addr)))
500     {
501     errorStr = "Cannot connect.";
502     printfd(__FILE__, "Cannot connect. Message: '%s'\n", strerror(errno));
503     return true;
504     }
505
506 return false;
507 }
508
509 bool WaitPackets(int sd)
510 {
511 fd_set rfds;
512 FD_ZERO(&rfds);
513 FD_SET(sd, &rfds);
514
515 struct timeval tv;
516 tv.tv_sec = 0;
517 tv.tv_usec = 500000;
518
519 int res = select(sd + 1, &rfds, NULL, NULL, &tv);
520 if (res == -1) // Error
521     {
522     if (errno != EINTR)
523         {
524         printfd(__FILE__, "Error on select: '%s'\n", strerror(errno));
525         }
526     return false;
527     }
528
529 if (res == 0) // Timeout
530     {
531     return false;
532     }
533
534 return true;
535 }
536
537 bool SMUX::DispatchPDUs(const SMUX_PDUs_t * pdus)
538 {
539 SMUXHandlers::iterator it;
540 it = smuxHandlers.find(pdus->present);
541 if (it != smuxHandlers.end())
542     {
543     return (this->*(it->second))(pdus);
544     }
545 else
546     {
547     switch (pdus->present)
548         {
549         case SMUX_PDUs_PR_NOTHING:
550             printfd(__FILE__, "PDUs: nothing\n");
551             break;
552         case SMUX_PDUs_PR_open:
553             printfd(__FILE__, "PDUs: open\n");
554             break;
555         case SMUX_PDUs_PR_registerRequest:
556             printfd(__FILE__, "PDUs: registerRequest\n");
557             break;
558         default:
559             printfd(__FILE__, "PDUs: undefined\n");
560         }
561     asn_fprint(stderr, &asn_DEF_SMUX_PDUs, pdus);
562     }
563 return false;
564 }