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