diff --git a/dist/Debug/GNU-Linux-x86/khttp b/dist/Debug/GNU-Linux-x86/khttp deleted file mode 100755 index 923439d..0000000 Binary files a/dist/Debug/GNU-Linux-x86/khttp and /dev/null differ diff --git a/nbproject/private/configurations.xml b/nbproject/private/configurations.xml index a0dea49..daa4a74 100644 --- a/nbproject/private/configurations.xml +++ b/nbproject/private/configurations.xml @@ -13,6 +13,8 @@ + + diff --git a/src/http/http.c b/src/http/http.c index 203f949..557d6f0 100644 --- a/src/http/http.c +++ b/src/http/http.c @@ -3,6 +3,7 @@ #include #include #include "http.h" +#include "../main.h" /* * METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, @@ -32,7 +33,7 @@ http_method http_method_fromstring(const char* method) { METHOD_CONNECT}; size_t count = sizeof(methods) / sizeof(http_method); - for(int i; i < count; i++) { + for(int i=0; i < count; i++) { if (strcmp(http_method_getstring(methods[i],NULL), method) == 0) { return methods[i]; } @@ -42,6 +43,9 @@ http_method http_method_fromstring(const char* method) { http_request_line *http_request_line_new(http_method method, const char* other) { http_request_line *req = calloc(1, sizeof(http_request_line)); + if (req == NULL) { + fatal("calloc failed"); + } req->method = method; if (req->method == METHOD_OTHER) { req->method_other = calloc(strlen(other)+1, sizeof(char)); @@ -59,6 +63,9 @@ void http_request_line_delete(http_request_line *req) { http_response_line *http_response_line_new(uint16_t code) { http_response_line *resp = calloc(1, sizeof(http_response_line)); + if (resp == NULL) { + fatal("calloc failed"); + } resp->code = code; resp->version = HTTP11; return resp; @@ -117,7 +124,9 @@ void http_reponse_line_delete(http_response_line *resp) { http_header *http_header_new(const char* name) { http_header *header = calloc(1, sizeof(http_header)); - + if (header == NULL) { + fatal("calloc failed"); + } header->name = calloc(strlen(name)+1, sizeof(char)); strcpy(header->name, name); @@ -126,10 +135,16 @@ http_header *http_header_new(const char* name) { void http_header_append_content(http_header *header, const char* content) { if (header->content == NULL) { header->content = calloc(strlen(content)+1, sizeof(char)); + if (header->content == NULL) { + fatal("calloc failed"); + } strcpy(header->content, content); } else { uint32_t newlen = strlen(header->content) + strlen(content) + 1; header->content = realloc(header->content, newlen); + if (header->content == NULL) { + fatal("calloc failed"); + } strcat(header->content, content); } } @@ -141,13 +156,20 @@ void http_header_delete(http_header *header) { http_request *http_request_new() { http_request *req = calloc(1, sizeof(http_request)); + if (req == NULL) { + fatal("calloc failed"); + } req->header_count = 0; req->body = NULL; + req->parsestatus = PARSE_REQUESTLINE; return req; } void http_request_add_header(http_request *req, http_header *header) { req->header_count++; req->headers = realloc(req->headers, req->header_count * sizeof(http_header*)); + if (req->headers == NULL) { + fatal("calloc failed"); + } req->headers[req->header_count-1] = header; } void http_request_apppend_body(http_request *req, const char* body) { @@ -157,6 +179,9 @@ void http_request_apppend_body(http_request *req, const char* body) { } bodylen += strlen(body) + 1; req->body = realloc(req->body, bodylen * sizeof(char)); + if (req->body == NULL) { + fatal("calloc failed"); + } strcat(req->body, body); } void http_request_delete(http_request *req) { diff --git a/src/http/http.h b/src/http/http.h index 1ca2ec7..9fef224 100644 --- a/src/http/http.h +++ b/src/http/http.h @@ -13,7 +13,6 @@ extern "C" { #endif #include -#include "request.h" typedef enum http_method { METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, @@ -43,13 +42,19 @@ extern "C" { char* content; } http_header; + typedef enum http_request_parsestatus { + PARSE_REQUESTLINE, PARSE_HEADERS, PARSE_BODY, PARSE_DONE, PARSE_FAIL + } http_request_parsestatus; + typedef struct http_request { http_request_line *req; + http_request_parsestatus parsestatus; http_header **headers; uint32_t header_count; char *body; } http_request; + char* http_method_getstring(http_method method, char* method_other); http_method http_method_fromstring(const char* method); diff --git a/src/http/request.c b/src/http/request.c index aded04b..45ed0ad 100644 --- a/src/http/request.c +++ b/src/http/request.c @@ -1,6 +1,66 @@ #include #include #include +#include +#include "../main.h" #include "http.h" - +char* parse_request(http_request *req, char *input) { + size_t line_count; + char** lines = str_splitlines(input, &line_count); + + 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) { + req->parsestatus = PARSE_FAIL; + break; + } + + http_method method = http_method_fromstring(methodStr); + if (method == METHOD_INVALID) { + req->parsestatus = PARSE_FAIL; + break; + } + + http_version version; + if (strcasecmp(versionStr, "HTTP/1.0") == 0) { version = HTTP10; } + if (strcasecmp(versionStr, "HTTP/1.1") == 0) { version = HTTP11; } + + 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; + + 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 NULL; +} \ No newline at end of file diff --git a/src/http/request.h b/src/http/request.h index bde8df1..79dcb5c 100644 --- a/src/http/request.h +++ b/src/http/request.h @@ -12,9 +12,10 @@ extern "C" { #endif +#include "../ut/utstring.h" #include "http.h" - + char* parse_request(http_request *req, char *input); #ifdef __cplusplus diff --git a/src/main.c b/src/main.c index 26f0e13..c0e3456 100644 --- a/src/main.c +++ b/src/main.c @@ -12,16 +12,26 @@ #include #include "ut/utlist.h" +#include "ut/utarray.h" #include "main.h" #include "socket.h" +#include "http/http.h" +#include "http/request.h" int serverfd = 0; +char* teststr = "GET /testing/123 HTTP/1.1\r\n"; /* * */ int main(int argc, char** argv) { + /*char *test = calloc(strlen(teststr)+1, sizeof(char)); + strcpy(test, teststr); + http_request *req = http_request_new(); + parse_request(req, test); + + return 0;*/ skt_elem *connections = NULL; serverfd = svr_create(); @@ -38,6 +48,7 @@ int main(int argc, char** argv) { if (info != NULL) { skt_elem* newconn = calloc(1, sizeof(skt_elem)); newconn->info = info; + newconn->current_request = http_request_new(); LL_APPEND(connections, newconn); } } @@ -90,6 +101,9 @@ int main(int argc, char** argv) { 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); } } @@ -124,4 +138,46 @@ void info(char* msg, ...) { vfprintf(stdout, msg, va); fputc('\n', stdout); va_end(va); +} + +char** str_splitlines(char *str, size_t *line_count) { + char **result; + *line_count = 0; + char *tmp = str; + + while(*tmp) { + if (*tmp == '\n') { + (*line_count)++; + } + tmp++; + } + if (*line_count == 0) { + result = calloc(1, sizeof(char*)); + result[0] = calloc(strlen(str), sizeof(char)); + strcpy(result[0], str); + return result; + } + result = calloc(*line_count, sizeof(char*)); + if (result == NULL) { + fatal("calloc failed"); + } + + size_t i=0, linelen = 0; + char *line = strtok(str, "\n"); + while(line) { + linelen = strlen(line); + result[i] = calloc(linelen+1, sizeof(char)); + if (result[i] == NULL) { + fatal("calloc failed"); + } + strcpy(result[i], line); + if (result[i][linelen-1] == '\r') { + result[i][linelen-1] = '\0'; + result[i] = realloc(result[i], linelen); + } + line = strtok(NULL, "\n"); + i++; + } + + return result; } \ No newline at end of file diff --git a/src/main.h b/src/main.h index f5146a4..2299e58 100644 --- a/src/main.h +++ b/src/main.h @@ -20,6 +20,8 @@ void fatal(char* msg); void warning(char* msg, bool showPError); void info(char* msg, ...); +char** str_splitlines(char *str, size_t *line_count); + #ifdef __cplusplus } diff --git a/src/socket.h b/src/socket.h index e6cfb4b..f161c65 100644 --- a/src/socket.h +++ b/src/socket.h @@ -17,8 +17,9 @@ extern "C" { #include #include #include +#include "http/http.h" #include "ut/utstring.h" - + typedef struct skt_info skt_info; struct skt_info { @@ -36,6 +37,7 @@ extern "C" { typedef struct skt_elem { skt_info* info; + http_request *current_request; struct skt_elem *next; } skt_elem; diff --git a/src/ut/utarray.h b/src/ut/utarray.h index dcddd72..a6f70dd 100644 --- a/src/ut/utarray.h +++ b/src/ut/utarray.h @@ -218,7 +218,12 @@ typedef struct { /* last we pre-define a few icd for common utarrays of ints and strings */ static void utarray_str_cpy(void *dst, const void *src) { char **_src = (char**)src, **_dst = (char**)dst; - *_dst = (*_src == NULL) ? NULL : strdup(*_src); + if (*_src != NULL) { + *_dst = calloc(strlen(*_src)+1, sizeof(char)); + if (*_dst != NULL) { + strcpy(*_dst, *_src); + } + } } static void utarray_str_dtor(void *elt) { char **eltc = (char**)elt;