From 003d55bd75ecd0eb5c71d4c883ad3fb096f1ef75 Mon Sep 17 00:00:00 2001 From: Tiago Batista Cardoso Date: Sun, 11 Jan 2026 22:00:10 +0100 Subject: [PATCH 1/5] thing --- client-gui/src/gui_app.rs | 22 +-- client-network/src/lib.rs | 6 +- client-network/src/messages_structure.rs | 173 +++++++++++++++++++++++ todo.md | 43 ++++-- 4 files changed, 221 insertions(+), 23 deletions(-) diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index 03c508f..4060d49 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -27,7 +27,7 @@ pub struct P2PClientApp { // GUI State status_message: String, - known_peers: Vec, + known_peers: Vec<(String, bool)>, connect_address_input: String, connected_address: String, connect_name_input: String, @@ -62,7 +62,7 @@ impl P2PClientApp { network_cmd_tx: cmd_tx, network_event_rx: event_rx, status_message: "Client Initialized. Awaiting network status...".to_string(), - known_peers: vec!["bob".to_string()], + known_peers: vec![("bob".to_string(), true)], connect_address_input: "https://jch.irif.fr:8443".to_string(), connected_address: "".to_string(), loaded_fs, @@ -111,8 +111,8 @@ impl eframe::App for P2PClientApp { todo!(); self.status_message = format!("✅ Peer connected: {}", addr); - if !self.known_peers.contains(&addr) { - self.known_peers.push(addr); + if !self.known_peers.contains(&(addr, true)) { + self.known_peers.push((addr, true)); } } NetworkEvent::PeerListUpdated(peers) => { @@ -361,18 +361,18 @@ impl eframe::App for P2PClientApp { } else { for peer in &self.known_peers { let is_active = - self.active_peer.as_ref().map_or(false, |id| id == peer); // if peer.id == self.active_peer_id + self.active_peer.as_ref().map_or(false, |id| id == &peer.0); // if peer.id == self.active_peer_id let selectable; - if &self.active_server == peer { + if &self.active_server == &peer.0 { selectable = - ui.selectable_label(is_active, format!("{} 📡 🌀", peer)) + ui.selectable_label(is_active, format!("{} 📡 🌀", peer.0)) } else { - selectable = ui.selectable_label(is_active, format!("{}", peer)); + selectable = ui.selectable_label(is_active, format!("{}", peer.0)); } if selectable.clicked() { // switch to displaying this peer's tree - self.active_peer = Some(peer.clone()); + self.active_peer = Some(peer.0.clone()); // Request root content if not loaded if !self .loaded_fs @@ -394,10 +394,10 @@ impl eframe::App for P2PClientApp { .button("Utiliser le peer en tant que serveur") .clicked() { - self.active_server = peer.to_string(); + self.active_server = peer.0.to_string(); let res = self.network_cmd_tx.send( NetworkCommand::ServerHandshake( - peer.to_string(), + peer.0.to_string(), self.connected_address.clone(), ), ); diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index 44fa3ab..5f56884 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -135,7 +135,7 @@ pub enum NetworkEvent { Disconnected(), Error(String), PeerConnected(String), - PeerListUpdated(Vec), + PeerListUpdated(Vec<(String, bool)>), FileTreeReceived(String, Vec), // peer_id, content DataReceived(String, MerkleNode), FileTreeRootReceived(String, NodeHash), @@ -308,11 +308,11 @@ pub fn start_p2p_executor( match get_peer_list(ip).await { Ok(body) => match String::from_utf8(body.to_vec()) { Ok(peers_list) => { - let mut peers: Vec = Vec::new(); + let mut peers: Vec<(String, bool)> = Vec::new(); let mut current = String::new(); for i in peers_list.chars() { if i == '\n' { - peers.push(current.clone()); + peers.push((current.clone(), false)); current.clear(); } else { current.push(i); diff --git a/client-network/src/messages_structure.rs b/client-network/src/messages_structure.rs index 4da9ffa..2002099 100644 --- a/client-network/src/messages_structure.rs +++ b/client-network/src/messages_structure.rs @@ -67,3 +67,176 @@ pub fn construct_message( } None } + +pub struct UDPMessage { + id: u32, + msg_type: u8, + length: u16, + body: Vec, + signature: Vec, +} + +pub struct HandshakeMessage { + pub id: u32, + msg_type: u8, + length: u16, + extensions: u32, + pub name: Vec, + pub signature: Vec, +} + +pub struct NatTraversal {} + +impl UDPMessage { + pub fn ping(id: u32) -> UDPMessage { + UDPMessage { + id: id, + msg_type: 0, + length: 0, + body: vec![0; 985], + signature: vec![0; 32], + } + } + + pub fn error(id: u32) -> UDPMessage { + UDPMessage { + id: id, + msg_type: 129, + length: 0, + body: vec![0; 985], + signature: vec![0; 32], + } + } + + pub fn parse(received_message: Vec) -> UDPMessage { + let id_bytes: [u8; 4] = received_message[0..4] + .try_into() + .expect("Taille incorrecte"); + let length_bytes: [u8; 2] = received_message[5..7] + .try_into() + .expect("Taille incorrecte"); + let msg_length = u16::from_be_bytes(length_bytes); + let name_bytes = &received_message[7..msg_length as usize + 8]; + let signature_bytes = + &received_message[msg_length as usize + 8..msg_length as usize + 9 + 32]; + UDPMessage { + id: u32::from_be_bytes(id_bytes), + msg_type: received_message[4], + length: u16::from_be_bytes(length_bytes), + body: name_bytes.to_vec(), + signature: signature_bytes.to_vec(), + } + } + + pub fn display(&self) { + println!("ID: {:?}", self.id); + println!("Message Type: {}", self.msg_type); + println!("Length: {:?}", self.length); + let good_length = usize::min(self.length as usize, 985); + println!("name: {:?}", &self.body[..good_length]); + println!("Signature: {:?}", self.signature); + } +} + +impl HandshakeMessage { + pub fn display(&self) { + println!("ID: {:?}", self.id); + println!("Message Type: {}", self.msg_type); + println!("Length: {:?}", self.length); + println!("extensions: {:?}", self.extensions); + println!("name: {:?}", &self.name[..(self.length - 4) as usize]); + println!("Signature: {:?}", self.signature); + } + pub fn hello(id: u32, length: u16, username: String) -> HandshakeMessage { + let name_vec = username.trim_end_matches(char::from(0)).as_bytes().to_vec(); + HandshakeMessage { + id: id, + msg_type: 1, + length: length, + extensions: 0, + name: name_vec, + signature: vec![0; 64], + } + } + + pub fn helloReply(id: u32, length: u16, username: String) -> HandshakeMessage { + let name_vec = username.trim_end_matches(char::from(0)).as_bytes().to_vec(); + HandshakeMessage { + id: id, + msg_type: 130, + length: length, + extensions: 0, + name: name_vec, + signature: vec![0; 64], + } + } + + pub fn serialize(&self) -> Vec { + let mut out = Vec::with_capacity(4 + 1 + 2 + 4 + self.name.len() + self.signature.len()); + + // id: u32 little-endian + out.extend_from_slice(&self.id.to_be_bytes()); + + // msg_type: u8 + out.push(self.msg_type); + + out.extend_from_slice(&self.length.to_be_bytes()); + + out.extend_from_slice(&self.extensions.to_be_bytes()); + + out.extend_from_slice(&self.name); + + out.extend_from_slice(&self.signature); + + out + } + + pub fn parse(received_message: Vec) -> HandshakeMessage { + let id_bytes: [u8; 4] = received_message[0..4] + .try_into() + .expect("Taille incorrecte"); + let length_bytes: [u8; 2] = received_message[5..7] + .try_into() + .expect("Taille incorrecte"); + let msg_length = u16::from_be_bytes(length_bytes); + let extensions_bytes: [u8; 4] = received_message[7..11] + .try_into() + .expect("Taille incorrecte"); + let name_bytes = &received_message[11..(11 + msg_length - 4) as usize]; + let signature_bytes = + &received_message[(11 + msg_length - 4) as usize..(11 + msg_length - 4 + 64) as usize]; + HandshakeMessage { + id: u32::from_be_bytes(id_bytes), + msg_type: received_message[4], + length: u16::from_be_bytes(length_bytes), + extensions: u32::from_be_bytes(extensions_bytes), + name: name_bytes.to_vec(), + signature: signature_bytes.to_vec(), + } + } +} + +#[cfg(test)] +mod tests { + // Note this useful idiom: importing names from outer (for mod tests) scope. + use super::*; + + /// creates an handshake message + #[tokio::test] + async fn creating_handshake_msg() { + let username = String::from("charlie_kirk"); + let handshake = HandshakeMessage::hello(0, 12, username); + handshake.display(); + } + + /// parses an handshake message + #[tokio::test] + async fn parse_handshakemessage() { + let username = String::from("charlie_kirk"); + let handshake = HandshakeMessage::hello(0, 12, username); + let ser = handshake.serialize(); + let parsed = HandshakeMessage::parse(ser); + handshake.display(); + parsed.display(); + } +} diff --git a/todo.md b/todo.md index 3931686..d5d7193 100644 --- a/todo.md +++ b/todo.md @@ -1,13 +1,32 @@ -# Todo : - +# Todo ## peer discovery ## handshake + +# Todo + +## peer discovery + +- get rsquest to the uri /peers/ + +## registration with the server + +- generation of the cryptographic key OK +- put request to the uri (check if the peer is already connected) OK +- udp handshakes 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 + +## handshake + +- handshake structure OK + - 5min timeout after handshake - matain connection every 4 min ## data transfer + - request structure - root/root reply structure - datum/nodatum and datum structures @@ -15,7 +34,16 @@ - setting in gui to act as a relay - chunk, directory, big, bigdirectory structures -## fonctionnalités application : +## fonctionnalités application + +## nat traversal + +- make hello and helloreply messages set the first extension bit to announce that peer is available for nat traversal +- implement actual nat traversal requests +- implement nat traversal : + - if hello/helloreply doesnt work with a peer, find a peer that supports nat traversal (server in priority) then begin protocol + +fonctionnalités : rechercher les fichiers d'un pair telechargement des fichiers @@ -25,16 +53,14 @@ choisir le nombre de canaux handshake server DOING se deconnecter du réseau DOING - -## autre : +## autre socket ipv6 - -# FAIT : +# FAIT - choisir un pseudo OK -- get rsquest to the uri /peers/ 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 @@ -45,4 +71,3 @@ socket ipv6 - generer une clé publique OK - verifier signature OK - 2 channels -> un pour envoyer et un pour recevoir OK - -- 2.39.5 From 60145f279a8aab9d43ae6d759bbc5be8e7d6a23e Mon Sep 17 00:00:00 2001 From: Tiago Batista Cardoso Date: Thu, 15 Jan 2026 22:01:48 +0100 Subject: [PATCH 2/5] 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)); } } -- 2.39.5 From be7430fdc6f36059e2e26e3bd62c1b1d4a280497 Mon Sep 17 00:00:00 2001 From: Tiago Batista Cardoso Date: Thu, 15 Jan 2026 22:08:11 +0100 Subject: [PATCH 3/5] peer address in nat traversal --- client-network/src/lib.rs | 41 +++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index 5d2e6f3..0c3a1c1 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -360,24 +360,31 @@ pub fn start_p2p_executor( 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(), - ); + Some(server_addr) => match peer_addr_query.await { + Some(peer_addr) => { + let natreq = construct_message( + NATTRAVERSALREQUEST, + peer_addr.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(), - ); - } + 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(); -- 2.39.5 From 29c67e340c03f4891cc660031e15ec6192872864 Mon Sep 17 00:00:00 2001 From: Tiago Batista Cardoso Date: Thu, 15 Jan 2026 22:37:24 +0100 Subject: [PATCH 4/5] update --- client-network/src/lib.rs | 32 +++++++++++++++++++++--- client-network/src/messages_structure.rs | 4 +-- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index 0c3a1c1..e06965f 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -19,7 +19,10 @@ use crate::{ registration::{parse_addresses, perform_handshake, register_with_the_server}, server_communication::{generate_id, get_peer_list}, }; -use std::{io::Error, net::UdpSocket}; +use std::{ + io::Error, + net::{Ipv4Addr, UdpSocket}, +}; use std::{ net::SocketAddr, sync::{Arc, Mutex}, @@ -35,6 +38,7 @@ pub struct P2PSharedData { } use bytes::Bytes; +use p256::pkcs8::der::pem::Base64Encoder; impl P2PSharedData { pub fn new( @@ -362,10 +366,16 @@ pub fn start_p2p_executor( match server_addr_query.await { Some(server_addr) => match peer_addr_query.await { Some(peer_addr) => { + let payload = + parse_pack(peer_addr.clone().to_string().as_str()) + .expect("couldnt create payload"); + + print!("{:?}", payload.clone()); + let natreq = construct_message( NATTRAVERSALREQUEST, - peer_addr.to_string().into_bytes(), - 8, + payload.clone().to_vec(), + generate_id(), &sd.cryptopair(), ); @@ -407,6 +417,22 @@ pub fn start_p2p_executor( }) } +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 /// diff --git a/client-network/src/messages_structure.rs b/client-network/src/messages_structure.rs index ab5f6cc..f913fe4 100644 --- a/client-network/src/messages_structure.rs +++ b/client-network/src/messages_structure.rs @@ -55,8 +55,8 @@ pub fn construct_message( ROOTREPLY | NODATUM | DATUM | NATTRAVERSALREQUEST => { message.extend_from_slice(&payload.len().to_be_bytes()); message.extend_from_slice(&payload); - let signature = sign_message(crypto_pair, &message); - message.extend_from_slice(&signature); + //let signature = sign_message(crypto_pair, &message); + //message.extend_from_slice(&signature); return Some(message); } -- 2.39.5 From 14fa256f9ca5f4acbb140c91aaeb120647b701f3 Mon Sep 17 00:00:00 2001 From: TIBERGHIEN corentin Date: Fri, 16 Jan 2026 01:12:52 +0100 Subject: [PATCH 5/5] wip nattraversal --- client-network/src/lib.rs | 17 ++++++++++++----- client-network/src/message_handling.rs | 3 +-- client-network/src/messages_structure.rs | 8 +++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index e06965f..6b7f9d2 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -21,7 +21,7 @@ use crate::{ }; use std::{ io::Error, - net::{Ipv4Addr, UdpSocket}, + net::{IpAddr, Ipv4Addr, UdpSocket}, }; use std::{ net::SocketAddr, @@ -366,15 +366,13 @@ pub fn start_p2p_executor( match server_addr_query.await { Some(server_addr) => match peer_addr_query.await { Some(peer_addr) => { - let payload = - parse_pack(peer_addr.clone().to_string().as_str()) - .expect("couldnt create payload"); + let payload = socket_addr_to_vec(server_addr); print!("{:?}", payload.clone()); let natreq = construct_message( NATTRAVERSALREQUEST, - payload.clone().to_vec(), + server_addr.to_string().into_bytes(), generate_id(), &sd.cryptopair(), ); @@ -417,6 +415,15 @@ pub fn start_p2p_executor( }) } +fn socket_addr_to_vec(addr: SocketAddr) -> Vec { + 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, ':'); diff --git a/client-network/src/message_handling.rs b/client-network/src/message_handling.rs index 00f338d..dcbea93 100644 --- a/client-network/src/message_handling.rs +++ b/client-network/src/message_handling.rs @@ -290,8 +290,7 @@ pub fn parse_message( 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 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); diff --git a/client-network/src/messages_structure.rs b/client-network/src/messages_structure.rs index f913fe4..115b19c 100644 --- a/client-network/src/messages_structure.rs +++ b/client-network/src/messages_structure.rs @@ -53,10 +53,12 @@ pub fn construct_message( return Some(message); } ROOTREPLY | NODATUM | DATUM | NATTRAVERSALREQUEST => { - message.extend_from_slice(&payload.len().to_be_bytes()); + println!("payload:{:?}", &payload); + message.extend_from_slice(&(payload.len() as u16).to_be_bytes()); message.extend_from_slice(&payload); - //let signature = sign_message(crypto_pair, &message); - //message.extend_from_slice(&signature); + println!("payload:{:?}", &message); + let signature = sign_message(crypto_pair, &message); + message.extend_from_slice(&signature); return Some(message); } -- 2.39.5