From 4ee62fe9e3e92648320b46e89e526cc1a1bf33b8 Mon Sep 17 00:00:00 2001 From: Thomas Claydon Date: Mon, 17 Jun 2019 17:08:59 -0400 Subject: [PATCH 1/5] Completed Part 1.1 --- src/server.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/server.c b/src/server.c index 30b878464..1fe6a6378 100644 --- a/src/server.c +++ b/src/server.c @@ -59,6 +59,16 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont // IMPLEMENT ME! // /////////////////// + int response_length = sprintf(response, + "%s\n" + "Content-Type: %s\n" + "Content_Length: %s\n", + "Connection: close\n" + "\n" + "%s" + , header, content_type, content_length, body + ); + // Send it all! int rv = send(fd, response, response_length, 0); @@ -214,6 +224,10 @@ int main(void) // newfd is a new socket descriptor for the new connection. // listenfd is still listening for new connections. + // Test for send_response(); + resp_404(newfd); + // ------------------------ + handle_http_request(newfd, cache); close(newfd); From 96390760df54c4d2614548b074594ab5d69769f9 Mon Sep 17 00:00:00 2001 From: Thomas Claydon Date: Mon, 17 Jun 2019 17:52:55 -0400 Subject: [PATCH 2/5] Completed Part 1.2 --- src/server.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/server.c b/src/server.c index 1fe6a6378..1f4c492ee 100644 --- a/src/server.c +++ b/src/server.c @@ -169,12 +169,36 @@ void handle_http_request(int fd, struct cache *cache) /////////////////// // Read the first two components of the first line of the request + + char method[200]; + char path[8192]; + char protocol[200]; + + sscanf(request, "%s %s %s", method, path, protocol); + + printf("request: %s", request); + printf("method: %s\n",method); + printf("path: %s\n",path); + printf("protocol: %s\n",protocol); // If GET, handle the get endpoints - // Check if it's /d20 and handle that special case // Otherwise serve the requested file by calling get_file() + if (strcmp(method,"GET") == 0) + { + printf("GET\n"); + if (strcmp(path,"/d20") == 0) + { + printf("/d20\n"); + }else{ + resp_404(fd); + } + + } + + + // (Stretch) If POST, handle the post request } @@ -225,7 +249,7 @@ int main(void) // listenfd is still listening for new connections. // Test for send_response(); - resp_404(newfd); + // resp_404(newfd); // ------------------------ handle_http_request(newfd, cache); From 1de0474aab39c19c54949c4c6fb6dd11fe12fbe0 Mon Sep 17 00:00:00 2001 From: Thomas Claydon Date: Mon, 17 Jun 2019 18:45:23 -0400 Subject: [PATCH 3/5] Completed Part 1.3 --- src/server.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/server.c b/src/server.c index 1f4c492ee..29ea87f3b 100644 --- a/src/server.c +++ b/src/server.c @@ -58,15 +58,20 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont /////////////////// // IMPLEMENT ME! // /////////////////// + // printf("header: %s\n",header); + // printf("content_type: %s\n",content_type); + // printf("body: %s\n",body); + // printf("content_length: %d\n",content_length); int response_length = sprintf(response, "%s\n" "Content-Type: %s\n" - "Content_Length: %s\n", + "Content-Length: %d\n" "Connection: close\n" "\n" "%s" - , header, content_type, content_length, body + "\n" + , header, content_type, content_length + 1, body ); // Send it all! @@ -90,12 +95,18 @@ void get_d20(int fd) /////////////////// // IMPLEMENT ME! // /////////////////// + char number[10]; + int num = (rand() % 20) + 1; + sprintf(number, "%i", num); + printf("number: %s\n", number); // Use send_response() to send it back as text/plain data /////////////////// // IMPLEMENT ME! // /////////////////// + + send_response(fd, "HTTP/1.1 200 OK", "text/plain", number, strlen(number)); } /** @@ -191,15 +202,11 @@ void handle_http_request(int fd, struct cache *cache) if (strcmp(path,"/d20") == 0) { printf("/d20\n"); + get_d20(fd); }else{ resp_404(fd); } - } - - - - // (Stretch) If POST, handle the post request } From 657f2876ccc15bb47a6ea55b3a405a296fb55efa Mon Sep 17 00:00:00 2001 From: Thomas Claydon Date: Tue, 18 Jun 2019 17:48:00 -0400 Subject: [PATCH 4/5] Completed Day 2 MVP --- src/server.c | 196 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 151 insertions(+), 45 deletions(-) diff --git a/src/server.c b/src/server.c index 29ea87f3b..99ab6b1f3 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" @@ -63,42 +63,69 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont // printf("body: %s\n",body); // printf("content_length: %d\n",content_length); - int response_length = sprintf(response, - "%s\n" - "Content-Type: %s\n" - "Content-Length: %d\n" - "Connection: close\n" - "\n" - "%s" - "\n" - , header, content_type, content_length + 1, body - ); + // int response_length = sprintf(response, + // "%s\n" + // "Content-Type: %s\n" + // "Content-Length: %d\n" + // "Connection: close\n" + // "\n" + // "%s" + // "\n" + // , header, content_type, content_length + 1, body + // ); + + // int response_length = sprintf(response, + // "%s\n" + // "Content-Type: %s\n" + // "Content-Length: %d\n" + // "Connection: close\n" + // "\n" + // , header, content_type, content_length + // ); + + // memcpy(response + response_length, body, content_length); + // response_length += content_length; + + int response_length = sprintf(response, + "%s\n" + "Content-Type: %s\n" + "Content-Length: %d\n" + "Connection: close\n" + "\n", + header, content_type, content_length); // Send it all! int rv = send(fd, response, response_length, 0); - if (rv < 0) { + if (rv < 0) + { + perror("send"); + } + + rv = send(fd, body, content_length, 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! // /////////////////// char number[10]; int num = (rand() % 20) + 1; - sprintf(number, "%i", num); - printf("number: %s\n", number); + int resp_len = sprintf(number, "%d", num); + printf("number ---: %s\n", number); // Use send_response() to send it back as text/plain data @@ -106,7 +133,7 @@ void get_d20(int fd) // IMPLEMENT ME! // /////////////////// - send_response(fd, "HTTP/1.1 200 OK", "text/plain", number, strlen(number)); + send_response(fd, "HTTP/1.1 200 OK", "text/plain", number, resp_len); } /** @@ -115,14 +142,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); @@ -134,15 +162,66 @@ void resp_404(int fd) file_free(filedata); } +/** + * Send a cat response + */ +void get_cat(int fd) +{ + char filepath[4096]; + struct file_data *filedata; + char *mime_type; + + // Fetch the cat.jpeg file + snprintf(filepath, sizeof filepath, "%s/cat.jpg", SERVER_ROOT); + filedata = file_load(filepath); + + if (filedata == NULL) + { + // TODO: make this non-fatal + fprintf(stderr, "cannot find cat file\n"); + exit(3); + } + + mime_type = mime_type_get(filepath); + + send_response(fd, "HTTP/1.1 200 FOUND", mime_type, filedata->data, filedata->size); + + file_free(filedata); +} /** * Read and return a file from disk or cache */ void get_file(int fd, struct cache *cache, char *request_path) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// + char filepath[4096]; + struct file_data *filedata; + char *mime_type; + // char src[4096], dest[4096]; + + // strcpy(src, request_path); + // strcpy(dest, "%s"); + + // strcat(dest, src); + // printf("dest: %s", dest); + + // Fetch the cat.jpeg file + snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); + filedata = file_load(filepath); + + if (filedata == NULL) + { + // TODO: make this non-fatal + fprintf(stderr, "cannot find file %s\n", request_path); + exit(3); + } + + mime_type = mime_type_get(filepath); + printf("mime_type: %s", mime_type); + + send_response(fd, "HTTP/1.1 200 FOUND", mime_type, filedata->data, filedata->size); + + file_free(filedata); } /** @@ -169,42 +248,64 @@ 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! // /////////////////// - // Read the first two components of the first line of the request + // Read the first two components of the first line of the request char method[200]; - char path[8192]; + char path[8192]; char protocol[200]; + // char needle[11] = "serverroot"; + // char *ret; sscanf(request, "%s %s %s", method, path, protocol); printf("request: %s", request); - printf("method: %s\n",method); - printf("path: %s\n",path); - printf("protocol: %s\n",protocol); - + printf("method: %s\n", method); + printf("path: %s\n", path); + printf("protocol ---: %s\n", protocol); + // If GET, handle the get endpoints // Check if it's /d20 and handle that special case // Otherwise serve the requested file by calling get_file() - if (strcmp(method,"GET") == 0) + if (strcmp(method, "GET") == 0) { - printf("GET\n"); - if (strcmp(path,"/d20") == 0) + // printf("needle: %s\n", needle); + printf("GET is this the value -----\n"); + + // ret = strstr(path, needle); + // printf("ret: %s\n", ret); + // printf("after ret\n"); + if (strcmp(path, "/d20") == 0) { - printf("/d20\n"); + // printf("/d20\n"); get_d20(fd); - }else{ - resp_404(fd); + } + else if (strcmp(path, "/cat") == 0) + { + get_cat(fd); + } + // else if (strstr(path, needle) != NULL) + // { + // printf("before get file\n"); + // get_file(fd, cache, path); + // } + // else + // { + // resp_404(fd); + // } + else + { + get_file(fd, cache, path); } } // (Stretch) If POST, handle the post request @@ -215,16 +316,20 @@ 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]; + // random randomizing seeding + srand(time(NULL)); + struct cache *cache = cache_create(10, 0); // 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); } @@ -234,24 +339,26 @@ int main(void) // This is the main loop that accepts incoming connections and // responds to the request. 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. @@ -268,4 +375,3 @@ int main(void) return 0; } - From 79d0caf156124586d30bcc984d0f78796273d158 Mon Sep 17 00:00:00 2001 From: Thomas Claydon Date: Wed, 19 Jun 2019 17:29:21 -0400 Subject: [PATCH 5/5] Completed MVP day 3 and 4 --- src/cache.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++------ src/server.c | 39 +++++++++++++++------------ 2 files changed, 88 insertions(+), 25 deletions(-) diff --git a/src/cache.c b/src/cache.c index c72975cdd..cb1bd9bef 100644 --- a/src/cache.c +++ b/src/cache.c @@ -12,6 +12,12 @@ 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 = path; + entry->content_type = content_type; + entry->content_length = content_length; + entry->content = content; + return entry; } /** @@ -22,6 +28,7 @@ void free_entry(struct cache_entry *entry) /////////////////// // IMPLEMENT ME! // /////////////////// + free(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 * @@ -94,6 +106,22 @@ struct cache *cache_create(int max_size, int hashsize) /////////////////// // IMPLEMENT ME! // /////////////////// + // allocate memory for cache structure + struct cache *cache = malloc(sizeof(struct cache)); + // create hashtable + struct hashtable *hashtable = hashtable_create(hashsize, NULL); + // cache index equal to newly created hashtable + cache->index = hashtable; + // initialized to NULL + cache->head = NULL; + // initialized to NULL + cache->tail = NULL; + // max cache size + cache->max_size = max_size; + // initialized to 0 + cache->cur_size = 0; + // return cache struct + return cache; } void cache_free(struct cache *cache) @@ -102,7 +130,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 +154,23 @@ void cache_put(struct cache *cache, char *path, char *content_type, void *conten /////////////////// // IMPLEMENT ME! // /////////////////// + + // create new entry + struct cache_entry *entry = alloc_entry(path, content_type, content, content_length); + // add new entry to the front of the cache + dllist_insert_head(cache, entry); + // add entry in hashtable + hashtable_put(cache->index, entry->path, entry); + // incerase current size current cache size counter + cache->cur_size++; + // determine if cache is larger than allowed + if (cache->cur_size > cache->max_size) + { + // delete hashtable by key + hashtable_delete(cache->index, cache->tail->path); + // delete and free cache tail + free_entry(dllist_remove_tail(cache)); + } } /** @@ -135,4 +181,16 @@ struct cache_entry *cache_get(struct cache *cache, char *path) /////////////////// // IMPLEMENT ME! // /////////////////// + + // find entry pointer in hashtable + struct cache_entry *entry = hashtable_get(cache->index, path); + // check to see if entry exists in hashtable, if no return null, otherwise move entry to head of the list and return entry + if (entry == NULL) + { + return NULL; + }else{ + dllist_move_to_head(cache, entry); + return entry; + } + } diff --git a/src/server.c b/src/server.c index 99ab6b1f3..d4f8b9bbc 100644 --- a/src/server.c +++ b/src/server.c @@ -196,32 +196,37 @@ void get_file(int fd, struct cache *cache, char *request_path) { char filepath[4096]; struct file_data *filedata; + struct cache_entry *entry; char *mime_type; - // char src[4096], dest[4096]; - // strcpy(src, request_path); - // strcpy(dest, "%s"); - - // strcat(dest, src); - // printf("dest: %s", dest); - - // Fetch the cat.jpeg file snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); - filedata = file_load(filepath); - if (filedata == NULL) + entry = cache_get(cache, filepath); + + if (entry != NULL) { - // TODO: make this non-fatal - fprintf(stderr, "cannot find file %s\n", request_path); - exit(3); + send_response(fd, "HTTP/1.1 200 FOUND", entry->content_type, entry->content, entry->content_length); } + else + { + filedata = file_load(filepath); - mime_type = mime_type_get(filepath); - printf("mime_type: %s", mime_type); + if (filedata == NULL) + { + // TODO: make this non-fatal + // fprintf(stderr, "cannot find file %s\n", request_path); + // exit(3); + resp_404(fd); + return; + } - send_response(fd, "HTTP/1.1 200 FOUND", mime_type, filedata->data, filedata->size); + mime_type = mime_type_get(filepath); + printf("mime_type: %s", mime_type); - file_free(filedata); + send_response(fd, "HTTP/1.1 200 FOUND", mime_type, filedata->data, filedata->size); + + file_free(filedata); + } } /**