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