Removed system function invocations and placed forked execl instead
[vlp.git] / src / net / lognet.cpp
1 #include "genint1.h"
2 #include "comm.h"
3
4 #include <sys/socket.h>
5 #include <sys/un.h>
6 #include <netinet/in.h>
7 #include <errno.h>
8 #include <netdb.h>
9 #include <arpa/inet.h>
10
11 #include <sys/types.h>
12 #include <sys/time.h>
13 #include <stdlib.h>
14 #include <stdio.h>
15 #include <fcntl.h>
16 #include <signal.h>
17 #include <sys/stat.h>
18 #include <string.h>
19 #include <QtCore/qlist.h>
20 #include <QtCore/qfile.h>
21 #include <QtCore/qstring.h>
22 #include <QtCore/qstringlist.h>
23 #include <QtCore/QDir>
24 #include <unistd.h>
25
26 #include <libconfig.h>
27
28 #define REMOTE_PATH "REMOTE"
29 #define MAXLINKS 30
30 #define LOGPORT 3600
31 #define CODEPORT 3700
32 #define CODEPORT1 3800
33 #define MAXINTERP 10
34 #define FILE_BUFFER_SIZE 2048
35
36
37
38 /*************** Interpreter slot ********************/
39 class INTlink {
40 public:
41         int sock;
42         int ID;
43         bool connected;
44         INTlink();
45 };
46
47 INTlink::INTlink()
48 {
49         connected = FALSE;
50         sock = 0;
51 }
52
53 /*********************  Network slot ********************/
54 class NETlink {
55 public:
56         int sock;
57         bool connected;
58         bool code_transmit;
59         char addr[255];
60
61         int node_number;
62         int aliases[5];
63
64         FILE *CodeFile;
65         char CodeName[255];
66         long CodeSize;
67
68         NETlink();
69 };
70
71 NETlink::NETlink()
72 {
73         int i;
74         for(i = 0; i < 5; i++) 
75                 aliases[i] = -1;
76
77         connected = FALSE;
78         sock = 0;
79         code_transmit = FALSE;
80 }
81
82 /*********************** NET Module *****************************/
83
84 class NETMOD {
85 public:
86         int kernel_sock;
87         int listen_sock;
88         bool all_connected;
89         bool local_mode;
90         int to_connect;
91         int MyNode;
92         char kername[256];
93
94         /* List of the Interpeter slots */
95         QList<INTlink*> Interpreters;
96         /* List of the Network slots */ 
97         QList<NETlink*> Links;
98
99         NETMOD(int argc, char ** argv);
100
101         void load_config(const char*);
102         void write_at_console(char*);
103         void send_to_kernel(MESSAGE*);
104         void sock_reopen(NETlink*);
105         void send_connect_info(NETlink*);
106         void send_accept_info(NETlink*);
107         void send_to_node(NETlink*, MESSAGE*);
108         void send_to_int(MESSAGE*);
109         void send_code_ack(NETlink*);
110         void send_to_all(MESSAGE *);
111
112         NETlink *findNETlink(int node);
113         INTlink *findINTlink(int id);
114         void transmit_file(int ton, char *fname, int fromINT);
115         void propagate_msg(MESSAGE *msg);
116         void check_node(int, int);
117
118         void run();
119         void exit_sequence();
120         void disconnect_seq();
121         void connect_seq(char*);
122         void accept_connection();
123         void get_internal();
124         void remote_messages(); 
125         void check_links();
126         void get_message(NETlink*);
127         void conn_info(int);
128
129         /* 2010 */
130         void doitall();
131 };
132
133 NETMOD::NETMOD(int argc, char ** argv)
134 {
135         QString kernelSocket(argv[1]);
136         QString configFile(argv[2]);
137
138         int i;
139         int len;
140         int on;
141         struct sockaddr_in svr;
142         struct sockaddr_un svr1;
143         MESSAGE m;
144         char s[256];
145
146         Links.clear();
147         Interpreters.clear();
148
149         bzero(&svr, sizeof(svr));
150         listen_sock = socket(AF_INET, SOCK_STREAM, 0);
151         svr.sin_family = AF_INET;
152         svr.sin_addr.s_addr = INADDR_ANY;
153         svr.sin_port = htons(LOGPORT);
154         bind(listen_sock, (struct sockaddr*)&svr, sizeof(svr));
155         listen(listen_sock,5);
156         fcntl(listen_sock, F_SETFL, O_NONBLOCK | fcntl(listen_sock, F_GETFL, 0));
157
158         to_connect = 0;
159         all_connected = FALSE;
160
161         load_config(configFile.toStdString().c_str());
162
163         kernel_sock = socket(AF_UNIX, SOCK_STREAM, 0);
164         bzero(&svr1, sizeof(svr1));
165         svr1.sun_family = AF_UNIX;
166         strcpy(svr1.sun_path, kernelSocket.toStdString().c_str());
167         strcpy(kername, kernelSocket.toStdString().c_str());
168         len = strlen(svr1.sun_path) + sizeof(svr1.sun_family);
169         i = connect(kernel_sock, (struct sockaddr*)&svr1, len);
170         if (i == 0)
171                 fcntl(kernel_sock, F_SETFL, O_NONBLOCK|fcntl(kernel_sock, F_GETFL, 0));
172         on = 1;
173         setsockopt(kernel_sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
174         m.msg_type = MSG_NET;
175         m.param.pword[0] = NET_NODE;
176         m.param.pword[1] = MyNode;
177         send_to_kernel(&m);
178
179         /* if (regme) regme_sequence();*/
180
181         if (to_connect > 0) {
182                 write_at_console("Connecting remote VLPs...");  
183                 while (!all_connected) {
184                         check_links();
185                 }
186         }
187         sprintf(s, "Local node number %d", MyNode);
188         write_at_console(s);
189 }
190
191 /*#####################  Load configuration ##########################*/
192
193 void NETMOD::load_config(const char *fname)
194 {
195         config_t cfg;
196         config_setting_t *setting;
197         int on;
198         int k = 0;
199         NETlink *pomlink;
200
201         config_init(&cfg);
202
203         /* Hack for checking if file exists without using external libs.*/
204         FILE * file = fopen(fname, "rt");
205         if (!file) {
206                 fprintf(stderr, "[Error]/Lognet: Cannot load configuration file %s!\n", fname);
207                 write_at_console("Cannot load configuration file!");
208                 fclose(file);
209                 exit(3);
210         }
211
212         /* Read the file. If there is an error, report it and exit. */
213         if (!config_read(&cfg, file))  {
214                 fprintf(stderr, "%s: In file %s, line %d\n",
215                                                 config_error_text(&cfg),
216                                                 config_error_file(&cfg),
217                                                 config_error_line(&cfg));
218                 config_destroy(&cfg);
219                 fclose(file);
220                 /* from original code. */
221                 exit(3);
222         }
223
224         setting = config_lookup(&cfg, "node_number");
225         if (setting) {
226                 MyNode = config_setting_get_int(setting);
227         }
228         /* else */
229         if (!setting || MyNode == -1) {
230                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
231                                                 "Error", fname, "node_number");
232                 write_at_console("Node number must be specified");
233                 config_destroy(&cfg);
234                 fclose(file);
235                 exit(1);
236         }
237
238         setting = config_lookup(&cfg, "host");  
239         if (setting) {
240                 k++;
241                 pomlink = new NETlink;
242
243                 switch(config_setting_type(setting)) {
244                 /* TODO: Deprecated. Made for back compatibility. */
245                 case CONFIG_TYPE_STRING:
246                         strncpy(pomlink->addr,
247                                 config_setting_get_string(setting), 255);
248                         break;
249                 case CONFIG_TYPE_ARRAY:
250                         strncpy(pomlink->addr,
251                                 config_setting_get_string_elem(setting, 0), 255);
252                         break;
253                 default:
254                         fprintf(stderr, "%s! In file %s, bad entry type for %s."
255                                                 " Will not be read.\n",
256                                                 "Fatal error", fname, "host");
257                         config_destroy(&cfg);
258                         fclose(file);
259                         exit(1);
260                 }
261                 pomlink->connected = FALSE;
262                 pomlink->sock = socket(AF_INET, SOCK_STREAM, 0); 
263                 fcntl(pomlink->sock, F_SETFL,O_NONBLOCK |
264                                         fcntl(pomlink->sock, F_GETFL, 0));
265                 on = 1; 
266                 setsockopt(pomlink->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
267                                                                 sizeof(on)); 
268                 Links.append(pomlink); 
269                 to_connect++;
270         } else {
271                 fprintf(stderr, "%s! In file %s, '%s' was not found.\n",
272                                                 "Warning", fname, "host");
273         }
274
275         config_destroy(&cfg);
276         fclose(file);
277
278         if (k == 0) {
279                 all_connected = TRUE;
280         }
281 }
282
283 void NETMOD::write_at_console(char *s)
284 {
285         MESSAGE msg;
286
287         msg.msg_type = MSG_NET;
288         msg.param.pword[0] = NET_CSWRITELN;
289         strcpy(msg.param.pstr, s);
290         send_to_kernel(&msg);
291 }
292
293 /**
294  * Sends message to kernel
295  * @param msg Message to send.
296  */
297 void NETMOD::send_to_kernel(MESSAGE *msg)
298 {
299         write(kernel_sock, msg, sizeof(MESSAGE));
300 }
301
302 /**
303  * Sends message to given node
304  * @param lnk Interpreter link.
305  * @param msg Message to send.
306  */
307 void NETMOD::send_to_node(NETlink *lnk, MESSAGE *msg)
308 {
309         msg->msg_type = MSG_NET;
310         /* msg2netmsg(msg);*/
311         if (lnk->sock) {
312                 write(lnk->sock, msg, sizeof(MESSAGE));
313         }
314 }
315
316 /**
317  * Sends message to interpreter
318  * @param msg Message to send.
319  */
320 void NETMOD::send_to_int(MESSAGE *msg)
321 {
322         INTlink *pomlink;
323
324         pomlink = findINTlink(msg->param.pword[5]);
325         if (pomlink != NULL) {
326                 write(pomlink->sock, msg, sizeof(MESSAGE));
327         }
328 }
329
330 void NETMOD::accept_connection()
331 {
332         unsigned int sz;
333         int nsock;
334         int on;
335         struct sockaddr_in svr;
336         fd_set rset;
337         fd_set wset;
338         struct timeval tout = {0, 0};
339         NETlink *pomlink;
340
341         FD_ZERO(&rset);
342         FD_ZERO(&wset);
343         FD_SET(listen_sock, &rset);
344
345         if (select(listen_sock + 1, &rset, &wset, 0, (struct timeval *)&tout) >
346                                                                         0) {
347                 if (FD_ISSET(listen_sock,&rset)) {
348                         /* accept connection on listen socket */
349                         sz = sizeof(svr);
350                         bzero(&svr, sizeof(svr));
351                         nsock = accept(listen_sock, (struct sockaddr*)&svr,
352                                                                         &sz);
353
354                         if (nsock > 0) {
355
356                                 /* i<0 someone wants to connect us */
357                                 pomlink = new NETlink;
358                                 strcpy(pomlink->addr, inet_ntoa(svr.sin_addr));
359                                 pomlink->sock = nsock;
360                                 pomlink->connected = TRUE;
361                                 fcntl(pomlink->sock, F_SETFL, O_NONBLOCK |
362                                         fcntl(pomlink->sock, F_GETFL,0));
363                                 on = 1;
364                                 setsockopt(pomlink->sock, IPPROTO_TCP,
365                                         TCP_NODELAY, (char*)&on, sizeof(on));
366                                 Links.append(pomlink);
367                         } /* nsock > 0 */
368                 } /* ISSET */
369         }
370 }
371
372
373 void NETMOD::check_node(int n, int sc)
374 {
375         MESSAGE m;
376         NETlink *pomlink;
377
378         m.msg_type = MSG_NET;
379         m.param.pword[0] = NET_NODE_EXIST;
380
381         pomlink = Links.first();
382         m.param.pword[1] = 0;
383         while (pomlink != NULL) {
384                 if (pomlink->node_number == n) {
385                         m.param.pword[1] = 1;
386                         strcpy(m.param.pstr, pomlink->addr);
387                         break;
388                 }
389                 pomlink = Links.takeFirst();
390         }
391         write(sc, &m, sizeof(MESSAGE));
392 }
393
394
395 /**
396  * Internal message from kernel or INT
397  */
398 void NETMOD::get_internal()
399 {
400         int nr;
401         int nrset;
402         MESSAGE msg;
403         int si;
404         int sj;
405         fd_set readset;
406         fd_set writeset;
407         struct timeval tout= {0, 0};
408         INTlink *pomlink;
409         struct sockaddr_un svr;
410
411         FD_ZERO(&readset);
412         FD_ZERO(&writeset);
413         FD_SET(kernel_sock, &readset);
414         nrset = kernel_sock;
415
416         pomlink = Interpreters.first();
417         while (pomlink != NULL) {
418                 FD_SET(pomlink->sock, &readset);
419                 if (nrset < pomlink->sock) {
420                         nrset = pomlink->sock;
421                 }
422                 pomlink = Interpreters.takeFirst();
423         }
424
425         if (select(nrset + 1, &readset, &writeset, 0, (struct timeval *)&tout) >
426                                                                         0) {
427
428                 /* Check request sockets */
429                 pomlink = Interpreters.first();
430                 while (pomlink != NULL) {
431                         if (FD_ISSET(pomlink->sock, &readset)) {
432                                 nr = read(pomlink->sock, &msg, sizeof(MESSAGE));
433                                 if (nr > 0) {
434                                         if (msg.msg_type == MSG_NET) {
435                                                 switch(msg.param.pword[0]) {
436                                                 case NET_PROPAGATE:
437                                                         propagate_msg(&msg);
438                                                         break;
439                                                 case NET_NODE_EXIST:
440                                                         check_node(msg.param.pword[1], pomlink->sock);
441                                                         break;
442                                                 case NET_GET_INFO: 
443                                                         conn_info(pomlink->sock);
444                                                         break;
445                                                 case NET_NODES_NUM:
446                                                         msg.param.pword[0] = NET_NODES_NUM_RESPONSE;
447                                                         msg.param.pword[1] = Links.count();
448                                                         write(pomlink->sock, &msg, sizeof(MESSAGE));
449                                                         break;
450                                                 }/* switch */
451                                         }
452                                 }
453                         } /* ISSET */
454                         pomlink=Interpreters.takeFirst();
455                 } // while
456
457                 /* Check internal socket */
458                 if (FD_ISSET(kernel_sock,&readset)) {
459                         nr = read(kernel_sock, &msg, sizeof(MESSAGE));
460                         if (nr > 0) {
461                                 if (msg.msg_type == MSG_NET) {
462                                         switch(msg.param.pword[0]) { 
463                                         case NET_TRANSMIT_CODE:
464                                                 transmit_file(msg.param.pword[2],
465                                                         msg.param.pstr, 
466                                                         msg.param.pword[1]);
467                                                 break;
468                                         case NET_EXIT:
469                                                 disconnect_seq();
470                                                 exit_sequence();
471                                                 break;
472                                         case NET_GET_INFO:
473                                                 conn_info(kernel_sock);
474                                                 break;
475                                         case NET_PROPAGATE:
476                                                 propagate_msg(&msg);
477                                                 break;
478                                         case NET_DISCONNECT:
479                                                 disconnect_seq();
480                                                 break;
481                                         case NET_NODE_EXIST:
482                                                 check_node(msg.param.pword[1], kernel_sock);
483                                                 break;
484                                         case NET_CONNECT_TO:
485                                                 connect_seq(msg.param.pstr);
486                                         } /* end switch */
487                                 } /* MSg_NET */
488
489                                 if (msg.msg_type == MSG_VLP) {
490                                         switch(msg.param.pword[0]) {
491                                         case VLP_REGINT: {
492                                                 pomlink = new INTlink;
493                                                 pomlink->sock = socket(AF_UNIX, SOCK_STREAM, 0);
494                                                 bzero(&svr,sizeof(svr));
495                                                 svr.sun_family = AF_UNIX;
496                                                 strcpy(svr.sun_path, msg.param.pstr);
497                                                 si = strlen(svr.sun_path) + sizeof(svr.sun_family);
498                                                 sj = connect(pomlink->sock, (struct sockaddr*)&svr, si);
499                                                 if (sj == 0)
500                                                         fcntl(pomlink->sock, F_SETFL, O_NONBLOCK | fcntl(pomlink->sock, F_GETFL, 0));
501                                                 int on = 1;
502                                                 setsockopt(pomlink->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
503                                                 pomlink->ID = msg.param.pword[1];
504                                                 pomlink->connected=TRUE;
505                                                 Interpreters.append(pomlink);
506                                                 };
507                                                 break;
508                                         case VLP_INTERPRETER_DOWN: {
509                                                 pomlink = findINTlink(msg.param.pword[1]);
510                                                 if (pomlink != NULL) {
511                                                         close(pomlink->sock);
512                                                         Interpreters.removeOne(pomlink);
513                                                 }
514                                                 };
515                                                 break;
516                                         break;
517                                         }
518                                 }
519                         }
520                 }
521         }
522 }
523
524 void NETMOD::get_message(NETlink *lnk)
525 {
526         int nr;
527         MESSAGE msg;
528         char pomstr[80];
529         int rdbt;
530         int rd;
531         int sz;
532         int j;
533         int psock;
534         struct sockaddr_in svr;
535         unsigned char buffer[FILE_BUFFER_SIZE];
536         protdescr proto;
537
538         if (lnk->connected) {
539                 nr = read(lnk->sock, &msg, sizeof(MESSAGE));
540                 if (nr > 0) {
541                         /* netmsg2msg(&msg); */
542                         if (msg.msg_type == MSG_NET) {
543                                 switch(msg.param.pword[0]) {
544                                 case NET_CCD_START:
545                                         lnk->code_transmit = TRUE;
546                                         sprintf(pomstr, "%s/%s", REMOTE_PATH, msg.param.pstr);
547                                         strcat(pomstr,".ccd");
548                                         lnk->CodeFile = fopen(pomstr, "wb");
549                                         if (lnk->CodeFile == NULL) {
550                                                 write_at_console("Cannot open file\n");
551                                                 lnk->code_transmit = FALSE;
552                                         }
553                                         lnk->CodeSize = msg.param.pword[1];
554                                         psock = socket(AF_INET, SOCK_STREAM, 0); 
555                                         bzero(&svr, sizeof(svr));
556                                         svr.sin_family = AF_INET;
557                                         svr.sin_port = htons(CODEPORT);
558                                         svr.sin_addr.s_addr = inet_addr(lnk->addr);
559                                         j = connect(psock, (struct sockaddr*)&svr, sizeof(svr));
560                                         if (j == 0) {
561                                                 /*fcntl(psock, F_SETFL,O_NONBLOCK | fcntl(psock, F_GETFL,0));*/
562                                                 sz = 0;
563                                                 while (sz < lnk->CodeSize) {
564                                                         rd = read(psock, &buffer, sizeof(buffer));
565                                                         rdbt = fwrite(&buffer, sizeof(unsigned char), rd, lnk->CodeFile);
566                                                         sz = sz + rd;
567                                                 }
568                                                 close(psock);
569                                                 fclose(lnk->CodeFile);
570                                         }
571                                         break;
572                                 case NET_PCD_START:
573                                         lnk->code_transmit = TRUE;
574                                         sprintf(pomstr, "%s/%s", REMOTE_PATH, msg.param.pstr);
575                                         strcat(pomstr, ".pcd");
576                                         lnk->CodeFile = fopen(pomstr, "wb");
577                                         if (lnk->CodeFile == NULL) {
578                                                 write_at_console("Cannot open file\n");
579                                                 lnk->code_transmit = FALSE;
580                                         }
581                                         lnk->CodeSize = msg.param.pword[1];
582                                         psock = socket(AF_INET, SOCK_STREAM, 0); 
583                                         bzero(&svr, sizeof(svr));
584                                         svr.sin_family = AF_INET;
585                                         svr.sin_port = htons(CODEPORT1);
586                                         svr.sin_addr.s_addr = inet_addr(lnk->addr);
587                                         j = connect(psock, (struct sockaddr*)&svr, sizeof(svr));
588                                         if (j == 0) {
589                                                 /*fcntl(psock, F_SETFL,O_NONBLOCK | fcntl(psock, F_GETFL,0));*/
590                                                 sz = 0;
591                                                 while (sz < lnk->CodeSize) {
592                                                         rd = read(psock, &proto, sizeof(proto));
593                                                         rdbt = fwrite(&proto, sizeof(unsigned char), rd, lnk->CodeFile);
594                                                         sz = sz + rd;
595                                                 }
596                                                 close(psock);
597                                                 fclose(lnk->CodeFile);
598                                         }
599                                         break;
600                                 case NET_CONNECT:
601                                         sprintf(pomstr, "Node: %d Addr: %s",
602                                                 msg.param.pword[1], lnk->addr);
603                                         lnk->node_number = msg.param.pword[1];
604                                         write_at_console(pomstr);
605                                         send_accept_info(lnk);
606                                         break;
607                                 case NET_ACCEPT:
608                                         sprintf(pomstr, "Node: %d Addr: %s",
609                                                 msg.param.pword[1], lnk->addr);
610                                         lnk->node_number = msg.param.pword[1];
611                                         write_at_console(pomstr);
612                                         break;
613                                 case NET_DISCONNECT:
614                                         sprintf(pomstr,"Node: %d disconnected",
615                                                 msg.param.pword[1]);
616                                         write_at_console(pomstr);
617                                         ::close(lnk->sock);
618                                         Links.removeOne(lnk);
619                                         delete lnk;
620                                         break;
621                                 case NET_PROPAGATE:
622                                         if (msg.param.pword[1] == MSG_VLP) {
623                                                 send_to_kernel(&msg);
624                                         } else if (msg.param.pword[1] == MSG_INT) {
625                                                 send_to_int(&msg);
626                                         }
627                                         break;
628                                 }
629                         }
630                 }
631
632         }
633 }
634
635
636
637 void NETMOD::remote_messages()
638 {
639         int max;
640         fd_set rset, wset;
641         struct timeval tout={0, 0};
642         NETlink *pomlink;
643
644         FD_ZERO(&rset);
645         FD_ZERO(&wset);
646         max = 0;
647
648         pomlink = Links.first();
649         while (pomlink != NULL) {
650                 if (pomlink->connected) {
651                         FD_SET(pomlink->sock, &rset);
652                         if (max < pomlink->sock){
653                                 max = pomlink->sock;
654                         }
655                 }
656                 pomlink=Links.takeFirst();
657         }
658
659         if (select(max + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
660                 pomlink=Links.first();
661                 while (pomlink!=NULL) {
662                         if (FD_ISSET(pomlink->sock,&rset)) {
663                                 get_message(pomlink);
664                         }
665                         pomlink=Links.takeFirst();
666                 }
667         }
668 }
669
670 /******************************2010********************************************/
671 void NETMOD::doitall() {
672         unsigned int sz;
673         int nsock,max = 0, on, nr, si, sj;
674         struct sockaddr_in svr;
675         fd_set rset;
676         NETlink *pomlink;
677         INTlink *pomlink2;
678         struct sockaddr_un svr2;
679         MESSAGE msg;
680
681         FD_ZERO(&rset);
682         FD_SET(listen_sock, &rset);
683         max = listen_sock;
684         FD_SET(kernel_sock, &rset);
685         if (max < kernel_sock) {
686                 max=kernel_sock;
687         }
688         pomlink2 = Interpreters.first();
689         while (pomlink2 != NULL) {
690                 FD_SET(pomlink2->sock, &rset);
691                 if (max < pomlink2->sock) {
692                         max=pomlink2->sock;
693                 }
694                 pomlink2 = Interpreters.takeFirst();
695         }
696         pomlink = Links.first();
697         while (pomlink != NULL) {
698                 if (pomlink->connected) {
699                         FD_SET(pomlink->sock, &rset);
700                         if (max < pomlink->sock) {
701                                 max = pomlink->sock;
702                         }
703                 }
704                 pomlink=Links.takeFirst();
705         }
706
707         /* odczyt */
708         if (select(max + 1, &rset, 0, 0, NULL) > 0) {
709                 /* accept connection */
710                 if (FD_ISSET(listen_sock,&rset)) {
711                         /* accept connection on listen socket */
712                         sz = sizeof(svr);
713                         bzero(&svr, sizeof(svr));
714                         nsock = accept(listen_sock, (struct sockaddr*)&svr, &sz);
715                         if (nsock > 0) {
716                                 pomlink = new NETlink;
717                                 strcpy(pomlink->addr, inet_ntoa(svr.sin_addr));
718                                 pomlink->sock = nsock;
719                                 pomlink->connected = TRUE;
720                                 fcntl(pomlink->sock, F_SETFL,O_NONBLOCK |
721                                         fcntl(pomlink->sock, F_GETFL, 0));
722                                 on = 1;
723                                 setsockopt(pomlink->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
724                                 Links.append(pomlink);
725                         } /* nsock > 0 */
726                 } /* ISSET */
727
728                 /* get internal message*/
729                 /* Check request sockets */
730                 pomlink2 = Interpreters.first();
731                 while (pomlink2 != NULL) {
732                         if (FD_ISSET(pomlink2->sock,&rset)) {
733                                 nr = read(pomlink2->sock, &msg, sizeof(MESSAGE));
734                                 if (nr > 0) {
735                                         if (msg.msg_type == MSG_NET) {
736                                                 switch(msg.param.pword[0]) {
737                                                 case NET_PROPAGATE:
738                                                         propagate_msg(&msg);
739                                                         break;
740                                                 case NET_NODE_EXIST:
741                                                         check_node(msg.param.pword[1], pomlink2->sock);
742                                                         break;
743                                                 case NET_GET_INFO:
744                                                         conn_info(pomlink2->sock);
745                                                         break;
746                                                 case NET_NODES_NUM:
747                                                         msg.param.pword[0] = NET_NODES_NUM_RESPONSE;
748                                                         msg.param.pword[1] = Links.count();
749                                                         write(pomlink2->sock, &msg, sizeof(MESSAGE));
750                                                         break;
751                                                 }/* switch */
752                                         }
753                                 }
754                         }/* ISSET */
755                         pomlink2 = Interpreters.takeFirst();
756                 }/* while */
757
758                 /* Check internal socket */
759                 if (FD_ISSET(kernel_sock, &rset)) {
760                         nr = read(kernel_sock, &msg, sizeof(MESSAGE));
761                         if (nr > 0) {
762                                 if (msg.msg_type == MSG_NET) {
763                                         switch(msg.param.pword[0]) { 
764                                         case NET_TRANSMIT_CODE:
765                                                 transmit_file(msg.param.pword[2], msg.param.pstr, msg.param.pword[1]);  
766                                                 break;
767                                         case NET_EXIT:
768                                                 disconnect_seq();
769                                                 exit_sequence();
770                                                 break;
771                                         case NET_GET_INFO:
772                                                 conn_info(kernel_sock);
773                                                 break;
774                                         case NET_PROPAGATE:
775                                                 propagate_msg(&msg);
776                                                 break;
777                                         case NET_DISCONNECT:
778                                                 disconnect_seq();
779                                                 break;
780                                         case NET_NODE_EXIST:
781                                                 check_node(msg.param.pword[1], kernel_sock);
782                                                 break;
783                                         case NET_CONNECT_TO:
784                                                 connect_seq(msg.param.pstr);
785                                         } /* end switch */
786                                 } /* MSG_NET */
787                                 if (msg.msg_type == MSG_VLP) {
788                                         switch(msg.param.pword[0]) {
789                                         case VLP_REGINT: {
790                                                 pomlink2 = new INTlink;
791                                                 pomlink2->sock = socket(AF_UNIX, SOCK_STREAM, 0);
792                                                 bzero(&svr2, sizeof(svr2));
793                                                 svr2.sun_family = AF_UNIX;
794                                                 strcpy(svr2.sun_path, msg.param.pstr);
795                                                 si = strlen(svr2.sun_path) + sizeof(svr2.sun_family);
796                                                 sj = connect(pomlink2->sock,(struct sockaddr*)&svr2, si);
797                                                 if (sj == 0)
798                                                         fcntl(pomlink2->sock,F_SETFL, O_NONBLOCK | fcntl(pomlink2->sock, F_GETFL, 0));
799                                                 int on = 1;
800                                                 setsockopt(pomlink2->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
801                                                 pomlink2->ID = msg.param.pword[1];
802                                                 pomlink2->connected = TRUE;
803                                                 Interpreters.append(pomlink2);
804                                                 };
805                                                 break;
806                                         case VLP_INTERPRETER_DOWN: {
807                                                 pomlink2 = findINTlink(msg.param.pword[1]);
808                                                 if (pomlink2 != NULL) {
809                                                         close(pomlink2->sock);
810                                                         Interpreters.removeOne(pomlink2);
811                                                 }
812                                                 };
813                                                 break;
814                                         } /* MSg_VLP */
815                                 }
816                         } /* nr > 0 */
817                 }/* ISSET */
818
819                 /* get remote message*/
820
821                 pomlink=Links.first();
822                 while (pomlink != NULL) {
823                         if (FD_ISSET(pomlink->sock, &rset))
824                                 get_message(pomlink);
825                         pomlink=Links.takeFirst();
826                 }
827         } // select 
828 }
829 /****************************** END 2010 **************************************/
830
831
832
833 void NETMOD::propagate_msg(MESSAGE *msg)
834 {
835         char ss[255];
836         NETlink *pomlink;
837
838         pomlink = findNETlink(msg->param.pword[4]);
839         if ((pomlink != NULL) && (pomlink->connected))
840                 send_to_node(pomlink, msg);
841         else {
842                 if (msg->param.pword[1] == MSG_INT) {
843                         send_to_int(msg);
844                 } else {
845                         sprintf(ss, "Not connected to Node %d",
846                                                         msg->param.pword[4]);  
847                         write_at_console(ss);
848                 }
849         }
850 }
851
852 void NETMOD::connect_seq(char *a)
853 {
854         NETlink *pom;
855         struct sockaddr_in svr;
856         int j, on;
857
858         pom = Links.first();
859         while (pom != NULL) {
860                 if (strcmp(pom->addr, a) == 0)
861                         return;
862                 pom = Links.takeFirst();
863         }
864         pom = new NETlink;
865         strcpy(pom->addr, a);
866         pom->connected = FALSE;
867         pom->sock = socket(AF_INET, SOCK_STREAM, 0); 
868         bzero(&svr, sizeof(svr));
869         svr.sin_family = AF_INET;
870         svr.sin_port = htons(LOGPORT);
871         svr.sin_addr.s_addr = inet_addr(pom->addr);
872         j = connect(pom->sock, (struct sockaddr*)&svr, sizeof(svr));
873         if (j == 0) {
874                 pom->connected = TRUE;
875                 fcntl(pom->sock, F_SETFL, O_NONBLOCK | fcntl(pom->sock, F_GETFL,
876                                                                         0));
877                 on = 1;
878                 setsockopt(pom->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
879                                                                 sizeof(on));
880                 send_connect_info(pom);
881                 Links.append(pom); 
882         } else {
883                 write_at_console("Connection failed");
884         }
885 }
886
887 void NETMOD::check_links()
888 {
889         int j = 1;
890         struct sockaddr_in svr;
891         NETlink *pomlink;
892
893         /* connect to all other nodes */
894         if (!all_connected) {
895                 pomlink = Links.first();
896                 while (pomlink != NULL) {
897                         if (!(pomlink->connected)) {
898                                 bzero(&svr, sizeof(svr));
899                                 svr.sin_family = AF_INET;
900                                 svr.sin_port = htons(LOGPORT);
901                                 svr.sin_addr.s_addr = inet_addr(pomlink->addr);
902
903                                 j = connect(pomlink->sock,
904                                         (struct sockaddr*)&svr, sizeof(svr));
905                                 if (j == 0) {
906                                         pomlink->connected = TRUE;
907                                         fcntl(pomlink->sock, F_SETFL, O_NONBLOCK
908                                                 | fcntl(pomlink->sock, F_GETFL,
909                                                                         0));
910                                         send_connect_info(pomlink);
911                                 }
912                                 if (errno == ECONNREFUSED) {
913                                         sock_reopen(pomlink);
914                                 }
915                         } /* not connected */
916                         pomlink = Links.takeFirst();
917                 } /* while */
918         } /* if */
919         all_connected = TRUE;
920         pomlink = Links.first();
921         while(pomlink != NULL) {
922                 if (pomlink->connected == FALSE) {
923                         all_connected = FALSE;
924                         break;
925                 }
926                 pomlink = Links.takeFirst();
927         }
928 }
929
930 void NETMOD::sock_reopen(NETlink *lnk)
931 {
932         int on = 1;
933
934         close(lnk->sock);
935         lnk->sock = socket(AF_INET, SOCK_STREAM, 0);
936         fcntl(lnk->sock, F_SETFL,O_NONBLOCK | fcntl(lnk->sock, F_GETFL, 0));
937         setsockopt(lnk->sock, IPPROTO_TCP,TCP_NODELAY, (char*)&on, sizeof(on));
938 }
939
940 /***************** Acknowledges **************************/
941
942 void NETMOD::send_connect_info(NETlink *lnk)
943 {
944         MESSAGE m;
945
946         m.param.pword[0] = NET_CONNECT;
947         m.param.pword[1] = MyNode;
948         m.msg_type = MSG_NET;
949         /* msg2netmsg(&m);*/
950         if (lnk->sock)
951                 write(lnk->sock, &m, sizeof(MESSAGE));
952 }
953
954 void NETMOD::send_accept_info(NETlink *lnk)
955 {
956         MESSAGE m;
957
958         m.param.pword[0] = NET_ACCEPT;
959         m.param.pword[1] = MyNode;
960         m.msg_type = MSG_NET;
961         /* msg2netmsg(&m);*/
962         if (lnk->sock)
963                 write(lnk->sock, &m, sizeof(MESSAGE));
964 }
965
966 void NETMOD::send_code_ack(NETlink *lnk)
967 {
968         MESSAGE m;
969
970         m.param.pword[0] = NET_CODESTREAM_OK;
971         m.msg_type = MSG_NET;
972         /* msg2netmsg(&m);*/
973         if (lnk->sock)
974                 write(lnk->sock, &m, sizeof(MESSAGE));
975 }
976
977 void NETMOD::send_to_all(MESSAGE *msg)
978 {
979         NETlink *pomlink;
980         pomlink = Links.first();
981         while (pomlink != NULL) {
982                 write(pomlink->sock, msg, sizeof(MESSAGE));
983                 pomlink = Links.takeFirst();
984         }
985 }
986
987 void NETMOD::run()
988 {
989         while(1) {
990                 /*
991                 accept_connection();
992                 get_internal();
993                 remote_messages();
994                 */
995                 /* 2010*/
996                 doitall();
997         }
998 }
999
1000 void NETMOD::exit_sequence()
1001 {
1002         NETlink *pomlink;
1003
1004         ::close(kernel_sock);
1005         ::close(listen_sock);
1006         unlink(kername);
1007         pomlink = Links.first();
1008         while (pomlink != NULL) {
1009                 ::close(pomlink->sock);
1010                 pomlink = Links.takeFirst();
1011         }
1012         exit(0);
1013 }
1014
1015 void NETMOD::disconnect_seq()
1016 {
1017         MESSAGE m;
1018         NETlink *p;
1019
1020         bzero(&m, sizeof(MESSAGE));
1021         m.msg_type = MSG_NET;
1022         m.param.pword[0] = NET_DISCONNECT;
1023         m.param.pword[1] = MyNode;
1024
1025         p = Links.first();
1026         while(p != NULL) {
1027                 send_to_node(p, &m);
1028                 p=Links.takeFirst();
1029         }
1030         p = Links.first();
1031         while(p != NULL) {
1032                 ::close(p->sock);
1033                 p = Links.takeFirst();
1034         }
1035         Links.clear();
1036 }
1037
1038 NETlink * NETMOD::findNETlink(int node)
1039 {
1040         NETlink *pomlink;
1041         pomlink = Links.first();
1042         while(pomlink != NULL) {
1043                 if (pomlink->node_number == node)
1044                         return pomlink;
1045
1046                 pomlink = Links.takeFirst();
1047         } 
1048         return pomlink;
1049 }
1050
1051 INTlink * NETMOD::findINTlink(int id)
1052 {
1053         INTlink *pomlink;
1054         pomlink = Interpreters.first();
1055         while(pomlink != NULL) {
1056                 if (pomlink->ID == id)
1057                         return pomlink;
1058                 pomlink = Interpreters.takeFirst();
1059         }
1060         return pomlink;
1061 }
1062
1063
1064 /**
1065  * Sending code to a remote node
1066  */
1067 void NETMOD::transmit_file(int ton, char *fname, int fromINT)
1068 {
1069         FILE *f;
1070         MESSAGE msg;
1071         char fn[80];
1072         char b[255];
1073         unsigned char buffer[FILE_BUFFER_SIZE];
1074         protdescr proto;
1075         int i,tsock,sock;
1076         unsigned int sz;
1077         NETlink *outlink;
1078         struct sockaddr_in svr;
1079         fd_set rset;
1080         fd_set wset;
1081
1082         /***************** CCD FILE */
1083         strcpy(fn, fname);
1084         strcat(fn, ".ccd");
1085         f = fopen(fn, "rb");
1086         if (f != NULL) {
1087                 fseek(f, 0, SEEK_END);
1088                 msg.param.pword[1] = ftell(f);
1089                 fclose(f);
1090                 f = fopen(fn, "rb");
1091
1092                 strcpy(b, rindex(fname, '/'));
1093                 for(i = 0; i < strlen(b); i++)
1094                         b[i] = b[i + 1];
1095
1096                 msg.param.pword[0] = NET_CCD_START;
1097                 strcpy(msg.param.pstr, b);
1098
1099                 outlink = findNETlink(ton);
1100                 if (outlink == NULL)
1101                         exit(1);
1102                 bzero(&svr, sizeof(svr));
1103                 sock = socket(AF_INET, SOCK_STREAM, 0);
1104                 svr.sin_family = AF_INET;
1105                 svr.sin_addr.s_addr = INADDR_ANY;
1106                 svr.sin_port = htons(CODEPORT);
1107                 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
1108                 listen(sock, 5);
1109                 send_to_node(outlink, &msg);
1110                 sz = sizeof(svr);
1111                 FD_ZERO(&rset);
1112                 FD_ZERO(&wset);
1113                 FD_SET(sock, &rset);
1114                 if (select(sock + 1, &rset, &wset, 0, 0))
1115                         if (FD_ISSET(sock,&rset))
1116                                 tsock = accept(sock, (struct sockaddr*)&svr,
1117                                                                         &sz);
1118                 if (tsock > 0) {
1119                         close(sock);
1120                         while (!feof(f)) {
1121                                 i = fread(&buffer, 1, sizeof(buffer), f);
1122                                 write(tsock, &buffer, i);
1123                                 FD_ZERO(&rset);
1124                                 FD_ZERO(&wset);
1125                                 FD_SET(tsock, &wset);
1126                                 select(tsock + 1, &rset, &wset, 0, 0);
1127                         }
1128                         close(tsock);
1129                 }
1130                 fclose(f);
1131         } // f!=NULL
1132         else {
1133                 sprintf(b, "Cannot open file to send %s\n", fname);
1134                 write_at_console(b);
1135         }
1136
1137
1138         /**************** PCD FILE */
1139
1140         strcpy(fn, fname);
1141         strcat(fn, ".pcd");
1142         f = fopen(fn, "r");
1143         if (f != NULL) {
1144                 fseek(f, 0, SEEK_END);
1145                 msg.param.pword[1] = ftell(f);
1146                 fclose(f);
1147                 f = fopen(fn, "rb");
1148
1149                 strcpy(b, rindex(fname, '/'));
1150                 for(i = 0; i < strlen(b); i++)
1151                         b[i] = b[i + 1];
1152                 msg.param.pword[0] = NET_PCD_START;
1153                 strcpy(msg.param.pstr, b);
1154
1155                 outlink = findNETlink(ton);
1156                 if (outlink == NULL)
1157                         exit(1);
1158                 bzero(&svr, sizeof(svr));
1159                 sock = socket(AF_INET, SOCK_STREAM, 0);
1160                 svr.sin_family = AF_INET;
1161                 svr.sin_addr.s_addr = INADDR_ANY;
1162                 svr.sin_port = htons(CODEPORT1);
1163                 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
1164                 listen(sock, 5);
1165                 send_to_node(outlink, &msg);
1166                 sz = sizeof(svr);
1167                 FD_ZERO(&rset);
1168                 FD_ZERO(&wset);
1169                 FD_SET(sock, &rset);
1170                 if (select(sock + 1, &rset, &wset, 0, 0))
1171                         if (FD_ISSET(sock, &rset))
1172                                 tsock = accept(sock, (struct sockaddr*)&svr,
1173                                                                         &sz);
1174                 if (tsock > 0) {
1175                         close(sock);
1176                         while (!feof(f)) {
1177                                 i = fread(&proto, 1, sizeof(proto), f);
1178                                 write(tsock, &proto, i);
1179                                 FD_ZERO(&rset);
1180                                 FD_ZERO(&wset);
1181                                 FD_SET(tsock, &wset);
1182                                 select(tsock + 1, &rset, &wset, 0, 0);
1183                         }
1184                         close(tsock);
1185                 }
1186                 fclose(f);
1187         } // f!=NULL
1188         else {
1189                 sprintf(b, "Cannot open file to send %s\n", fname);
1190                 write_at_console(b);
1191         }
1192
1193         msg.msg_type = MSG_NET; 
1194         msg.param.pword[0] = NET_TRANSMITTED;
1195         msg.param.pword[1] = fromINT;
1196         send_to_kernel(&msg);
1197 }
1198
1199 void NETMOD::conn_info(int sk)
1200 {
1201         NETlink *pom;
1202         MESSAGE m;
1203         int k = 0;
1204         char poms[255];
1205
1206         m.msg_type = MSG_NET;
1207         m.param.pword[0] = NET_INFO;
1208         strcpy(m.param.pstr, "");
1209         pom = Links.first();
1210         while (pom != NULL) {
1211                 sprintf(poms, "%d=%s;", pom->node_number, pom->addr);
1212                 strcat(m.param.pstr, poms);
1213                 k++;
1214                 if (k == 12) {
1215                         m.param.pword[1] = 12;
1216                         write(sk, &m, sizeof(MESSAGE));
1217                         k = 0;
1218                 }
1219                 pom = Links.takeFirst();
1220         }
1221         if (k > 0) {
1222                 m.param.pword[1] = k;
1223                 write(sk, &m, sizeof(MESSAGE));
1224         }
1225         m.msg_type = MSG_NET;
1226         m.param.pword[0] = NET_INFO_END;
1227         write(sk, &m, sizeof(MESSAGE));
1228 }
1229
1230 /**
1231  * argv0 = program current path
1232  * argv1 = socket path
1233  * argv2 = config path
1234  */
1235 int main(int argc, char **argv)
1236 {
1237         if (argc < 3) {
1238                 return 1;
1239         }
1240
1241         fprintf(stderr, "lognet: Net module path: %s\n", argv[0]);
1242         fprintf(stderr, "lognet: Kernel socket: %s\n", argv[1]);
1243         fprintf(stderr, "lognet: Configuration file: %s\n", argv[2]);
1244
1245         NETMOD netter(argc, argv);
1246         netter.run();
1247         return 0;
1248 }