Work on request header parsing

This commit is contained in:
2014-07-18 23:40:15 +01:00
parent 6d3ca314d4
commit e56f8f3715
10 changed files with 165 additions and 7 deletions

Binary file not shown.

View File

@@ -13,6 +13,8 @@
<gdb_interceptlist> <gdb_interceptlist>
<gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/> <gdbinterceptoptions gdb_all="false" gdb_unhandled="true" gdb_unexpected="true"/>
</gdb_interceptlist> </gdb_interceptlist>
<gdb_signals>
</gdb_signals>
<gdb_options> <gdb_options>
<DebugOptions> <DebugOptions>
</DebugOptions> </DebugOptions>

View File

@@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include "http.h" #include "http.h"
#include "../main.h"
/* /*
* METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, * METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
@@ -32,7 +33,7 @@ http_method http_method_fromstring(const char* method) {
METHOD_CONNECT}; METHOD_CONNECT};
size_t count = sizeof(methods) / sizeof(http_method); 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) { if (strcmp(http_method_getstring(methods[i],NULL), method) == 0) {
return methods[i]; 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 *http_request_line_new(http_method method, const char* other) {
http_request_line *req = calloc(1, sizeof(http_request_line)); http_request_line *req = calloc(1, sizeof(http_request_line));
if (req == NULL) {
fatal("calloc failed");
}
req->method = method; req->method = method;
if (req->method == METHOD_OTHER) { if (req->method == METHOD_OTHER) {
req->method_other = calloc(strlen(other)+1, sizeof(char)); 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 *http_response_line_new(uint16_t code) {
http_response_line *resp = calloc(1, sizeof(http_response_line)); http_response_line *resp = calloc(1, sizeof(http_response_line));
if (resp == NULL) {
fatal("calloc failed");
}
resp->code = code; resp->code = code;
resp->version = HTTP11; resp->version = HTTP11;
return resp; 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 *http_header_new(const char* name) {
http_header *header = calloc(1, sizeof(http_header)); http_header *header = calloc(1, sizeof(http_header));
if (header == NULL) {
fatal("calloc failed");
}
header->name = calloc(strlen(name)+1, sizeof(char)); header->name = calloc(strlen(name)+1, sizeof(char));
strcpy(header->name, name); 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) { void http_header_append_content(http_header *header, const char* content) {
if (header->content == NULL) { if (header->content == NULL) {
header->content = calloc(strlen(content)+1, sizeof(char)); header->content = calloc(strlen(content)+1, sizeof(char));
if (header->content == NULL) {
fatal("calloc failed");
}
strcpy(header->content, content); strcpy(header->content, content);
} else { } else {
uint32_t newlen = strlen(header->content) + strlen(content) + 1; uint32_t newlen = strlen(header->content) + strlen(content) + 1;
header->content = realloc(header->content, newlen); header->content = realloc(header->content, newlen);
if (header->content == NULL) {
fatal("calloc failed");
}
strcat(header->content, content); strcat(header->content, content);
} }
} }
@@ -141,13 +156,20 @@ void http_header_delete(http_header *header) {
http_request *http_request_new() { http_request *http_request_new() {
http_request *req = calloc(1, sizeof(http_request)); http_request *req = calloc(1, sizeof(http_request));
if (req == NULL) {
fatal("calloc failed");
}
req->header_count = 0; req->header_count = 0;
req->body = NULL; req->body = NULL;
req->parsestatus = PARSE_REQUESTLINE;
return req; return req;
} }
void http_request_add_header(http_request *req, http_header *header) { void http_request_add_header(http_request *req, http_header *header) {
req->header_count++; req->header_count++;
req->headers = realloc(req->headers, req->header_count * sizeof(http_header*)); 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; req->headers[req->header_count-1] = header;
} }
void http_request_apppend_body(http_request *req, const char* body) { 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; bodylen += strlen(body) + 1;
req->body = realloc(req->body, bodylen * sizeof(char)); req->body = realloc(req->body, bodylen * sizeof(char));
if (req->body == NULL) {
fatal("calloc failed");
}
strcat(req->body, body); strcat(req->body, body);
} }
void http_request_delete(http_request *req) { void http_request_delete(http_request *req) {

View File

@@ -13,7 +13,6 @@ extern "C" {
#endif #endif
#include <stdint.h> #include <stdint.h>
#include "request.h"
typedef enum http_method { typedef enum http_method {
METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT, METHOD_GET, METHOD_POST, METHOD_HEAD, METHOD_PUT,
@@ -43,13 +42,19 @@ extern "C" {
char* content; char* content;
} http_header; } http_header;
typedef enum http_request_parsestatus {
PARSE_REQUESTLINE, PARSE_HEADERS, PARSE_BODY, PARSE_DONE, PARSE_FAIL
} http_request_parsestatus;
typedef struct http_request { typedef struct http_request {
http_request_line *req; http_request_line *req;
http_request_parsestatus parsestatus;
http_header **headers; http_header **headers;
uint32_t header_count; uint32_t header_count;
char *body; char *body;
} http_request; } http_request;
char* http_method_getstring(http_method method, char* method_other); char* http_method_getstring(http_method method, char* method_other);
http_method http_method_fromstring(const char* method); http_method http_method_fromstring(const char* method);

View File

@@ -1,6 +1,66 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <strings.h>
#include "../main.h"
#include "http.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;
}

View File

@@ -12,9 +12,10 @@
extern "C" { extern "C" {
#endif #endif
#include "../ut/utstring.h"
#include "http.h" #include "http.h"
char* parse_request(http_request *req, char *input);
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -12,16 +12,26 @@
#include <strings.h> #include <strings.h>
#include "ut/utlist.h" #include "ut/utlist.h"
#include "ut/utarray.h"
#include "main.h" #include "main.h"
#include "socket.h" #include "socket.h"
#include "http/http.h"
#include "http/request.h"
int serverfd = 0; int serverfd = 0;
char* teststr = "GET /testing/123 HTTP/1.1\r\n";
/* /*
* *
*/ */
int main(int argc, char** argv) { 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; skt_elem *connections = NULL;
serverfd = svr_create(); serverfd = svr_create();
@@ -38,6 +48,7 @@ int main(int argc, char** argv) {
if (info != NULL) { if (info != NULL) {
skt_elem* newconn = calloc(1, sizeof(skt_elem)); skt_elem* newconn = calloc(1, sizeof(skt_elem));
newconn->info = info; newconn->info = info;
newconn->current_request = http_request_new();
LL_APPEND(connections, newconn); LL_APPEND(connections, newconn);
} }
} }
@@ -90,6 +101,9 @@ int main(int argc, char** argv) {
if (elem->info->closed) { if (elem->info->closed) {
LL_DELETE(connections, elem); LL_DELETE(connections, elem);
skt_delete(elem->info); skt_delete(elem->info);
if (elem->current_request != NULL) {
http_request_delete(elem->current_request);
}
free(elem); free(elem);
} }
} }
@@ -125,3 +139,45 @@ void info(char* msg, ...) {
fputc('\n', stdout); fputc('\n', stdout);
va_end(va); 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;
}

