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