2805194 [rkeene@sledge /home/rkeene/projects/webdraw]$ cat -n serv.c
  1 /*
  2  * The WebDraw Project is released without copyright for use as public domain.
  3  */
  4 
  5 #ifndef _WIN32
  6 #include <sys/socket.h>
  7 #include <netinet/in.h>
  8 #include <arpa/inet.h>
  9 #include <sys/wait.h>
 10 #include <signal.h>
 11 #else
 12 #define __USE_W32_SOCKETS 1
 13 #endif
 14 #include <sys/types.h>
 15 #include <sys/stat.h>
 16 #include <stdlib.h>
 17 #include <unistd.h>
 18 #include <string.h>
 19 #include <stdio.h>
 20 #include <fcntl.h>
 21 #include <time.h>
 22 
 23 /* GD */
 24 #include <gd.h>
 25 #include <gdfonts.h>
 26 
 27 /* Pthreads, or on win32, emulated pthreads */
 28 #include "win32-pthread-emul.h"
 29 #ifdef _WIN32
 30 #include <ws2tcpip.h>
 31 #endif
 32 
 33 /* Win32 requires O_BINARY as an option to open(), but noone else even has it defined */
 34 #ifndef O_BINARY
 35 #define O_BINARY 0
 36 #endif
 37 
 38 struct session_info_st;
 39 struct session_info_st {
 40     uint32_t sessionid;
 41     gdImagePtr imgptr;
 42     pthread_mutex_t imgptr_mut;
 43     uint16_t lastx;
 44     uint16_t lasty;
 45     uint32_t lastcnt;
 46     int img_color_black;
 47     time_t last_used_time;
 48     struct session_info_st *_next;
 49 };
 50 struct session_info_st *session_list = NULL;
 51 pthread_mutex_t session_list_mut;
 52 
 53 struct image_info_st {
 54     void *imgbuf;
 55     int32_t imgbuflen;
 56 };
 57 
 58 typedef enum {
 59     WEBDRAW_EVENT_MOVE,
 60     WEBDRAW_EVENT_CLICK,
 61 } webdraw_event_t;
 62 
 63 static struct session_info_st *find_session_info(uint32_t sessionid, int createIfNotExisting) {
 64     struct session_info_st *ret = NULL, *chk_session_list;
 65 
 66     /* search for an existing session */
 67     pthread_mutex_lock(&session_list_mut);
 68 
 69     for (chk_session_list = session_list; chk_session_list; chk_session_list = chk_session_list->_next) {
 70         if (chk_session_list->sessionid == sessionid) {
 71             ret = chk_session_list;
 72             break;
 73         }
 74     }
 75 
 76     /* create it and initialize it if needed */
 77     if (!ret && createIfNotExisting) {
 78         ret = malloc(sizeof(*ret));
 79         if (ret) {
 80             ret->sessionid = sessionid;
 81             ret->imgptr = NULL;
 82             ret->last_used_time = time(NULL);
 83             ret->lastx = 65535;
 84             ret->lasty = 65535;
 85             ret->lastcnt = 0;
 86             pthread_mutex_init(&ret->imgptr_mut, NULL);
 87 
 88             ret->_next = session_list;
 89             session_list = ret;
 90         }
 91     }
 92 
 93     pthread_mutex_unlock(&session_list_mut);
 94 
 95     return(ret);
 96 }
 97 
 98 static void cleanup_sessions(int session_age_limit) {
 99     struct session_info_st *chk_session_list, *next, *prev = NULL;
100     time_t expire_time;
101 
102     expire_time = time(NULL) - session_age_limit;
103 
104     pthread_mutex_lock(&session_list_mut);
105 
106     for (chk_session_list = session_list; chk_session_list; chk_session_list = next) {
107         next = chk_session_list->_next;
108 
109         if (chk_session_list->last_used_time < expire_time) {
110             if (chk_session_list->imgptr) {
111                 gdImageDestroy(chk_session_list->imgptr);
112             }
113             pthread_mutex_destroy(&chk_session_list->imgptr_mut);
114 
115             if (session_list == chk_session_list) {
116                 session_list = next;
117             }
118 
119             if (prev) {
120                 prev->_next = next;
121             }
122 
123             free(chk_session_list);
124         } else {
125             prev = chk_session_list;
126         }
127     }
128 
129     pthread_mutex_unlock(&session_list_mut);
130 
131     return;
132 }
133 
134 static struct image_info_st *get_image(uint32_t sessionid) {
135     struct image_info_st *ret;
136     struct session_info_st *curr_sess = NULL;
137 
138     curr_sess = find_session_info(sessionid, 0);
139 
140     if (!curr_sess) {
141         return(NULL);
142     }
143 
144     ret = malloc(sizeof(*ret));
145     if (!ret) {
146         return(NULL);
147     }
148 
149     pthread_mutex_lock(&curr_sess->imgptr_mut);
150     ret->imgbuf = gdImagePngPtr(curr_sess->imgptr, &ret->imgbuflen);
151     pthread_mutex_unlock(&curr_sess->imgptr_mut);
152 
153     return(ret);
154 }
155 
156 static struct image_info_st *get_image_str(const char *sessionid_str) {
157     uint32_t sessionid;
158 
159     sessionid = strtoul(sessionid_str, NULL, 10);
160 
161     return(get_image(sessionid));
162 }
163 
164 static int handle_event(uint32_t sessionid, uint16_t x, uint16_t y, uint32_t counter, webdraw_event_t type) {
165     struct session_info_st *curr_sess = NULL;
166     FILE *pngfp;
167 
168     curr_sess = find_session_info(sessionid, 1);
169 
170     if (!curr_sess) {
171         return(-1);
172     }
173 
174     if (type == WEBDRAW_EVENT_MOVE && counter != 0) {
175         if (counter < curr_sess->lastcnt) {
176 #ifndef NDEBUG
177             printf("Ignoring out of order move request (sess=%lu, cnt=%lu, lastcnt=%lu)\n", (unsigned long) sessionid,
	(unsigned long) counter, (unsigned long) curr_sess->lastcnt);
178 #endif
179             return(-1);
180         }
181 
182         curr_sess->lastcnt = counter;
183     }
184 
185     /* Update session with new data */
186     pthread_mutex_lock(&curr_sess->imgptr_mut);
187     if (!curr_sess->imgptr) {
188         pngfp = fopen("blank.png", "rb");
189         if (pngfp) {
190             curr_sess->imgptr = gdImageCreateFromPng(pngfp);
191             fclose(pngfp);
192 
193             if (curr_sess->imgptr) {
194                 curr_sess->img_color_black = gdImageColorAllocate(curr_sess->imgptr, 0, 0, 0); 
195                 gdImageSetAntiAliased(curr_sess->imgptr, curr_sess->img_color_black);
196             }
197         }
198     }
199 
200     if (curr_sess->imgptr && curr_sess->lastx != 65535 && curr_sess->lasty != 65535) {
201         /* Update image */
202         gdImageLine(curr_sess->imgptr, curr_sess->lastx, curr_sess->lasty, x, y, gdAntiAliased);
203     }
204 
205     if (curr_sess->imgptr && type == WEBDRAW_EVENT_CLICK) {
206         gdImageFilledArc(curr_sess->imgptr, x, y, 6, 6, 0, 360, gdAntiAliased, gdArc);
207     }
208 
209     curr_sess->lastx = x;
210     curr_sess->lasty = y;
211     pthread_mutex_unlock(&curr_sess->imgptr_mut);
212 
213     /* Update session information */
214     curr_sess->last_used_time = time(NULL);
215 
216     return(0);
217 }
218 
219 static int handle_event_str(char *str, webdraw_event_t type) {
220     uint32_t sessionid, counter;
221     uint16_t x, y;
222     char *sessionid_str, *x_str, *y_str, *counter_str;
223 
224     sessionid_str = str;
225     x_str = strchr(sessionid_str, ',');
226     if (!x_str) {
227         return(-1);
228     }
229     *x_str = '\0';
230     x_str++;
231 
232     y_str = strchr(x_str, ',');
233     if (!y_str) {
234         return(-1);
235     }
236     *y_str = '\0';
237     y_str++;
238 
239     counter_str = strchr(y_str, ',');
240     if (counter_str) {
241         *counter_str = '\0';
242         counter_str++;
243         counter = strtoul(counter_str, NULL, 10);
244     } else {
245         counter = 0;
246     }
247 
248     sessionid = strtoul(sessionid_str, NULL, 10);
249     x = strtoul(x_str, NULL, 10);
250     y = strtoul(y_str, NULL, 10);
251 
252     return(handle_event(sessionid, x, y, counter, type));
253 }
254 
255 /* Not HTTP/1.0 compliant, yet */
256 THREAD_FUNCTION_RETURN handle_connection(void *arg) {
257     ssize_t bytes_recv;
258     size_t buflen, bufused;
259     char buf[16384], *buf_p, *request_end_p = NULL;
260     char *request_line, *request_line_end_p, *request_line_operation, *request_line_resource, *request_line_protocol;
261     char *curr_header_p, *next_header_p, *curr_header_var, *curr_header_val;
262     int fd, *fd_p;
263     int abort = 0, close_conn, invalid_request = 0;
264 
265     struct image_info_st *imginfo = NULL;
266     struct stat fileinfo;
267     ssize_t sent_bytes, read_bytes;
268     size_t bytes_to_send, bytes_to_read;
269     char reply_buf[1024], *reply_buf_p, copy_buf[8192];
270     char *http_reply_msg, *http_reply_body, *http_reply_body_file, *http_reply_content_type;
271     int http_reply_code, http_reply_content_length = 0;
272     int reply_buf_len;
273     int stat_ret, event_ret;
274     int srcfd;
275 
276     /* Determine our args original values */
277     fd_p = arg;
278     fd = *fd_p;
279 
280     /* Pre-use initialization */
281     buf_p = buf;
282     bufused = 0;
283     *buf_p = '\0';
284     while (1) {
285         close_conn = 1;
286         imginfo = NULL;
287         while (1) {
288             buflen = sizeof(buf) - (buf_p - buf) - bufused - 1;
289             if (buflen == 0) {
290                 /* We ran out of buffer space on input, oops. */
291                 abort = 1;
292                 break;
293             }
294 
295             buf_p[bufused] = '\0';
296             request_end_p = strstr(buf_p, "\015\012\015\012");
297             if (bufused == 0 || !request_end_p) {
298                 bytes_recv = recv(fd, buf_p + bufused, buflen, 0);
299                 if (bytes_recv <= 0) {
300                     abort = 1;
301                     break;
302                 }
303 
304                 bufused += bytes_recv;
305                 buf_p[bufused] = '\0';
306             }
307 
308             request_end_p = strstr(buf_p, "\015\012\015\012");
309             if (!request_end_p) {
310                 continue;
311             }
312 
313             /* We do not handle POST requests */
314             break;
315         }
316 
317         if (abort) {
318             break;
319         }
320 
321         if (!request_end_p) {
322             break;
323         }
324 
325         /* Parse HTTP request */
326         request_line_end_p = strstr(buf_p, "\015\012");
327         *request_line_end_p = '\0';
328         request_line = buf_p;
329 
330         request_line_operation = request_line;
331         request_line_resource = strchr(request_line_operation, ' ');
332         if (!request_line_resource) {
333             break;
334         }
335         *request_line_resource = '\0';
336         request_line_resource++;
337 
338         request_line_protocol = strchr(request_line_resource, ' ');
339         if (!request_line_protocol) {
340             request_line_protocol = "HTTP/1.0";
341         } else {
342             *request_line_protocol = '\0';
343             request_line_protocol++;
344         }
345 
346         if (strcasecmp(request_line_operation, "GET") != 0) {
347             /* We only support GET */
348             invalid_request = 1;
349             break;
350         }
351 
352         if (strcasecmp(request_line_protocol, "HTTP/1.1") == 0) {
353             close_conn = 0;
354         }
355 
356         curr_header_p = request_line_end_p + 2;
357         while (1) {
358             if (curr_header_p == (request_end_p + 2)) {
359                 break;
360             }
361 
362             next_header_p = strstr(curr_header_p, "\015\012");
363             if (next_header_p) {
364 
365                 *next_header_p = '\0';
366             }
367 
368             /* Parse header into variable and value components, and trim leading spaces */
369             curr_header_var = curr_header_p;
370             curr_header_val = strchr(curr_header_p, ':');
371             if (!curr_header_val) {
372                 /* Malformed header */
373                 abort = 1;
374                 break;
375             }
376             *curr_header_val = '\0';
377             curr_header_val++;
378             while (*curr_header_val && (*curr_header_val == ' ' || *curr_header_val == '\t')) {
379                 curr_header_val++;
380             }
381 
382             /* Handle HTTP headers as appropriate */
383             if (strcasecmp(curr_header_var, "connection") == 0) {
384                 if (strcasecmp(curr_header_val, "close") == 0) {
385                     close_conn = 1;
386                 }
387                 if (strcasecmp(curr_header_val, "keep-alive") == 0) {
388                     close_conn = 0;
389                 }
390             }
391 
392             /* Iterate */
393             if (!next_header_p) {
394                 break;
395             }
396             curr_header_p = next_header_p + 2;
397         }
398 
399         if (abort) {
400             break;
401         }
402 
403         /* Process request */
404 #ifndef NDEBUG
405         {
406             int gpn_ret;
407             struct sockaddr_in peerinfo;
408             socklen_t peerinfolen = sizeof(peerinfo);
409 
410             gpn_ret = getpeername(fd, (struct sockaddr *) &peerinfo, &peerinfolen);
411 
412             if (gpn_ret == 0) {
413                 printf("[%llx] [%s] GET %s\n", (unsigned long long) pthread_self(), inet_ntoa(peerinfo.sin_addr),
	request_line_resource);
414             } else {
415                 printf("[%llx] [??.??.??.??] GET %s\n", (unsigned long long) pthread_self(), request_line_resource);
416             }
417         }
418 #endif
419         if (strncmp(request_line_resource, "/event/", 7) == 0) {
420             /* Process an event */
421             if (strncmp(request_line_resource + 7, "move?", 5) == 0) {
422                 event_ret = handle_event_str(request_line_resource + 12, WEBDRAW_EVENT_MOVE);
423             } else if (strncmp(request_line_resource + 7, "click?", 6) == 0) {
424                 event_ret = handle_event_str(request_line_resource + 13, WEBDRAW_EVENT_CLICK);
425             } else {
426                 event_ret = -1;
427             }
428 
429             /* Reply to event */
430             if (event_ret == 0) {
431                 http_reply_code = 200;
432                 http_reply_msg = "OK";
433                 http_reply_content_type = "text/plain";
434                 http_reply_body_file = NULL;
435 
436                 /* Body should be a valid JavaScript command, it will be eval()'d */
437                 http_reply_body = "";
438                 http_reply_content_length = strlen(http_reply_body);
439             } else {
440                 http_reply_code = 500;
441                 http_reply_msg = "Event Error";
442                 http_reply_content_type = "text/plain";
443                 http_reply_body = "Event Error";
444                 http_reply_body_file = NULL;
445                 http_reply_content_length = strlen(http_reply_body);
446             }
447         } else if (strncmp(request_line_resource, "/dynamic/image?", 15) == 0) {
448             /* Return an image */
449             imginfo = get_image_str(request_line_resource + 15);
450 
451             if (imginfo) {
452                 http_reply_code = 200;
453                 http_reply_msg = "OK";
454                 http_reply_content_type = "image/png";
455                 http_reply_body = imginfo->imgbuf;
456                 http_reply_body_file = NULL;
457                 http_reply_content_length = imginfo->imgbuflen;
458             } else {
459                 http_reply_code = 500;
460                 http_reply_msg = "Event Error";
461                 http_reply_content_type = "text/plain";
462                 http_reply_body = "Event Error";
463                 http_reply_body_file = NULL;
464                 http_reply_content_length = strlen(http_reply_body);
465             }
466         } else if (strcmp(request_line_resource, "/static/page.html") == 0 || strcmp(request_line_resource, "/") == 0 ||
	strcmp(request_line_resource, "") == 0) {
467             /* Return a file */
468             http_reply_code = 200;
469             http_reply_msg = "OK";
470             http_reply_content_type = "text/html";
471             http_reply_body = NULL;
472             http_reply_body_file = "page.html";
473         } else if (strcmp(request_line_resource, "/static/page-test.html") == 0) {
474             /* Return a file */
475             http_reply_code = 200;
476             http_reply_msg = "OK";
477             http_reply_content_type = "text/html";
478             http_reply_body = NULL;
479             http_reply_body_file = "page-test.html";
480         } else if (strcmp(request_line_resource, "/static/blank.png") == 0) {
481             /* Return a file */
482             http_reply_code = 200;
483             http_reply_msg = "OK";
484             http_reply_content_type = "image/png";
485             http_reply_body = NULL;
486             http_reply_body_file = "blank.png";
487         } else if (strcmp(request_line_resource, "/static/serv.c") == 0) {
488             /* Return a file */
489             http_reply_code = 200;
490             http_reply_msg = "OK";
491             http_reply_content_type = "text/plain";
492             http_reply_body = NULL;
493             http_reply_body_file = "serv.c";
494         } else {
495             /* Return an error */
496             http_reply_code = 404;
497             http_reply_msg = "Resource not found";
498             http_reply_body = "<html><head><title>Resource not found</title></head><body><h1>Resource not
	found</h1><br>This HTTP server offers very limited resources.</body></html>";
499             http_reply_body_file = NULL;
500             http_reply_content_type = "text/html";
501             http_reply_content_length = strlen(http_reply_body);
502         }
503 
504         if (http_reply_body == NULL) {
505             if (http_reply_body_file != NULL) {
506                 stat_ret = stat(http_reply_body_file, &fileinfo);
507                 if (stat_ret != 0) {
508                     break;
509                 }
510 
511                 http_reply_content_length = fileinfo.st_size;
512             } else {
513                 break;
514             }
515         } else {
516             http_reply_body_file = NULL;
517         }
518 
519         /* Form reply and send it */
520         reply_buf_len = snprintf(reply_buf, sizeof(reply_buf), "%s %i %s\015\012Date: %s\015\012Server:
	webdraw\015\012Connection: %s\015\012Content-Length: %i\015\012Content-Type: %s\015\012\015\012",
	request_line_protocol, http_reply_code, http_reply_msg, "Thu, 21 Feb 2008 08:16:03 GMT", (close_conn ? "close" :
	"keep-alive"), http_reply_content_length, http_reply_content_type);
521         bytes_to_send = reply_buf_len;
522         reply_buf_p = reply_buf;
523         while (bytes_to_send) {
524             sent_bytes = send(fd, reply_buf_p, bytes_to_send, 0);
525             if (sent_bytes <= 0) {
526                 abort = 1;
527                 break;
528             }
529 
530             bytes_to_send -= sent_bytes;
531             reply_buf_p += sent_bytes;
532         }
533         if (abort) {
534             break;
535         }
536 
537         /* Send body */
538         if (http_reply_body != NULL) {
539             /* String */
540             bytes_to_send = http_reply_content_length;
541             reply_buf_p = http_reply_body;
542             while (bytes_to_send) {
543                 sent_bytes = send(fd, reply_buf_p, bytes_to_send, 0);
544                 if (sent_bytes <= 0) {
545                     abort = 1;
546                     break;
547                 }
548 
549                 bytes_to_send -= sent_bytes;
550                 reply_buf_p += sent_bytes;
551             }
552         } else {
553             /* File */
554             srcfd = open(http_reply_body_file, O_RDONLY | O_BINARY);
555 
556             bytes_to_send = http_reply_content_length;
557             reply_buf_p = http_reply_body;
558             while (bytes_to_send) {
559                 if (bytes_to_send <= sizeof(copy_buf)) {
560                     bytes_to_read = bytes_to_send;
561                 } else {
562                     bytes_to_read = sizeof(copy_buf);
563                 }
564 
565                 read_bytes = read(srcfd, copy_buf, bytes_to_read);
566                 if (read_bytes <= 0) {
567                     abort = 1;
568                     break;
569                 }
570 
571                 sent_bytes = send(fd, copy_buf, read_bytes, 0);
572                 if (sent_bytes <= 0) {
573                     abort = 1;
574                     break;
575                 }
576 
577                 bytes_to_send -= sent_bytes;
578                 reply_buf_p += sent_bytes;
579             }
580 
581             close(srcfd);
582         }
583 
584         if (imginfo) {
585             if (imginfo->imgbuf) {
586                 gdFree(imginfo->imgbuf);
587                 imginfo->imgbuf = NULL;
588             }
589             free(imginfo);
590             imginfo = NULL;
591         }
592 
593         if (abort) {
594             break;
595         }
596         
597         /* Close connection if set */
598         if (close_conn) {
599             break;
600         }
601 
602         /* Prepare for the next connection */
603         /* We support pipelining by ignoring part of the buffer, or resetting it if possible */
604         bufused -= (request_end_p + 4) - buf_p;
605         if (bufused == 0) {
606             buf_p = buf;
607         } else {
608             buf_p = request_end_p + 4;
609         }
610     }
611     
612     if (imginfo) {
613         if (imginfo->imgbuf) {
614             gdFree(imginfo->imgbuf);
615             imginfo->imgbuf = NULL;
616         }
617         free(imginfo);
618         imginfo = NULL;
619     }
620 
621 #ifndef NDEBUG
622     printf("[%llx] Thread terminating\n", (unsigned long long) pthread_self());
623 #endif
624 
625     close(fd);
626     free(fd_p);
627 
628     pthread_detach(pthread_self());
629 
630     return((THREAD_FUNCTION_RETURN) 0);
631 }
632 
633 static void daemonize(void) {
634 #ifndef _WIN32
635     int dummyfd;
636 
637     dummyfd = open("/dev/null", O_RDWR);
638 
639     dup2(dummyfd, STDIN_FILENO);
640     dup2(dummyfd, STDOUT_FILENO);
641     dup2(dummyfd, STDERR_FILENO);
642 
643     /* Parent */
644     if (fork() != 0) {
645         /* Parent */
646         while (wait(NULL) == -1) {
647             /* Busy loop */
648         }
649     } else {
650         /* Child */
651         if (fork() == 0) {
652             /* Grandchild */
653             return;
654         }
655     }
656     exit(EXIT_SUCCESS);
657 #endif
658 
659     return;
660 }
661 
662 int main(int argc, char **argv) {
663     struct sockaddr_in localaddr;
664     pthread_t curr_thread;
665     int masterfd, currfd, *currfd_copy;
666     int bind_ret, listen_ret, pthcreate_ret;
667     uint16_t parm_port = 8013;
668 #ifdef _WIN32
669     /* Win32 Specific Crap */
670     WSADATA wsaData;
671 
672     if (WSAStartup(MAKEWORD(2, 0), &wsaData) != 0) {
673         fprintf(stderr, "WSAStartup() failed.  Blame Microsoft.\n");
674         return(EXIT_FAILURE);
675     }
676     if (wsaData.wVersion != MAKEWORD(2, 0)) {
677         WSACleanup();
678         fprintf(stderr, "WSAStartup() returned unexpected version.  Blame Microsoft.\n");
679         return(EXIT_FAILURE);
680     }
681 #endif
682 
683     /* Initialize session list mutex */
684     pthread_mutex_init(&session_list_mut, NULL);
685 
686 
687     /* Setup listening socket on appropriate port */
688     if (argc == 2) {
689         if (!argv[1]) {
690             fprintf(stderr, "Invalid port specification\n");
691             return(EXIT_FAILURE);
692         }
693 
694         parm_port = atoi(argv[1]);
695         if (parm_port == 0) {
696             fprintf(stderr, "Invalid port specification %s (== %i), must be between 1 and 65535\n", argv[1], parm_port);
697             return(EXIT_FAILURE);
698         }
699     }
700 
701     masterfd = socket(PF_INET, SOCK_STREAM, 0);
702     if (masterfd < 0) {
703         perror("socket");
704         return(EXIT_FAILURE);
705     }
706 
707     localaddr.sin_family = AF_INET;
708     localaddr.sin_port = htons(parm_port);
709     localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
710     while (1) {
711         printf("Binding to 0.0.0.0:%i\n", parm_port);
712         bind_ret = bind(masterfd, (struct sockaddr *) &localaddr, sizeof(localaddr));
713         if (bind_ret != 0) {
714             perror("bind");
715 #ifndef _WIN32
716             sleep(5);
717 #endif
718             continue;
719         }
720 
721         break;
722     }
723 
724     listen_ret = listen(masterfd, 5);
725     if (listen_ret != 0) {
726         perror("listen");
727         return(EXIT_FAILURE);
728     }
729 
730 #ifndef _WIN32
731     signal(SIGPIPE, SIG_IGN);
732 #endif
733 
734     daemonize();
735 
736     /* Handle incoming connections and create worker threads to handle them */
737     while (1) {
738         cleanup_sessions(300);
739 
740         currfd = accept(masterfd, NULL, NULL);
741         if (currfd < 0) {
742             perror("accept");
743             return(EXIT_FAILURE);
744         }
745 
746         /* Duplicate child FD for worker thread -- it will be freed appropriately */
747         currfd_copy = malloc(sizeof(*currfd_copy));
748         if (!currfd_copy) {
749             perror("malloc");
750             return(EXIT_FAILURE);
751         }
752         *currfd_copy = currfd;
753 
754         /* Create worker thread for this request */
755         pthcreate_ret = pthread_create(&curr_thread, NULL, handle_connection, currfd_copy);
756         if (pthcreate_ret != 0) {
757             fprintf(stderr, "Error creating thread, closing socket and aborting. pthread_create() returned %i\n",
	pthcreate_ret);
758             free(currfd_copy);
759             close(currfd);
760             break;
761         }
762     }
763 
764     return(EXIT_FAILURE);
765 }
2805195 [rkeene@sledge /home/rkeene/projects/webdraw]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2009-06-23 03:25:49