tinywebd
diff src/main.c @ 3:852a745503cf
http header parsing, not tested
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Thu, 16 Apr 2015 15:20:16 +0300 |
parents | f425a9805d17 |
children | 9e054c002489 |
line diff
1.1 --- a/src/main.c Wed Apr 15 23:44:22 2015 +0300 1.2 +++ b/src/main.c Thu Apr 16 15:20:16 2015 +0300 1.3 @@ -1,6 +1,8 @@ 1.4 #include <stdio.h> 1.5 #include <stdlib.h> 1.6 #include <string.h> 1.7 +#include <ctype.h> 1.8 +#include <signal.h> 1.9 #include <errno.h> 1.10 #include <unistd.h> 1.11 #include <fcntl.h> 1.12 @@ -27,8 +29,11 @@ 1.13 1.14 int start_server(void); 1.15 int accept_conn(int lis); 1.16 +void close_conn(struct client *c); 1.17 int handle_client(struct client *c); 1.18 +void do_get_head(struct client *c); 1.19 void respond_error(struct client *c, int errcode); 1.20 +void sighandler(int s); 1.21 int parse_args(int argc, char **argv); 1.22 1.23 static int lis; 1.24 @@ -41,6 +46,10 @@ 1.25 return 1; 1.26 } 1.27 1.28 + signal(SIGINT, sighandler); 1.29 + signal(SIGTERM, sighandler); 1.30 + signal(SIGQUIT, sighandler); 1.31 + 1.32 if((lis = start_server()) == -1) { 1.33 return 1; 1.34 } 1.35 @@ -91,6 +100,8 @@ 1.36 } 1.37 } 1.38 } 1.39 + 1.40 + return 0; /* unreachable */ 1.41 } 1.42 1.43 int start_server(void) 1.44 @@ -150,30 +161,22 @@ 1.45 free(c->rcvbuf); 1.46 } 1.47 1.48 -static char *skip_space(char *s, char *endp) 1.49 -{ 1.50 - while(s < endp && *s && isspace(*s)) 1.51 - ++s; 1.52 - return s; 1.53 -} 1.54 - 1.55 int handle_client(struct client *c) 1.56 { 1.57 - char *reqp, *hdrp, *bodyp, *endp, *eol; 1.58 - char req_type[32]; 1.59 + struct http_req_header hdr; 1.60 static char buf[2048]; 1.61 - int rdsz; 1.62 + int rdsz, status; 1.63 1.64 while((rdsz = recv(c->s, buf, sizeof buf, 0)) > 0) { 1.65 if(c->rcvbuf) { 1.66 + char *newbuf; 1.67 int newsz = c->bufsz + rdsz; 1.68 if(newsz > MAX_REQ_LENGTH) { 1.69 respond_error(c, 413); 1.70 return -1; 1.71 } 1.72 1.73 - char *newbuf = realloc(buf, newsz + 1); 1.74 - if(!newbuf) { 1.75 + if(!(newbuf = realloc(buf, newsz + 1))) { 1.76 fprintf(stderr, "failed to allocate %d byte buffer\n", newsz); 1.77 respond_error(c, 503); 1.78 return -1; 1.79 @@ -187,17 +190,41 @@ 1.80 } 1.81 } 1.82 1.83 - endp = c->rcvbuf + c->bufsz; 1.84 - if((reqp = skip_space(buf, endp)) >= endp) { 1.85 - return 0; /* incomplete have to read more ... */ 1.86 + if((status = http_parse_header(&hdr, c->rcvbuf, c->bufsz)) != HTTP_HDR_OK) { 1.87 + http_print_header(&hdr); 1.88 + switch(status) { 1.89 + case HTTP_HDR_INVALID: 1.90 + respond_error(c, 400); 1.91 + return -1; 1.92 + 1.93 + case HTTP_HDR_NOMEM: 1.94 + respond_error(c, 503); 1.95 + return -1; 1.96 + 1.97 + case HTTP_HDR_PARTIAL: 1.98 + return 0; /* partial header, continue reading */ 1.99 + } 1.100 + } 1.101 + http_print_header(&hdr); 1.102 + 1.103 + /* we only support GET and HEAD at this point, so freak out on anything else */ 1.104 + switch(hdr.method) { 1.105 + case HTTP_GET: 1.106 + case HTTP_HEAD: 1.107 + do_get_head(c); 1.108 + break; 1.109 + 1.110 + default: 1.111 + respond_error(c, 501); 1.112 + return -1; 1.113 } 1.114 1.115 + close_conn(c); 1.116 + return 0; 1.117 +} 1.118 1.119 - /* we only support GET and HEAD at this point, so freak out on anything else */ 1.120 - 1.121 - /* TODO: parse header, drop on invalid, determine if the request 1.122 - * is complete and process 1.123 - */ 1.124 +void do_get_head(struct client *c) 1.125 +{ 1.126 } 1.127 1.128 void respond_error(struct client *c, int errcode) 1.129 @@ -210,6 +237,23 @@ 1.130 close_conn(c); 1.131 } 1.132 1.133 +void sighandler(int s) 1.134 +{ 1.135 + if(s == SIGINT || s == SIGTERM || s == SIGQUIT) { 1.136 + close(lis); 1.137 + while(clist) { 1.138 + struct client *c = clist; 1.139 + clist = clist->next; 1.140 + close_conn(c); 1.141 + free(c); 1.142 + } 1.143 + clist = 0; 1.144 + 1.145 + printf("bye!\n"); 1.146 + exit(0); 1.147 + } 1.148 +} 1.149 + 1.150 1.151 static void print_help(const char *argv0) 1.152 {