Server 0.0.1
HTTP/REST server implementation

src/http/parser/parse.c

Go to the documentation of this file.
00001 
00023 #include <stdlib.h>
00024 
00025 #include "class.h"
00026 #include "cbuf.h"
00027 #include "stream.h"
00028 
00029 #include "http/parser.h"
00030 #include "http/header.h"
00031 #include "http/interface/http_intro.h"
00032 
00033 #include "utils/memory.h"
00034 #include "commons.h"
00035 
00036 #define MIN(a,b)        ((a)<(b)? (a) : (b))
00037 
00038 
00039 ssize_t
00040 httpParserParse(void * _this, Stream st)
00041 {
00042         HttpParser this = _this;
00043         int        cont = 1;
00044         ssize_t    read;
00045         char *     line;
00046         char *     line_end;
00047 
00048         if (cbufIsLocked(this->buffer)) {
00049                 if (FALSE == this->ourLock)
00050                         return 0;
00051         }
00052         else {
00053                 cbufLock(this->buffer);
00054                 this->ourLock = TRUE;
00055         }
00056 
00057         if (NULL != this->incomplete) {
00058                 cbufSetData(this->buffer, this->incomplete, this->isize);
00059                 free(this->incomplete);
00060                 this->incomplete = NULL;
00061         }
00062 
00063         if (0 > (read = cbufRead(this->buffer, st))) {
00064                 return read;
00065         }
00066 
00067         while (cont) {
00068                 switch(this->state) {
00069                         case HTTP_MESSAGE_GARBAGE:
00070                                 cbufSkipNonAlpha(this->buffer);
00071                                 if (! cbufIsEmpty(this->buffer)) {
00072                                         this->state = HTTP_MESSAGE_START;
00073                                 }
00074                                 else {
00075                                         cbufRelease(this->buffer);
00076                                         this->ourLock = FALSE;
00077                                         cont          = 0;
00078                                 }
00079 
00080                                 break;
00081 
00082                         case HTTP_MESSAGE_START:
00083                                 if (NULL == (line = cbufGetLine(this->buffer, &line_end))) {
00084                                         if (! cbufIsEmpty(this->buffer)) {
00085                                                 this->isize = this->buffer->bused;
00086                                                 this->incomplete = malloc(this->isize);
00087                                                 memcpy(this->incomplete,
00088                                                                 cbufGetData(this->buffer, this->isize),
00089                                                                 this->isize);
00090                                         }
00091                                         cbufRelease(this->buffer);
00092                                         this->ourLock = FALSE;
00093                                         cont = 0;
00094                                         break;
00095                                 }
00096                                 
00097                                 httpParserNewMessage(this, line, line_end);
00098                                 if (NULL == this->current) {
00099                                         cbufRelease(this->buffer);
00100                                         this->ourLock = FALSE;
00101                                         return -1;
00102                                 }
00103                                 httpParserRequestVars(this);
00104 
00105                                 this->state = HTTP_MESSAGE_INTRO_DONE;
00106                                 break;
00107 
00108                         case HTTP_MESSAGE_INTRO_DONE:
00109                                 if (NULL == (line = cbufGetLine(this->buffer, &line_end))) {
00110                                         if (! cbufIsEmpty(this->buffer)) {
00111                                                 this->isize = this->buffer->bused;
00112                                                 this->incomplete = malloc(this->isize);
00113                                                 memcpy(this->incomplete,
00114                                                                 cbufGetData(this->buffer, this->isize),
00115                                                                 this->isize);
00116                                         }
00117                                         cbufRelease(this->buffer);
00118                                         this->ourLock = FALSE;
00119                                         cont = 0;
00120                                         break;
00121                                 }
00122 
00123                                 if (0 == strlen(line)) {
00124                                         this->state = HTTP_MESSAGE_HEADERS_DONE;
00125                                         break;
00126                                 }
00127 
00128                                 httpParserHeader(this, line, line_end);
00129                                 break;
00130 
00131                         case HTTP_MESSAGE_HEADERS_DONE:
00132                                 if (this->current->dbody == this->current->nbody) {
00133                                         this->state = HTTP_MESSAGE_DONE;
00134                                         break;
00135                                 }
00136 
00137                                 if (cbufIsEmpty(this->buffer)) {
00138                                         cbufRelease(this->buffer);
00139                                         this->ourLock = FALSE;
00140                                         cont = 0;
00141                                         break;
00142                                 }
00143 
00144                                 cbufIncRead(
00145                                                 this->buffer,
00146                                                 httpParserBody(
00147                                                         this,
00148                                                         cbufGetRead(this->buffer),
00149                                                         this->buffer->bused));
00150                                 break;
00151 
00152                         case HTTP_MESSAGE_DONE:
00153                                 {
00154                                         HttpHeader enc = hashGet(
00155                                                         this->current->header,
00156                                                         CSTRA("content-type"));
00157 
00161                                         if (NULL != enc && 0 == strncasecmp(
00162                                                                 "application/x-www-form-urlencoded",
00163                                                                 enc->value[0],
00164                                                                 MIN(sizeof("application/x-www-form-urlencoded")-1,
00165                                                                         enc->nvalue[0]))) {
00167                                                 httpParserPostVars(this);
00168                                         }
00169 
00173                                 this->queue->msgs[(this->queue->nmsgs)++] = this->current;
00174                                 this->current                             = NULL;
00175 
00179                                 this->state = HTTP_MESSAGE_GARBAGE;
00180                                 }
00181                                 break;
00182 
00183                         default:
00184                                 break;
00185                 }
00186         }
00187 
00188         return this->queue->nmsgs;
00189 }
00190 
00191 // vim: set ts=4 sw=4:
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines