integrated http-parser lib

This commit is contained in:
2014-07-23 03:11:38 +01:00
parent b51ca6262a
commit bfe3a66903
16 changed files with 327 additions and 276 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -4,10 +4,9 @@
<logicalFolder name="HeaderFiles"
displayName="Header Files"
projectFiles="true">
<itemPath>src/http/basicresponses.h</itemPath>
<itemPath>src/http/http.h</itemPath>
<itemPath>src/main.h</itemPath>
<itemPath>src/http/request.h</itemPath>
<itemPath>src/http/parse.h</itemPath>
<itemPath>src/socket.h</itemPath>
</logicalFolder>
<logicalFolder name="ResourceFiles"
@@ -17,10 +16,9 @@
<logicalFolder name="SourceFiles"
displayName="Source Files"
projectFiles="true">
<itemPath>src/http/basicresponses.c</itemPath>
<itemPath>src/http/http.c</itemPath>
<itemPath>src/main.c</itemPath>
<itemPath>src/http/request.c</itemPath>
<itemPath>src/http/parse.c</itemPath>
<itemPath>src/socket.c</itemPath>
</logicalFolder>
<logicalFolder name="TestFiles"
@@ -34,10 +32,7 @@
kind="IMPORTANT_FILES_FOLDER">
<itemPath>Makefile</itemPath>
</logicalFolder>
<itemPath>content/responses/400.html</itemPath>
<itemPath>dist/Debug/GNU-Linux-x86/content/blah</itemPath>
<itemPath>content/error.html</itemPath>
<itemPath>content/test.txt</itemPath>
</logicalFolder>
<sourceRootList>
<Elem>include</Elem>
@@ -58,32 +53,19 @@
</cTool>
<linkerTool>
<linkerLibItems>
<linkerLibStdlibItem>PosixThreads</linkerLibStdlibItem>
<linkerLibLibItem>http_parser</linkerLibLibItem>
</linkerLibItems>
</linkerTool>
</compileType>
<item path="content/error.html" ex="false" tool="3" flavor2="0">
</item>
<item path="content/responses/400.html" ex="false" tool="3" flavor2="0">
</item>
<item path="content/test.txt" ex="false" tool="3" flavor2="0">
</item>
<item path="dist/Debug/GNU-Linux-x86/content/blah"
ex="false"
tool="3"
flavor2="0">
</item>
<item path="src/http/basicresponses.c" ex="false" tool="0" flavor2="0">
</item>
<item path="src/http/basicresponses.h" ex="false" tool="3" flavor2="0">
</item>
<item path="src/http/http.c" ex="false" tool="0" flavor2="0">
</item>
<item path="src/http/http.h" ex="false" tool="3" flavor2="0">
</item>
<item path="src/http/request.c" ex="false" tool="0" flavor2="0">
<item path="src/http/parse.c" ex="false" tool="0" flavor2="0">
</item>
<item path="src/http/request.h" ex="false" tool="3" flavor2="0">
<item path="src/http/parse.h" ex="false" tool="3" flavor2="0">
</item>
<item path="src/main.c" ex="false" tool="0" flavor2="0">
</item>
@@ -116,26 +98,13 @@
</compileType>
<item path="content/error.html" ex="false" tool="3" flavor2="0">
</item>
<item path="content/responses/400.html" ex="false" tool="3" flavor2="0">
</item>
<item path="content/test.txt" ex="false" tool="3" flavor2="0">
</item>
<item path="dist/Debug/GNU-Linux-x86/content/blah"
ex="false"
tool="3"
flavor2="0">
</item>
<item path="src/http/basicresponses.c" ex="false" tool="0" flavor2="0">
</item>
<item path="src/http/basicresponses.h" ex="false" tool="3" flavor2="0">
</item>
<item path="src/http/http.c" ex="false" tool="0" flavor2="0">
</item>
<item path="src/http/http.h" ex="false" tool="3" flavor2="0">
</item>
<item path="src/http/request.c" ex="false" tool="0" flavor2="0">
<item path="src/http/parse.c" ex="false" tool="0" flavor2="0">
</item>
<item path="src/http/request.h" ex="false" tool="3" flavor2="0">
<item path="src/http/parse.h" ex="false" tool="3" flavor2="0">
</item>
<item path="src/main.c" ex="false" tool="0" flavor2="0">
</item>

View File

@@ -7,17 +7,17 @@
<editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
<open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
<group>
<file>file:/home/sam/NetBeansProjects/KHttp/src/socket.c</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/http.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/parse.c</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/ut/utarray.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/main.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/Makefile</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/request.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/content/error.html</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/basicresponses.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/parse.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/main.c</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/request.c</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/socket.h</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/http.c</file>
<file>file:/home/sam/NetBeansProjects/KHttp/src/http/basicresponses.c</file>
</group>
</open-files>
</project-private>

View File

@@ -1,26 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#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;
}

View File

@@ -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 */

View File

@@ -6,8 +6,8 @@
#include <time.h>
#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) {
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;
}

View File

@@ -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
}

140
src/http/parse.c Normal file
View File

@@ -0,0 +1,140 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include <http_parser.h>
#include <assert.h>
#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;
}

38
src/http/parse.h Normal file
View File

@@ -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 <http_parser.h>
#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 */

View File

@@ -1,79 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#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;
}

View File

@@ -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 */

View File

@@ -14,30 +14,18 @@
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <http_parser.h>
#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);
}
}
@@ -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);

View File

@@ -13,12 +13,29 @@ extern "C" {
#endif
#include <stdbool.h>
#include <http_parser.h>
#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);
void fatal(char* msg);

View File

@@ -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);

7
testreq.txt Normal file
View File

@@ -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