View File

@@ -20,6 +20,8 @@ void fatal(char* msg);
void warning(char* msg, bool showPError); void warning(char* msg, bool showPError);
void info(char* msg, ...); void info(char* msg, ...);
char** str_splitlines(char *str, size_t *line_count);
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@@ -17,6 +17,7 @@ extern "C" {
#include <sys/socket.h> #include <sys/socket.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <time.h> #include <time.h>
#include "http/http.h"
#include "ut/utstring.h" #include "ut/utstring.h"
typedef struct skt_info skt_info; typedef struct skt_info skt_info;
@@ -36,6 +37,7 @@ extern "C" {
typedef struct skt_elem { typedef struct skt_elem {
skt_info* info; skt_info* info;
http_request *current_request;
struct skt_elem *next; struct skt_elem *next;
} skt_elem; } skt_elem;

View File

@@ -218,7 +218,12 @@ typedef struct {
/* last we pre-define a few icd for common utarrays of ints and strings */ /* last we pre-define a few icd for common utarrays of ints and strings */
static void utarray_str_cpy(void *dst, const void *src) { static void utarray_str_cpy(void *dst, const void *src) {
char **_src = (char**)src, **_dst = (char**)dst; 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) { static void utarray_str_dtor(void *elt) {
char **eltc = (char**)elt; char **eltc = (char**)elt;