From c852c5bb4a72f60615d531d45bab3f3859e81dcc Mon Sep 17 00:00:00 2001 From: TIBERGHIEN corentin Date: Tue, 13 Jan 2026 17:13:35 +0100 Subject: [PATCH] root request --- client-gui/src/gui_app.rs | 24 ++++++- client-network/src/lib.rs | 65 ++++++++++++++++--- client-network/src/message_handling.rs | 84 ++++++++++++++++++------- client-network/src/messages_channels.rs | 79 ++++++++++++----------- client-network/src/peers_refresh.rs | 31 +++++++-- client-network/src/registration.rs | 5 +- 6 files changed, 210 insertions(+), 78 deletions(-) diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index 39bb3a5..03c508f 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -1,5 +1,5 @@ use client_network::{ - MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string, + ChunkNode, MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string, node_hash_to_hex_string, }; use crossbeam_channel::{Receiver, Sender}; @@ -129,11 +129,28 @@ impl eframe::App for P2PClientApp { NetworkEvent::FileTreeRootReceived(peer_id, root_hash) => { // todo!(); - self.status_message = format!( + /*self.status_message = format!( "🔄 Received Merkle Root from {}: {}", peer_id, &root_hash[..8] - ); + );*/ + + if let Ok(chunknode) = ChunkNode::new(Vec::new()) { + let mut data_map: HashMap = HashMap::new(); + data_map.insert(root_hash, MerkleNode::Chunk(chunknode)); + let tree = MerkleTree { + 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()); @@ -365,6 +382,7 @@ impl eframe::App for P2PClientApp { let _ = self.network_cmd_tx.send(NetworkCommand::Discover( peer.clone(), "root".to_string(), + self.connected_address.clone(), )); } } diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index c0dd386..44fa3ab 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -12,7 +12,7 @@ use crate::{ cryptographic_signature::CryptographicSignature, message_handling::EventType, messages_channels::{MultipleSenders, start_receving_thread}, - messages_structure::construct_message, + messages_structure::{ROOTREQUEST, construct_message}, peers_refresh::HandshakeHistory, registration::{ get_socket_address, parse_addresses, perform_handshake, register_with_the_server, @@ -123,7 +123,7 @@ pub enum NetworkCommand { RequestChunk(String, String), Disconnect(), ResetServerPeer(), - Discover(String, String), + Discover(String, String, String), GetChildren(String, String), // ... } @@ -138,7 +138,7 @@ pub enum NetworkEvent { PeerListUpdated(Vec), FileTreeReceived(String, Vec), // peer_id, content DataReceived(String, MerkleNode), - FileTreeRootReceived(String, String), + FileTreeRootReceived(String, NodeHash), HandshakeFailed(), ServerHandshakeFailed(String), // ... @@ -173,6 +173,8 @@ pub fn start_p2p_executor( // Use tokio to spawn the asynchronous networking logic tokio::task::spawn(async move { // P2P/Networking Setup goes here + let handshake_history = Arc::new(Mutex::new(HandshakeHistory::new())); + let handshake_clone = handshake_history.clone(); println!("Network executor started."); @@ -182,12 +184,13 @@ pub fn start_p2p_executor( if let Ok(cmd) = cmd_rx.try_recv() { match cmd { NetworkCommand::ServerHandshake(username, ip) => { + println!("server handshake called"); if let Some(sd) = shared_data.as_ref() { - start_receving_thread( - sd, - event_tx.clone(), // - ); - perform_handshake(&sd, username, ip, event_tx.clone()); + start_receving_thread(sd, event_tx.clone(), &handshake_clone); + let res = + perform_handshake(&sd, username, ip, event_tx.clone(), true).await; + } else { + println!("no shared data"); } } NetworkCommand::ConnectPeer(addr) => { @@ -200,8 +203,52 @@ pub fn start_p2p_executor( NetworkCommand::RequestFileTree(_) => { println!("[Network] RequestFileTree() called"); } - NetworkCommand::Discover(username, hash) => { + 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 diff --git a/client-network/src/message_handling.rs b/client-network/src/message_handling.rs index c5bed0a..c4793d1 100644 --- a/client-network/src/message_handling.rs +++ b/client-network/src/message_handling.rs @@ -1,5 +1,5 @@ use crate::{ - NetworkEvent, + NetworkEvent, NodeHash, cryptographic_signature::{ CryptographicSignature, get_peer_key, sign_message, verify_signature, }, @@ -47,7 +47,7 @@ pub fn handle_recevied_message( server_name: &String, cmd_tx: crossbeam_channel::Sender, ip: SocketAddr, - handshake_history: HandshakeHistory, + handhsake_history: &Arc>, ) { if recevied_message.len() < 4 { return; @@ -78,7 +78,7 @@ pub fn handle_recevied_message( cmd_tx, ip, messages_list, - handshake_history, + handhsake_history, ); match resp { @@ -168,8 +168,9 @@ pub fn parse_message( cmd_tx: crossbeam_channel::Sender, ip: SocketAddr, messages_list: &Arc>>, - handhsake_history: HandshakeHistory, + handhsake_history_mutex: &Arc>, ) -> Option> { + 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] @@ -185,20 +186,27 @@ pub fn parse_message( let msg_length = u16::from_be_bytes(length_bytes) as usize; // verify signature match msgtype { - HELLO | HELLOREPLY | ROOTREPLY | NODATUM | NATTRAVERSALREQUEST | NATTRAVERSALREQUEST2 => { + 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) { - Some(peerinfo) => peerinfo.pubkey, - _ => tokio::runtime::Runtime::new() - .unwrap() - .block_on(get_peer_key(&username)) - .expect("failed to retrieve public key"), - }; + 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() @@ -217,6 +225,22 @@ pub fn parse_message( } } } + 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"); + } + } + } + _ => {} } @@ -268,8 +292,18 @@ pub fn parse_message( // // ajoute a la liste des peers handshake HELLOREPLY => { - // ajoute a la liste des peers handshake - handhsake_history.add_new_handshake(hash, username, ip); + // 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); @@ -300,15 +334,21 @@ pub fn parse_message( // ROOTREPLY => { // recuperer le pseudo du peers ayant repondu - - // envoyer le hash a la gui - let received_hash = String::from_utf8(received_message[LENGTH..(32 + LENGTH)].to_vec()); - match received_hash { - Ok(hash) => { - cmd_tx_clone.send(NetworkEvent::FileTreeRootReceived()); + 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") } - Err(e) => { - println!("{}", e); + None => { + eprintln!("no peers found"); } } } diff --git a/client-network/src/messages_channels.rs b/client-network/src/messages_channels.rs index b02f00f..83c3cee 100644 --- a/client-network/src/messages_channels.rs +++ b/client-network/src/messages_channels.rs @@ -219,8 +219,11 @@ impl MultipleSenders { }; if let Some(sender) = self.senders.get(channel_idx) { let _ = sender.send(msg_to_send); - let mut guard = messages_list.lock().expect("Échec du verrouillage"); - let id = i32::from_be_bytes(data[..4].try_into().unwrap()); + } + if !is_resp_to_server_handshake { + let mut guard = messages_list.lock().unwrap(); + 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); } } @@ -257,39 +260,41 @@ impl MultipleSenders { } }); }*/ - - pub fn start_receving_thread( - shared_data: &P2PSharedData, - cmd_tx: crossbeam_channel::Sender, - ) { - let sock_clone = shared_data.socket(); - let cryptopair_clone = shared_data.cryptopair(); - let senders_clone = shared_data.senders(); - let messages_clone = shared_data.messages_list(); - let servername_clone = shared_data.servername(); - let handshake_history = HandshakeHistory::new(); - thread::spawn(move || { - let mut buf = [0u8; 1024]; - loop { - match sock_clone.recv_from(&mut buf) { - Ok((amt, src)) => { - let received_data = buf[..amt].to_vec(); - - println!("Reçu {} octets de {}: {:?}", amt, src, received_data); - handle_recevied_message( - &messages_clone, - &received_data, - &cryptopair_clone, - &senders_clone, - &servername_clone, - cmd_tx.clone(), - src, - handshake_history, - ); - } - Err(e) => eprintln!("Erreur de réception: {}", e), - } - } - }); - } +} + +pub fn start_receving_thread( + shared_data: &P2PSharedData, + cmd_tx: crossbeam_channel::Sender, + handshake_history: &Arc>, +) { + let sock_clone = shared_data.socket(); + let cryptopair_clone = shared_data.cryptopair(); + let senders_clone = shared_data.senders(); + let messages_clone = shared_data.messages_list(); + let servername_clone = shared_data.servername(); + + let handshake_clone = handshake_history.clone(); + thread::spawn(move || { + let mut buf = [0u8; 1024]; + loop { + match sock_clone.recv_from(&mut buf) { + Ok((amt, src)) => { + let received_data = buf[..amt].to_vec(); + + println!("Reçu {} octets de {}: {:?}", amt, src, received_data); + handle_recevied_message( + &messages_clone, + &received_data, + &cryptopair_clone, + &senders_clone, + &servername_clone, + cmd_tx.clone(), + src, + &handshake_clone, + ); + } + Err(e) => eprintln!("Erreur de réception: {}", e), + } + } + }); } diff --git a/client-network/src/peers_refresh.rs b/client-network/src/peers_refresh.rs index cf409eb..ea70c4a 100644 --- a/client-network/src/peers_refresh.rs +++ b/client-network/src/peers_refresh.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, VecDeque}, - net::{AddrParseError, SocketAddr}, + net::{AddrParseError, Ipv4Addr, SocketAddr}, ops::Add, process::Command, sync::{Arc, Mutex}, @@ -21,7 +21,7 @@ use p256::ecdsa::VerifyingKey; #[derive(Debug, Clone)] pub struct PeerInfo { - username: String, + pub username: String, pub pubkey: VerifyingKey, pub ip: SocketAddr, } @@ -82,6 +82,27 @@ impl HandshakeHistory { }); } + 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::() { + 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(), @@ -104,8 +125,8 @@ pub fn perform_discover( ) { // first, sends handshake if hash == "root" { - perform_handshake(sd, username, server_ip, event_tx); - if let Some(data) = construct_message( + perform_handshake(sd, username, server_ip, event_tx, false); + /*if let Some(data) = construct_message( messages_structure::ROOTREQUEST, Vec::new(), generate_id(), @@ -115,7 +136,7 @@ pub fn perform_discover( sd.senders_ref() .send_via(0, data, peerinfo.ip.to_string(), false); } - } + }*/ } else { // envoyer un datum request } diff --git a/client-network/src/registration.rs b/client-network/src/registration.rs index 6b10813..64a1d91 100644 --- a/client-network/src/registration.rs +++ b/client-network/src/registration.rs @@ -75,13 +75,14 @@ pub async fn perform_handshake( username: String, ip: String, event_tx: Sender, + is_server_handshake: bool, ) { + println!("username: {}, ip: {}", username.clone(), ip.clone()); let crypto_pair = sd.cryptopair_ref(); let senders = sd.senders_ref(); let messages_list = sd.messages_list_ref(); let id = generate_id(); let server_addr_query = get_socket_address(username.clone(), ip.clone()); - match server_addr_query.await { Ok(sockaddr_bytes) => { match String::from_utf8(sockaddr_bytes.to_vec()) { @@ -100,7 +101,7 @@ pub async fn perform_handshake( 0, handshake_message, first.to_string(), - false, + is_server_handshake, messages_list, ); }