add more comments
[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 TASK
196   fcntl(fd, F_SETFD, 1);
197   fcntl(fd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
198 #endif
199
200   /* bind to port */
201   if (bind(fd, (struct sockaddr *) &sin, sizeof(sin))<0) { 
202     close(fd);
203 #ifdef DEBUG
204     perror("");
205     printf("createSocket error #3\n");
206 #endif
207 #ifdef TASK
208     longjmp(error_handler,7);
209 #else
210 #ifdef THREADS
211     threadexit();
212 #else
213     exit(-1);
214 #endif
215 #endif
216   }
217
218   /* listen */
219   if (listen(fd, 5)<0) { 
220     close (fd);
221 #ifdef DEBUG
222     perror("");
223     printf("createSocket error #4\n");
224 #endif
225 #ifdef TASK
226     longjmp(error_handler,8);
227 #else
228 #ifdef THREADS
229     threadexit();
230 #else
231     exit(-1);
232 #endif
233 #endif
234   }
235
236   /* Store the fd/socket object mapping */
237 #ifdef TASK
238   RuntimeHashadd(fdtoobject, fd, (int) VAR(___this___));
239   addreadfd(fd);
240 #endif
241   return fd;
242 }
243
244 int CALL02(___ServerSocket______nativeaccept____L___Socket___,struct ___ServerSocket___ * ___this___, struct ___Socket___ * ___s___) {
245   struct sockaddr_in sin;
246   unsigned int sinlen=sizeof(sin);
247   int fd=VAR(___this___)->___fd___;
248   int newfd;
249 #ifdef THREADS
250 #ifdef PRECISE_GC
251   struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
252 #endif
253 #endif
254   newfd=accept(fd, (struct sockaddr *)&sin, &sinlen);
255 #ifdef THREADS 
256 #ifdef PRECISE_GC
257   restartaftergc(tmp);
258 #endif
259 #endif
260   if (newfd<0) { 
261 #ifdef DEBUG
262     perror(NULL);
263     printf("acceptSocket error #1\n");
264 #endif
265 #ifdef TASK
266     longjmp(error_handler,9);
267 #else
268 #ifdef THREADS
269     threadexit();
270 #else
271     exit(-1);
272 #endif
273 #endif
274   }
275 #ifdef TASK
276   fcntl(newfd, F_SETFL, fcntl(fd, F_GETFL)|O_NONBLOCK);
277   RuntimeHashadd(fdtoobject, newfd, (int) VAR(___s___));
278   addreadfd(newfd);
279   flagorand(VAR(___this___),0,0xFFFFFFFE);
280 #endif
281   return newfd;
282 }
283
284 void CALL02(___Socket______nativeWrite_____AR_B, struct ___Socket___ * ___this___, struct ArrayObject * ___b___) {
285   int fd=VAR(___this___)->___fd___;
286   int length=VAR(___b___)->___length___;
287   char * charstr=((char *)& VAR(___b___)->___length___)+sizeof(int);
288   while(1) {
289     int bytewritten=write(fd, charstr, length);
290     if (bytewritten==-1&&errno==EAGAIN)
291       continue;
292
293     if (bytewritten!=length) {
294       perror("ERROR IN NATIVEWRITE");
295       printf("Supposed to write %d, wrote %d\n", length, bytewritten);
296     }
297     break;
298   }
299 }
300
301 int CALL02(___Socket______nativeRead_____AR_B, struct ___Socket___ * ___this___, struct ArrayObject * ___b___) {
302   int fd=VAR(___this___)->___fd___;
303   int length=VAR(___b___)->___length___;
304
305   char * charstr=malloc(length);
306   
307 #ifdef THREADS
308 #ifdef PRECISE_GC
309   struct listitem *tmp=stopforgc((struct garbagelist *)___params___);
310 #endif
311 #endif
312   int byteread;
313
314   //  printf("Doing read on %d\n",fd);
315   while(1) {
316     byteread=read(fd, charstr, length);
317     
318     break;
319   }
320 #ifdef THREADS
321 #ifdef PRECISE_GC
322   restartaftergc(tmp);
323 #endif
324 #endif
325   
326   {
327     int i;
328     for(i=0;i<byteread;i++) {
329       (((char *)& VAR(___b___)->___length___)+sizeof(int))[i]=charstr[i];
330     }
331     free(charstr);
332   }
333
334
335   if (byteread<0) {
336     printf("ERROR IN NATIVEREAD\n");
337     perror("");
338     byteread=0;
339   }
340 #ifdef TASK
341   flagorand(VAR(___this___),0,0xFFFFFFFE);
342 #endif
343   return byteread;
344 }
345
346 void CALL01(___Socket______nativeClose____, struct ___Socket___ * ___this___) {
347   int fd=VAR(___this___)->___fd___;
348   int data;
349 #ifdef TASK
350   RuntimeHashget(fdtoobject, fd, &data);
351   RuntimeHashremove(fdtoobject, fd, data);
352   removereadfd(fd);
353   flagorand(VAR(___this___),0,0xFFFFFFFE);
354 #endif
355   close(fd);
356 }