Added upstream from http://ftp.icm.edu.pl/pub/loglan/
[loglan.git] / sources / int / tcpip.c
1      /* Loglan82 Compiler&Interpreter\r
2      Copyright (C) 1981-1993 Institute of Informatics, University of Warsaw\r
3      Copyright (C)  1993, 1994 LITA, Pau\r
4      \r
5      This program is free software; you can redistribute it and/or modify\r
6      it under the terms of the GNU General Public License as published by\r
7      the Free Software Foundation; either version 2 of the License, or\r
8      (at your option) any later version.\r
9      \r
10      This program is distributed in the hope that it will be useful,\r
11      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13      GNU General Public License for more details.\r
14      \r
15              You should have received a copy of the GNU General Public License\r
16              along with this program; if not, write to the Free Software\r
17              Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
18 \r
19  contacts:  Andrzej.Salwicki@univ-pau.fr\r
20 \r
21 or             Andrzej Salwicki\r
22                 LITA   Departement d'Informatique\r
23                 Universite de Pau\r
24                 Avenue de l'Universite\r
25                 64000 Pau   FRANCE\r
26                  tel.  ++33 59923154    fax. ++33 59841696\r
27 \r
28 =======================================================================\r
29 */\r
30 \r
31 #include "depend.h"\r
32 #include "genint.h"\r
33 #include "int.h"\r
34 #include "process.h"\r
35 \r
36 #include "sock.h"\r
37 #include "tcpip.h"\r
38 \r
39 #include <assert.h>\r
40 \r
41 \r
42 static int sock;\r
43 \r
44 static int slaves=0;\r
45 static struct addr {\r
46    int console;\r
47    struct sockaddr_in addr;\r
48 } *phone_book;\r
49 \r
50 \r
51 #define MAX_NODES 256\r
52 static int node2book[ MAX_NODES ];    /* only 256 nodes - can be changed */\r
53 \r
54 \r
55 static void sock_recv_from( void *, int, struct sockaddr_in * );\r
56 static void sock_recv_from( buf, buflen, from_addr )\r
57    int buflen;\r
58    void *buf;\r
59    struct sockaddr_in *from_addr;\r
60 {\r
61    struct sockaddr_in addr;\r
62    int retval;\r
63    for(;;){\r
64       if( ( retval = sock_recv( sock, buf, buflen, &addr ) ) < 0 )\r
65          perror("receive"),abend("no answer from master");\r
66       if(\r
67          from_addr->sin_port != addr.sin_port\r
68          ||\r
69          from_addr->sin_addr.s_addr != addr.sin_addr.s_addr\r
70          ||\r
71          buflen != retval\r
72         )\r
73          fprintf( stderr, "unexpected message from %s:%d length %d\n",\r
74                 inet_ntoa( from_addr->sin_addr ),\r
75                 (int)ntohs( from_addr->sin_port ),\r
76                 retval\r
77                );\r
78       else\r
79          break;\r
80    }\r
81 }\r
82 \r
83                                                  /* nn.nn.nn.nn:port address */\r
84 void tcpip_connect_to_master( addr )  char *addr; {\r
85 \r
86    char *host = addr;\r
87    int namelen;\r
88    int aux;\r
89    struct sockaddr_in m_address;\r
90 \r
91    for( aux = 0; aux < MAX_NODES; aux++ )\r
92       node2book[ aux ] = -1;\r
93 \r
94    if( host_addr( host, &m_address ) < 0 ){\r
95       perror("invalid host name:");\r
96       usage();\r
97    }\r
98 \r
99    sock = sock_open( SOCK_DGRAM, "udp", NULL, 0 ); /* any port */\r
100    if( sock < 0 )  perror("can't open any socket"),exit(10);\r
101 \r
102    {\r
103       struct sockaddr_in addr;\r
104       int namelen = sizeof(struct sockaddr_in);\r
105       getsockname( sock, &addr, &namelen );\r
106       fprintf( stderr, "socket opened on %s:%d\n",\r
107               inet_ntoa(addr.sin_addr),\r
108               (int)ntohs(addr.sin_port)\r
109             );\r
110    }\r
111 \r
112    aux = htonl( console );\r
113    sock_send( sock, &aux, sizeof(aux), &m_address );\r
114    fprintf(\r
115            stderr, "waiting for acknowledge from %s:%d\n",\r
116            host, (int)ntohs( m_address.sin_port )\r
117           );\r
118 \r
119    sock_recv_from( &aux, sizeof(aux), &m_address );\r
120    slaves = ntohl( aux );\r
121    fprintf( stderr, "answer from master: %d interpreters\n", slaves );\r
122 \r
123    phone_book = (struct addr *)calloc( slaves, sizeof( struct addr ) );\r
124    if( phone_book==NULL )  abend("can't allocate table of addresses");\r
125 \r
126    sock_recv_from( &aux, sizeof(aux), &m_address );\r
127    phone_book[0].console = ntohl( aux );\r
128    phone_book[0].addr = m_address;\r
129 \r
130    fprintf( stderr, "master console %d at %s:%d\n",\r
131            phone_book[0].console,\r
132            inet_ntoa(phone_book[0].addr.sin_addr),\r
133            (int)ntohs(phone_book[0].addr.sin_port)\r
134          );\r
135 \r
136    node2book[ phone_book[ 0 ].console ] = 0;\r
137 \r
138    {\r
139       int i;\r
140       for( i=1; i<slaves; i++ ){  /* on 0 will be master */\r
141 \r
142          sock_recv_from( &aux, sizeof(aux), &m_address );\r
143          phone_book[i].console = ntohl( aux );\r
144          sock_recv_from(\r
145                         &(phone_book[i].addr),\r
146                         sizeof(struct sockaddr_in),\r
147                         &m_address\r
148                        );\r
149          fprintf( stderr, "interpreter %d connected at %s:%d\n",\r
150                  phone_book[i].console,\r
151                  inet_ntoa(phone_book[i].addr.sin_addr),\r
152                  (int)ntohs(phone_book[i].addr.sin_port)\r
153                );\r
154          node2book[ phone_book[ i ].console ] = i;\r
155 \r
156       }\r
157    }\r
158    fprintf( stderr, "\nprogram started\n\n" );\r
159 }\r
160 \r
161 \r
162 \r
163 \r
164 void tcpip_wait_for_slaves( _slaves )  int _slaves; {\r
165 \r
166    int aux;\r
167    int slave_console;\r
168    struct sockaddr_in slave_address;\r
169    int namelen = sizeof(struct sockaddr_in);\r
170 \r
171    for( aux = 0; aux < MAX_NODES; aux++ )\r
172       node2book[ aux ] = -1;\r
173 \r
174    slaves = _slaves+1;\r
175 \r
176    phone_book = (struct addr *)calloc( slaves, sizeof( struct addr ) );\r
177    if( phone_book==NULL )  abend("can't allocate table of addresses");\r
178 \r
179    sock = sock_open( SOCK_DGRAM, "udp", NULL, PORT );\r
180    if( sock < 0 )  perror("master socket"),abend("can't install master");\r
181 \r
182    phone_book[0].console = console;\r
183    getsockname( sock, &(phone_book[0].addr), &namelen );\r
184    assert( namelen == sizeof( struct sockaddr_in ) );\r
185 \r
186    fprintf( stderr, "waiting for %d slaves on console %d at %s:%d\n",\r
187            _slaves,\r
188            phone_book[0].console,\r
189            inet_ntoa(phone_book[0].addr.sin_addr),\r
190            (int)ntohs(phone_book[0].addr.sin_port)\r
191          );\r
192 \r
193    node2book[ console ] = 0;\r
194 \r
195    while( _slaves > 0 ){\r
196 \r
197       if( sock_recv( sock , &slave_console, sizeof(slave_console), &slave_address ) < 0 )\r
198          perror("server receive"),abend("can't connect slave");\r
199 \r
200       fprintf( stderr, "slave %d connected at %s:%d\n",\r
201               ntohl(slave_console),\r
202               inet_ntoa(slave_address.sin_addr),\r
203               (int)ntohs(slave_address.sin_port)\r
204             );\r
205 \r
206       slave_console = ntohl( slave_console );\r
207 \r
208       phone_book[_slaves].console = slave_console;\r
209       phone_book[_slaves].addr    = slave_address;\r
210 \r
211       if( node2book[ slave_console ] != -1 ){\r
212          fprintf( stderr, "node %d already bound\n", slave_console );\r
213          abend("exiting");\r
214       }\r
215       node2book[ slave_console ] = _slaves;\r
216 \r
217       _slaves--;\r
218 \r
219    }\r
220 \r
221    fprintf( stderr, "all slaves notified - sending acknowledges\n" );\r
222 \r
223    {\r
224       int i,j;\r
225       for( i=1; i<slaves; i++ ){\r
226 \r
227          aux = htonl(slaves);\r
228          sock_send( sock, &aux, sizeof(aux), &(phone_book[i].addr) );\r
229 \r
230          aux = htonl(console);\r
231          sock_send( sock, &aux, sizeof(aux), &(phone_book[i].addr) );\r
232 \r
233          for( j=1; j<slaves; j++ ){\r
234             aux = htonl(phone_book[j].console);\r
235             sock_send( sock, &aux, sizeof(aux), &(phone_book[i].addr) );\r
236             sock_send(\r
237                       sock,\r
238                       &(phone_book[j].addr),\r
239                       sizeof(struct sockaddr_in),\r
240                       &(phone_book[i].addr)\r
241                     );\r
242          }\r
243       }\r
244    }\r
245 \r
246    fprintf( stderr, "\nprogram started\n\n" );\r
247 }\r
248 \r
249 \r
250 void tcpip_send( msg )  message *msg; {\r
251    int node = msg->control.receiver.node;\r
252    int ix = node2book[ node ];\r
253    if( ix == -1 ){\r
254       fprintf( stderr, "tcpip send message to not existing node %d\n", node );\r
255       abend("exiting");\r
256    }\r
257 /*\r
258    fprintf( stderr, "tcpip send message to node %d indx %d\n", node, ix );\r
259 */\r
260    sock_send(\r
261              sock,\r
262              msg,\r
263              sizeof( message ),\r
264              &( phone_book[ ix ].addr )\r
265             );\r
266 }\r
267 \r
268 bool tcpip_poll( ms )  int ms; {\r
269    return sock_poll( sock, ms );\r
270 }\r
271 \r
272 bool tcpip_recv( msg )  message *msg; {\r
273    int retval;\r
274    struct sockaddr_in addr;\r
275    if( ( retval = sock_recv( sock, msg, sizeof( message ), &addr ) ) < 0 ){\r
276       perror("receive");\r
277       return FALSE;\r
278    }\r
279 /*\r
280    if( retval == sizeof( message ) )\r
281       fprintf(stderr,"tcpip recv message from node %d\n",msg->control.sender.node);\r
282    else\r
283       fprintf(stderr,"tcpip recv incorrect message from node %d\n",msg->control.sender.node);\r
284 */\r
285    return ( retval == sizeof( message ) );\r
286 }\r
287 \r
288 \r
289 \r