work with tlvs
This commit is contained in:
		
							parent
							
								
									a832c2f64c
								
							
						
					
					
						commit
						9c93785ca6
					
				
							
								
								
									
										266
									
								
								src/node.c
									
									
									
									
									
								
							
							
						
						
									
										266
									
								
								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;
 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
							
								
								
									
										22
									
								
								src/tlv.c
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								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; | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/tlv.h
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								src/tlv.h
									
									
									
									
									
								
							| @ -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 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gonzalef
						gonzalef