add header parser and fix hash map
This commit is contained in:
@@ -31,7 +31,6 @@ And then open the `docs/html/index.html`.
|
||||
|
||||
## Roadmap
|
||||
|
||||
- Request parser
|
||||
- Implement Keep-Alive
|
||||
- Support for virtual hosting
|
||||
- HTTPS support with TLS
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#ifndef CWS_HTTP_H
|
||||
#define CWS_HTTP_H
|
||||
|
||||
#include "utils/hashmap.h"
|
||||
|
||||
#define CWS_WWW "../www" /**< Directory used to get html files */
|
||||
/** In the future I'll move conf stuff under a server struct, I can skip just because I want something that works */
|
||||
#define CWS_HTTP_LOCATION_LEN 512
|
||||
#define CWS_HTTP_LOCATION_PATH_LEN 1024
|
||||
#define CWS_HTTP_VERSION_LEN 8
|
||||
#define CWS_HTTP_USER_AGENT_LEN 1024
|
||||
#define CWS_HTTP_HOST_LEN 1024
|
||||
|
||||
typedef enum cws_http_method_t {
|
||||
CWS_HTTP_GET, /**< GET method */
|
||||
@@ -27,8 +27,7 @@ typedef struct cws_http_t {
|
||||
char location[CWS_HTTP_LOCATION_LEN]; /**< Resource requested */
|
||||
char location_path[CWS_HTTP_LOCATION_PATH_LEN]; /**< Full resource path */
|
||||
char http_version[CWS_HTTP_VERSION_LEN]; /**< HTTP version */
|
||||
char user_agent[CWS_HTTP_USER_AGENT_LEN]; /**< User-Agent */
|
||||
char host[CWS_HTTP_HOST_LEN]; /**< Host */
|
||||
cws_hashmap *headers; /**< Headers hash map */
|
||||
} cws_http;
|
||||
/* Connection */
|
||||
/* Accept-Encoding */
|
||||
|
||||
@@ -25,9 +25,11 @@ void cws_utils_print_ips(const char *hostname, const char *port);
|
||||
void cws_utils_get_client_ip(struct sockaddr_storage *sa, char *ip);
|
||||
|
||||
/* TODO: add docs */
|
||||
char *cws_strip(char *str);
|
||||
|
||||
/* Functions used for hash maps */
|
||||
int my_hash_fn(void *key);
|
||||
bool my_equal_fn(void *a, void *b);
|
||||
void my_free_value_fn(void *value);
|
||||
int my_str_hash_fn(void *key);
|
||||
bool my_str_equal_fn(void *a, void *b);
|
||||
void my_str_free_fn(void *value);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "utils/colors.h"
|
||||
#include "utils/utils.h"
|
||||
|
||||
cws_http *cws_http_parse(char *request_str, int sockfd) {
|
||||
cws_http *request = malloc(sizeof(cws_http));
|
||||
@@ -22,7 +23,7 @@ cws_http *cws_http_parse(char *request_str, int sockfd) {
|
||||
if (pch == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
CWS_LOG_DEBUG("[client::http] method: %s", pch);
|
||||
CWS_LOG_DEBUG("[http] method: %s", pch);
|
||||
cws_http_parse_method(request, pch);
|
||||
|
||||
/* Parse location */
|
||||
@@ -30,29 +31,53 @@ cws_http *cws_http_parse(char *request_str, int sockfd) {
|
||||
if (pch == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
CWS_LOG_DEBUG("[client::http] location: %s", pch);
|
||||
CWS_LOG_DEBUG("[http] location: %s", pch);
|
||||
strncpy(request->location, pch, CWS_HTTP_LOCATION_LEN);
|
||||
|
||||
/* Parse location path */
|
||||
/* Adjust location path */
|
||||
if (strcmp(request->location, "/") == 0) {
|
||||
snprintf(request->location_path, CWS_HTTP_LOCATION_PATH_LEN, "%s/index.html", CWS_WWW);
|
||||
} else {
|
||||
snprintf(request->location_path, CWS_HTTP_LOCATION_PATH_LEN, "%s%s", CWS_WWW, request->location);
|
||||
}
|
||||
CWS_LOG_DEBUG("[client::http] location path: %s", request->location_path);
|
||||
CWS_LOG_DEBUG("[http] location path: %s", request->location_path);
|
||||
|
||||
/* Parse HTTP version */
|
||||
pch = strtok(NULL, " \r\n");
|
||||
if (pch == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
CWS_LOG_DEBUG("[client::http] version: %s", pch);
|
||||
CWS_LOG_DEBUG("[http] version: %s", pch);
|
||||
strncpy(request->http_version, pch, CWS_HTTP_VERSION_LEN);
|
||||
|
||||
/* Parse other stuff... */
|
||||
/* Parse until a \r\n and store the header with its value
|
||||
* into a hashmap
|
||||
*/
|
||||
/* Parse headers until a \r\n */
|
||||
request->headers = cws_hm_init(my_str_hash_fn, my_str_equal_fn, my_str_free_fn, my_str_free_fn);
|
||||
char *header_colon;
|
||||
while (pch) {
|
||||
/* Get header line */
|
||||
pch = strtok(NULL, "\r\n");
|
||||
if (pch == NULL) {
|
||||
break;
|
||||
}
|
||||
/* Find ":" */
|
||||
header_colon = strchr(pch, ':');
|
||||
if (header_colon != NULL) {
|
||||
*header_colon = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Header key */
|
||||
char *hkey = pch;
|
||||
char *hkey_dup = strdup(hkey);
|
||||
/* Header value (starting from ": ") */
|
||||
char *hvalue = header_colon + 2;
|
||||
char *hvalue_dup = strdup(hvalue);
|
||||
|
||||
cws_hm_set(request->headers, hkey_dup, hvalue_dup);
|
||||
}
|
||||
|
||||
/* Parse body */
|
||||
|
||||
return request;
|
||||
}
|
||||
@@ -178,4 +203,7 @@ void cws_http_send_not_found(cws_http *request) {
|
||||
send(request->sockfd, response, response_len, 0);
|
||||
}
|
||||
|
||||
void cws_http_free(cws_http *request) { free(request); }
|
||||
void cws_http_free(cws_http *request) {
|
||||
cws_hm_free(request->headers);
|
||||
free(request);
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ void cws_server_loop(int sockfd) {
|
||||
struct sockaddr_storage their_sa;
|
||||
socklen_t theirsa_size = sizeof their_sa;
|
||||
|
||||
cws_hashmap *clients = cws_hm_init(my_hash_fn, my_equal_fn, NULL, NULL);
|
||||
cws_hashmap *clients = cws_hm_init(my_str_hash_fn, my_str_equal_fn, NULL, NULL);
|
||||
|
||||
int epfd = epoll_create1(0);
|
||||
cws_fd_set_nonblocking(sockfd);
|
||||
|
||||
@@ -58,7 +58,7 @@ void cws_hm_free(cws_hashmap *hashmap) {
|
||||
|
||||
bool cws_hm_set(cws_hashmap *hashmap, void *key, void *value) {
|
||||
/* Get hash index */
|
||||
int index = hashmap->hash_fn(key);
|
||||
int index = hashmap->hash_fn(key) % CWS_HASHMAP_SIZE;
|
||||
cws_bucket *bucket = &hashmap->map[index];
|
||||
|
||||
/* Check if the key at index is empty */
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "utils/utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@@ -45,7 +46,21 @@ void cws_utils_get_client_ip(struct sockaddr_storage *sa, char *ip) {
|
||||
inet_ntop(AF_INET, &sin->sin_addr, ip, INET_ADDRSTRLEN);
|
||||
}
|
||||
|
||||
int my_hash_fn(void *key) {
|
||||
char *cws_strip(char *str) {
|
||||
char *end;
|
||||
|
||||
while (isspace((int)*str)) str++;
|
||||
|
||||
if (*str == 0) return str;
|
||||
|
||||
end = str + strlen(str) - 1;
|
||||
while (end > str && isspace((int)*end)) end--;
|
||||
*(end + 1) = '\0';
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
int my_str_hash_fn(void *key) {
|
||||
char *key_str = (char *)key;
|
||||
size_t key_len = strlen(key_str);
|
||||
|
||||
@@ -58,7 +73,7 @@ int my_hash_fn(void *key) {
|
||||
return total % 2069;
|
||||
}
|
||||
|
||||
bool my_equal_fn(void *a, void *b) {
|
||||
bool my_str_equal_fn(void *a, void *b) {
|
||||
if (strcmp((char *)a, (char *)b) == 0) {
|
||||
return true;
|
||||
}
|
||||
@@ -66,4 +81,4 @@ bool my_equal_fn(void *a, void *b) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void my_free_str_fn(void *value) { free(value); }
|
||||
void my_str_free_fn(void *value) { free(value); }
|
||||
|
||||
Reference in New Issue
Block a user