From 5e5d25cd75b8c681200d6fe3790f77cb7089093b Mon Sep 17 00:00:00 2001 From: Francesco Date: Sat, 9 Nov 2024 20:43:12 +0100 Subject: [PATCH] initial version of hashmap works --- include/hashmap.h | 5 ++++- include/server.h | 1 - include/utils.h | 1 + notes/hash-table.md | 2 ++ src/hashmap.c | 17 ++++++++++++++++- src/mainc.c | 2 +- src/meson.build | 2 +- src/server.c | 43 ++++++++++++++++++++----------------------- src/utils.c | 6 ++++++ 9 files changed, 51 insertions(+), 28 deletions(-) diff --git a/include/hashmap.h b/include/hashmap.h index 300c4eb..70a1024 100644 --- a/include/hashmap.h +++ b/include/hashmap.h @@ -1,9 +1,10 @@ #ifndef __HASHMAP_C__ #define __HASHMAP_C__ +#include #include -#define HASHMAP_MAX_ITEMS 10000 +#define HASHMAP_MAX_CLIENTS 10000 struct hashmap { int sockfd; @@ -11,6 +12,8 @@ struct hashmap { }; int hash(int sockfd); +void hm_init(struct hashmap *map); void hm_insert(struct hashmap *map, int sockfd, struct sockaddr_storage *sas); +struct hashmap *hm_lookup(struct hashmap *map, int sockfd); #endif \ No newline at end of file diff --git a/include/server.h b/include/server.h index 06dd8c3..ec267e2 100644 --- a/include/server.h +++ b/include/server.h @@ -26,6 +26,5 @@ void epoll_ctl_add(int epfd, int sockfd, uint32_t events); void epoll_ctl_del(int epfd, int sockfd); void setnonblocking(int sockfd); int handle_new_client(int sockfd, struct sockaddr_storage *their_sa, socklen_t *theirsa_size); -void print_client_ip(struct sockaddr_in *sin); #endif diff --git a/include/utils.h b/include/utils.h index 6251400..c52c2fc 100644 --- a/include/utils.h +++ b/include/utils.h @@ -12,5 +12,6 @@ // print every IPs of a hostname void print_ips(const char *hostname, const char *port); +void get_client_ip(struct sockaddr_storage *sa, char *ip); #endif diff --git a/notes/hash-table.md b/notes/hash-table.md index 70c2c64..0cfbd65 100644 --- a/notes/hash-table.md +++ b/notes/hash-table.md @@ -17,3 +17,5 @@ $$ 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 c94c7b7..6b200f4 100644 --- a/src/hashmap.c +++ b/src/hashmap.c @@ -1,9 +1,24 @@ #include "hashmap.h" -int hash(int sockfd) { return sockfd % HASHMAP_MAX_ITEMS; } +int hash(int sockfd) { return sockfd % HASHMAP_MAX_CLIENTS; } + +void hm_init(struct hashmap *map) { + memset(map, 0, sizeof(struct hashmap) * HASHMAP_MAX_CLIENTS); + + for (size_t i = 0; i < HASHMAP_MAX_CLIENTS; ++i) { + map[i].sockfd = -1; + } +} 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 +} + +struct hashmap *hm_lookup(struct hashmap *map, int sockfd) { + int index = hash(sockfd); + return &map[index]; } diff --git a/src/mainc.c b/src/mainc.c index 1994874..0228b95 100644 --- a/src/mainc.c +++ b/src/mainc.c @@ -3,7 +3,7 @@ #include "main.h" int main(int argc, char **argv) { - fprintf(stdout, BOLD GREEN "[client] Running cws...\n" RESET); + fprintf(stdout, BOLD GREEN "[client] Running client...\n" RESET); int ret = test_client_connection(argv[1], argv[2]); if (ret < 0) { diff --git a/src/meson.build b/src/meson.build index 64cd73b..f26f12d 100644 --- a/src/meson.build +++ b/src/meson.build @@ -1,2 +1,2 @@ -server = files('main.c', 'server.c', 'utils.c') +server = files('main.c', 'server.c', 'utils.c', 'hashmap.c') client = files('mainc.c', 'client.c') \ No newline at end of file diff --git a/src/server.c b/src/server.c index 687fbb2..04b083a 100644 --- a/src/server.c +++ b/src/server.c @@ -1,6 +1,8 @@ #include "server.h" #include "colors.h" +#include "hashmap.h" +#include "utils.h" int start_server(const char *hostname, const char *service) { struct addrinfo hints; @@ -50,6 +52,9 @@ void handle_clients(int sockfd) { struct sockaddr_storage their_sa; socklen_t theirsa_size = sizeof their_sa; + struct hashmap clients[HASHMAP_MAX_CLIENTS]; + hm_init(clients); + int epfd = epoll_create1(0); setnonblocking(sockfd); epoll_ctl_add(epfd, sockfd, EPOLLIN | EPOLLET); @@ -70,28 +75,31 @@ void handle_clients(int sockfd) { if (revents[i].data.fd == sockfd) { // new client client_fd = handle_new_client(sockfd, &their_sa, &theirsa_size); + setnonblocking(client_fd); epoll_ctl_add(epfd, client_fd, EPOLLIN); - - print_client_ip((struct sockaddr_in *)&their_sa); + hm_insert(clients, client_fd, &their_sa); int bytes_sent = send(client_fd, msg, msg_len, 0); - fprintf(stdout, BLUE "[server] Sent %d bytes\n" RESET, bytes_sent); + fprintf(stdout, "[server] Sent %d bytes\n", bytes_sent); } else { // incoming data client_fd = revents[i].data.fd; - // fprintf(stdout, "[%d] EPOLLIN\n", client_fd); int bytes_read = recv(client_fd, data, sizeof data, 0); if (bytes_read == 0) { - // client disconnect - fprintf(stdout, BLUE "[server] Client disconnection\n"); + // client disconnected + char ip[INET_ADDRSTRLEN]; + struct hashmap *client = hm_lookup(clients, client_fd); + get_client_ip(&client->sas, ip); + + fprintf(stdout, BLUE "[server] Client (%s) disconnected\n" RESET, ip); epoll_ctl_del(epfd, client_fd); close(client_fd); continue; } - data[strlen(data) - 1] = '\0'; + data[strcspn(data, "\n")] = '\0'; fprintf(stdout, "[server] Bytes read (%d): %s\n", bytes_read, data); if (strcmp(data, "stop") == 0) { fprintf(stdout, GREEN BOLD "[server] Stopping...\n" RESET); @@ -104,6 +112,10 @@ void handle_clients(int sockfd) { free(revents); close(epfd); + + for (size_t i = 0; i < HASHMAP_MAX_CLIENTS; ++i) { + close(clients[i].sockfd); + } } void epoll_ctl_add(int epfd, int sockfd, uint32_t events) { @@ -138,25 +150,10 @@ int handle_new_client(int sockfd, struct sockaddr_storage *their_sa, socklen_t * if (client_fd == -1) { if (errno != EWOULDBLOCK) { - fprintf(stderr, - RED BOLD - "[server] " - "accept(): " - "%s\n" RESET, - strerror(errno)); + fprintf(stderr, RED BOLD "[server] accept(): %s\n" RESET, strerror(errno)); } return -1; } return client_fd; } - -void print_client_ip(struct sockaddr_in *sin) { - char ip[INET_ADDRSTRLEN]; - inet_ntop(AF_INET, &sin->sin_addr, ip, INET_ADDRSTRLEN); - fprintf(stdout, - BLUE - "[server] Incoming " - "client, IP: %s\n" RESET, - ip); -} \ No newline at end of file diff --git a/src/utils.c b/src/utils.c index 7f6b9e8..9769943 100644 --- a/src/utils.c +++ b/src/utils.c @@ -33,4 +33,10 @@ void print_ips(const char *hostname, const char *port) { } freeaddrinfo(res); +} + +void get_client_ip(struct sockaddr_storage *sa, char *ip) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + + inet_ntop(AF_INET, &sin->sin_addr, ip, INET_ADDRSTRLEN); } \ No newline at end of file