Skip to content
Snippets Groups Projects
Commit 3b218972 authored by Abhisha Nirmalathas's avatar Abhisha Nirmalathas
Browse files

adding request struct and parser

parent de890bf2
No related branches found
No related tags found
No related merge requests found
Makefile 0 → 100644
CC = gcc
CFLAGS = -Wall -std=c99 -g
# modify the flags here ^
EXE = image_tagger
OBJ = hashtable.o http-parser.o http-response.o http-server.o
# add any new object files here ^
# top (default) target
all: $(EXE)
# how to link executable
$(EXE): $(OBJ)
$(CC) $(CFLAGS) -o $(EXE) $(OBJ) -lm
# other dependencies
http-parser.o: http-parser.h hashtable.h
http-response.o: http-response.h http-parser.h hashtable.h
http-server.o: http-parser.h
# ^ add any new dependencies here (for example if you add new modules)
# phony targets (these targets do not represent actual files)
.PHONY: clean cleanly all CLEAN
# `make clean` to remove all object files
# `make CLEAN` to remove all object and executable files
# `make cleanly` to `make` then immediately remove object files (inefficient)
clean:
rm -f $(OBJ)
CLEAN: clean
rm -f $(EXE)
cleanly: all clean
\ No newline at end of file
/* This hash table has been adapted by Abhisha Nirmalathas.
The original hash table it was adapted from was made
by Matt Farrugia <matt.farrugia@unimelb.edu.au, for Design of Algorithms.
This hash table uses separate chaining with an array.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "hashtable.h"
typedef struct bucket Bucket;
struct bucket {
char **keys; //array of words
char **values; //array of weighted frequencies, lower value is higher frequency
int capacity; //space available in bucket
int n_elems; //number of elements in bucket
};
struct table {
int size; //number of buckets
Bucket *buckets; //list of buckets
};
/************************************************************************/
// moves recently accessed key & value to the front of bucket
void move_to_front(Bucket *bucket, int hash_value);
unsigned int seed = 73802;
unsigned int xor_hash(const char *key, unsigned int size) {
unsigned int h = seed;
int i;
for (i = 0; key[i] != '\0'; i++) {
h = h ^ ((h << 5) + key[i] + (h >> 2));
}
return h % size;
}
/************************************************************************/
Bucket *add_to_bucket(Bucket *bucket, char *key, char *value) {
/*Adds new key and value to existing bucket*/
bucket->n_elems = bucket->n_elems + 1;
// allocates more memory if not enough space
if (bucket->capacity <= bucket->n_elems){
bucket->capacity = 2*(bucket->capacity + 1);
bucket->keys = realloc(bucket->keys,sizeof(char*) * (bucket->capacity));
bucket->values = realloc(bucket->values,sizeof(char*) * (bucket->capacity));
}
assert(bucket->keys);
assert(bucket->values);
//adds new key and avlue to end of bucket
bucket->values[bucket->n_elems-1] = value;
bucket->keys[bucket->n_elems-1] = key;
return bucket;
}
/************************************************************************/
// Warning: does not free bucket->next
void free_bucket(Bucket bucket) {
/*Deallocates memory in bucket*/
free(bucket.keys);
free(bucket.values);
}
/************************************************************************/
HashTable *new_hash_table(int size) {
/*Builds a new hash table of input size*/
HashTable *table = malloc(sizeof *table);
assert(table);
table->size = size;
table->buckets = malloc(size * (sizeof *table->buckets));
assert(table->buckets);
int i;
for (i = 0; i < size; i++) {
table->buckets[i].keys = malloc(sizeof(char*));
table->buckets[i].values = malloc(sizeof(char*));
table->buckets[i].capacity = 0;
table->buckets[i].n_elems = 0;
}
return table;
}
/************************************************************************/
void free_hash_table(HashTable *table) {
/*Deallocates memory from hash table*/
assert(table != NULL);
int i;
for (i = 0; i < table->size; i++) {
free_bucket(table->buckets[i]);
}
free(table->buckets);
free(table);
}
/************************************************************************/
bool equal(char *a, char *b) {
/*Returns if a string is equal to another string*/
return strcmp(a, b) == 0;
}
/************************************************************************/
void hash_table_put(HashTable *table, char *key, char *value) {
/*Inserts new key into hash table with weighted value*/
assert(table != NULL);
assert(key != NULL);
int hash_value = xor_hash(key, table->size);
// look for existing key
Bucket *bucket = &table->buckets[hash_value];
for (int i=0; i < bucket->n_elems; i++){
if (equal(bucket->keys[i], key)){
bucket->values[i] = value;
move_to_front(bucket, i);
return;
}
}
// adds key and value as not in hash table
bucket = add_to_bucket(bucket, key, value);
table->buckets[hash_value] = *bucket;
move_to_front(bucket, bucket->n_elems - 1);
}
/************************************************************************/
void move_to_front(Bucket *bucket, int index){
/*moves recently accessed key & value to the front of bucket*/
char* temp_key;
char* temp_value;
if (bucket->n_elems <= 1 && index >= bucket->n_elems){
return;
}
// swaps position of first element with recently accessed
temp_key = bucket->keys[index];
temp_value = bucket->values[index];
bucket->keys[index] = bucket->keys[0];
bucket->values[index] = bucket->values[0];
bucket->values[0] = temp_value;
bucket->keys[0] = temp_key;
}
/************************************************************************/
char* hash_table_get(HashTable *table, char *key) {
/*Checks if key in hash table and returns value if present*/
char* freq = malloc(60*sizeof(char));
assert(table != NULL);
assert(key != NULL);
int hash_value = xor_hash(key, table->size);
// look for existing key
Bucket *bucket = &table->buckets[hash_value];
for (int i=0; i < bucket->n_elems; i++){
if (equal(bucket->keys[i], key)){
freq = bucket->values[i];
move_to_front(bucket, i);
break;
}
}
//returns value of key if found, else return -1
return freq;
}
/************************************************************************/
bool hash_table_has(HashTable *table, char *key) {
/*Checks if the key exists in hash table*/
assert(table != NULL);
assert(key != NULL);
int hash_value = xor_hash(key, table->size);
// look for existing key
Bucket *bucket = &table->buckets[hash_value];
for (int i=0; i < bucket->n_elems; i++){
if (equal(bucket->keys[i], key)){
return true;
}
}
return false;
}
/* This hash table has been adapted by Abhisha Nirmalathas.
The original hash table it was adapted from was made
by Matt Farrugia <matt.farrugia@unimelb.edu.au, for Design of Algorithms.
This hash table uses separate chaining with an array.
*/
#include <stdbool.h>
typedef struct table HashTable;
//Creates a new hash table of input size
HashTable *new_hash_table(int size);
//Deallocates memory from hash table
void free_hash_table(HashTable *table);
//Inserts new key into hash table with weighted value
void hash_table_put(HashTable *table, char *key, char *value);
//checks if key in hash table and returns value if present
char* hash_table_get(HashTable *table, char *key);
//Checks if the key exists in hash table
bool hash_table_has(HashTable *table, char *key);
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "http-parser.h"
#define MAX_URL_SIZE 60
#define MAX_HEADER_SIZE 300
#define MAX_VERSION_SIZE 10
Request* parse_request(char* request_message){
Request *req = malloc(sizeof *req);
assert(req);
int n_headers = 10;
if (strncmp(request_message, "GET ", 4) == 0){
req->method = GET;
request_message += 4;
printf("Its a get\n");
}
else if (strncmp(request_message, "POST ", 5) == 0){
request_message += 5;
req->method = POST;
printf("Its a post\n");
}
req->url = strtok(request_message, " ");
request_message += strlen(req->url)+1;
req->version = strtok(request_message, "\r\n");
request_message+= strlen(req->version)+2;
req->header = new_hash_table(10);
char header_field_name[MAX_HEADER_SIZE];
char header_value[MAX_HEADER_SIZE];
while(*request_message != '\r' && *request_message != '\n'){
printf("req message first char %d\n", *request_message);
strcpy(header_field_name,strtok(request_message, " "));
printf("header field name: %s\n", header_field_name);
request_message += strcspn(request_message, " ")+1;
strcpy(header_value,strtok(request_message, "\r\n"));
printf("header value: %s\n", header_value);
request_message += strcspn(request_message, "\r\n")+2;
hash_table_put(req->header, header_field_name, header_value);
}
if(*request_message != '\r'||*request_message != '\n'){
req->body = request_message;
}
else{
req->body = "";
}
return req;
}
void free_request(Request* req){
free_hash_table(req->header);
free(req);
}
\ No newline at end of file
#include <stdbool.h>
#include "hashtable.h"
typedef enum
{
GET,
POST,
UNKNOWN
} METHOD;
typedef struct Request {
METHOD method;
char *url;
char *version;
HashTable *header;
char *body;
} Request;
//Creates a new hash table of input size
Request* parse_request(char* request_message);
void free_request(Request* req);
\ No newline at end of file
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "http-parser.h"
#include "http-response.h"
#define MAX_URL_SIZE 60
#define MAX_HEADER_SIZE 300
#define MAX_VERSION_SIZE 10
Response* redirect(Request* request_message){
}
void free_response(Response* resp){
free_hash_table(resp->header);
free(resp);
}
\ No newline at end of file
#include <stdbool.h>
#include "hashtable.h"
typedef struct Response {
int status_code;
char *version;
HashTable *header;
char* phrase;
char *body;
} Response;
//Creates a new hash table of input size
Response *redirect(Request *req);
\ No newline at end of file
......@@ -19,6 +19,7 @@
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "http-parser.h"
// constants
static char const * const HTTP_200_FORMAT = "HTTP/1.1 200 OK\r\n\
......@@ -29,13 +30,7 @@ static int const HTTP_400_LENGTH = 47;
static char const * const HTTP_404 = "HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n";
static int const HTTP_404_LENGTH = 45;
// represents the types of method
typedef enum
{
GET,
POST,
UNKNOWN
} METHOD;
bool get_request(char* buff, int sockfd, char* file_name){
// get the size of the file
......@@ -68,7 +63,7 @@ bool get_request(char* buff, int sockfd, char* file_name){
bool post_request(char *buff, int sockfd, char* file_name){
// locate the username, it is safe to do so in this sample code, but usually the result is expected to be
// copied to another buffer using strcpy or strncpy to ensure that it will not be overwritten.
char * username = strstr(buff, "user=") + 5;
char * username = strcpy(buff, "user=") + 5;
int username_length = strlen(username);
// the length needs to include the ", " before the username
long added_length = username_length + 2;
......@@ -113,6 +108,7 @@ bool post_request(char *buff, int sockfd, char* file_name){
return true;
}
static bool handle_http_request(int sockfd)
{
// try to read the request
......@@ -133,46 +129,28 @@ static bool handle_http_request(int sockfd)
char * curr = buff;
// parse the method
printf("cur is: %s\n\n", curr);
METHOD method = UNKNOWN;
if (strncmp(curr, "GET ", 4) == 0)
{
curr += 4;
method = GET;
}
else if (strncmp(curr, "POST ", 5) == 0)
{
curr += 5;
method = POST;
}
else if (write(sockfd, HTTP_400, HTTP_400_LENGTH) < 0)
{
perror("write");
return false;
}
// sanitise the URI
while (*curr == '.' || *curr == '/')
++curr;
printf("**************THE CURR IS %s\n\n\n", curr);
if (strncmp(curr, "?start=Start", 12) == 0){
Request* req = parse_request(curr);
printf("%s\n%s\n", req->url, req->version);
if (strncmp(req->url, "?start=Start", 12) == 0){
printf("matches start");
if (method == GET){
if (req->method == GET){
get_request(buff,sockfd, "3_first_turn.html");
}
if (req->method == POST){
post_request(buff,sockfd, "7_gameover.html");
}
}
// assume the only valid request URI is "/" but it can be modified to accept more files
else if (*curr == ' ')
if (method == GET)
{
if (strncmp(curr, "start=Start", 11) == 0)
else if (*req->url == '/')
if (req->method == GET)
{
printf("is start start mort");
}
printf("%s\n", curr);
get_request(buff,sockfd, "1_welcome.html");
}
else if (method == POST)
else if (req->method == POST)
{
post_request(buff,sockfd, "2_start.html");
}
......@@ -182,10 +160,11 @@ printf("**************THE CURR IS %s\n\n\n", curr);
// send 404
else if (write(sockfd, HTTP_404, HTTP_404_LENGTH) < 0)
{
free_request(req);
perror("write");
return false;
}
free_request(req);
return true;
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment