diff options
-rw-r--r-- | http.c | 59 | ||||
-rw-r--r-- | http.h | 8 | ||||
-rw-r--r-- | plop.c | 30 |
3 files changed, 52 insertions, 45 deletions
@@ -7,6 +7,8 @@ #include <string.h> #include <unistd.h> +static const int REQUEST_DATA_SIZE = 4096; + const char * status_str[] = { [STATUS_OK] = "200 OK", [STATUS_BAD_REQUEST] = "400 Bad Request", @@ -18,7 +20,7 @@ const char * status_str[] = { }; /// Allocates and initializes request structure. -/// \return Pointer to initialized request +/// \return Pointer to initialized request or NULL in case of an error /// \see /free_request struct request * new_request(void) { @@ -30,7 +32,15 @@ struct request * new_request(void) } memset(request, 0, sizeof(struct request)); - request->step = parse_method; + request->step = parse_step_method; + + request->data = malloc(REQUEST_DATA_SIZE); + + if (NULL == request->data) + { + free(request); + return NULL; + } return request; } @@ -42,7 +52,7 @@ void free_request(struct request * request) { if (NULL != request->data) { - // TODO: free(request->data); data lifetime is now managed by plop, move it here + free(request->data); } if (NULL != request->headers) @@ -92,15 +102,13 @@ int respond_with_body(const int fd, const enum status status, const char * body, /// Collects request between calls to `poll`. /// \param fd Client socket -/// \param request Buffer with the request content +/// \param request Pointer to current request context of handled client /// \return Number of bytes parsed, -1 if an error occured or 0 if expects more data -int collect_request(const int fd, char ** request) +int parse_request(const int fd, struct request ** request) { - static const int size = 4096; - if (NULL == *request) { - *request = malloc(size); + *request = new_request(); if (NULL == *request) { return -1; @@ -108,30 +116,17 @@ int collect_request(const int fd, char ** request) } // TODO: Expand buffer until EAGAIN or arbitrary limit - int length = read(fd, *request, size - 1); + int length = read(fd, (*request)->data, REQUEST_DATA_SIZE - 1); if (0 == length || (-1 == length && EWOULDBLOCK != errno && EAGAIN != errno)) { return -1; // TODO: Handle errors properly } - // TODO: Use struct request in plop - struct request * debug = new_request(); - debug->data = *request; - debug->length = length; - debug->step(debug); - - printf( - "(%.*s) [%.*s] %.*s\n", - debug->version.length, debug->data + debug->version.start, - debug->method.length, debug->data + debug->method.start, - debug->path.length, debug->data + debug->path.start); - - free_request(debug); - - (*request)[length] = 0; + (*request)->data[length] = 0; + (*request)->length = length; - return length; + return (*request)->step(*request); } @@ -199,7 +194,7 @@ static int read_rest_of_line(struct request * request) /// Parses method field of the request. /// \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_method(struct request * request) +int parse_step_method(struct request * request) { request->method.length = read_until_char(request, ' '); @@ -208,16 +203,16 @@ int parse_method(struct request * request) return 0; } - request->step = parse_path; + request->step = parse_step_path; - return parse_path(request); + return parse_step_path(request); } /// Parses path field of the request. /// \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_path(struct request * request) +int parse_step_path(struct request * request) { if (0 >= request->path.start) { @@ -237,16 +232,16 @@ int parse_path(struct request * request) } request->path.length = request->position - request->path.start; - request->step = parse_version; + request->step = parse_step_version; - return parse_version(request); + return parse_step_version(request); } /// Parses and verifies http version field of the request. /// \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_version(struct request * request) +int parse_step_version(struct request * request) { if (0 >= request->version.start) { @@ -45,10 +45,10 @@ void free_request(struct request *); int respond_only_status(int, enum status); int respond_with_body(int, enum status, const char *, int); -int collect_request(int, char **); +int parse_request(int, struct request **); -int parse_method(struct request *); -int parse_path(struct request *); -int parse_version(struct request *); +int parse_step_method(struct request *); +int parse_step_path(struct request *); +int parse_step_version(struct request *); #endif // HTTP_H @@ -5,6 +5,7 @@ #include <lualib.h> #include <netdb.h> #include <poll.h> +#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> @@ -82,11 +83,11 @@ int make_server(const char * node, const char * service) /// `pfd` must be at least `shift_by + 1`-th element of the array. /// \param L Server's Lua state /// \param pfd Element in array processed by poll -/// \param data Pointer to data associated with the client +/// \param request Pointer to request context associated with current client /// \param shift_by Element will be moved by in array this many indices /// \return Shift value for next handler /// \see poll(2) -int handle_client(lua_State * L, struct pollfd * pfd, char ** data, const int shift_by) +int handle_client(lua_State * L, struct pollfd * pfd, struct request ** request, const int shift_by) { if (0 == pfd->revents) { @@ -98,14 +99,22 @@ int handle_client(lua_State * L, struct pollfd * pfd, char ** data, const int sh return -1; // TODO: Handle errors properly } - if (-1 == collect_request(pfd->fd, data)) + if (-1 == parse_request(pfd->fd, request)) { respond_only_status(pfd->fd, STATUS_BAD_REQUEST); return -1; // TODO: Handle errors properly } + // TODO: Remove debug information or move to logging + printf( + "(%.*s) [%.*s] %.*s\n", + (*request)->version.length, (*request)->data + (*request)->version.start, + (*request)->method.length, (*request)->data + (*request)->method.start, + (*request)->path.length, (*request)->data + (*request)->path.start); + + // TODO: Use results from parsing instead of raw data lua_getglobal(L, "Handler"); - lua_pushstring(L, *data); + lua_pushlstring(L, (*request)->data, (*request)->length); lua_call(L, 1, 1); size_t length; @@ -124,8 +133,11 @@ int handle_client(lua_State * L, struct pollfd * pfd, char ** data, const int sh (pfd - shift_by)->fd = -1; (pfd - shift_by)->events = pfd->events; - free(*data); - *data = NULL; + if (NULL != *request) + { + free_request(*request); + *request = NULL; + } return shift_by + 1; } @@ -179,10 +191,10 @@ int main(int argc, char ** argv) static const int max_clients = 200; int fdc = 0; - char * data[max_clients]; + struct request * requests[max_clients]; struct pollfd fdv[max_clients]; - memset(data, 0, sizeof(data)); + memset(requests, 0, sizeof(requests)); memset(fdv, 0, sizeof(fdv)); fdv[0].fd = make_server(NULL, argv[1]); @@ -200,7 +212,7 @@ int main(int argc, char ** argv) for (int i = 1; i < fdc; ++i) { - shift_by = handle_client(L, &fdv[i], &data[i], shift_by); + shift_by = handle_client(L, &fdv[i], &requests[i], shift_by); } fdc = handle_server(fdv, fdc - shift_by, max_clients); |