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