Merge branch 'dev-nelson' into 12-changer-le-node-id
This commit is contained in:
		
						commit
						e16af52ab5
					
				
							
								
								
									
										6
									
								
								Notes.md
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								Notes.md
									
									
									
									
									
								
							| @ -7,3 +7,9 @@ s ⊕ n = (s + n) and 65535 | ||||
| 
 | ||||
| s ≼ s ′ lorsque ((s ′ − s) mod 2 16 ) < 32768 | ||||
| s ≼ s ′ lorsque ((s ′ − s) and 32768) = 0 | ||||
| 
 | ||||
| ------- | ||||
| 
 | ||||
| jch.irif.fr port UDP 1212 | ||||
| 
 | ||||
| http://jch.irif.fr:8082/ | ||||
|  | ||||
							
								
								
									
										4
									
								
								src/Notes.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/Notes.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| # Notes et recherches sur le projet | ||||
| 
 | ||||
| Telecharger la librarie OpenSSl avec 'sudo apt-get install libssl-dev' | ||||
| Utiliser 'gcc -o {exec} {fichier.c} -lssl -lcrypto' pour utiliser la librarie OpenSSL | ||||
							
								
								
									
										5
									
								
								src/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/README.md
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| # dazibao | ||||
| 
 | ||||
| Le but de ce projet est d’implémenter un dazibao (« journal à grandes lettres »), semblable à | ||||
| un « mur » de réseau social, mais de façon complètement distribuée. Le protocole est basé sur un | ||||
| algorithme non-fiable d’inondation. | ||||
							
								
								
									
										60
									
								
								src/hash.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/hash.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| #include "hash.h" | ||||
| 
 | ||||
| // Hash a single data
 | ||||
| void hash_data(pub_data *data, unsigned char *buf) { | ||||
| 	// All three fields are concatenated into a single buffer
 | ||||
| 	int totlen = data->length + 10; | ||||
| 	unsigned char concat[totlen]; | ||||
| 	concat_data(data, concat); | ||||
| 
 | ||||
| 	// The resulting buf is hashed and put into a buffer
 | ||||
| 	unsigned char hash[SHA256_DIGEST_LENGTH]; | ||||
| 	SHA256(concat, totlen, hash); | ||||
| 
 | ||||
| 	// Put truncated hash into buf 
 | ||||
| 	hash_trunc(hash, buf); | ||||
| } | ||||
| 
 | ||||
| // 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); | ||||
| 	unsigned char hash[SHA256_DIGEST_LENGTH]; | ||||
| 	int totlen = 0; | ||||
| 	list *tmp = data_list; | ||||
| 
 | ||||
| 	// Hash every known data and concatenate it to buffer concat
 | ||||
| 	while(tmp != NULL) { | ||||
| 		hash_data((pub_data*) tmp->data, hash); | ||||
| 		concat_hash(concat, hash, totlen); | ||||
| 		totlen += 16; | ||||
| 		tmp = tmp->next; | ||||
| 	} | ||||
| 
 | ||||
| 	// Hash all of concat to obtain the network hash
 | ||||
| 	SHA256(concat, totlen, hash); | ||||
| 
 | ||||
| 	// Put truncated hash into buf 
 | ||||
| 	hash_trunc(hash, buf); | ||||
| 
 | ||||
| 	// Get rid of concat
 | ||||
| 	free(concat); | ||||
| } | ||||
| 
 | ||||
| // 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); | ||||
| } | ||||
| 
 | ||||
| // 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); | ||||
| } | ||||
| 
 | ||||
| // 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); | ||||
| } | ||||
							
								
								
									
										23
									
								
								src/hash.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/hash.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| #ifndef HASH_H | ||||
| #define HASH_H | ||||
| 
 | ||||
| #include <openssl/sha.h> | ||||
| #include "node.h" | ||||
| #include "tlv.h" | ||||
| 
 | ||||
| // Hash a single data
 | ||||
| void hash_data(pub_data *data, unsigned char *buf); | ||||
| 
 | ||||
| // Hash every data contained in data_list then return a network hash
 | ||||
| void hash_network(list *data_list, unsigned char *buf); | ||||
| 
 | ||||
| // Truncate 32 octet hash to 16 octets
 | ||||
| void hash_trunc(unsigned char *hash256bit, unsigned char *buf); | ||||
| 
 | ||||
