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

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

ssize_t
httpRequestParserParse(HttpRequestParser this, int fd)
{
	int     cont = 1;
	ssize_t read;
	char *  line;

	if (cbufIsLocked(this->buffer)) {
		if (FALSE == this->ourLock)
			return 0;
	}
	else {
		cbufLock(this->buffer);
		this->ourLock = TRUE;
	}

	if(0 > (read = cbufRead(this->buffer, fd))) {
		return read;
	}

	while (cont) {
		switch(this->state) {
			case HTTP_REQUEST_GARBAGE:
				cbufSkipNonAlpha(this->buffer);
				if (! cbufIsEmpty(this->buffer)) {
					this->cur_request = new(HttpRequest);
					this->state       = HTTP_REQUEST_START;
				}
				else {
					cbufRelease(this->buffer);
					this->ourLock = FALSE;
					cont          = 0;
				}

				break;

			case HTTP_REQUEST_START:
				if (NULL == (line = cbufGetLine(this->buffer))) {
					cont = 0;
					break;
				}

				if (0 > httpRequestParserGetRequestLine(this, line_end)) {
					ret  = -1;
					cont = 0;
					break;
				}

				len = line_end - this->buffer->buffer - this->buffer->bstart + 2;
				this->buffer->bstart += len;
				if (this->buffer->bstart >= this->buffer->bsize) {
					this->buffer->bstart -= this->buffer->bsize;
				}
				this->buffer->bused  -= len;

				this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
				break;

			case HTTP_REQUEST_REQUEST_LINE_DONE:
				if (NULL == (line = cbufGetLine(this->buffer))) {
					cont = 0;
					break;
				}

				if (0 == line_end - this->buffer->buffer - this->buffer->bstart) {
					this->buffer->bstart += 2;
					if (this->buffer->bstart >= this->buffer->bsize) {
						this->buffer->bstart -= this->buffer->bsize;
					}
					this->buffer->bused  -= 2;

					this->state = HTTP_REQUEST_HEADERS_DONE;
					break;
				}

				httpRequestParserGetHeader(this, line_end);

				len = line_end - this->buffer->buffer - this->buffer->bstart + 2;
				this->buffer->bstart += len;
				if (this->buffer->bstart >= this->buffer->bsize) {
					this->buffer->bstart -= this->buffer->bsize;
				}
				this->buffer->bused  -= len;

				break;

			case HTTP_REQUEST_HEADERS_DONE:
				{
					HttpMessage message = (HttpMessage)this->cur_request;

					httpRequestParserGetBody(this);

					if (message->dbody == message->nbody) {
						this->state = HTTP_REQUEST_DONE;
					}
				}
				break;

			case HTTP_REQUEST_DONE:
				this->request_queue->msgs[(this->request_queue->nmsgs)++] =
					(HttpMessage)this->cur_request;

				this->cur_request = NULL;

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

				break;

			default:
				break;
		}
	}

	return ret;
}

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