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