diff --git a/src/node.c b/src/node.c index 41e648c..b5e69af 100644 --- a/src/node.c +++ b/src/node.c @@ -1,19 +1,6 @@ // This is the main file of the Dazibao project. It represents the node, and // handles all of the main logic, including the network connexions. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "node.h" -#include "debug.h" // Static variables static list *data_list; @@ -201,7 +188,7 @@ pub_data *get_data(int64_t id) { } // Take data as args and create a pub_data structure in the heap -pub_data *copy_data(unsigned char len, int64_t id, int16_t seqno, char *data) { +pub_data *copy_data(unsigned char len, int64_t id, uint16_t seqno, char *data) { pub_data *new_data = (pub_data*) malloc(sizeof(pub_data)); char *_data = (char*) malloc(len); new_data->length = len; @@ -213,121 +200,102 @@ pub_data *copy_data(unsigned char len, int64_t id, int16_t seqno, char *data) { return new_data; } -// Add new data to data list -int add_data(unsigned char len, int64_t id, int16_t seqno, char *data) { - print_debug(">> Adding data to the data list."); - // If id is the same as this node's id then we only update seqno +// A node state TLV was received and either no data associated to it's id is in our data list or the data was updated, return -1 if an error occurend, 0 if nothing had to be done and 1 if something was updated/added +int add_data(unsigned char len, int64_t id, uint16_t seqno, char *data, pub_data *found) { + // Check if it's our own id + if(id == NODE_ID) { + // wtf + if(found == NULL) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Our own node is not in the data list, something went terribly wrong.\n"); + return -1; + } - if(id == NODE_ID) { - // We create our pub_data. - pub_data * message = malloc(sizeof(struct pub_data)); - message->length = len; - message->id = id; - message->seqno = seqno; - message->data = data; + // If seqno is bigger or equals than our stored seqno then update seqno + if( ((seqno - found->seqno) & 32768) == 0 ) { + printf(">> Updating seqno of our own published data.\n"); + found->seqno = (seqno + 1) % (65535); + return 1; + } + + // Else, do nothing + printf(">> Our own seqno didn't need to be updated.\n"); + return 0; + } - // If the data list has never been used, or is empty ( same thing ) - if (data_list == NULL) { - data_list = (list*) malloc(sizeof(struct list)); + // If it's not our own id, update the data if it's already in our data list and seqno is bigger than our stored seqno + if(found != NULL) { + // Check if seqno is smaller or equals to our stored seqno + if( ((found->seqno - seqno) & 32768) == 0 ) { + printf(">> Data received has smaller seqno than stored seqno, nothing has to be done.\n"); + return 0; + } - list *tmp = data_list; - // We create the next node of the linked list. - tmp->data = (void *) message; - tmp->next = NULL; + // Update data + found->length = len; + found->id = id; + found->seqno = seqno; - } else { - // we move until the last element of the dala_list, - // and add or data there. - // We use a temporary address to avoid writing to the static list. - // Seems weird but ok. - list *tmp = data_list; - while(tmp->next != NULL){ - tmp = tmp->next; + // Updata message + free(found->data); + found->data = (char*) malloc(len); + memcpy(found->data, data, len); + + printf(">> Updated %li's published data.\n", id); + + return 1; + } + + // Else, add new data + pub_data *new_data = copy_data(len, id, seqno, data); + + // Find correct position for new data + list *tmp = data_list; + list *last = NULL; + list *new_node; + int64_t cur_id; + + while(tmp != NULL) { + cur_id = ((pub_data*) tmp->data)->id; + + // If id is smaller than cur_id then the new data has to be added at this position + if(id < cur_id) { + // If last hasn't been set then the new data becomes the head of the list + if(last == NULL) { + // Update list + data_list = (list*) malloc(sizeof(list)); + data_list->data = (void*) new_data; + data_list->next = tmp; + + printf(">> Added new message to data list.\n"); + + return 1; } - // We create the next node of the linked list. - list * new_node = malloc(sizeof(struct list)); - new_node->data = (void *) message; + // Else, we update the last node + new_node = (list*) malloc(sizeof(list)); + new_node->data = (void*) new_data; + new_node->next = tmp; + last->next = new_node; - // Adding the message to the list. - tmp->next = (void *) new_node; + printf(">> Added new message to data list.\n"); + + return 1; } - return 1; - } else { - // Copy data - pub_data *new_data = copy_data(len, id, seqno, data); - if(data_list == NULL) { - // Update list - data_list = (list*) malloc(sizeof(list)); - data_list->data = (void*) new_data; - data_list->next = NULL; - - return 2; - } - - // Find correct position for new data - list *tmp = data_list; - list *last = NULL; - list *new_node; - int64_t cur_id; - - while(tmp != NULL) { - cur_id = ((pub_data*) tmp->data)->id; - - // If id is smaller than cur_id then the new data has to be added at this position - if(id < cur_id) { - // If last hasn't been set then the new data becomes the head of the list - if(last == NULL) { - // Update list - data_list = (list*) malloc(sizeof(list)); - data_list->data = (void*) new_data; - data_list->next = tmp; - - return 2; - } - - // Else, we update the last node - new_node = (list*) malloc(sizeof(list)); - new_node->data = (void*) new_data; - new_node->next = tmp; - last->next = new_node; - - return 1; - } else if(id == cur_id) { - // If data already exists for this id then we update it if it's seqno is greater than the one stored - pub_data *cur_data = (pub_data*) tmp->data; - - if(seqno > cur_data->seqno) { - // Updata data - tmp->data = (void*) new_data; - - // Free old data - free(cur_data); - - return 2; - } - - // seqno is smaller so the new data allocated is freed and nothing else is done - free(new_data); - - return 2; - } - - // Get next node in list - last = tmp; - tmp = tmp->next; - } - - // If no correct position was found then the new data has to be added at the end of the list - - // Update list - new_node = (list*) malloc(sizeof(list)); - new_node->data = (void*) new_data; - new_node->next = NULL; - last->next = new_node; - return 3; + // Get next node in list + last = tmp; + tmp = tmp->next; } + + // If no correct position was found then the new data has to be added at the end of the list + new_node = (list*) malloc(sizeof(list)); + new_node->data = (void*) new_data; + new_node->next = NULL; + last->next = new_node; + + printf(">> Added new message to data list.\n"); + + return 1; } /* ---- Fin fonctions utilitaires ---- */ @@ -489,7 +457,7 @@ int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { } // Send length bytes from packet -int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, int socket_num) { +int send_packet(char *packet_buff, uint16_t length, struct sockaddr_in6 *dest, int socket_num) { ((packet*) packet_buff)->length = htons(((packet*) packet_buff)->length); // Vectorized buffer @@ -595,7 +563,7 @@ int send_single_tlv(tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { return send_packet((char*) &pack, pack.length, dest, socket_num); } -int send_tlv(tlv *tlv_to_send, int16_t tlv_size, struct sockaddr_in6 * dest_list, int dest_list_size, int socket_num){ +int send_tlv(tlv *tlv_to_send, uint16_t tlv_size, struct sockaddr_in6 * dest_list, int dest_list_size, int socket_num){ print_debug(">> Building packet to send a TLV."); // We first need to build the packet, @@ -662,7 +630,7 @@ int send_tlv(tlv *tlv_to_send, int16_t tlv_size, struct sockaddr_in6 * dest_list // We need to make sure the TLV announces a length that will no go onto // another tlv, as we might end up reading bullshit. -int validate_tlv(char *data, int pos, int16_t packet_len){ +int validate_tlv(char *data, int pos, uint16_t packet_len){ char type = data[pos]; @@ -754,17 +722,32 @@ int check_header(char * received_data_buffer, int received_data_len, struct pack } int add_message(char * message, int message_len){ - int seqno = 1337; - int rc = add_data((unsigned char) message_len, (int64_t) NODE_ID ,(int16_t) seqno, message); - if (rc > 0) { + // Don't update the message if it's empty + if(message_len == 0) + return -1; + + // If not, get our data in the list and update it + pub_data *our_data = get_data(NODE_ID); + + if(our_data != NULL) { + our_data->seqno = (our_data->seqno + 1) % 65535; + our_data->length = message_len; + free(our_data->data); + our_data->data = (char*) malloc(message_len); + memcpy(our_data->data, message, message_len); + print_debug(">> Message added."); + + return 0; } - return 0; + + print_debug(">> Message could not be added because our own ID is not in the data_list, something went wrong."); + return -1; } // We then look at the differents TLVs in the packet. -int work_with_tlvs(char * data, int16_t total_packet_len, struct sockaddr_in6 *sender, int socket_num){ - int16_t packet_len = ((packet*) data)->length; +int work_with_tlvs(char * data, uint16_t total_packet_len, struct sockaddr_in6 *sender, int socket_num){ + uint16_t packet_len = ((packet*) data)->length; if(packet_len != total_packet_len - 4) { print_debug(">> Length indicated in packet differs from real length of packet received, disgarding packet."); @@ -914,7 +897,7 @@ int work_with_tlvs(char * data, int16_t total_packet_len, struct sockaddr_in6 *s hash_data(pdata, hash); // If both hashes are the same then nothing has to be done - if(memcmp(hash, cur_tlv.node_hash->node_hash, 16) != 0) { + if(memcmp(hash, cur_tlv.node_hash->node_hash, 16) == 0) { // The position is updated tlv_len = data[pos+1]; pos += 2; @@ -962,7 +945,28 @@ int work_with_tlvs(char * data, int16_t total_packet_len, struct sockaddr_in6 *s if (DEBUG_LEVEL > 0) { printf("\n\t %s \n", (char *) cur_tlv.node_state->data); } - int rc = add_data(cur_tlv.node_state->length - 26, ntohl(cur_tlv.node_state->node_id), ntohs(cur_tlv.node_state->seqno), cur_tlv.node_state->data); + + // Compare hashes + pdata = get_data(ntohl(cur_tlv.node_state->node_id)); + + // If data is found for this id then we check that both hashes are the same + if(pdata != NULL) { + // We hash the data stored in the data list + hash_data(pdata, hash); + + // If both hashes are the same then nothing has to be done + if(memcmp(hash, cur_tlv.node_hash->node_hash, 16) == 0) { + // The position is updated + tlv_len = data[pos+1]; + pos += 2; + + break; + } + + } + + // Else, we update the data + int rc = add_data(cur_tlv.node_state->length - 26, ntohl(cur_tlv.node_state->node_id), ntohs(cur_tlv.node_state->seqno), cur_tlv.node_state->data, pdata); if (rc < 0) { print_debug(">> Error while adding note state !"); } @@ -1224,6 +1228,17 @@ int bootstrap_node(int * sock_fd){ neighbour_list->data = (void *) root_peer; neighbour_list->next = NULL; + print_debug(">> Initializing data list..."); + data_list = (list*) malloc(sizeof(list)); + data_list->data = malloc(sizeof(pub_data)); + data_list->next = NULL; + + pub_data *our_data = (pub_data*) data_list->data; + our_data->length = 0; + our_data->id = NODE_ID; + our_data->seqno = 1337; + our_data->data = NULL; + print_debug(">> Boostraping done."); return 0; } diff --git a/src/node.h b/src/node.h index a45a61e..597de2f 100644 --- a/src/node.h +++ b/src/node.h @@ -12,6 +12,12 @@ #include #include #include +#include +#include +#include +#include +#include +#include "debug.h" /* la table de voisins, qui est indexée par adresses de socket (des paires (IP, Port)), * et dont chaque entrée contient un booléen indiquant si le pair est permanent @@ -35,7 +41,7 @@ typedef struct neighbour_peer { typedef struct pub_data { unsigned char length; int64_t id; - int16_t seqno; + uint16_t seqno; char *data; } pub_data; @@ -69,17 +75,17 @@ int listen_for_packets(char * received_data_buffer, int received_data_len, struc int check_header(char * received_data_buffer, int received_data_len, packet * packet_to_return); -int validate_tlv(char *data, int pos, int16_t packet_len); +int validate_tlv(char *data, int pos, uint16_t packet_len); int update_neighbours(); int ask_for_peers(int socket_num); -int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, int socket_num); +int work_with_tlvs(char * data, uint16_t packet_len, struct sockaddr_in6 *sender, int socket_num); int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num); -int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, int socket_num); +int send_packet(char *packet_buff, uint16_t length, struct sockaddr_in6 *dest, int socket_num); int send_single_tlv(tlv *tlv, struct sockaddr_in6 *dest, int socket_num); @@ -89,12 +95,12 @@ int run_node(int sock_fd); /* Takes a TLV and sends it over to everyone in the list of addresses. * Returns -1 in case of error, 0 otherwise. */ -int send_tlv(tlv *tlv_to_send, int16_t length, struct sockaddr_in6 * dest_list, int dest_list_size, int socket_num); +int send_tlv(tlv *tlv_to_send, uint16_t length, struct sockaddr_in6 * dest_list, int dest_list_size, int socket_num); /* Takes a list of TLV and sends them over to everyone in the list of addresses. * Returns -1 in case of error, 0 otherwise. */ -int send_tlvs(struct list * tlv_list, int16_t length, struct sockaddr_in6 * dest_list, int dest_list_size, int socket_num); +int send_tlvs(struct list * tlv_list, uint16_t length, struct sockaddr_in6 * dest_list, int dest_list_size, int socket_num); /* Check our peer list. If we have less than 5 peers, send out a TLV NEIGHBOUR_REQUEST to a random peer @@ -133,9 +139,9 @@ int add_n_update_neighbour(struct in6_addr *ip, int16_t port); pub_data *get_data(int64_t id); // Take data as args and create a pub_data structure in the heap -pub_data *copy_data(unsigned char len, int64_t id, int16_t seqno, char *data); +pub_data *copy_data(unsigned char len, int64_t id, uint16_t seqno, char *data); // add new data to data list -int add_data(unsigned char len, int64_t id, int16_t seqno, char *data); +int add_data(unsigned char len, int64_t id, uint16_t seqno, char *data, pub_data *found); #endif diff --git a/src/tlv.c b/src/tlv.c index 70207a7..4c4acd8 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -134,7 +134,7 @@ int build_network_state_req(tlv *tlv) { return 0; } -int build_node_hash(tlv *tlv, int64_t node_id, int16_t seqno, char *data) { +int build_node_hash(tlv *tlv, int64_t node_id, uint16_t seqno, char *data) { // Free the previously allocated memory free(tlv->pad1); @@ -174,7 +174,7 @@ int build_node_state_req(tlv *tlv, int64_t node_id) { return 0; } -int build_node_state(tlv *tlv, int64_t node_id, int16_t seqno, char *data, size_t data_len) { +int build_node_state(tlv *tlv, int64_t node_id, uint16_t seqno, char *data, size_t data_len) { // Free the previously allocated memory free(tlv->pad1); diff --git a/src/tlv.h b/src/tlv.h index d10d3c9..10b4eee 100644 --- a/src/tlv.h +++ b/src/tlv.h @@ -19,7 +19,7 @@ typedef struct packet { unsigned char magic; // 95 (si autre, ignorer) unsigned char version; // 1 (si autre, ignorer) - int16_t length; // 1020 max + uint16_t length; // 1020 max char body[1020]; } packet; @@ -67,7 +67,7 @@ typedef struct node_hash { unsigned char type; unsigned char length; int64_t node_id; - int16_t seqno; + uint16_t seqno; char node_hash[16]; } node_hash; @@ -83,7 +83,7 @@ typedef struct node_state { unsigned char type; unsigned char length; int64_t node_id; - int16_t seqno; + uint16_t seqno; char node_hash[16]; char data[192]; } node_state; @@ -122,9 +122,9 @@ int build_neighbour_req(union tlv *tlv); int build_neighbour(tlv *tlv, struct in6_addr ip, int16_t port); int build_network_hash(tlv *tlv, list *data_list); int build_network_state_req(tlv *tlv); -int build_node_hash(tlv *tlv, int64_t node_id, int16_t seqno, char *data); +int build_node_hash(tlv *tlv, int64_t node_id, uint16_t seqno, char *data); int build_node_state_req(tlv *tlv, int64_t node_id); -int build_node_state(tlv *tlv, int64_t node_id, int16_t seqno, char *data, size_t data_len); +int build_node_state(tlv *tlv, int64_t node_id, uint16_t seqno, char *data, size_t data_len); int build_warning(tlv *tlv, char *message, size_t message_len); #endif