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