tinywebd
diff src/main.c @ 1:f425a9805d17
foo
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 14 Apr 2015 08:32:51 +0300 |
parents | 9c9e24956d99 |
children | 852a745503cf |
line diff
1.1 --- a/src/main.c Tue Apr 14 02:13:29 2015 +0300 1.2 +++ b/src/main.c Tue Apr 14 08:32:51 2015 +0300 1.3 @@ -8,6 +8,15 @@ 1.4 #include <sys/types.h> 1.5 #include <sys/socket.h> 1.6 #include <arpa/inet.h> 1.7 +#include "http.h" 1.8 + 1.9 +/* HTTP version */ 1.10 +#define HTTP_VER_MAJOR 1 1.11 +#define HTTP_VER_MINOR 1 1.12 +#define HTTP_VER_STR "1.1" 1.13 + 1.14 +/* maximum request length: 64mb */ 1.15 +#define MAX_REQ_LENGTH (65536 * 1024) 1.16 1.17 struct client { 1.18 int s; 1.19 @@ -19,6 +28,8 @@ 1.20 int start_server(void); 1.21 int accept_conn(int lis); 1.22 int handle_client(struct client *c); 1.23 +void respond_error(struct client *c, int errcode); 1.24 +int parse_args(int argc, char **argv); 1.25 1.26 static int lis; 1.27 static int port = 8080; 1.28 @@ -26,6 +37,10 @@ 1.29 1.30 int main(int argc, char **argv) 1.31 { 1.32 + if(parse_args(argc, argv) == -1) { 1.33 + return 1; 1.34 + } 1.35 + 1.36 if((lis = start_server()) == -1) { 1.37 return 1; 1.38 } 1.39 @@ -128,37 +143,108 @@ 1.40 return 0; 1.41 } 1.42 1.43 +void close_conn(struct client *c) 1.44 +{ 1.45 + close(c->s); 1.46 + c->s = -1; /* mark it for removal */ 1.47 + free(c->rcvbuf); 1.48 +} 1.49 + 1.50 +static char *skip_space(char *s, char *endp) 1.51 +{ 1.52 + while(s < endp && *s && isspace(*s)) 1.53 + ++s; 1.54 + return s; 1.55 +} 1.56 + 1.57 int handle_client(struct client *c) 1.58 { 1.59 + char *reqp, *hdrp, *bodyp, *endp, *eol; 1.60 + char req_type[32]; 1.61 static char buf[2048]; 1.62 int rdsz; 1.63 1.64 while((rdsz = recv(c->s, buf, sizeof buf, 0)) > 0) { 1.65 if(c->rcvbuf) { 1.66 int newsz = c->bufsz + rdsz; 1.67 - char *newbuf = realloc(buf, newsz); 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 fprintf(stderr, "failed to allocate %d byte buffer\n", newsz); 1.76 - /* TODO http error */ 1.77 - goto drop; 1.78 + respond_error(c, 503); 1.79 + return -1; 1.80 } 1.81 1.82 memcpy(newbuf + c->bufsz, buf, rdsz); 1.83 + newbuf[newsz] = 0; 1.84 1.85 c->rcvbuf = newbuf; 1.86 c->bufsz = newsz; 1.87 } 1.88 } 1.89 1.90 + endp = c->rcvbuf + c->bufsz; 1.91 + if((reqp = skip_space(buf, endp)) >= endp) { 1.92 + return 0; /* incomplete have to read more ... */ 1.93 + } 1.94 + 1.95 + 1.96 + /* we only support GET and HEAD at this point, so freak out on anything else */ 1.97 + 1.98 /* TODO: parse header, drop on invalid, determine if the request 1.99 * is complete and process 1.100 */ 1.101 +} 1.102 1.103 - if(rdsz == -1 && errno != EAGAIN) { 1.104 -drop: 1.105 - close(c->s); 1.106 - c->s = -1; 1.107 - free(c->rcvbuf); 1.108 +void respond_error(struct client *c, int errcode) 1.109 +{ 1.110 + char buf[512]; 1.111 + 1.112 + sprintf(buf, HTTP_VER_STR " %d %s\r\n\r\n", errcode, http_strmsg(errcode)); 1.113 + 1.114 + send(c->s, buf, strlen(buf), 0); 1.115 + close_conn(c); 1.116 +} 1.117 + 1.118 + 1.119 +static void print_help(const char *argv0) 1.120 +{ 1.121 + printf("Usage: %s [options]\n", argv0); 1.122 + printf("Options:\n"); 1.123 + printf(" -p <port> set the TCP/IP port number to use\n"); 1.124 + printf(" -h print usage help and exit\n"); 1.125 +} 1.126 + 1.127 +int parse_args(int argc, char **argv) 1.128 +{ 1.129 + int i; 1.130 + 1.131 + for(i=1; i<argc; i++) { 1.132 + if(argv[i][0] == '-' && argv[i][2] == 0) { 1.133 + switch(argv[i][1]) { 1.134 + case 'p': 1.135 + if((port = atoi(argv[++i])) == 0) { 1.136 + fprintf(stderr, "-p must be followed by a valid port number\n"); 1.137 + return -1; 1.138 + } 1.139 + break; 1.140 + 1.141 + case 'h': 1.142 + print_help(argv[0]); 1.143 + exit(0); 1.144 + 1.145 + default: 1.146 + fprintf(stderr, "unrecognized option: %s\n", argv[i]); 1.147 + return -1; 1.148 + } 1.149 + } else { 1.150 + fprintf(stderr, "unexpected argument: %s\n", argv[i]); 1.151 + return -1; 1.152 + } 1.153 } 1.154 return 0; 1.155 }