1 Commits

Author SHA1 Message Date
Tiago Batista Cardoso
82cc134626 thing 2026-01-11 22:00:10 +01:00
12 changed files with 255 additions and 1183 deletions

BIN
README.md

Binary file not shown.

View File

@@ -1,5 +1,5 @@
use client_network::{ use client_network::{
ChunkNode, MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string, MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string,
node_hash_to_hex_string, node_hash_to_hex_string,
}; };
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::{Receiver, Sender};
@@ -49,11 +49,11 @@ pub struct P2PClientApp {
impl P2PClientApp { impl P2PClientApp {
pub fn new(cmd_tx: Sender<NetworkCommand>, event_rx: Receiver<NetworkEvent>) -> Self { pub fn new(cmd_tx: Sender<NetworkCommand>, event_rx: Receiver<NetworkEvent>) -> Self {
//let (root_hash, tree_content) = MerkleNode::generate_base_tree(); let (root_hash, tree_content) = MerkleNode::generate_base_tree();
let mut loaded_fs = HashMap::new(); let mut loaded_fs = HashMap::new();
//let tree = MerkleTree::new(tree_content, root_hash); let tree = MerkleTree::new(tree_content, root_hash);
//loaded_fs.insert("bob".to_string(), tree); loaded_fs.insert("bob".to_string(), tree);
Self { Self {
remaining: std::time::Duration::from_secs(0), remaining: std::time::Duration::from_secs(0),
@@ -123,41 +123,23 @@ impl eframe::App for P2PClientApp {
NetworkEvent::FileTreeReceived(_peer_id, _) => { NetworkEvent::FileTreeReceived(_peer_id, _) => {
todo!(); todo!();
//self.loaded_tree_nodes.insert(_peer_id, tree); // self.loaded_tree_nodes.insert(_peer_id, tree);
//self.status_message = "🔄 File tree updated successfully.".to_string(); self.status_message = "🔄 File tree updated successfully.".to_string();
} }
NetworkEvent::FileTreeRootReceived(peer_id, root_hash) => { NetworkEvent::FileTreeRootReceived(peer_id, root_hash) => {
// todo!(); todo!();
/*self.status_message = format!( // self.status_message = format!("🔄 Received Merkle Root from {}: {}", peer_id, &root_hash[..8]);
"🔄 Received Merkle Root from {}: {}", //
peer_id, //
&root_hash[..8] // self.active_peer_id = Some(peer_id.clone());
);*/ //
//
if let Ok(chunknode) = ChunkNode::new(Vec::new()) { // // Request the content of the root directory immediately
let mut data_map: HashMap<NodeHash, MerkleNode> = HashMap::new(); // let _ = self.network_cmd_tx.send(NetworkCommand::RequestDirectoryContent(
data_map.insert(root_hash, MerkleNode::Chunk(chunknode)); // peer_id,
let tree = MerkleTree { // root_hash,
data: data_map, // ));
root: root_hash,
};
match &self.active_peer {
Some(activepeer) => {
self.loaded_fs.insert(activepeer.clone(), tree);
}
None => {}
}
println!("tree created");
}
//self.active_peer_id = Some(peer_id.clone());
// Request the content of the root directory immediately
/*let _ = self
.network_cmd_tx
.send(NetworkCommand::RequestDirectoryContent(peer_id, root_hash));*/
} }
NetworkEvent::Connected(ip) => { NetworkEvent::Connected(ip) => {
self.server_status = ServerStatus::Connected; self.server_status = ServerStatus::Connected;
@@ -319,7 +301,7 @@ impl eframe::App for P2PClientApp {
ui.label("No connection.."); ui.label("No connection..");
} }
ServerStatus::ConnectedHandshake => { ServerStatus::ConnectedHandshake => {
let str = format!("📡"); let str = format!("📡 {}", self.active_server);
ui.label(str); ui.label(str);
} }
} }
@@ -361,29 +343,21 @@ impl eframe::App for P2PClientApp {
} else { } else {
for peer in &self.known_peers { for peer in &self.known_peers {
let is_active = let is_active =
self.active_peer.as_ref().map_or(false, |id| id == &peer.0); // if peer.id == self.active_peer_id self.active_peer.as_ref().map_or(false, |id| id == peer); // if peer.id == self.active_peer_id
let selectable = ui.selectable_label(is_active, format!("{}", peer));
let selectable;
if &self.active_server == &peer.0 {
selectable =
ui.selectable_label(is_active, format!("{} 📡 🌀", peer.0))
} else {
selectable = ui.selectable_label(is_active, format!("{}", peer.0));
}
if selectable.clicked() { if selectable.clicked() {
// switch to displaying this peer's tree // switch to displaying this peer's tree
self.active_peer = Some(peer.0.clone()); self.active_peer = Some(peer.clone());
// Request root content if not loaded // Request root content if not loaded
if !self if !self
.loaded_fs .loaded_fs
.contains_key(self.active_peer.as_ref().unwrap()) .contains_key(self.active_peer.as_ref().unwrap())
{ {
//todo!(); todo!();
let _ = self.network_cmd_tx.send(NetworkCommand::Discover( // let _ = self.network_cmd_tx.send(NetworkCommand::RequestDirectoryContent(
peer.0.clone(), // peer.clone(),
"root".to_string(), // peer.clone(),
self.connected_address.clone(), // ));
));
} }
} }
selectable.context_menu(|ui| { selectable.context_menu(|ui| {
@@ -394,10 +368,10 @@ impl eframe::App for P2PClientApp {
.button("Utiliser le peer en tant que serveur") .button("Utiliser le peer en tant que serveur")
.clicked() .clicked()
{ {
self.active_server = peer.0.to_string(); self.active_server = peer.to_string();
let res = self.network_cmd_tx.send( let res = self.network_cmd_tx.send(
NetworkCommand::ServerHandshake( NetworkCommand::ServerHandshake(
peer.0.to_string(), peer.to_string(),
self.connected_address.clone(), self.connected_address.clone(),
), ),
); );
@@ -405,29 +379,10 @@ impl eframe::App for P2PClientApp {
} }
_ => {} _ => {}
} }
if ui.button("Send Ping").clicked() {
let res = self
.network_cmd_tx
.send(NetworkCommand::Ping(peer.0.to_string()));
}
if ui.button("Send Nat Traversal Request").clicked() {
match self.network_cmd_tx.send(NetworkCommand::NatTraversal(
peer.0.to_string(),
self.connected_address.clone(),
)) {
Ok(_) => {
print!("[+] successfully sent nat traversal request")
}
Err(_) => {
print!("[-] failed to send nat traversal request")
}
}
}
if ui.button("Infos").clicked() { if ui.button("Infos").clicked() {
// action 3 // action 3
ui.close(); ui.close();
} }
// ... autres boutons // ... autres boutons
}); });
} }
@@ -546,13 +501,7 @@ impl P2PClientApp {
entry.content_hash, entry.content_hash,
tree, tree,
depth + 1, depth + 1,
Some( Some(entry.filename),
entry
.filename
.as_slice()
.try_into()
.expect("incorrect size"),
),
); );
} }
}); });
@@ -573,7 +522,7 @@ impl P2PClientApp {
.enabled(true) .enabled(true)
.show(ui, |ui| { .show(ui, |ui| {
for child in &node.children_hashes { for child in &node.children_hashes {
self.draw_file_node(ui, child.content_hash, tree, depth + 1, None); self.draw_file_node(ui, child.clone(), tree, depth + 1, None);
} }
}); });
} }

View File

