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