From fa0361344ce4a23569216633385c1af4c9cf8fb7 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Fri, 5 Jan 2024 15:48:13 -0700 Subject: [PATCH] Initial commit --- Makefile | 2 + main.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 Makefile create mode 100644 main.c diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..d698de6 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +main: main.c + gcc -o main main.c diff --git a/main.c b/main.c new file mode 100644 index 0000000..e2adaa5 --- /dev/null +++ b/main.c @@ -0,0 +1,159 @@ +#include +#include +#include +#include + +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; +}