From 57ca2f6aa25b49c062f5acbeca95ffce5b9b0dba Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Mon, 11 Mar 2019 16:49:32 -0400 Subject: [PATCH 1/7] send_response implemented --- src/server.c | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/server.c b/src/server.c index ea43306fc..d461441b5 100644 --- a/src/server.c +++ b/src/server.c @@ -34,7 +34,7 @@ #include "mime.h" #include "cache.h" -#define PORT "3490" // the port users will be connecting to +#define PORT "3490" // the port users will be connecting to #define SERVER_FILES "./serverfiles" #define SERVER_ROOT "./serverroot" @@ -52,31 +52,39 @@ 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]; - + int response_length = strlen(body); // Build HTTP response and store it in response /////////////////// // IMPLEMENT ME! // /////////////////// + sprintf(response, "%s\n" + "Content-Type: %s\n" + "Content-Length: %d\n" + "Connection: close\n" + "\n" + "%s", + header, content_type, response_length, body); + // Send it all! int rv = send(fd, response, response_length, 0); - if (rv < 0) { + if (rv < 0) + { perror("send"); } return rv; } - /** * Send a /d20 endpoint response */ void get_d20(int fd) { // Generate a random number between 1 and 20 inclusive - + /////////////////// // IMPLEMENT ME! // /////////////////// @@ -94,14 +102,15 @@ void get_d20(int fd) void resp_404(int fd) { char filepath[4096]; - struct file_data *filedata; + struct file_data *filedata; char *mime_type; // Fetch the 404.html file snprintf(filepath, sizeof filepath, "%s/404.html", SERVER_FILES); filedata = file_load(filepath); - if (filedata == NULL) { + if (filedata == NULL) + { // TODO: make this non-fatal fprintf(stderr, "cannot find system 404 file\n"); exit(3); @@ -148,12 +157,12 @@ void handle_http_request(int fd, struct cache *cache) // Read request int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0); - if (bytes_recvd < 0) { + if (bytes_recvd < 0) + { perror("recv"); return; } - /////////////////// // IMPLEMENT ME! // /////////////////// @@ -165,7 +174,6 @@ void handle_http_request(int fd, struct cache *cache) // Check if it's /d20 and handle that special case // Otherwise serve the requested file by calling get_file() - // (Stretch) If POST, handle the post request } @@ -174,7 +182,7 @@ void handle_http_request(int fd, struct cache *cache) */ int main(void) { - int newfd; // listen on sock_fd, new connection on newfd + int newfd; // listen on sock_fd, new connection on newfd struct sockaddr_storage their_addr; // connector's address information char s[INET6_ADDRSTRLEN]; @@ -183,7 +191,8 @@ int main(void) // Get a listening socket int listenfd = get_listener_socket(PORT); - if (listenfd < 0) { + if (listenfd < 0) + { fprintf(stderr, "webserver: fatal error getting listening socket\n"); exit(1); } @@ -193,24 +202,26 @@ 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) { + + while (1) + { socklen_t sin_size = sizeof their_addr; // Parent process will block on the accept() call until someone // makes a new connection: newfd = accept(listenfd, (struct sockaddr *)&their_addr, &sin_size); - if (newfd == -1) { + if (newfd == -1) + { perror("accept"); continue; } // Print out a message that we got the connection inet_ntop(their_addr.ss_family, - get_in_addr((struct sockaddr *)&their_addr), - s, sizeof s); + get_in_addr((struct sockaddr *)&their_addr), + s, sizeof s); printf("server: got connection from %s\n", s); - + // newfd is a new socket descriptor for the new connection. // listenfd is still listening for new connections. @@ -223,4 +234,3 @@ int main(void) return 0; } - From e4fc88a953195fda6675e33a0897b888dfbe2f06 Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Mon, 11 Mar 2019 18:48:11 -0400 Subject: [PATCH 2/7] implemented handle_http_request --- src/server.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/server.c b/src/server.c index d461441b5..d45cff673 100644 --- a/src/server.c +++ b/src/server.c @@ -153,6 +153,9 @@ void handle_http_request(int fd, struct cache *cache) { const int request_buffer_size = 65536; // 64K char request[request_buffer_size]; + char method[200]; + char path[8192]; + char req_body[1785]; // Read request int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0); @@ -168,10 +171,25 @@ void handle_http_request(int fd, struct cache *cache) /////////////////// // Read the three components of the first request line + sscanf(request, "%s %s %s", method, path, req_body); + printf("method: \"%s\"\n", method); + printf("path: \"%s\"\n", path); + printf("req \"%s\"\n", request); // If GET, handle the get endpoints + if (strcmp(method, "GET") == 0) + { + // Check if it's /d20 and handle that special case + if (strcmp(path, "GET") == 0) + { + get_d20(fd); + } + } + else + { + resp_404(fd); + } - // Check if it's /d20 and handle that special case // Otherwise serve the requested file by calling get_file() // (Stretch) If POST, handle the post request @@ -224,9 +242,8 @@ int main(void) // newfd is a new socket descriptor for the new connection. // listenfd is still listening for new connections. - + resp_404(newfd); handle_http_request(newfd, cache); - close(newfd); } From f2a858f2ead358ae9156991c83361c1c9a07b17d Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Tue, 12 Mar 2019 19:01:39 -0400 Subject: [PATCH 3/7] updated http request function and added get_file code --- src/server.c | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index d45cff673..6133d9c65 100644 --- a/src/server.c +++ b/src/server.c @@ -131,6 +131,33 @@ void get_file(int fd, struct cache *cache, char *request_path) /////////////////// // IMPLEMENT ME! // /////////////////// + char filepath[4096]; + struct file_data *filedata; + char *mime_type; + + // Fetch index.html + if (strcmp(request_path, "/") == 0 || strcmp(request_path, "/index.html") == 0) + { + snprintf(filepath, sizeof filepath, "%s/index.html", SERVER_ROOT); + } + else + { + snprintf(filepath, sizeof filepath, "%s/%s", SERVER_ROOT, request_path); + } + + filedata = file_load(filepath); + + if (filedata == NULL) + { + resp_404(fd); + return; + } + + mime_type = mime_type_get(filepath); + + send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + + file_free(filedata); } /** @@ -184,11 +211,12 @@ void handle_http_request(int fd, struct cache *cache) { get_d20(fd); } + else + { + get_file(fd, cache, path); + } } - else - { - resp_404(fd); - } + resp_404(fd); // Otherwise serve the requested file by calling get_file() From 9ba613ce1af431d1dc4a1523fceec83c75e20e54 Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Wed, 13 Mar 2019 19:05:08 -0400 Subject: [PATCH 4/7] added cache entry and cache put --- src/cache.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/cache.c b/src/cache.c index c72975cdd..657931fd1 100644 --- a/src/cache.c +++ b/src/cache.c @@ -12,6 +12,13 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i /////////////////// // IMPLEMENT ME! // /////////////////// + struct cache_entry *new_entry = malloc(sizeof(struct cache_entry)); + new_entry->path = path; + new_entry->content_type = content_type; + new_entry->content = content; + new_entry->content_length = content_length; + + return new_entry; } /** @@ -30,10 +37,13 @@ void free_entry(struct cache_entry *entry) void dllist_insert_head(struct cache *cache, struct cache_entry *ce) { // Insert at the head of the list - if (cache->head == NULL) { + if (cache->head == NULL) + { cache->head = cache->tail = ce; ce->prev = ce->next = NULL; - } else { + } + else + { cache->head->prev = ce; ce->next = cache->head; ce->prev = NULL; @@ -46,13 +56,16 @@ void dllist_insert_head(struct cache *cache, struct cache_entry *ce) */ void dllist_move_to_head(struct cache *cache, struct cache_entry *ce) { - if (ce != cache->head) { - if (ce == cache->tail) { + if (ce != cache->head) + { + if (ce == cache->tail) + { // We're the tail cache->tail = ce->prev; cache->tail->next = NULL; - - } else { + } + else + { // We're neither the head nor the tail ce->prev->next = ce->next; ce->next->prev = ce->prev; @@ -65,7 +78,6 @@ void dllist_move_to_head(struct cache *cache, struct cache_entry *ce) } } - /** * Removes the tail from the list and returns it * @@ -102,7 +114,8 @@ void cache_free(struct cache *cache) hashtable_destroy(cache->index); - while (cur_entry != NULL) { + while (cur_entry != NULL) + { struct cache_entry *next_entry = cur_entry->next; free_entry(cur_entry); @@ -125,6 +138,26 @@ void cache_put(struct cache *cache, char *path, char *content_type, void *conten /////////////////// // IMPLEMENT ME! // /////////////////// + + struct cache_entry *new_entry = alloc_entry(path, content_type, content, content_length); + + dllist_insert_head(cache, new_entry); + + hashtable_put(cache->index, path, new_entry); + + cache->cur_size += 1; + + if (cache->cur_size > cache->max_size) + { + + struct cache_entry *old_entry = dllist_remove_tail(cache); + hashtable_delete(cache->index, old_entry->path); + free_entry(old_entry); + if (cache->cur_size > cache->max_size) + { + cache->cur_size -= 1; + } + } } /** From fed61b8437397a18b427da53e2415dcdf6540454 Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Wed, 13 Mar 2019 19:10:42 -0400 Subject: [PATCH 5/7] updated get_file --- src/server.c | 89 +++++++++++++++++++++++++--------------------------- 1 file changed, 43 insertions(+), 46 deletions(-) diff --git a/src/server.c b/src/server.c index 6133d9c65..9b653f481 100644 --- a/src/server.c +++ b/src/server.c @@ -52,21 +52,21 @@ 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]; - int response_length = strlen(body); - // Build HTTP response and store it in response + // Build HTTP response and store it in response + int response_length = snprintf(response, max_response_size, + "%s\n" + "Connection: close \n" + // "Date : %s" + "Content-Length: %d\n" + "Content-Type: %s\n" + "\n", + header, content_length, content_type); /////////////////// // IMPLEMENT ME! // /////////////////// - - sprintf(response, "%s\n" - "Content-Type: %s\n" - "Content-Length: %d\n" - "Connection: close\n" - "\n" - "%s", - header, content_type, response_length, body); - + memcpy(response + response_length, body, content_length); + response_length += content_length; // Send it all! int rv = send(fd, response, response_length, 0); @@ -75,6 +75,12 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont perror("send"); } + // rv = send(fd, body, content_length, 0); + + // if (rv < 0) { + // perror("send"); + // } + return rv; } @@ -84,7 +90,7 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont void get_d20(int fd) { // Generate a random number between 1 and 20 inclusive - + (void)fd; /////////////////// // IMPLEMENT ME! // /////////////////// @@ -135,27 +141,19 @@ void get_file(int fd, struct cache *cache, char *request_path) struct file_data *filedata; char *mime_type; - // Fetch index.html - if (strcmp(request_path, "/") == 0 || strcmp(request_path, "/index.html") == 0) - { - snprintf(filepath, sizeof filepath, "%s/index.html", SERVER_ROOT); - } - else - { - snprintf(filepath, sizeof filepath, "%s/%s", SERVER_ROOT, request_path); - } - + snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); + printf("\"%s\"\n", filepath); filedata = file_load(filepath); if (filedata == NULL) { + // TODO: make this non-fatal resp_404(fd); - return; } mime_type = mime_type_get(filepath); - send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + send_response(fd, "HTTP/1.1 200 ok", mime_type, filedata->data, filedata->size); file_free(filedata); } @@ -171,6 +169,8 @@ char *find_start_of_body(char *header) /////////////////// // IMPLEMENT ME! // (Stretch) /////////////////// + (void)header; + return NULL; } /** @@ -180,9 +180,9 @@ void handle_http_request(int fd, struct cache *cache) { const int request_buffer_size = 65536; // 64K char request[request_buffer_size]; - char method[200]; + //similar to yesterday + char method[512]; //GET or POST char path[8192]; - char req_body[1785]; // Read request int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0); @@ -193,33 +193,29 @@ 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 %s", method, path, req_body); - printf("method: \"%s\"\n", method); - printf("path: \"%s\"\n", path); - printf("req \"%s\"\n", request); + sscanf(request, "%s %s", method, path); + printf("GOT REQUEST: \"%s\" \"%s\"\n", method, path); + //testing function. + // resp_404(fd); // If GET, handle the get endpoints - if (strcmp(method, "GET") == 0) - { - // Check if it's /d20 and handle that special case - if (strcmp(path, "GET") == 0) - { - get_d20(fd); - } - else - { - get_file(fd, cache, path); - } - } - resp_404(fd); + // Check if it's /d20 and handle that special case // Otherwise serve the requested file by calling get_file() - + if (strcmp(path, "/jonathan") == 0) + { + send_response(fd, "HTTP/1.1 200 OK", "text/plain", "Jonathan!", 9); + } + else + { + get_file(fd, NULL, path); + } // (Stretch) If POST, handle the post request } @@ -270,12 +266,13 @@ int main(void) // newfd is a new socket descriptor for the new connection. // listenfd is still listening for new connections. - resp_404(newfd); + handle_http_request(newfd, cache); + close(newfd); } // Unreachable code return 0; -} +} \ No newline at end of file From fff1b5e0fc6c1696aa659ab87241dc05e5e6da08 Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Thu, 14 Mar 2019 18:38:53 -0400 Subject: [PATCH 6/7] fixed cache_put, cache get implemented, all cache tests passing --- src/cache.c | 47 ++++++++++++++++++++++++++++++++--- src/cache_tests/cache_tests.c | 2 +- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/src/cache.c b/src/cache.c index 657931fd1..702d632c9 100644 --- a/src/cache.c +++ b/src/cache.c @@ -13,11 +13,25 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i // IMPLEMENT ME! // /////////////////// struct cache_entry *new_entry = malloc(sizeof(struct cache_entry)); - new_entry->path = path; - new_entry->content_type = content_type; - new_entry->content = content; + // new_entry->path = path; + // new_entry->content_type = content_type; + // new_entry->content = content; + // new_entry->content_length = content_length; + + // return new_entry; + new_entry->path = malloc(strlen(path) + 1); + strcpy(new_entry->path, path); + + new_entry->content_type = malloc(strlen(content_type) + 1); + strcpy(new_entry->content_type, content_type); + + new_entry->content = malloc(content_length); + memcpy(new_entry->content, content, content_length); + new_entry->content_length = content_length; + new_entry->prev = new_entry->next = NULL; + return new_entry; } @@ -29,6 +43,11 @@ void free_entry(struct cache_entry *entry) /////////////////// // IMPLEMENT ME! // /////////////////// + + free(entry->path); + free(entry->content_type); + free(entry->content); + free(entry); } /** @@ -106,6 +125,17 @@ struct cache *cache_create(int max_size, int hashsize) /////////////////// // IMPLEMENT ME! // /////////////////// + struct cache *new_cache = malloc(sizeof(struct cache)); + struct hashtable *hash_table = hashtable_create(hashsize, NULL); + + // new_cache->head = NULL; + // new_cache->tail = NULL; + new_cache->head = new_cache->tail = NULL; + new_cache->cur_size = 0; + new_cache->max_size = max_size; + new_cache->index = hash_table; + + return new_cache; } void cache_free(struct cache *cache) @@ -168,4 +198,15 @@ struct cache_entry *cache_get(struct cache *cache, char *path) /////////////////// // IMPLEMENT ME! // /////////////////// + if (hashtable_get(cache->index, path) == NULL) + { + return NULL; + } + else + { + // Move the cache entry to the head of the doubly-linked list. + dllist_move_to_head(cache, hashtable_get(cache->index, path)); + // Return the cache entry pointer. + return cache->head; + } } diff --git a/src/cache_tests/cache_tests.c b/src/cache_tests/cache_tests.c index 5e245d005..1f4689083 100644 --- a/src/cache_tests/cache_tests.c +++ b/src/cache_tests/cache_tests.c @@ -82,7 +82,7 @@ char *test_cache_put() mu_assert(check_cache_entries(cache->head->next->prev, test_entry_3) == 0, "Your cache_put function did not update the head->next->prev pointer to point to the new head entry"); mu_assert(check_cache_entries(cache->head->next->next, test_entry_1) == 0, "Your cache_put function did not update the head->next->next pointer to point to the tail entry"); mu_assert(check_cache_entries(cache->tail->prev, test_entry_2) == 0, "Your cache_put function did not update the tail->prev pointer to poin to the second-to-last entry"); - mu_assert(check_cache_entries(cache->tail, test_entry_1) == 0, "Your cache_put function did not correctly update the tail pointer of the cache"); + mu_assert(check_cache_entries(cache->tail, test_entry_1) == 0, "Your cache_put function did not correctly update the tail pointer of the cache"); // Add in a fourth entry to the cache cache_put(cache, test_entry_4->path, test_entry_4->content_type, test_entry_4->content, test_entry_4->content_length); From 81af292428475f283d20fc4d208497852efd62e5 Mon Sep 17 00:00:00 2001 From: Riley-Brown Date: Thu, 14 Mar 2019 19:16:27 -0400 Subject: [PATCH 7/7] cache functionality implemented --- src/server.c | 46 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/server.c b/src/server.c index 9b653f481..f98de6e59 100644 --- a/src/server.c +++ b/src/server.c @@ -137,25 +137,47 @@ void get_file(int fd, struct cache *cache, char *request_path) /////////////////// // IMPLEMENT ME! // /////////////////// - char filepath[4096]; - struct file_data *filedata; - char *mime_type; + // char filepath[4096]; + // struct file_data *filedata; + // char *mime_type; + /////////////////// + // IMPLEMENT ME! // + /////////////////// - snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); - printf("\"%s\"\n", filepath); - filedata = file_load(filepath); + struct cache_entry *cache_entry = cache_get(cache, request_path); - if (filedata == NULL) + if (cache_entry != NULL) { - // TODO: make this non-fatal - resp_404(fd); + send_response(fd, "HTTP/1.1 200 OK", cache_entry->content_type, cache_entry->content, cache_entry->content_length); } + else + { + char filepath[4096]; + struct file_data *filedata; + char *mime_type; - mime_type = mime_type_get(filepath); + if (strcmp(request_path, "/") == 0 || strcmp(request_path, "/index.html") == 0) + { + snprintf(filepath, sizeof filepath, "%s/index.html", SERVER_ROOT); + } + else + { + snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); + } - send_response(fd, "HTTP/1.1 200 ok", mime_type, filedata->data, filedata->size); + filedata = file_load(filepath); - file_free(filedata); + if (filedata == NULL) + { + resp_404(fd); + return; + } + + mime_type = mime_type_get(filepath); + 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); + } } /**