parse.c 2.11 KB
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>

#include "http/request/parser.h"
#include "interface/class.h"


static
inline
char *
httpRequestParserGetLine(char ** data)
{
	char * line_end = strstr(*data, "\r\n");
	char * ret      = *data;

	if (NULL == line_end) {
		return NULL;
	}

	*line_end = 0;
	*data = line_end + 2;

	return ret;
}

static
inline
void
httpRequestSkip(char ** data)
{
	for (; 0 != **data && ! isalpha(**data); (*data)++);
}

void
httpRequestParserParse(HttpRequestParser this)
{
	char * line;
	int    cont = 1;

	while (cont) {
		switch(this->state) {
			case HTTP_REQUEST_GARBAGE:
				this->cur_data = this->buffer; // initialize static pointer
				httpRequestSkip(&(this->cur_data));
				this->cur_request = new(HttpRequest);

				this->state = HTTP_REQUEST_START;
				break;

			case HTTP_REQUEST_START:
				if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) {
					cont = 0;
					break;
				}
				
				httpRequestParserGetRequestLine(this->cur_request, line);

				this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
				break;

			case HTTP_REQUEST_REQUEST_LINE_DONE:
				if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) {
					cont = 0;
					break;
				}

				if (0 == strlen(line)) {
					this->state = HTTP_REQUEST_HEADERS_DONE;
					break;
				}

				httpRequestParserGetHeader(this->cur_request, line);
				break;

			case HTTP_REQUEST_HEADERS_DONE:
				httpRequestParserGetBody(this);
				break;

			case HTTP_REQUEST_DONE:
				/**
				 * enqueue current request
				 */
				this->request_queue->msgs[(this->request_queue->nmsgs)++] =
					(HttpMessage)this->cur_request;
				this->cur_request = NULL;

				/**
				 * remove processed stuff from input buffer.
				 */
				memmove(this->buffer, this->cur_data, REMAINS(this));

				this->buffer_used -= this->cur_data - this->buffer;

				/**
				 * dont continue loop if input buffer is empty
				 */
				if (0 == this->buffer_used) {
					cont = 0;
				}

				/**
				 * prepare for next request
				 */
				this->state = HTTP_REQUEST_GARBAGE;

				break;

			default:
				break;
		}
	}
}

// vim: set ts=4 sw=4: