server 0.0.1
basicserverinfrastructure

src/http/request/parser/parse.c

Go to the documentation of this file.
00001 #include <stdlib.h>
00002 #include <string.h>
00003 #include <unistd.h>
00004 #include <ctype.h>
00005 
00006 #include "http/request_parser.h"
00007 #include "interface/class.h"
00008 
00009 
00010 #define REMAINS(pars,done) \
00011         ((pars)->buffer_used - ((done) - (pars)->buffer))
00012 
00013 
00014 static
00015 inline
00016 char *
00017 httpRequestParserGetLine(char ** data)
00018 {
00019         char * line_end = strstr(*data, "\r\n");
00020         char * ret      = *data;
00021 
00022         if (NULL == line_end) {
00023                 return NULL;
00024         }
00025 
00026         *line_end = 0;
00027         *data = line_end + 2;
00028 
00029         return ret;
00030 }
00031 
00032 static
00033 inline
00034 void
00035 httpRequestSkip(char ** data)
00036 {
00037         for (; 0 != **data && ! isalpha(**data); (*data)++);
00038 }
00039 
00040 void httpRequestParserGetRequestLine(HttpRequest, char *);
00041 
00042 void
00043 httpRequestParserParse(HttpRequestParser this)
00044 {
00045         static HttpRequest request  = NULL;
00046         static char *      data; // static pointer to unprocessed data
00047         char *             line;
00048         int                cont = 1;
00049 
00050         while(cont) {
00051                 switch(this->state) {
00052                         case HTTP_REQUEST_GARBAGE:
00053                                 data = this->buffer; // initialize static pointer
00054                                 httpRequestSkip(&data);
00055                                 request = new(HttpRequest);
00056 
00057                                 this->state = HTTP_REQUEST_START;
00058                                 break;
00059 
00060                         case HTTP_REQUEST_START:
00061                                 if (NULL == (line = httpRequestParserGetLine(&data))) {
00062                                         cont = 0;
00063                                         break;
00064                                 }
00065                                 
00066                                 httpRequestParserGetRequestLine(request, line);
00067 
00068                                 this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
00069                                 break;
00070 
00071                         case HTTP_REQUEST_REQUEST_LINE_DONE:
00072                                 if (NULL == (line = httpRequestParserGetLine(&data))) {
00073                                         cont = 0;
00074                                         break;
00075                                 }
00076 
00077                                 if (0 == strlen(line)) {
00078                                         this->state = HTTP_REQUEST_HEADERS_DONE;
00079                                         break;
00080                                 }
00081 
00082                                 httpRequestParserGetHeader(request, line);
00083                                 break;
00084 
00085                         case HTTP_REQUEST_HEADERS_DONE:
00086                                 httpHeaderSort(request->header, request->nheader);
00087 
00088                                 {
00089                                         char * nbody;
00090 
00091                                         if (0 == request->nbody) {
00092                                                 nbody = httpHeaderGet(
00093                                                                 request->header,
00094                                                                 request->nheader,
00095                                                                 "Content-Length");
00096 
00097                                                 if (NULL == nbody) {
00098                                                         this->state = HTTP_REQUEST_DONE;
00099                                                         break;
00100                                                 }
00101                                                 else {
00102                                                         request->nbody = atoi(nbody);
00103                                                 }
00104                                         }
00105 
00106                                         if (REMAINS(this, data) >= request->nbody) {
00107                                                 request->body = calloc(1, request->nbody + 1);
00108                                                 memcpy(request->body, data, request->nbody);
00109                                                 data += request->nbody;
00110                                                 this->state = HTTP_REQUEST_DONE;
00111                                         }
00112                                 }
00113                                         
00114                                 break;
00115 
00116                         case HTTP_REQUEST_DONE:
00120                                 this->request_queue->requests[(this->request_queue->nrequests)++] =
00121                                         request;
00122 
00126                                 memmove(this->buffer, data, REMAINS(this, data));
00127 
00128                                 this->buffer_used -= data - this->buffer;
00129 
00133                                 if (0 == this->buffer_used) {
00134                                         cont = 0;
00135                                 }
00136 
00140                                 this->state = HTTP_REQUEST_GARBAGE;
00141 
00142                                 break;
00143 
00144                         default:
00145                                 break;
00146                 }
00147         }
00148 }
00149 
00150 // vim: set ts=4 sw=4:
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines