Merge branch '16-update_neighbours' into 'master'

Resolve "Où faire les conversions big endian/little endian?"

Closes #16

See merge request perdriau/dazibao!12
This commit is contained in:
PERDRIAU nelson 2020-04-29 14:16:30 +02:00
commit d302de0390
3 changed files with 247 additions and 73 deletions

View File

@ -12,7 +12,6 @@
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>
#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; i<n; i++) {
for(int i=1; i < n; i++) {
tmp = tmp->next;
}
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;

View File

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

View File

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