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  {