From f735ab34fcb2ff57e24656e4f5e000579957cf66 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 | 27 +++- client-network/src/lib.rs | 156 ++++++++++++++--------- client-network/src/message_handling.rs | 52 +++++++- client-network/src/messages_structure.rs | 29 ++--- client-network/src/registration.rs | 23 +--- 5 files changed, 182 insertions(+), 105 deletions(-) diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index 9b5fdc2..29fe612 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -360,11 +360,9 @@ impl eframe::App for P2PClientApp { .loaded_fs .contains_key(self.active_peer.as_ref().unwrap()) { - todo!(); - // let _ = self.network_cmd_tx.send(NetworkCommand::RequestDirectoryContent( - // peer.clone(), - // peer.clone(), - // )); + let _ = self + .network_cmd_tx + .send(NetworkCommand::ConnectPeer(peer.clone())); } } selectable.context_menu(|ui| { @@ -386,10 +384,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 3e41ef7..8d8ab26 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -12,20 +12,15 @@ use crate::{ cryptographic_signature::CryptographicSignature, message_handling::EventType, messages_channels::{MultipleSenders, start_receving_thread}, - registration::{ - get_socket_address, parse_addresses, register_ip_addresses, register_with_the_server, - }, + messages_structure::{NATTRAVERSALREQUEST, NATTRAVERSALREQUEST2, construct_message}, + registration::{parse_addresses, register_ip_addresses, 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, @@ -35,6 +30,8 @@ pub struct P2PSharedData { server_name: Arc>, } +use bytes::Bytes; + impl P2PSharedData { pub fn new( username: String, @@ -108,9 +105,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(), @@ -177,62 +175,33 @@ pub fn start_p2p_executor( let server_addr_query = get_socket_address(username.clone(), ip); 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 - start_receving_thread( - sd, - *first, // copie le SocketAddr (implémente Copy pour SocketAddr) - event_tx.clone(), // - ); - 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)); - } - } + Some(server_address) => { + sd.set_servername(username); + // first: &SocketAddr + start_receving_thread( + sd, + server_address, // copie le SocketAddr (implémente Copy pour SocketAddr) + event_tx.clone(), // + ); + register_ip_addresses( + sd.cryptopair_ref(), + server_address.to_string(), + sd.senders_ref(), + sd.messages_list_ref(), + generate_id(), + ); } - Err(e) => { + None => { let err_msg = - format!("failed to retreive socket address: {}", e) - .to_string(); + format!("failed to retreive socket address").to_string(); let res = event_tx.send(NetworkEvent::Error(err_msg)); } } } } - 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(); @@ -320,7 +289,7 @@ pub fn start_p2p_executor( NetworkCommand::RegisterAsPeer(_) => { println!("[Network] RegisterAsPeer() called"); } - NetworkCommand::Ping() => { + NetworkCommand::Ping(String) => { println!("[Network] Ping() called"); } NetworkCommand::Disconnect() => { @@ -339,6 +308,40 @@ 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, + ); + } + None => { + let err_msg = + format!("failed to retreive socket address").to_string(); + let res = event_tx.send(NetworkEvent::Error(err_msg)); + } + } + } + } } } @@ -352,3 +355,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 9b427f5..a84f35e 100644 --- a/client-network/src/message_handling.rs +++ b/client-network/src/message_handling.rs @@ -70,7 +70,14 @@ pub fn handle_recevied_message( } } - let resp = parse_message(recevied_message.to_vec(), id, crypto_pair, cmd_tx, ip); + let resp = parse_message( + recevied_message.to_vec(), + id, + crypto_pair, + cmd_tx, + ip, + senders, + ); match resp { None => {} @@ -152,6 +159,7 @@ pub fn parse_message( crypto_pair: &CryptographicSignature, cmd_tx: crossbeam_channel::Sender, ip: SocketAddr, + senders: &MultipleSenders, ) -> Option> { let cmd_tx_clone = cmd_tx.clone(); @@ -215,6 +223,48 @@ 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, + ); + } + + 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, + ); + } // // ERROR // diff --git a/client-network/src/messages_structure.rs b/client-network/src/messages_structure.rs index 215ea7b..5788597 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; -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 5ddcdf5..a83338a 100644 --- a/client-network/src/registration.rs +++ b/client-network/src/registration.rs @@ -1,9 +1,8 @@ use bytes::Bytes; -use getrandom::Error; use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message}; use crate::message_handling::EventType; -use crate::messages_channels::{Message, MultipleSenders}; +use crate::messages_channels::MultipleSenders; use crate::messages_structure::construct_message; use std::collections::HashMap; use std::net::SocketAddr; @@ -29,26 +28,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() {