Initial commit
commit
fa0361344c
@ -0,0 +1,159 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <strings.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
const char * http_version_str = "HTTP/1.1 ";
|
||||||
|
|
||||||
|
typedef struct http_header {
|
||||||
|
uint8_t * status_code_ptr;
|
||||||
|
size_t status_code_len;
|
||||||
|
|
||||||
|
size_t num_headers;
|
||||||
|
uint8_t ** header_key_ptrs;
|
||||||
|
size_t * header_key_lens;
|
||||||
|
uint8_t ** header_val_ptrs;
|
||||||
|
size_t * header_val_lens;
|
||||||
|
|
||||||
|
uint8_t * body_ptr;
|
||||||
|
size_t body_len;
|
||||||
|
} http_header_t;
|
||||||
|
|
||||||
|
http_header_t * parse_header(uint8_t * data, size_t len) {
|
||||||
|
http_header_t * ret = malloc(sizeof(http_header_t));
|
||||||
|
|
||||||
|
// Parse version
|
||||||
|
if(len < strlen(http_version_str)) {
|
||||||
|
fprintf(stderr, "Data shorter than version string\n");
|
||||||
|
return 0;
|
||||||
|
} else if(strncmp((const char *)data, http_version_str, strlen(http_version_str)) != 0) {
|
||||||
|
fprintf(stderr, "http_version_str did not match\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t ptr = strlen(http_version_str);
|
||||||
|
|
||||||
|
// Prase status code
|
||||||
|
size_t status_code_start = ptr;
|
||||||
|
size_t status_code_end = 0;
|
||||||
|
while(ptr < len-1) {
|
||||||
|
if((data[ptr] == '\r') && (data[ptr+1] == '\n')) {
|
||||||
|
status_code_end = ptr;
|
||||||
|
ptr += 2;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ptr >= (len-1)) {
|
||||||
|
fprintf(stderr, "Reached EOF while parsing status code\n");
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
ret->status_code_ptr = data + status_code_start;
|
||||||
|
ret->status_code_len = status_code_end - status_code_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ptr < len-1) {
|
||||||
|
if((data[ptr] == '\r') && (data[ptr+1] == '\n')) {
|
||||||
|
ret->num_headers = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse header
|
||||||
|
size_t num_headers = 0;
|
||||||
|
uint8_t * header_key_ptrs[1024];
|
||||||
|
uint8_t * header_val_ptrs[1024];
|
||||||
|
size_t header_key_lens[1024];
|
||||||
|
size_t header_val_lens[1024];
|
||||||
|
while(ptr < len-1) {
|
||||||
|
size_t key_start = ptr;
|
||||||
|
size_t key_len = 0;
|
||||||
|
while(ptr < len-1) {
|
||||||
|
if(data[ptr] == ':') {
|
||||||
|
key_len = ptr - key_start;
|
||||||
|
ptr += 1;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ptr >= len-1) {
|
||||||
|
fprintf(stderr, "Reached EOF reading header key\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t val_start = ptr;
|
||||||
|
size_t val_len = 0;
|
||||||
|
while(ptr < len-1) {
|
||||||
|
if((data[ptr] == '\r') && (data[ptr+1] == '\n')) {
|
||||||
|
val_len = ptr - val_start;
|
||||||
|
ptr += 2;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
ptr += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ptr >= len-1) {
|
||||||
|
fprintf(stderr, "Reached EOF reading header val\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
header_key_ptrs[num_headers] = &data[key_start];
|
||||||
|
header_key_lens[num_headers] = key_len;
|
||||||
|
header_val_ptrs[num_headers] = &data[val_start];
|
||||||
|
header_val_lens[num_headers] = val_len;
|
||||||
|
|
||||||
|
num_headers += 1;
|
||||||
|
|
||||||
|
if(ptr < len-1) {
|
||||||
|
if((data[ptr] == '\r') && (data[ptr+1] == '\n')) {
|
||||||
|
ptr += 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->num_headers = num_headers;
|
||||||
|
|
||||||
|
ret->header_key_ptrs = malloc(sizeof(uint8_t*)*num_headers);
|
||||||
|
ret->header_key_lens = malloc(sizeof(size_t)*num_headers);
|
||||||
|
|
||||||
|
ret->header_val_ptrs = malloc(sizeof(uint8_t*)*num_headers);
|
||||||
|
ret->header_val_lens = malloc(sizeof(size_t)*num_headers);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < num_headers; i++) {
|
||||||
|
ret->header_key_ptrs[i] = header_key_ptrs[i];
|
||||||
|
ret->header_key_lens[i] = header_key_lens[i];
|
||||||
|
|
||||||
|
ret->header_val_ptrs[i] = header_val_ptrs[i];
|
||||||
|
ret->header_val_lens[i] = header_val_lens[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
ret->body_ptr = data + ptr;
|
||||||
|
ret->body_len = len - ptr;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char ** argv) {
|
||||||
|
if(argc < 2) {
|
||||||
|
printf("Data to parse required as input\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
http_header_t * header = parse_header((uint8_t*)argv[1], strlen(argv[1]));
|
||||||
|
if(header == 0) {
|
||||||
|
fprintf(stderr, "no header returned from parse\n");
|
||||||
|
} else {
|
||||||
|
printf("Parsed header with code %.*s and %d headers\n", header->status_code_len, header->status_code_ptr, header->num_headers);
|
||||||
|
for(size_t i = 0; i < header->num_headers; i++) {
|
||||||
|
printf("Header %ld: %.*s - %.*s\n", i,header->header_key_lens[i], header->header_key_ptrs[i], header->header_val_lens[i], header->header_val_ptrs[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue