Skip to content

Hargobind Atwal #324

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

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/autorun.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodemon -w . --exec "make clean; clear; make && ./server"
45 changes: 42 additions & 3 deletions src/cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,15 @@ 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;
new_entry->next = NULL;
new_entry->prev = NULL;

return new_entry;
}

/**
Expand All @@ -22,6 +31,7 @@ void free_entry(struct cache_entry *entry)
///////////////////
// IMPLEMENT ME! //
///////////////////
free(entry);
}

/**
Expand Down Expand Up @@ -94,6 +104,16 @@ struct cache *cache_create(int max_size, int hashsize)
///////////////////
// IMPLEMENT ME! //
///////////////////
struct cache *new_cache;
new_cache = malloc(sizeof(struct cache));
new_cache->head = NULL;
new_cache->tail = NULL;
new_cache->cur_size = 0;
new_cache->max_size = max_size;
new_cache->index = hashtable_create(hashsize, NULL);
// new_cache->index->size = hashsize;
return new_cache;

}

void cache_free(struct cache *cache)
Expand Down Expand Up @@ -125,14 +145,33 @@ 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++;

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);
// keep cache at max_size
cache->cur_size = cache->max_size;

}

}

/**
* Retrieve an entry from the cache
*/
struct cache_entry *cache_get(struct cache *cache, char *path)
{
///////////////////
// IMPLEMENT ME! //
///////////////////
// attempting to find entry in hashtable
struct cache_entry * ce = hashtable_get(cache->index, path);
if (ce == NULL) {
return NULL;
}
dllist_move_to_head(cache, ce);
return ce;
}
1 change: 1 addition & 0 deletions src/run.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
make clean; clear; make && ./server
172 changes: 163 additions & 9 deletions src/server.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,15 @@
#define SERVER_FILES "./serverfiles"
#define SERVER_ROOT "./serverroot"

// int get_current_time() {
// // gets current time as a string
// time_t rawtime;
// struct tm * timeinfo;
// time (&rawtime);
// timeinfo = localtime (&rawtime);
// return timeinfo;
// }

/**
* Send an HTTP response
*
Expand All @@ -55,12 +64,35 @@ int send_response(int fd, char *header, char *content_type, void *body, int cont

// Build HTTP response and store it in response

///////////////////
// IMPLEMENT ME! //
///////////////////
// gets current time as a string
time_t rawtime;
struct tm * timeinfo;
time (&rawtime);
timeinfo = localtime (&rawtime);

char * current_date = asctime(timeinfo);

int header_length = sprintf(response, "%s\n"
"Date: %s"
"Connection: close\n"
"Content-Length: %d\n"
"Content-Type: %s\n"
"\n", header, current_date, content_length, content_type);

// char *file_blob = malloc(content_length);
printf("copying memory %d - %d\n", header_length, content_length);

if (header_length + content_length > max_response_size) {
content_length = content_length - (header_length + content_length - max_response_size);
}
memcpy(response + header_length , body, content_length);

// response[header_length + content_length+1] = '\0';

printf("response\n------------\n%s\n-----------\n", response);

// Send it all!
int rv = send(fd, response, response_length, 0);
int rv = send(fd, response, header_length + content_length, 0);

if (rv < 0) {
perror("send");
Expand All @@ -76,16 +108,27 @@ 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

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

// Use send_response() to send it back as text/plain data
// time_t rawtime;
srand(time(NULL));
int d20_val = rand();

char output[100]; // one hundred just to be safe
sprintf(output, "%d", d20_val);

int output_len = strlen(output);//(int)((ceil(log10(d20_val))+1)*sizeof(char));
printf("d20 roll: %d\n", d20_val);

// Use send_response() to send it back as text/plain data
///////////////////
// IMPLEMENT ME! //
///////////////////

send_response(fd, "http/1.1 200 /d20", "text/plain", output, output_len);
}

/**
Expand All @@ -108,7 +151,7 @@ void resp_404(int fd)
}

mime_type = mime_type_get(filepath);

// printf("\"%s\"", filedata->data);
send_response(fd, "HTTP/1.1 404 NOT FOUND", mime_type, filedata->data, filedata->size);

file_free(filedata);
Expand All @@ -122,6 +165,48 @@ void get_file(int fd, struct cache *cache, char *request_path)
///////////////////
// IMPLEMENT ME! //
///////////////////

struct file_data *filedata;
char *mime_type;
char filepath[4096];
char header[64];

mime_type = mime_type_get(filepath);
sprintf(header, "HTTP/1.1 200 %s", request_path);

struct cache_entry * cached_entry = cache_get(cache, request_path);
// snprintf(request_path, sizeof request_path, "%s/index.html", SERVER_ROOT);
if (cached_entry != NULL) // file was cached
{
printf("serving cached file: %s \n", request_path);
send_response(fd, header, mime_type, cached_entry->content, cached_entry->content_length);
}
else // load from disk
{


// concat request_path with local dir
snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, request_path);
printf("getting file: %s\n", filepath);
filedata = file_load(filepath);

if (filedata == NULL) {
fprintf(stderr, "cannot find %s\n", filepath);
printf("path does not exist \n");
resp_404(fd);
// exit(3);
return;
}

// cache file
cache_put(cache, request_path, mime_type, filedata->data, filedata->size);

// mime_type = mime_type_get(filepath);
printf("header: %s\n", header);

send_response(fd, header, mime_type, filedata->data, filedata->size);
file_free(filedata);
}
}

/**
Expand All @@ -135,14 +220,15 @@ char *find_start_of_body(char *header)
///////////////////
// IMPLEMENT ME! // (Stretch)
///////////////////
return "";
}

/**
* Handle HTTP request and send response
*/
void handle_http_request(int fd, struct cache *cache)
{
const int request_buffer_size = 65536; // 64K
const int request_buffer_size = 262144; // 256 kb
char request[request_buffer_size];

// Read request
Expand All @@ -158,14 +244,82 @@ void handle_http_request(int fd, struct cache *cache)
// IMPLEMENT ME! //
///////////////////

// char *request_parts = strtok(request, " ");
// printf("request verb: %s request endpoint: %s", request_parts[0],request_parts[1]);

char request_type[10], path[50];
sscanf(request, "%s %s", request_type, path);
printf("request: %s %s\n", request_type, path);

// parse header

// Read the first two components of the first line of the request
// printf("request: %s\n", request);

// If GET, handle the get endpoints
// char *is_get = strstr(request, "GET");
// char *route = strchr(request, '/');

// printf("request endpoint: \"%s\" \"%s\"\n", is_get, route);

char filepath[4096];
struct file_data *filedata;
char *mime_type;


if (strcmp(request_type, "GET") == 0 && strcmp(path, "/index.html") == 0)
{


// I could make this into another function
printf("is get index.html\n");
struct cache_entry * cached_entry = cache_get(cache, path);
get_file(fd, cache, "index.html");
/*
if (cached_entry == NULL)
{

snprintf(filepath, sizeof filepath, "%s/index.html", SERVER_ROOT);
filedata = file_load(filepath);

if (filedata == NULL) {
fprintf(stderr, "cannot find index.html\n");
exit(3);
}

mime_type = mime_type_get(filepath);

cache_put(cache, path, mime_type, filedata->data, filedata->size);
send_response(fd, "HTTP/1.1 200 /index.html", mime_type, filedata->data, filedata->size);
file_free(filedata);
}
else
{

printf("serving cached file: %s \n", path);
send_response(fd, "HTTP/1.1 200 /index.html", mime_type, cached_entry->content, cached_entry->content_length);
}
*/

}
else if (strcmp(request_type, "GET") == 0 && strcmp(path, "/d20") == 0)
{

get_d20(fd);
}
else
{

// snprintf(filepath, sizeof filepath, "%s%s", SERVER_ROOT, path);
// printf("%s", filepath);

// check if file exists?
get_file(fd, cache, path);

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

Expand Down