From c00f3b32cc90e093cdaa509c5ee5d3fbcc735783 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Mon, 8 Apr 2019 15:08:16 -0400 Subject: [PATCH 01/10] implemented send response, not tested yet --- example/sprintf_example | Bin 0 -> 8432 bytes example/sprintf_example.c | 35 ++++++++++++++++++++ example/sscanf_example | Bin 0 -> 8416 bytes example/sscanf_example.c | 27 ++++++++++++++++ src/cache.c | 30 +++++++++++------- src/server.c | 65 ++++++++++++++++++++++---------------- 6 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 example/sprintf_example create mode 100644 example/sprintf_example.c create mode 100644 example/sscanf_example create mode 100644 example/sscanf_example.c diff --git a/example/sprintf_example b/example/sprintf_example new file mode 100644 index 0000000000000000000000000000000000000000..97dc5f727108d9d4fd5e13847eabe5fc9791d125 GIT binary patch literal 8432 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 literal 0 HcmV?d00001 diff --git a/example/sprintf_example.c b/example/sprintf_example.c new file mode 100644 index 000000000..aff9d6173 --- /dev/null +++ b/example/sprintf_example.c @@ -0,0 +1,35 @@ +#include +#include + +/* + HTTP/1.1 200 OK\n + Date: .... <--- would be here but not in this example + Content-Type: text/html\n + Content-Length: %d\n + Connection: close\n + \n <--- needs to be a new line that separates header from body + +*/ + +// Example of how to build a response +int main(void) +{ + // buffer to hold the res data + char response[500000]; + + char *body = "

Hello, world!

