From abba4f78182e9817cf37c6910e41f08c6fda287d Mon Sep 17 00:00:00 2001 From: Aki Date: Thu, 25 Feb 2021 21:27:07 +0100 Subject: Removed old request parsing implementation --- connection.c | 2 - request.c | 364 ----------------------------------------------------------- request.h | 33 ------ 3 files changed, 399 deletions(-) delete mode 100644 request.c delete mode 100644 request.h diff --git a/connection.c b/connection.c index 055b498..8fad3c5 100644 --- a/connection.c +++ b/connection.c @@ -7,8 +7,6 @@ #include #include -#include "request.h" - /// Creates new connection. /// \param L Server's Lua state /// \param client File descriptor of client's socket diff --git a/request.c b/request.c deleted file mode 100644 index ae5f74d..0000000 --- a/request.c +++ /dev/null @@ -1,364 +0,0 @@ -#include "request.h" - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "connection.h" - -static const int REQUEST_DATA_SIZE = 4096; - -/// Allocates and initializes request structure. -/// \param connection Origin connection of the request -/// \return Pointer to initialized request or NULL in case of an error -/// \see /free_request -struct request * new_request(void) -{ - struct request * request = malloc(sizeof(struct request)); - - if (NULL == request) - { - return NULL; - } - - memset(request, 0, sizeof(struct request)); - request->step = parse_step_method; - - request->data = malloc(REQUEST_DATA_SIZE); - - if (NULL == request->data) - { - free(request); - return NULL; - } - - return request; -} - -/// Releases memory used by the request and the request itself. -/// \param request Request to free -/// \see /new_request -void free_request(struct request * request) -{ - if (NULL != request->data) - { - free(request->data); - } - - free(request); -} - -/// Collects request between calls to `poll`. -/// \param connection Origin connection of the request -/// \return Number of bytes parsed, -1 if an error occured or 0 if expects more data -int parse_request(struct connection * connection) -{ - if (NULL == connection->request) - { - connection->request = new_request(); - if (NULL == connection->request) - { - return -1; - } - } - - // TODO: Expand buffer until EAGAIN or arbitrary limit - int length = read(connection->fd, connection->request->data, REQUEST_DATA_SIZE - 1); - - if (0 == length || (-1 == length && EWOULDBLOCK != errno && EAGAIN != errno)) - { - return -1; // TODO: Handle errors properly - } - - connection->request->data[length] = 0; - connection->request->length = length; - - return connection->request->step(connection->L, connection->request); -} - - -/// Progresses the readout of the request until delimiter is found. -/// \param request Request to process -/// \param delimiter Character that marks the end of the readout -/// \return Position of the delimiter or 0 if the deliminter could not be found -static int read_until_char(struct request * request, const char delimiter) -{ - char character; - while (request->position < request->length) - { - character = request->data[request->position]; - if (delimiter == character) - { - return request->position; - } - request->position++; - } - return 0; -} - -/// Progresses the readout of the request until non-whitespace character is found. -/// \param request Request to process -/// \return Position of the first non-whitespace character or 0 if it could not be found -/// \see isalpha(3) -static int read_until_word(struct request * request) -{ - char character; - while (request->position < request->length) - { - character = request->data[request->position]; - if (!isspace(character)) - { - return request->position; - } - request->position++; - } - return 0; -} - -/// Progresses the readout of the request until line separator is found. -/// \param request Request to process -/// \return Position of the first byte of the separator or 0 if line separator could not be found -static int read_rest_of_line(struct request * request) -{ - while (request->position < request->length - 1) - { - if ('\r' == request->data[request->position] && '\n' == request->data[request->position + 1]) - { - return request->position; - } - else if ('\r' == request->data[request->position + 1]) - { - request->position += 1; - } - else - { - request->position += 2; - } - } - return 0; -} - -#define PROCEED_TO(_x) \ - request->temp.start = 0; \ - request->temp.length = 0; \ - request->step = _x; \ - return _x(L, request) - -/// Parses method field of the request. -/// \param L Connection's Lua state -/// \param request Request to process -/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed -int parse_step_method(lua_State * L, struct request * request) -{ - // TODO: Consider reworking read_* functions to be more aware of word boundaries. - request->temp.length = read_until_char(request, ' '); - - if (0 == request->temp.length) - { - return 0; - } - - lua_pushlstring(L, request->data + request->temp.start, request->temp.length); - - PROCEED_TO(parse_step_path); -} - -/// Parses path field of the request. -/// \param L Connection's Lua state -/// \param request Request to process -/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed -// TODO: Consider spliting path into an actual path and arguments in this stage -int parse_step_path(lua_State * L, struct request * request) -{ - // TODO: Rethink interface of parse_step_* and read_* functions. After a break it looks like mess; it's a bad sign. - if (0 >= request->temp.start) - { - request->temp.start = read_until_word(request); - - if (0 == request->temp.start) - { - return 0; - } - } - - const int result = read_until_char(request, ' '); - - if (0 == result) - { - return 0; - } - - request->temp.length = request->position - request->temp.start; - - // TODO: Use macro for pushing temporary span. Also clear the span in that macro instead of PROCEED_TO. - lua_pushlstring(L, request->data + request->temp.start, request->temp.length); - - PROCEED_TO(parse_step_version); -} - -/// Parses and verifies http version field of the request. -/// \param L Connection's Lua state -/// \param request Request to process -/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed -// TODO: Return -1 if version is unsupported, meaning other than HTTP/1.1 -int parse_step_version(lua_State * L, struct request * request) -{ - if (0 >= request->temp.start) - { - request->temp.start = read_until_word(request); - - if (0 == request->temp.start) - { - return 0; - } - } - - const int result = read_rest_of_line(request); - - if (0 == result) - { - return 0; - } - - request->temp.length = request->position - request->temp.start; - - lua_pushlstring(L, request->data + request->temp.start, request->temp.length); - - PROCEED_TO(parse_step_header_name); -} - -/// Parses and verifies name of a single header from the request. -/// \param L Connection's Lua state -/// \param request Request to process -/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed -int parse_step_header_name(lua_State * L, struct request * request) -{ - if (0 == lua_istable(L, -1)) - { - lua_newtable(L); - } - - if (request->length - request->position < 4) - { - return 0; - } - - if ( - request->data[request->position] == '\r' && - request->data[request->position + 1] == '\n' && - request->data[request->position + 2] == '\r' && - request->data[request->position + 3] == '\n') - { - // Skip "\r\n\r\n", end of headers. - request->position += 4; - - // Early return hidden in a macro! - PROCEED_TO(parse_step_data); - } - - if (0 >= request->temp.start) - { - request->temp.start = read_until_word(request); - - if (0 == request->temp.start) - { - return 0; - } - } - - int result = read_until_char(request, ':'); - - if (0 == result) - { - printf("parse_step_header_name:no ':'\n"); - return 0; - } - - request->temp.length = request->position - request->temp.start; - - if (0 == strncasecmp("content-length", request->data + request->temp.start, request->temp.length)) - { - // TODO: While it shouldn't happen, use a flag instead of a magic value. - request->expected_data_length = -1; - } - - lua_pushlstring(L, request->data + request->temp.start, request->temp.length); - - // Skip ':' - request->position++; - PROCEED_TO(parse_step_header_value); -} - -/// Parses and verifies value of a single header from the request. -/// \param L Connection's Lua state -/// \param request Request to process -/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed -int parse_step_header_value(lua_State * L, struct request * request) -{ - if (0 >= request->temp.start) - { - request->temp.start = read_until_word(request); - - if (0 == request->temp.start) - { - return 0; - } - } - - const int result = read_rest_of_line(request); - - if (0 == result) - { - return 0; - } - - request->temp.length = request->position - request->temp.start; - - if (-1 == request->expected_data_length) - { - *(request->data + request->temp.start + request->temp.length) = 0; - request->expected_data_length = atoi(request->data + request->temp.start); - *(request->data + request->temp.start + request->temp.length) = '\r'; - } - - lua_pushlstring(L, request->data + request->temp.start, request->temp.length); - lua_rawset(L, -3); - - PROCEED_TO(parse_step_header_name); -} - -/// Makes sure that the expected data is in payload and pushes it forward to Lua. -/// \param L Connection's Lua state -/// \param request Request to process -/// \return -1 if an error has occured, 0 if too little data available or total number of bytes processed -int parse_step_data(lua_State * L, struct request * request) -{ - const int bytes_left = request->length - request->position; - - if (bytes_left > request->expected_data_length) - { - return -1; - } - else if (bytes_left < request->expected_data_length) - { - return 0; - } - - lua_pushlstring(L, request->data + request->position, request->expected_data_length); - - if (NULL != request->data) - { - free(request->data); - request->data = NULL; - } - - return request->position; -} - -// TODO: Make a table from the request. diff --git a/request.h b/request.h deleted file mode 100644 index 690df88..0000000 --- a/request.h +++ /dev/null @@ -1,33 +0,0 @@ -#pragma once - -#include - -struct connection; - -struct span -{ - int start; - int length; -}; - -struct request -{ - int (* step)(lua_State *, struct request *); - char * data; - int length; - int position; - struct span temp; - int expected_data_length; -}; - -struct request * new_request(void); -void free_request(struct request *); - -int parse_request(struct connection *); - -int parse_step_method(lua_State *, struct request *); -int parse_step_path(lua_State *, struct request *); -int parse_step_version(lua_State *, struct request *); -int parse_step_header_name(lua_State *, struct request *); -int parse_step_header_value(lua_State *, struct request *); -int parse_step_data(lua_State *, struct request *); -- cgit v1.1