diff --git a/lib/circ_buff.c b/lib/circ_buff.c index 789766e..f926acf 100644 --- a/lib/circ_buff.c +++ b/lib/circ_buff.c @@ -40,140 +40,6 @@ unit_static void retreat_pointer(cbuf_handle_t cbuf) { cbuf->tail = (cbuf->tail + 1) % cbuf->max; } -// Compares the buffers cbuf1 and cbuf2. Elements present on cbuf1 that do not -// exist on cbuf2 are added to the array add2, elements present on cbuf2 that do -// not exist on cbuf1 are added to the array add1. -// Both buffers must be ordered on the same way! -unit_static void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, - char ***add1, char ***add2) { - assert(cbuf1 && cbuf2 && - (circ_buf_element_size(cbuf1) == circ_buf_element_size(cbuf2)) && - (circ_buf_capacity(cbuf1) == circ_buf_capacity(cbuf2))); - - // Initializes the diff arrays - (*add1) = (char **) malloc(circ_buf_capacity(cbuf2) * sizeof(char *)); - (*add2) = (char **) malloc(circ_buf_capacity(cbuf1) * sizeof(char *)); - - char *curr_str1 = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); - char *curr_str2 = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); - /*uint8_t diff_array_index = 0; - for (uint8_t i = 0; i < circ_buf_size(cbuf1); ++i) { - // Reads current element of cbuf1 - circ_buf_read(cbuf1, i, curr_str1); - bool element_exists = false; - - for (uint8_t j = 0; j < circ_buf_size(cbuf2); ++j) { - circ_buf_read(cbuf2, j, curr_str2); - // Checks against cbuf2 elements - if (!strcmp(curr_str2, curr_str1)) { - element_exists = true; - break; - } - } - - if (!element_exists) { - (*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); - strcpy((*add2)[diff_array_index], curr_str1); - ++diff_array_index; - } - } - - (*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); - strcpy((*add1)[diff_array_index], EOB); - - diff_array_index = 0; - for (uint8_t i = 0; i < circ_buf_size(cbuf2); ++i) { - // Reads current element of cbuf2 - circ_buf_read(cbuf2, i, curr_str2); - bool element_exists = false; - - for (uint8_t j = 0; j < circ_buf_size(cbuf1); ++j) { - circ_buf_read(cbuf1, j, curr_str1); - // Checks against cbuf1 elements - if (!strcmp(curr_str1, curr_str2)) { - element_exists = true; - break; - } - } - - if (!element_exists) { - (*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); - strcpy((*add1)[diff_array_index], curr_str2); - ++diff_array_index; - } - } - - (*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); - strcpy((*add2)[diff_array_index], EOB);*/ - - - - uint8_t cbuf1_idx = 0, cbuf2_idx = 0, add1_arr_idx = 0, add2_arr_idx = 0; - while ((cbuf1_idx < circ_buf_size(cbuf1)) && - (cbuf2_idx < circ_buf_size(cbuf2))) { - circ_buf_read(cbuf1, cbuf1_idx, curr_str1); - circ_buf_read(cbuf2, cbuf2_idx, curr_str2); - - int strcmp_res = strcmp(curr_str1, curr_str2); - if (!strcmp_res) { - ++cbuf1_idx; - ++cbuf2_idx; - } else { // TODO: change the inner comparisons (strtok etc) - if (strcmp_res < 0) { - (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); - strcpy((*add2)[add2_arr_idx], curr_str1); - ++add2_arr_idx; - ++cbuf1_idx; - } - else if (strcmp_res > 0) { - (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); - strcpy((*add1)[add1_arr_idx], curr_str2); - ++add1_arr_idx; - ++cbuf2_idx; - } - } - } - - while (cbuf1_idx < circ_buf_size(cbuf1)) { - (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); - circ_buf_read(cbuf1, cbuf1_idx, curr_str1); - strcpy((*add2)[add2_arr_idx], curr_str1); - ++add2_arr_idx; - ++cbuf1_idx; - } - - while (cbuf2_idx < circ_buf_size(cbuf2)) { - (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); - circ_buf_read(cbuf2, cbuf2_idx, curr_str2); - strcpy((*add1)[add1_arr_idx], curr_str2); - ++add1_arr_idx; - ++cbuf2_idx; - } - - (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); - strcpy((*add1)[add1_arr_idx], EOB); - - (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); - strcpy((*add2)[add2_arr_idx], EOB); - - free(curr_str1); - free(curr_str2); - - /*uint8_t i = 0; - printf("add1:\n"); - while (strcmp((*add1)[i], EOB)) { - printf("%s\n", (*add1)[i]); - ++i; - } - - i = 0; - printf("add2:\n"); - while (strcmp((*add2)[i], EOB)) { - printf("%s\n", (*add2)[i]); - ++i; - }*/ -} - // APIs cbuf_handle_t circ_buf_init(char **buffer, size_t size, size_t element_size) { @@ -303,6 +169,136 @@ int circ_buf_read(cbuf_handle_t cbuf, size_t position, char *data) { return r; } +void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, + char ***add1, char ***add2) { + assert(cbuf1 && cbuf2 && + (circ_buf_element_size(cbuf1) == circ_buf_element_size(cbuf2)) && + (circ_buf_capacity(cbuf1) == circ_buf_capacity(cbuf2))); + + // Initializes the diff arrays + (*add1) = (char **) malloc(circ_buf_capacity(cbuf2) * sizeof(char *)); + (*add2) = (char **) malloc(circ_buf_capacity(cbuf1) * sizeof(char *)); + + char *curr_str1 = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); + char *curr_str2 = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); + /*uint8_t diff_array_index = 0; + for (uint8_t i = 0; i < circ_buf_size(cbuf1); ++i) { + // Reads current element of cbuf1 + circ_buf_read(cbuf1, i, curr_str1); + bool element_exists = false; + + for (uint8_t j = 0; j < circ_buf_size(cbuf2); ++j) { + circ_buf_read(cbuf2, j, curr_str2); + // Checks against cbuf2 elements + if (!strcmp(curr_str2, curr_str1)) { + element_exists = true; + break; + } + } + + if (!element_exists) { + (*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); + strcpy((*add2)[diff_array_index], curr_str1); + ++diff_array_index; + } + } + + (*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); + strcpy((*add1)[diff_array_index], EOB); + + diff_array_index = 0; + for (uint8_t i = 0; i < circ_buf_size(cbuf2); ++i) { + // Reads current element of cbuf2 + circ_buf_read(cbuf2, i, curr_str2); + bool element_exists = false; + + for (uint8_t j = 0; j < circ_buf_size(cbuf1); ++j) { + circ_buf_read(cbuf1, j, curr_str1); + // Checks against cbuf1 elements + if (!strcmp(curr_str1, curr_str2)) { + element_exists = true; + break; + } + } + + if (!element_exists) { + (*add1)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); + strcpy((*add1)[diff_array_index], curr_str2); + ++diff_array_index; + } + } + + (*add2)[diff_array_index] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); + strcpy((*add2)[diff_array_index], EOB);*/ + + + + uint8_t cbuf1_idx = 0, cbuf2_idx = 0, add1_arr_idx = 0, add2_arr_idx = 0; + while ((cbuf1_idx < circ_buf_size(cbuf1)) && + (cbuf2_idx < circ_buf_size(cbuf2))) { + circ_buf_read(cbuf1, cbuf1_idx, curr_str1); + circ_buf_read(cbuf2, cbuf2_idx, curr_str2); + + int strcmp_res = strcmp(curr_str1, curr_str2); + if (!strcmp_res) { + ++cbuf1_idx; + ++cbuf2_idx; + } else { // TODO: change the inner comparisons (strtok etc) + if (strcmp_res < 0) { + (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); + strcpy((*add2)[add2_arr_idx], curr_str1); + ++add2_arr_idx; + ++cbuf1_idx; + } + else if (strcmp_res > 0) { + (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); + strcpy((*add1)[add1_arr_idx], curr_str2); + ++add1_arr_idx; + ++cbuf2_idx; + } + } + } + + while (cbuf1_idx < circ_buf_size(cbuf1)) { + (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); + circ_buf_read(cbuf1, cbuf1_idx, curr_str1); + strcpy((*add2)[add2_arr_idx], curr_str1); + ++add2_arr_idx; + ++cbuf1_idx; + } + + while (cbuf2_idx < circ_buf_size(cbuf2)) { + (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); + circ_buf_read(cbuf2, cbuf2_idx, curr_str2); + strcpy((*add1)[add1_arr_idx], curr_str2); + ++add1_arr_idx; + ++cbuf2_idx; + } + + (*add1)[add1_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf1) * sizeof(char)); + strcpy((*add1)[add1_arr_idx], EOB); + + (*add2)[add2_arr_idx] = (char*) malloc(circ_buf_element_size(cbuf2) * sizeof(char)); + strcpy((*add2)[add2_arr_idx], EOB); + + free(curr_str1); + free(curr_str2); + + /*uint8_t i = 0; + printf("add1:\n"); + while (strcmp((*add1)[i], EOB)) { + printf("%s\n", (*add1)[i]); + ++i; + } + + i = 0; + printf("add2:\n"); + while (strcmp((*add2)[i], EOB)) { + printf("%s\n", (*add2)[i]); + ++i; + }*/ +} + int circ_buf_serialize(cbuf_handle_t cbuf, char **serialized) { char *temp = (char*) malloc(circ_buf_element_size(cbuf) * sizeof(char)); const char separator[2] = "\r"; diff --git a/lib/circ_buff.h b/lib/circ_buff.h index 5a751f5..5d2a5fd 100644 --- a/lib/circ_buff.h +++ b/lib/circ_buff.h @@ -20,7 +20,6 @@ typedef circ_buf_t *cbuf_handle_t; #define unit_static unit_static void advance_pointer(cbuf_handle_t cbuf); unit_static void retreat_pointer(cbuf_handle_t cbuf); -unit_static void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, char ***add1, char ***add2); #else #define unit_static static #endif @@ -50,6 +49,13 @@ int circ_buf_get(cbuf_handle_t cbuf, char *data); // Reads a value from the buffer. Does NOT retrieve, size is not reduced! int circ_buf_read(cbuf_handle_t cbuf, size_t position, char *data); +// Compares the buffers cbuf1 and cbuf2. Elements present on cbuf1 that do not +// exist on cbuf2 are added to the array add2, elements present on cbuf2 that do +// not exist on cbuf1 are added to the array add1. +// Both buffers must be ordered on the same way! +void diff_bufs(cbuf_handle_t cbuf1, cbuf_handle_t cbuf2, + char ***add1, char ***add2); + // Serializes the whole buffer to a single string int circ_buf_serialize(cbuf_handle_t cbuf, char **serialized); diff --git a/lib/helpers.c b/lib/helpers.c index ac3ffa2..21f0c3d 100644 --- a/lib/helpers.c +++ b/lib/helpers.c @@ -1,5 +1,86 @@ #include "helpers.h" +/* + * Function based on this example: + * http://man7.org/linux/man-pages/man3/getifaddrs.3.html#EXAMPLE +*/ +int get_own_id(void) { + int id = -1; + struct ifaddrs *ifaddr, *ifa; + int family, s, n; + char host[NI_MAXHOST]; + + if (getifaddrs(&ifaddr) == -1) { + perror("Couldn't get network interfaces."); + exit(EXIT_FAILURE); + } + + // Walks through linked list, maintaining head pointer so we can free list later + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) { + if (ifa->ifa_addr == NULL) { + continue; + } + + family = ifa->ifa_addr->sa_family; + + // Gets the address of an AF_INET* interface address + if (family == AF_INET || family == AF_INET6) { + s = getnameinfo(ifa->ifa_addr, + (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), + host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); + if (s != 0) { + printf("getnameinfo() failed: %s\n", gai_strerror(s)); + exit(EXIT_FAILURE); + } + + id = extract_id_from_ip(host); + if (id < 0) { + continue; + } + + break; + } + } + + freeifaddrs(ifaddr); + + return(id); +} + +int extract_id_from_ip(const char *ip) { + const char separator[2] = "."; + int id = 0; + char *rest, *token, *ip_cp; + + ip_cp = malloc(strlen(ip) * sizeof(char)); + strcpy(ip_cp, ip); + + rest = ip_cp; + token = strtok_r(rest, separator, &rest); + if (!token || atoi(token) != 10) { + return -1; + } + + token = strtok_r(rest, separator, &rest); + if (!token || atoi(token) != 0) { + return -1; + } + + token = strtok_r(rest, separator, &rest); + if (!token) { + return -1; + } + id = atoi(token) * 100; + + token = strtok_r(rest, separator, &rest); + if (!token) { + return -1; + } + id += atoi(token); + + return id; +} + void set_timer_and_handler(void (*handler)(int), long int timer_interval) { struct itimerval interval_timer; struct sigaction signal_action; @@ -67,7 +148,7 @@ void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, ui int count = 0; while (1 == fscanf(arpCache, ARP_LINE_FORMAT, ipAddr)) { ++count; - if (count > 1){ + if (count > 1) { char **r_neighbors_ips = realloc(neighbors_ips, count * sizeof(char *)); if (!r_neighbors_ips) { free(r_neighbors_ips); @@ -132,6 +213,20 @@ void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, ui fclose(arpCache); } +void create_message(node_handle_t *neighbors, char *new_message, int own_id, + uint8_t num_neighbors, uint16_t max_message_length) { + node_handle_t random_node = neighbors[rand() % (num_neighbors)]; + + int peer_id = extract_id_from_ip(inet_ntoa((node_get_addr(random_node)).sin_addr)); + if (peer_id < 0) { + perror("Couldn't extract own ID."); + exit(EXIT_FAILURE); + } + + snprintf(new_message, max_message_length, "%04d_%04d_%ld_%s", own_id, peer_id, time(NULL), + "It's amazing... It's fantastic!"); +} + bool check_node_alive(const char *ipv4) { char command[64]; @@ -253,5 +348,6 @@ void init_sockaddr(struct sockaddr_in *peer_name, const char *ipv4, uint16_t por fprintf(stderr, "Unknown host %s.\n", ipv4); exit(EXIT_FAILURE); } + peer_name->sin_addr = *(struct in_addr *) hostinfo->h_addr_list[0]; } diff --git a/lib/helpers.h b/lib/helpers.h index ee0ac7c..45768fc 100644 --- a/lib/helpers.h +++ b/lib/helpers.h @@ -1,6 +1,8 @@ #ifndef HELPERS_H_ #define HELPERS_H_ +#define _GNU_SOURCE + #include #include #include @@ -11,6 +13,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,12 +35,19 @@ // Format for fscanf() to read the 1st field of ARP #define ARP_LINE_FORMAT "%" xstr(ARP_STRING_LEN) "s %*s %*s %*s %*s %*s" +int get_own_id(void); + +int extract_id_from_ip(const char *ip); + void set_timer_and_handler(void (*handler)(int), long int timer_interval); void enable_echo_broadcast(void); void search_for_neighbors(node_handle_t **neighbors, uint16_t *num_neighbors, uint16_t port); +void create_message(node_handle_t *neighbors, char *new_message, int own_id, + uint8_t num_neighbors, uint16_t max_message_length); + bool check_node_alive(const char *ipv4); int create_socket_and_listen(uint16_t port, uint8_t backlog_size); diff --git a/src/zaqar.c b/src/zaqar.c index 999a952..40ea2d3 100644 --- a/src/zaqar.c +++ b/src/zaqar.c @@ -5,12 +5,18 @@ volatile sig_atomic_t sigalrm_flag = false; int main(void) { - int in_sock; + int in_sock, own_id; fd_set active_fd_set, read_fd_set; struct sockaddr_in peer_name; node_handle_t *neighbors; uint16_t num_neighbors = 0; + own_id = get_own_id(); + if (own_id < 0) { + perror("Couldn't extract own ID."); + exit(EXIT_FAILURE); + } + // Enables echo broadcast pings enable_echo_broadcast(); @@ -32,12 +38,14 @@ int main(void) { while (1) { if (sigalrm_flag) { // It's time to send a message! + char new_message[MAX_MESSAGE_LENGTH]; search_for_neighbors(&neighbors, &num_neighbors, PORT); + create_message(neighbors, new_message, own_id, num_neighbors, MAX_MESSAGE_LENGTH); 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); + send_message(node_get_addr(neighbors[i]), new_message); } } @@ -66,7 +74,7 @@ int main(void) { accept_connection(in_sock, &peer_name, &active_fd_set); } else { // Data arriving on an already-connected socket - if (read_from_peer(i, MAXLINE) < 0) { + if (read_from_peer(i, MAX_MESSAGE_LENGTH) < 0) { close(i); FD_CLR(i, &active_fd_set); } diff --git a/src/zaqar.h b/src/zaqar.h index daee30e..5567b77 100644 --- a/src/zaqar.h +++ b/src/zaqar.h @@ -20,7 +20,7 @@ #define TIMER_INTERVAL 10 #define PORT 5000 -#define MAXLINE 1024 +#define MAX_MESSAGE_LENGTH 277 #define BACKLOG_SIZE 2 void handle_alarm(int sig);