diff --git a/src/node.c b/src/node.c index c096d64..8e011d5 100644 --- a/src/node.c +++ b/src/node.c @@ -12,7 +12,6 @@ #include #include #include - #include "node.h" // Static variables @@ -36,27 +35,94 @@ int len_list(list *l) { tmp = tmp->next; len++; } - return len; } // Get a random neighbour neighbour_peer *get_random_neighbour() { + printf(">> Getting random peer...\n"); // 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, int16_t 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 && peer->port == port) { + 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, int16_t port) { + + char * buff_str_ip[1024]; + char * ip_str = (char * ) inet_ntop(AF_INET6,ip,(char * restrict) buff_str_ip, 1024); + + printf(">> Found peer %s @ %i.\n", ip_str, 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) { + printf(">> We don't know this peer yet\n"); + // check if there are less than 15 neighbours + if(len_list(neighbour_list) >= 15){ + return -1; + } else { + printf(">> Adding them to the peer table.\n"); + // 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 = LISTEN_PORT; + peer->is_temporary = 1; + + // set last_seen time + time(&curtime); + peer->last_seen = curtime; + + // set new peer as head of list + list *node = (list*) malloc(sizeof(list)); + node->data = (void*) peer; + node->next = neighbour_list; + neighbour_list = node; + return 1; + } + } else { + printf(">> 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) { list *tmp = data_list; @@ -174,6 +240,65 @@ void add_data(unsigned char len, int64_t id, int16_t seqno, char *data) { /* ---- Fin fonctions utilitaires ---- */ +// Update the neighbour list +int update_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; + + // 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++; + + // 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; + } + } + + 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) { char type = tlv->pad1->type, sent = 0, errval = 0; @@ -259,8 +384,10 @@ int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { // Send length bytes from packet int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, int socket_num) { + ((packet*) packet_buff)->length = htons(((packet*) packet_buff)->length); + // Vectorized buffer - struct iovec vec_buff = {.iov_len = length, .iov_base = packet_buff}; + struct iovec vec_buff = {.iov_len = length + 4, .iov_base = packet_buff}; int error_while_sending = 0; @@ -274,17 +401,16 @@ int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, in 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); + printf(">> Unable to send out the packet to peer.\n"); error_while_sending = 1; } else if (response_code < length) { - // debug_print("Sent out only part of the packet."); + printf(">> Sent out only part of the packet.\n"); error_while_sending = 1; } else { - // debug_print("Send out packet to peer %i", i); + printf(">> Send out packet to peer, size : %i\n", response_code); } if (error_while_sending == 1) { - // debug_print("Error occured while sending out a packet."); return -1; } else { return 0; @@ -295,7 +421,7 @@ int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, in 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 @@ -358,6 +484,7 @@ int send_single_tlv(tlv *tlv, struct sockaddr_in6 *dest, int socket_num) { } // Send the packet + printf("(%i)\n", pack.length ); return send_packet((char*) &pack, pack.length, dest, socket_num); } @@ -423,21 +550,32 @@ int send_tlv(tlv *tlv_to_send, int16_t tlv_size, struct sockaddr_in6 * dest_list // 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){ + char type = data[pos]; // Nothing to do in this case - if(type == 0) + if(type == 0){ + printf(">> Found padding TLV type.\n"); return 0; + } // Check that we can read a length - if(pos + 1 >= packet_len) + if(pos + 1 >= packet_len){ + printf(">> Reading out of packet length. \n"); 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) + printf("%i ; %i ; %i\n", pos, tlv_len, packet_len ); + if(pos + tlv_len > packet_len){ + printf(">> The TLV Length exceed the packet length\n"); return -1; + } + + printf(">> TLV has type %i\n", type ); // Returns the type of the tlv or -1 if something went wrong switch(type) { @@ -491,7 +629,10 @@ int check_header(char * received_data_buffer, int received_data_len, struct pack return -1; } - if (packet_to_return->length + 4 > received_data_len ) { + // Convert to hardware order. + ((packet*) packet_to_return)->length = ntohs(((packet*) packet_to_return)->length); + printf("packet : %i, %i \n", packet_to_return->length + 4,received_data_len ); + 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."); return -1; } @@ -499,19 +640,19 @@ int check_header(char * received_data_buffer, int received_data_len, struct pack 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; } // 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; +int work_with_tlvs(char * data, int16_t total_packet_len, struct sockaddr_in6 *sender, int socket_num){ + int16_t packet_len = ((packet*) data)->length; + + if(packet_len != total_packet_len - 4) { + fprintf(stderr, ">> Length indicated in packet differs from real length of packet received.\n"); + return -1; + } + + int pos = 4; unsigned char tlv_len, hash[16]; char warn[32]; tlv new_tlv, cur_tlv; @@ -525,15 +666,21 @@ int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, packet pack = (packet) {.magic = 95, .version = 1, .length = 0}; memset(pack.body, 0, 1020); - int ifindex = if_nametoindex("eth0"); - +/* + int ifindex = if_nametoindex("enp3s0"); if(ifindex == 0) { - perror("if_nametoindex failed"); - return -1; + int ifindex = if_nametoindex("eth0"); + if(ifindex == 0) { + perror("if_nametoindex failed"); + return -1; + } } +*/ + int ifindex = 0; - while(pos < packet_len) { - switch(validate_tlv(data, pos, packet_len)) { + ifindex = 0; + while(pos < total_packet_len) { + switch(validate_tlv(data, pos, total_packet_len)) { case 0: // We received a padding tlv so it is ignored pos += 1; @@ -576,6 +723,7 @@ 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; + printf("fzfzfe\n"); break; case 4: @@ -585,7 +733,8 @@ int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, if(memcmp(hash, cur_tlv.network_hash->network_hash, 16) == 0) { build_network_state_req(&new_tlv); - add_tlv(&pack, &new_tlv, sender, socket_num); + send_single_tlv(&new_tlv, sender, socket_num); + } // The position is updated @@ -681,6 +830,7 @@ int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, default: // A malformed packet was found so we stop looking for more packets and send a warning tlv strcpy(warn, "Packet is malformed."); + printf("Malformed packet\n"); build_warning(&new_tlv, warn, strlen(warn)); add_tlv(&pack, &new_tlv, sender, socket_num); @@ -708,10 +858,21 @@ int listen_for_packets(char * received_data_buffer, int received_data_len, struc return -1; } - // TODO : Add the neighbour check here. + // Neighbour check + struct in6_addr ip = sender->sin6_addr; + int16_t port = htons(sender->sin6_port); + + + int rc = add_n_update_neighbour(&ip, port); + if( rc == -1) { + printf(">> We have enough peers, we won't add him..\n"); + return -1; + } else if (rc == 1){ + printf(">> Peer was added to the table.\n"); + } else { + printf(">> Updated the time it was last seen.\n"); + } - // 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."); @@ -724,19 +885,19 @@ int listen_for_packets(char * received_data_buffer, int received_data_len, struc } -int t_ask_for_more_peers(list * neighbourhood, int sock_fd){ +int t_ask_for_more_peers(int sock_fd){ + return ask_for_peers(sock_fd); +} + +int t_get_network_state(int sock_fd){ return 0; } -int t_get_network_state(list * neighbourhood, int sock_fd){ - return 0; +int t_update_neighbours(){ + return update_neighbours(); } -int t_update_neighbours(list * neighbourhood){ - return 0; -} - -int run_node(int sock_fd, list * neighbourhood){ +int run_node(int sock_fd){ printf(">> Running node...\n"); int ret; @@ -747,7 +908,7 @@ int run_node(int sock_fd, list * neighbourhood){ // 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; @@ -760,13 +921,13 @@ int run_node(int sock_fd, list * neighbourhood){ */ while (1) { - if (time(NULL) >= delay) { + if(time(NULL) >= delay) { printf(">> Asking for more peers...\n"); - t_ask_for_more_peers(neighbourhood, sock_fd); + t_ask_for_more_peers(sock_fd); printf(">> Updating neighbours...\n"); - t_update_neighbours(neighbourhood); + t_update_neighbours(); printf(">> Getting network state...\n"); - t_get_network_state(neighbourhood, sock_fd); + t_get_network_state(sock_fd); delay = time(NULL) + 20 + (rand() % 10); } @@ -837,7 +998,7 @@ int run_node(int sock_fd, list * neighbourhood){ break; } if (bytes > 0) { - printf("Received: %.*s\r", (int)bytes, output_buffer); + printf("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) { @@ -856,7 +1017,7 @@ int run_node(int sock_fd, list * neighbourhood){ // This function runs once, and sets the sock_fd as well as the neighbourhood -int bootstrap_node(int * sock_fd, list * neighbourhood){ +int bootstrap_node(int * sock_fd){ printf(">> Boostraping node...\n"); struct sockaddr_in6 server_addr; @@ -879,20 +1040,24 @@ int bootstrap_node(int * sock_fd, list * neighbourhood){ } /* Make the first peer*/ - struct neighbour_peer root_peer; - struct timeval root_peer_seen; + struct neighbour_peer * root_peer = (struct neighbour_peer *) malloc(sizeof(struct neighbour_peer)); + time_t root_peer_seen = time(NULL); - int inet_p = inet_pton(AF_INET6, ROOT_PEER_ADDR, &root_peer.ip); + int inet_p = inet_pton(AF_INET6, ROOT_PEER_ADDR, &root_peer->ip); if(inet_p < 1){ perror(">> Failed to create the root peer."); return -3; } - root_peer.port = 1212; - root_peer.is_temporary = 0; - root_peer.last_seen = root_peer_seen; + root_peer->port = 1212; + root_peer->is_temporary = 0; + root_peer->last_seen = root_peer_seen; // TODO: Add the first peer to the neighbourhood + printf(">> Adding the first root peer to the list...\n"); + neighbour_list = malloc(sizeof(struct list)); + neighbour_list->data = (void *) root_peer; + neighbour_list->next = NULL; printf(">> Boostraping done.\n"); return 0; @@ -902,11 +1067,9 @@ int bootstrap_node(int * sock_fd, list * neighbourhood){ int main(int argc, const char *argv[]) { printf(">> Starting node\n"); - list neighbourhood; - int sock_fd; - bootstrap_node(&sock_fd, &neighbourhood); - run_node(sock_fd, &neighbourhood); + bootstrap_node(&sock_fd); + run_node(sock_fd); close(sock_fd); return 0; diff --git a/src/node.h b/src/node.h index 7baf163..b47f957 100644 --- a/src/node.h +++ b/src/node.h @@ -22,7 +22,7 @@ typedef struct neighbour_peer { struct in6_addr ip; int16_t port; char is_temporary; - struct timeval last_seen; + time_t last_seen; } neighbour_peer; // The strucuture to hold the messages @@ -53,7 +53,8 @@ typedef struct list { #define LISTEN_PORT 1212 // The node ID -#define NODE_ID 42675882021843277 +// #define NODE_ID 42675882021843277 +#define NODE_ID 42013376900101010 // The number of neighbours // The neighbour table has 15 entries @@ -61,8 +62,7 @@ typedef struct list { // The adress of the main peer #define ROOT_PEER_ADDR "2001:660:3301:9200::51c2:1b9b" - -// TODO + // fonctions signatures int listen_for_packets(char * received_data_buffer, int received_data_len, struct sockaddr_in6 * sender, int sock_fd); @@ -73,6 +73,8 @@ int validate_tlv(char *data, int pos, int16_t packet_len); int update_neighbours(); +int ask_for_peers(int socket_num); + int work_with_tlvs(char * data, int16_t packet_len, struct sockaddr_in6 *sender, int socket_num); int add_tlv(packet *pack, tlv *tlv, struct sockaddr_in6 *dest, int socket_num); @@ -82,7 +84,7 @@ int send_packet(char *packet_buff, int16_t length, struct sockaddr_in6 *dest, in int send_single_tlv(tlv *tlv, struct sockaddr_in6 *dest, int socket_num); // This function is in charge of saying how and what goes where. -int run_node(int sock_fd, list * neighbourhood); +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. @@ -97,24 +99,24 @@ int send_tlvs(struct list * tlv_list, int16_t length, struct sockaddr_in6 * dest /* 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(list * neighbourhood, int sock_fd); +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(list * neighbourhood); +int t_update_neighbours(); /* 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(list * neighbourhoodn, int sock_fd); +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, list * neighbourhood); +int bootstrap_node(int * sock_fd); // Helper functions int len_list(list *l); @@ -123,6 +125,12 @@ void debug_print(char message_debug); neighbour_peer *get_random_neighbour(); +// Search for this peer in the neighbour table +neighbour_peer *get_neighbour(struct in6_addr *ip, int16_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, int16_t port); + // get data associated with id, if it doesn't exist return NULL pub_data *get_data(int64_t id); diff --git a/src/tlv.c b/src/tlv.c index 1f5b4e8..82de813 100644 --- a/src/tlv.c +++ b/src/tlv.c @@ -62,12 +62,15 @@ int build_padn(tlv *tlv, size_t len) { int build_neighbour_req(tlv *tlv) { // Free the previously allocated memory - free(tlv->pad1); + // if (tlv != NULL) { + // free(tlv->pad1); + // } neighbour_req *new = (neighbour_req*) malloc(sizeof(neighbour_req)); - if(new == NULL) + if(new == NULL){ return -1; + } new->type = 2; new->length = 0;