From 60145f279a8aab9d43ae6d759bbc5be8e7d6a23e Mon Sep 17 00:00:00 2001 From: Tiago Batista Cardoso Date: Thu, 15 Jan 2026 22:01:48 +0100 Subject: [PATCH] implementation --- client-gui/src/gui_app.rs | 21 ++++- client-network/src/lib.rs | 97 ++++++++++++++++++++---- client-network/src/message_handling.rs | 46 +++++++++++ client-network/src/messages_structure.rs | 29 ++++--- client-network/src/registration.rs | 83 +++++--------------- 5 files changed, 181 insertions(+), 95 deletions(-) diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index 4060d49..8f73e6c 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -380,7 +380,7 @@ impl eframe::App for P2PClientApp { { //todo!(); let _ = self.network_cmd_tx.send(NetworkCommand::Discover( - peer.clone(), + peer.0.clone(), "root".to_string(), self.connected_address.clone(), )); @@ -405,10 +405,29 @@ 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() { // action 3 ui.close(); } + // ... autres boutons }); } diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index 5f56884..5d2e6f3 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -12,22 +12,18 @@ use crate::{ cryptographic_signature::CryptographicSignature, message_handling::EventType, messages_channels::{MultipleSenders, start_receving_thread}, - messages_structure::{ROOTREQUEST, construct_message}, - peers_refresh::HandshakeHistory, - registration::{ - get_socket_address, parse_addresses, perform_handshake, register_with_the_server, + messages_structure::{ + NATTRAVERSALREQUEST, NATTRAVERSALREQUEST2, ROOTREQUEST, construct_message, }, + peers_refresh::HandshakeHistory, + registration::{parse_addresses, perform_handshake, register_with_the_server}, server_communication::{generate_id, get_peer_list}, }; +use std::{io::Error, net::UdpSocket}; use std::{ - fmt, + net::SocketAddr, sync::{Arc, Mutex}, }; -use std::{ - io::Error, - net::{SocketAddr, UdpSocket}, - str::FromStr, -}; pub struct P2PSharedData { shared_socket: Arc, @@ -38,6 +34,8 @@ pub struct P2PSharedData { handshake_peers: Arc, } +use bytes::Bytes; + impl P2PSharedData { pub fn new( username: String, @@ -116,9 +114,10 @@ pub enum NetworkCommand { ServerHandshake(String, String), // ServerName FetchPeerList(String), // ServerIP RegisterAsPeer(String), - Ping(), - ConnectPeer(String), // IP:PORT - RequestFileTree(String), // peer_id + Ping(String), + NatTraversal(String, String), + ConnectPeer((String, bool)), // IP:PORT + RequestFileTree(String), // peer_id RequestDirectoryContent(String, String), RequestChunk(String, String), Disconnect(), @@ -193,9 +192,9 @@ pub fn start_p2p_executor( println!("no shared data"); } } - NetworkCommand::ConnectPeer(addr) => { + NetworkCommand::ConnectPeer((username, connected)) => { println!("[Network] ConnectPeer() called"); - println!("[Network] Attempting to connect to: {}", addr); + println!("[Network] Attempting to connect to: {}", username); // Network logic to connect... // If successful, send an event back: // event_tx.send(NetworkEvent::PeerConnected(addr)).unwrap(); @@ -333,7 +332,7 @@ pub fn start_p2p_executor( NetworkCommand::RegisterAsPeer(_) => { println!("[Network] RegisterAsPeer() called"); } - NetworkCommand::Ping() => { + NetworkCommand::Ping(String) => { println!("[Network] Ping() called"); } NetworkCommand::Disconnect() => { @@ -352,6 +351,41 @@ pub fn start_p2p_executor( 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) => { + let natreq = construct_message( + NATTRAVERSALREQUEST, + ip.to_string().into_bytes(), + 8, + &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)); + } + } + } + } } } @@ -365,3 +399,34 @@ pub fn start_p2p_executor( } }) } + +/// +/// 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 { + 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); + if let Some(first) = addresses.first() { + Some(first.clone()) + } else { + None + } + } + Err(_) => None, + } +} diff --git a/client-network/src/message_handling.rs b/client-network/src/message_handling.rs index c4793d1..00f338d 100644 --- a/client-network/src/message_handling.rs +++ b/client-network/src/message_handling.rs @@ -79,6 +79,7 @@ pub fn handle_recevied_message( ip, messages_list, handhsake_history, + senders, ); match resp { @@ -169,6 +170,7 @@ pub fn parse_message( ip: SocketAddr, messages_list: &Arc>>, handhsake_history_mutex: &Arc>, + senders: &MultipleSenders, ) -> Option> { let mut handhsake_history = handhsake_history_mutex.lock().unwrap(); let cmd_tx_clone = cmd_tx.clone(); @@ -258,6 +260,50 @@ pub fn parse_message( // // 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 + EXTENSIONS..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 // diff --git a/client-network/src/messages_structure.rs b/client-network/src/messages_structure.rs index 2002099..ab5f6cc 100644 --- a/client-network/src/messages_structure.rs +++ b/client-network/src/messages_structure.rs @@ -1,7 +1,4 @@ -use crate::{ - cryptographic_signature::{CryptographicSignature, sign_message}, - server_communication::generate_id, -}; +use crate::cryptographic_signature::{CryptographicSignature, sign_message}; const ID: usize = 4; const TYPE: usize = 5; @@ -9,18 +6,18 @@ const LENGTH: usize = 7; const EXTENSIONS: usize = 4; const SIGNATURE: usize = 64; -const PING: u8 = 0; -const OK: u8 = 128; -const ERROR: u8 = 129; -const HELLO: u8 = 1; -const HELLOREPLY: u8 = 130; -pub const ROOTREQUEST: u8 = 2; -const ROOTREPLY: u8 = 131; -const DATUMREQUEST: u8 = 3; -const NODATUM: u8 = 133; -const DATUM: u8 = 132; -const NATTRAVERSALREQUEST: u8 = 4; -const NATTRAVERSALREQUEST2: u8 = 5; +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, diff --git a/client-network/src/registration.rs b/client-network/src/registration.rs index 64a1d91..36a6d6b 100644 --- a/client-network/src/registration.rs +++ b/client-network/src/registration.rs @@ -1,11 +1,11 @@ use bytes::Bytes; -use getrandom::Error; use crate::NetworkEvent; use crate::P2PSharedData; use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message}; +use crate::get_socket_address; use crate::message_handling::EventType; -use crate::messages_channels::{Message, MultipleSenders}; +use crate::messages_channels::MultipleSenders; use crate::messages_structure::construct_message; use crate::server_communication::generate_id; use crossbeam_channel::{Receiver, Sender}; @@ -33,26 +33,6 @@ pub async fn register_with_the_server( 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 { - 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 { let mut addrs = Vec::new(); for line in input.lines() { @@ -84,49 +64,28 @@ pub async fn perform_handshake( 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()) { - Ok(s) => { - let addresses = parse_addresses(&s); - if let Some(first) = addresses.first() { - sd.set_servername(username); - // first: &SocketAddr - let mut payload = Vec::new(); - 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, - first.to_string(), - is_server_handshake, - messages_list, - ); - } - None => {} - } - - //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)); + Some(sockaddr_bytes) => { + sd.set_servername(username); + // first: &SocketAddr + let mut payload = Vec::new(); + 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 => {} } } - Err(e) => { - let err_msg = format!("failed to retreive socket address: {}", e).to_string(); + None => { + let err_msg = format!("failed to retreive socket address:").to_string(); let res = event_tx.send(NetworkEvent::Error(err_msg)); } }