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