diff --git a/include/colors.h b/include/colors.h index cc5e36f..2f6bd2d 100644 --- a/include/colors.h +++ b/include/colors.h @@ -1,6 +1,7 @@ #ifndef __COLORS_H__ #define __COLORS_H__ +/* ANSI color escape sequences */ #define RED "\033[31m" #define GREEN "\033[32m" #define YELLOW "\033[33m" diff --git a/include/hashmap.h b/include/hashmap.h index 70a1024..fc9ae03 100644 --- a/include/hashmap.h +++ b/include/hashmap.h @@ -1,19 +1,32 @@ #ifndef __HASHMAP_C__ #define __HASHMAP_C__ +#include #include #include -#define HASHMAP_MAX_CLIENTS 10000 +/* Each process on Linux can have a maximum of 1024 open file descriptors */ +#define HASHMAP_MAX_CLIENTS 1024 struct hashmap { int sockfd; struct sockaddr_storage sas; + struct hashmap *next; }; +/* Calculate the hash code of a file descriptor */ int hash(int sockfd); + +/* Initialize the hash map */ void hm_init(struct hashmap *map); + +/* Insert a new key in the hash map */ void hm_insert(struct hashmap *map, int sockfd, struct sockaddr_storage *sas); + +/* Search for a key in the hash map */ struct hashmap *hm_lookup(struct hashmap *map, int sockfd); +/* Clean up the hash map */ +void hm_free(struct hashmap *map); + #endif \ No newline at end of file diff --git a/include/server.h b/include/server.h index ec267e2..0e0deb7 100644 --- a/include/server.h +++ b/include/server.h @@ -14,17 +14,76 @@ #include #include +/* On which port the server will run */ #define PORT 3030 + +/* Clients max queue */ #define BACKLOG 10 + +/* Size of the epoll_event array */ #define EPOLL_MAXEVENTS 10 + +/* Wait forever (epoll_wait()) */ #define EPOLL_TIMEOUT -1 +/** + * @brief Runs the server + * + * @param hostname[in] The hostname of the server (default localhost, it could be NULL) + * @param service[in] The service (found in /etc/services) or the port where to run + * @return int 0 on success, -1 on error + */ int start_server(const char *hostname, const char *service); + +/** + * @brief Sets the up hints object + * + * @param hints[out] The hints addrinfo + * @param len[in] The length of hints + * @param hostname[in] The hostname (could be NULL) + */ void setup_hints(struct addrinfo *hints, size_t len, const char *hostname); + +/** + * @brief Main server loop + * + * @param sockfd[in,out] Socket of the commincation endpoint + */ void handle_clients(int sockfd); + +/** + * @brief Adds a file descriptor to the interest list + * + * @param epfd[in] epoll file descriptor + * @param sockfd[in] The file descriptor to watch + * @param events[in] The events to follow + */ void epoll_ctl_add(int epfd, int sockfd, uint32_t events); + +/* Remove a file descriptor from the interest list */ +/** + * @brief Removes a file descriptor from the interest list + * + * @param epfd[in] epoll file descriptor + * @param sockfd[in] The file descriptor to remove + */ void epoll_ctl_del(int epfd, int sockfd); + +/** + * @brief Makes a file descriptor non blocking + * + * @param sockfd[in] The file descriptor to make non blocking + */ void setnonblocking(int sockfd); + +/** + * @brief Handles the new client + * + * @param sockfd[in] Server's file descriptor + * @param their_sa[out] Populates the struct with client's information + * @param theirsa_size[in] Size of the struct + * @return int Returns -1 on error or the file descriptor on success + */ int handle_new_client(int sockfd, struct sockaddr_storage *their_sa, socklen_t *theirsa_size); #endif diff --git a/include/utils.h b/include/utils.h index c52c2fc..78f395a 100644 --- a/include/utils.h +++ b/include/utils.h @@ -10,8 +10,20 @@ #include #include -// print every IPs of a hostname +/** + * @brief Prints each IP address associated with a host + * + * @param hostname[in] Hostname + * @param port[in] Port + */ void print_ips(const char *hostname, const char *port); + +/** + * @brief Retrieves the client ip from the sockaddr_storage and put it in the ip str + * + * @param sa[in] The sockaddr_storage of the client + * @param ip[out] The IP of the client + */ void get_client_ip(struct sockaddr_storage *sa, char *ip); #endif diff --git a/notes/advanced-techniques.md b/notes/advanced-techniques.md index e1029a1..82fe575 100644 --- a/notes/advanced-techniques.md +++ b/notes/advanced-techniques.md @@ -85,5 +85,3 @@ union epoll_data { uint64_t u64; }; ``` - -**TODO: improve the notes for epoll()** diff --git a/notes/hash-table.md b/notes/hash-table.md index 0cfbd65..70c2c64 100644 --- a/notes/hash-table.md +++ b/notes/hash-table.md @@ -17,5 +17,3 @@ $$ hash(\text{key}) = \text{key} \mod \text{table\_dim} $$ - String keys: $$ hash(key) = \sum_{i=0}^{len(key) - 1} ascii\_value(key[i]) * prime\_number$$ - -**TODO** \ No newline at end of file diff --git a/src/hashmap.c b/src/hashmap.c index 6b200f4..f0e2284 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -7,18 +7,41 @@ void hm_init(struct hashmap *map) { for (size_t i = 0; i < HASHMAP_MAX_CLIENTS; ++i) { map[i].sockfd = -1; + map[i].next = NULL; } } void hm_insert(struct hashmap *map, int sockfd, struct sockaddr_storage *sas) { int index = hash(sockfd); - map[index].sockfd = sockfd; - map[index].sas = *sas; - // I should check the collisions + if (map[index].sockfd == -1) { + map[index].sockfd = sockfd; + map[index].sas = *sas; + } else { + /* Go through the linked list and append the new item */ + struct hashmap *p; + for (p = &map[index]; p->next != NULL; p = p->next); + struct hashmap *new = malloc(sizeof(struct hashmap)); + new->sockfd = sockfd; + new->sas = *sas; + new->next = NULL; + + p->next = new; + } } struct hashmap *hm_lookup(struct hashmap *map, int sockfd) { int index = hash(sockfd); - return &map[index]; + + if (map[index].sockfd != sockfd) { + struct hashmap *p; + for (p = map[index].next; p->sockfd != sockfd; p = p->next); + return p; + } else { + return &map[index]; + } + + return NULL; } + +void hm_free(struct hashmap *map) {}