From b809ef430ede600091f79908ea52597d2271f957 Mon Sep 17 00:00:00 2001 From: Santo Cariotti Date: Fri, 22 Oct 2021 20:44:24 +0200 Subject: parse the request --- Year_3/TSDWL/webserver/server.c | 102 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 5 deletions(-) diff --git a/Year_3/TSDWL/webserver/server.c b/Year_3/TSDWL/webserver/server.c index 9bf1f7d..e2f6a3e 100644 --- a/Year_3/TSDWL/webserver/server.c +++ b/Year_3/TSDWL/webserver/server.c @@ -1,3 +1,7 @@ +/* An example of the work of this file is showed at [1] + * + * [1] https://it.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Richiesta_GET_e_risposta_di_successo + */ #include #include #include @@ -8,6 +12,33 @@ #define DEFAULT_WWW "./www" +typedef enum { + GET, + /* TODO: types below */ + HEAD, + OPTIONS, + POST, + PUT, + PATCH, + DELETE +} methods; + +typedef enum { + /* Some of the HTTP versions defined at [1] + * + * [1] https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#History + */ + HTTP1, /* HTTP/1.0 */ + HTTP1_1, /* HTTP/1.1 */ + HTTP2, /* HTTP/2 */ +} http_t; + +typedef struct { + methods method; + char path[256]; /* FIXME: handle path with more than 256 chars */ + http_t http_version; +} request_t; + /* TODO: Make the parsing of headers */ void read_headers(int* fd, char** headers, int* headers_num) @@ -30,7 +61,7 @@ read_headers(int* fd, char** headers, int* headers_num) exit(1); } - *(buffer + i) = ch; + buffer[i] = ch; if (ch == '\n' && (i < 1 || buffer[i - 1] == '\r')) { break; } @@ -38,12 +69,12 @@ read_headers(int* fd, char** headers, int* headers_num) i++; } - buffer[i + 1] = '\0'; + buffer[i - 1] = '\0'; if (i < 2) { break; } - memcpy(headers[*headers_num], buffer, i + 1); + memcpy(headers[*headers_num], buffer, i); (*headers_num)++; } } @@ -57,6 +88,60 @@ get_client_ip(int fd, char* buffer) strcpy(buffer, inet_ntoa(addr.sin_addr)); } +int +parse_first_line(request_t* request, char* header, size_t len) +{ + char* token; + int i; + + i = 0; + token = strtok(header, " "); + do { + switch (i) { + case 0: { + if (strcmp(token, "GET") == 0) { + request->method = GET; + } else { + fprintf(stderr, "'%s' method not supported\n", token); + goto parse_error; + } + /* TODO: Handle the other HTTP methods */ + break; + } + case 1: { + strcpy(request->path, token); + break; + } + case 2: { + if (strcmp(token, "HTTP/1.0") == 0) { + request->http_version = HTTP1; + } else if (strcmp(token, "HTTP/1.1") == 0) { + request->http_version = HTTP1_1; + } else if (strcmp(token, "HTTP/2") == 0) { + request->http_version = HTTP2; + } else { + fprintf(stderr, "'%s' version not supported\n", token); + goto parse_error; + } + break; + } + /* If it comes here, it means that the header have more than 3 tokens */ + default: { + fprintf(stderr, "Header does not have a valid syntax\n"); + goto parse_error; + } + } + + i++; + token = strtok(NULL, " "); + } while (token != NULL); + + return 0; + +parse_error: + return -1; +} + int main(int argc, char* argv[]) { @@ -68,6 +153,8 @@ main(int argc, char* argv[]) struct sockaddr_in address; char client_ip[20]; socklen_t address_len; + char* buffer; + request_t request; if (argc < 2) { fprintf(stderr, "Usage: %s [root_path]", argv[0]); @@ -111,11 +198,16 @@ main(int argc, char* argv[]) read_headers(&clientfd, headers, &headers_num); + if (headers_num == 0) { + buffer = "You must specify almost one header\n"; + write(clientfd, buffer, strlen(buffer) + 1); + } + + parse_first_line(&request, headers[0], strlen(headers[0])); + for (i = 0; i < headers_num; ++i) { - printf("%s", headers[i]); free(headers + i); } - printf("[Connection closed]\n\n"); close(clientfd); } -- cgit v1.2.3-18-g5258