@@ -1,5 +1,6 @@
use std::io::Read; use std::io::Read;
use crate::messages_structure::HandshakeMessage;
use bytes::Bytes; use bytes::Bytes;
use p256::EncodedPoint; use p256::EncodedPoint;
use p256::ecdsa::{ use p256::ecdsa::{
@@ -7,7 +8,6 @@ use p256::ecdsa::{
signature::{Signer, Verifier}, signature::{Signer, Verifier},
}; };
use rand_core::OsRng; use rand_core::OsRng;
use reqwest::Error;
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
/// ///
@@ -51,24 +51,19 @@ pub async fn get_peer_key(username: &String) -> Result<VerifyingKey, reqwest::Er
let client = reqwest::Client::new(); let client = reqwest::Client::new();
let uri = format!("https://jch.irif.fr:8443/peers/{}/key", username); let uri = format!("https://jch.irif.fr:8443/peers/{}/key", username);
let res = client.get(uri).send().await?; let res = client.get(uri).send().await?;
if res.status().is_success() {
match res.error_for_status_ref() { println!("Successfully retreived the peers key.");
Ok(_) => { } else {
println!("Successfully retreived the peers key."); eprintln!(
let body: Bytes = res.bytes().await?; "Failed to get the peers key from the server. Status: {}",
let slice: &[u8] = body.as_ref(); res.status()
let body_bytes: &[u8; 64] = slice.try_into().expect("size error"); );
let received_key = convert_verifyingkey(body_bytes);
Ok(received_key)
}
Err(e) => {
eprintln!(
"Failed to get the peers key from the server. Status: {}",
res.status()
);
Err(e)
}
} }
let body: Bytes = res.bytes().await?;
let slice: &[u8] = body.as_ref();
let body_bytes: &[u8; 64] = slice.try_into().expect("size error");
let received_key = convert_verifyingkey(body_bytes);
Ok(received_key)
} }
fn convert_verifyingkey(raw_xy: &[u8; 64]) -> VerifyingKey { fn convert_verifyingkey(raw_xy: &[u8; 64]) -> VerifyingKey {
@@ -114,10 +109,11 @@ pub fn sign_message(crypto_pair: &CryptographicSignature, message: &Vec<u8>) ->
let digest = Sha256::digest(&message[..7 + msg_length as usize]); let digest = Sha256::digest(&message[..7 + msg_length as usize]);
let signature = crypto_pair.priv_key.sign_prehash_recoverable(&digest); let signature = crypto_pair.priv_key.sign_prehash_recoverable(&digest);
let message_length = 7 + msg_length as usize + 64; let message_length = 12 + msg_length as usize + 32;
let mut signed_message = Vec::with_capacity(message_length); let mut signed_message = Vec::with_capacity(message_length);
println!("{}", message_length); println!("{}", message_length);
signed_message.extend_from_slice(&message[..7 + msg_length as usize]); signed_message.extend_from_slice(&message[..8 + msg_length as usize]);
signed_message.pop();
println!("signed_tmp:{:?}", signed_message); println!("signed_tmp:{:?}", signed_message);
match signature { match signature {
Ok(signature) => { Ok(signature) => {
@@ -128,7 +124,7 @@ pub fn sign_message(crypto_pair: &CryptographicSignature, message: &Vec<u8>) ->
let s_bytes = s.to_bytes(); let s_bytes = s.to_bytes();
signed_message.extend_from_slice(&r_bytes[..32]); signed_message.extend_from_slice(&r_bytes[..32]);
signed_message.extend_from_slice(&s_bytes[..32]); signed_message.extend_from_slice(&s_bytes[..32]);
println!("signed:{:?}, len: {}", signed_message, signed_message.len()); println!("signed:{:?}", signed_message);
signed_message signed_message
} }
Err(e) => { Err(e) => {
@@ -152,7 +148,10 @@ mod tests {
println!("pubkey : {}", formatted_pubkey); println!("pubkey : {}", formatted_pubkey);
} }
/*#[test] ///
/// signs a message
///
#[test]
fn signing_message() { fn signing_message() {
let username = String::from("gamixtreize"); let username = String::from("gamixtreize");
let crypto_pair = CryptographicSignature::new(username.clone()); let crypto_pair = CryptographicSignature::new(username.clone());
@@ -161,5 +160,5 @@ mod tests {
let signed_message = sign_message(&crypto_pair, &ser); let signed_message = sign_message(&crypto_pair, &ser);
println!("unsigned_message: {:?}", ser); println!("unsigned_message: {:?}", ser);
println!("signed_message: {:?}", signed_message); println!("signed_message: {:?}", signed_message);
}*/ }
} }

View File

@@ -80,7 +80,7 @@ impl MerkleTree {
} }
} }
/*fn generate_random_file_node( fn generate_random_file_node(
storage: &mut HashMap<NodeHash, MerkleNode>, storage: &mut HashMap<NodeHash, MerkleNode>,
) -> Result<NodeHash, String> { ) -> Result<NodeHash, String> {
let mut rng = rng(); let mut rng = rng();
@@ -110,9 +110,9 @@ impl MerkleTree {
storage.insert(hash, node); storage.insert(hash, node);
Ok(hash) Ok(hash)
} }
}*/ }
/*fn generate_random_directory_node( fn generate_random_directory_node(
depth: u32, depth: u32,
max_depth: u32, max_depth: u32,
storage: &mut HashMap<NodeHash, MerkleNode>, storage: &mut HashMap<NodeHash, MerkleNode>,
@@ -172,7 +172,7 @@ impl MerkleTree {
storage.insert(hash, node); storage.insert(hash, node);
Ok(hash) Ok(hash)
} }
}*/ }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ChunkNode { pub struct ChunkNode {
@@ -208,7 +208,7 @@ impl ChunkNode {
// Helper struct // Helper struct
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct DirectoryEntry { pub struct DirectoryEntry {
pub filename: Vec<u8>, pub filename: [u8; FILENAME_HASH_SIZE],
pub content_hash: NodeHash, pub content_hash: NodeHash,
} }
@@ -240,7 +240,7 @@ pub struct BigNode {
} }
impl BigNode { impl BigNode {
/*pub fn new(children_hashes: Vec<NodeHash>) -> Result<Self, String> { pub fn new(children_hashes: Vec<NodeHash>) -> Result<Self, String> {
let n = children_hashes.len(); let n = children_hashes.len();
if n < MIN_BIG_CHILDREN || n > MAX_BIG_CHILDREN { if n < MIN_BIG_CHILDREN || n > MAX_BIG_CHILDREN {
return Err(format!( return Err(format!(
@@ -249,17 +249,16 @@ impl BigNode {
)); ));
} }
Ok(BigNode { children_hashes }) Ok(BigNode { children_hashes })
}*/ }
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BigDirectoryNode { pub struct BigDirectoryNode {
//pub children_hashes: Vec<NodeHash>, pub children_hashes: Vec<NodeHash>,
pub children_hashes: Vec<DirectoryEntry>,
} }
impl BigDirectoryNode { impl BigDirectoryNode {
/*pub fn new(children_hashes: Vec<NodeHash>) -> Result<Self, String> { pub fn new(children_hashes: Vec<NodeHash>) -> Result<Self, String> {
let n = children_hashes.len(); let n = children_hashes.len();
if n < MIN_BIG_CHILDREN || n > MAX_BIG_CHILDREN { if n < MIN_BIG_CHILDREN || n > MAX_BIG_CHILDREN {
return Err(format!( return Err(format!(
@@ -268,14 +267,6 @@ impl BigDirectoryNode {
)); ));
} }
Ok(BigDirectoryNode { children_hashes }) Ok(BigDirectoryNode { children_hashes })
}*/
pub fn new(entries: Vec<DirectoryEntry>) -> Result<Self, String> {
if entries.len() > MAX_DIRECTORY_ENTRIES {
return Err(format!("Directory exceeds {} bytes", entries.len()));
}
Ok(BigDirectoryNode {
children_hashes: entries,
})
} }
} }
@@ -310,14 +301,14 @@ impl MerkleNode {
} }
MerkleNode::BigDirectory(node) => { MerkleNode::BigDirectory(node) => {
for hash in &node.children_hashes { for hash in &node.children_hashes {
bytes.extend_from_slice(&hash.content_hash); bytes.extend_from_slice(hash);
} }
} }
} }
bytes bytes
} }
/*pub fn generate_random_tree( pub fn generate_random_tree(
max_depth: u32, max_depth: u32,
) -> Result<(NodeHash, HashMap<NodeHash, MerkleNode>), String> { ) -> Result<(NodeHash, HashMap<NodeHash, MerkleNode>), String> {
let mut storage = HashMap::new(); let mut storage = HashMap::new();
@@ -326,9 +317,9 @@ impl MerkleNode {
let root_hash = generate_random_directory_node(0, max_depth, &mut storage)?; let root_hash = generate_random_directory_node(0, max_depth, &mut storage)?;
Ok((root_hash, storage)) Ok((root_hash, storage))
}*/ }
/*pub fn generate_base_tree() -> (NodeHash, HashMap<NodeHash, MerkleNode>) { pub fn generate_base_tree() -> (NodeHash, HashMap<NodeHash, MerkleNode>) {
let mut res = HashMap::new(); let mut res = HashMap::new();
let node1 = MerkleNode::Chunk(ChunkNode::new_random()); let node1 = MerkleNode::Chunk(ChunkNode::new_random());
@@ -378,5 +369,5 @@ impl MerkleNode {
res.insert(root_hash, root); res.insert(root_hash, root);
(root_hash, res) (root_hash, res)
}*/ }
} }

