From 31f9ddfe9f9441bd575b8e47017cf80d460ebb2e Mon Sep 17 00:00:00 2001 From: Sheldon Lee Date: Sun, 17 Nov 2024 21:15:44 +0800 Subject: [PATCH] Implement queue system to display peers broadcasting --- main.c | 35 +++++++++-- net.c | 184 ++++++++++++++++++++++++++++++++++++++++++++++++--------- net.h | 10 +++- 3 files changed, 194 insertions(+), 35 deletions(-) diff --git a/main.c b/main.c index c45f4b0..fffb48a 100644 --- a/main.c +++ b/main.c @@ -39,6 +39,7 @@ void destroy(); int select_device(SDL_KeyboardEvent* key_event, int max_index); void application_state_to_string(application_state state, char* string); +void* broadcast_t(void* args); void* peer_discovery_t(void* args); SDL_Window* window = NULL; @@ -59,8 +60,8 @@ int main(int argc, char* argv[]) char device_selected_fmt[] = "Device selected: %i"; state state; - //state.application_state = SOCKET_LISTEN; - state.application_state = SELECTING_DEVICE; + state.application_state = SOCKET_LISTEN; + //state.application_state = SELECTING_DEVICE; if (!audio_init(&state.audio)) return 1; state.device_index = -1; state.update_ui = 0; @@ -90,6 +91,9 @@ int main(int argc, char* argv[]) pthread_t peer_discovery_thread; pthread_create(&peer_discovery_thread, NULL, peer_discovery_t, &state); + pthread_t broadcast_thread; + pthread_create(&broadcast_thread, NULL, broadcast_t, &state); + SDL_Event event; while (1) { sem_wait(&state.sem); @@ -116,6 +120,19 @@ int main(int argc, char* argv[]) application_state_to_string(state.application_state, char_buffer); text_texture_load(&state_text_texture, char_buffer); log_message(LOG_INFO, "Update UI State: %s", char_buffer); + + int i = 0; + struct sockaddr_in* peer_addr; + while (net_get_peers(&peer_addr)) { + if (i >= socket_frame.len) break;; + char* ip = inet_ntoa(peer_addr->sin_addr); + int port = ntohs(peer_addr->sin_port); + sprintf(char_buffer, "%s:%i", ip, port); + text_texture_load(&socket_frame.textures[i], char_buffer); + i++; + } + for (; i < socket_frame.len; i++) text_texture_load(&socket_frame.textures[i], ""); + state.update_ui = 0; } @@ -168,6 +185,7 @@ int handle_input(SDL_Event* event, state* state) break; case SDLK_2: log_message(LOG_INFO, "Socket button 2 pressed"); + net_print_peers(); break; } break; @@ -357,13 +375,22 @@ void application_state_to_string(application_state state, char* string) } } +void* broadcast_t(void* args) +{ + while (1) { + net_broadcast(); + sleep(1); + } +} + void* peer_discovery_t(void* args) { state* state = args; while (1) { + int added_client = net_listen_peers(); + int pruned_client = net_prune_peers(); sem_wait(&state->sem); - net_listen_clients(); + state->update_ui = added_client || pruned_client; sem_post(&state->sem); - sleep(1); } } diff --git a/net.c b/net.c index 032de69..2c3fa56 100644 --- a/net.c +++ b/net.c @@ -1,6 +1,8 @@ #include "net.h" #include "log.h" #include +#include +#include typedef struct { struct sockaddr_in addr; @@ -8,6 +10,18 @@ typedef struct { socklen_t addr_len; } net_info; +typedef struct peer_addr_node { + struct sockaddr_in addr; + time_t time_last; + time_t time_elapsed; + struct peer_addr_node* next; +} peer_addr_node; +static peer_addr_node* peer_list = NULL; + +static int peer_list_add(struct sockaddr_in* addr); +static int peer_list_exists(struct sockaddr_in* addr); +static void peer_list_destroy(); + static net_info broadcast_info; static net_info listen_info; static net_info peer_info; @@ -18,7 +32,7 @@ static int init = 0; int net_init(unsigned int port) { PORT = port; - // broadcast socket init + // broadcast socket broadcast_info.socket = socket(AF_INET, SOCK_DGRAM, 0); if (broadcast_info.socket < 0) { log_message(LOG_ERROR, "Error creating broadcast socket"); @@ -36,7 +50,7 @@ int net_init(unsigned int port) broadcast_info.addr_len = sizeof(broadcast_info.addr); - // listen socket init + // listen socket listen_info.socket = socket(AF_INET, SOCK_DGRAM, 0); if (listen_info.socket < 0) { log_message(LOG_ERROR, "Error creating listen socket", strerror(errno)); @@ -71,6 +85,14 @@ int net_init(unsigned int port) return 1; } +void net_destroy() +{ + close(broadcast_info.socket); + close(listen_info.socket); + close(peer_info.socket); + peer_list_destroy(); +} + int net_broadcast() { if (!init) return 0;; @@ -88,59 +110,92 @@ int net_broadcast() return 1; } -int net_listen_clients() +int net_listen_peers() { if (!init) return 0; - if (peer_info.socket >= 0) { - log_message(LOG_WARNING, "Peer socket already created"); - log_message(LOG_INFO, - "Peer socket address:\n%s:%d", - inet_ntoa(peer_info.addr.sin_addr), - ntohs(peer_info.addr.sin_port)); - return 1; - } + net_info broadcast_listen; - peer_info.socket = socket(AF_INET, SOCK_DGRAM, 0); - if (peer_info.socket < 0) { + broadcast_listen.socket = socket(AF_INET, SOCK_DGRAM, 0); + if (broadcast_listen.socket < 0) { log_message(LOG_ERROR, "Error creating listen socket", strerror(errno)); - close(peer_info.socket); + close(broadcast_listen.socket); return 0; } char buffer[64]; - memset(&peer_info.addr, 0, sizeof(peer_info.addr)); - peer_info.addr.sin_family = AF_INET; - peer_info.addr.sin_addr.s_addr = INADDR_ANY; - peer_info.addr.sin_port = htons(PORT); + memset(&broadcast_listen.addr, 0, sizeof(broadcast_listen.addr)); + broadcast_listen.addr.sin_family = AF_INET; + broadcast_listen.addr.sin_addr.s_addr = INADDR_ANY; + broadcast_listen.addr.sin_port = htons(PORT); - peer_info.addr_len = sizeof(peer_info.addr); + broadcast_listen.addr_len = sizeof(broadcast_listen.addr); int retv = recvfrom(listen_info.socket, buffer, sizeof(buffer), 0, - (struct sockaddr*)&peer_info.addr, - &peer_info.addr_len); + (struct sockaddr*)&broadcast_listen.addr, + &broadcast_listen.addr_len); + + close(broadcast_listen.socket); if (retv < 0) { - log_message(LOG_ERROR, "Failed to receive broadcast message: %s", strerror(errno)); - close(peer_info.socket); - peer_info.socket = -1; + if (errno != EAGAIN) + log_message(LOG_ERROR, "Failed to receive broadcast message: %s", strerror(errno)); + close(broadcast_listen.socket); + broadcast_listen.socket = -1; return 0; } buffer[retv] = '\0'; + log_message(LOG_INFO, - "Broadcast message received from:\n%s:%d", - inet_ntoa(peer_info.addr.sin_addr), - ntohs(peer_info.addr.sin_port)); - log_message(LOG_INFO, "%s", buffer); + "Broadcast message received from:\n%s:%d\n%s", + inet_ntoa(broadcast_listen.addr.sin_addr), + ntohs(broadcast_listen.addr.sin_port), + buffer); + + retv = peer_list_exists(&broadcast_listen.addr); + if (retv) return 0; + + peer_list_add(&broadcast_listen.addr); return 1; } -int net_send() +int net_prune_peers() { if (!init) return 0; + if (!peer_list) return 0; + int pruned = 0; + peer_addr_node* node = peer_list; + peer_addr_node* last_node = NULL; + while (node) { + peer_addr_node* next_node = node->next; + + node->time_elapsed += time(NULL) - node->time_last; + node->time_last = time(NULL); + + if (node->time_elapsed < CLIENT_MAX_TIME) { + last_node = node; + goto next; + } + + pruned = 1; + free(node); + if (node == peer_list) + peer_list = next_node; + if (last_node != NULL) + last_node->next = next_node; +next: + node = next_node; + } + return pruned; +} + +int net_send(void* buffer, size_t size) +{ + if (!init) return 0; + if (peer_info.socket < 0) return 0; return 1; } @@ -149,3 +204,74 @@ int net_receive() if (!init) return 0; return 1; } + +void net_print_peers() +{ + if (!peer_list) return; + peer_addr_node* node = peer_list; + while (node) { + log_message(LOG_INFO, + "Peers :\n%s:%d", + inet_ntoa(node->addr.sin_addr), + ntohs(node->addr.sin_port)); + node = node->next; + } +} + +int net_get_peers(struct sockaddr_in** peer_addr) +{ + if (!peer_list) return 0; + static peer_addr_node* node = NULL; + static int done = 0; + + if (done) { + done = 0; + return 0; + } + + if (!node) node = peer_list; + *peer_addr = &node->addr; + + if (!node->next) done = 1; + node = node->next; + return 1; +} + +static int peer_list_add(struct sockaddr_in* addr) +{ + peer_addr_node* new_node = malloc(sizeof(peer_addr_node)); + size_t size = sizeof(struct sockaddr_in); + memset(&new_node->addr, 0, sizeof(size)); + memcpy(&new_node->addr, addr, sizeof(size)); + new_node->time_last = time(NULL); + new_node->time_elapsed = 0; + new_node->next = peer_list ? peer_list : NULL; + peer_list = new_node; + return 1; +} + +static int peer_list_exists(struct sockaddr_in* addr) +{ + if (!peer_list) return 0; + peer_addr_node* node = peer_list; + while (node) { + int address_match = addr->sin_addr.s_addr == node->addr.sin_addr.s_addr; + int port_match = addr->sin_port == node->addr.sin_port; + if (address_match && port_match) { + node->time_elapsed = 0; + return 1; + } + node = node->next; + } + return 0; +} + +static void peer_list_destroy() +{ + peer_addr_node* node = peer_list; + while (node) { + peer_addr_node* next_node = node->next; + free(node); + node = next_node; + } +} diff --git a/net.h b/net.h index 19cdcda..bad0452 100644 --- a/net.h +++ b/net.h @@ -7,10 +7,16 @@ #include #include +#define CLIENT_MAX_TIME 4 + int net_init(unsigned int port); +void net_destroy(); int net_broadcast(); -int net_listen_clients(); -int net_send(); +int net_listen_peers(); +int net_prune_peers(); +int net_send(void* buffer, size_t size); int net_receive(); +void net_print_peers(); +int net_get_peers(struct sockaddr_in** peer_addr); #endif