e9ce2ffe2548ce2cec2eb7f9b4ad6039c8093b2f
[IRC.git] / Robust / src / Runtime / socket.c
1 #include "runtime.h"
2 #include "structdefs.h"
3 #include <sys/socket.h>
4 #include <fcntl.h>
5 #include <arpa/inet.h>
6 #include <strings.h>
7 #include <errno.h>
8 #include <netdb.h>
9 #include "SimpleHash.h"
10 #include "GenericHashtable.h"
11
12 extern struct RuntimeHash *fdtoobject;
13
14 int CALL24(___Socket______nativeConnect____I__AR_B_I, int ___fd___, int ___port___, struct ___Socket___ * ___this___, int ___fd___, struct ArrayObject * ___address___ ,int ___port___) {
15   struct sockaddr_in sin;
16   int rc;
17   
18   bzero(&sin, sizeof(sin));
19   sin.sin_family= AF_INET;
20   sin.sin_port=htons(___port___);
21   sin.sin_addr.s_addr=htonl(*(int *)(((char *)&VAR(___address___)->___length___)+sizeof(int)));
22 #ifdef THREADS
23 #ifdef PRECISE_GC
24   struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
25 #endif
26 #endif
27   do {
28     rc = connect(___fd___, (struct sockaddr *) &sin, sizeof(sin));
29   } while (rc<0 && errno==EINTR); /* repeat if interrupted */
30 #ifdef THREADS
31 #ifdef PRECISE_GC
32   restartaftergc(tmp);
33 #endif
34 #endif
35
36   
37   if (rc<0) goto error;
38
39 #ifdef TASK
40   //Make non-blocking
41   fcntl(___fd___, F_SETFD, 1);
42   fcntl(___fd___, F_SETFL, fcntl(___fd___, F_GETFL)|O_NONBLOCK);
43   RuntimeHashadd(fdtoobject, ___fd___, (int) VAR(___this___));
44   addreadfd(___fd___);
45 #endif
46
47   return 0;
48   
49  error:
50   close(___fd___);
51   return -1;
52 }
53
54 #ifdef TASK
55 int CALL12(___Socket______nativeBindFD____I, int ___fd___, struct ___Socket___ * ___this___, int ___fd___) {
56   if (RuntimeHashcontainskey(fdtoobject, ___fd___))
57       RuntimeHashremovekey(fdtoobject, ___fd___);
58   RuntimeHashadd(fdtoobject, ___fd___, (int) VAR(___this___));
59   addreadfd(___fd___);
60 }
61 #endif
62
63
64 int CALL12(___Socket______nativeBind_____AR_B_I, int ___port___,  struct ArrayObject * ___address___, int ___port___) {
65   int fd;
66   int rc;
67   socklen_t sa_size;
68   struct sockaddr_in sin;
69   bzero(&sin, sizeof(sin));
70   sin.sin_family= AF_INET;
71   sin.sin_port=0;
72   sin.sin_addr.s_addr=INADDR_ANY;
73   
74   fd=socket(AF_INET, SOCK_STREAM, 0);
75   if (fd<0) {
76 #ifdef DEBUG
77     perror(NULL);
78     printf("createSocket error in nativeBind\n");
79 #endif
80 #ifdef TASK
81     longjmp(error_handler,12);
82 #else
83 #ifdef THREADS
84     threadexit();
85 #else
86     exit(-1);
87 #endif
88 #endif
89   }
90   
91   rc = bind(fd, (struct sockaddr *) &sin, sizeof(sin));
92   if (rc<0) goto error;
93
94   sa_size = sizeof(sin);
95   rc = getsockname(fd, (struct sockaddr *) &sin, &sa_size);
96   if (rc<0) goto error;
97
98   return fd;
99
100  error:
101   close(fd);
102 #ifdef DEBUG
103   perror(NULL);
104   printf("createSocket error #2 in nativeBind\n");
105 #endif
106 #ifdef TASK
107   longjmp(error_handler,13);
108 #else
109 #ifdef THREADS
110   threadexit();
111 #else
112   exit(-1);
113 #endif
114 #endif
115 }
116
117 struct ArrayObject * CALL01(___InetAddress______getHostByName_____AR_B, struct ___ArrayObject___ * ___hostname___) {
118   int length=VAR(___hostname___)->___length___;
119   int i,j,n;
120   char * str=malloc(length+1);
121   struct hostent *h;
122   struct ArrayObject * arraybytearray;
123
124   for(i=0;i<length;i++) {
125     str[i]=(((char *)&VAR(___hostname___)->___length___)+sizeof(int))[i];
126   }
127   str[length]=0;
128   h=gethostbyname(str);
129   free(str);
130   
131   for (n=0; h->h_addr_list[n]; n++) /* do nothing */ ;
132   
133 #ifdef PRECISE_GC
134   arraybytearray=allocate_newarray(___params___,BYTEARRAYARRAYTYPE,n);
135 #else
136   arraybytearray=allocate_newarray(BYTEARRAYARRAYTYPE,n);
137 #endif
138   for(i=0;i<n;i++) {
139     struct ArrayObject *bytearray;
140 #ifdef PRECISE_GC
141     {
142       int ptrarray[]={1, (int) ___params___, (int)arraybytearray};
143       bytearray=allocate_newarray(&ptrarray,BYTEARRAYTYPE,h->h_length);
144       arraybytearray=(struct ArrayObject *) ptrarray[2];
145     }
146 #else
147     bytearray=allocate_newarray(BYTEARRAYTYPE,h->h_length);
148 #endif
149     ((void **)&((&arraybytearray->___length___)[1]))[i]=bytearray;
150     {
151       int ha=ntohl(*(int *)h->h_addr_list[i]);
152       (&bytearray->___length___)[1]=ha;
153     }
154   }
155   
156   return arraybytearray;
157 }
158
159
160 int CALL12(___ServerSocket______createSocket____I, int port, struct ___ServerSocket___ * ___this___, int port) {
161   int fd;
162
163   int n=1;
164   struct sockaddr_in sin;
165
166   bzero(&sin, sizeof(sin));
167   sin.sin_family = AF_INET;
168   sin.sin_port = htons (port);
169   sin.sin_addr.s_addr = htonl (INADDR_ANY);
170   fd=socket(AF_INET, SOCK_STREAM, 0);
171   if (fd<0) {
172 #ifdef DEBUG
173     perror(NULL);
174     printf("createSocket error #1\n");
175 #endif
176 #ifdef TASK
177     longjmp(error_handler,5);
178 #else
179 #ifdef THREADS
180     threadexit();
181 #else
182     exit(-1);
183 #endif
184 #endif
185   }
186
187   if (setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (char *)&n, sizeof (n)) < 0) {
188     close(fd);
189 #ifdef DEBUG
190     perror("");
191     printf("createSocket error #2\n");
192 #endif
193 #ifdef TASK
194     longjmp(error_handler,6);
195 #else
196 #ifdef THREADS
197     threadexit();
198 #else
199     exit(-1);
200 #endif
201 #endif
202   }
203
204 #ifdef MAC
205         if (setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &n, sizeof (n)) < 0) {
206           perror("socket");
207           exit(-1);
208         }
209 #endif
210
211 #ifdef TASK
212   fcntl(fd, F_SETFD, 1);
213   fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
214 #endif
215
216   /* bind to port */
217   if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))<0) { 
218     close(fd);
219 #ifdef DEBUG
220     perror("");
221     printf("createSocket error #3\n");
222 #endif
223 #ifdef TASK
224     longjmp(error_handler,7);
225 #else
226 #ifdef THREADS
227     threadexit();
228 #else
229     exit(-1);
230 #endif
231 #endif
232   }
233
234   /* listen */
235   if (listen(fd, 5)<0) { 
236     close (fd);
237 #ifdef DEBUG
238     perror("");
239     printf("createSocket error #4\n");
240 #endif
241 #ifdef TASK
242     longjmp(error_handler,8);
243 #else
244 #ifdef THREADS
245     threadexit();
246 #else
247     exit(-1);
248 #endif
249 #endif
250   }
251
252   /* Store the fd/socket object mapping */
253 #ifdef TASK
254   RuntimeHashadd(fdtoobject, fd, (int) VAR(___this___));
255   addreadfd(fd);
256 #endif
257   return fd;
258 }
259
260 int CALL02(___ServerSocket______nativeaccept____L___Socket___,struct ___ServerSocket___ * ___this___, struct ___Socket___ * ___s___) {
261   struct sockaddr_in sin;
262   unsigned int sinlen=sizeof(sin);
263   int fd=VAR(___this___)->___fd___;
264   int newfd;
265 #ifdef THREADS
266 #ifdef PRECISE_GC
267   struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
268 #endif
269 #endif
270   newfd=accept(fd, (struct sockaddr *)&sin, &sinlen);
271 #ifdef THREADS 
272 #ifdef PRECISE_GC
273   restartaftergc(tmp);
274 #endif
275 #endif
276   if (newfd<0) { 
277 #ifdef DEBUG
278     perror(NULL);
279     printf("acceptSocket error #1\n");
280 #endif
281 #ifdef TASK
282     longjmp(error_handler,9);
283 #else
284 #ifdef THREADS
285     threadexit();
286 #else
287     exit(-1);
288 #endif
289 #endif
290   }
291 #ifdef TASK
292   fcntl(newfd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
293   RuntimeHashadd(fdtoobject, newfd, (int) VAR(___s___));
294   addreadfd(newfd);
295 #ifdef MULTICORE
296   flagorand(VAR(___this___),0,0xFFFFFFFE,objq4socketobj[corenum],numqueues4socketobj[corenum]);
297   enqueueObject(VAR(___this___), objq4socketobj[corenum], numqueues4socketobj[corenum]);
298 #else
299   flagorand(VAR(___this___),0,0xFFFFFFFE);
300   enqueueObject(VAR(___this___));
301 #endif
302 #endif
303   return newfd;
304 }
305
306 void CALL24(___Socket______nativeWrite_____AR_B_I_I, int offset, int length, struct ___Socket___ * ___this___, struct ArrayObject * ___b___, int offset, int length) {
307   int fd=VAR(___this___)->___fd___;
308   char * charstr=((char *)& VAR(___b___)->___length___)+sizeof(int)+offset;
309   while(1) {
310     int offset=0;
311     int bytewritten;
312     while(length>0) {
313       bytewritten=write(fd, &charstr[offset], length);
314       if (bytewritten==-1&&errno!=EAGAIN)
315         break;
316       length-=bytewritten;
317       offset+=bytewritten;
318    }
319
320     if (length!=0) {
321       perror("ERROR IN NATIVEWRITE");
322       printf("error=%d remaining bytes %d\n",errno, length); 
323     }
324     break;
325   }
326 }
327
328 int CALL02(___Socket______nativeRead_____AR_B, struct ___Socket___ * ___this___, struct ArrayObject * ___b___) {
329   int fd=VAR(___this___)->___fd___;
330   int length=VAR(___b___)->___length___;
331
332   char * charstr=malloc(length);
333   
334 #ifdef THREADS
335 #ifdef PRECISE_GC
336   struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
337 #endif
338 #endif
339   int byteread=-1;
340
341   //  printf("Doing read on %d\n",fd);
342   do {
343     byteread=read(fd, charstr, length);
344   } while(byteread==-1&&errno==EINTR);
345 #ifdef THREADS
346 #ifdef PRECISE_GC
347   restartaftergc(tmp);
348 #endif
349 #endif
350   
351   {
352     int i;
353     for(i=0;i<byteread;i++) {
354       (((char *)& VAR(___b___)->___length___)+sizeof(int))[i]=charstr[i];
355     }
356     free(charstr);
357   }
358
359
360   if (byteread<0) {
361     printf("ERROR IN NATIVEREAD\n");
362     perror("");
363   }
364 #ifdef TASK
365 #ifdef MULTICORE
366   flagorand(VAR(___this___),0,0xFFFFFFFE,objq4socketobj[corenum],numqueues4socketobj[corenum]);
367   enqueueObject(VAR(___this___),objq4socketobj[corenum],numqueues4socketobj[corenum]);
368 #else
369   flagorand(VAR(___this___),0,0xFFFFFFFE);
370   enqueueObject(VAR(___this___));
371 #endif
372 #endif
373   return byteread;
374 }
375
376 void CALL01(___Socket______nativeClose____, struct ___Socket___ * ___this___) {
377   int fd=VAR(___this___)->___fd___;
378   int data;
379 #ifdef TASK
380   RuntimeHashget(fdtoobject, fd, &data);
381   RuntimeHashremove(fdtoobject, fd, data);
382   removereadfd(fd);
383 #ifdef MULTICORE
384   flagorand(VAR(___this___),0,0xFFFFFFFE,objq4socketobj[corenum],numqueues4socketobj[corenum]);
385   enqueueObject(VAR(___this___),objq4socketobj[corenum],numqueues4socketobj[corenum]);
386 #else
387   flagorand(VAR(___this___),0,0xFFFFFFFE);
388   enqueueObject(VAR(___this___));
389 #endif
390 #endif
391   close(fd);
392 }