View File

@@ -1,96 +0,0 @@
use crate::{BigDirectoryNode, DirectoryEntry, DirectoryNode, MerkleNode, MerkleTree, NodeHash};
use sha2::{Digest, Sha256};
const CHUNK: u8 = 0;
const DIRECTORY: u8 = 1;
const BIG: u8 = 2;
const BIGDIRECTORY: u8 = 3;
fn parse_received_datum(recevied_datum: Vec<u8>, datum_length: usize, mut tree: MerkleTree) {
if datum_length > recevied_datum.len() {
return;
}
if datum_length < 32 + 64 {
return;
}
let hash_name: [u8; 32] = recevied_datum[..32].try_into().expect("error");
let sigstart = datum_length - 64;
let value = &recevied_datum[32..sigstart];
let value_slice = value.to_vec();
let signature: [u8; 32] = recevied_datum[sigstart..datum_length]
.try_into()
.expect("Taille incorrecte");
let datum_type = value_slice[0];
match datum_type {
CHUNK => {
tree.data.insert(
hash_name,
MerkleNode::Chunk(crate::ChunkNode { data: value_slice }),
);
}
DIRECTORY => {
let nb_entries = value_slice[1];
let mut dir_entries = Vec::new();
let mut offset = 1 as usize;
for i in 0..nb_entries {
offset = (offset as u8 + 64 * i) as usize;
let name = &recevied_datum[offset..offset + 32];
let mut hash = [0u8; 32];
hash.copy_from_slice(&recevied_datum[offset + 32..offset + 64]);
// envoyer un datum request
dir_entries.push(DirectoryEntry {
filename: name.to_vec(),
content_hash: hash,
});
}
let current = DirectoryNode::new(dir_entries);
match current {
Ok(current_node) => {
tree.data
.insert(hash_name, MerkleNode::Directory(current_node));
}
Err(e) => {
println!("{}", e);
}
}
}
BIG => {
let chlidren: Vec<NodeHash> = Vec::new();
tree.data.insert(
hash_name,
MerkleNode::Big(crate::BigNode {
children_hashes: chlidren,
}),
);
}
BIGDIRECTORY => {
let nb_entries = value_slice[1];
let mut dir_entries = Vec::new();
let mut offset = 1 as usize;
for i in 0..nb_entries {
offset = (offset as u8 + 64 * i) as usize;
let name = &recevied_datum[offset..offset + 32];
let mut hash = [0u8; 32];
hash.copy_from_slice(&recevied_datum[offset + 32..offset + 64]);
// envoyer un datum request
dir_entries.push(DirectoryEntry {
filename: name.to_vec(),
content_hash: hash,
});
}
let current = BigDirectoryNode::new(dir_entries);
match current {
Ok(current_node) => {
tree.data
.insert(hash_name, MerkleNode::BigDirectory(current_node));
}
Err(e) => {
println!("{}", e);
}
}
}
_ => {}
}
}

View File

