diff --git a/src/node.c b/src/node.c index 499651d..689ce52 100644 --- a/src/node.c +++ b/src/node.c @@ -43,6 +43,121 @@ neighbour_peer *get_random_neighbour() { return (neighbour_peer*) tmp->data; } +// get data associated with id, if it doesn't exist return NULL +pub_data *get_data(long id) { + list *tmp = data_list; + pub_data *data; + + while(tmp != NULL) { + data = (pub_data*) tmp->data; + + if(data->id == id) + return data; + } + + return NULL; +} + +// Take data as args and create a pub_data structure in the heap +pub_data *copy_data(unsigned char len, long id, short seqno, char *data) { + pub_data *new_data = (pub_data*) malloc(sizeof(pub_data)); + char *_data = (char*) malloc(len); + new_data->length = len; + new_data->id = id; + new_data->seqno = seqno; + new_data->data = _data; + memcpy(_data, data, len); + + return new_data; +} + +// Add new data to data list +void add_data(unsigned char len, long id, short 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); + + if(seqno >= node_data->seqno) { + node_data->seqno = seqno ^ 1; + } + + return; + } + + // 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; + } + + // Find correct position for new data + list *tmp = data_list; + list *last = NULL; + list *new_node; + long 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; + } + + // 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; + } 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; + } + + // seqno is smaller so the new data allocated is freed and nothing else is done + free(new_data); + + return; + } + + // 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; +} + /* ---- Fin fonctions utilitaires ---- */ // We need to make sure the TLV announces a length that will no go onto @@ -61,7 +176,7 @@ int validate_tlv(char *data, int pos, short packet_len){ unsigned char tlv_len = data[pos+1]; // Check that the tlv does not exceed the packet length - if(pos + length >= packet_len) + if(pos + tlv_len >= packet_len) return -1; // Returns the type of the tlv or -1 if something went wrong @@ -132,91 +247,172 @@ int update_neighbours(){ }; // We then look at the differents TLVs in the packet. -void work_with_tlvs(char *data, short packet_len, struct sockaddr_in6 sender){ +int work_with_tlvs(char *data, short packet_len, struct sockaddr_in6 sender){ int pos = 0; - unsigned char tlv_len; - tlv tmp_tlv; + unsigned char tlv_len, hash[16], warn[32]; + tlv new_tlv, cur_tlv; + list *tmp_list; + pub_data *pdata; while(pos < packet_len) { switch(validate_tlv(data, pos, packet_len)) { case 0: // We received a padding tlv so it is ignored pos += 1; + break; case 1: // We received a padding tlv so it is ignored tlv_len = data[pos+1]; pos += tlv_len + 2; + break; case 2: // We received a neighbour request so a random neighbor tlv has to be sent - tlv_len = data[pos+1]; - pos += tlv_len + 2; // Send a neighbour tlv neighbour_peer *random = get_random_neighbour(); - build_neighbour(&tmp_tlv, random->ip, random->port); + build_neighbour(&new_tlv, random->ip, random->port); // NOT FINISHED - What packet is it added to? - add_tlv(packet, &tmp_tlv, 3); - break; - case 3: - // We received a neighbour tlv so a tlv network hash is sent to that address - neighbour* cur_tlv = ((neighbour*) data) + pos; - struct in6_addr ip = cur_tlv->ip; - short port = cur_tlv->port; + add_tlv(packet, &new_tlv, 3); + // The position is updated tlv_len = data[pos+1]; pos += tlv_len + 2; + break; + case 3: + // We received a neighbour tlv so a tlv network hash is sent to that address + cur_tlv.neighbour = (neighbour*) (data + pos); + // Build network hash - unsigned char hash[16]; - hash_network(neighbour_list, hash); - build_network_hash(&tmp_tlv, hash); + build_network_hash(&new_tlv, data_list); // NOT FINISHED - What packet is it added to? - add_tlv(packet, &tmp_tlv, 4); + add_tlv(packet, &new_tlv, 4); + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; + break; case 4: - // We reveived a network hash tlv so - tlv_len = data[pos+1]; - pos += tlv_len +2; + // 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); + hash_network(data_list, hash); + + if(memcmp(hash, cur_tlv.network_hash->network_hash, 16) == 0) { + build_network_state_req(&new_tlv); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &new_tlv, 5); + } + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; - // NOT FINISHED - Where is network_hash? - build_neighbour(&tmp_tlv, network_hash); - // NOT FINISHED - What packet is it added to? - add_tlv(packet, &tmp_tlv, 4); 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 - pos += 2; - // NOT FINISHED - for each known data - list *tmp_list = data_list; - pub_data *tmp_data; + // for each known data build a node hash and add to packet + tmp_list = data_list; while(tmp_list != NULL) { - tmp_data = (pub_data*) tmp_list->data; - build_node_hash(&tmp_tlv, tmp_data->id, tmp_data->seqno); + pdata = (pub_data*) tmp_list->data; + build_node_hash(&new_tlv, pdata->id, pdata->seqno, pdata->data); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &new_tlv, 4); } + // The position is updated + pos += 2; + break; case 6: - // We received a node hash tlv + // 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); + + // 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; + } + + } + + // 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); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &new_tlv, 7); + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; + break; case 7: - // We received a node state request tlv + // 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); + + if(pdata != NULL) { + build_node_state(&new_tlv, pdata->id, pdata->seqno, pdata->data, pdata->length); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &new_tlv, 8); + } + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; + break; case 8: - // We received a node state tlv + // 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); + + add_data(cur_tlv.node_state->length - 26, cur_tlv.node_state->node_id, cur_tlv.node_state->seqno, cur_tlv.node_state->data); + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; + break; case 9: // We received a warning tlv so it's message is printed + cur_tlv.warning = (warning*) (data + pos); + + // 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); + + // The position is updated + tlv_len = data[pos+1]; + pos += tlv_len + 2; + break; default: - return ; + // A malformed packet was found so we stop looking for more packets and send a warning tlv + strcpy(warn, "Packet is malformed."); + build_warning(&new_tlv, warn, strlen(warn)); + // NOT FINISHED - What packet is it added to? + add_tlv(packet, &new_tlv, 9); + + return -1; } } + + return 0; } // We listen forever for new paquets; diff --git a/src/node.h b/src/node.h index d4ba94b..630a93e 100644 --- a/src/node.h +++ b/src/node.h @@ -90,4 +90,13 @@ int len_list(list *l); neighbour_peer *get_random_neighbour(); +// get data associated with id, if it doesn't exist return NULL +pub_data *get_data(long id); + +// Take data as args and create a pub_data structure in the heap +pub_data *copy_data(unsigned char len, long id, short seqno, char *data); + +// add new data to data list +void add_data(unsigned char len, long id, short seqno, char *data); + #endif diff --git a/src/tlv.c b/src/tlv.c index 2284815..c93436a 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -79,7 +79,7 @@ int build_neighbour(tlv *tlv, struct in6_addr ip, short port) { return 0; } -int build_network_hash(tlv *tlv, char *hash) { +int build_network_hash(tlv *tlv, list *data_list) { network_hash *new = (network_hash*) malloc(sizeof(network_hash)); if(new == NULL) @@ -87,7 +87,7 @@ int build_network_hash(tlv *tlv, char *hash) { new->type = 4; new->length = 16; - memcpy(new->network_hash, hash, 16); + hash_network(data_list, new->network_hash); tlv->network_hash = new; @@ -108,7 +108,7 @@ int build_network_state_req(tlv *tlv) { return 0; } -int build_node_hash(tlv *tlv, long node_id, short seqno, char *hash) { +int build_node_hash(tlv *tlv, long node_id, short seqno, char *data) { node_hash *new = (node_hash*) malloc(sizeof(node_hash)); if(new == NULL) @@ -118,7 +118,9 @@ int build_node_hash(tlv *tlv, long node_id, short seqno, char *hash) { new->length = 26; new->node_id = node_id; new->seqno = seqno; - memcpy(new->node_hash, hash, 16); + + pub_data pdata = (pub_data) {.id = node_id, .seqno = seqno, .data = data}; + hash_data(&pdata, new->node_hash); tlv->node_hash = new; @@ -140,9 +142,9 @@ int build_node_state_req(tlv *tlv, long node_id) { return 0; } -int build_node_state(tlv *tlv, long node_id, short seqno, char *node_hash, char *data) { +int build_node_state(tlv *tlv, long node_id, short seqno, char *data, size_t data_len) { node_state *new = (node_state*) malloc(sizeof(node_state)); - int len = strlen(data); + int len = data_len + 26; if(new == NULL) return -1; @@ -157,17 +159,19 @@ int build_node_state(tlv *tlv, long node_id, short seqno, char *node_hash, char new->length = 26 + len; new->node_id = node_id; new->seqno = seqno; - memcpy(new->node_hash, node_hash, 16); memcpy(new->data, data, len); + pub_data pdata = (pub_data) {.id = node_id, .seqno = seqno, .data = data}; + hash_data(&pdata, new->node_hash); + tlv->node_state = new; return 0; } -int build_warning(tlv *tlv, char *message) { +int build_warning(tlv *tlv, char *message, size_t message_len) { warning *new = (warning*) malloc(sizeof(warning)); - int len = strlen(message); + int len = message_len; if(new == NULL) return -1; diff --git a/src/tlv.h b/src/tlv.h index c9a3d00..33bbaf5 100644 --- a/src/tlv.h +++ b/src/tlv.h @@ -6,6 +6,7 @@ #include #include "parser.h" #include "hash.h" +#include "node.h" #define LEN_NEIGHBOUR_REQ 0 #define LEN_NEIGHBOUR 18 @@ -33,7 +34,7 @@ typedef struct pad1 { typedef struct padn { unsigned char type; unsigned char length; - char mbz[256]; + char *mbz; } padn; // 2 octets @@ -117,11 +118,11 @@ int build_pad1(tlv *tlv); int build_padn(tlv *tlv, size_t len); int build_neighbour_req(tlv *tlv); int build_neighbour(tlv *tlv, struct in6_addr ip, short port); -int build_network_hash(tlv *tlv, char *network_hash); +int build_network_hash(tlv *tlv, list *data_list); int build_network_state_req(tlv *tlv); -int build_node_hash(tlv *tlv, long node_id, short seqno, char *node_hash); +int build_node_hash(tlv *tlv, long node_id, short seqno, char *data); int build_node_state_req(tlv *tlv, long node_id); -int build_node_state(tlv *tlv, long node_id, short seqno, char *node_hash, char *data); -int build_warning(tlv *tlv, char *message); +int build_node_state(tlv *tlv, long node_id, short seqno, char *data, size_t data_len); +int build_warning(tlv *tlv, char *message, size_t message_len); #endif