"; + int length = strlen(body); + + // Let's build the actual response now + sprintf(response, + "HTTP/1.1 200 OK\n" + "Content-Type: text/html\n" + "Content-Length: %d\n" + "Connection: close\n" + "\n" + "%s", + length, body); + + printf("%s", response); + return 0; +} \ No newline at end of file diff --git a/example/sscanf_example b/example/sscanf_example new file mode 100644 index 0000000000000000000000000000000000000000..3b74e9b1f17db091849f01c83a6611a063577ff2 GIT binary patch literal 8416 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 literal 0 HcmV?d00001 diff --git a/example/sscanf_example.c b/example/sscanf_example.c new file mode 100644 index 000000000..3490bb3d4 --- /dev/null +++ b/example/sscanf_example.c @@ -0,0 +1,27 @@ +#include + +/* + given this request, how do we parse (extract important parts of it) it? + GET /foobar HTTP/1.1 + Host: www.example.com + Connection: close + +*/ + +int main(void) +{ + char *s = "GET /foobar HTTP/1.1\nHost: www.example.com\nConnection: clone\n"; + + // buffer to hold the method + char method[200]; + // buffer to hold the path + char path[8192]; + + // take some string, supply a format specifier + // %s %s pulls out the first two strings which will be the GET and path + sscanf(s, "%s %s", method, path); + + printf("method: %s\n", method); + printf("path: %s\n", path); + return 0; +} \ No newline at end of file diff --git a/src/cache.c b/src/cache.c index c72975cdd..5a85f8d4f 100644 --- a/src/cache.c +++ b/src/cache.c @@ -3,7 +3,7 @@ #include #include "hashtable.h" #include "cache.h" - +// day 2 stuff /** * Allocate a cache entry */ @@ -30,10 +30,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 +49,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,10 +71,9 @@ void dllist_move_to_head(struct cache *cache, struct cache_entry *ce) } } - /** * Removes the tail from the list and returns it - * + * * NOTE: does not deallocate the tail */ struct cache_entry *dllist_remove_tail(struct cache *cache) @@ -85,7 +90,7 @@ struct cache_entry *dllist_remove_tail(struct cache *cache) /** * Create a new cache - * + * * max_size: maximum number of entries in the cache * hashsize: hashtable size (0 for default) */ @@ -102,7 +107,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); @@ -117,7 +123,7 @@ void cache_free(struct cache *cache) * Store an entry in the cache * * This will also remove the least-recently-used items as necessary. - * + * * NOTE: doesn't check for duplicate cache entries */ void cache_put(struct cache *cache, char *path, char *content_type, void *content, int content_length) diff --git a/src/server.c b/src/server.c index ea43306fc..1ca1dc945 100644 --- a/src/server.c +++ b/src/server.c @@ -1,18 +1,18 @@ /** * webserver.c -- A webserver written in C - * + * * Test with curl (if you don't have it, install it): - * + * * curl -D - http://localhost:3490/ * curl -D - http://localhost:3490/d20 * curl -D - http://localhost:3490/date - * + * * You can also test the above URLs in your browser! They should work! - * + * * Posting Data: - * + * * curl -D - -X POST -H 'Content-Type: text/plain' -d 'Hello, sample data!' http://localhost:3490/save - * + * * (Posting data is harder to test from a browser.) */ @@ -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" @@ -45,7 +45,7 @@ * header: "HTTP/1.1 404 NOT FOUND" or "HTTP/1.1 200 OK", etc. * content_type: "text/plain", etc. * body: the data to send. - * + * * Return the value from the send() function. */ int send_response(int fd, char *header, char *content_type, void *body, int content_length) @@ -54,7 +54,13 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont char response[max_response_size]; // Build HTTP response and store it in response - + int response_length = sscanf(response, max_response_size, + "%s\n" + "Content-Type: %s\n" + "Content-Length: %s\n" + "Connection: close\n" + "\n", + header, content_type, content_length); /////////////////// // IMPLEMENT ME! // /////////////////// @@ -62,21 +68,21 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont // 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! // /////////////////// @@ -89,19 +95,20 @@ void get_d20(int fd) } /** - * Send a 404 response + * Send a 404 response || already implamented */ 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); @@ -116,6 +123,7 @@ void resp_404(int fd) /** * Read and return a file from disk or cache + * get file will look similar to response 404 */ void get_file(int fd, struct cache *cache, char *request_path) { @@ -126,7 +134,7 @@ void get_file(int fd, struct cache *cache, char *request_path) /** * Search for the end of the HTTP header - * + * * "Newlines" in HTTP can be \r\n (carriage return followed by newline) or \n * (newline) or \r (carriage return). */ @@ -148,12 +156,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 +173,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 +181,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 +190,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 +201,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 +233,3 @@ int main(void) return 0; } - From 493ec9ccc51eb3964221853f3d58b721501b3306 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Mon, 8 Apr 2019 15:20:10 -0400 Subject: [PATCH 02/10] added a random number using rand, not sure if it works yet --- src/server.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index 1ca1dc945..dadbfbf12 100644 --- a/src/server.c +++ b/src/server.c @@ -61,9 +61,6 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont "Connection: close\n" "\n", header, content_type, content_length); - /////////////////// - // IMPLEMENT ME! // - /////////////////// // Send it all! int rv = send(fd, response, response_length, 0); @@ -82,7 +79,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 - + int rand = rand() % 20 + 1; /////////////////// // IMPLEMENT ME! // /////////////////// From 2cf6cec90aff82e003e2230d359d3ac18ab451e8 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Mon, 8 Apr 2019 15:30:01 -0400 Subject: [PATCH 03/10] fixed issues with rand and send response function --- src/server.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/server.c b/src/server.c index dadbfbf12..0c826146a 100644 --- a/src/server.c +++ b/src/server.c @@ -70,6 +70,8 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont perror("send"); } + rv = send(fd, body, content_length, 0); + return rv; } @@ -79,16 +81,13 @@ 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 - int rand = rand() % 20 + 1; + int random = (rand() % 20) + 1; /////////////////// // IMPLEMENT ME! // /////////////////// // Use send_response() to send it back as text/plain data - /////////////////// - // IMPLEMENT ME! // - /////////////////// } /** From b7087b7cefcd80aefd745e564c78883ca940a79e Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Mon, 8 Apr 2019 16:43:50 -0400 Subject: [PATCH 04/10] seems I some how made it through get_d20.. not sure how --- example/sscanf_example.c | 2 +- src/server.c | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/example/sscanf_example.c b/example/sscanf_example.c index 3490bb3d4..8bacbbfd1 100644 --- a/example/sscanf_example.c +++ b/example/sscanf_example.c @@ -10,7 +10,7 @@ int main(void) { - char *s = "GET /foobar HTTP/1.1\nHost: www.example.com\nConnection: clone\n"; + char *s = "GET /foobar HTTP/1.1\nHost: www.example.com\nConnection: close\n"; // buffer to hold the method char method[200]; diff --git a/src/server.c b/src/server.c index 0c826146a..3261c3e78 100644 --- a/src/server.c +++ b/src/server.c @@ -54,13 +54,13 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont char response[max_response_size]; // Build HTTP response and store it in response - int response_length = sscanf(response, max_response_size, - "%s\n" - "Content-Type: %s\n" - "Content-Length: %s\n" - "Connection: close\n" - "\n", - header, content_type, content_length); + int response_length = snprintf(response, max_response_size, + "%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); @@ -81,13 +81,18 @@ 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 - int random = (rand() % 20) + 1; + int body = (rand() % 20) + 1; + + char *status = "HTTP/1.1 200 OK\n"; + char *type = "text/plain\n"; + char res_body[20]; + /////////////////// // IMPLEMENT ME! // /////////////////// - + sprintf(res_body, "%d\n", body); // Use send_response() to send it back as text/plain data - + send_response(fd, status, type, res_body, strlen(res_body)); } /** From be05c8d1fae70783c5e82a873d76bb9b4139c54a Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Mon, 8 Apr 2019 18:19:54 -0400 Subject: [PATCH 05/10] added a fake get_file function that I know probably doesn't work --- src/server.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/server.c b/src/server.c index 3261c3e78..8d2266227 100644 --- a/src/server.c +++ b/src/server.c @@ -131,6 +131,26 @@ void get_file(int fd, struct cache *cache, char *request_path) /////////////////// // IMPLEMENT ME! // /////////////////// + char filepath[4096]; + struct file_data *filedata; + char *mime_type; + + // Fetch the 404.html file + snprintf(filepath, sizeof filepath + sizeof request_path, "%s/%s", SERVER_FILES, request_path); + filedata = file_load(filepath); + + if (filedata == NULL) + { + // TODO: make this non-fatal + fprintf(stderr, "cannot find system 404 file\n"); + exit(3); + } + + mime_type = mime_type_get(filepath); + + send_response(fd, "HTTP/1.1", mime_type, filedata->data, filedata->size); + + file_free(filedata); } /** From cb555f6831ccc177ddfbed7b1a3653deb74cae23 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Tue, 9 Apr 2019 16:55:42 -0400 Subject: [PATCH 06/10] fixed get file and resp 404 --- src/server.c | 93 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 61 insertions(+), 32 deletions(-) diff --git a/src/server.c b/src/server.c index 8d2266227..cc8612620 100644 --- a/src/server.c +++ b/src/server.c @@ -50,20 +50,33 @@ */ int send_response(int fd, char *header, char *content_type, void *body, int content_length) { - const int max_response_size = 262144; - char response[max_response_size]; - - // Build HTTP response and store it in response - int response_length = snprintf(response, max_response_size, - "%s\n" - "Content-Type: %s\n" - "Content-Length: %d\n" - "Connection: close\n" - "\n", - header, content_type, content_length); + const int max_res_size = 262144; + char res[max_res_size]; + int res_length = 0; + time_t t = time(NULL); // Unix timestamp + + (void)header; + (void)content_type; + (void)body; + (void)content_length; + // Build HTTP res and store it in res + + res_length = sprintf(res, + "%s\n" // header + "Date: %s" // date + "Connection: close\n" // close + "Content-Length: %d\n" // length + "Content-Type: %s\n" // type + "\n", // mandatory space + header, + asctime(gmtime(&t)), + content_length, + content_type); + + memcpy(res + res_length, body, content_length); // Send it all! - int rv = send(fd, response, response_length, 0); + int rv = send(fd, res, res_length + content_length, 0); if (rv < 0) { @@ -133,24 +146,19 @@ void get_file(int fd, struct cache *cache, char *request_path) /////////////////// char filepath[4096]; struct file_data *filedata; - char *mime_type; + (void)cache; - // Fetch the 404.html file - snprintf(filepath, sizeof filepath + sizeof request_path, "%s/%s", SERVER_FILES, request_path); + // construct the full file path + snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path); + // can also use sprintf if you're feeling lazy + // sprintf(filepath, "%s%s", SERVER_ROOT, request_path); filedata = file_load(filepath); + // check to see if file_load returned a valid file if (filedata == NULL) { - // TODO: make this non-fatal - fprintf(stderr, "cannot find system 404 file\n"); - exit(3); + resp_404(fd); } - - mime_type = mime_type_get(filepath); - - send_response(fd, "HTTP/1.1", mime_type, filedata->data, filedata->size); - - file_free(filedata); } /** @@ -159,12 +167,12 @@ void get_file(int fd, struct cache *cache, char *request_path) * "Newlines" in HTTP can be \r\n (carriage return followed by newline) or \n * (newline) or \r (carriage return). */ -char *find_start_of_body(char *header) -{ - /////////////////// - // IMPLEMENT ME! // (Stretch) - /////////////////// -} +// char *find_start_of_body(char *header) +// { +// /////////////////// +// // IMPLEMENT ME! // (Stretch) +// /////////////////// +// } /** * Handle HTTP request and send response @@ -173,6 +181,8 @@ void handle_http_request(int fd, struct cache *cache) { const int request_buffer_size = 65536; // 64K char request[request_buffer_size]; + char request_type[8]; + char request_path[1024]; // Read request int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0); @@ -183,17 +193,36 @@ 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" request_type, request_path); + + printf("REQUEST: %s %s\n", request_type, request_path); // If GET, handle the get endpoints + if (strcmp(request_type, "GET") == 0 && strcmp(request_path, "/d20") == 0) + { + // Check if it's /d20 and handle that special case + get_d20(fd); + } + else + { + // Otherwise serve the requested file by calling get_file() + get_file(fd, cache, request_path); + } - // Check if it's /d20 and handle that special case - // Otherwise serve the requested file by calling get_file() + char *mime_type = mime_type_get(file_data); + //we fetched the valid file + // make sure we send it + send_response(fd, "HTTP/1.1 200 OK", mime_type, file_data->data, file_data->data); + // free the file data struct after it's been sent + file_free(file_data); // (Stretch) If POST, handle the post request } From 0f983a1a3f46c5f4ba64c40d511fda5299211f53 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Tue, 9 Apr 2019 17:39:51 -0400 Subject: [PATCH 07/10] getting connection refuced error --- src/server.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/server.c b/src/server.c index cc8612620..d45ff4635 100644 --- a/src/server.c +++ b/src/server.c @@ -158,7 +158,16 @@ void get_file(int fd, struct cache *cache, char *request_path) if (filedata == NULL) { resp_404(fd); + return; } + + char *mime_type = mime_type_get(filepath); + // we fetched a valid file + // make sure we send it! + send_response(fd, "HTTP/1.1 200 OK", mime_type, filedata->data, filedata->size); + + // free file data struct after it's been sent + file_free(filedata); } /** @@ -200,7 +209,7 @@ void handle_http_request(int fd, struct cache *cache) /////////////////// // Read the three components of the first request line - sscanf(request, "%s %s" request_type, request_path); + sscanf(request, "%s %s", request_type, request_path); printf("REQUEST: %s %s\n", request_type, request_path); @@ -216,13 +225,6 @@ void handle_http_request(int fd, struct cache *cache) get_file(fd, cache, request_path); } - char *mime_type = mime_type_get(file_data); - - //we fetched the valid file - // make sure we send it - send_response(fd, "HTTP/1.1 200 OK", mime_type, file_data->data, file_data->data); - // free the file data struct after it's been sent - file_free(file_data); // (Stretch) If POST, handle the post request } From 7e5cf8f4e24c8822bcd058b5e38cd64240fa49a9 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Wed, 10 Apr 2019 15:19:16 -0400 Subject: [PATCH 08/10] working on cache.c file --- src/cache.c | 28 ++++++++++++++++++++++------ src/cache.h | 12 +++++++----- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/src/cache.c b/src/cache.c index 5a85f8d4f..c3f3291dd 100644 --- a/src/cache.c +++ b/src/cache.c @@ -9,9 +9,23 @@ */ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, int content_length) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// + // free spaces for cache entry + struct cache_entry *new_entry = malloc(sizeof(struct cache_entry)); + + // deep copy path + new_entry->path = malloc(strlen(path) + 1); + strcpy(new_entry->path, path); + // deep copy content type + new_entry->content_type = malloc(strlen(content_type) + 1); + strcpy(new_entry->content_type, content_type); + // deep copy content length + new_entry->content_length = malloc(strlen(content_length) + 1); + memcpy(new_entry->content_length, content, content_length); + + new_entry->content_length = content_length; + new_entry->prev = new_entry->next = NULL; + + return new_entry; } /** @@ -19,9 +33,11 @@ struct cache_entry *alloc_entry(char *path, char *content_type, void *content, i */ void free_entry(struct cache_entry *entry) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// + // free entry struct properties + free(entry->content); + free(entry->content_length); + free(entry->content_type); + free(entry); } /** diff --git a/src/cache.h b/src/cache.h index f64c976ad..7432d6ac7 100644 --- a/src/cache.h +++ b/src/cache.h @@ -2,8 +2,9 @@ #define _WEBCACHE_H_ // Individual hash table entry -struct cache_entry { - char *path; // Endpoint path--key to the cache +struct cache_entry +{ // each entry is a node + char *path; // Endpoint path--key to the cache char *content_type; int content_length; void *content; @@ -12,11 +13,12 @@ struct cache_entry { }; // A cache -struct cache { +struct cache +{ struct hashtable *index; struct cache_entry *head, *tail; // Doubly-linked list - int max_size; // Maxiumum number of entries - int cur_size; // Current number of entries + int max_size; // Maxiumum number of entries + int cur_size; // Current number of entries }; extern struct cache_entry *alloc_entry(char *path, char *content_type, void *content, int content_length); From 522951e2e7f4f868db8f48dc264311dd30419897 Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Wed, 10 Apr 2019 15:26:24 -0400 Subject: [PATCH 09/10] working on a few functions, not tested yet --- src/cache.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/cache.c b/src/cache.c index c3f3291dd..b19b5d777 100644 --- a/src/cache.c +++ b/src/cache.c @@ -37,6 +37,7 @@ void free_entry(struct cache_entry *entry) free(entry->content); free(entry->content_length); free(entry->content_type); + // free the struct itself free(entry); } @@ -112,9 +113,15 @@ struct cache_entry *dllist_remove_tail(struct cache *cache) */ 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 = 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) From 55a3c2effdb3d74995156b55fce95fcb8232ec2c Mon Sep 17 00:00:00 2001 From: Carlos Lantigua Date: Thu, 11 Apr 2019 18:12:13 -0400 Subject: [PATCH 10/10] cleaned finished cache. refactored some code and took care of some of the errors. added comments to explain thoughts in case I need to go back. --- src/cache.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/src/cache.c b/src/cache.c index b19b5d777..fc15ee707 100644 --- a/src/cache.c +++ b/src/cache.c @@ -151,9 +151,33 @@ void cache_free(struct cache *cache) */ void cache_put(struct cache *cache, char *path, char *content_type, void *content, int content_length) { - /////////////////// - // IMPLEMENT ME! // - /////////////////// + // Allocate a new cache entry + struct cache_entry *new_entry = alloc_entry(path, content_type, content, content_length); + + // Insert the entry at the head of the dll + dllist_insert_head(cache, new_entry); + + // Store the entry into the hashtable + hashtable_put(cache->index, path, new_entry); + + // Increment the current size of the cache + cache->cur_size += 1; + + // If the cache size is greater than max size + if (cache->cur_size > cache->max_size) + { + // Remove the entry from dll tail + struct cache_entry *old_entry = dllist_remove_tail(cache); + // remove the entry from hash + hashtable_delete(cache->index, old_entry->path); + // Free the cache entry + free_entry(old_entry); + // bring down current size to be no bigger than max size + if (cache->cur_size > cache->max_size) + { + cache->cur_size -= 1; + } + } } /** @@ -161,7 +185,14 @@ 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! // - /////////////////// + // if entry at index is NULL + if (hashtable_get(cache->index, path) == NULL) + { + return NULL; + } + else + { // Move entry to head of the dll + dllist_move_to_head(cache, hashtable_get(cache->index, path)); + return cache->head; + } }