Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C-Web-Server - Scott Bren #303

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down
64 changes: 49 additions & 15 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,32 @@
*/
struct cache_entry *alloc_entry(char *path, char *content_type, void *content, int content_length)
{
///////////////////
// 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);

entry->content = strdup(content_str);
entry->content_length = content_length;

return entry;

}

/**
* Deallocate a cache entry
*/
void free_entry(struct cache_entry *entry)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
if (entry != NULL) {
free(entry->path);
free(entry->content_type);
free(entry->content);
free(entry);
}
}

/**
Expand Down Expand Up @@ -91,9 +104,16 @@ 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;
cache->cur_size = 0;

cache->index = hashtable_create(hashsize, NULL);
cache->head = NULL;
cache->tail = NULL;

return cache;
}

void cache_free(struct cache *cache)
Expand Down Expand Up @@ -122,17 +142,31 @@ void cache_free(struct cache *cache)
*/
void cache_put(struct cache *cache, char *path, char *content_type, void *content, int content_length)
{
///////////////////
// IMPLEMENT ME! //
///////////////////

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, oldtail->path);
free_entry(oldtail);
}

}

/**
* Retrieve an entry from the cache
*/
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;
}
}
88 changes: 79 additions & 9 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,12 @@ 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 = sprintf(response, "%s\nContent-Type: %s\nContent-Length: %d\nConnection: close\n\n", header, content_type, content_length);

///////////////////
// IMPLEMENT ME! //
///////////////////
memcpy(response+response_length, body, content_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");
Expand All @@ -73,20 +72,24 @@ 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

///////////////////
// 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! //
///////////////////
}
*/

/**
* Send a 404 response
Expand Down Expand Up @@ -122,6 +125,70 @@ 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( 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 {

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);
}

} */

//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);

}

}

/**
Expand All @@ -144,6 +211,8 @@ void handle_http_request(int fd, struct cache *cache)
{
const int request_buffer_size = 65536; // 64K
char request[request_buffer_size];
char action[100];
char endpoint[100];

// Read request
int bytes_recvd = recv(fd, request, request_buffer_size - 1, 0);
Expand All @@ -153,12 +222,14 @@ void handle_http_request(int fd, struct cache *cache)
return;
}


///////////////////
// IMPLEMENT ME! //
///////////////////

// Read the three components of the first request line
sscanf(request, "%s %s", action, endpoint);


get_file(fd, cache, endpoint);

// If GET, handle the get endpoints

Expand Down Expand Up @@ -193,7 +264,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;

Expand All @@ -213,7 +284,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);
Expand Down