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