work with tlvs

This commit is contained in:
gonzalef 2020-04-07 19:05:30 +02:00
parent a832c2f64c
commit 9c93785ca6
4 changed files with 259 additions and 49 deletions

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -6,6 +6,7 @@
#include <stdlib.h>
#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