From f51b8e999c7e1244fa205b374a6605a4f13cc8fd Mon Sep 17 00:00:00 2001 From: wikano Date: Mon, 5 Jan 2026 02:48:58 +0100 Subject: [PATCH] server handshake handling --- client-gui/src/gui_app.rs | 18 ++++++++-- client-network/src/lib.rs | 33 +++++++++++++++--- client-network/src/message_handling.rs | 10 +++++- client-network/src/messages_channels.rs | 45 ++++++++++++++++++++++--- client-network/src/registration.rs | 2 +- 5 files changed, 96 insertions(+), 12 deletions(-) diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index b5fbc0e..020b250 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -7,7 +7,7 @@ use egui::{ Align, Align2, Button, CentralPanel, CollapsingHeader, Context, Id, LayerId, Layout, Order, Popup, ScrollArea, SidePanel, TextStyle, TopBottomPanel, Ui, ViewportCommand, }; -use std::collections::HashMap; +use std::{collections::HashMap, fmt::format}; enum ServerStatus { Loading, @@ -43,6 +43,8 @@ pub struct P2PClientApp { show_network_popup: bool, // gérer selon besoin error_message: Option, // Some(message) -> afficher, None -> rien + // + active_server: String, } impl P2PClientApp { @@ -69,6 +71,7 @@ impl P2PClientApp { show_network_popup: false, error_message: None, connect_name_input: "bob".to_string(), + active_server: "".to_string(), } } pub fn show_error(&mut self, msg: impl Into) { @@ -149,6 +152,7 @@ impl eframe::App for P2PClientApp { self.server_status = ServerStatus::ConnectedHandshake; } NetworkEvent::Disconnected() => { + self.active_server = "".to_string(); self.connected_address = "".to_string(); self.known_peers.clear(); self.server_status = ServerStatus::NotConnected; @@ -157,6 +161,14 @@ impl eframe::App for P2PClientApp { self.show_error(err); } NetworkEvent::DataReceived(_, merkle_node) => todo!(), + NetworkEvent::HandshakeFailed() => {} + NetworkEvent::ServerHandshakeFailed(err) => { + self.active_server = "".to_string(); + self.server_status = ServerStatus::NotConnected; + let err_msg = format!("Failed to connect to the server: {}", err); + self.show_error(err_msg); + let res = self.network_cmd_tx.send(NetworkCommand::ResetServerPeer()); + } } } @@ -289,7 +301,8 @@ impl eframe::App for P2PClientApp { ui.label("No connection.."); } ServerStatus::ConnectedHandshake => { - ui.label("📡"); + let str = format!("📡 {}", self.active_server); + ui.label(str); } } ui.add_space(ui.available_width() - 30.0); @@ -355,6 +368,7 @@ impl eframe::App for P2PClientApp { .button("Utiliser le peer en tant que serveur") .clicked() { + self.active_server = peer.to_string(); let res = self.network_cmd_tx.send( NetworkCommand::ServerHandshake( peer.to_string(), diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index bc99605..e5ef93e 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -30,10 +30,14 @@ pub struct P2PSharedData { shared_cryptopair: Arc, shared_messageslist: Arc>>, shared_senders: Arc, + server_name: Arc>, } impl P2PSharedData { - pub fn new(username: String) -> Result { + pub fn new( + username: String, + cmd_tx: crossbeam_channel::Sender, + ) -> Result { let messages_list = HashMap::::new(); let username = String::from(username); let crypto_pair = CryptographicSignature::new(username); @@ -42,13 +46,15 @@ impl P2PSharedData { let shared_cryptopair = Arc::new(crypto_pair); let shared_messageslist = Arc::new(Mutex::new(messages_list)); - let senders = MultipleSenders::new(1, &shared_socket); + let senders = MultipleSenders::new(1, &shared_socket, cmd_tx); let shared_senders = Arc::new(senders); + let server_name = Arc::new(Mutex::new("".to_string())); Ok(P2PSharedData { shared_socket: shared_socket, shared_cryptopair: shared_cryptopair, shared_messageslist: shared_messageslist, shared_senders: shared_senders, + server_name: server_name, }) } pub fn socket(&self) -> Arc { @@ -61,6 +67,14 @@ impl P2PSharedData { pub fn messages_list(&self) -> Arc>> { self.shared_messageslist.clone() } + pub fn servername(&self) -> String { + let guard = self.server_name.lock().unwrap(); + guard.to_string() + } + pub fn set_servername(&self, new: String) { + let mut guard = self.server_name.lock().unwrap(); + *guard = new + } pub fn senders(&self) -> Arc { self.shared_senders.clone() } @@ -98,6 +112,7 @@ pub enum NetworkCommand { RequestDirectoryContent(String, String), RequestChunk(String, String), Disconnect(), + ResetServerPeer(), // ... } @@ -112,6 +127,8 @@ pub enum NetworkEvent { FileTreeReceived(String, Vec), // peer_id, content DataReceived(String, MerkleNode), FileTreeRootReceived(String, String), + HandshakeFailed(), + ServerHandshakeFailed(String), // ... } @@ -155,7 +172,7 @@ pub fn start_p2p_executor( NetworkCommand::ServerHandshake(username, ip) => { if let Some(sd) = shared_data.as_ref() { println!("username:{}, ip:{}", username, ip); - let server_addr_query = get_socket_address(username, ip); + let server_addr_query = get_socket_address(username.clone(), ip); match server_addr_query.await { Ok(sockaddr_bytes) => { @@ -163,6 +180,7 @@ pub fn start_p2p_executor( Ok(s) => { let addresses = parse_addresses(&s); if let Some(first) = addresses.first() { + sd.set_servername(username); // first: &SocketAddr start_receving_thread( sd, @@ -230,7 +248,7 @@ pub fn start_p2p_executor( // Actual server connection - shared_data = match P2PSharedData::new(name.clone()) { + shared_data = match P2PSharedData::new(name.clone(), event_tx.clone()) { Ok(sd) => Some(sd), Err(e) => { let mut err_msg = String::from("failed to initialize socket: "); @@ -311,6 +329,13 @@ pub fn start_p2p_executor( println!("no p2p data"); } } + NetworkCommand::ResetServerPeer() => { + if let Some(sd) = shared_data.as_ref() { + sd.set_servername("".to_string()); + } else { + println!("no p2p data"); + } + } } } diff --git a/client-network/src/message_handling.rs b/client-network/src/message_handling.rs index 79fef9b..dd651f9 100644 --- a/client-network/src/message_handling.rs +++ b/client-network/src/message_handling.rs @@ -1,4 +1,5 @@ use crate::{ + NetworkEvent, cryptographic_signature::{ CryptographicSignature, get_peer_key, sign_message, verify_signature, }, @@ -45,6 +46,7 @@ pub fn handle_recevied_message( crypto_pair: &CryptographicSignature, socket_addr: &SocketAddr, senders: &MultipleSenders, + server_name: &String, ) { if recevied_message.len() < 4 { return; @@ -73,6 +75,7 @@ pub fn handle_recevied_message( // Handle handshake if message_type == 1 { + let mut resp_to_serv = false; println!("verify the signature"); let parsed_received_message = HandshakeMessage::parse(recevied_message.to_vec()); let received_name = String::from_utf8(parsed_received_message.name).expect("error"); @@ -81,12 +84,17 @@ pub fn handle_recevied_message( .block_on(get_peer_key(&received_name)) .expect("failed to retrieve public key"); + if received_name == server_name.to_string() { + resp_to_serv = true; + } + if !verify_signature(peer_pubkey, recevied_message) { println!( "incorrect signature from given peer: {}, ignoring message {}", &received_name, id ); } else { + // verify if this is a server handshake request let username_size = crypto_pair.username.len(); let hello_handshake = HandshakeMessage::helloReply( id as u32, @@ -96,7 +104,7 @@ pub fn handle_recevied_message( //HandshakeMessage::display(&hello_handshake); let hello_handshake_serialized = hello_handshake.serialize(); let message_signed = sign_message(crypto_pair, &hello_handshake_serialized); - senders.send_via(0, message_signed, socket_addr.to_string()); + senders.send_via(0, message_signed, socket_addr.to_string(), resp_to_serv); let mut list = messages_list.lock().expect("Failed to lock messages_list"); match list.get(&id) { Some(_) => { diff --git a/client-network/src/messages_channels.rs b/client-network/src/messages_channels.rs index 34b2905..13bb67b 100644 --- a/client-network/src/messages_channels.rs +++ b/client-network/src/messages_channels.rs @@ -13,13 +13,17 @@ use std::thread; use std::collections::VecDeque; use std::time::{Duration, Instant}; +use crate::NetworkEvent; + pub struct MultipleSenders { senders: Vec>, + response_channel: crossbeam_channel::Sender, } pub struct Message { payload: Vec, address: String, + is_resp_to_server_handshake: bool, } struct RetryMessage { @@ -68,12 +72,17 @@ impl MultipleSenders { MultipleSenders { senders } }*/ - pub fn new(num_channels: usize, socket: &Arc) -> Self { + pub fn new( + num_channels: usize, + socket: &Arc, + cmd_tx: crossbeam_channel::Sender, + ) -> Self { let mut senders = Vec::new(); for i in 0..num_channels { let (tx, rx) = mpsc::channel::(); let sock_clone = Arc::clone(&socket); + let cmd_tx_clone = cmd_tx.clone(); senders.push(tx); @@ -91,6 +100,10 @@ impl MultipleSenders { let mut item = queue.pop_front().unwrap(); match sock_clone.send_to(&item.msg.payload, &item.msg.address) { Ok(_) => { + if (&item).msg.is_resp_to_server_handshake { + let res = + cmd_tx_clone.send(NetworkEvent::ConnectedHandshake()); + } let message_id: [u8; 4] = item.msg.payload[0..4].try_into().expect("size error"); let id = i32::from_be_bytes(message_id); @@ -103,10 +116,14 @@ impl MultipleSenders { Err(e) => { item.attempts += 1; if item.attempts >= max_attempts { - eprintln!( + let str = format!( "Abandon du message après {} tentatives sur canal {}: {}, address: {}", item.attempts, i, e, item.msg.address ); + if (&item).msg.is_resp_to_server_handshake { + let res = cmd_tx_clone + .send(NetworkEvent::ServerHandshakeFailed(str)); + } } else { // Backoff exponentiel simple let backoff = Duration::from_millis( @@ -131,6 +148,10 @@ impl MultipleSenders { // On tente d'envoyer immédiatement match sock_clone.send_to(&msg.payload, &msg.address) { Ok(_) => { + if msg.is_resp_to_server_handshake { + let res = + cmd_tx_clone.send(NetworkEvent::ConnectedHandshake()); + } let message_id: [u8; 4] = msg.payload[0..4].try_into().expect("size error"); let id = i32::from_be_bytes(message_id); @@ -171,15 +192,29 @@ impl MultipleSenders { }); } - MultipleSenders { senders } + MultipleSenders { + senders, + response_channel: cmd_tx.clone(), + } } /// Envoie un message via un canal spécifique (round-robin ou index précis) - pub fn send_via(&self, channel_idx: usize, data: Vec, remote_addr: String) { + pub fn send_via( + &self, + channel_idx: usize, + data: Vec, + remote_addr: String, + is_resp_to_server_handshake: bool, + ) { + println!( + "is_resp_to_server_handshake {}", + is_resp_to_server_handshake + ); if let Some(sender) = self.senders.get(channel_idx) { let _ = sender.send(Message { payload: data, address: remote_addr, + is_resp_to_server_handshake, }); } } @@ -223,6 +258,7 @@ pub fn start_receving_thread(shared_data: &P2PSharedData, socket_addr: SocketAdd 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(); thread::spawn(move || { let mut buf = [0u8; 1024]; loop { @@ -237,6 +273,7 @@ pub fn start_receving_thread(shared_data: &P2PSharedData, socket_addr: SocketAdd &cryptopair_clone, &socket_addr, &senders_clone, + &servername_clone, ); } Err(e) => eprintln!("Erreur de réception: {}", e), diff --git a/client-network/src/registration.rs b/client-network/src/registration.rs index d7f411d..52f3198 100644 --- a/client-network/src/registration.rs +++ b/client-network/src/registration.rs @@ -82,7 +82,7 @@ pub fn register_ip_addresses( //HandshakeMessage::display(&hello_handshake); let hello_handshake_serialized = hello_handshake.serialize(); let message_signed = sign_message(crypto_pair, &hello_handshake_serialized); - senders.send_via(0, message_signed, server_uri); + senders.send_via(0, message_signed, server_uri, false); let mut list = messages_list.lock().expect("Failed to lock messages_list"); match list.get(&id) { Some(_) => {