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