diff --git a/lib/helpers.c b/lib/helpers.c index 3994e44..ac3ffa2 100644 --- a/lib/helpers.c +++ b/lib/helpers.c @@ -35,7 +35,7 @@ void enable_echo_broadcast(void) { * Function based on this snippet: * https://codereview.stackexchange.com/a/58107 */ -void search_for_neighbors(void) { +void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, uint16_t port) { // Broadcasts ping if (system("ping -b 10.255.255.255 -c 3 > /dev/null") < 0) { perror("Couldn't broadcast echo."); @@ -58,14 +58,94 @@ void search_for_neighbors(void) { // Extracts IP addresses found in the file char ipAddr[ARP_BUFFER_LEN]; + char **neighbors_ips = (char **) malloc(sizeof(char *)); + if (!neighbors_ips) { + perror("Unable to allocate memory for neighbor IP."); + exit(EXIT_FAILURE); + } + int count = 0; while (1 == fscanf(arpCache, ARP_LINE_FORMAT, ipAddr)) { - printf("%03d: [%s]\n", ++count, ipAddr); + ++count; + if (count > 1){ + char **r_neighbors_ips = realloc(neighbors_ips, count * sizeof(char *)); + if (!r_neighbors_ips) { + free(r_neighbors_ips); + perror("Unable to reallocate memory for neighbor IP."); + exit(EXIT_FAILURE); + } + + neighbors_ips = r_neighbors_ips; + } + + neighbors_ips[count - 1] = (char *) malloc(ARP_BUFFER_LEN * sizeof(char)); + strcpy(neighbors_ips[count - 1], ipAddr); + } + + // Allocates memory for the new neighbors structs + if (!(*num_neighbors)) { + // Neighbors array came empty + (*neighbors) = (node_handle_t *) malloc(count * sizeof(node_handle_t)); + if (!neighbors_ips) { + perror("Unable to allocate memory for nodes."); + exit(EXIT_FAILURE); + } + } else { + node_handle_t *r_neighbors = realloc((*neighbors), count * sizeof(node_handle_t)); + if (!r_neighbors) { + free(r_neighbors); + perror("Unable to reallocate memory for nodes."); + exit(EXIT_FAILURE); + } + + (*neighbors) = r_neighbors; + } + + // Adds new event timestamps to neighbors structs + for (uint8_t i = 0; i < count; ++i) { + bool found_flag = false; + + for (uint8_t j = 0; j < (*num_neighbors); ++j) { + if (!strcmp(inet_ntoa(node_get_addr((*neighbors)[j]).sin_addr), + neighbors_ips[i])) { + bool node_alive = check_node_alive(neighbors_ips[i]); + node_add_timestamp((*neighbors)[i], time(NULL), node_alive); + + found_flag = true; + break; + } + } + + if (!found_flag) { + // New node found! + printf("Adding %s\n", neighbors_ips[i]); + struct sockaddr_in peer_name; + init_sockaddr(&peer_name, neighbors_ips[i], port); + (*neighbors)[(*num_neighbors)++] = node_init(peer_name); + } + } + + if (!((*num_neighbors) == count)) { + (*num_neighbors) = count; } fclose(arpCache); } +bool check_node_alive(const char *ipv4) { + char command[64]; + + snprintf(command, 64, "ping %s -c 1 -W 1 | grep \"1 received\" > /dev/null", ipv4); + + int call_res = system(command); + if (call_res < 0) { + perror("Couldn't ping node."); + exit(EXIT_FAILURE); + } + + return call_res == 0; +} + /* * Function based on this example: * https://www.gnu.org/software/libc/manual/html_node/Inet-Example.html#Inet-Example @@ -100,9 +180,8 @@ int create_socket_and_listen(uint16_t port, uint8_t backlog_size) { return in_sock; } -void send_message(const char *ipv4, uint16_t port, const char *message) { +void send_message(struct sockaddr_in peer_name, const char *message) { int out_sock; - struct sockaddr_in peer_name; // Creates the socket out_sock = socket(PF_INET, SOCK_STREAM, 0); @@ -112,7 +191,6 @@ void send_message(const char *ipv4, uint16_t port, const char *message) { } // Connects to the peer - init_sockaddr(&peer_name, ipv4, port); if (connect(out_sock, (struct sockaddr *) &peer_name, sizeof(peer_name))) { printf("Couldn't connect to the peer.\n"); } else { diff --git a/lib/helpers.h b/lib/helpers.h index 64195af..ee0ac7c 100644 --- a/lib/helpers.h +++ b/lib/helpers.h @@ -14,6 +14,9 @@ #include #include #include +#include + +#include "node.h" // Macros to turn a numeric macro into a string literal #define xstr(s) str(s) @@ -23,6 +26,7 @@ #define ARP_CACHE "/proc/net/arp" #define ARP_STRING_LEN 1023 #define ARP_BUFFER_LEN (ARP_STRING_LEN + 1) +#define PING_BUFFER_LEN 1024 // Format for fscanf() to read the 1st field of ARP #define ARP_LINE_FORMAT "%" xstr(ARP_STRING_LEN) "s %*s %*s %*s %*s %*s" @@ -31,11 +35,13 @@ void set_timer_and_handler(void (*handler)(int), long int timer_interval); void enable_echo_broadcast(void); -void search_for_neighbors(void); +void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, uint16_t port); + +bool check_node_alive(const char *ipv4); int create_socket_and_listen(uint16_t port, uint8_t backlog_size); -void send_message(const char *ipv4, uint16_t port, const char *message); +void send_message(struct sockaddr_in peer_name, const char *message); void accept_connection(int sock, struct sockaddr_in *client_name, fd_set *active_fd_set); diff --git a/lib/node.c b/lib/node.c index 9157860..6d9bf19 100644 --- a/lib/node.c +++ b/lib/node.c @@ -5,8 +5,6 @@ #include "node.h" -//enum node_status { NODE_INITIALIAZED, NODE_PRESENT, NODE_GONE }; - // Defines the node structure struct node_t { struct sockaddr_in addr; diff --git a/src/zaqar.c b/src/zaqar.c index 2e7a5ab..999a952 100644 --- a/src/zaqar.c +++ b/src/zaqar.c @@ -8,13 +8,17 @@ int main(void) { int in_sock; fd_set active_fd_set, read_fd_set; struct sockaddr_in peer_name; + node_handle_t *neighbors; + uint16_t num_neighbors = 0; - // Sets a timer and handler to produce interrupts for sending messages - set_timer_and_handler(handle_alarm, TIMER_INTERVAL); + // Enables echo broadcast pings + enable_echo_broadcast(); // Searches network for neighbors - enable_echo_broadcast(); - search_for_neighbors(); + search_for_neighbors(&neighbors, &num_neighbors, PORT); + + // Sets a timer and handler to produce interrupts for sending messages + set_timer_and_handler(handle_alarm, TIMER_INTERVAL); // Creates a socket and sets it up to accept connections in_sock = create_socket_and_listen(PORT, BACKLOG_SIZE); @@ -28,7 +32,14 @@ int main(void) { while (1) { if (sigalrm_flag) { // It's time to send a message! - send_message("10.0.82.61", PORT, MESSAGE); + + search_for_neighbors(&neighbors, &num_neighbors, PORT); + + for (uint8_t i = 0; i < num_neighbors; ++i) { + if (node_get_status(neighbors[i]) == NODE_PRESENT) { + send_message(node_get_addr(neighbors[i]), MESSAGE); + } + } sigalrm_flag = false; } diff --git a/src/zaqar.h b/src/zaqar.h index 41822ef..daee30e 100644 --- a/src/zaqar.h +++ b/src/zaqar.h @@ -16,6 +16,7 @@ #include #include "helpers.h" +#include "node.h" #define TIMER_INTERVAL 10 #define PORT 5000