diff --git a/nbproject/Makefile-Debug.mk b/nbproject/Makefile-Debug.mk index 355b786..f847d2b 100644 --- a/nbproject/Makefile-Debug.mk +++ b/nbproject/Makefile-Debug.mk @@ -35,9 +35,8 @@ OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM} # Object Files OBJECTFILES= \ - ${OBJECTDIR}/src/http/basicresponses.o \ ${OBJECTDIR}/src/http/http.o \ - ${OBJECTDIR}/src/http/request.o \ + ${OBJECTDIR}/src/http/parse.o \ ${OBJECTDIR}/src/main.o \ ${OBJECTDIR}/src/socket.o @@ -56,7 +55,7 @@ FFLAGS= ASFLAGS= # Link Libraries and Options -LDLIBSOPTIONS=-lpthread +LDLIBSOPTIONS=-lhttp_parser # Build Targets .build-conf: ${BUILD_SUBPROJECTS} @@ -66,20 +65,15 @@ ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp: ${OBJECTFILES} ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} ${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp ${OBJECTFILES} ${LDLIBSOPTIONS} -${OBJECTDIR}/src/http/basicresponses.o: src/http/basicresponses.c - ${MKDIR} -p ${OBJECTDIR}/src/http - ${RM} "$@.d" - $(COMPILE.c) -g -Werror -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/basicresponses.o src/http/basicresponses.c - ${OBJECTDIR}/src/http/http.o: src/http/http.c ${MKDIR} -p ${OBJECTDIR}/src/http ${RM} "$@.d" $(COMPILE.c) -g -Werror -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/http.o src/http/http.c -${OBJECTDIR}/src/http/request.o: src/http/request.c +${OBJECTDIR}/src/http/parse.o: src/http/parse.c ${MKDIR} -p ${OBJECTDIR}/src/http ${RM} "$@.d" - $(COMPILE.c) -g -Werror -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/request.o src/http/request.c + $(COMPILE.c) -g -Werror -std=c99 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/parse.o src/http/parse.c ${OBJECTDIR}/src/main.o: src/main.c ${MKDIR} -p ${OBJECTDIR}/src diff --git a/nbproject/Makefile-Release.mk b/nbproject/Makefile-Release.mk index 033d87d..a0870ca 100644 --- a/nbproject/Makefile-Release.mk +++ b/nbproject/Makefile-Release.mk @@ -35,9 +35,8 @@ OBJECTDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM} # Object Files OBJECTFILES= \ - ${OBJECTDIR}/src/http/basicresponses.o \ ${OBJECTDIR}/src/http/http.o \ - ${OBJECTDIR}/src/http/request.o \ + ${OBJECTDIR}/src/http/parse.o \ ${OBJECTDIR}/src/main.o \ ${OBJECTDIR}/src/socket.o @@ -66,20 +65,15 @@ ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp: ${OBJECTFILES} ${MKDIR} -p ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM} ${LINK.c} -o ${CND_DISTDIR}/${CND_CONF}/${CND_PLATFORM}/khttp ${OBJECTFILES} ${LDLIBSOPTIONS} -${OBJECTDIR}/src/http/basicresponses.o: src/http/basicresponses.c - ${MKDIR} -p ${OBJECTDIR}/src/http - ${RM} "$@.d" - $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/basicresponses.o src/http/basicresponses.c - ${OBJECTDIR}/src/http/http.o: src/http/http.c ${MKDIR} -p ${OBJECTDIR}/src/http ${RM} "$@.d" $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/http.o src/http/http.c -${OBJECTDIR}/src/http/request.o: src/http/request.c +${OBJECTDIR}/src/http/parse.o: src/http/parse.c ${MKDIR} -p ${OBJECTDIR}/src/http ${RM} "$@.d" - $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/request.o src/http/request.c + $(COMPILE.c) -O2 -MMD -MP -MF "$@.d" -o ${OBJECTDIR}/src/http/parse.o src/http/parse.c ${OBJECTDIR}/src/main.o: src/main.c ${MKDIR} -p ${OBJECTDIR}/src diff --git a/nbproject/configurations.xml b/nbproject/configurations.xml index 35ba6c8..2f4bb61 100644 --- a/nbproject/configurations.xml +++ b/nbproject/configurations.xml @@ -4,10 +4,9 @@ - src/http/basicresponses.h src/http/http.h src/main.h - src/http/request.h + src/http/parse.h src/socket.h - src/http/basicresponses.c src/http/http.c src/main.c - src/http/request.c + src/http/parse.c src/socket.c Makefile - content/responses/400.html - dist/Debug/GNU-Linux-x86/content/blah content/error.html - content/test.txt include @@ -58,32 +53,19 @@ - PosixThreads + http_parser - - - - - - - - - - - + - + @@ -116,26 +98,13 @@ - - - - - - - - - - - + - + diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml index e33a103..04e60a6 100644 --- a/nbproject/private/private.xml +++ b/nbproject/private/private.xml @@ -7,17 +7,17 @@ + file:/home/sam/NetBeansProjects/KHttp/src/socket.c file:/home/sam/NetBeansProjects/KHttp/src/http/http.h + file:/home/sam/NetBeansProjects/KHttp/src/http/parse.c file:/home/sam/NetBeansProjects/KHttp/src/ut/utarray.h file:/home/sam/NetBeansProjects/KHttp/src/main.h file:/home/sam/NetBeansProjects/KHttp/Makefile - file:/home/sam/NetBeansProjects/KHttp/src/http/request.h file:/home/sam/NetBeansProjects/KHttp/content/error.html - file:/home/sam/NetBeansProjects/KHttp/src/http/basicresponses.h + file:/home/sam/NetBeansProjects/KHttp/src/http/parse.h file:/home/sam/NetBeansProjects/KHttp/src/main.c - file:/home/sam/NetBeansProjects/KHttp/src/http/request.c + file:/home/sam/NetBeansProjects/KHttp/src/socket.h file:/home/sam/NetBeansProjects/KHttp/src/http/http.c - file:/home/sam/NetBeansProjects/KHttp/src/http/basicresponses.c diff --git a/src/http/basicresponses.c b/src/http/basicresponses.c deleted file mode 100644 index 48b6906..0000000 --- a/src/http/basicresponses.c +++ /dev/null @@ -1,26 +0,0 @@ -#include -#include -#include -#include "http.h" -#include "../main.h" - -http_response* response_create_builtin(uint16_t code, char* errmsg) { - http_response *resp = http_response_new(http_response_line_new(code)); - - http_header_list_add(resp->headers, http_header_new(HEADER_CONTENT_TYPE, "text/html"), false); - - file_map* errorpage = map_file("content/error.html"); - http_response_append_body(resp, errorpage->map); - free_mapped_file(errorpage); - - char buffer[1024] = {0}; - - char* title_message = http_response_line_get_message(resp->resp); - snprintf(buffer, 1023, "%s %hu - %s", (code >= 400) ? "Error" : "Response Code", code, title_message); - resp->body = str_replace(resp->body, "{{title}}", buffer); - resp->body = str_replace(resp->body, "{{body_title}}", buffer); - - resp->body = str_replace(resp->body, "{{message}}", errmsg); - - return resp; -} \ No newline at end of file diff --git a/src/http/basicresponses.h b/src/http/basicresponses.h deleted file mode 100644 index 493853e..0000000 --- a/src/http/basicresponses.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * File: basicresponses.h - * Author: sam - * - * Created on 20 July 2014, 15:19 - */ - -#ifndef BASICRESPONSES_H -#define BASICRESPONSES_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "http.h" -#include "../main.h" - - http_response* response_create_builtin(uint16_t code, char* errmsg); - -#ifdef __cplusplus -} -#endif - -#endif /* BASICRESPONSES_H */ - diff --git a/src/http/http.c b/src/http/http.c index f7ade84..cf9dc7e 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -6,8 +6,8 @@ #include #include "../main.h" #include "../ut/utarray.h" +#include "../ut/utstring.h" #include "http.h" -#include "basicresponses.h" /* * METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, @@ -15,9 +15,13 @@ METHOD_CONNECT, METHOD_OTHER */ -UT_icd http_header_icd = {sizeof(http_header), NULL, NULL, NULL}; +void http_header_icd_init_f(void* elem) { + memset(elem, 1, sizeof(http_header)); +} -char* http_method_getstring(http_method method, char* method_other) { +UT_icd http_header_icd = {sizeof(http_header), http_header_icd_init_f, NULL, NULL}; + +char* http_method_getstring(http_request_method method, char* method_other) { switch(method) { case METHOD_GET: return "GET"; case METHOD_POST: return "POST"; @@ -33,12 +37,12 @@ char* http_method_getstring(http_method method, char* method_other) { } } -http_method http_method_fromstring(const char* method) { - http_method methods[] = {METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, +http_request_method http_method_fromstring(const char* method) { + http_request_method methods[] = {METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, METHOD_DELETE, METHOD_OPTIONS, METHOD_TRACE, METHOD_CONNECT}; - size_t count = sizeof(methods) / sizeof(http_method); + size_t count = sizeof(methods) / sizeof(http_request_method); for(int i=0; i < count; i++) { if (strcmp(http_method_getstring(methods[i],NULL), method) == 0) { return methods[i]; @@ -47,7 +51,7 @@ http_method http_method_fromstring(const char* method) { return METHOD_INVALID; } -http_request_line *http_request_line_new(http_method method, const char* other) { +http_request_line *http_request_line_new(http_request_method method, const char* other) { http_request_line *req = calloc(1, sizeof(http_request_line)); if (req == NULL) { fatal("calloc failed"); @@ -150,7 +154,7 @@ void http_header_append_content(http_header *header, const char* content) { } strcpy(header->content, content); } else { - uint32_t newlen = strlen(header->content) + strlen(content) + 1; + size_t newlen = strlen(header->content) + strlen(content) + 1; header->content = realloc(header->content, newlen); if (header->content == NULL) { fatal("calloc failed"); @@ -239,7 +243,9 @@ void http_request_append_body(http_request *req, const char* body) { strcat(req->body, body); } void http_request_delete(http_request *req) { - http_request_line_delete(req->req); + if (req->req != NULL) { + http_request_line_delete(req->req); + } http_header_list_delete(req->headers); free(req->body); free(req); @@ -271,14 +277,17 @@ void http_response_delete(http_response *resp) { free(resp->body); free(resp); } -void http_response_write(FILE *target, http_response *resp) { +char* http_response_write(http_response *resp) { + UT_string *output = calloc(1, sizeof(UT_string)); + utstring_init(output); + if (resp->resp->version == HTTP10) { - fprintf(target, "HTTP/1.0 "); + utstring_printf(output, "HTTP/1.0 "); } else if (resp->resp->version == HTTP11) { - fprintf(target, "HTTP/1.1 "); + utstring_printf(output, "HTTP/1.1 "); } //Write the response line - fprintf(target, "%hu %s\r\n", resp->resp->code, http_response_line_get_message(resp->resp)); + utstring_printf(output, "%hu %s\r\n", resp->resp->code, http_response_line_get_message(resp->resp)); if (resp->resp->code != 100) { //No additional headers for Continue messages //Add content length header @@ -300,13 +309,42 @@ void http_response_write(FILE *target, http_response *resp) { //write headers HTTP_HEADER_FOREACH(resp->headers, elem) { - fprintf(target, "%s: %s\r\n", elem->name, elem->content); + utstring_printf(output, "%s: %s\r\n", elem->name, elem->content); } - fprintf(target, "\r\n"); + utstring_printf(output, "\r\n"); //Write the request //TODO: chunked support for output if (resp->body != NULL) { - fprintf(target, "%s", resp->body); + utstring_printf(output, "%s", resp->body); } + char* outputStr = utstring_body(output); + free(output); + return outputStr; +} + +http_response* http_response_create_builtin(uint16_t code, char* errmsg) { + http_response *resp = http_response_new(http_response_line_new(code)); + + http_header_list_add(resp->headers, http_header_new(HEADER_CONTENT_TYPE, "text/html"), false); + + file_map* errorpage = map_file("content/error.html"); + if (errorpage != NULL) { + http_response_append_body(resp, errorpage->map); + free_mapped_file(errorpage); + } else { + http_response_append_body(resp, "{{title}}\n\n{{message}}"); + http_header_list_add(resp->headers, http_header_new(HEADER_CONTENT_TYPE, "text/plain"), true); + } + + char buffer[1024] = {0}; + + char* title_message = http_response_line_get_message(resp->resp); + snprintf(buffer, 1023, "%s %hu - %s", (code >= 400) ? "Error" : "Response Code", code, title_message); + resp->body = str_replace(resp->body, "{{title}}", buffer); + resp->body = str_replace(resp->body, "{{body_title}}", buffer); + + resp->body = str_replace(resp->body, "{{message}}", errmsg); + + return resp; } \ No newline at end of file diff --git a/src/http/http.h b/src/http/http.h index 5e44854..f2b1b5e 100644 --- a/src/http/http.h +++ b/src/http/http.h @@ -31,18 +31,18 @@ extern "C" { #define FORMAT_HEADER_DATE "%a, %e %h %Y %T %Z" - typedef enum http_method { + typedef enum http_request_method { METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, METHOD_DELETE, METHOD_OPTIONS, METHOD_TRACE, METHOD_CONNECT, METHOD_OTHER, METHOD_INVALID - } http_method; + } http_request_method; typedef enum http_version { HTTP10, HTTP11 } http_version; typedef struct http_request_line { - http_method method; + http_request_method method; char* method_other; char* uri; http_version version; @@ -64,7 +64,7 @@ extern "C" { extern UT_icd http_header_icd; #define HTTP_HEADER_FOREACH(list, elem) \ - for ( http_header *elem= (http_header*)utarray_front(list); \ + for ( http_header *elem= (http_header*)utarray_next(list,NULL); \ elem!= NULL; \ elem=(http_header*)utarray_next(list,elem)) @@ -86,10 +86,10 @@ extern "C" { } http_response; - char* http_method_getstring(http_method method, char* method_other); - http_method http_method_fromstring(const char* method); + char* http_method_getstring(http_request_method method, char* method_other); + http_request_method http_method_fromstring(const char* method); - http_request_line* http_request_line_new(http_method method, const char* other); + http_request_line* http_request_line_new(http_request_method method, const char* other); void http_request_line_delete(http_request_line *req); http_response_line* http_response_line_new(uint16_t code); @@ -113,7 +113,8 @@ extern "C" { http_response* http_response_new(http_response_line *resp); void http_response_append_body(http_response *resp, const char* body); void http_response_delete(http_response *resp); - void http_response_write(FILE *target, http_response *resp); + char* http_response_write(http_response *resp); + http_response* http_response_create_builtin(uint16_t code, char* errmsg); #ifdef __cplusplus } diff --git a/src/http/parse.c b/src/http/parse.c new file mode 100644 index 0000000..e78fe08 --- /dev/null +++ b/src/http/parse.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include + +#include "../main.h" +#include "http.h" +#include "parse.h" + +#define GETSTR(str, at, length) do { \ + str = calloc(length+1, sizeof(char));\ + strncpy(str, at, length);\ +}while(0); + +http_parser_settings *parser_settings = NULL; + +skt_elem *current_socket=NULL; + +void parser_set_currentskt(skt_elem *elem) { + current_socket = elem; +} + +http_parser_settings* parser_get_settings(skt_elem *elem) { + if (parser_settings == NULL) { + parser_settings = calloc(1, sizeof(http_parser_settings)); + parser_settings->on_body = parser_cb_on_body; + parser_settings->on_header_field = parser_cb_on_header_field; + parser_settings->on_header_value = parser_cb_on_header_value; + parser_settings->on_headers_complete = parser_cb_on_headers_complete; + parser_settings->on_message_begin = parser_cb_on_message_begin; + parser_settings->on_message_complete = parser_cb_on_message_complete; + parser_settings->on_status_complete = parser_cb_on_status; + parser_settings->on_url = parser_cb_on_url; + } + parser_set_currentskt(elem); + return parser_settings; +} + +int parser_cb_on_message_begin(http_parser* parser) { + info("parser_cb_on_message_begin"); + if (current_socket->current_request != NULL) { + http_request_delete(current_socket->current_request); + } + current_socket->current_request = http_request_new(); + + return 0; +} +int parser_cb_on_url(http_parser* parser, const char *at, size_t length) { + char* str;GETSTR(str,at,length); + info("parser_cb_on_url: %s",str); + current_socket->current_request->req = http_request_line_new(http_method_fromstring(http_method_str(parser->method)), NULL); + current_socket->current_request->req->uri = str; + return 0; +} +int parser_cb_on_status(http_parser* parser) { + //Responses only, so ignored + info("parser_cb_on_status"); + return 0; +} +int parser_cb_on_header_field(http_parser* parser, const char *at, size_t length) { + char* str;GETSTR(str,at,length); + info("parser_cb_on_header_field: %s",str); + + if (current_socket->parser_header_state == HSTATE_NONE) { + //First call, new header + if (current_socket->parser_current_header != NULL) { + http_header_delete(current_socket->parser_current_header); + } + current_socket->parser_current_header = http_header_new(str, NULL); + } else if (current_socket->parser_header_state == HSTATE_VALUE) { + //New header + if (current_socket->parser_current_header != NULL) { + http_header_list_add(current_socket->current_request->headers, current_socket->parser_current_header, false); + } + current_socket->parser_current_header = http_header_new(str, NULL); + } else if (current_socket->parser_header_state == HSTATE_FIELD) { + //continuation of current headers name + http_header* header = current_socket->parser_current_header; + size_t newlen = strlen(header->name) + length +1; + header->name = realloc(header->name, newlen * sizeof(char)); + } else { + return 1; + } + + current_socket->parser_header_state = HSTATE_FIELD; + free(str); + return 0; + +} +int parser_cb_on_header_value(http_parser* parser, const char *at, size_t length) { + char* str;GETSTR(str,at,length); + info("parser_cb_on_header_value: %s",str); + + http_header_append_content(current_socket->parser_current_header, str); + + current_socket->parser_header_state = HSTATE_VALUE; + free(str); + return 0; +} +int parser_cb_on_headers_complete(http_parser* parser) { + info("parser_cb_on_headers_complete"); + + //save current header + if (current_socket->parser_current_header != NULL) { + http_header_list_add(current_socket->current_request->headers, current_socket->parser_current_header, false); + current_socket->parser_current_header = NULL; + } + + //the http version should also be set now + if (parser->http_major == 1) { + if (parser->http_minor == 0) { + current_socket->current_request->req->version = HTTP10; + } else if (parser->http_minor == 1) { + current_socket->current_request->req->version = HTTP11; + } else { + return -1; + } + } else { + return -1; + } + + return 0; +} +int parser_cb_on_body(http_parser* parser, const char *at, size_t length) { + char* str;GETSTR(str,at,length); + info("parser_cb_on_body: %s",str); + + http_request_append_body(current_socket->current_request, str); + + free(str); + return 0; +} +int parser_cb_on_message_complete(http_parser* parser) { + info("parser_cb_on_message_complete"); + + current_socket->request_complete = true; + + return 0; +} \ No newline at end of file diff --git a/src/http/parse.h b/src/http/parse.h new file mode 100644 index 0000000..7ac44a5 --- /dev/null +++ b/src/http/parse.h @@ -0,0 +1,38 @@ +/* + * File: parse.h + * Author: sam + * + * Created on 21 July 2014, 15:17 + */ + +#ifndef PARSE_H +#define PARSE_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include "http.h" +#include "../main.h" + + + void parser_set_currentskt(skt_elem *elem); + + http_parser_settings* parser_get_settings(skt_elem *elem); + + int parser_cb_on_message_begin(http_parser* parser); + int parser_cb_on_url(http_parser* parser, const char *at, size_t length); + int parser_cb_on_status(http_parser* parser); + int parser_cb_on_header_field(http_parser* parser, const char *at, size_t length); + int parser_cb_on_header_value(http_parser* parser, const char *at, size_t length); + int parser_cb_on_headers_complete(http_parser* parser); + int parser_cb_on_body(http_parser* parser, const char *at, size_t length); + int parser_cb_on_message_complete(http_parser* parser); + +#ifdef __cplusplus +} +#endif + +#endif /* PARSE_H */ + diff --git a/src/http/request.c b/src/http/request.c deleted file mode 100644 index 4dee891..0000000 --- a/src/http/request.c +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -#include "../main.h" -#include "http.h" -#include "basicresponses.h" - -http_response* parse_request(http_request *req, char *input) { - size_t line_count; - char** lines = str_splitlines(input, &line_count); - http_response* response = NULL; - - switch(req->parsestatus) { - case PARSE_REQUESTLINE: - if (line_count == 0) { - break; - } - - char* requestStr = lines[0]; - - char methodStr[20] = {0}; - char uriStr[1024] = {0}; - char versionStr[16] = {0}; - - int count = sscanf(requestStr, "%19s%*[ \t]%1023s%*[ \t]%15s", methodStr, uriStr, versionStr); - if (count < 3) { - response = response_create_builtin(400, "Could not parse request line"); - req->parsestatus = PARSE_FAIL; - break; - } - - http_method method = http_method_fromstring(methodStr); - if (method == METHOD_INVALID) { - response = response_create_builtin(405, ""); - req->parsestatus = PARSE_FAIL; - break; - } - - http_version version; - if (strcasecmp(versionStr, "HTTP/1.0") == 0) { version = HTTP10; } - else if (strcasecmp(versionStr, "HTTP/1.1") == 0) { version = HTTP11; } - else { - response = response_create_builtin(505, ""); - req->parsestatus = PARSE_FAIL; - break; - } - - http_request_line *request_line = http_request_line_new(method, NULL); - request_line->version = version; - request_line->uri = calloc(strlen(uriStr)+1, sizeof(char)); - if (request_line->uri == NULL) { - fatal("calloc failed"); - } - strcpy(request_line->uri, uriStr); - req->req = request_line; - req->parsestatus = PARSE_HEADERS; - - if (req->req->version == HTTP11) { - response = http_response_new(http_response_line_new(100)); - } - - break; - case PARSE_HEADERS: - break; - case PARSE_BODY: - break; - case PARSE_DONE: - case PARSE_FAIL: - break; - } - - for(size_t i=0; i < line_count; i++) { - free(lines[i]); - free(lines); - } - - return response; -} \ No newline at end of file diff --git a/src/http/request.h b/src/http/request.h deleted file mode 100644 index 9cb4eb6..0000000 --- a/src/http/request.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * File: request.h - * Author: sam - * - * Created on 18 July 2014, 14:43 - */ - -#ifndef REQUEST_H -#define REQUEST_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../ut/utstring.h" -#include "http.h" - - http_response *parse_request(http_request *req, char *input); - - -#ifdef __cplusplus -} -#endif - -#endif /* REQUEST_H */ - diff --git a/src/main.c b/src/main.c index ce5a42b..f1ab8e3 100644 --- a/src/main.c +++ b/src/main.c @@ -14,30 +14,18 @@ #include #include #include +#include #include "ut/utlist.h" #include "ut/utarray.h" #include "main.h" #include "socket.h" #include "http/http.h" -#include "http/request.h" -#include "http/basicresponses.h" +#include "http/parse.h" int serverfd = 0; -char* teststr = "testing testing 123 123 omg"; -/* - * - */ int main(int argc, char** argv) { - - http_response* resp = response_create_builtin(404, "testing"); - - http_response_write(stdout, resp); - - http_response_delete(resp); - - return 0; skt_elem *connections = NULL; serverfd = svr_create(); @@ -52,10 +40,7 @@ int main(int argc, char** argv) { while(counter < 100 && svr_canaccept(serverfd)) { skt_info *info = svr_accept(serverfd); if (info != NULL) { - skt_elem* newconn = calloc(1, sizeof(skt_elem)); - newconn->info = info; - newconn->current_request = http_request_new(); - LL_APPEND(connections, newconn); + LL_APPEND(connections, skt_elem_new(info)); } } @@ -69,15 +54,31 @@ int main(int argc, char** argv) { //Process sockets LL_FOREACH(connections, elem) { if (utstring_len(elem->info->read) > 0) { - utstring_printf(elem->info->write, "->"); - utstring_concat(elem->info->write, elem->info->read); + int parsedcount = http_parser_execute( + elem->parser, + parser_get_settings(elem), + utstring_body(elem->info->read), + utstring_len(elem->info->read)); + if (parsedcount != utstring_len(elem->info->read)) { + warning("error parsing request. closing connection", false); + elem->info->close = true; + } utstring_clear(elem->info->read); + if (elem->request_complete == true) { + http_response* resp = http_response_create_builtin(200, elem->current_request->req->uri); + utstring_printf(elem->info->write, "%s", http_response_write(resp)); + http_response_delete(resp); + elem->request_complete = false; + http_request_delete(elem->current_request); + elem->current_request = NULL; + elem->info->close_afterwrite = true; + } } } //Write to connections LL_FOREACH(connections, elem) { - if (utstring_len(elem->info->write) > 0) { + if (utstring_len(elem->info->write) > 0 && elem->info->close == false) { skt_write(elem->info); } } @@ -91,7 +92,7 @@ int main(int argc, char** argv) { info("[#%lu %s] Timeout", elem->info->id, skt_clientaddr(elem->info)); elem->info->close = true; } - if (current - elem->info->time_opened> maxlife) { + if (current - elem->info->time_opened > maxlife) { info("[#%lu %s] Reached max life", elem->info->id, skt_clientaddr(elem->info)); elem->info->close = true; } @@ -106,11 +107,7 @@ int main(int argc, char** argv) { LL_FOREACH_SAFE(connections, elem, tmp) { if (elem->info->closed) { LL_DELETE(connections, elem); - skt_delete(elem->info); - if (elem->current_request != NULL) { - http_request_delete(elem->current_request); - } - free(elem); + skt_elem_delete(elem); } } } @@ -121,6 +118,21 @@ int main(int argc, char** argv) { return (EXIT_SUCCESS); } +skt_elem* skt_elem_new(skt_info *info) { + skt_elem* elem = calloc(1, sizeof(skt_elem)); + elem->info = info; + elem->parser = calloc(1, sizeof(http_parser)); + http_parser_init(elem->parser, HTTP_REQUEST); + elem->parser_header_state = HSTATE_NONE; + elem->request_complete = false; + return elem; +} +void skt_elem_delete(skt_elem* elem) { + if (elem->info!=NULL) skt_delete(elem->info); + if (elem->current_request!=NULL) http_request_delete(elem->current_request); + free(elem); +} + void fatal(char* msg) { fprintf(stderr, "\n"); perror(msg); @@ -192,12 +204,15 @@ file_map* map_file(const char* filename) { int fd = open(filename, O_RDONLY); if (fd < 0) { - fatal("Failed to open file for memory mapping"); + warning("Failed to open file for memory mapping", true); + return NULL; } size_t size = lseek(fd, 0L, SEEK_END); void* map = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0); if (map == MAP_FAILED) { - fatal("Failed to mmap file"); + warning("Failed to mmap file", true); + close(fd); + return NULL; } close(fd); diff --git a/src/main.h b/src/main.h index c2d2789..ef2eff8 100644 --- a/src/main.h +++ b/src/main.h @@ -13,11 +13,28 @@ extern "C" { #endif #include +#include +#include "socket.h" +#include "http/http.h" typedef struct file_map { char* map; size_t size; } file_map; + + typedef enum skt_elem_hstate {HSTATE_NONE, HSTATE_VALUE, HSTATE_FIELD} skt_elem_hstate; + typedef struct skt_elem { + skt_info* info; + http_request *current_request; + bool request_complete; + http_parser *parser; + http_header *parser_current_header; + skt_elem_hstate parser_header_state; + struct skt_elem *next; + } skt_elem; + + skt_elem* skt_elem_new(skt_info *info); + void skt_elem_delete(skt_elem* elem); int main(int argc, char** argv); diff --git a/src/socket.h b/src/socket.h index f161c65..e3ac468 100644 --- a/src/socket.h +++ b/src/socket.h @@ -35,12 +35,6 @@ extern "C" { struct sockaddr_in* clientaddr; }; - typedef struct skt_elem { - skt_info* info; - http_request *current_request; - struct skt_elem *next; - } skt_elem; - u_int64_t skt_nextid(); skt_info* skt_new(int fd); void skt_delete(skt_info *skt); diff --git a/testreq.txt b/testreq.txt new file mode 100644 index 0000000..d6d2969 --- /dev/null +++ b/testreq.txt @@ -0,0 +1,7 @@ +GET /testing123 HTTP/1.1 +Host: example.com +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/36.0.1985.125 Safari/537.36 +Referer: https://www.google.co.uk/ +Accept-Language: en-US,en;q=0.8 +