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) mod 2 16 ) < 32768
|
||||||
s ≼ s ′ lorsque ((s ′ − s) and 32768) = 0
|
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
|
// This is the main file of the Dazibao project. It represents the node, and
|
||||||
// handles all of the main logic, including the network connexions.
|
// 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.
|
/* ---- Fonctions utilitaires ---- */
|
||||||
packet listen_for_packets(){
|
|
||||||
|
|
||||||
|
// 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){
|
// Get a random neighbour
|
||||||
// We need to make sure the TLV announces a length that will no go onto
|
neighbour_peer *get_random_neighbour() {
|
||||||
// another tlv, as we might end up reading bullshit.
|
// 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 need to make sure the TLV announces a length that will no go onto
|
||||||
// We make sure the TLV is legal.
|
// another tlv, as we might end up reading bullshit.
|
||||||
if(!validate_tlvs(tlv)){
|
int validate_tlv(char *data, int pos, short packet_len){
|
||||||
perror(">> Invalid TLV receivied, is will be ignored.");
|
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
|
// TODO : Here, we need to fork.
|
||||||
// We calculate a network hash,
|
|
||||||
|
|
||||||
// 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
|
// TODO : Add the neighbour check here.
|
||||||
// back to the sender.
|
|
||||||
|
|
||||||
// TLV Network State Request
|
// struct tlv_list received_tlvs;
|
||||||
// We check our neighbourhood, and for each peer, we send back
|
// if (validate_tlvs(formated_rec_datagram) < 0)
|
||||||
// to the sender a TLV Node Hash
|
int nbr_success_tlv = work_with_tlvs(formated_rec_datagram, &req, sender);
|
||||||
|
if (nbr_success_tlv < 0){
|
||||||
// TLV Node hash
|
perror(">> Error while treating the TLVs of the packet.");
|
||||||
// We get a hash _h_ for the node _l_
|
printf(">> Managed to deal with %i TLVs\n", -nbr_success_tlv );
|
||||||
// If we don't have an entry for _l_, or if we have the same one as the
|
} else {
|
||||||
// on we just receivied, we send out a TLV Node State Request back.
|
printf(">> Done working with the TLVs of the packet, listenin for new packets.\n");
|
||||||
|
}
|
||||||
// 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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// We create the neighbourhood table
|
||||||
|
neighbour_peer neighbour_list[NEIGHBOUR_MAX];
|
||||||
// We create the message table
|
// We create the message table
|
||||||
|
|
||||||
// We create our own message.
|
// We create our own message.
|
||||||
|
|
||||||
// Listen for incoming packets
|
// Listen for incoming packets
|
||||||
listen_for_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;
|
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
|
// Theses functions are there for general book-keeping,and run in there own
|
||||||
// thread, being run every 20 seconds.
|
// thread, being run every 20 seconds.
|
||||||
// Every 20 sec, if we have less than 5 neighbours, we ask for more peers
|
// 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
|
// 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
|
// fonctions signatures
|
||||||
void listen_for_packets();
|
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
|
// threaded functions
|
||||||
|
|
||||||
@ -21,6 +86,8 @@ void t_update_neighbours();
|
|||||||
void t_get_network_state();
|
void t_get_network_state();
|
||||||
|
|
||||||
// Helper functions
|
// 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…
Reference in New Issue
Block a user