From f427773223ef0bf270c7a59cc85a9e0c22f56a05 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 11 Mar 2019 15:27:14 -0400 Subject: [PATCH 01/11] initial commit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8fd528143..a2e9a1f3f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# A Simple Web Server in C +# A Simple Web Server in C - In this project, we'll finish the implementation of a web server in C. From 639cf72f0c7bdc3660a223504e5509b61237bcc1 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 11 Mar 2019 16:41:34 -0400 Subject: [PATCH 02/11] send_response implemented --- src/server.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index ea43306fc..4f6994ada 100644 --- a/src/server.c +++ b/src/server.c @@ -58,6 +58,9 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont /////////////////// // IMPLEMENT ME! // /////////////////// + sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%s", header, content_type, content_length, body); + + int response_length = strlen(header) + content_length; // Send it all! int rv = send(fd, response, response_length, 0); @@ -153,11 +156,10 @@ void handle_http_request(int fd, struct cache *cache) return; } - + resp_404(fd); /////////////////// // IMPLEMENT ME! // /////////////////// - // Read the three components of the first request line // If GET, handle the get endpoints @@ -193,7 +195,7 @@ int main(void) // This is the main loop that accepts incoming connections and // forks a handler process to take care of it. The main parent // process then goes back to waiting for new connections. - + while(1) { socklen_t sin_size = sizeof their_addr; @@ -213,7 +215,6 @@ int main(void) // newfd is a new socket descriptor for the new connection. // listenfd is still listening for new connections. - handle_http_request(newfd, cache); close(newfd); From 311a4971287c20e86b96a0c2752864a93e606858 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Mon, 11 Mar 2019 17:41:33 -0400 Subject: [PATCH 03/11] handle_http_request and get_d20 implemented --- src/server.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/server.c b/src/server.c index 4f6994ada..53d638f82 100644 --- a/src/server.c +++ b/src/server.c @@ -58,7 +58,7 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont /////////////////// // IMPLEMENT ME! // /////////////////// - sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%s", header, content_type, content_length, body); + sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%p", header, content_type, content_length, body); int response_length = strlen(header) + content_length; @@ -83,8 +83,10 @@ void get_d20(int fd) /////////////////// // IMPLEMENT ME! // /////////////////// - + int *roll; + roll = (rand() % 20) + 1; // Use send_response() to send it back as text/plain data + send_response(fd, "HTTP/1.1 200 OK", "text/plain", roll, sizeof(roll)); /////////////////// // IMPLEMENT ME! // @@ -147,6 +149,8 @@ void handle_http_request(int fd, struct cache *cache) { const int request_buffer_size = 65536; // 64K char request[request_buffer_size]; + char *handle; + char *endpoint; // Read request int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0); @@ -156,11 +160,21 @@ void handle_http_request(int fd, struct cache *cache) return; } - resp_404(fd); /////////////////// // IMPLEMENT ME! // /////////////////// // Read the three components of the first request line + sscanf(request, "%s %s", handle, endpoint); + + if(strcmp(handle, "GET") == 0) { + if(strcmp(endpoint, "/d20") == 0) { + get_d20(fd); + } else { + get_file(fd, cache, endpoint); + } + } else { + resp_404(fd); + } // If GET, handle the get endpoints From 6719ace7cbff17ee7cbfc4431542ffc95996d9a3 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 12 Mar 2019 16:56:43 -0400 Subject: [PATCH 04/11] working on handling files --- src/server.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/server.c b/src/server.c index 53d638f82..6f8f6ac0f 100644 --- a/src/server.c +++ b/src/server.c @@ -58,7 +58,7 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont /////////////////// // IMPLEMENT ME! // /////////////////// - sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%p", header, content_type, content_length, body); + sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%s", header, content_type, content_length, body); int response_length = strlen(header) + content_length; @@ -76,6 +76,7 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont /** * Send a /d20 endpoint response */ +/* void get_d20(int fd) { // Generate a random number between 1 and 20 inclusive @@ -92,6 +93,7 @@ void get_d20(int fd) // IMPLEMENT ME! // /////////////////// } +*/ /** * Send a 404 response @@ -127,6 +129,23 @@ void get_file(int fd, struct cache *cache, char *request_path) /////////////////// // IMPLEMENT ME! // /////////////////// + char filepath[4096]; + struct file_data *filedata; + char *mime_type; + + snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); + + filedata = file_load(filepath); + + mime_type = mime_type_get(filepath); + + if(filedata == NULL) { + fprintf(stderr, "%s", request_path); + } else { + send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + } + + //file_free(filedata); } /** @@ -149,7 +168,7 @@ void handle_http_request(int fd, struct cache *cache) { const int request_buffer_size = 65536; // 64K char request[request_buffer_size]; - char *handle; + char *action; char *endpoint; // Read request @@ -160,21 +179,16 @@ void handle_http_request(int fd, struct cache *cache) return; } + (void)cache; + /////////////////// // IMPLEMENT ME! // /////////////////// // Read the three components of the first request line - sscanf(request, "%s %s", handle, endpoint); + sscanf(request, "%s %s", action, endpoint); - if(strcmp(handle, "GET") == 0) { - if(strcmp(endpoint, "/d20") == 0) { - get_d20(fd); - } else { - get_file(fd, cache, endpoint); - } - } else { - resp_404(fd); - } + + get_file(fd, cache, endpoint); // If GET, handle the get endpoints From a721805683dfb5dd802b29db59cfad51774772f2 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Tue, 12 Mar 2019 17:14:16 -0400 Subject: [PATCH 05/11] fixed mem management bug for arbitrary file serving --- src/server.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index 6f8f6ac0f..43b2fa05b 100644 --- a/src/server.c +++ b/src/server.c @@ -140,12 +140,12 @@ void get_file(int fd, struct cache *cache, char *request_path) mime_type = mime_type_get(filepath); if(filedata == NULL) { - fprintf(stderr, "%s", request_path); + resp_404(fd); } else { send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + file_free(filedata); } - //file_free(filedata); } /** @@ -168,8 +168,8 @@ void handle_http_request(int fd, struct cache *cache) { const int request_buffer_size = 65536; // 64K char request[request_buffer_size]; - char *action; - char *endpoint; + char action[100]; + char endpoint[100]; // Read request int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0); From 3c4f7fea70116e30d9e9d1c2dbf8becff8d55a40 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 13 Mar 2019 16:41:31 -0400 Subject: [PATCH 06/11] working on allocating cache and cache entry memory --- src/cache.c | 23 +++++++++++++++++++++++ src/server.c | 2 +- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/cache.c b/src/cache.c index c72975cdd..1b75a0fc5 100644 --- a/src/cache.c +++ b/src/cache.c @@ -12,6 +12,16 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i /////////////////// // IMPLEMENT ME! // /////////////////// + struct cache_entry *entry = malloc(sizeof(struct cache_entry)); + entry->path = strdup(path); + entry->content_type = strdup(content_type); + + //double check use of strdup here + entry->content = content; + entry->content_length = content_length; + + return entry; + } /** @@ -22,6 +32,13 @@ void free_entry(struct cache_entry *entry) /////////////////// // IMPLEMENT ME! // /////////////////// + if (entry != NULL) { + free(entry->path); + free(entry->content_type); + free(entry->content); + free(entry->content_length); + free(entry); + } } /** @@ -94,6 +111,12 @@ struct cache *cache_create(int max_size, int hashsize) /////////////////// // IMPLEMENT ME! // /////////////////// + struct cache *cache = malloc(sizeof(struct cache)); + + cache->max_size = max_size; + cache->cur_size = hashsize; + + } void cache_free(struct cache *cache) diff --git a/src/server.c b/src/server.c index 43b2fa05b..7ba1c6b00 100644 --- a/src/server.c +++ b/src/server.c @@ -58,7 +58,7 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont /////////////////// // IMPLEMENT ME! // /////////////////// - sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%s", header, content_type, content_length, body); + sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%p", header, content_type, content_length, body); int response_length = strlen(header) + content_length; From 2f6b9315a58248436aab7180c8123b41c9f86ae7 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 13 Mar 2019 17:57:36 -0400 Subject: [PATCH 07/11] fixed cache mem allocation and serving images --- src/cache.c | 15 +++++++++++---- src/server.c | 8 +++++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/src/cache.c b/src/cache.c index 1b75a0fc5..06de6c7a5 100644 --- a/src/cache.c +++ b/src/cache.c @@ -12,12 +12,15 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i /////////////////// // IMPLEMENT ME! // /////////////////// + char *content_str = (char *) content; + + struct cache_entry *entry = malloc(sizeof(struct cache_entry)); entry->path = strdup(path); entry->content_type = strdup(content_type); //double check use of strdup here - entry->content = content; + entry->content = strdup(content_str); entry->content_length = content_length; return entry; @@ -36,7 +39,6 @@ void free_entry(struct cache_entry *entry) free(entry->path); free(entry->content_type); free(entry->content); - free(entry->content_length); free(entry); } } @@ -114,9 +116,13 @@ struct cache *cache_create(int max_size, int hashsize) struct cache *cache = malloc(sizeof(struct cache)); cache->max_size = max_size; - cache->cur_size = hashsize; + cache->cur_size = 0; + + cache->index = hashtable_create(hashsize, NULL); + cache->head = NULL; + cache->tail = NULL; - + return cache; } void cache_free(struct cache *cache) @@ -148,6 +154,7 @@ void cache_put(struct cache *cache, char *path, char *content_type, void *conten /////////////////// // IMPLEMENT ME! // /////////////////// + alloc_entry(path, content_type, content, content_length); } /** diff --git a/src/server.c b/src/server.c index 7ba1c6b00..d3c96513c 100644 --- a/src/server.c +++ b/src/server.c @@ -53,17 +53,19 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont const int max_response_size = 262144; char response[max_response_size]; + printf("Sending Response\n"); // Build HTTP response and store it in response /////////////////// // IMPLEMENT ME! // /////////////////// - sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n%p", header, content_type, content_length, body); + int response_length = sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n", header, content_type, content_length); - int response_length = strlen(header) + content_length; + memcpy(response+response_length, body, content_length); + printf("Response Length:%d", response_length); // Send it all! - int rv = send(fd, response, response_length, 0); + int rv = send(fd, response, response_length+content_length, 0); if (rv < 0) { perror("send"); From 9076f1b2b288d05615ca9293c5040e95a94d225a Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 13 Mar 2019 18:47:52 -0400 Subject: [PATCH 08/11] working on adding and removing from cache --- src/cache.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/cache.c b/src/cache.c index 06de6c7a5..56a28d837 100644 --- a/src/cache.c +++ b/src/cache.c @@ -9,9 +9,6 @@ */ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, int content_length) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// char *content_str = (char *) content; @@ -32,9 +29,6 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i */ void free_entry(struct cache_entry *entry) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// if (entry != NULL) { free(entry->path); free(entry->content_type); @@ -110,9 +104,6 @@ struct cache_entry *dllist_remove_tail(struct cache *cache) */ struct cache *cache_create(int max_size, int hashsize) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// struct cache *cache = malloc(sizeof(struct cache)); cache->max_size = max_size; @@ -151,10 +142,16 @@ void cache_free(struct cache *cache) */ void cache_put(struct cache *cache, char *path, char *content_type, void *content, int content_length) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// - alloc_entry(path, content_type, content, content_length); + struct cache_entry *entry = alloc_entry(path, content_type, content, content_length); + dllist_insert_head(cache, entry); + hashtable_put(cache->index, path, entry); + cache->cur_size++; + + if (cache->cur_size > cache->max_size) { + struct cache_entry *oldtail = dllist_remove_tail(cache); + hashtable_delete(cache->index, path); + free_entry(oldtail); + } } /** @@ -162,7 +159,12 @@ void cache_put(struct cache *cache, char *path, char *content_type, void *conten */ struct cache_entry *cache_get(struct cache *cache, char *path) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// + struct cache_entry *entry = hashtable_get(cache->index, path); + + if (entry != NULL) { + dllist_move_to_head(cache, entry); + return cache->head; + } else { + return NULL; + } } From 9d3770cb2f852e9597b0f39ec51ff45ab54c3f83 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Wed, 13 Mar 2019 19:48:22 -0400 Subject: [PATCH 09/11] fixed cache_put --- src/cache.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/cache.c b/src/cache.c index 56a28d837..bceee61a0 100644 --- a/src/cache.c +++ b/src/cache.c @@ -142,16 +142,18 @@ void cache_free(struct cache *cache) */ void cache_put(struct cache *cache, char *path, char *content_type, void *content, int content_length) { + struct cache_entry *entry = alloc_entry(path, content_type, content, content_length); dllist_insert_head(cache, entry); hashtable_put(cache->index, path, entry); cache->cur_size++; - - if (cache->cur_size > cache->max_size) { + + if ((cache->cur_size) > cache->max_size) { struct cache_entry *oldtail = dllist_remove_tail(cache); - hashtable_delete(cache->index, path); + hashtable_delete(cache->index, oldtail->path); free_entry(oldtail); - } + } + } /** From edc4a5fe7fbc3b89e42e6fdda658b8787e0dbdef Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Thu, 14 Mar 2019 15:21:47 -0400 Subject: [PATCH 10/11] working on serving files from cache --- src/cache.c | 2 +- src/server.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/cache.c b/src/cache.c index bceee61a0..bcebf96d7 100644 --- a/src/cache.c +++ b/src/cache.c @@ -13,10 +13,10 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i struct cache_entry *entry = malloc(sizeof(struct cache_entry)); + entry->path = strdup(path); entry->content_type = strdup(content_type); - //double check use of strdup here entry->content = strdup(content_str); entry->content_length = content_length; diff --git a/src/server.c b/src/server.c index d3c96513c..f1616e072 100644 --- a/src/server.c +++ b/src/server.c @@ -53,17 +53,11 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont const int max_response_size = 262144; char response[max_response_size]; - printf("Sending Response\n"); // Build HTTP response and store it in response - - /////////////////// - // IMPLEMENT ME! // - /////////////////// int response_length = sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n", header, content_type, content_length); memcpy(response+response_length, body, content_length); - printf("Response Length:%d", response_length); // Send it all! int rv = send(fd, response, response_length+content_length, 0); @@ -137,15 +131,35 @@ void get_file(int fd, struct cache *cache, char *request_path) snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); - filedata = file_load(filepath); + //filedata = file_load(filepath); mime_type = mime_type_get(filepath); - if(filedata == NULL) { - resp_404(fd); + if( cache_get(cache, filepath) != NULL ) { + + printf("Found file in cache!\n"); + + struct cache_entry *entry = cache_get(cache, filepath); + + send_response(fd, "HTTP/1.1 200 OK", entry->content_type, entry->content, entry->content_length); + } else { - send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); - file_free(filedata); + + printf("loading file from disk\n"); + + filedata = file_load(filepath); + + if(filedata == NULL) { + resp_404(fd); + } else { + + printf("storing file in cache\n"); + + cache_put(cache, filepath, mime_type, filedata->data, filedata->size); + send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + file_free(filedata); + } + } } From 2bf99d5b3c7fce6863273de2adf3c63f41bd7354 Mon Sep 17 00:00:00 2001 From: Scott Bren Date: Thu, 14 Mar 2019 16:41:04 -0400 Subject: [PATCH 11/11] added serving files from the cache --- src/server.c | 33 +++++++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index f1616e072..845d1a227 100644 --- a/src/server.c +++ b/src/server.c @@ -133,9 +133,9 @@ void get_file(int fd, struct cache *cache, char *request_path) //filedata = file_load(filepath); - mime_type = mime_type_get(filepath); + //mime_type = mime_type_get(filepath); - if( cache_get(cache, filepath) != NULL ) { +/* if( cache_get(cache, filepath) != NULL ) { printf("Found file in cache!\n"); @@ -160,6 +160,33 @@ void get_file(int fd, struct cache *cache, char *request_path) file_free(filedata); } + } */ + + //struct cache_entry *entry = cache_get(cache, filepath); + + if ( cache_get(cache, request_path) == NULL ) { + + printf("loading file from disk\n"); + + filedata = file_load(filepath); + + mime_type = mime_type_get(filepath); + + if(filedata == NULL) { + resp_404(fd); + } else { + printf("storing file in cache\n"); + cache_put(cache, request_path, mime_type, filedata->data, filedata->size); + send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + file_free(filedata); + } + + } else { + + printf("Found file in cache!\n"); + struct cache_entry *entry = cache_get(cache, request_path); + send_response(fd, "HTTP/1.1 200 OK", entry->content_type, entry->content, entry->content_length); + } } @@ -195,8 +222,6 @@ void handle_http_request(int fd, struct cache *cache) return; } - (void)cache; - /////////////////// // IMPLEMENT ME! // ///////////////////