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
+