Fix problems from porting Qt3->Qt4, which were caused by introducing takeFirst()...
[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         m.param.pword[1] = 0;
381
382         QListIterator<NETlink*> linksIterator(Links);
383
384         while (linksIterator.hasNext()) {
385                 pomlink = linksIterator.next();
386                 if (pomlink->node_number == n) {
387                         m.param.pword[1] = 1;
388                         strcpy(m.param.pstr, pomlink->addr);
389                         break;
390                 }
391         }
392         write(sc, &m, sizeof(MESSAGE));
393 }
394
395
396 /**
397  * Internal message from kernel or INT
398  */
399 void NETMOD::get_internal()
400 {
401         int nr;
402         int nrset;
403         MESSAGE msg;
404         int si;
405         int sj;
406         fd_set readset;
407         fd_set writeset;
408         struct timeval tout= {0, 0};
409         INTlink *pomlink;
410         struct sockaddr_un svr;
411
412         FD_ZERO(&readset);
413         FD_ZERO(&writeset);
414         FD_SET(kernel_sock, &readset);
415         nrset = kernel_sock;
416
417         QListIterator<INTlink*> interpretersIterator(Interpreters);
418         while (interpretersIterator.hasNext()) {
419                 pomlink = interpretersIterator.next();
420                 FD_SET(pomlink->sock, &readset);
421                 if (nrset < pomlink->sock) {
422                         nrset = pomlink->sock;
423                 }
424         }
425
426         if (select(nrset + 1, &readset, &writeset, 0, (struct timeval *)&tout) >
427                                                                         0) {
428
429                 /* Check request sockets */
430                 interpretersIterator.toFront();
431                 while (interpretersIterator.hasNext()) {
432                         pomlink = interpretersIterator.next();
433                         if (FD_ISSET(pomlink->sock, &readset)) {
434                                 nr = read(pomlink->sock, &msg, sizeof(MESSAGE));
435                                 if (nr > 0) {
436                                         if (msg.msg_type == MSG_NET) {
437                                                 switch(msg.param.pword[0]) {
438                                                 case NET_PROPAGATE:
439                                                         propagate_msg(&msg);
440                                                         break;
441                                                 case NET_NODE_EXIST:
442                                                         check_node(msg.param.pword[1], pomlink->sock);
443                                                         break;
444                                                 case NET_GET_INFO: 
445                                                         conn_info(pomlink->sock);
446                                                         break;
447                                                 case NET_NODES_NUM:
448                                                         msg.param.pword[0] = NET_NODES_NUM_RESPONSE;
449                                                         msg.param.pword[1] = Links.count();
450                                                         write(pomlink->sock, &msg, sizeof(MESSAGE));
451                                                         break;
452                                                 }/* switch */
453                                         }
454                                 }
455                         } /* ISSET */
456                 } // while
457
458                 /* Check internal socket */
459                 if (FD_ISSET(kernel_sock,&readset)) {
460                         nr = read(kernel_sock, &msg, sizeof(MESSAGE));
461                         if (nr > 0) {
462                                 if (msg.msg_type == MSG_NET) {
463                                         switch(msg.param.pword[0]) { 
464                                         case NET_TRANSMIT_CODE:
465                                                 transmit_file(msg.param.pword[2],
466                                                         msg.param.pstr, 
467                                                         msg.param.pword[1]);
468                                                 break;
469                                         case NET_EXIT:
470                                                 disconnect_seq();
471                                                 exit_sequence();
472                                                 break;
473                                         case NET_GET_INFO:
474                                                 conn_info(kernel_sock);
475                                                 break;
476                                         case NET_PROPAGATE:
477                                                 propagate_msg(&msg);
478                                                 break;
479                                         case NET_DISCONNECT:
480                                                 disconnect_seq();
481                                                 break;
482                                         case NET_NODE_EXIST:
483                                                 check_node(msg.param.pword[1], kernel_sock);
484                                                 break;
485                                         case NET_CONNECT_TO:
486                                                 connect_seq(msg.param.pstr);
487                                         } /* end switch */
488                                 } /* MSg_NET */
489
490                                 if (msg.msg_type == MSG_VLP) {
491                                         switch(msg.param.pword[0]) {
492                                         case VLP_REGINT: {
493                                                 pomlink = new INTlink;
494                                                 pomlink->sock = socket(AF_UNIX, SOCK_STREAM, 0);
495                                                 bzero(&svr,sizeof(svr));
496                                                 svr.sun_family = AF_UNIX;
497                                                 strcpy(svr.sun_path, msg.param.pstr);
498                                                 si = strlen(svr.sun_path) + sizeof(svr.sun_family);
499                                                 sj = connect(pomlink->sock, (struct sockaddr*)&svr, si);
500                                                 if (sj == 0)
501                                                         fcntl(pomlink->sock, F_SETFL, O_NONBLOCK | fcntl(pomlink->sock, F_GETFL, 0));
502                                                 int on = 1;
503                                                 setsockopt(pomlink->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
504                                                 pomlink->ID = msg.param.pword[1];
505                                                 pomlink->connected=TRUE;
506                                                 Interpreters.append(pomlink);
507                                                 };
508                                                 break;
509                                         case VLP_INTERPRETER_DOWN: {
510                                                 pomlink = findINTlink(msg.param.pword[1]);
511                                                 if (pomlink != NULL) {
512                                                         close(pomlink->sock);
513                                                         Interpreters.removeOne(pomlink);
514                                                 }
515                                                 };
516                                                 break;
517                                         break;
518                                         }
519                                 }
520                         }
521                 }
522         }
523 }
524
525 void NETMOD::get_message(NETlink *lnk)
526 {
527         int nr;
528         MESSAGE msg;
529         char pomstr[80];
530         int rdbt;
531         int rd;
532         int sz;
533         int j;
534         int psock;
535         struct sockaddr_in svr;
536         unsigned char buffer[FILE_BUFFER_SIZE];
537         protdescr proto;
538
539         if (lnk->connected) {
540                 nr = read(lnk->sock, &msg, sizeof(MESSAGE));
541                 if (nr > 0) {
542                         /* netmsg2msg(&msg); */
543                         if (msg.msg_type == MSG_NET) {
544                                 switch(msg.param.pword[0]) {
545                                 case NET_CCD_START:
546                                         lnk->code_transmit = TRUE;
547                                         sprintf(pomstr, "%s/%s", REMOTE_PATH, msg.param.pstr);
548                                         strcat(pomstr,".ccd");
549                                         lnk->CodeFile = fopen(pomstr, "wb");
550                                         if (lnk->CodeFile == NULL) {
551                                                 write_at_console("Cannot open file\n");
552                                                 lnk->code_transmit = FALSE;
553                                         }
554                                         lnk->CodeSize = msg.param.pword[1];
555                                         psock = socket(AF_INET, SOCK_STREAM, 0); 
556                                         bzero(&svr, sizeof(svr));
557                                         svr.sin_family = AF_INET;
558                                         svr.sin_port = htons(CODEPORT);
559                                         svr.sin_addr.s_addr = inet_addr(lnk->addr);
560                                         j = connect(psock, (struct sockaddr*)&svr, sizeof(svr));
561                                         if (j == 0) {
562                                                 /*fcntl(psock, F_SETFL,O_NONBLOCK | fcntl(psock, F_GETFL,0));*/
563                                                 sz = 0;
564                                                 while (sz < lnk->CodeSize) {
565                                                         rd = read(psock, &buffer, sizeof(buffer));
566                                                         rdbt = fwrite(&buffer, sizeof(unsigned char), rd, lnk->CodeFile);
567                                                         sz = sz + rd;
568                                                 }
569                                                 close(psock);
570                                                 fclose(lnk->CodeFile);
571                                         }
572                                         break;
573                                 case NET_PCD_START:
574                                         lnk->code_transmit = TRUE;
575                                         sprintf(pomstr, "%s/%s", REMOTE_PATH, msg.param.pstr);
576                                         strcat(pomstr, ".pcd");
577                                         lnk->CodeFile = fopen(pomstr, "wb");
578                                         if (lnk->CodeFile == NULL) {
579                                                 write_at_console("Cannot open file\n");
580                                                 lnk->code_transmit = FALSE;
581                                         }
582                                         lnk->CodeSize = msg.param.pword[1];
583                                         psock = socket(AF_INET, SOCK_STREAM, 0); 
584                                         bzero(&svr, sizeof(svr));
585                                         svr.sin_family = AF_INET;
586                                         svr.sin_port = htons(CODEPORT1);
587                                         svr.sin_addr.s_addr = inet_addr(lnk->addr);
588                                         j = connect(psock, (struct sockaddr*)&svr, sizeof(svr));
589                                         if (j == 0) {
590                                                 /*fcntl(psock, F_SETFL,O_NONBLOCK | fcntl(psock, F_GETFL,0));*/
591                                                 sz = 0;
592                                                 while (sz < lnk->CodeSize) {
593                                                         rd = read(psock, &proto, sizeof(proto));
594                                                         rdbt = fwrite(&proto, sizeof(unsigned char), rd, lnk->CodeFile);
595                                                         sz = sz + rd;
596                                                 }
597                                                 close(psock);
598                                                 fclose(lnk->CodeFile);
599                                         }
600                                         break;
601                                 case NET_CONNECT:
602                                         sprintf(pomstr, "Node: %d Addr: %s",
603                                                 msg.param.pword[1], lnk->addr);
604                                         lnk->node_number = msg.param.pword[1];
605                                         write_at_console(pomstr);
606                                         send_accept_info(lnk);
607                                         break;
608                                 case NET_ACCEPT:
609                                         sprintf(pomstr, "Node: %d Addr: %s",
610                                                 msg.param.pword[1], lnk->addr);
611                                         lnk->node_number = msg.param.pword[1];
612                                         write_at_console(pomstr);
613                                         break;
614                                 case NET_DISCONNECT:
615                                         sprintf(pomstr,"Node: %d disconnected",
616                                                 msg.param.pword[1]);
617                                         write_at_console(pomstr);
618                                         ::close(lnk->sock);
619                                         Links.removeOne(lnk);
620                                         delete lnk;
621                                         break;
622                                 case NET_PROPAGATE:
623                                         if (msg.param.pword[1] == MSG_VLP) {
624                                                 send_to_kernel(&msg);
625                                         } else if (msg.param.pword[1] == MSG_INT) {
626                                                 send_to_int(&msg);
627                                         }
628                                         break;
629                                 }
630                         }
631                 }
632
633         }
634 }
635
636
637
638 void NETMOD::remote_messages()
639 {
640         int max;
641         fd_set rset, wset;
642         struct timeval tout={0, 0};
643         NETlink *pomlink;
644
645         FD_ZERO(&rset);
646         FD_ZERO(&wset);
647         max = 0;
648
649         QListIterator<NETlink*> linksIterator(Links);
650         while (linksIterator.hasNext()) {
651                 pomlink = linksIterator.next();
652                 if (pomlink->connected) {
653                         FD_SET(pomlink->sock, &rset);
654                         if (max < pomlink->sock){
655                                 max = pomlink->sock;
656                         }
657                 }
658         }
659
660         if (select(max + 1, &rset, &wset, 0, (struct timeval *)&tout) > 0) {
661                 linksIterator.toFront();
662                 while (linksIterator.hasNext()) {
663                         pomlink = linksIterator.next();
664                         if (FD_ISSET(pomlink->sock,&rset)) {
665                                 get_message(pomlink);
666                         }
667                 }
668         }
669 }
670
671 /******************************2010********************************************/
672 void NETMOD::doitall() {
673         unsigned int sz;
674         int nsock,max = 0, on, nr, si, sj;
675         struct sockaddr_in svr;
676         fd_set rset;
677         NETlink *pomlink;
678         INTlink *pomlink2;
679         struct sockaddr_un svr2;
680         MESSAGE msg;
681
682         FD_ZERO(&rset);
683         FD_SET(listen_sock, &rset);
684         max = listen_sock;
685         FD_SET(kernel_sock, &rset);
686         if (max < kernel_sock) {
687                 max=kernel_sock;
688         }
689
690         QListIterator<INTlink*> interpretersIterator(Interpreters);
691         while (interpretersIterator.hasNext()) {
692                 pomlink2 = interpretersIterator.next();
693                 FD_SET(pomlink2->sock, &rset);
694                 if (max < pomlink2->sock) {
695                         max = pomlink2->sock;
696                 }
697         }
698
699         QListIterator<NETlink*> linksIterator(Links);
700         while (linksIterator.hasNext()) {
701                 pomlink = linksIterator.next();
702                 if (pomlink->connected) {
703                         FD_SET(pomlink->sock, &rset);
704                         if (max < pomlink->sock) {
705                                 max = pomlink->sock;
706                         }
707                 }
708         }
709
710         /* odczyt */
711         if (select(max + 1, &rset, 0, 0, NULL) > 0) {
712                 /* accept connection */
713                 if (FD_ISSET(listen_sock,&rset)) {
714                         /* accept connection on listen socket */
715                         sz = sizeof(svr);
716                         bzero(&svr, sizeof(svr));
717                         nsock = accept(listen_sock, (struct sockaddr*)&svr, &sz);
718                         if (nsock > 0) {
719                                 pomlink = new NETlink;
720                                 strcpy(pomlink->addr, inet_ntoa(svr.sin_addr));
721                                 pomlink->sock = nsock;
722                                 pomlink->connected = TRUE;
723                                 fcntl(pomlink->sock, F_SETFL,O_NONBLOCK |
724                                         fcntl(pomlink->sock, F_GETFL, 0));
725                                 on = 1;
726                                 setsockopt(pomlink->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
727                                 Links.append(pomlink);
728                         } /* nsock > 0 */
729                 } /* ISSET */
730
731                 /* get internal message*/
732                 /* Check request sockets */
733                 interpretersIterator.toFront();
734                 while (interpretersIterator.hasNext()) {
735                         pomlink2 = interpretersIterator.next();
736                         if (FD_ISSET(pomlink2->sock,&rset)) {
737                                 nr = read(pomlink2->sock, &msg, sizeof(MESSAGE));
738                                 if (nr > 0) {
739                                         if (msg.msg_type == MSG_NET) {
740                                                 switch(msg.param.pword[0]) {
741                                                 case NET_PROPAGATE:
742                                                         propagate_msg(&msg);
743                                                         break;
744                                                 case NET_NODE_EXIST:
745                                                         check_node(msg.param.pword[1], pomlink2->sock);
746                                                         break;
747                                                 case NET_GET_INFO:
748                                                         conn_info(pomlink2->sock);
749                                                         break;
750                                                 case NET_NODES_NUM:
751                                                         msg.param.pword[0] = NET_NODES_NUM_RESPONSE;
752                                                         msg.param.pword[1] = Links.count();
753                                                         write(pomlink2->sock, &msg, sizeof(MESSAGE));
754                                                         break;
755                                                 }/* switch */
756                                         }
757                                 }
758                         }/* ISSET */
759                 }/* while */
760
761                 /* Check internal socket */
762                 if (FD_ISSET(kernel_sock, &rset)) {
763                         nr = read(kernel_sock, &msg, sizeof(MESSAGE));
764                         if (nr > 0) {
765                                 if (msg.msg_type == MSG_NET) {
766                                         switch(msg.param.pword[0]) { 
767                                         case NET_TRANSMIT_CODE:
768                                                 transmit_file(msg.param.pword[2], msg.param.pstr, msg.param.pword[1]);  
769                                                 break;
770                                         case NET_EXIT:
771                                                 disconnect_seq();
772                                                 exit_sequence();
773                                                 break;
774                                         case NET_GET_INFO:
775                                                 conn_info(kernel_sock);
776                                                 break;
777                                         case NET_PROPAGATE:
778                                                 propagate_msg(&msg);
779                                                 break;
780                                         case NET_DISCONNECT:
781                                                 disconnect_seq();
782                                                 break;
783                                         case NET_NODE_EXIST:
784                                                 check_node(msg.param.pword[1], kernel_sock);
785                                                 break;
786                                         case NET_CONNECT_TO:
787                                                 connect_seq(msg.param.pstr);
788                                         } /* end switch */
789                                 } /* MSG_NET */
790                                 if (msg.msg_type == MSG_VLP) {
791                                         switch(msg.param.pword[0]) {
792                                         case VLP_REGINT: {
793                                                 pomlink2 = new INTlink;
794                                                 pomlink2->sock = socket(AF_UNIX, SOCK_STREAM, 0);
795                                                 bzero(&svr2, sizeof(svr2));
796                                                 svr2.sun_family = AF_UNIX;
797                                                 strcpy(svr2.sun_path, msg.param.pstr);
798                                                 si = strlen(svr2.sun_path) + sizeof(svr2.sun_family);
799                                                 sj = connect(pomlink2->sock,(struct sockaddr*)&svr2, si);
800                                                 if (sj == 0)
801                                                         fcntl(pomlink2->sock,F_SETFL, O_NONBLOCK | fcntl(pomlink2->sock, F_GETFL, 0));
802                                                 int on = 1;
803                                                 setsockopt(pomlink2->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
804                                                 pomlink2->ID = msg.param.pword[1];
805                                                 pomlink2->connected = TRUE;
806                                                 Interpreters.append(pomlink2);
807                                                 };
808                                                 break;
809                                         case VLP_INTERPRETER_DOWN: {
810                                                 pomlink2 = findINTlink(msg.param.pword[1]);
811                                                 if (pomlink2 != NULL) {
812                                                         close(pomlink2->sock);
813                                                         Interpreters.removeOne(pomlink2);
814                                                 }
815                                                 };
816                                                 break;
817                                         } /* MSg_VLP */
818                                 }
819                         } /* nr > 0 */
820                 }/* ISSET */
821
822                 /* get remote message*/
823
824                 linksIterator.toFront();
825                 while (linksIterator.hasNext()) {
826                         pomlink = linksIterator.next();
827                         if (FD_ISSET(pomlink->sock, &rset))
828                                 get_message(pomlink);
829                 }
830         } // select 
831 }
832 /****************************** END 2010 **************************************/
833
834
835
836 void NETMOD::propagate_msg(MESSAGE *msg)
837 {
838         char ss[255];
839         NETlink *pomlink;
840
841         pomlink = findNETlink(msg->param.pword[4]);
842         if ((pomlink != NULL) && (pomlink->connected))
843                 send_to_node(pomlink, msg);
844         else {
845                 if (msg->param.pword[1] == MSG_INT) {
846                         send_to_int(msg);
847                 } else {
848                         sprintf(ss, "Not connected to Node %d",
849                                                         msg->param.pword[4]);  
850                         write_at_console(ss);
851                 }
852         }
853 }
854
855 void NETMOD::connect_seq(char *a)
856 {
857         NETlink *pom;
858         struct sockaddr_in svr;
859         int j, on;
860
861         QListIterator<NETlink*> linksIterator(Links);
862         while (linksIterator.hasNext()) {
863                 pom = linksIterator.next();
864                 if (strcmp(pom->addr, a) == 0)
865                         return;
866         }
867         pom = new NETlink;
868         strcpy(pom->addr, a);
869         pom->connected = FALSE;
870         pom->sock = socket(AF_INET, SOCK_STREAM, 0); 
871         bzero(&svr, sizeof(svr));
872         svr.sin_family = AF_INET;
873         svr.sin_port = htons(LOGPORT);
874         svr.sin_addr.s_addr = inet_addr(pom->addr);
875         j = connect(pom->sock, (struct sockaddr*)&svr, sizeof(svr));
876         if (j == 0) {
877                 pom->connected = TRUE;
878                 fcntl(pom->sock, F_SETFL, O_NONBLOCK | fcntl(pom->sock, F_GETFL,
879                                                                         0));
880                 on = 1;
881                 setsockopt(pom->sock, IPPROTO_TCP, TCP_NODELAY, (char*)&on,
882                                                                 sizeof(on));
883                 send_connect_info(pom);
884                 Links.append(pom); 
885         } else {
886                 write_at_console("Connection failed");
887         }
888 }
889
890 void NETMOD::check_links()
891 {
892         int j = 1;
893         struct sockaddr_in svr;
894         NETlink *pomlink;
895         QListIterator<NETlink*> linksIterator(Links);
896
897         /* connect to all other nodes */
898         if (!all_connected) {
899                 while (linksIterator.hasNext()) {
900                         pomlink = linksIterator.next();
901                         if (!(pomlink->connected)) {
902                                 bzero(&svr, sizeof(svr));
903                                 svr.sin_family = AF_INET;
904                                 svr.sin_port = htons(LOGPORT);
905                                 svr.sin_addr.s_addr = inet_addr(pomlink->addr);
906
907                                 j = connect(pomlink->sock,
908                                         (struct sockaddr*)&svr, sizeof(svr));
909                                 if (j == 0) {
910                                         pomlink->connected = TRUE;
911                                         fcntl(pomlink->sock, F_SETFL, O_NONBLOCK
912                                                 | fcntl(pomlink->sock, F_GETFL,
913                                                                         0));
914                                         send_connect_info(pomlink);
915                                 }
916                                 if (errno == ECONNREFUSED) {
917                                         sock_reopen(pomlink);
918                                 }
919                         } /* not connected */
920                 } /* while */
921         } /* if */
922         all_connected = TRUE;
923         linksIterator.toFront();
924         while(linksIterator.hasNext()) {
925                 pomlink = linksIterator.next();
926                 if (pomlink->connected == FALSE) {
927                         all_connected = FALSE;
928                         break;
929                 }
930         }
931 }
932
933 void NETMOD::sock_reopen(NETlink *lnk)
934 {
935         int on = 1;
936
937         close(lnk->sock);
938         lnk->sock = socket(AF_INET, SOCK_STREAM, 0);
939         fcntl(lnk->sock, F_SETFL,O_NONBLOCK | fcntl(lnk->sock, F_GETFL, 0));
940         setsockopt(lnk->sock, IPPROTO_TCP,TCP_NODELAY, (char*)&on, sizeof(on));
941 }
942
943 /***************** Acknowledges **************************/
944
945 void NETMOD::send_connect_info(NETlink *lnk)
946 {
947         MESSAGE m;
948
949         m.param.pword[0] = NET_CONNECT;
950         m.param.pword[1] = MyNode;
951         m.msg_type = MSG_NET;
952         /* msg2netmsg(&m);*/
953         if (lnk->sock)
954                 write(lnk->sock, &m, sizeof(MESSAGE));
955 }
956
957 void NETMOD::send_accept_info(NETlink *lnk)
958 {
959         MESSAGE m;
960
961         m.param.pword[0] = NET_ACCEPT;
962         m.param.pword[1] = MyNode;
963         m.msg_type = MSG_NET;
964         /* msg2netmsg(&m);*/
965         if (lnk->sock)
966                 write(lnk->sock, &m, sizeof(MESSAGE));
967 }
968
969 void NETMOD::send_code_ack(NETlink *lnk)
970 {
971         MESSAGE m;
972
973         m.param.pword[0] = NET_CODESTREAM_OK;
974         m.msg_type = MSG_NET;
975         /* msg2netmsg(&m);*/
976         if (lnk->sock)
977                 write(lnk->sock, &m, sizeof(MESSAGE));
978 }
979
980 void NETMOD::send_to_all(MESSAGE *msg)
981 {
982         NETlink *pomlink;
983
984         QListIterator<NETlink*> linksIterator(Links);
985         while (linksIterator.hasNext()) {
986                 pomlink = linksIterator.next();
987                 write(pomlink->sock, msg, sizeof(MESSAGE));
988         }
989 }
990
991 void NETMOD::run()
992 {
993         while(1) {
994                 /*
995                 accept_connection();
996                 get_internal();
997                 remote_messages();
998                 */
999                 /* 2010*/
1000                 doitall();
1001         }
1002 }
1003
1004 void NETMOD::exit_sequence()
1005 {
1006         NETlink *pomlink;
1007
1008         ::close(kernel_sock);
1009         ::close(listen_sock);
1010         unlink(kername);
1011
1012         QListIterator<NETlink*> linksIterator(Links);
1013         while (linksIterator.hasNext()) {
1014                 pomlink = linksIterator.next();
1015                 ::close(pomlink->sock);
1016         }
1017         exit(0);
1018 }
1019
1020 void NETMOD::disconnect_seq()
1021 {
1022         MESSAGE m;
1023         NETlink *p;
1024
1025         bzero(&m, sizeof(MESSAGE));
1026         m.msg_type = MSG_NET;
1027         m.param.pword[0] = NET_DISCONNECT;
1028         m.param.pword[1] = MyNode;
1029
1030         QListIterator<NETlink*> linksIterator(Links);
1031         while(linksIterator.hasNext()) {
1032                 p = linksIterator.next();
1033                 send_to_node(p, &m);
1034         }
1035
1036         linksIterator.toFront();
1037         while(linksIterator.hasNext()) {
1038                 p = linksIterator.next();
1039                 ::close(p->sock);
1040         }
1041         Links.clear();
1042 }
1043
1044 NETlink * NETMOD::findNETlink(int node)
1045 {
1046         NETlink *pomlink = NULL;
1047         QListIterator<NETlink*> linksIterator(Links);
1048
1049         while(linksIterator.hasNext()) {
1050                 pomlink = linksIterator.next();
1051
1052                 if (pomlink->node_number == node)
1053                         return pomlink;
1054         }
1055         return pomlink;
1056 }
1057
1058 INTlink * NETMOD::findINTlink(int id)
1059 {
1060         INTlink *pomlink = NULL;
1061         QListIterator<INTlink*> interpretersIterator(Interpreters);
1062         while(interpretersIterator.hasNext()) {
1063                 pomlink = interpretersIterator.next();
1064                 if (pomlink->ID == id)
1065                         return pomlink;
1066         }
1067         return pomlink;
1068 }
1069
1070
1071 /**
1072  * Sending code to a remote node
1073  */
1074 void NETMOD::transmit_file(int ton, char *fname, int fromINT)
1075 {
1076         FILE *f;
1077         MESSAGE msg;
1078         char fn[80];
1079         char b[255];
1080         unsigned char buffer[FILE_BUFFER_SIZE];
1081         protdescr proto;
1082         int i,tsock,sock;
1083         unsigned int sz;
1084         NETlink *outlink;
1085         struct sockaddr_in svr;
1086         fd_set rset;
1087         fd_set wset;
1088
1089         /***************** CCD FILE */
1090         strcpy(fn, fname);
1091         strcat(fn, ".ccd");
1092         f = fopen(fn, "rb");
1093         if (f != NULL) {
1094                 fseek(f, 0, SEEK_END);
1095                 msg.param.pword[1] = ftell(f);
1096                 fclose(f);
1097                 f = fopen(fn, "rb");
1098
1099                 strcpy(b, rindex(fname, '/'));
1100                 for(i = 0; i < strlen(b); i++)
1101                         b[i] = b[i + 1];
1102
1103                 msg.param.pword[0] = NET_CCD_START;
1104                 strcpy(msg.param.pstr, b);
1105
1106                 outlink = findNETlink(ton);
1107                 if (outlink == NULL)
1108                         exit(1);
1109                 bzero(&svr, sizeof(svr));
1110                 sock = socket(AF_INET, SOCK_STREAM, 0);
1111                 svr.sin_family = AF_INET;
1112                 svr.sin_addr.s_addr = INADDR_ANY;
1113                 svr.sin_port = htons(CODEPORT);
1114                 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
1115                 listen(sock, 5);
1116                 send_to_node(outlink, &msg);
1117                 sz = sizeof(svr);
1118                 FD_ZERO(&rset);
1119                 FD_ZERO(&wset);
1120                 FD_SET(sock, &rset);
1121                 if (select(sock + 1, &rset, &wset, 0, 0))
1122                         if (FD_ISSET(sock,&rset))
1123                                 tsock = accept(sock, (struct sockaddr*)&svr,
1124                                                                         &sz);
1125                 if (tsock > 0) {
1126                         close(sock);
1127                         while (!feof(f)) {
1128                                 i = fread(&buffer, 1, sizeof(buffer), f);
1129                                 write(tsock, &buffer, i);
1130                                 FD_ZERO(&rset);
1131                                 FD_ZERO(&wset);
1132                                 FD_SET(tsock, &wset);
1133                                 select(tsock + 1, &rset, &wset, 0, 0);
1134                         }
1135                         close(tsock);
1136                 }
1137                 fclose(f);
1138         } // f!=NULL
1139         else {
1140                 sprintf(b, "Cannot open file to send %s\n", fname);
1141                 write_at_console(b);
1142         }
1143
1144
1145         /**************** PCD FILE */
1146
1147         strcpy(fn, fname);
1148         strcat(fn, ".pcd");
1149         f = fopen(fn, "r");
1150         if (f != NULL) {
1151                 fseek(f, 0, SEEK_END);
1152                 msg.param.pword[1] = ftell(f);
1153                 fclose(f);
1154                 f = fopen(fn, "rb");
1155
1156                 strcpy(b, rindex(fname, '/'));
1157                 for(i = 0; i < strlen(b); i++)
1158                         b[i] = b[i + 1];
1159                 msg.param.pword[0] = NET_PCD_START;
1160                 strcpy(msg.param.pstr, b);
1161
1162                 outlink = findNETlink(ton);
1163                 if (outlink == NULL)
1164                         exit(1);
1165                 bzero(&svr, sizeof(svr));
1166                 sock = socket(AF_INET, SOCK_STREAM, 0);
1167                 svr.sin_family = AF_INET;
1168                 svr.sin_addr.s_addr = INADDR_ANY;
1169                 svr.sin_port = htons(CODEPORT1);
1170                 bind(sock, (struct sockaddr*)&svr, sizeof(svr));
1171                 listen(sock, 5);
1172                 send_to_node(outlink, &msg);
1173                 sz = sizeof(svr);
1174                 FD_ZERO(&rset);
1175                 FD_ZERO(&wset);
1176                 FD_SET(sock, &rset);
1177                 if (select(sock + 1, &rset, &wset, 0, 0))
1178                         if (FD_ISSET(sock, &rset))
1179                                 tsock = accept(sock, (struct sockaddr*)&svr,
1180                                                                         &sz);
1181                 if (tsock > 0) {
1182                         close(sock);
1183                         while (!feof(f)) {
1184                                 i = fread(&proto, 1, sizeof(proto), f);
1185                                 write(tsock, &proto, i);
1186                                 FD_ZERO(&rset);
1187                                 FD_ZERO(&wset);
1188                                 FD_SET(tsock, &wset);
1189                                 select(tsock + 1, &rset, &wset, 0, 0);
1190                         }
1191                         close(tsock);
1192                 }
1193                 fclose(f);
1194         } // f!=NULL
1195         else {
1196                 sprintf(b, "Cannot open file to send %s\n", fname);
1197                 write_at_console(b);
1198         }
1199
1200         msg.msg_type = MSG_NET; 
1201         msg.param.pword[0] = NET_TRANSMITTED;
1202         msg.param.pword[1] = fromINT;
1203         send_to_kernel(&msg);
1204 }
1205
1206 void NETMOD::conn_info(int sk)
1207 {
1208         NETlink *pom;
1209         MESSAGE m;
1210         int k = 0;
1211         char poms[255];
1212
1213         m.msg_type = MSG_NET;
1214         m.param.pword[0] = NET_INFO;
1215         strcpy(m.param.pstr, "");
1216
1217         QListIterator<NETlink*> linksIterator(Links);
1218         while (linksIterator.hasNext()) {
1219                 pom = linksIterator.next();
1220                 sprintf(poms, "%d=%s;", pom->node_number, pom->addr);
1221                 strcat(m.param.pstr, poms);
1222                 k++;
1223                 if (k == 12) {
1224                         m.param.pword[1] = 12;
1225                         write(sk, &m, sizeof(MESSAGE));
1226                         k = 0;
1227                 }
1228         }
1229         if (k > 0) {
1230                 m.param.pword[1] = k;
1231                 write(sk, &m, sizeof(MESSAGE));
1232         }
1233         m.msg_type = MSG_NET;
1234         m.param.pword[0] = NET_INFO_END;
1235         write(sk, &m, sizeof(MESSAGE));
1236 }
1237
1238 /**
1239  * argv0 = program current path
1240  * argv1 = socket path
1241  * argv2 = config path
1242  */
1243 int main(int argc, char **argv)
1244 {
1245         if (argc < 3) {
1246                 return 1;
1247         }
1248
1249         fprintf(stderr, "lognet: Net module path: %s\n", argv[0]);
1250         fprintf(stderr, "lognet: Kernel socket: %s\n", argv[1]);
1251         fprintf(stderr, "lognet: Configuration file: %s\n", argv[2]);
1252
1253         NETMOD netter(argc, argv);
1254         netter.run();
1255         return 0;
1256 }