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