Merge branch 'net-dev'. See body of commit for details.
[akaros.git] / tools / syscall_server.c
1 #include "syscall_server.h"
2 #include <sys/ioctl.h>
3 #include <termios.h>
4
5 /* Remote Syscall Server app. 
6    Written by Paul Pearce.
7    This is an UGLY HACK to avoid sockets to work with the 
8    ugly hack that is the current tesselaton udp wrapping.
9
10    If you search for the comment UDP you can see how to revert this back
11    to socket niceness.
12
13    Note: The server.h has a shared structure with the newlib_backend.h. These must be kept in sync
14          The only difference is Paul's GCC won't allow unions without names, so the 'subheader' name was added
15 */
16
17 // UDP BRANCH
18 #include <netdb.h>
19 char udp_arr[4096];
20 int udp_arr_size = 0;
21 int udp_cur_pos = 0;
22 // END UDP BRANCH
23
24 // TODO: A syscall_id_t that says close the link, and deal with that in the main switch statement.
25 int main()
26 {
27         // Listen for connections.
28         int data_port = listen_for_connections();
29
30         // Once here, we are inside of new processes, setup the new port.
31         int data_fd = setup_data_connection(data_port);
32
33         // Begin processing data from the connection
34         process_connections(data_fd);
35 }
36
37 // Bind to LISTEN_PORT and listen for connections on the specified port.
38 // If a client requests a connection, spawn off a new process, then continue.
39 // In new process, return with the port we are going to listen for data on
40 int listen_for_connections()
41 {
42         //UDP BRANCH. Do nothing, as this is UDP
43         return -1;
44         // END UDP BRANCH
45
46         // Sockets
47         int listen_socket, data_socket;
48
49         // Address structures
50         struct sockaddr_in server_addr, client_addr;
51
52         // Self explanatory
53         int num_connections, response_msg;
54
55         // Size of our address structure
56         unsigned int addr_len = sizeof(struct sockaddr_in);
57
58         // Fork response for determining if child or parent
59         int child;
60
61         // Create socket
62         if ((listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
63         {
64                 printf("Error: Could not create socket.\n");
65                 exit(1);
66         }
67
68         // Setup sockaddr_in
69         server_addr.sin_family = AF_INET;
70         server_addr.sin_port = htons(LISTEN_PORT);
71         server_addr.sin_addr.s_addr = INADDR_ANY;
72         bzero(&(server_addr.sin_zero), 8);      // This is apparently a source of bugs? Who knew.
73
74         // Bind to the given port.
75         if (bind(listen_socket, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)))
76         {
77                 printf("Error: Could not bind to port: %i\n", LISTEN_PORT);
78                 exit(1);
79         }
80
81         // Listen on the socket
82     if (listen(listen_socket, BACKLOG_LEN) < 0)
83     {
84         printf("Error: Could not listen on socket.\n");
85         exit(1);
86     }
87
88         printf("Server started.\n");
89
90         // Main loop to listen for connections.
91         while(1)
92         {
93                 printf("Waiting for connections on port: %i\n", LISTEN_PORT);
94
95                 if ((data_socket = accept(listen_socket, (struct sockaddr *)&client_addr,  &addr_len)) < 0)
96                 {
97                         printf("Error: Could not accept a new connection.\n");
98                 }
99
100                 num_connections++;
101                 response_msg = num_connections + LISTEN_PORT;
102
103                 printf("New connection detected. Assigning port: %i\n", response_msg);
104                 if (send(data_socket, (char*)(&response_msg), sizeof(int), 0) < 0)
105                 {
106                         printf("Error: Could not send response. New client may not have received port. Continuing.\n");
107                         close(data_socket);
108                         continue;
109                 }
110                 close(data_socket);
111
112                 // Spawn a new process for the connection and offload further communications to that process.
113                 if ((child = fork()) == -1)
114                 {
115                         printf("Error: Fork failed. Client responses will be ignored. Continuing.\n");
116                         continue;
117                 }
118                 else if (child)
119                 {
120                         // Spawned Process, break out of loop for cleanup and initialization of the listen function.
121                         break;
122                 }
123                 else
124                 {
125                         // Original Process
126                         // Nothing to do. Continue loop.
127                 }
128         }
129
130         // Only reach here inside of new process, after spawning. Clean up.
131         close(listen_socket);
132
133         return response_msg;
134 }
135
136
137 // Perform socket setup on the new port
138 int setup_data_connection(int port)
139 {
140         // UDP BRANCH
141         port = 44444;
142         // END UDP BRANCH
143
144         // Sockets
145         int listen_socket, data_socket;
146
147         // Address structures
148         struct sockaddr_in server_addr, client_addr;
149
150         // Size of our address structure
151         unsigned int addr_len = sizeof(struct sockaddr_in);
152
153         // Create socket
154         // UDP BRANCH
155         // if ((listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
156         if ((listen_socket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
157         {
158                 printf("Error: Spawned Process, PORT: %i. Could not create socket.\n", port);
159                 exit(1);
160         }
161
162         // Setup sockaddr_in
163         server_addr.sin_family = AF_INET;
164         server_addr.sin_port = htons(port);
165         server_addr.sin_addr.s_addr=INADDR_ANY;
166         bzero(&(server_addr.sin_zero), 8);      // This is apparently a source of bugs? Who knew.
167
168         // Bind to the given port.
169         if (bind(listen_socket, (struct sockaddr *) &server_addr, sizeof(struct sockaddr)))
170         {
171                 printf("Error: Spawned Process, PORT: %i. Could not bind to port.\n", port);
172                 exit(1);
173         }
174
175         //UDP BRANCH
176         data_socket = listen_socket;
177
178         // UDP BRANCH COMMENTED
179         /*
180
181         // Listen on the socket
182     if (listen(listen_socket, BACKLOG_LEN) < 0)
183     {
184         printf("Error: Spawned Process, PORT: %i. Could not listen on socket.\n", port);
185         exit(1);
186     }
187
188         if ((data_socket = accept(listen_socket, (struct sockaddr *)&client_addr,  &addr_len)) < 0)
189         {
190                 printf("Error:  Spawned Process, PORT: %i. Could not accept a new connection.\n", port);
191         }
192
193         */ // UDP BRANCH END COMMENT
194
195         printf("Spawned Process, PORT: %i. FD: %i. Established.\n", port, data_socket);
196
197         // END SOCKET SETUP
198
199         return data_socket;
200 }
201
202 // Poll for a message, return a pointer to message. Caller is required to manage memory of the buffer
203 // Called by the server to get data
204 void process_connections(int fd) {
205
206         // Variables for the fixed filds.
207         syscall_id_t id;
208
209         int just_read;
210         
211         msg_t temp_msg;
212
213         // TODO: Better msg cleanup on close. Channel cleanup in general
214         while(1)
215         {
216                 // Read data from the socket.
217                 // Peek == 1, thus if no data is avaiable, return. Else, wait until full syscall_id_t is avaiable
218                 just_read = read_header_from_socket(&temp_msg, fd);
219
220                 if (just_read == 0)
221                 {
222                         //sleep(1);
223                         continue;
224                 }
225                 
226                 id = temp_msg.id;
227
228                 // If we couldnt read data, or the ID we got is bad, terminate process.
229                 if ((just_read == -1) || (id < 0) || (id > NUM_CALLS))
230                 {
231                         printf("error on id: %d\n", id);
232                         send_error(fd);
233
234                         return;
235                 }
236
237                 msg_t * msg = NULL;
238                 response_t * return_msg = NULL;
239                 int return_len = -1;
240
241                 switch (id) {
242                         case OPEN_ID:
243                                 msg = malloc(sizeof(msg_t) + temp_msg.subheader.open.len);
244                                 if (msg == NULL) {
245                                         send_error(fd);
246                                         return;
247                                 }
248                                 
249                                 *msg = temp_msg;
250                                 just_read = read_buffer_from_socket(msg->subheader.open.buf, fd, msg->subheader.open.len);
251                                 
252                                 if (just_read != msg->subheader.open.len) {
253                                         free(msg);
254                                         send_error(fd);
255                                         return;
256                                 }
257
258                                 return_msg = handle_open(msg);
259                                 free(msg);
260                                 return_len = sizeof(response_t);
261                                 break;
262
263                         case CLOSE_ID:
264                                 return_msg = handle_close(&temp_msg);
265                                 return_len = sizeof(response_t);
266                                 break;
267
268                         case READ_ID:
269                                 return_msg = handle_read(&temp_msg);
270                                 if (return_msg != NULL)
271                                         return_len = sizeof(response_t) + ((return_msg->ret >= 0)  ? return_msg->ret : 0);
272                                 break;
273
274                         case WRITE_ID:
275
276                                 msg = malloc(sizeof(msg_t) + temp_msg.subheader.write.len);
277                                 if (msg == NULL) {
278                                         send_error(fd);
279                                         return;
280                                 }
281                                 
282                                 *msg = temp_msg;
283                                 just_read = read_buffer_from_socket(msg->subheader.write.buf, fd, msg->subheader.write.len);
284
285                                 if (just_read != msg->subheader.write.len) {
286                                         free(msg);
287                                         send_error(fd);
288                                         return;
289                                 }
290
291                                 return_msg = handle_write(msg);
292                                 free(msg);
293
294                                 return_len = sizeof(response_t);
295                                 break;
296
297                         case LSEEK_ID:
298
299                                 return_msg = handle_lseek(&temp_msg);
300                                 return_len = sizeof(response_t);
301                                 break;
302
303                         case ISATTY_ID:
304                                 return_msg = handle_isatty(&temp_msg);
305                                 return_len = sizeof(response_t);
306                                 break;
307
308                         case UNLINK_ID:
309                                 msg = malloc(sizeof(msg_t) + temp_msg.subheader.unlink.len);
310                                 if (msg == NULL) {
311                                         send_error(fd);
312                                         return;
313                                 }
314                                 
315                                 *msg = temp_msg;
316                                 just_read = read_buffer_from_socket(msg->subheader.unlink.buf, fd, msg->subheader.unlink.len);
317                                 
318                                 if (just_read != msg->subheader.unlink.len) {
319                                         free(msg);
320                                         send_error(fd);
321                                         return;
322                                 }
323                         
324                                 return_msg = handle_unlink(msg);
325                                 free(msg);
326                                 return_len = sizeof(response_t);
327                                 break;
328
329                         case LINK_ID:
330                         
331                                 msg = malloc(sizeof(msg_t) + temp_msg.subheader.link.old_len + temp_msg.subheader.link.new_len);
332                                 if (msg == NULL) {
333                                         send_error(fd);
334                                         return;
335                                 }
336                                 
337                                 *msg = temp_msg;
338                                 just_read = read_buffer_from_socket(msg->subheader.link.buf, fd, temp_msg.subheader.link.old_len + temp_msg.subheader.link.new_len);
339                                 
340                                 if (just_read != (temp_msg.subheader.link.old_len + temp_msg.subheader.link.new_len)) {
341                                         free(msg);
342                                         send_error(fd);
343                                         return;
344                                 }
345                         
346                                 return_msg = handle_link(msg);
347                                 free(msg);
348                                 return_len = sizeof(response_t);
349                                 break;
350
351                         case FSTAT_ID:
352                                 return_msg = handle_fstat(&temp_msg);
353                                 return_len = sizeof(response_t);
354
355                                 break;
356
357                         case STAT_ID:
358                                 msg = malloc(sizeof(msg_t) + temp_msg.subheader.stat.len);
359                                 if (msg == NULL) {
360                                         send_error(fd);
361                                         return;
362                                 }
363                         
364                                 *msg = temp_msg;
365                                 just_read = read_buffer_from_socket(msg->subheader.stat.buf, fd, msg->subheader.stat.len);
366                         
367                                 if (just_read != msg->subheader.stat.len) {
368                                         free(msg);
369                                         send_error(fd);
370                                         return;
371                                 }
372
373                                 return_msg = handle_stat(msg);
374                                 free(msg);
375                                 return_len = sizeof(response_t);
376
377                                 break;
378                         default:
379                                 send_error(fd);
380                                 return;
381                 }
382
383                 if (return_msg == NULL)
384                 {
385                         send_error(fd);
386                         return;
387                 }
388
389                 // UDP BRANCH. 
390                 struct hostent *hp;
391                 hp = gethostbyname("192.168.0.10");
392                 struct sockaddr_in addr;
393                 memset(&addr, 0, sizeof(addr));
394                 addr.sin_family = AF_INET;
395                 memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
396                 addr.sin_port = htons(44443);
397                 // END UDP BRANCH
398
399                 if ( sendto(fd, return_msg, return_len, 0, (struct sockaddr *)&addr, sizeof(addr)) != return_len)
400                 //if (write(fd, return_msg, return_len) != return_len)
401                 {
402                         free(return_msg);
403                         // If we cant write to the socket, cant send CONNECTION_TERMINATED. Just die.
404                         printf("Error: Spawned Process, FD: %i. Could not send data out. Dying.\n", fd);
405                         return;
406                 }
407
408                 free(return_msg);
409         }
410 }
411
412 int read_header_from_socket(msg_t* msg, int socket) {
413         return read_from_socket((char*)msg, socket, sizeof(msg_t), PEEK);
414 }
415
416 int read_buffer_from_socket(char* buf, int socket, int len) {
417         return read_from_socket(buf, socket, len, NO_PEEK);
418 }
419
420 // UDP HACK VERSION
421 // Read len bytes from the given socket to the buffer.
422 // If peek is NO_PEEK, will wait indefinitely until that much data is read.
423 // If peek is PEEK, if no data is available, will return immediately.
424 //              However once some data is available, it will block until the entire amount is available.
425 // Return values are:
426 // -1 if error
427 // 0 if peek and nothing avaiable
428 // else len
429 int read_from_socket(char* buf, int socket, int len, int peek) {
430
431         // This function is now super hacked to deal with UDP uglyness. Do not use this to revert once we get tcpip online!
432
433         int total_read = 0;
434
435         if (udp_arr_size == 0) {
436                 udp_arr_size = recvfrom(socket, udp_arr, 4096, 0, 0, 0);
437
438                 if (udp_arr_size == 0)
439                         return -1;
440         }
441
442         if ((udp_cur_pos + len) > udp_arr_size)
443                 return -1;
444
445         memcpy(buf, udp_arr + udp_cur_pos, len);
446
447         udp_cur_pos = udp_cur_pos + len;
448
449         if (udp_cur_pos == udp_arr_size) {
450                 udp_cur_pos = 0;
451                 udp_arr_size = 0;
452         }
453
454         return len;
455
456         // UDP BRANCH
457         //int just_read = read(socket, buf, len);
458         int just_read = recvfrom(socket, buf, len, 0, 0, 0);
459
460         if (just_read < 0) return just_read;
461         if (just_read == 0 && peek) return just_read;
462
463         total_read += just_read;
464
465         while (total_read != len) {
466                 // UDP BRANCH
467                 //just_read = read(socket, buf + total_read, len - total_read);
468                 just_read = recvfrom(socket, buf + total_read, len - total_read, 0, 0, 0);
469
470                 if (just_read == -1) return -1;
471
472                 total_read += just_read;
473         }
474
475         return total_read;
476 }
477
478 // Non hacky UDP version
479 /*
480 int read_from_socket(char* buf, int socket, int len, int peek) {
481         int total_read = 0;
482         //printf("\t\treading %i bytes on socket %i with peek %i\n", len, socket, peek);
483         int just_read = read(socket, buf, len);
484         //printf("\t\tread    %i bytes on socket %i with peek %i\n", just_read, socket, peek);
485                                         
486         if (just_read < 0) return just_read;
487         if (just_read == 0 && peek) return just_read;
488                                 
489         total_read += just_read;
490                                 
491         while (total_read != len) {
492                 just_read = read(socket, buf + total_read, len - total_read);
493                 if (just_read == -1) return -1;
494                 total_read += just_read;
495         }                       
496                 
497         return total_read;
498 }*/
499
500
501 // Send CONNECTION_TERMINATED over the FD (if possible)
502 // Not fully functional.
503 void send_error(int fd)
504 {
505         printf("Error: Spawned Process, FD: %i. Could not read from from socket. Sending CONNECTION_TERMINATED.... ", fd);
506
507         int error_msg = CONNECTION_TERMINATED;
508
509         /*if (write(fd, (char*)(&error_msg) , sizeof(int)) != sizeof(int))
510         {
511                 printf("Could not send CONNECTION_TERMINATED.\n");
512         }
513         else
514         {
515                 printf("Sent.\n");
516
517         }*/
518
519         close(fd);
520 }
521
522
523 response_t* handle_open(msg_t *msg)
524 {
525         printf("opening: %s\n", msg->subheader.open.buf);
526         
527         response_t * response = malloc(sizeof(response_t));
528         if (response == NULL) return NULL;
529
530
531         response->ret = open(msg->subheader.open.buf, msg->subheader.open.flags, msg->subheader.open.mode);
532         if (response->ret == -1) {
533                 response->err = errno;
534         }
535
536         return response;
537 }
538
539 response_t* handle_close(msg_t *msg)
540 {               
541         response_t * response = malloc(sizeof(response_t));
542         if (response == NULL) return NULL;
543
544
545         response->ret = close(msg->subheader.close.fd);
546         if (response->ret == -1) {
547                 response->err = errno;
548         }
549
550         return response;
551 }
552
553 response_t* handle_read(msg_t * msg) 
554 {       
555         response_t * response = malloc(sizeof(response_t) + msg->subheader.read.len);
556         if (response == NULL) return NULL;
557
558         response->ret = read(msg->subheader.read.fd, response->buf, msg->subheader.read.len);
559         if (response->ret == -1) {
560                 response->err = errno;
561         }
562
563         return response;
564 }
565
566 response_t* handle_write(msg_t * msg) 
567 {
568         response_t * response = malloc(sizeof(response_t));
569         if (response == NULL) return NULL;
570
571         response->ret = write(msg->subheader.write.fd, msg->subheader.write.buf, msg->subheader.write.len);
572         if (response->ret == -1) {
573                 response->err = errno;
574         }
575
576         return response;
577 }
578
579 response_t* handle_lseek(msg_t * msg)
580 {
581         response_t * response = malloc(sizeof(response_t));
582         if (response == NULL) return NULL;
583
584         response->ret = lseek(msg->subheader.lseek.fd, msg->subheader.lseek.ptr, msg->subheader.lseek.dir);
585         if (response->ret == -1) {
586                 response->err = errno;
587         }
588 }
589
590 response_t* handle_isatty(msg_t * msg) 
591 {
592         response_t * response = malloc(sizeof(response_t));
593         if (response == NULL) return NULL;
594         
595         response->ret = isatty(msg->subheader.isatty.fd);
596         if (response->ret == -1) {
597                 response->err = errno;
598         }
599
600         return response;
601 }
602
603 response_t* handle_unlink(msg_t * msg)
604 {
605         response_t * response = malloc(sizeof(response_t));
606         if (response == NULL) return NULL;
607
608
609         response->ret = unlink(msg->subheader.unlink.buf);
610         if (response->ret == -1) {
611                 response->err = errno;
612         }
613
614         return response;
615 }
616
617 response_t* handle_link(msg_t * msg) 
618 {
619         response_t * response = malloc(sizeof(response_t));
620         if (response == NULL) return NULL;
621
622
623         response->ret = link(msg->subheader.link.buf, msg->subheader.link.buf + msg->subheader.link.old_len);
624         if (response->ret == -1) {
625                 response->err = errno;
626         }
627
628         return response;
629 }
630
631 response_t* handle_stat(msg_t * msg) {
632         response_t * response = malloc(sizeof(response_t));
633         if (response == NULL) return NULL;
634
635
636         response->ret = stat(msg->subheader.stat.buf, &(response->st));
637         if (response->ret == -1) {
638                 response->err = errno;
639         }
640
641         return response;
642 }
643
644 response_t* handle_fstat(msg_t *msg) {
645         
646         response_t * response = malloc(sizeof(response_t));
647         if (response == NULL) return NULL;
648
649         response->ret = fstat(msg->subheader.fstat.fd, &(response->st));
650         
651         if (response->ret == -1) {
652                 response->err = errno;
653         }
654
655         return response;
656 }