diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4a116ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,55 @@ +# binary +dazibao + +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.a +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf diff --git a/Makefile b/Makefile index 3d676e4..321bd99 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ TARGET ?= dazibao SRC_DIRS ?= ./src/* CC := gcc -CFLAGS= -O2 -Wall +CFLAGS= -O2 -Wall -g SRCS := $(shell find $(SRC_DIRS) -name *.c -or -name *.s) OBJS := $(addsuffix .o,$(basename $(SRCS))) DEPS := $(OBJS:.o=.d) diff --git a/src/debug.c b/src/debug.c new file mode 100644 index 0000000..a23736d --- /dev/null +++ b/src/debug.c @@ -0,0 +1,114 @@ +#include +#include +#include +#include +#include +#include "debug.h" +#include "node.h" + +void welcome(){ + print_info("----------------------------------------"); + print_info(" 大字报"); + print_info("----------------------------------------"); + print_info(">> To write a message, just write it to the terminal and press enter."); + print_info(">> To show all messages, just press enter without writing anything."); +} + +void print_info(char * msg) { + printf("\x1b[1m\x1b[36m[大字报]\x1b[0m %s\n", msg); +} + +void print_debug(char * msg){ + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m %s \n", msg); + } + if (DEBUG_LEVEL > 9) { + getchar(); + } +} + +void print_error(char * msg){ + printf("\x1b[41m\x1b[97m[ERROR] >> %s \x1b[0m\n", msg); + if (DEBUG_LEVEL > 1) { + getchar(); + } +} + +void print_peers(list * l){ + if (DEBUG_LEVEL > 0) { + // Print out the peers we have in the neighbour_list + int nbr_peers = 0; + if (l == NULL) { + print_error("The neighbour_list is empty !"); + } else { + print_debug(">> Printing out peer list :"); + while(l != NULL){ + neighbour_peer * peer = (neighbour_peer *) l->data; + if (peer == NULL) { + print_error("Peer is empty ?"); + return; + } + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,&peer->ip,(char * restrict) buff_str_ip, 1024); + int last_seen = time(NULL) - peer->last_seen; + printf("\x1b[31m[DEBUG]\x1b[0m >> %s @ %i | is temporary ? %s | last seen %i secs ago. |\n", ip_str, peer->port, peer->is_temporary ? "yes":"no", last_seen); + nbr_peers++; + if (l->next == NULL) { + break; + } else { + l = l->next; + } + + } + printf("\x1b[31m[DEBUG]\x1b[0m >> Found %i peers.\n", nbr_peers); + print_debug(">> Finished printing peer list."); + } + + } +} + +void print_data(list * l){ + if (DEBUG_LEVEL > 0) { + + if (l == NULL) { + print_error("Message list is empty !"); + } else { + print_debug(">> Printing messages we know of so far :"); + int nbr_msg = 0; + setlocale(LC_ALL, "en_US.utf8"); + print_debug(">> Peer ID | Seqno | Length | Message "); + while(l != NULL){ + pub_data * message = l->data; + printf("\x1b[31m[DEBUG]\x1b[0m >> %lu | %i | %i | “%s” \n", message->id, message->seqno, message->length, message->data); + nbr_msg++; + if (l->next == NULL) { + break; + } else { + l = l->next; + } + } + printf("\x1b[31m[DEBUG]\x1b[0m >> Found %i messages.\n", nbr_msg); + } + } +} + +void print_data_info(list * l){ + if (l == NULL) { + print_error("Message list is empty !"); + } else { + int nbr_msg = 0; + setlocale(LC_ALL, "en_US.utf8"); + print_info(">> Peer ID | Seqno | Length | Message "); + while(l != NULL){ + pub_data * message = l->data; + printf("\x1b[1m\x1b[36m[大字报]\x1b[0m >> %lu | %i | %i | “%s” \n", message->id, message->seqno, message->length, message->data); + nbr_msg++; + if (l->next == NULL) { + break; + } else { + l = l->next; + } + } + printf("\x1b[1m\x1b[36m[大字报]\x1b[0m >> Found %i messages.\n", nbr_msg); + } +} diff --git a/src/debug.h b/src/debug.h new file mode 100644 index 0000000..99f6811 --- /dev/null +++ b/src/debug.h @@ -0,0 +1,23 @@ +#ifndef DEBUG_H +#define DEBUG_H + +#include "node.h" + + +#define DEBUG_LEVEL 7 + +void welcome(); + +void print_info(char * msg); + +void print_debug(char * msg); + +void print_error(char * msg); + +void print_peers(list * l); + +void print_data(list * l); + +void print_data_info(list * l); + +#endif diff --git a/src/hash.c b/src/hash.c index 44e3827..9c05afb 100644 --- a/src/hash.c +++ b/src/hash.c @@ -1,7 +1,16 @@ #include "hash.h" +#include "debug.h" // Hash a single data void hash_data(pub_data *data, unsigned char *buf) { + /* + data->length = 52 - 26; + data->id = 34538; + data->seqno = 4864; + data->data = "Luke, je suis ton \"pair\" !"; + printf("Hash received: 9ffe841a99776f6d1295ac75b53a58d7\n"); + */ + // All three fields are concatenated into a single buffer int totlen = data->length + 10; unsigned char concat[totlen]; @@ -9,15 +18,30 @@ void hash_data(pub_data *data, unsigned char *buf) { // The resulting buf is hashed and put into a buffer unsigned char hash[SHA256_DIGEST_LENGTH]; - SHA256(concat, totlen, hash); + + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, concat, totlen); + SHA256_Final(hash, &sha256); // Put truncated hash into buf hash_trunc(hash, buf); + + /* + printf("Hash built: "); + for(int i = 0; i < 16; i++) { + printf("%02x", buf[i]); + } + printf("\n"); + */ } // Hash every data contained in data_list then return a network hash void hash_network(list *data_list, unsigned char *buf) { - unsigned char *concat = (unsigned char*) malloc(0); + // Get list length to initialize concat buffer + int concat_len = len_list(data_list) * 16; + unsigned char *concat = (unsigned char*) malloc(concat_len); + unsigned char hash[SHA256_DIGEST_LENGTH]; int totlen = 0; list *tmp = data_list; @@ -31,7 +55,10 @@ void hash_network(list *data_list, unsigned char *buf) { } // Hash all of concat to obtain the network hash - SHA256(concat, totlen, hash); + SHA256_CTX sha256; + SHA256_Init(&sha256); + SHA256_Update(&sha256, concat, concat_len); + SHA256_Final(hash, &sha256); // Put truncated hash into buf hash_trunc(hash, buf); @@ -43,18 +70,49 @@ void hash_network(list *data_list, unsigned char *buf) { // Truncate 32 octet hash to 16 octets void hash_trunc(unsigned char *hash32oct, unsigned char *buf) { // Copy the first 16 octets from hash32oct - memcpy(buf, hash32oct, 16); + if (memcpy(buf, hash32oct, 16) == NULL) { + print_debug(">> Truncating the hashs didn't work !"); + } } // Concat all fields of data and put them in buf void concat_data(pub_data *data, unsigned char *buf) { - memcpy(buf, &(data->id), 8); - memcpy(buf+8, &(data->seqno), 2); - memcpy(buf+10, data->data, data->length); + // Turn seqno to big endian + uint16_t seqno = htobe16(data->seqno); + uint64_t id = htobe64(data->id); + + if (memcpy(buf, (char*) &id, 8) == NULL) { + print_debug(">> Concat the data (id) didn't work !"); + } + if (memcpy(buf+8, (char*) &seqno, 2) == NULL) { + print_debug(">> concat the data (seqno) didn't work !"); + } + if (memcpy(buf+10, data->data, data->length) == NULL) { + print_debug(">> Contact the data (data) didn't work !"); + } + + /* + uint64_t *id = (uint64_t *) buf; + uint16_t *seqno2 = (uint16_t *) (buf + 8); + char *message = (char*) (buf + 10); + char fuck[100]; + + printf("id: %ld\nseqno: %d\nmessage: ", *id, *seqno2); + for(int i = 0; i < data->length; i++) { + printf("%c", message[i]); + } + printf("\nORIGINAL\n"); + printf("id: %ld\nseqno: %d\nmessage: ", data->id, htobe16(data->seqno)); + for(int i = 0; i < data->length; i++) { + printf("%c", data->data[i]); + } + printf("\n"); + */ } // Concat hash2 to hash1 (hash1 is modified) void concat_hash(unsigned char *hash1, unsigned char *hash2, size_t size) { - hash1 = (unsigned char*) realloc(hash1, size + 16); - memcpy(hash1+size, hash2, 16); + if(memcpy(hash1+size, hash2, 16) == NULL){ + print_debug(">> Concat the hash didn't work !"); + } } diff --git a/src/hash.o b/src/hash.o deleted file mode 100644 index 920c6ac..0000000 Binary files a/src/hash.o and /dev/null differ diff --git a/src/node.c b/src/node.c index a5d39e7..cb72406 100644 --- a/src/node.c +++ b/src/node.c @@ -1,17 +1,5 @@ // 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" @@ -21,6 +9,64 @@ static list *neighbour_list; /* ---- Fonctions utilitaires ---- */ +// Looks for more peers +int ask_for_peers(int socket_num) { + print_debug(">> Asking for more peers..."); + // Print out the current peer list. + + // Only ask for more peers if the neighbour list is small enough + int nbr_peers = len_list(neighbour_list); + if( nbr_peers >= 5){ + print_debug(">> We have enough peers, skipping..."); + return 0; + } else if (nbr_peers <= 0){ + print_debug(">> No peers found in the peer list, something terrible happened."); + return -1; + } else { + + // Get random peer + neighbour_peer *peer = get_random_neighbour(); + struct in6_addr ip = peer->ip; + int16_t port = peer->port; + + /*int ifindex = if_nametoindex("enp3s0"); + if(ifindex == 0) { + int ifindex = if_nametoindex("eth0"); + if(ifindex == 0) { + perror("if_nametoindex failed"); + return -1; + } + }*/ + + int ifindex = 0; + + // Initialize sockaddr + struct sockaddr_in6 dest; + memset(&dest, 0, sizeof(struct sockaddr_in6)); + dest.sin6_family = AF_INET6; + memcpy(&dest.sin6_addr, &ip, 16); + dest.sin6_port = htobe16(port); + dest.sin6_scope_id = ifindex; + + // Send neighbour request TLV + tlv neighbour_req; + neighbour_req.pad1 = NULL; + int rc = build_neighbour_req(&neighbour_req); + if (rc < 0) { + print_debug(">> Failed to build neighbour_req"); + } + + rc = send_single_tlv(&neighbour_req, &dest, socket_num); + if (rc < 0) { + print_debug(">> Error while sending a TLV."); + return -1; + } else { + print_debug(">> Send TLV."); + return 0; + } + } +} + // Get list length int len_list(list *l) { int len = 0; @@ -30,35 +76,124 @@ int len_list(list *l) { tmp = tmp->next; len++; } - return len; } // Get a random neighbour neighbour_peer *get_random_neighbour() { + print_debug(">> Getting random peer..."); // Get a random number - time_t t; - srand((unsigned) time(&t)); - int n = rand() % len_list(neighbour_list); - + srand((unsigned) time(NULL)); + int n = (rand() % len_list(neighbour_list)) + 1; // Get nth neighbour list *tmp = neighbour_list; - for(int i=0; inext; } return (neighbour_peer*) tmp->data; } +// Search for this peer in the neighbour table +neighbour_peer *get_neighbour(struct in6_addr *ip, uint16_t port) { + print_debug(">> Getting neighbour."); + + if (DEBUG_LEVEL > 1) { + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,ip,(char * restrict) buff_str_ip, 1024); + printf("\x1b[31m[DEBUG]\x1b[0m >> Looking up %s @ %i\n", ip_str, port ); + } + + // Look for neighbour + list *tmp = neighbour_list; + neighbour_peer *peer; + + while(tmp != NULL) { + // check for same ip and same port + peer = (neighbour_peer*) tmp->data; + + if(memcmp(&peer->ip, ip, sizeof(struct in6_addr)) == 0 + && memcmp(&peer->port, &port, sizeof(uint16_t)) == 0) { + return peer; + } + + // if they differ, get next peer + tmp = tmp->next; + } + + return NULL; +} + +// Return -1 if we have enough peers, +// 1 if it was added +// Return 0 if peer was updated as last_seen +int add_n_update_neighbour(struct in6_addr *ip, uint16_t port) { + + + // We try to find a peer with this address and port. + neighbour_peer *peer = get_neighbour(ip, port); + time_t curtime; + + if (peer == NULL) { + print_debug(">> We don't know this peer yet"); + // check if there are less than 15 neighbours + if(len_list(neighbour_list) >= 15){ + return -1; + } else { + if (DEBUG_LEVEL > 0) { + if (DEBUG_LEVEL > 1) { + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,ip,(char * restrict) buff_str_ip, 1024); + printf("\x1b[31m[DEBUG]\x1b[0m >> Adding peer %s @ %i to the peer table.\n", ip_str, port ); + sleep(3); + } + } + // if there are less, initialize the new peer to add to the list + peer = (neighbour_peer*) malloc(sizeof(neighbour_peer)); + memcpy(&peer->ip, ip, sizeof(struct in6_addr)); + peer->port = port; + peer->is_temporary = 1; + + // set last_seen time + time(&curtime); + peer->last_seen = curtime; + + list * tmp = neighbour_list; + + // set new peer as head of list + list *node = (list*) malloc(sizeof(list)); + node->data = (void*) peer; + node->next = tmp; + neighbour_list = node; + return 1; + } + } else { + + if (DEBUG_LEVEL > 0) { + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,ip,(char * restrict) buff_str_ip, 1024); + printf("\x1b[31m[DEBUG]\x1b[0m >> Found peer %s @ %i, updating the last seen time...\n", ip_str, port); + + } + + time_t curtime; + // if the peer was already in the list, update it + time(&curtime); + peer->last_seen = curtime; + return 0; + + } +} + // get data associated with id, if it doesn't exist return NULL -pub_data *get_data(int64_t id) { +pub_data *get_data(uint64_t id) { list *tmp = data_list; pub_data *data; while(tmp != NULL) { data = (pub_data*) tmp->data; - + tmp = tmp->next; if(data->id == id) return data; } @@ -67,109 +202,201 @@ 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, uint64_t id, uint16_t seqno, char *data) { pub_data *new_data = (pub_data*) malloc(sizeof(pub_data)); char *_data = (char*) malloc(len); + if (_data == NULL) { + print_error("Failed to allocate memory for copying the data !"); + return NULL; + } new_data->length = len; new_data->id = id; new_data->seqno = seqno; new_data->data = _data; - memcpy(_data, data, len); + if(memcpy(_data, data, len) == NULL){ + print_error("Failed to copy data !"); + return NULL; + } + return new_data; } -// Add new data to data list -void add_data(unsigned char len, int64_t id, int16_t seqno, char *data) { - // If id is the same as this node's id then we only update seqno - if(id == NODE_ID) { - pub_data *node_data = get_data(NODE_ID); +// 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, uint64_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(seqno >= node_data->seqno) { - node_data->seqno = seqno ^ 1; - } + // If seqno is bigger or equals than our stored seqno then update seqno + if( ((seqno - found->seqno) & 32768) == 0 ) { + print_debug(">> Updating seqno of our own published data.\n"); + found->seqno = (seqno + 1) % (65535); + return 1; + } - return; - } + // Else, do nothing + print_debug(">> Our own seqno didn't need to be updated."); + return 0; + } - // Copy data - pub_data *new_data = copy_data(len, id, seqno, data); + // 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 ) { + print_debug(">> Data received has smaller seqno than stored seqno, nothing has to be done."); + return 0; + } - if(data_list == NULL) { - // Update list - data_list = (list*) malloc(sizeof(list)); - data_list->data = (void*) new_data; - data_list->next = NULL; + // Update data + found->length = len; + found->id = id; + found->seqno = seqno; - return; - } + // Updata message + free(found->data); + found->data = (char*) malloc(len); + memcpy(found->data, data, len); - // Find correct position for new data - list *tmp = data_list; - list *last = NULL; - list *new_node; - int64_t cur_id; + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Updated %li's published data.\n", id); + } - while(tmp != NULL) { - cur_id = ((pub_data*) tmp->data)->id; + return 1; + } - // 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; + // Else, add new data + pub_data *new_data = copy_data(len, id, seqno, data); - return; - } + // Find correct position for new data + list *tmp = data_list; + list *last = NULL; + list *new_node; + uint64_t cur_id; - // 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; + while(tmp != NULL) { + cur_id = ((pub_data*) tmp->data)->id; - return; - } 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 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; - if(seqno > cur_data->seqno) { - // Updata data - tmp->data = (void*) new_data; + print_debug(">> Added new message to data list."); - // Free old data - free(cur_data); + return 1; + } - return; - } + // 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; - // seqno is smaller so the new data allocated is freed and nothing else is done - free(new_data); + print_debug(">> Added new message to data list."); - return; - } + return 1; + } - // Get next node in list - last = tmp; - tmp = tmp->next; - } + // 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 + // 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; - // Update list - new_node = (list*) malloc(sizeof(list)); - new_node->data = (void*) new_data; - new_node->next = NULL; - last->next = new_node; + print_debug(">> Added new message to data list."); + + return 1; } /* ---- Fin fonctions utilitaires ---- */ +// Update the neighbour list +int update_neighbours() { + print_debug(">> Updating neighbours."); + list *tmp = neighbour_list, *last = NULL, *node_to_delete; + neighbour_peer *peer; + time_t curtime; + int deleted = 0; + + // check every neighbour + while(tmp != NULL) { + peer = (neighbour_peer*) tmp->data; + if (DEBUG_LEVEL > 1) { + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,&peer->ip,(char * restrict) buff_str_ip, 1024); + printf("\x1b[31m[DEBUG]\x1b[0m >> Checking for neighbour %s\n", ip_str ); + } + // Check if peer is temporary + if(peer->is_temporary) { + // If it's been 70 seconds or more since we last received a packet from this peer then remove it from the list + time(&curtime); + + if(difftime(peer->last_seen, curtime) >= 70) { + // increase the count of deleted nodes + deleted++; + + print_debug(">> They have not been seen for the past 70 seconds, deleting..."); + + // If head of the list + if(last == NULL) { + // Store node to delete + node_to_delete = tmp; + + // Update list + tmp = tmp->next; + neighbour_list = tmp; + + // Free allocated memory + free(node_to_delete->data); + free(node_to_delete); + + continue; + } + + // Store node to delete + node_to_delete = tmp; + + // Update list + tmp = tmp->next; + last->next = tmp; + + // Free allocated memory + free(node_to_delete->data); + free(node_to_delete); + + continue; + } else { + print_debug(">> Peer has been seen in the last 70 seconds, keeping him in."); + } + } else { + print_debug(">> Peer is not temporary, keeping him in."); + } + + last = tmp; + tmp = tmp->next; + } + + // returns the amount of nodes that were deleted + return deleted; +} + // Add TLV to packet, if it does not fit then send the packet and reset the packet buff to be able to add more TLVs that will be sent afterwards int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { + print_debug(">> Adding tlv to packet"); char type = tlv->pad1->type, sent = 0, errval = 0; unsigned char len; @@ -179,14 +406,24 @@ int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { if(pack->length + len > 1020) { errval = send_packet((char*) pack, pack->length, dest, socket_num); - *pack = (packet) {.magic = 95, .version = 1, .length = 0}; + + pack->magic = 95; + pack->version = 1; + pack->length = 0; + memset(pack->body, 0, 1020); sent = 1; } } else { + // In case we need to add a padding packet, and the packet is full, + // we just ignore that padding, and send out the packet. if(pack->length >= 1020) { errval = send_packet((char*) pack, pack->length, dest, socket_num); - *pack = (packet) {.magic = 95, .version = 1, .length = 0}; + + pack->magic = 95; + pack->version = 1; + pack->length = 0; + memset(pack->body, 0, 1020); sent = 1; } @@ -195,47 +432,74 @@ int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { // Copy data from tlv into body switch(type) { case 1: - memcpy(pack->body + pack->length, tlv->pad1, 1); + memcpy(pack->body + pack->length, (char*) &tlv->pad1->type, 1); pack->length += 1; break; case 2: - memcpy(pack->body + pack->length, tlv->padn, len); + memcpy(pack->body + pack->length, (char*) &tlv->padn->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->padn->length, 1); + memcpy(pack->body + pack->length + 2, (char*) &tlv->padn->mbz, tlv->padn->length); + pack->length += len; break; case 3: - memcpy(pack->body + pack->length, tlv->neighbour, len); + memcpy(pack->body + pack->length, (char*) &tlv->neighbour->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->neighbour->length, 1); + pack->length += len; break; case 4: - memcpy(pack->body + pack->length, tlv->network_hash, len); + memcpy(pack->body + pack->length, (char*) &tlv->network_hash->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->network_hash->length, 1); + memcpy(pack->body + pack->length + 2, (char*) &tlv->network_hash->network_hash, 16); + pack->length += len; break; case 5: - memcpy(pack->body + pack->length, tlv->network_state_req, len); + memcpy(pack->body + pack->length, (char*) &tlv->network_state_req->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->network_state_req->length, 1); + pack->length += len; break; case 6: - memcpy(pack->body + pack->length, tlv->node_hash, len); + memcpy(pack->body + pack->length, (char*) &tlv->node_hash->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->node_hash->length, 1); + memcpy(pack->body + pack->length + 2, (char*) &tlv->node_hash->node_id, 8); + memcpy(pack->body + pack->length + 10, (char*) &tlv->node_hash->seqno, 2); + memcpy(pack->body + pack->length + 12, (char*) &tlv->node_hash->node_hash, 16); + pack->length += len; break; case 7: - memcpy(pack->body + pack->length, tlv->node_state_req, len); + memcpy(pack->body + pack->length, (char*) &tlv->node_state_req->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->node_state_req->length, 1); + memcpy(pack->body + pack->length + 2, (char*) &tlv->node_state_req->node_id, 8); + pack->length += len; break; case 8: - memcpy(pack->body + pack->length, tlv->node_state, len); + memcpy(pack->body + pack->length, (char*) &tlv->node_state->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->node_state->length, 1); + memcpy(pack->body + pack->length + 2, (char*) &tlv->node_state->node_id, 8); + memcpy(pack->body + pack->length + 10, (char*) &tlv->node_state->seqno, 2); + memcpy(pack->body + pack->length + 12, (char*) &tlv->node_state->node_hash, 16); + memcpy(pack->body + pack->length + 28, (char*) &tlv->node_state->data, tlv->node_state->length - 26); + pack->length += len; break; case 9: - memcpy(pack->body + pack->length, tlv->warning, len); + memcpy(pack->body + pack->length, (char*) &tlv->warning->type, 1); + memcpy(pack->body + pack->length + 1, (char*) &tlv->warning->length, 1); + memcpy(pack->body + pack->length + 2, (char*) &tlv->warning->message, tlv->warning->length); + pack->length += len; break; @@ -243,44 +507,54 @@ int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { return -1; } - // If the previous packet was went return 1 or -1 if there was an error sending it - if(sent) + print_debug(">> Finished adding the TLVs to the packet"); + + // If the previous packet was sent return 1 or -1 if there was an error sending it + if(sent){ return errval? -1:1; + } // Return 0 if the TLV was added to the packet return 0; } // 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) { + uint16_t be_len = htobe16(*(uint16_t*) (packet_buff + 2)); + memcpy(packet_buff + 2, &be_len, 2); + // Vectorized buffer - struct iovec vec_buff = {.iov_len = length, .iov_base = packet_buff}; + struct iovec vec_buff[1]; + vec_buff[0].iov_len = length + 4; + vec_buff[0].iov_base = packet_buff; int error_while_sending = 0; // Creating the struct to send out with sendmsg - struct msghdr packet_tlv_send_out = { - .msg_name = dest, - .msg_namelen = sizeof(struct sockaddr_in6), - .msg_iov = &vec_buff, - .msg_iovlen = 1 // We have only one iovec buffer. But if we had 2, we would write 2. - }; + struct msghdr packet_tlv_send_out; + memset(&packet_tlv_send_out, 0, sizeof(struct msghdr)); + packet_tlv_send_out.msg_name = dest; + packet_tlv_send_out.msg_namelen = sizeof(struct sockaddr_in6); + packet_tlv_send_out.msg_iov = vec_buff; + packet_tlv_send_out.msg_iovlen = 1; // We have only one iovec buffer. But if we had 2, we would write 2. int response_code = sendmsg(socket_num, &packet_tlv_send_out, 0); if (response_code < 0) { - // debug_print("Unable to send out the packet to peer %i", i); + print_error("Unable to send out the packet to peer."); error_while_sending = 1; } else if (response_code < length) { - // debug_print("Sent out only part of the packet."); + print_debug(">> Sent out only part of the packet."); error_while_sending = 1; } else { - // debug_print("Send out packet to peer %i", i); + print_debug(">> Send out packet to peer."); } if (error_while_sending == 1) { - // debug_print("Error occured while sending out a packet."); return -1; } else { + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Packet successfully sent to peer. %d bytes sent.\n", response_code); + } return 0; } } @@ -288,63 +562,81 @@ int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, in // Send a single TLV to the specified addresses, return -1 if an error was encountered, 0 otherwise int send_single_tlv(tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { char type = tlv->pad1->type; - unsigned char len; - packet pack = (packet) {.magic = 95, .version = 1, .length = 4}; + packet pack = (packet) {.magic = 95, .version = 1, .length = 0}; memset(pack.body, 0, 1020); // Copy data from tlv into body - switch(type) { + switch(type) { case 1: - memcpy(pack.body, tlv->pad1, 1); + memcpy(pack.body + pack.length, (char*) &tlv->pad1->type, 1); pack.length += 1; break; case 2: - len = tlv->padn->length + 2; - memcpy(pack.body, tlv->padn, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->padn->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->padn->length, 1); + memcpy(pack.body + pack.length + 2, (char*) &tlv->padn->mbz, tlv->padn->length); + + pack.length += tlv->padn->length + 2; break; case 3: - len = tlv->neighbour->length + 2; - memcpy(pack.body, tlv->neighbour, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->neighbour->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->neighbour->length, 1); + + pack.length += tlv->neighbour->length + 2; break; case 4: - len = tlv->network_hash->length + 2; - memcpy(pack.body, tlv->network_hash, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->network_hash->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->network_hash->length, 1); + memcpy(pack.body + pack.length + 2, (char*) &tlv->network_hash->network_hash, 16); + + pack.length += tlv->network_hash->length + 2; break; case 5: - len = tlv->network_state_req->length + 2; - memcpy(pack.body, tlv->network_state_req, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->network_state_req->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->network_state_req->length, 1); + + pack.length += tlv->network_state_req->length + 2; break; case 6: - len = tlv->node_hash->length + 2; - memcpy(pack.body, tlv->node_hash, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->node_hash->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->node_hash->length, 1); + memcpy(pack.body + pack.length + 2, (char*) &tlv->node_hash->node_id, 8); + memcpy(pack.body + pack.length + 10, (char*) &tlv->node_hash->seqno, 2); + memcpy(pack.body + pack.length + 12, (char*) &tlv->node_hash->node_hash, 16); + + pack.length += tlv->node_hash->length + 2; break; case 7: - len = tlv->node_state_req->length + 2; - memcpy(pack.body, tlv->node_state_req, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->node_state_req->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->node_state_req->length, 1); + memcpy(pack.body + pack.length + 2, (char*) &tlv->node_state_req->node_id, 8); + + pack.length += tlv->node_state_req->length + 2; break; case 8: - len = tlv->node_state->length + 2; - memcpy(pack.body, tlv->node_state, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->node_state->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->node_state->length, 1); + memcpy(pack.body + pack.length + 2, (char*) &tlv->node_state->node_id, 8); + memcpy(pack.body + pack.length + 10, (char*) &tlv->node_state->seqno, 2); + memcpy(pack.body + pack.length + 12, (char*) &tlv->node_state->node_hash, 16); + memcpy(pack.body + pack.length + 28, (char*) &tlv->node_state->data, tlv->node_state->length - 26); + + pack.length += tlv->node_state->length + 2; break; case 9: - len = tlv->warning->length + 2; - memcpy(pack.body, tlv->warning, len); - pack.length += len; + memcpy(pack.body + pack.length, (char*) &tlv->warning->type, 1); + memcpy(pack.body + pack.length + 1, (char*) &tlv->warning->length, 1); + memcpy(pack.body + pack.length + 2, (char*) &tlv->warning->message, tlv->warning->length); + + pack.length += tlv->warning->length + 2; break; default: @@ -355,83 +647,101 @@ 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){ - // debug_print("Building packet to send a TLV."); - - // We first need to build the packet, - char packet_buff[1024]; - struct packet pack; - pack.magic = 95; - pack.version = 1; - if (tlv_size > 1020) { - perror(">> Unable to send the tlv, it's size if above 1020 bytes."); - return -1; - } else { - memcpy((void *) pack.body, tlv_to_send, tlv_size); - } - - // Move the content of the paquet struct to a buffer - // That will be send out in a vectorized buffer. - // packet_buff = (char *) pack; - memcpy(&packet_buff,&pack,1024); - - // debug_print("Packet has been built."); - - // Vectorized buffer - struct iovec vec_buff = { .iov_len = sizeof(packet_buff), .iov_base = packet_buff }; - - int error_while_sending = 0; - - // For every dest - for (size_t i = 0; i < dest_list_size; i++) { - // Creating the struct to send out with sendmsg - struct msghdr packet_tlv_send_out = { - .msg_name = &dest_list[i], - .msg_namelen = sizeof(dest_list[i]), - .msg_iov = &vec_buff, - .msg_iovlen = 1 // We have only one iovec buffer. But if we had 2, we would write 2. - }; - - int response_code = sendmsg((int) socket_num, &packet_tlv_send_out, 0); - if (response_code < 0) { - // debug_print("Unable to send out the packet to peer %i", i); - error_while_sending = 1; - continue; - } else if (response_code < sizeof(packet_tlv_send_out)) { - // debug_print("Sent out only part of the packet."); - error_while_sending = 1; - continue; - } else { - // debug_print("Send out packet to peer %i", i); - } - } - - if (error_while_sending == 1) { - // debug_print("Error occured while sending out a packet."); - return -1; - } else { - return 0; - } -} +// TODO This function can be deleted. +// 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, +// char packet_buff[1024]; +// struct packet pack; +// pack.magic = 95; +// pack.version = 1; +// if (tlv_size > 1020) { +// print_debug(">> Unable to send the tlv, it's size is above 1020 bytes."); +// return -1; +// } else { +// memcpy((void *) pack.body, tlv_to_send, tlv_size); +// } +// +// // Move the content of the paquet struct to a buffer +// // That will be send out in a vectorized buffer. +// memcpy(&packet_buff,&pack,1024); +// +// if (DEBUG_LEVEL > 1) { +// print_debug(">> Packet has been built."); +// } +// +// // Vectorized buffer +// struct iovec vec_buff = { .iov_len = sizeof(packet_buff), .iov_base = packet_buff }; +// +// int error_while_sending = 0; +// +// // For every dest +// for (size_t i = 0; i < dest_list_size; i++) { +// // Creating the struct to send out with sendmsg +// struct msghdr packet_tlv_send_out = { +// .msg_name = &dest_list[i], +// .msg_namelen = sizeof(dest_list[i]), +// .msg_iov = &vec_buff, +// .msg_iovlen = 1 // We have only one iovec buffer. But if we had 2, we would write 2. +// }; +// +// int response_code = sendmsg((int) socket_num, &packet_tlv_send_out, 0); +// if (response_code < 0) { +// if (DEBUG_LEVEL > 0) { +// printf("\x1b[31m[DEBUG]\x1b[0m >> Unable to send out the packet to peer %li", i); +// } +// error_while_sending = 1; +// continue; +// } else if (response_code < sizeof(packet_tlv_send_out)) { +// print_debug(">> Sent out only part of the packet."); +// error_while_sending = 1; +// continue; +// } else { +// if (DEBUG_LEVEL > 0) { +// printf("\x1b[31m[DEBUG]\x1b[0m >> Sent out packet to peer %i", i); +// } +// } +// } +// +// if (error_while_sending == 1) { +// print_debug(">> Error occured while sending out a packet."); +// return -1; +// } else { +// return 0; +// } +// } // 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]; // Nothing to do in this case - if(type == 0) + if(type == 0){ + print_debug(">> Found padding TLV type."); return 0; + } // Check that we can read a length - if(pos + 1 >= packet_len) + if(pos + 1 >= packet_len){ + print_debug(">> Reading outside of packet's max length."); return -1; - + } + // 0 1 2 3 = Packet + // 4 = type 5 = tlv_len unsigned char tlv_len = data[pos+1]; // Check that the tlv does not exceed the packet length - if(pos + tlv_len >= packet_len) + if(pos + tlv_len > packet_len){ + print_debug(">> The TLV Length exceeds the packet length\n"); return -1; + } + + if (DEBUG_LEVEL > 1) { + printf("\x1b[31m[DEBUG]\x1b[0m >> TLV has type %i\n", type ); + } // Returns the type of the tlv or -1 if something went wrong switch(type) { @@ -457,6 +767,51 @@ int validate_tlv(char *data, int pos, int16_t packet_len){ return 7; case 8: if(tlv_len < MIN_LEN_NODE_STATE || tlv_len > MAX_LEN_NODE_STATE) return -1; + + /* + // Check if it has the right hash + uint16_t *seqno = (uint16_t*) (data + pos + 10); + uint64_t *id = (uint64_t*) (data + pos + 2); + + pub_data pdata = (pub_data) { + .length = tlv_len, + .id = *id, + .seqno = *seqno, + .data = (unsigned char*) malloc(tlv_len) + }; + + unsigned char *cur_hash = (unsigned char*) (data + pos + 12); + char *cur_message = data + pos + 28; + + unsigned char hash[16]; + + memcpy(pdata.data, cur_message, tlv_len); + + hash_data(&pdata, hash); + + if(memcmp(hash, cur_hash, 16) != 0) { + print_debug(">> Malformed hash."); + printf("\x1b[31m[DEBUG]\x1b[0m >> Received : "); + + for(int x = 0; x < 16; x++){ + printf("%02x", hash[x]); + fflush(0); + } + + printf("\n"); + printf("\x1b[31m[DEBUG]\x1b[0m >> Received : "); + + for(int x = 0; x < 16; x++){ + printf("%02x", cur_hash[x]); + fflush(0); + } + + printf("\n"); + + return -1; + + } + */ return 8; case 9: return 9; @@ -468,99 +823,158 @@ int validate_tlv(char *data, int pos, int16_t packet_len){ // For every packet recivied, // then we make sure it's conform // We then extract the data from it to make it easy to work with -int check_header(char * received_data_buffer[], int received_data_len, struct packet * packet_to_return){ +int check_header(char * received_data_buffer, int received_data_len, struct packet * packet_to_return){ packet_to_return = (packet*) received_data_buffer; // We need to check a few things ; // The first byte must be worth 95, if (packet_to_return->magic != 95) { - perror(">> The magic number of the packet is no good."); + print_debug(">> The magic number of the packet is no good."); return -1; } // The second byte must be worth 1, if (packet_to_return->version != 1) { - perror(">> The version number of the packet is no good."); + print_debug(">> The version number of the packet is no good."); return -1; } - if (packet_to_return->length + 4 > received_data_len ) { - perror(">> The packet length is bigger than the UDP datagram, which is not possible with the current laws of physics."); + // Convert to hardware order. + ((packet*) packet_to_return)->length = be16toh(((packet*) packet_to_return)->length); + if (packet_to_return->length + 4 < received_data_len ) { + print_debug(">> The packet length is bigger than the UDP datagram, which is not possible with the current laws of physics."); return -1; } return 0; } -// If the sender is not in the neighbourhood, and we have 15 neighbours, we -// ignore the packet. Otherwise, we add him to the neighbourhood, marked as -// temporary. -int update_neighbours(){ - return 0; -}; - int add_message(char * message, int message_len){ - return 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; + } + + 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 packet_len, struct sockaddr_in6 *sender, int socket_num){ - int pos = 0; - unsigned char tlv_len, hash[16]; +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."); + return -1; + } + int nbr_of_tlvs = 0; + + int pos = 4; + unsigned char tlv_len, hash[16], hash2[16]; char warn[32]; - tlv new_tlv, cur_tlv; + + // The TLV we are going to send back. + tlv new_tlv; new_tlv.pad1 = NULL; - cur_tlv.pad1 = NULL; - list *tmp_list; - pub_data *pdata; + + list * tmp_list; + pub_data * pdata; + + // holds the random neighbour we send back in case of a neighbour_req. struct neighbour_peer *random_neighbour; + // memset(random_neighbour, 0, sizeof(struct neighbour_peer)); + + // Holds the new neighbour send to us by a "neighbour tlv" struct sockaddr_in6 new_neighbour; + // We create the packet in which we are going to send back our responses. packet pack = (packet) {.magic = 95, .version = 1, .length = 0}; memset(pack.body, 0, 1020); - int ifindex = if_nametoindex("eth0"); + int ifindex = 0; - if(ifindex == 0) { - perror("if_nametoindex failed"); - return -1; - } + // Temporary values + uint16_t *port, *seqno; + uint64_t *id; + unsigned char *cur_hash, *ip; + char *cur_message; - while(pos < packet_len) { - switch(validate_tlv(data, pos, packet_len)) { + while(pos < total_packet_len) { + // Making sure the current TLV we are looking at is valid. + // TODO : I think we should reset all the structs here. + // memset(random_neighbour, 0, sizeof(struct neighbour_peer)); + // memset(pdata, 0, sizeof(struct pub_data)); + // memset(tmp_list, 0, sizeof(struct list)); + memset(hash, 0, 16); + memset(warn, 0, 32); + tlv_len = 0; + + switch(validate_tlv(data, pos, total_packet_len)) { case 0: // We received a padding tlv so it is ignored + print_debug(">> Received padding tlv, ignoring..."); pos += 1; - + nbr_of_tlvs++; break; case 1: // We received a padding tlv so it is ignored + print_debug(">> Received padding(n) tlv, ignoring..."); tlv_len = data[pos+1]; pos += tlv_len + 2; + nbr_of_tlvs++; break; case 2: - // We received a neighbour request so a random neighbor tlv has to be sent + // We received a neighbour request so a random neighbor tlv has to be sent + print_debug(">> Received neighbour request, sending out a neighbour address."); // Send a neighbour tlv random_neighbour = get_random_neighbour(); + if (random_neighbour == NULL) { + print_debug(">> Failed to get a random neighbour, failing..."); + return -1; + } + + // TODO : Seems to be a bug here, as this frees the new_tlv build_neighbour(&new_tlv, random_neighbour->ip, random_neighbour->port); + // TODO : I suppose that since new_tlv is freed above, add_tlv ads an empty + // value to the packet ? add_tlv(&pack, &new_tlv, sender, socket_num); // The position is updated tlv_len = data[pos+1]; pos += tlv_len + 2; + nbr_of_tlvs++; break; case 3: + + print_debug(">> Received neighbour tlv, sending back network hash."); // We received a neighbour tlv so a tlv network hash is sent to that address - cur_tlv.neighbour = (neighbour*) (data + pos); + ip = (unsigned char*) (data + pos + 2); + port = (uint16_t*) (data + pos + 18); // Init dest socket memset(&new_neighbour, 0, sizeof(new_neighbour)); new_neighbour.sin6_family = AF_INET6; - memcpy(&new_neighbour.sin6_addr, &cur_tlv.neighbour->ip, 16); - new_neighbour.sin6_port = htons(LISTEN_PORT); + memcpy(&new_neighbour.sin6_addr, ip, 16); + new_neighbour.sin6_port = be16toh(*port); new_neighbour.sin6_scope_id = ifindex; // Build network hash @@ -570,78 +984,132 @@ int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, // The position is updated tlv_len = data[pos+1]; pos += tlv_len + 2; + nbr_of_tlvs++; break; case 4: - // We reveived a network hash tlv so we compare the hash with our own, if they differ we send a network state request tlv - cur_tlv.network_hash = (network_hash*) (data + pos); + + print_debug(">> Received network_hash, comparing with our own.."); + // We reveived a network hash tlv so we compare the hash with our own, + // if they differ we send a network state request tlv + cur_hash = (unsigned char*) (data + pos + 2); + hash_network(data_list, hash); - if(memcmp(hash, cur_tlv.network_hash->network_hash, 16) == 0) { - build_network_state_req(&new_tlv); + if (DEBUG_LEVEL > 1) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Our hash : "); + for(int x = 0; x < 16; x++){ + printf("%02x", hash[x]); + fflush(0); + } + printf("\n"); + printf("\x1b[31m[DEBUG]\x1b[0m >> Received : "); + for(int x = 0; x < 16; x++){ + printf("%02x", cur_hash[x]); + fflush(0); + } + printf("\n"); + } + + if(memcmp(hash, cur_hash, 16) != 0) { + print_debug(">> Sending out our network hash."); + build_network_state_req(&new_tlv); + send_single_tlv(&new_tlv, sender, socket_num); + } else { + print_debug(">> We're up to date."); + } + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; + nbr_of_tlvs++; + + break; + case 5: + // We received a network state request tlv + // so a series of tlv node hash have to be sent for each data known + print_debug(">> Received network state request, sending back hashes for messages."); + // for each known data build a node hash and add to packet + tmp_list = data_list; + + while(tmp_list != NULL) { + pdata = (pub_data*) tmp_list->data; + build_node_hash(&new_tlv, pdata->id, pdata->seqno, pdata->data, pdata->length); add_tlv(&pack, &new_tlv, sender, socket_num); - } + tmp_list = tmp_list->next; + + if (DEBUG_LEVEL > 1) { + // TODO wtf is this ? + printf(" >> \x1b[31m[DEBUG]\x1b[0m %lu\n", *(uint64_t*) (pack.body + 2)); + } + + } // The position is updated tlv_len = data[pos+1]; pos += tlv_len + 2; - break; - case 5: - // We received a network state request tlv so a series of tlv node hash have to be sent for each data known - - // for each known data build a node hash and add to packet - tmp_list = data_list; - - while(tmp_list != NULL) { - pdata = (pub_data*) tmp_list->data; - build_node_hash(&new_tlv, pdata->id, pdata->seqno, pdata->data); - add_tlv(&pack, &new_tlv, sender, socket_num); - } - - // The position is updated - pos += 2; - break; case 6: - // We received a node hash tlv so if there is no entry for node_id in the data list or the hashes differ we send a node state request, if the hashes are identical nothing has to be done - cur_tlv.node_hash = (node_hash*) (data + pos); - pdata = get_data(cur_tlv.node_hash->node_id); + // We received a node hash tlv so + // if there is no entry for node_id in the data list or the hashes differ + // we send a node state request, + //if the hashes are identical nothing has to be done + print_debug(">> Received node hash, updating message entry..."); + + id = (uint64_t*) (data + pos + 2); + cur_hash = (unsigned char*) (data + pos + 12); + + pdata = get_data(be64toh(*id)); // If data is found for this id then we check that both hashes are the same if(pdata != NULL) { + print_debug(">> Comparing hashes..."); // 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) { + if(memcmp(hash, cur_hash, 16) == 0) { // The position is updated tlv_len = data[pos+1]; - pos += 2; - + pos += tlv_len + 2; + print_debug(">> Both hashes are the same, nothing to do."); break; } } + print_debug(">> No hash found, or hashes are different, sending back node state request."); // If no pub_data was found or the hashes differ then we send a node state request - build_node_state_req(&new_tlv, cur_tlv.node_hash->node_id); + build_node_state_req(&new_tlv, be64toh(*id)); add_tlv(&pack, &new_tlv, sender, socket_num); + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Sending node state request for node %lu...\n", be64toh(*id)); + } + // The position is updated tlv_len = data[pos+1]; pos += tlv_len + 2; break; case 7: - // We received a node state request tlv so a node state tlv for this node id has to be sent, if no pub_data exists for this id nothing is sent - cur_tlv.node_state_req = (node_state_req*) (data + pos); - pdata = get_data(cur_tlv.node_state_req->node_id); + + // We received a node state request tlv + // so a node state tlv for this node id has to be sent, + // if no pub_data exists for this id nothing is sent + print_debug(">> Received node state request. Processing..."); + + id = (uint64_t*) (data + pos + 2); + + pdata = get_data(be64toh(*id)); if(pdata != NULL) { build_node_state(&new_tlv, pdata->id, pdata->seqno, pdata->data, pdata->length); add_tlv(&pack, &new_tlv, sender, socket_num); - } + } else { + print_debug(">> Found no data for the requested node, skipping..."); + } // The position is updated tlv_len = data[pos+1]; @@ -649,32 +1117,138 @@ int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, break; case 8: - // We received a node state tlv so we add it to the data list or update the data stored - cur_tlv.node_state = (node_state*) (data + pos); + // We received a node state tlv so + // we add it to the data list + // or update the data stored + print_debug(">> Received node state, updating..."); - add_data(cur_tlv.node_state->length - 26, cur_tlv.node_state->node_id, cur_tlv.node_state->seqno, cur_tlv.node_state->data); + tlv_len = data[pos + 1]; + id = (uint64_t*) (data + pos + 2); + seqno = (uint16_t*) (data + pos + 10); + cur_hash = (unsigned char*) (data + pos + 12); + cur_message = data + pos + 28; + print_debug(">> Received message ! "); + // printf("Type : %d\n", data[pos] ); + // printf("Length : %d\n", tlv_len ); + // printf("Node ID : %lu\n", be64toh(*id) ); + // printf("Seqno : %hu\n", be16toh(*seqno) ); + // printf("Hash :"); + // for(int x = 0; x < 16; x++){ + // printf("%02x", cur_hash[x]); + // fflush(0); + // } + // printf("\n"); + // for(int x = 0; x < tlv_len - 26; x++){ + // printf("%c", cur_message[x]); + // fflush(0); + // } + // printf("\n"); + + // Check if it has the right hash + pub_data pdata_check = (pub_data) { + .length = tlv_len - 26, + .id = be64toh(*id), + .seqno = be16toh(*seqno), + .data = (char*) malloc(tlv_len) + }; + + memcpy(pdata_check.data, cur_message, tlv_len - 26); + + hash_data(&pdata_check, hash2); + + // print_debug(">> Built message: "); + // printf("Type : %d\n", data[pos] ); + // printf("Length : %d\n", pdata_check.length + 26); + // printf("Node ID : %lu\n", pdata_check.id); + // printf("Seqno : %hu\n", pdata_check.seqno); + // printf("Hash :"); + // for(int x = 0; x < 16; x++){ + // printf("%02x", hash2[x]); + // fflush(0); + // } + // printf("\n"); + // for(int x = 0; x < tlv_len - 26; x++){ + // printf("%c", pdata_check.data[x]); + // fflush(0); + // } + // printf("\n"); + + if(memcmp(hash2, cur_hash, 16) != 0) { + print_debug(">> Malformed hash."); + printf("\x1b[31m[DEBUG]\x1b[0m >> Calculated : "); + + for(int x = 0; x < 16; x++){ + printf("%02x", hash2[x]); + fflush(0); + } + + printf("\n"); + printf("\x1b[31m[DEBUG]\x1b[0m >> Received : "); + + for(int x = 0; x < 16; x++){ + printf("%02x", cur_hash[x]); + fflush(0); + } + + printf("\n"); + + pos += tlv_len + 2; + break; + } + + free(pdata_check.data); + + // Compare hashes + pdata = get_data(be64toh(*id)); + + // If data is found for this id then we check that both hashes are the same + if(pdata != NULL) { + print_debug(">> Comparing hashes..."); + // We hash the data stored in the data list + memset(hash, 0, 16); + hash_data(pdata, hash); + + // If both hashes are the same then nothing has to be done + if(memcmp(hash, cur_hash, 16) == 0) { + // The position is updated + pos += tlv_len + 2; + + break; + } + + } + + // Else, we update the data + int rc = add_data(tlv_len - 26, be64toh(*id), be16toh(*seqno), cur_message, pdata); + if (rc < 0) { + print_error("Error while adding node state !"); + } else { + print_info("Received a message."); + } // The position is updated - tlv_len = data[pos+1]; pos += tlv_len + 2; break; case 9: + print_debug(">> \aReceived warning !"); // We received a warning tlv so it's message is printed - cur_tlv.warning = (warning*) (data + pos); + tlv_len = data[pos+1]; + cur_message = data + pos + 2; // Print exactly new_tlv.length characters from new_tlv.message - sprintf(warn, ">> WARNING:\n%%.%ds", cur_tlv.warning->length + 1); - printf(warn, cur_tlv.warning->message); + sprintf(warn, ">> WARNING:\n%%.%ds\n", tlv_len + 1); + printf(warn, cur_message); // The position is updated - tlv_len = data[pos+1]; pos += tlv_len + 2; break; default: // A malformed packet was found so we stop looking for more packets and send a warning tlv strcpy(warn, "Packet is malformed."); + print_debug(">> Malformed packet, we won't treat it."); + print_debug(">> Sending back a Warning to sender."); build_warning(&new_tlv, warn, strlen(warn)); add_tlv(&pack, &new_tlv, sender, socket_num); @@ -686,52 +1260,113 @@ int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, free(new_tlv.pad1); // If the packet still has data in it then send it - if(pack.length > 0) + if(pack.length > 0){ send_packet((char*) &pack, pack.length, sender, socket_num); + } + // print_data(data_list); return 0; } -int listen_for_packets(char * received_data_buffer[], int received_data_len, struct sockaddr_in6 * sender, int sock_fd){ +int listen_for_packets(char * received_data_buffer, int received_data_len, struct sockaddr_in6 * sender, int sock_fd){ // We verify the received packet is well formated, // and we return it in the struct designed to work with it. struct packet formated_rec_datagram; if(check_header(received_data_buffer, received_data_len, &formated_rec_datagram) < 0){ - perror(">> Error while checking the header, aborting this packet, by choice, and conviction."); + print_debug(">> Error while checking the header, aborting this packet, by choice, and conviction."); return -1; } - // TODO : Add the neighbour check here. + // Neighbour check + struct in6_addr ip = sender->sin6_addr; + int16_t port = htobe16(sender->sin6_port); + + int rc = add_n_update_neighbour(&ip, port); + if( rc == -1) { + print_debug(">> We have enough peers, we won't add him.."); + return -3; + } else if (rc == 1){ + print_debug(">> Peer was added to the table.\a"); + } else { + print_debug(">> Updated the time it was last seen."); + } - // struct tlv_list received_tlvs; - // if (validate_tlvs(formated_rec_datagram) < 0) int nbr_success_tlv = work_with_tlvs(received_data_buffer, received_data_len, sender, sock_fd); if (nbr_success_tlv < 0){ - perror(">> Error while treating the TLVs of the packet."); - printf(">> Managed to deal with %i TLVs\n", -nbr_success_tlv ); + print_debug(">> Error while treating the TLVs of the packet."); + if (DEBUG_LEVEL > 1) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Managed to deal with %i TLVs\n", -nbr_success_tlv ); + } return -2; } else { - printf(">> Done working with the TLVs of the packet, listening for new packets.\n"); + print_debug(">> Done working with the TLVs of the packet, listening for new packets."); return 0; } } -int t_ask_for_more_peers(){ - return 0; +int t_ask_for_more_peers(int sock_fd){ + if (DEBUG_LEVEL > 1) { + print_peers(neighbour_list); + sleep(3); + } + return ask_for_peers(sock_fd); } -int t_get_network_state(){ +/* For every peer we know about, we send out a TLV network hash +*/ +int t_get_network_state(int sock_fd){ + print_debug(">> Getting network state..."); + print_debug(">> Sending out a TLV network hash to every peer we know of."); + if (neighbour_list == NULL) { + print_error("Our peer list is empty !"); + print_error("Skipping.."); + return -1; + } else { + // Build the network hash + // We use another variable so that we don't interfier with the current list + list * tmp_list = neighbour_list; + while (tmp_list != NULL) { + + neighbour_peer * peer = (neighbour_peer *) tmp_list->data; + tlv new_tlv; + memset(&new_tlv, 0, sizeof(union tlv)); + + // Create the structure for the receiver. + struct sockaddr_in6 receiver; + memset(&receiver, 0, sizeof(struct sockaddr_in6)); + + receiver.sin6_family = AF_INET6; + receiver.sin6_addr = peer->ip; + receiver.sin6_port = htobe16(peer->port); + receiver.sin6_scope_id = 0; + + // Send out a TLV network state. + if (build_network_hash(&new_tlv, data_list) < 0) { + print_error("Error while building a network hash."); + return -1; + } else { + if (send_single_tlv(&new_tlv, &receiver, sock_fd) < 0) { + print_error("Error while sending a network hash to a peer."); + return -1; + } else { + print_debug(">> Sent network hash to a peer."); + } + } + + tmp_list = tmp_list->next; + } + } return 0; } int t_update_neighbours(){ - return 0; + return update_neighbours(); } int run_node(int sock_fd){ - printf(">> Running node...\n"); + print_debug(">> Running node..."); int ret; ssize_t bytes; @@ -741,7 +1376,7 @@ int run_node(int sock_fd){ // Init the ~20s delay for node update. srand(time(NULL)); - int delay = time(NULL) + 20; + time_t delay = time(NULL) + 5; /* Descriptor zero is stdin */ fds[0].fd = 0; @@ -754,13 +1389,12 @@ int run_node(int sock_fd){ */ while (1) { - if (time(NULL) >= delay) { - printf(">> Asking for more peers...\n"); - t_ask_for_more_peers(); - printf(">> Updating neighbours...\n"); + if(time(NULL) >= delay) { + t_ask_for_more_peers(sock_fd); t_update_neighbours(); - printf(">> Getting network state...\n"); - t_get_network_state(); + t_get_network_state(sock_fd); + print_data(data_list); + sleep(3); delay = time(NULL) + 20 + (rand() % 10); } @@ -774,22 +1408,21 @@ int run_node(int sock_fd){ // } // printf("\n"); - /* Call poll() */ - ret = poll(fds, 2, 5); + ret = poll(fds, 2, 10); if (ret < 0) { - printf(">> Error - poll returned error: %s\n", strerror(errno)); + print_error("Poll returned error"); break; } else if (ret > 0) { /* Regardless of requested events, poll() can always return these */ if (fds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - printf("Error - poll indicated stdin error\n"); + print_error("Poll indicated stdin error\n"); break; } if (fds[1].revents & (POLLERR | POLLHUP | POLLNVAL)) { - printf("Error - poll indicated socket error\n"); + print_error("Poll indicated socket error\n"); break; } @@ -797,15 +1430,29 @@ int run_node(int sock_fd){ if (fds[0].revents & (POLLIN | POLLPRI)) { bytes = read(0, input_buffer, sizeof(input_buffer)); if (bytes < 0) { - printf("Error - stdin error: %s\n", strerror(errno)); + print_error("stdin error"); break; } + // Remove trailing \n input_buffer[strcspn(input_buffer, "\n")] = 0; - printf(">> Adding following message to the table : “%s”\n", input_buffer ); - // Add message to the message table. - if (add_message(&input_buffer, bytes) < 0) { - perror(">> Error while trying to add the message to the list of messages, please try again.."); - } + + + if (strcmp("",input_buffer) == 0){ + print_info(">> Printing all messages we know of so far :"); + print_data_info(data_list); + } else { + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Adding following message to the table : “%s”\n", input_buffer ); + } + // Add message to the message table. + if (add_message(input_buffer, bytes-1) < 0) { + print_debug(">> Error while trying to add the message to the list of messages, please try again.."); + // Reset buffer + memset(input_buffer, 0, sizeof(input_buffer)); + } else { + print_info(">> Added message to the message list."); + } + } } // Read data from the socket ( incoming packet ) @@ -827,19 +1474,30 @@ int run_node(int sock_fd){ bytes = recvmsg(sock_fd, &msg_from_peer, 0); if (bytes < 0) { - printf("Error - recvfrom error: %s\n", strerror(errno)); + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Error - recvfrom error: %s\n", strerror(errno)); + } break; } if (bytes > 0) { - printf("Received: %.*s\r", (int)bytes, output_buffer); + if (DEBUG_LEVEL > 0) { + printf("\x1b[31m[DEBUG]\x1b[0m >> Received %i bytes as : %s\n", (int)bytes, output_buffer); + } // Treat incoming packets. - int work_tlv_status = listen_for_packets(&output_buffer, bytes, &sender, sock_fd); - if (work_tlv_status < 0) { - perror(">> Error while treating the incoming packet."); - } + int work_tlv_status = listen_for_packets(output_buffer, bytes, &sender, sock_fd); + if (work_tlv_status == -3) { + print_debug(">> Received paquet from peer not in peer list, and we have enough peers, ignoring..."); + } else if (work_tlv_status < 0) { + print_error("Error while treating the incoming packet."); + } + // Reset buffer + memset(output_buffer, 0, sizeof(output_buffer)); } } } else { + // TODO : Here, we can write all of the current messages we have in stack + // to a file, or to stdout. + // TODO : Same as above, but for the peers have know about. continue; } @@ -848,38 +1506,129 @@ int run_node(int sock_fd){ return 0; } -int bootstrap_node(int * sock_fd){ - printf(">> Boostraping node...\n"); + +// This function runs once, and sets the sock_fd as well as the neighbourhood +int bootstrap_node(int * sock_fd, char * root_peer_ip, uint16_t root_peer_port){ + print_debug(">> Boostraping node..."); struct sockaddr_in6 server_addr; /* Create UDP socket */ * sock_fd = socket(AF_INET6, SOCK_DGRAM, 0); if ( * sock_fd < 0) { - printf("Error - failed to open socket: %s\n", strerror(errno)); - return -1; + print_error("Failed to open socket"); + exit(-1); } /* Bind socket */ memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin6_family = AF_INET6; - // server_addr.sin6_addr.in6_addr = htonl(INADDR_ANY); - server_addr.sin6_port = htons(LISTEN_PORT); + // server_addr.sin6_addr = INADDR_ANY; + server_addr.sin6_port = LISTEN_PORT; if (bind( * sock_fd, (struct sockaddr *)(&server_addr), sizeof(server_addr)) < 0) { - printf("Error - failed to bind socket: %s\n", strerror(errno)); - return -2; + print_error("Failed to bind socket"); + perror(""); + exit(-1); } - printf(">> Boostraping done.\n"); + print_debug(">> Adding the first root peers to the list..."); + + // Get the address via getaddrinfo. + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET6; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = 0; + hints.ai_flags = (AI_V4MAPPED | AI_ALL); // get back ipv4 mapped to ipv6 + + struct addrinfo *res; + print_debug(">> Resolving root peer name via getaddrinfo"); + int rc = getaddrinfo(root_peer_ip, "http", &hints, &res); + if(rc != 0) { + print_error("Failed to resolve hostname, exiting..."); + exit(1); + } + + neighbour_list = malloc(sizeof(struct list)); + memset(neighbour_list, 0, sizeof(struct list)); + + // For every address given to us by getaddrinfo, we create a new peer. + struct addrinfo *p; + struct neighbour_peer *peer ; + + list * tmp = neighbour_list; + for(p = res; p != NULL; p = p->ai_next) { + peer = (neighbour_peer*) malloc(sizeof(neighbour_peer)); + memcpy(&peer->ip, &((struct sockaddr_in6 *) p->ai_addr)->sin6_addr, sizeof(struct in6_addr)); + peer->port = root_peer_port; + peer->is_temporary = 0; + + // set last_seen time + peer->last_seen = time(NULL); + + if (DEBUG_LEVEL > 0) { + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,&peer->ip,(char * restrict) buff_str_ip, 1024); + printf("\x1b[31m[DEBUG]\x1b[0m >> Adding %s @ %i to peer list.\n", ip_str, root_peer_port ); + } + + + + // Add new peer to the list. + list *node = (list*) malloc(sizeof(list)); + node->data = (void*) peer; + node->next = NULL; + + // Goint to the end of the list + while(tmp->next != NULL){ + tmp = tmp->next; + } + tmp->next = node; + } + + neighbour_list = tmp; + + print_peers(neighbour_list); + + print_debug(">> Initializing data list..."); + data_list = (list*) malloc(sizeof(list)); + memset(data_list, 0, sizeof(struct 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; + + freeaddrinfo(res); + print_debug(">> Boostraping done."); return 0; } int main(int argc, const char *argv[]) { - printf(">> Starting node\n"); + + if (argc != 3) { + print_error("Usage : ./dazibao "); + exit(-1); + } + + char *end; + intmax_t val = strtoimax(argv[2], &end, 10); + if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == argv[2] || *end != '\0'){ + print_error("Conversion of port number failed, please choose a smaller number."); + } + uint16_t root_peer_port = (uint16_t) val; + char * root_peer_ip = (char *) argv[1]; + + setlocale(LC_ALL, ""); + print_debug(">> Starting node"); int sock_fd; - bootstrap_node(&sock_fd); + bootstrap_node(&sock_fd, root_peer_ip, root_peer_port); + welcome(); run_node(sock_fd); close(sock_fd); diff --git a/src/node.h b/src/node.h index ba28d61..3dfe7db 100644 --- a/src/node.h +++ b/src/node.h @@ -12,6 +12,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include /* 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 @@ -20,9 +28,9 @@ */ typedef struct neighbour_peer { struct in6_addr ip; - int16_t port; + uint16_t port; char is_temporary; - struct timeval last_seen; + time_t last_seen; } neighbour_peer; // The strucuture to hold the messages @@ -34,8 +42,8 @@ typedef struct neighbour_peer { typedef struct pub_data { unsigned char length; - int64_t id; - int16_t seqno; + uint64_t id; + uint16_t seqno; char *data; } pub_data; @@ -48,33 +56,40 @@ typedef struct list { #include "tlv.h" #include "hash.h" #include "parser.h" +#include "debug.h" // On which port do we listen to #define LISTEN_PORT 1212 // The node ID -#define NODE_ID 42675882021843277 +#define NODE_ID 4209169790617845760 +// #define NODE_ID 42675882021843277 +// #define NODE_ID 1312 // The number of neighbours // The neighbour table has 15 entries #define NEIGHBOUR_MAX 15 -// TODO +// The adress of the main peer +#define ROOT_PEER_ADDR "::1" + // fonctions signatures -int listen_for_packets(char * received_data_buffer[], int received_data_len, struct sockaddr_in6 * sender, int sock_fd); +int listen_for_packets(char * received_data_buffer, int received_data_len, struct sockaddr_in6 * sender, int sock_fd); -int check_header(char * received_data_buffer[], int received_data_len, packet * packet_to_return); +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 work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, int socket_num); +int ask_for_peers(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); @@ -84,39 +99,53 @@ 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); -// threaded functions -int t_ask_for_more_peers(); +/* Check our peer list. If we have less than 5 peers, send out a + TLV NEIGHBOUR_REQUEST to a random peer +*/ +int t_ask_for_more_peers(int sock_fd); +/* We look at every peer, if he is marked as is_temporary, AND we didn't get a + packet from him in the last 70 sec, we remove him from the list. +*/ int t_update_neighbours(); -int t_get_network_state(); +/* We send out a TLV Network Hash to every peer, and we expect getting a TLV + Network state from each of them. +*/ +int t_get_network_state(int sock_fd); // This function adds a message to the message table. int add_message(char * message, int message_len); // This functions creates the structures needed for the rest of the project, // creates the socket, and returns all of it. -int bootstrap_node(int * sock_fd); +int bootstrap_node(int * sock_fd, char * root_peer_ip, uint16_t root_peer_port); // Helper functions int len_list(list *l); neighbour_peer *get_random_neighbour(); +// Search for this peer in the neighbour table +neighbour_peer *get_neighbour(struct in6_addr *ip, uint16_t port); + +// Return -1 if the peer could not be added, 0 if it could or if it was already in the table +int add_n_update_neighbour(struct in6_addr *ip, uint16_t port); + // get data associated with id, if it doesn't exist return NULL -pub_data *get_data(int64_t id); +pub_data *get_data(uint64_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, uint64_t id, uint16_t seqno, char *data); // add new data to data list -void add_data(unsigned char len, int64_t id, int16_t seqno, char *data); +int add_data(unsigned char len, uint64_t id, uint16_t seqno, char *data, pub_data *found); #endif diff --git a/src/node.o b/src/node.o deleted file mode 100644 index 21df733..0000000 Binary files a/src/node.o and /dev/null differ diff --git a/src/parser.o b/src/parser.o deleted file mode 100644 index 0cdd296..0000000 Binary files a/src/parser.o and /dev/null differ diff --git a/src/tlv.c b/src/tlv.c index 1f5b4e8..ebf9830 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -1,36 +1,11 @@ #include "tlv.h" -// creer un tlv -int build_tlv(tlv *tlv, cmd_token token) { - switch(token.type) { - case NEIGHBOUR_REQ: - // a remplir - break; - case NETWORK_STATE_REQ: - // a remplir - break; - case NODE_STATE_REQ: - // a remplir - break; - case POST: - // a remplir - break; - case ERROR: - printf("Wrong format, use 'req {neighbour | network state | node state}' or 'post {message}'"); - break; - default: - perror("Unrecognized tlv type."); - return -1; - } - - return -1; -} - int build_pad1(tlv *tlv) { // Free the previously allocated memory free(tlv->pad1); pad1 *new = (pad1*) malloc(sizeof(pad1)); + memset(new, 0, sizeof(pad1)); if(new == NULL) return -1; @@ -47,6 +22,7 @@ int build_padn(tlv *tlv, size_t len) { free(tlv->pad1); padn *new = (padn*) malloc(sizeof(padn)); + memset(new, 0, sizeof(padn)); if(new == NULL) return -1; @@ -65,9 +41,11 @@ int build_neighbour_req(tlv *tlv) { free(tlv->pad1); neighbour_req *new = (neighbour_req*) malloc(sizeof(neighbour_req)); + memset(new, 0, sizeof(neighbour_req)); - if(new == NULL) + if(new == NULL){ return -1; + } new->type = 2; new->length = 0; @@ -79,9 +57,14 @@ int build_neighbour_req(tlv *tlv) { int build_neighbour(tlv *tlv, struct in6_addr ip, int16_t port) { // Free the previously allocated memory + // TODO : why do we free this part ? Doesn't it mean that, once the + // tlv has entered this function, it's not on the heap anymore, + // and thus, setting a value will not be accessible from other part of the + // code ? free(tlv->pad1); neighbour *new = (neighbour*) malloc(sizeof(neighbour)); + memset(new, 0, sizeof(neighbour)); if(new == NULL) return -1; @@ -89,7 +72,7 @@ int build_neighbour(tlv *tlv, struct in6_addr ip, int16_t port) { new->type = 3; new->length = 18; new->ip = ip; - new->port = port; + new->port = htobe16(port); tlv->neighbour = new; @@ -101,13 +84,14 @@ int build_network_hash(tlv *tlv, list *data_list) { free(tlv->pad1); network_hash *new = (network_hash*) malloc(sizeof(network_hash)); + memset(new, 0, sizeof(network_hash)); if(new == NULL) return -1; new->type = 4; new->length = 16; - hash_network(data_list, (unsigned char*) new->network_hash); + hash_network(data_list, new->network_hash); tlv->network_hash = new; @@ -119,6 +103,7 @@ int build_network_state_req(tlv *tlv) { free(tlv->pad1); network_state_req *new = (network_state_req*) malloc(sizeof(network_state_req)); + memset(new,0,sizeof(network_state_req)); if(new == NULL) return -1; @@ -131,70 +116,66 @@ 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, uint64_t node_id, uint16_t seqno, char *data, unsigned char length) { // Free the previously allocated memory free(tlv->pad1); node_hash *new = (node_hash*) malloc(sizeof(node_hash)); + memset(new,0,sizeof(node_hash)); if(new == NULL) return -1; new->type = 6; new->length = 26; - new->node_id = node_id; - new->seqno = seqno; + new->node_id = htobe64(node_id); + new->seqno = htobe16(seqno); - pub_data pdata = (pub_data) {.id = node_id, .seqno = seqno, .data = data}; - hash_data(&pdata, (unsigned char*) new->node_hash); + pub_data pdata = (pub_data) {.length = length, .id = node_id, .seqno = seqno, .data = data}; + hash_data(&pdata, new->node_hash); tlv->node_hash = new; return 0; } -int build_node_state_req(tlv *tlv, int64_t node_id) { +int build_node_state_req(tlv *tlv, uint64_t node_id) { // Free the previously allocated memory free(tlv->pad1); node_state_req *new = (node_state_req*) malloc(sizeof(node_state_req)); + memset(new, 0, sizeof(node_state_req)); if(new == NULL) return -1; new->type = 7; new->length = 8; - new->node_id = node_id; + new->node_id = htobe64(node_id); tlv->node_state_req = new; 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, uint64_t node_id, uint16_t seqno, char *data, size_t data_len) { // Free the previously allocated memory free(tlv->pad1); node_state *new = (node_state*) malloc(sizeof(node_state)); - int len = data_len + 26; + memset(new, 0, sizeof(node_state)); if(new == NULL) return -1; - // en mettant cet octet à 0 on est surs de traiter un champ data de taille 192 max - if(len > 192) { - data[192] = 0; - len = 192; - } - new->type = 8; - new->length = 26 + len; - new->node_id = node_id; - new->seqno = seqno; - memcpy(new->data, data, len); + new->length = data_len + 26; + new->node_id = htobe64(node_id); + new->seqno = htobe16(seqno); + memcpy(new->data, data, data_len); - pub_data pdata = (pub_data) {.id = node_id, .seqno = seqno, .data = data}; - hash_data(&pdata, (unsigned char*) new->node_hash); + pub_data pdata = (pub_data) {.length = data_len, .id = node_id, .seqno = seqno, .data = data}; + hash_data(&pdata, new->node_hash); tlv->node_state = new; @@ -206,17 +187,13 @@ int build_warning(tlv *tlv, char *message, size_t message_len) { free(tlv->pad1); warning *new = (warning*) malloc(sizeof(warning)); + memset(new, 0, sizeof(warning)); + int len = message_len; if(new == NULL) return -1; - // en mettant cet octet à 0 on est surs de traiter un champ message de taille 256 max - if(len > 256) { - message[256] = 0; - len = 256; - } - new->type = 9; new->length = len; memcpy(new->message, message, len); diff --git a/src/tlv.h b/src/tlv.h index d10d3c9..d976faf 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; @@ -53,7 +53,7 @@ typedef struct neighbour { typedef struct network_hash { unsigned char type; unsigned char length; - char network_hash[16]; + unsigned char network_hash[16]; } network_hash; // 2 octets @@ -66,25 +66,25 @@ typedef struct network_state_req { typedef struct node_hash { unsigned char type; unsigned char length; - int64_t node_id; - int16_t seqno; - char node_hash[16]; + uint64_t node_id; + uint16_t seqno; + unsigned char node_hash[16]; } node_hash; // 10 octets typedef struct node_state_req { unsigned char type; unsigned char length; - int64_t node_id; + uint64_t node_id; } node_state_req; // 28 octets min, 220 octets max (data 0 -> 192) typedef struct node_state { unsigned char type; unsigned char length; - int64_t node_id; - int16_t seqno; - char node_hash[16]; + uint64_t node_id; + uint16_t seqno; + unsigned 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_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_hash(tlv *tlv, uint64_t node_id, uint16_t seqno, char *data, unsigned char length); +int build_node_state_req(tlv *tlv, uint64_t node_id); +int build_node_state(tlv *tlv, uint64_t node_id, uint16_t seqno, char *data, size_t data_len); int build_warning(tlv *tlv, char *message, size_t message_len); #endif diff --git a/src/tlv.o b/src/tlv.o deleted file mode 100644 index 1e8ab96..0000000 Binary files a/src/tlv.o and /dev/null differ