@@ -1,10 +1,8 @@
mod cryptographic_signature; mod cryptographic_signature;
mod data; mod data;
mod datum_parsing;
mod message_handling; mod message_handling;
mod messages_channels; mod messages_channels;
mod messages_structure; mod messages_structure;
mod peers_refresh;
mod registration; mod registration;
mod server_communication; mod server_communication;
@@ -12,20 +10,19 @@ use crate::{
cryptographic_signature::CryptographicSignature, cryptographic_signature::CryptographicSignature,
message_handling::EventType, message_handling::EventType,
messages_channels::{MultipleSenders, start_receving_thread}, messages_channels::{MultipleSenders, start_receving_thread},
messages_structure::{ registration::{
NATTRAVERSALREQUEST, NATTRAVERSALREQUEST2, ROOTREQUEST, construct_message, get_socket_address, parse_addresses, register_ip_addresses, register_with_the_server,
}, },
peers_refresh::HandshakeHistory,
registration::{parse_addresses, perform_handshake, register_with_the_server},
server_communication::{generate_id, get_peer_list}, server_communication::{generate_id, get_peer_list},
}; };
use std::{ use std::{
io::Error, fmt,
net::{IpAddr, Ipv4Addr, UdpSocket}, sync::{Arc, Mutex},
}; };
use std::{ use std::{
net::SocketAddr, io::Error,
sync::{Arc, Mutex}, net::{SocketAddr, UdpSocket},
str::FromStr,
}; };
pub struct P2PSharedData { pub struct P2PSharedData {
@@ -34,12 +31,8 @@ pub struct P2PSharedData {
shared_messageslist: Arc<Mutex<HashMap<i32, EventType>>>, shared_messageslist: Arc<Mutex<HashMap<i32, EventType>>>,
shared_senders: Arc<MultipleSenders>, shared_senders: Arc<MultipleSenders>,
server_name: Arc<Mutex<String>>, server_name: Arc<Mutex<String>>,
handshake_peers: Arc<HandshakeHistory>,
} }
use bytes::Bytes;
use p256::pkcs8::der::pem::Base64Encoder;
impl P2PSharedData { impl P2PSharedData {
pub fn new( pub fn new(
username: String, username: String,
@@ -56,14 +49,12 @@ impl P2PSharedData {
let senders = MultipleSenders::new(1, &shared_socket, cmd_tx); let senders = MultipleSenders::new(1, &shared_socket, cmd_tx);
let shared_senders = Arc::new(senders); let shared_senders = Arc::new(senders);
let server_name = Arc::new(Mutex::new("".to_string())); let server_name = Arc::new(Mutex::new("".to_string()));
let handhsake_peers = Arc::new(HandshakeHistory::new());
Ok(P2PSharedData { Ok(P2PSharedData {
shared_socket: shared_socket, shared_socket: shared_socket,
shared_cryptopair: shared_cryptopair, shared_cryptopair: shared_cryptopair,
shared_messageslist: shared_messageslist, shared_messageslist: shared_messageslist,
shared_senders: shared_senders, shared_senders: shared_senders,
server_name: server_name, server_name: server_name,
handshake_peers: handhsake_peers,
}) })
} }
pub fn socket(&self) -> Arc<UdpSocket> { pub fn socket(&self) -> Arc<UdpSocket> {
@@ -94,9 +85,6 @@ impl P2PSharedData {
pub fn cryptopair_ref(&self) -> &CryptographicSignature { pub fn cryptopair_ref(&self) -> &CryptographicSignature {
&*self.shared_cryptopair &*self.shared_cryptopair
} }
pub fn handshake_ref(&self) -> &HandshakeHistory {
&*self.handshake_peers
}
pub fn messages_list_ref(&self) -> &Mutex<HashMap<i32, EventType>> { pub fn messages_list_ref(&self) -> &Mutex<HashMap<i32, EventType>> {
&*self.shared_messageslist &*self.shared_messageslist
@@ -118,16 +106,13 @@ pub enum NetworkCommand {
ServerHandshake(String, String), // ServerName ServerHandshake(String, String), // ServerName
FetchPeerList(String), // ServerIP FetchPeerList(String), // ServerIP
RegisterAsPeer(String), RegisterAsPeer(String),
Ping(String), Ping(),
NatTraversal(String, String), ConnectPeer(String), // IP:PORT
ConnectPeer((String, bool)), // IP:PORT RequestFileTree(String), // peer_id
RequestFileTree(String), // peer_id
RequestDirectoryContent(String, String), RequestDirectoryContent(String, String),
RequestChunk(String, String), RequestChunk(String, String),
Disconnect(), Disconnect(),
ResetServerPeer(), ResetServerPeer(),
Discover(String, String, String),
GetChildren(String, String),
// ... // ...
} }
@@ -141,7 +126,7 @@ pub enum NetworkEvent {
PeerListUpdated(Vec<(String, bool)>), PeerListUpdated(Vec<(String, bool)>),
FileTreeReceived(String, Vec<MerkleNode>), // peer_id, content FileTreeReceived(String, Vec<MerkleNode>), // peer_id, content
DataReceived(String, MerkleNode), DataReceived(String, MerkleNode),
FileTreeRootReceived(String, NodeHash), FileTreeRootReceived(String, String),
HandshakeFailed(), HandshakeFailed(),
ServerHandshakeFailed(String), ServerHandshakeFailed(String),
// ... // ...
@@ -176,8 +161,6 @@ pub fn start_p2p_executor(
// Use tokio to spawn the asynchronous networking logic // Use tokio to spawn the asynchronous networking logic
tokio::task::spawn(async move { tokio::task::spawn(async move {
// P2P/Networking Setup goes here // P2P/Networking Setup goes here
let handshake_history = Arc::new(Mutex::new(HandshakeHistory::new()));
let handshake_clone = handshake_history.clone();
println!("Network executor started."); println!("Network executor started.");
@@ -187,18 +170,66 @@ pub fn start_p2p_executor(
if let Ok(cmd) = cmd_rx.try_recv() { if let Ok(cmd) = cmd_rx.try_recv() {
match cmd { match cmd {
NetworkCommand::ServerHandshake(username, ip) => { NetworkCommand::ServerHandshake(username, ip) => {
println!("server handshake called");
if let Some(sd) = shared_data.as_ref() { if let Some(sd) = shared_data.as_ref() {
start_receving_thread(sd, event_tx.clone(), &handshake_clone); println!("username:{}, ip:{}", username, ip);
let res = let server_addr_query = get_socket_address(username.clone(), ip);
perform_handshake(&sd, username, ip, event_tx.clone(), true).await;
} else { match server_addr_query.await {
println!("no shared data"); Ok(sockaddr_bytes) => {
match String::from_utf8(sockaddr_bytes.to_vec()) {
Ok(s) => {
let addresses = parse_addresses(&s);
if let Some(first) = addresses.first() {
sd.set_servername(username);
// first: &SocketAddr
start_receving_thread(
sd,
*first, // copie le SocketAddr (implémente Copy pour SocketAddr)
);
register_ip_addresses(
sd.cryptopair_ref(),
first.to_string(),
sd.senders_ref(),
sd.messages_list_ref(),
generate_id(),
);
//let res = event_tx
// .send(NetworkEvent::());
} else {
//let res = event_tx.send(NetworkEvent::Error());
let err_msg = format!(
"no valid socket addresses found in: {}",
s
)
.to_string();
let res =
event_tx.send(NetworkEvent::Error(err_msg));
}
}
Err(e) => {
//let res = event_tx.send(NetworkEvent::Error());
let err_msg = format!(
"invalid UTF-8 in socket address bytes: {}",
e
)
.to_string();
let res = event_tx.send(NetworkEvent::Error(err_msg));
}
}
}
Err(e) => {
let err_msg =
format!("failed to retreive socket address: {}", e)
.to_string();
let res = event_tx.send(NetworkEvent::Error(err_msg));
}
}
} }
} }
NetworkCommand::ConnectPeer((username, connected)) => { NetworkCommand::ConnectPeer(addr) => {
println!("[Network] ConnectPeer() called"); println!("[Network] ConnectPeer() called");
println!("[Network] Attempting to connect to: {}", username); println!("[Network] Attempting to connect to: {}", addr);
// Network logic to connect... // Network logic to connect...
// If successful, send an event back: // If successful, send an event back:
// event_tx.send(NetworkEvent::PeerConnected(addr)).unwrap(); // event_tx.send(NetworkEvent::PeerConnected(addr)).unwrap();
@@ -206,56 +237,6 @@ pub fn start_p2p_executor(
NetworkCommand::RequestFileTree(_) => { NetworkCommand::RequestFileTree(_) => {
println!("[Network] RequestFileTree() called"); println!("[Network] RequestFileTree() called");
} }
NetworkCommand::Discover(username, hash, ip) => {
// envoie un handshake au peer, puis un root request
if let Some(sd) = shared_data.as_ref() {
let res = {
let m = handshake_clone.lock().unwrap();
m.get_peer_info_username(username.clone()).cloned()
};
match res {
Some(peerinfo) => {
// envoyer un root request
let rootrequest = construct_message(
ROOTREQUEST,
Vec::new(),
generate_id(),
sd.cryptopair_ref(),
);
match rootrequest {
None => {}
Some(resp_msg) => {
println!("msg_sent:{:?}", resp_msg);
sd.senders_ref().send_via(
0,
resp_msg,
peerinfo.ip.to_string(),
false,
sd.messages_list_ref(),
);
}
}
}
None => {
// envoyer un handshake
let res = perform_handshake(
&sd,
username,
ip,
event_tx.clone(),
false,
)
.await;
}
}
} else {
println!("no shared data");
}
}
NetworkCommand::GetChildren(username, hash) => {
// envoie un datum request au peer
}
NetworkCommand::RequestDirectoryContent(_, _) => { NetworkCommand::RequestDirectoryContent(_, _) => {
println!("[Network] RequestDirectoryContent() called"); println!("[Network] RequestDirectoryContent() called");
} }
@@ -315,7 +296,7 @@ pub fn start_p2p_executor(
let mut current = String::new(); let mut current = String::new();
for i in peers_list.chars() { for i in peers_list.chars() {
if i == '\n' { if i == '\n' {
peers.push((current.clone(), false)); peers.push(current.clone());
current.clear(); current.clear();
} else { } else {
current.push(i); current.push(i);
@@ -336,7 +317,7 @@ pub fn start_p2p_executor(
NetworkCommand::RegisterAsPeer(_) => { NetworkCommand::RegisterAsPeer(_) => {
println!("[Network] RegisterAsPeer() called"); println!("[Network] RegisterAsPeer() called");
} }
NetworkCommand::Ping(String) => { NetworkCommand::Ping() => {
println!("[Network] Ping() called"); println!("[Network] Ping() called");
} }
NetworkCommand::Disconnect() => { NetworkCommand::Disconnect() => {
@@ -355,52 +336,6 @@ pub fn start_p2p_executor(
println!("no p2p data"); println!("no p2p data");
} }
} }
NetworkCommand::NatTraversal(username, ip) => {
if let Some(sd) = shared_data.as_ref() {
println!("username:{}, ip:{}", username, ip);
// user server to send nattraversal request
let server_addr_query =
get_socket_address(sd.servername().clone(), ip.clone());
let peer_addr_query = get_socket_address(username.clone(), ip.clone());
match server_addr_query.await {
Some(server_addr) => match peer_addr_query.await {
Some(peer_addr) => {
let payload = socket_addr_to_vec(server_addr);
print!("{:?}", payload.clone());
let natreq = construct_message(
NATTRAVERSALREQUEST,
server_addr.to_string().into_bytes(),
generate_id(),
&sd.cryptopair(),
);
sd.senders_ref().send_via(
0,
natreq.expect(
"couldnt construct message nattraversalrequest2",
),
server_addr.to_string(),
false,
sd.messages_list_ref(),
);
}
None => {
let err_msg = format!("failed to retreive socket address")
.to_string();
let res = event_tx.send(NetworkEvent::Error(err_msg));
}
},
None => {
let err_msg =
format!("failed to retreive socket address").to_string();
let res = event_tx.send(NetworkEvent::Error(err_msg));
}
}
}
}
} }
} }
@@ -414,78 +349,3 @@ pub fn start_p2p_executor(
} }
}) })
} }
fn socket_addr_to_vec(addr: SocketAddr) -> Vec<u8> {
let mut v = match addr.ip() {
IpAddr::V4(v4) => v4.octets().to_vec(),
IpAddr::V6(v6) => v6.octets().to_vec(),
};
v.extend(&addr.port().to_be_bytes());
v
}
fn parse_pack(s: &str) -> Option<[u8; 6]> {
// split into "ip" and "port"
let mut parts = s.rsplitn(2, ':');
let port_str = parts.next()?;
let ip_str = parts.next()?; // if missing, invalid
let ip: Ipv4Addr = ip_str.parse().ok()?;
let port: u16 = port_str.parse().ok()?;
let octets = ip.octets();
let port_be = port.to_be_bytes();
Some([
octets[0], octets[1], octets[2], octets[3], port_be[0], port_be[1],
])
}
///
/// sends a get request to the server to get the socket address of the given peer
///
pub async fn get_socket_address(username: String, ip: String) -> Option<SocketAddr> {
let client = reqwest::Client::new();
let uri = format!("{}/peers/{}/addresses", ip, username);
let res = client.get(uri).send().await.expect("couldnt get response");
if res.status().is_success() {
println!("Successfully retreived the addresses.");
} else {
eprintln!(
"Failed to get the peers addresses from the server. Status: {}",
res.status()
);
}
let body: Bytes = res.bytes().await.expect("couldnt get bytes");
match String::from_utf8(body.to_vec()) {
Ok(s) => {
let addresses = parse_addresses(&s);
addresses.iter().copied().find(|a| a.is_ipv4())
}
Err(_) => None,
}
}
pub async fn get_possible_socket_address(username: String, ip: String) -> Vec<SocketAddr> {
let client = reqwest::Client::new();
let uri = format!("{}/peers/{}/addresses", ip, username);
let res = client.get(uri).send().await.expect("couldnt get response");
if res.status().is_success() {
println!("Successfully retreived the addresses.");
} else {
eprintln!(
"Failed to get the peers addresses from the server. Status: {}",
res.status()
);
}
let body: Bytes = res.bytes().await.expect("couldnt get bytes");
match String::from_utf8(body.to_vec()) {
Ok(s) => {
let addresses = parse_addresses(&s);
addresses.iter().copied().filter(|a| a.is_ipv4()).collect()
}
Err(_) => Vec::new(),
}
}

View File

@@ -1,53 +1,52 @@
use crate::{ use crate::{
NetworkEvent, NodeHash, NetworkEvent,
cryptographic_signature::{ cryptographic_signature::{
CryptographicSignature, get_peer_key, sign_message, verify_signature, CryptographicSignature, get_peer_key, sign_message, verify_signature,
}, },
messages_channels::MultipleSenders, messages_channels::MultipleSenders,
messages_structure::construct_message, messages_structure::HandshakeMessage,
peers_refresh::HandshakeHistory,
registration, registration,
server_communication::generate_id,
}; };
use std::sync::{Arc, Mutex};
use std::{collections::HashMap, net::SocketAddr}; use std::{collections::HashMap, net::SocketAddr};
use std::{
net::IpAddr,
sync::{Arc, Mutex},
};
pub enum EventType { pub enum EventType {
SendRootRequest, ServerHelloReply,
PeerHelloReply,
PeerHello,
} }
const ID: usize = 4; /*pub fn handle_recevied_message(
const TYPE: usize = 5; messages_list: &mut HashMap<i32, EventType>,
const LENGTH: usize = 7; recevied_message: &Vec<u8>,
const EXTENSIONS: usize = 4; crypto_pair: &CryptographicSignature,
const SIGNATURE: usize = 64; socket_addr: &SocketAddr,
senders: &MultipleSenders,
const PING: u8 = 0; ) {
const OK: u8 = 128; let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error");
const ERROR: u8 = 129; let id = i32::from_be_bytes(message_id);
const HELLO: u8 = 1; let eventtype = messages_list.get(&id);
const HELLOREPLY: u8 = 130; match eventtype {
const ROOTREQUEST: u8 = 2; Some(EventType::ServerHelloReply) => {
const ROOTREPLY: u8 = 131; registration::register_ip_addresses(
const DATUMREQUEST: u8 = 3; &crypto_pair,
const NODATUM: u8 = 133; socket_addr.ip().to_string(),
const DATUM: u8 = 132; &senders,
const NATTRAVERSALREQUEST: u8 = 4; messages_list,
const NATTRAVERSALREQUEST2: u8 = 5; );
}
Some(_) => print!("Not implemented"),
None => print!("Message not found"),
}
}*/
pub fn handle_recevied_message( pub fn handle_recevied_message(
messages_list: &Arc<Mutex<HashMap<i32, EventType>>>, messages_list: &Arc<Mutex<HashMap<i32, EventType>>>,
recevied_message: &Vec<u8>, recevied_message: &Vec<u8>,
crypto_pair: &CryptographicSignature, crypto_pair: &CryptographicSignature,
//socket_addr: &SocketAddr, socket_addr: &SocketAddr,
senders: &MultipleSenders, senders: &MultipleSenders,
server_name: &String, server_name: &String,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr,
handhsake_history: &Arc<Mutex<HandshakeHistory>>,
) { ) {
if recevied_message.len() < 4 { if recevied_message.len() < 4 {
return; return;
@@ -56,48 +55,8 @@ pub fn handle_recevied_message(
let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error"); let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error");
let id = i32::from_be_bytes(message_id); let id = i32::from_be_bytes(message_id);
let mut is_resp_to_server_handshake = false;
if recevied_message[4] == HELLO {
let length_bytes: [u8; 2] = recevied_message[TYPE..LENGTH]
.try_into()
.expect("Taille incorrecte");
let msg_length = u16::from_be_bytes(length_bytes) as usize;
let ilength = u16::from_be_bytes(length_bytes);
let received_name = &recevied_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize];
let name = String::from_utf8(received_name.to_vec()).expect("wrong name");
if name.clone() == server_name.clone() {
is_resp_to_server_handshake = true;
}
}
let resp = parse_message(
recevied_message.to_vec(),
id,
crypto_pair,
cmd_tx,
ip,
messages_list,
handhsake_history,
senders,
);
match resp {
None => {}
Some(resp_msg) => {
println!("msg_sent:{:?}", resp_msg);
senders.send_via(
0,
resp_msg,
ip.to_string(),
is_resp_to_server_handshake,
messages_list,
);
}
}
// Lock the mutex to access the HashMap // Lock the mutex to access the HashMap
/*let list = messages_list.lock().unwrap(); let list = messages_list.lock().unwrap();
let eventtype = list.get(&id); // Clone the enum so we can release the lock if needed let eventtype = list.get(&id); // Clone the enum so we can release the lock if needed
match eventtype { match eventtype {
@@ -159,315 +118,5 @@ pub fn handle_recevied_message(
} }
print!("Message not found for ID: {}", id) print!("Message not found for ID: {}", id)
} }
}*/
}
pub fn parse_message(
received_message: Vec<u8>,
id: i32,
crypto_pair: &CryptographicSignature,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr,
messages_list: &Arc<Mutex<HashMap<i32, EventType>>>,
handhsake_history_mutex: &Arc<Mutex<HandshakeHistory>>,
senders: &MultipleSenders,
) -> Option<Vec<u8>> {
let mut handhsake_history = handhsake_history_mutex.lock().unwrap();
let cmd_tx_clone = cmd_tx.clone();
let id_bytes: [u8; 4] = received_message[0..ID]
.try_into()
.expect("Taille incorrecte");
let msgtype = received_message[ID];
let length_bytes: [u8; 2] = received_message[TYPE..LENGTH]
.try_into()
.expect("Taille incorrecte");
let msg_length = u16::from_be_bytes(length_bytes) as usize;
// verify signature
match msgtype {
HELLO | HELLOREPLY | NODATUM | NATTRAVERSALREQUEST | NATTRAVERSALREQUEST2 => {
let ilength = u16::from_be_bytes(length_bytes);
println!("name received length: {}", ilength);
let received_name = &received_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize];
let received_username = String::from_utf8(received_name.to_vec());
match received_username {
Ok(username) => {
let peer_pubkey =
match handhsake_history.get_peer_info_username(username.clone()) {
Some(peerinfo) => peerinfo.pubkey,
_ => tokio::runtime::Runtime::new()
.unwrap()
.block_on(get_peer_key(&username))
.expect("failed to retrieve public key"),
};
match msgtype {
HELLOREPLY => {
handhsake_history.add_new_handshake(peer_pubkey, "".to_string(), ip);
}
_ => {}
}
let signature: [u8; SIGNATURE] = received_message
[LENGTH + msg_length..LENGTH + msg_length + SIGNATURE]
.try_into()
.expect("Taille incorrecte");
if !verify_signature(peer_pubkey, &received_message) {
println!(
"incorrect signature from given peer: {}, ignoring message of type {} with id {}",
&username, received_message[ID], id
);
return None;
}
}
Err(e) => {
println!("incorrect name: {}", e);
return None;
}
}
}
ROOTREPLY => {
let ilength = u16::from_be_bytes(length_bytes);
println!("name received length: {}", ilength);
if let Some(peerinfo) = handhsake_history.get_peer_info_ip(ip.to_string()) {
if !verify_signature(peerinfo.pubkey, &received_message) {
println!(
"incorrect signature from given peer: {}, ignoring message of type {} with id {}",
&peerinfo.username, received_message[ID], id
);
return None;
} else {
println!("signature verified");
}
}
}
_ => {}
} }
// Message handling
let mut constructed_message: Option<Vec<u8>> = None;
match msgtype {
// PING
//
// envoie un OK
PING => {
constructed_message = construct_message(OK, Vec::new(), id, crypto_pair);
}
//
// OK
//
// rien ?
// si NATTRAVERSALREQUEST alors
NATTRAVERSALREQUEST => {
// send ok & send nattraversalrequest2 to peer
constructed_message = construct_message(OK, Vec::new(), id, crypto_pair);
let ilength = u16::from_be_bytes(length_bytes);
let received_address =
&received_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize];
let address = String::from_utf8(received_address.to_vec()).expect("wrong name");
let natreq2 = construct_message(
NATTRAVERSALREQUEST2,
ip.to_string().into_bytes(),
id,
crypto_pair,
);
senders.send_via(
0,
natreq2.expect("couldnt construct message nattraversalrequest2"),
address,
false,
&messages_list,
);
}
NATTRAVERSALREQUEST2 => {
// send ok & send ping to peer
constructed_message = construct_message(OK, Vec::new(), id, crypto_pair);
let ilength = u16::from_be_bytes(length_bytes);
let received_address = &received_message[LENGTH..LENGTH + ilength as usize];
let address = String::from_utf8(received_address.to_vec()).expect("wrong name");
let pingreq = construct_message(PING, Vec::new(), id, crypto_pair);
senders.send_via(
0,
pingreq.expect("couldnt construct message ping request"),
address,
false,
&messages_list,
);
}
//
// ERROR
//
// affiche un msg d'erreur
ERROR => {
if let Ok(err_received) =
String::from_utf8(received_message[LENGTH..(msg_length + LENGTH)].to_vec())
{
let err_msg = format!("Error received from peer {} : {}", ip, err_received);
let _ = cmd_tx_clone.send(NetworkEvent::Error(err_msg));
} else {
let err_msg = format!("Error received from peer {} : N/A", ip,);
let _ = cmd_tx_clone.send(NetworkEvent::Error(err_msg));
}
}
// HELLO
//
// envoie une hello reply
//
HELLO => {
let mut payload = Vec::new();
payload.extend_from_slice(&0u32.to_be_bytes());
payload.extend_from_slice(&crypto_pair.username.clone().as_bytes());
let helloreply = construct_message(HELLOREPLY, payload, id, crypto_pair);
return helloreply;
}
// HELLOREPLY
//
//
// ajoute a la liste des peers handshake
HELLOREPLY => {
// ajoute l'username a la liste des peers handshake
let received_length = u16::from_be_bytes(
received_message[TYPE..LENGTH]
.try_into()
.expect("incorrect size"),
);
let received_username =
&received_message[LENGTH + EXTENSIONS..LENGTH + received_length as usize];
handhsake_history.update_peer_info(
ip.to_string(),
String::from_utf8(received_username.to_vec()).expect("invalid conversion"),
);
// verifie s'il faut renvoyer un root request
let guard = messages_list.lock().expect("Échec du verrouillage");
let res = guard.get(&id);
match res {
Some(ev) => {
match ev {
EventType::SendRootRequest => {
// envoyer la root request
let rootrequest = construct_message(
ROOTREQUEST,
Vec::new(),
generate_id(),
crypto_pair,
);
return rootrequest;
}
}
}
None => {}
}
}
//
// ROOTREQUEST
//
// envoie un root reply
//
// ROOTREPLY
//
ROOTREPLY => {
// recuperer le pseudo du peers ayant repondu
let peers_exist = handhsake_history.get_peer_info_ip(ip.to_string());
match peers_exist {
Some(peerinfo) => {
// envoyer le hash a la gui
let received_hash: NodeHash = received_message[LENGTH..(32 + LENGTH)]
.try_into()
.expect("incorrect size");
let res = cmd_tx_clone.send(NetworkEvent::FileTreeRootReceived(
peerinfo.username.clone(),
received_hash,
));
println!("file tree sent")
}
None => {
eprintln!("no peers found");
}
}
}
//
// DATUMREQUEST
//
// envoie le datum
//
// NODATUM
//
// affiche un msg d'erreur
//
// DATUM
//
// parcourt le directory recu ou le big directory et renvoie une DATUMREQUEST pour chaque
// directory ou big directory lu
//
// NATTRAVERSALREQUEST
//
// repond OK et envoie un NATTRAVERSALREQUEST2 au pair B
//
// NATTRAVERSALREQUEST2
//
// envoie OK à S puis envoie un ping à S
// PING
//
// envoie un OK
//
// OK
//
// si NATTRAVERSALREQUEST alors
//
// ERROR
//
// affiche un msg d'erreur
//
// HELLO
//
// envoie une hello reply
//
// HELLOREPLY
//
// envoie un root request
//
// ROOTREQUEST
//
// envoie un root reply
//
// ROOTREPLY
//
// envoie un datum request
//
// DATUMREQUEST
//
// envoie le datum
//
// NODATUM
//
// affiche un msg d'erreur
//
// DATUM
//
// parcourt le directory recu ou le big directory et renvoie une DATUMREQUEST pour chaque
// directory ou big directory lu
//
// NATTRAVERSALREQUEST
//
// repond OK et envoie un NATTRAVERSALREQUEST2 au pair B
//
// NATTRAVERSALREQUEST2
//
// envoie OK à S puis envoie un ping à S
_ => return None,
};
constructed_message
} }

View File

@@ -2,7 +2,6 @@ use crate::P2PSharedData;
use crate::cryptographic_signature::CryptographicSignature; use crate::cryptographic_signature::CryptographicSignature;
use crate::message_handling::EventType; use crate::message_handling::EventType;
use crate::message_handling::handle_recevied_message; use crate::message_handling::handle_recevied_message;
use crate::peers_refresh::HandshakeHistory;
use std::collections::HashMap; use std::collections::HashMap;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::net::UdpSocket; use std::net::UdpSocket;
@@ -22,9 +21,9 @@ pub struct MultipleSenders {
} }
pub struct Message { pub struct Message {
pub payload: Vec<u8>, payload: Vec<u8>,
pub address: String, address: String,
pub is_resp_to_server_handshake: bool, is_resp_to_server_handshake: bool,
} }
struct RetryMessage { struct RetryMessage {
@@ -206,74 +205,60 @@ impl MultipleSenders {
data: Vec<u8>, data: Vec<u8>,
remote_addr: String, remote_addr: String,
is_resp_to_server_handshake: bool, is_resp_to_server_handshake: bool,
messages_list: &Mutex<HashMap<i32, EventType>>,
) { ) {
println!( println!(
"is_resp_to_server_handshake {}", "is_resp_to_server_handshake {}",
is_resp_to_server_handshake is_resp_to_server_handshake
); );
let msg_to_send = Message {
payload: data.clone(),
address: remote_addr,
is_resp_to_server_handshake,
};
if let Some(sender) = self.senders.get(channel_idx) { if let Some(sender) = self.senders.get(channel_idx) {
let _ = sender.send(msg_to_send); let _ = sender.send(Message {
} payload: data,
if !is_resp_to_server_handshake { address: remote_addr,
let mut guard = messages_list.lock().unwrap(); is_resp_to_server_handshake,
let message_id: [u8; 4] = data[0..4].try_into().expect("size error"); });
let id = i32::from_be_bytes(message_id);
guard.insert(id, EventType::SendRootRequest);
} }
} }
/*pub fn start_receving_thread(
socket: &Arc<UdpSocket>,
messages_list: &Arc<HashMap<i32, EventType>>,
crypto_pair: &Arc<CryptographicSignature>,
socket_addr: SocketAddr,
senders: &Arc<MultipleSenders>,
) {
let sock_clone = Arc::clone(socket);
let cryptopair_clone = Arc::clone(crypto_pair);
let senders_clone = Arc::clone(senders);
let messages_clone = Arc::clone(messages_list);
thread::spawn(move || {
let mut buf = [0u8; 1024];
loop {
match sock_clone.recv_from(&mut buf) {
Ok((amt, src)) => {
handle_recevied_message(
&messages_clone,
&buf.to_vec(),
&cryptopair_clone,
&socket_addr,
&senders_clone,
);
println!("Reçu {} octets de {}: {:?}", amt, src, &buf[..amt]);
}
Err(e) => eprintln!("Erreur de réception: {}", e),
}
}
});
}*/
} }
pub fn start_receving_thread( /*pub fn start_receving_thread(
shared_data: &P2PSharedData, socket: &Arc<UdpSocket>,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>, messages_list: &Arc<HashMap<i32, EventType>>,
handshake_history: &Arc<Mutex<HandshakeHistory>>, crypto_pair: &Arc<CryptographicSignature>,
socket_addr: SocketAddr,
senders: &Arc<MultipleSenders>,
) { ) {
let sock_clone = Arc::clone(socket);
let cryptopair_clone = Arc::clone(crypto_pair);
let senders_clone = Arc::clone(senders);
let messages_clone = Arc::clone(messages_list);
thread::spawn(move || {
let mut buf = [0u8; 1024];
loop {
match sock_clone.recv_from(&mut buf) {
Ok((amt, src)) => {
handle_recevied_message(
&messages_clone,
&buf.to_vec(),
&cryptopair_clone,
&socket_addr,
&senders_clone,
);
println!("Reçu {} octets de {}: {:?}", amt, src, &buf[..amt]);
}
Err(e) => eprintln!("Erreur de réception: {}", e),
}
}
});
}*/
pub fn start_receving_thread(shared_data: &P2PSharedData, socket_addr: SocketAddr) {
let sock_clone = shared_data.socket(); let sock_clone = shared_data.socket();
let cryptopair_clone = shared_data.cryptopair(); let cryptopair_clone = shared_data.cryptopair();
let senders_clone = shared_data.senders(); let senders_clone = shared_data.senders();
let messages_clone = shared_data.messages_list(); let messages_clone = shared_data.messages_list();
let servername_clone = shared_data.servername(); let servername_clone = shared_data.servername();
let handshake_clone = handshake_history.clone();
thread::spawn(move || { thread::spawn(move || {
let mut buf = [0u8; 1024]; let mut buf = [0u8; 1024];
loop { loop {
@@ -286,11 +271,9 @@ pub fn start_receving_thread(
&messages_clone, &messages_clone,
&received_data, &received_data,
&cryptopair_clone, &cryptopair_clone,
&socket_addr,
&senders_clone, &senders_clone,
&servername_clone, &servername_clone,
cmd_tx.clone(),
src,
&handshake_clone,
); );
} }
Err(e) => eprintln!("Erreur de réception: {}", e), Err(e) => eprintln!("Erreur de réception: {}", e),

View File

@@ -1,72 +1,3 @@
use crate::cryptographic_signature::{CryptographicSignature, sign_message};
const ID: usize = 4;
const TYPE: usize = 5;
const LENGTH: usize = 7;
const EXTENSIONS: usize = 4;
const SIGNATURE: usize = 64;
pub(crate) const PING: u8 = 0;
pub(crate) const OK: u8 = 128;
pub(crate) const ERROR: u8 = 129;
pub(crate) const HELLO: u8 = 1;
pub(crate) const HELLOREPLY: u8 = 130;
pub(crate) const ROOTREQUEST: u8 = 2;
pub(crate) const ROOTREPLY: u8 = 131;
pub(crate) const DATUMREQUEST: u8 = 3;
pub(crate) const NODATUM: u8 = 133;
pub(crate) const DATUM: u8 = 132;
pub(crate) const NATTRAVERSALREQUEST: u8 = 4;
pub(crate) const NATTRAVERSALREQUEST2: u8 = 5;
pub fn construct_message(
msgtype: u8,
payload: Vec<u8>,
id: i32,
crypto_pair: &CryptographicSignature,
) -> Option<Vec<u8>> {
let mut message = Vec::new();
// ID
// type
message.extend_from_slice(&id.to_be_bytes());
message.push(msgtype);
match msgtype {
HELLO | HELLOREPLY => {
// length
let a = payload.len() as u16;
println!("payload size:{}", a);
message.extend_from_slice(&a.to_be_bytes());
message.extend_from_slice(&payload);
let signature = sign_message(crypto_pair, &message);
return Some(signature);
}
PING | OK | ROOTREQUEST => {
message.extend_from_slice(&0u16.to_be_bytes());
return Some(message);
}
ERROR | DATUMREQUEST => {
message.extend_from_slice(&payload.len().to_be_bytes());
message.extend_from_slice(&payload);
return Some(message);
}
ROOTREPLY | NODATUM | DATUM | NATTRAVERSALREQUEST => {
println!("payload:{:?}", &payload);
message.extend_from_slice(&(payload.len() as u16).to_be_bytes());
message.extend_from_slice(&payload);
println!("payload:{:?}", &message);
let signature = sign_message(crypto_pair, &message);
message.extend_from_slice(&signature);
return Some(message);
}
_ => {}
}
None
}
pub struct UDPMessage { pub struct UDPMessage {
id: u32, id: u32,
msg_type: u8, msg_type: u8,

View File

@@ -1,160 +0,0 @@
// this class consists of a thread that will re send pings every time the first element
// of the stack is at the correct unix time
use std::{
collections::{HashMap, VecDeque},
net::{AddrParseError, Ipv4Addr, SocketAddr},
ops::Add,
process::Command,
sync::{Arc, Mutex},
thread,
time::{self, Duration, SystemTime},
};
use crate::NetworkEvent;
use crate::{
P2PSharedData, construct_message, generate_id, messages_structure,
registration::perform_handshake,
};
use crossbeam_channel::{Receiver, Sender};
use p256::ecdsa::VerifyingKey;
#[derive(Debug, Clone)]
pub struct PeerInfo {
pub username: String,
pub pubkey: VerifyingKey,
pub ip: SocketAddr,
}
pub struct HandshakeHistory {
//time_k_ip_v: HashMap<u64, u64>,
username_k_peerinfo_v: HashMap<String, PeerInfo>,
ip_k_peerinfo_v: HashMap<String, PeerInfo>,
}
impl HandshakeHistory {
pub fn new() -> HandshakeHistory {
HandshakeHistory {
//time_k_ip_v: HashMap::new(),
//ip_k_peerinfo_v: HashMap::new(),
username_k_peerinfo_v: HashMap::new(),
ip_k_peerinfo_v: HashMap::new(),
}
}
/*pub fn update_handshake(&self) {
let hashmap_shared = Arc::new(self.username_k_peerinfo_v);
thread::spawn(move || {
let selfhashmap = hashmap_shared.clone();
loop {
for peer in selfhashmap.keys() {
let peer_ip = selfhashmap.get(peer);
// send ping
}
let mut child = Command::new("sleep").arg("10").spawn().unwrap();
let _result = child.wait().unwrap();
}
});
}*/
pub fn get_peer_info_username(&self, username: String) -> Option<&PeerInfo> {
self.username_k_peerinfo_v.get(&username).clone()
}
pub fn get_peer_info_ip(&self, ip: String) -> Option<&PeerInfo> {
self.ip_k_peerinfo_v.get(&ip).clone()
}
pub fn update_handshake(&self) {
// clone the map so we own it (cheap if PeerInfo is Clone)
let map_clone: Arc<HashMap<String, PeerInfo>> =
Arc::new(self.username_k_peerinfo_v.clone());
//let map_ip_clone: Arc<HashMap<String, PeerInfo>> = Arc::new(self.ip_k_peerinfo_v.clone());
let map_for_thread = Arc::clone(&map_clone);
thread::spawn(move || {
loop {
// Arc<HashMap<..>> derefs to &HashMap so these reads work
for (peer, peerinfo) in map_for_thread.iter() {
// send ping to peerinfo
}
thread::sleep(Duration::from_secs(10));
}
});
}
pub fn update_peer_info(&mut self, ip: String, username: String) {
let peerinfo = self.get_peer_info_ip(ip.clone());
match peerinfo {
Some(peer_info) => match ip.parse::<SocketAddr>() {
Ok(addr) => {
let new_peer_info = PeerInfo {
username: username.clone(),
pubkey: peer_info.pubkey,
ip: addr,
};
self.ip_k_peerinfo_v.insert(ip, new_peer_info.clone());
self.username_k_peerinfo_v.insert(username, new_peer_info);
}
Err(e) => eprintln!("parse error: {}", e),
},
None => {
eprintln!("no peer info found in hashmap")
}
}
}
pub fn add_new_handshake(&mut self, hash: VerifyingKey, username: String, ip: SocketAddr) {
let peerinfo = PeerInfo {
username: username.clone(),
pubkey: hash,
ip,
};
self.username_k_peerinfo_v
.insert(username, peerinfo.clone());
self.ip_k_peerinfo_v
.insert(ip.to_string(), peerinfo.clone());
}
}
pub fn perform_discover(
username: String,
hash: String,
sd: &P2PSharedData,
server_ip: String,
event_tx: Sender<NetworkEvent>,
) {
// first, sends handshake
if hash == "root" {
perform_handshake(sd, username, server_ip, event_tx, false);
/*if let Some(data) = construct_message(
messages_structure::ROOTREQUEST,
Vec::new(),
generate_id(),
sd.cryptopair_ref(),
) {
if let Some(peerinfo) = sd.handshake_ref() {
sd.senders_ref()
.send_via(0, data, peerinfo.ip.to_string(), false);
}
}*/
} else {
// envoyer un datum request
}
}
#[cfg(test)]
mod tests {
use std::net::{IpAddr, Ipv4Addr};
use super::*;
/*#[test]
fn creating_cryptographic_signature() {
let mut hh = HandshakeHistory::new();
hh.add_new_handshake(
20,
"putain".to_string(),
SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 1),
);
}*/
}

View File

@@ -1,14 +1,10 @@
use bytes::Bytes; use bytes::Bytes;
use getrandom::Error;
use crate::NetworkEvent;
use crate::P2PSharedData;
use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message}; use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message};
use crate::get_socket_address;
use crate::message_handling::EventType; use crate::message_handling::EventType;
use crate::messages_channels::MultipleSenders; use crate::messages_channels::{Message, MultipleSenders};
use crate::messages_structure::construct_message; use crate::messages_structure::{HandshakeMessage, UDPMessage};
use crate::server_communication::generate_id;
use crossbeam_channel::{Receiver, Sender};
use std::collections::HashMap; use std::collections::HashMap;
use std::net::SocketAddr; use std::net::SocketAddr;
use std::net::UdpSocket; use std::net::UdpSocket;
@@ -33,6 +29,26 @@ pub async fn register_with_the_server(
Ok(()) Ok(())
} }
///
/// sends a get request to the server to get the socket address of the given peer
///
pub async fn get_socket_address(username: String, ip: String) -> Result<Bytes, reqwest::Error> {
let client = reqwest::Client::new();
let uri = format!("{}/peers/{}/addresses", ip, username);
let res = client.get(uri).send().await?;
if res.status().is_success() {
println!("Successfully retreived the addresses.");
} else {
eprintln!(
"Failed to get the peers addresses from the server. Status: {}",
res.status()
);
}
let body: Bytes = res.bytes().await?;
Ok(body)
}
pub fn parse_addresses(input: &String) -> Vec<SocketAddr> { pub fn parse_addresses(input: &String) -> Vec<SocketAddr> {
let mut addrs = Vec::new(); let mut addrs = Vec::new();
for line in input.lines() { for line in input.lines() {
@@ -50,47 +66,24 @@ pub fn parse_addresses(input: &String) -> Vec<SocketAddr> {
/// ///
/// registers the IP addresses by sending a Hello request to the server. /// registers the IP addresses by sending a Hello request to the server.
/// ///
pub async fn perform_handshake( pub fn register_ip_addresses(
sd: &P2PSharedData, crypto_pair: &CryptographicSignature,
username: String, server_uri: String,
ip: String, senders: &MultipleSenders,
event_tx: Sender<NetworkEvent>, messages_list: &Mutex<HashMap<i32, EventType>>,
is_server_handshake: bool, id: i32,
) { ) {
println!("username: {}, ip: {}", username.clone(), ip.clone()); let username_size = crypto_pair.username.len();
let crypto_pair = sd.cryptopair_ref(); let hello_handshake = HandshakeMessage::hello(
let senders = sd.senders_ref(); id as u32,
let messages_list = sd.messages_list_ref(); username_size as u16 + 4,
let id = generate_id(); crypto_pair.username.clone(),
let server_addr_query = get_socket_address(username.clone(), ip.clone()); );
match server_addr_query.await { //HandshakeMessage::display(&hello_handshake);
Some(sockaddr_bytes) => { let hello_handshake_serialized = hello_handshake.serialize();
sd.set_servername(username); let message_signed = sign_message(crypto_pair, &hello_handshake_serialized);
// first: &SocketAddr senders.send_via(0, message_signed, server_uri, false);
let mut payload = Vec::new(); let mut list = messages_list.lock().expect("Failed to lock messages_list");
payload.extend_from_slice(&0u32.to_be_bytes());
payload.extend_from_slice(&crypto_pair.username.clone().as_bytes());
let hello_handshake = construct_message(1, payload, id, crypto_pair);
match hello_handshake {
Some(handshake_message) => {
senders.send_via(
0,
handshake_message,
sockaddr_bytes.to_string(),
is_server_handshake,
messages_list,
);
}
None => {}
}
}
None => {
let err_msg = format!("failed to retreive socket address:").to_string();
let res = event_tx.send(NetworkEvent::Error(err_msg));
}
}
/*let mut list = messages_list.lock().expect("Failed to lock messages_list");
match list.get(&id) { match list.get(&id) {
Some(_) => { Some(_) => {
list.remove(&id); list.remove(&id);
@@ -99,13 +92,12 @@ pub async fn perform_handshake(
list.insert(id, EventType::ServerHelloReply); list.insert(id, EventType::ServerHelloReply);
} }
} }
println!("message sent: {}", &id);*/ println!("message sent: {}", &id);
// 3. Perform the insertion // 3. Perform the insertion
/*let mut buf = [0u8; 1024]; /*let mut buf = [0u8; 1024];
socket.recv_from(&mut buf).expect("receive failed"); socket.recv_from(&mut buf).expect("receive failed");
let hello_handshake_received = UDPMessage::parse(buf.to_vec()); let hello_handshake_received = UDPMessage::parse(buf.to_vec());
hello_handshake_received.display();*/ hello_handshake_received.display();*/
//TODO
} }
#[cfg(test)] #[cfg(test)]

36
todo.md
View File

@@ -2,12 +2,6 @@
## peer discovery ## peer discovery
## handshake
# Todo
## peer discovery
- get rsquest to the uri /peers/ - get rsquest to the uri /peers/
## registration with the server ## registration with the server
@@ -21,7 +15,6 @@
## handshake ## handshake
- handshake structure OK - handshake structure OK
- 5min timeout after handshake - 5min timeout after handshake
- matain connection every 4 min - matain connection every 4 min
@@ -34,8 +27,6 @@
- setting in gui to act as a relay - setting in gui to act as a relay
- chunk, directory, big, bigdirectory structures - chunk, directory, big, bigdirectory structures
## fonctionnalités application
## nat traversal ## nat traversal
- make hello and helloreply messages set the first extension bit to announce that peer is available for nat traversal - make hello and helloreply messages set the first extension bit to announce that peer is available for nat traversal
@@ -45,29 +36,12 @@
fonctionnalités : fonctionnalités :
s'enregistrer avec le serveur OK
rechercher un pair
generer une clé publique OK
rechercher les fichiers d'un pair rechercher les fichiers d'un pair
telechargement des fichiers telechargement des fichiers
choisir un dossier à partager choisir un dossier à partager
choisir le nombre de canaux se deconnecter du réseau
handshake server DOING 2 channels -> un pour envoyer et un pour recevoir OK
se deconnecter du réseau DOING
## autre
socket ipv6
# FAIT
- choisir un pseudo OK
- get rsquest to the uri /peers/ OK
- generation of the cryptographic key OK
- put request to the uri (check if the peer is already connected) OK
- get request to the uri /peers/key to get the public key of a peer OK
- get request to the uri /peers/key/addresses OK
- udp handshakes OK
- handshake structure OK
- s'enregistrer avec le serveur OK
- generer une clé publique OK
- verifier signature OK
- 2 channels -> un pour envoyer et un pour recevoir OK