| // Concat all fields of data and put them in buf
 | ||||
| void concat_data(pub_data *data, unsigned char *buf); | ||||
| 
 | ||||
| // Concat hash2 to hash1 (hash1 is modified)
 | ||||
| void concat_hash(unsigned char *hash1, unsigned char *hash2, size_t size); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										1
									
								
								src/install.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								src/install.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1 @@ | ||||
| sudo apt-get install libssl-dev | ||||
							
								
								
									
										329
									
								
								src/node.c
									
									
									
									
									
								
							
							
						
						
									
										329
									
								
								src/node.c
									
									
									
									
									
								
							| @ -1,79 +1,312 @@ | ||||
| // 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 <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| 
 | ||||
| #include "tlv.h" | ||||
| #include "node.h" | ||||
| 
 | ||||
| // Will return a packet when we receive one that's valid.
 | ||||
| packet listen_for_packets(){ | ||||
| /* ----  Fonctions utilitaires  ---- */ | ||||
| 
 | ||||
| // Get list length
 | ||||
| int len_list(list *l) { | ||||
| 	int len = 0; | ||||
| 	list *tmp = l; | ||||
| 
 | ||||
| 	while(tmp != NULL) { | ||||
| 		tmp = tmp->next; | ||||
| 		len++; | ||||
| 	} | ||||
| 
 | ||||
| 	return len; | ||||
| } | ||||
| 
 | ||||
| int validate_tlvs(union tlv tlv_to_validate){ | ||||
|     // We need to make sure the TLV announces a length that will no go onto
 | ||||
|     // another tlv, as we might end up reading bullshit.
 | ||||
| // Get a random neighbour
 | ||||
| neighbour_peer *get_random_neighbour() { | ||||
| 	// Get a random number
 | ||||
|     time_t t; | ||||
|     srand((unsigned) time(&t)); | ||||
|     int n = rand() % len_list(neighbour_list); | ||||
| 
 | ||||
|     // Get nth neighbour
 | ||||
|     list *tmp = neighbour_list; | ||||
| 
 | ||||
|     for(int i=0; i<n; i++) { | ||||
|     	tmp = tmp->next; | ||||
|     } | ||||
| 
 | ||||
|     return (neighbour_peer*) tmp->data; | ||||
| } | ||||
| 
 | ||||
| void work_with_tlvs(struct tlvs_list receivied_tlvs){ | ||||
| /* ---- Fin fonctions utilitaires ---- */ | ||||
| 
 | ||||
|     // For every TLV,
 | ||||
|         // We make sure the TLV is legal.
 | ||||
|         if(!validate_tlvs(tlv)){ | ||||
|             perror(">> Invalid TLV receivied, is will be ignored."); | ||||
| // 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, short packet_len){ | ||||
|     char type = data[pos]; | ||||
| 
 | ||||
|     // Nothing to do in this case
 | ||||
|     if(type == 0) | ||||
|         return 0; | ||||
| 
 | ||||
|     // Check that we can read a length
 | ||||
|     if(pos + 1 >= packet_len) | ||||
|         return -1; | ||||
| 
 | ||||
|     unsigned char tlv_len = data[pos+1]; | ||||
| 
 | ||||
|     // Check that the tlv does not exceed the packet length
 | ||||
|     if(pos + length >= packet_len) | ||||
|         return -1; | ||||
| 
 | ||||
|     // Returns the type of the tlv or -1 if something went wrong
 | ||||
|     switch(type) { | ||||
|         case 1: | ||||
|             return 1; | ||||
|         case 2: | ||||
|             if(tlv_len != LEN_NEIGHBOUR_REQ) return -1; | ||||
|             return 2; | ||||
|         case 3: | ||||
|             if(tlv_len != LEN_NEIGHBOUR) return -1; | ||||
|             return 3; | ||||
|         case 4: | ||||
|             if(tlv_len != LEN_NETWORK_HASH) return -1; | ||||
|             return 4; | ||||
|         case 5: | ||||
|             if(tlv_len != LEN_NETWORK_STATE_REQ) return -1; | ||||
|             return 5; | ||||
|         case 6: | ||||
|             if(tlv_len != LEN_NODE_HASH) return -1; | ||||
|             return 6; | ||||
|         case 7: | ||||
|             if(tlv_len != LEN_NODE_STATE_REQ) return -1; | ||||
|             return 7; | ||||
|         case 8: | ||||
|             if(tlv_len < MIN_LEN_NODE_STATE || tlv_len > MAX_LEN_NODE_STATE) return -1; | ||||
|             return 8; | ||||
|         case 9: | ||||
|             return 9; | ||||
|         default: | ||||
|             return -1; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // 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 * req[], int buffer_size, struct packet * packet_to_return){ | ||||
| 
 | ||||
|     packet * packet_to_return = (packet*) req; | ||||
| 
 | ||||
|     // 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."); | ||||
|         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."); | ||||
|         return -1; | ||||
|     } | ||||
| 
 | ||||
|     if (packet_to_return.length + 4 > buffer_size  ) { | ||||
|         perror(">> 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; | ||||
| }; | ||||
| 
 | ||||
| // We then look at the differents TLVs in the packet.
 | ||||
| void work_with_tlvs(char *data, short packet_len, struct sockaddr_in6 sender){ | ||||
|     int pos = 0; | ||||
|     unsigned char tlv_len; | ||||
|     tlv tmp_tlv; | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|                 // 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; | ||||
| 
 | ||||
|                 tlv_len = data[pos+1]; | ||||
|                 pos += tlv_len + 2; | ||||
| 
 | ||||
|                 // Build network hash
 | ||||
|                 unsigned char hash[16]; | ||||
|                 hash_network(neighbour_list, hash); | ||||
|                 build_network_hash(&tmp_tlv, hash); | ||||
| 
 | ||||
|                 // NOT FINISHED - What packet is it added to?
 | ||||
|                 add_tlv(packet, &tmp_tlv, 4); | ||||
|                 break; | ||||
|             case 4: | ||||
|                 // We reveived a network hash tlv so
 | ||||
|                 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; | ||||
| 
 | ||||
|                 while(tmp_list != NULL) { | ||||
|                 	tmp_data = (pub_data*) tmp_list->data; | ||||
|                 	build_node_hash(&tmp_tlv, tmp_data->id, tmp_data->seqno); | ||||
|                 } | ||||
| 
 | ||||
|                 break; | ||||
|             case 6: | ||||
|                 // We received a node hash tlv
 | ||||
|                 break; | ||||
|             case 7: | ||||
|                 // We received a node state request tlv
 | ||||
|                 break; | ||||
|             case 8: | ||||
|                 // We received a node state tlv
 | ||||
|                 break; | ||||
|             case 9: | ||||
|                 // We received a warning tlv so it's message is printed
 | ||||
|                 break; | ||||
|             default: | ||||
|                 return ; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // We listen forever for new paquets;
 | ||||
| void listen_for_packets(){ | ||||
| 
 | ||||
|     // Create new socket for UDP
 | ||||
|     int s = socket(AF_INET6, SOCK_DGRAM, 0); | ||||
| 
 | ||||
|     if(s < 0) { | ||||
|         perror(">> Error, cannot create socket."); | ||||
|         perror(">> Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     struct sockaddr_in6 server; | ||||
|     memset(&server, 0, sizeof(server)); | ||||
| 
 | ||||
|     server.sin6_family = AF_INET6; | ||||
|     server.sin6_port = htons(LISTEN_PORT); | ||||
|     int rc = bind(s, (struct sockaddr*)&server, sizeof(server)); | ||||
|     if(rc < 0) { | ||||
|         perror(">> Error, cannot bind socket to choosen port."); | ||||
|         perror(">> Exiting..."); | ||||
|         exit(1); | ||||
|     } | ||||
| 
 | ||||
|     // A paquet has at most a length of 1024 bytes
 | ||||
|     char req[1024]; | ||||
|     struct sockaddr_in6 sender; | ||||
|     struct iovec io = { .iov_len = 1024, .iov_base = req }; | ||||
|     struct msghdr msg_to_receive = { | ||||
|         .msg_name = &sender, | ||||
|         .msg_namelen = sizeof(sender), | ||||
|         .msg_iov = &io, | ||||
|         .msg_iovlen = 1 | ||||
|     }; | ||||
|     while(1){ | ||||
|         memset(req, '\0', 1024); | ||||
| 
 | ||||
|         rc = recvmsg(s, &msg_to_receive, 0); | ||||
|         if(rc < 0) { | ||||
|             perror(">> Error while receiving a new datagram."); | ||||
|             perror(">> Ignoring, continuing..."); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|     // Switch
 | ||||
|         printf(">> New paquet received :\n"); | ||||
|         printf("%s\n", req); | ||||
| 
 | ||||
|     // TLV Network Hash
 | ||||
|         // We calculate a network hash,
 | ||||
|         // TODO : Here, we need to fork.
 | ||||
| 
 | ||||
|         // We compare both,
 | ||||
|         // 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(&req, 1024, formated_rec_datagram) < 0){ | ||||
|             perror(">> Error while checking the header, aborting this packet, by choice, and conviction."); | ||||
|             continue; | ||||
|         } | ||||
| 
 | ||||
|         // If they differ, we send a TLV Network State Request
 | ||||
|         // back to the sender.
 | ||||
|         // TODO : Add the neighbour check here.
 | ||||
| 
 | ||||
|     // TLV Network State Request
 | ||||
|         // We check our neighbourhood, and for each peer, we send back
 | ||||
|         // to the sender a TLV Node Hash
 | ||||
| 
 | ||||
|     // TLV Node hash
 | ||||
|         // We get a hash _h_ for the node _l_
 | ||||
|         // If we don't have an entry for _l_, or if we have the same one as the
 | ||||
|         // on we just receivied, we send out a TLV Node State Request back.
 | ||||
| 
 | ||||
|     // TLV Node State
 | ||||
|         // We get a hash _h_, sequence number _s_, data _d_ for node _l_.
 | ||||
|         // We compute a network hash,
 | ||||
|         // We compare the hash, if they differ, then with l',s',d' our data and
 | ||||
|         // h' the corresponding hash,
 | ||||
|             // if _l_ is our own node id, then
 | ||||
|                 // if s >> s' then we update our sequence number to s ⊕ 1 mod 2^16
 | ||||
|             // If it's another's node id, then
 | ||||
|                 // If there is no entry for the sender,
 | ||||
|                 // we store the entry in our data table.
 | ||||
|         // struct tlv_list received_tlvs;
 | ||||
|         // if (validate_tlvs(formated_rec_datagram) < 0)
 | ||||
|         int nbr_success_tlv = work_with_tlvs(formated_rec_datagram, &req, sender); | ||||
|         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 ); | ||||
|         } else { | ||||
|             printf(">> Done working with the TLVs of the packet, listenin for new packets.\n"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| int main(int argc, char const *argv[]) { | ||||
| int main(int argc, const char *argv[]) { | ||||
|     int cont = 1; | ||||
| 
 | ||||
|     while(CONTINUE){ | ||||
|     while(cont){ | ||||
| 
 | ||||
|         // We create the neighbourhood table
 | ||||
|         neighbour_peer neighbour_list[NEIGHBOUR_MAX]; | ||||
|         // We create the message table
 | ||||
| 
 | ||||
|         // We create our own message.
 | ||||
| 
 | ||||
|         // Listen for incoming packets
 | ||||
|         listen_for_packets(); | ||||
|         // For every packet recivied, we fork,
 | ||||
|         // then we make sure it's conform
 | ||||
|         // We then extract the data from it to make it easy to work with
 | ||||
|         check_header(); | ||||
|         // 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.
 | ||||
|         update_neighbours(); | ||||
|         // We then look at the differents TLVs in the packet.
 | ||||
|         work_with_tlvs(); | ||||
| 
 | ||||
|         // This is in it's own fork.
 | ||||
|         time_t delay = time(NULL) + 20; | ||||
|         while(! (delay < time(NULL)){ | ||||
|         while(! (delay < time(NULL))) { | ||||
|             // Theses functions are there for general book-keeping,and run in there own
 | ||||
|             // thread, being run every 20 seconds.
 | ||||
|             // Every 20 sec, if we have less than 5 neighbours, we ask for more peers
 | ||||
|  | ||||
							
								
								
									
										79
									
								
								src/node.h
									
									
									
									
									
								
							
							
						
						
									
										79
									
								
								src/node.h
									
									
									
									
									
								
							| @ -1,16 +1,81 @@ | ||||
| // Define constants
 | ||||
| 
 | ||||
| #ifndef NODE_H | ||||
| #define NODE_H | ||||
| 
 | ||||
| #include <stdlib.h> | ||||
| #include <time.h> | ||||
| #include <stdio.h> | ||||
| #include <sys/types.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #include "tlv.h" | ||||
| #include "hash.h" | ||||
| 
 | ||||
| // On which port do we listen to
 | ||||
| #define LISTEN_PORT 1212 | ||||
| 
 | ||||
| // The node ID
 | ||||
| #define NODE_ID 203242402519736214145149136169422092269247115186189140178187251487819615911212154252117172522111472481308026129190139512419121015210238252292031613214452118122204415160254 | ||||
| 
 | ||||
| // The number of neighbours
 | ||||
| // The neighbour table has 15 entries
 | ||||
| #define NEIGHBOUR_MAX 15 | ||||
| 
 | ||||
| /* 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 | ||||
|  * (configuré au lancement) ou transitoire, et la date de dernière réception d’un | ||||
|  * paquet de la part de ce pair ; | ||||
| */ | ||||
| typedef struct neighbour_peer { | ||||
|     struct in6_addr ip; | ||||
|     short port; | ||||
|     char is_temporary; | ||||
|     struct timeval last_seen; | ||||
| } neighbour_peer; | ||||
| 
 | ||||
| // The strucuture to hold the messages
 | ||||
| /* It's a list of triplets, (Li,Si,Di)
 | ||||
|  * Li : The Node ID of the publisher 64 bits | ||||
|  * Si : the sequence number 16 bits | ||||
|  * Di : the data of the message 192 bytes | ||||
| */ | ||||
| 
 | ||||
| typedef struct pub_data { | ||||
| 	unsigned char length; | ||||
|     long id; | ||||
|     short seqno; | ||||
|     char *data; | ||||
| } pub_data; | ||||
| 
 | ||||
| // General list
 | ||||
| typedef struct list { | ||||
| 	void *data; | ||||
| 	void *next; | ||||
| } list; | ||||
| 
 | ||||
| // Static variables
 | ||||
| static list *data_list; | ||||
| static list *neighbour_list; | ||||
| 
 | ||||
| // TODO
 | ||||
| 
 | ||||
| // fonctions signatures
 | ||||
| void listen_for_packets(); | ||||
| 
 | ||||
| void check_header(); | ||||
| int check_header(char * received_datagram[], int len, struct packet pack); | ||||
| 
 | ||||
| void update_neighbours(); | ||||
| int validate_tlvs(struct packet * pack, struct tlv_list * tlv_l); | ||||
| 
 | ||||
| void work_with_tlvs(); | ||||
| int update_neighbours(); | ||||
| 
 | ||||
| int validate_tlvs(); | ||||
| int work_with_tlvs(struct packet received_packet, char * data_from_packet[], struct sockaddr_in6 sender); | ||||
| 
 | ||||
| void add_tlv(packet *packet, tlv *tlv, char type); | ||||
| 
 | ||||
| int send_packet(struct tlv_list tlvs_to_send, ); | ||||
| 
 | ||||
| // threaded functions
 | ||||
| 
 | ||||
| @ -21,6 +86,8 @@ void t_update_neighbours(); | ||||
| void t_get_network_state(); | ||||
| 
 | ||||
| // Helper functions
 | ||||
| char * hash(); | ||||
| int len_list(list *l); | ||||
| 
 | ||||
| short * get_seq_no(short s, int n); | ||||
| neighbour_peer *get_random_neighbour(); | ||||
| 
 | ||||
| #endif | ||||
|  | ||||
							
								
								
									
										32
									
								
								src/parser.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/parser.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,32 @@ | ||||
| #include "parser.h" | ||||
| 
 | ||||
| // retourne le type de commande à exécuter
 | ||||
| cmd_token parse_cmd() { | ||||
| 	char buf[198], cmd[5], arg[193]; | ||||
| 	cmd_token token; | ||||
| 	token.type = ERROR; | ||||
| 	memset(token.arg, 0, 193); | ||||
| 
 | ||||
| 	if(fgets(buf, 198, stdin) == NULL) | ||||
| 		return token; | ||||
| 
 | ||||
| 	// cmd sera le premier mot rencontré et arg la suite de mots après celui ci,
 | ||||
| 	// si les deux variables ne sont pas remplies alors il y a une erreur
 | ||||
| 	if(sscanf(buf, "%s %[^\t\n]", cmd, arg) != 2) | ||||
| 		return token; | ||||
| 
 | ||||
| 	if(strcmp("req", cmd) == 0) { | ||||
| 		if(strcmp("neighbour", arg) == 0) | ||||
| 			token.type = NEIGHBOUR_REQ; | ||||
| 		else if(strcmp("network state", arg) == 0) | ||||
| 			token.type = NETWORK_STATE_REQ; | ||||
| 		else if(strcmp("node state", arg) == 0) | ||||
| 			token.type = NODE_STATE_REQ; | ||||
| 	} else if(strcmp("post", cmd) == 0) { | ||||
| 		token.type = POST; | ||||
| 		//arg[192] = 0;
 | ||||
| 		strcpy(token.arg, arg); | ||||
| 	} | ||||
| 
 | ||||
| 	return token; | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/parser.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/parser.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| 
 | ||||
| #ifndef PARSER_H | ||||
| #define PARSER_H | ||||
| 
 | ||||
| typedef enum cmd_type { | ||||
| 	NEIGHBOUR_REQ, NETWORK_STATE_REQ, NODE_STATE_REQ, POST, ERROR | ||||
| } cmd_type; | ||||
| 
 | ||||
| typedef struct cmd_token { | ||||
| 	cmd_type type; | ||||
| 	char arg[193]; | ||||
| } cmd_token; | ||||
| 
 | ||||
| // retourne le type de commande à exécuter
 | ||||
| cmd_token parse_cmd(); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										188
									
								
								src/tlv.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										188
									
								
								src/tlv.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,188 @@ | ||||
| #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; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int build_pad1(tlv *tlv) { | ||||
| 	pad1 *new = (pad1*) malloc(sizeof(pad1)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 0; | ||||
| 
 | ||||
| 	tlv->pad1 = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_padn(tlv *tlv, size_t len) { | ||||
| 	padn *new = (padn*) malloc(sizeof(padn)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 1; | ||||
| 	new->length = len; | ||||
| 	new->mbz = (char*) calloc(sizeof(char), len); | ||||
| 
 | ||||
| 	tlv->padn = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_neighbour_req(tlv *tlv) { | ||||
| 	neighbour_req *new = (neighbour_req*) malloc(sizeof(neighbour_req)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 2; | ||||
| 	new->length = 0; | ||||
| 
 | ||||
| 	tlv->neighbour_req = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_neighbour(tlv *tlv, struct in6_addr ip, short port) { | ||||
| 	neighbour *new = (neighbour*) malloc(sizeof(neighbour)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 3; | ||||
| 	new->length = 18; | ||||
| 	new->ip = ip; | ||||
| 	new->port = port; | ||||
| 
 | ||||
| 	tlv->neighbour = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_network_hash(tlv *tlv, char *hash) { | ||||
| 	network_hash *new = (network_hash*) malloc(sizeof(network_hash)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 4; | ||||
| 	new->length = 16; | ||||
| 	memcpy(new->network_hash, hash, 16); | ||||
| 
 | ||||
| 	tlv->network_hash = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_network_state_req(tlv *tlv) { | ||||
| 	network_state_req *new = (network_state_req*) malloc(sizeof(network_state_req)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 5; | ||||
| 	new->length = 0; | ||||
| 
 | ||||
| 	tlv->network_state_req = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_node_hash(tlv *tlv, long node_id, short seqno, char *hash) { | ||||
| 	node_hash *new = (node_hash*) malloc(sizeof(node_hash)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 6; | ||||
| 	new->length = 26; | ||||
| 	new->node_id = node_id; | ||||
| 	new->seqno = seqno; | ||||
| 	memcpy(new->node_hash, hash, 16); | ||||
| 
 | ||||
| 	tlv->node_hash = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_node_state_req(tlv *tlv, long node_id) { | ||||
| 	node_state_req *new = (node_state_req*) malloc(sizeof(node_state_req)); | ||||
| 
 | ||||
| 	if(new == NULL) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	new->type = 7; | ||||
| 	new->length = 8; | ||||
| 	new->node_id = node_id; | ||||
| 
 | ||||
| 	tlv->node_state_req = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_node_state(tlv *tlv, long node_id, short seqno, char *node_hash, char *data) { | ||||
| 	node_state *new = (node_state*) malloc(sizeof(node_state)); | ||||
| 	int len = strlen(data); | ||||
| 
 | ||||
| 	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->node_hash, node_hash, 16); | ||||
| 	memcpy(new->data, data, len); | ||||
| 
 | ||||
| 	tlv->node_state = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int build_warning(tlv *tlv, char *message) { | ||||
| 	warning *new = (warning*) malloc(sizeof(warning)); | ||||
| 	int len = strlen(message); | ||||
| 
 | ||||
| 	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);  | ||||
| 
 | ||||
| 	tlv->warning = new; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										127
									
								
								src/tlv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										127
									
								
								src/tlv.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,127 @@ | ||||
| #ifndef TLV_H | ||||
| #define TLV_H | ||||
| 
 | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <stdlib.h> | ||||
| #include "parser.h" | ||||
| #include "hash.h" | ||||
| 
 | ||||
| #define LEN_NEIGHBOUR_REQ 0 | ||||
| #define LEN_NEIGHBOUR 18 | ||||
| #define LEN_NETWORK_HASH 16 | ||||
| #define LEN_NETWORK_STATE_REQ 0 | ||||
| #define LEN_NODE_HASH 26 | ||||
| #define LEN_NODE_STATE_REQ 8 | ||||
| #define MIN_LEN_NODE_STATE 26 | ||||
| #define MAX_LEN_NODE_STATE 218 | ||||
| 
 | ||||
| // 8 octets min (struct pointer 4 octets), 1024 octets max
 | ||||
| typedef struct packet { | ||||
| 	unsigned char magic; // 95 (si autre, ignorer)
 | ||||
| 	unsigned char version; // 1 (si autre, ignorer)
 | ||||
| 	short length; // 1020 max
 | ||||
| 	char *body; | ||||
| } packet; | ||||
| 
 | ||||
| // 1 octet
 | ||||
| typedef struct pad1 { | ||||
| 	unsigned char type; | ||||
| } pad1; | ||||
| 
 | ||||
| // 2 octets min, 258 octets max (unsigned char 0 -> 255)
 | ||||
| typedef struct padn { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	char mbz[256]; | ||||
| } padn; | ||||
| 
 | ||||
| // 2 octets
 | ||||
| typedef struct neighbour_req { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| } neighbour_req; | ||||
| 
 | ||||
| // 20 octets
 | ||||
| typedef struct neighbour { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	struct in6_addr ip; | ||||
| 	short port; | ||||
| } neighbour; | ||||
| 
 | ||||
| // 18 octets
 | ||||
| typedef struct network_hash { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	char network_hash[16]; | ||||
| } network_hash; | ||||
| 
 | ||||
| // 2 octets
 | ||||
| typedef struct network_state_req { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| } network_state_req; | ||||
| 
 | ||||
| // 28 octets
 | ||||
| typedef struct node_hash { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	long node_id; | ||||
| 	short seqno; | ||||
| 	char node_hash[16]; | ||||
| } node_hash; | ||||
| 
 | ||||
| // 10 octets
 | ||||
| typedef struct node_state_req { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	long node_id; | ||||
| } node_state_req; | ||||
| 
 | ||||
| // 28 octets min, 220 octets max (data 0 -> 192)
 | ||||
| typedef struct node_state { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	long node_id; | ||||
| 	short seqno; | ||||
| 	char node_hash[16]; | ||||
| 	char data[192]; | ||||
| } node_state; | ||||
| 
 | ||||
| // 2 octets min, 258 ocets max (unsigned char 0 -> 255)
 | ||||
| typedef struct warning { | ||||
| 	unsigned char type; | ||||
| 	unsigned char length; | ||||
| 	char message[256]; | ||||
| } warning; | ||||
| 
 | ||||
| typedef union tlv { | ||||
| 	pad1 *pad1; | ||||
| 	padn *padn; | ||||
| 	neighbour_req *neighbour_req; | ||||
| 	neighbour *neighbour; | ||||
| 	network_hash *network_hash; | ||||
| 	network_state_req *network_state_req; | ||||
| 	node_hash *node_hash; | ||||
| 	node_state_req *node_state_req; | ||||
| 	node_state *node_state; | ||||
| 	warning *warning; | ||||
| } tlv; | ||||
| 
 | ||||
| // build tlv from token
 | ||||
| int build_tlv(tlv *tlv, cmd_token token); | ||||
| 
 | ||||
| // build specific tlv
 | ||||
| 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_state_req(tlv *tlv); | ||||
| int build_node_hash(tlv *tlv, long node_id, short seqno, char *node_hash); | ||||
| 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); | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										
											BIN
										
									
								
								src/énoncé.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/énoncé.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 n07070
						n07070