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