#include "net.h" #include "log.h" #include #include #include typedef struct { struct sockaddr_in addr; int socket; 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; static int PORT; static int init = 0; int net_init(unsigned int port) { PORT = port; // broadcast socket broadcast_info.socket = socket(AF_INET, SOCK_DGRAM, 0); if (broadcast_info.socket < 0) { log_message(LOG_ERROR, "Error creating broadcast socket"); close(broadcast_info.socket); return 0; } int broadcast_enable = 1; if (setsockopt(broadcast_info.socket, SOL_SOCKET, SO_BROADCAST, &broadcast_enable, sizeof(broadcast_enable)) < 0) return 0; memset(&broadcast_info.addr, 0, sizeof(broadcast_info.addr)); broadcast_info.addr.sin_family = AF_INET; broadcast_info.addr.sin_addr.s_addr = inet_addr("255.255.255.255"); broadcast_info.addr.sin_port = htons(port); broadcast_info.addr_len = sizeof(broadcast_info.addr); // 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)); close(listen_info.socket); return 0; } int reuse_enable = 1; if (setsockopt(listen_info.socket, SOL_SOCKET, SO_REUSEADDR, &reuse_enable, sizeof(reuse_enable)) < 0) return 0; memset(&listen_info.addr, 0, sizeof(listen_info.addr)); listen_info.addr.sin_family = AF_INET; listen_info.addr.sin_addr.s_addr = INADDR_BROADCAST; listen_info.addr.sin_port = htons(port); listen_info.addr_len =sizeof(listen_info.addr); struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 100000; setsockopt(listen_info.socket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); if (bind(listen_info.socket, (const struct sockaddr*)&listen_info.addr, sizeof(listen_info.addr)) < 0) { log_message(LOG_ERROR, "Socket bind failed: %s", strerror(errno)); close(listen_info.socket); return 0; } peer_info.socket = -1; init = 1; 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;; const char* message = "broadcast message"; int retv = sendto(broadcast_info.socket, message, strlen(message), 0, (struct sockaddr*)&broadcast_info.addr, broadcast_info.addr_len); if (retv < 0) { log_message(LOG_ERROR, "Failed to send broadcast message: %s", strerror(errno)); log_message(LOG_ERROR, "retv: %i", retv); return 0; } log_message(LOG_INFO, "Broadcast message sent"); return 1; } int net_listen_peers() { if (!init) return 0; net_info broadcast_listen; 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(broadcast_listen.socket); return 0; } char buffer[64]; 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); broadcast_listen.addr_len = sizeof(broadcast_listen.addr); int retv = recvfrom(listen_info.socket, buffer, sizeof(buffer), 0, (struct sockaddr*)&broadcast_listen.addr, &broadcast_listen.addr_len); close(broadcast_listen.socket); if (retv < 0) { 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\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_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; } 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; } }