From 1914c68c9faa489879dd1163f40bb2a993f4fc03 Mon Sep 17 00:00:00 2001 From: wikano Date: Fri, 2 Jan 2026 22:27:26 +0100 Subject: [PATCH] registration put --- client-gui/src/gui_app.rs | 119 +++++++++++++++++------ client-network/src/lib.rs | 145 +++++++++++++++++------------ client-network/src/registration.rs | 11 +-- 3 files changed, 181 insertions(+), 94 deletions(-) diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index f8a052f..15fbc9f 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -5,7 +5,7 @@ use client_network::{ use crossbeam_channel::{Receiver, Sender}; use egui::{ Align, Align2, Button, CentralPanel, CollapsingHeader, Context, Id, LayerId, Layout, Order, - Popup, ScrollArea, SidePanel, TopBottomPanel, Ui, ViewportCommand, + Popup, ScrollArea, SidePanel, TextStyle, TopBottomPanel, Ui, ViewportCommand, }; use std::collections::HashMap; @@ -29,7 +29,8 @@ pub struct P2PClientApp { status_message: String, known_peers: Vec, connect_address_input: String, - connect_server_name_input: String, + connected_address: String, + connect_name_input: String, // Key: Parent Directory Hash (String), Value: List of children FileNode loaded_fs: HashMap, @@ -40,6 +41,8 @@ pub struct P2PClientApp { server_status: ServerStatus, show_network_popup: bool, // gérer selon besoin + + error_message: Option, // Some(message) -> afficher, None -> rien } impl P2PClientApp { @@ -59,13 +62,21 @@ impl P2PClientApp { status_message: "Client Initialized. Awaiting network status...".to_string(), known_peers: vec!["bob".to_string()], connect_address_input: "https://jch.irif.fr:8443".to_string(), - connect_server_name_input: "jch.irif.fr".to_string(), + connected_address: "".to_string(), loaded_fs, active_peer: None, server_status: ServerStatus::NotConnected, show_network_popup: false, + error_message: None, + connect_name_input: "bob".to_string(), } } + pub fn show_error(&mut self, msg: impl Into) { + self.error_message = Some(msg.into()); + } + pub fn clear_error(&mut self) { + self.error_message = None; + } } // --- eframe::App Trait Implementation --- @@ -127,14 +138,24 @@ impl eframe::App for P2PClientApp { // root_hash, // )); } - NetworkEvent::Connected() => { + NetworkEvent::Connected(ip) => { self.server_status = ServerStatus::Connected; + self.connected_address = ip.clone(); + let _ = self.network_cmd_tx.send(NetworkCommand::FetchPeerList( + self.connected_address.clone(), + )); } NetworkEvent::ConnectedHandshake() => { self.server_status = ServerStatus::ConnectedHandshake; } - NetworkEvent::Disconnected() => todo!(), - NetworkEvent::Error() => todo!(), + NetworkEvent::Disconnected() => { + self.connected_address = "".to_string(); + self.known_peers.clear(); + self.server_status = ServerStatus::NotConnected; + } + NetworkEvent::Error(err) => { + self.show_error(err); + } NetworkEvent::DataReceived(_, merkle_node) => todo!(), } } @@ -154,34 +175,60 @@ impl eframe::App for P2PClientApp { }); ui.menu_button("Network", |ui| { - ui.vertical(|ui| { - ui.horizontal(|ui| { - ui.label("Server IP:"); - ui.text_edit_singleline(&mut self.connect_address_input); - }); + match self.server_status { + ServerStatus::Connected | ServerStatus::ConnectedHandshake => { + let desired = egui::vec2(300.0, 0.0); // width 300, auto-height if 0 + ui.set_min_size(desired); + ui.vertical(|ui| { + if ui.button("Disconnect").clicked() { + println!("Disconnecting..."); + let _ = self.network_cmd_tx.send(NetworkCommand::Disconnect()); + self.server_status = ServerStatus::NotConnected; + self.remaining = std::time::Duration::from_secs(0); + self.timer_started = false; + ui.close(); + } + }); + } + ServerStatus::NotConnected => { + let desired = egui::vec2(0.0, 0.0); // width 300, auto-height if 0 + ui.set_min_size(desired); + ui.vertical(|ui| { + ui.horizontal(|ui| { + ui.label("Server IP:"); + ui.text_edit_singleline(&mut self.connect_address_input); + }); + ui.horizontal(|ui| { + ui.label("Name:"); + ui.text_edit_singleline(&mut self.connect_name_input); + }); + if ui.button("Connect").clicked() { + let addr = self.connect_address_input.clone(); + let name = self.connect_name_input.clone(); + let _ = self + .network_cmd_tx + .send(NetworkCommand::ConnectToServerPut(addr, name)); + self.server_status = ServerStatus::Loading; + ui.close(); + } + }); + } + _ => {} + } + + /* ui.horizontal(|ui| { + ui.label("Server peer name:"); + ui.text_edit_singleline(&mut self.connect_server_name_input); if ui.button("Connect").clicked() { let addr = self.connect_address_input.clone(); + let serv_name = self.connect_server_name_input.clone(); let _ = self .network_cmd_tx - .send(NetworkCommand::ConnectToServerPut(addr)); + .send(NetworkCommand::ConnectToServer(addr, serv_name)); self.server_status = ServerStatus::Loading; ui.close(); } - - /* ui.horizontal(|ui| { - ui.label("Server peer name:"); - ui.text_edit_singleline(&mut self.connect_server_name_input); - if ui.button("Connect").clicked() { - let addr = self.connect_address_input.clone(); - let serv_name = self.connect_server_name_input.clone(); - let _ = self - .network_cmd_tx - .send(NetworkCommand::ConnectToServer(addr, serv_name)); - self.server_status = ServerStatus::Loading; - ui.close(); - } - });*/ - }); + });*/ }); // état @@ -262,8 +309,9 @@ impl eframe::App for P2PClientApp { ui.heading("🌐 Known Peers"); ui.add_space(20.0); if ui.button("🔄").clicked() { + println!("addr:{}", self.connected_address.clone()); let res = self.network_cmd_tx.send(NetworkCommand::FetchPeerList( - self.connect_address_input.clone(), + self.connected_address.clone(), )); if let Some(error) = res.err() { println!( @@ -350,6 +398,21 @@ impl eframe::App for P2PClientApp { // ui.label(format!("Status: {}", self.status_message)); }); + if let Some(msg) = &self.error_message { + let msg = msg.clone(); + egui::Window::new("Error") + .collapsible(false) + .resizable(false) + .anchor(egui::Align2::CENTER_CENTER, [0.0, 0.0]) + .show(ctx, |ui| { + ui.label(&msg); + if ui.button("OK").clicked() { + self.clear_error(); + } + }); + ctx.request_repaint(); + } + ctx.request_repaint_after(std::time::Duration::from_millis(10)); } } diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index ec5a2c7..2829b05 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -17,6 +17,7 @@ use crate::{ }; use std::sync::{Arc, Mutex}; use std::{ + io::Error, net::{SocketAddr, UdpSocket}, str::FromStr, }; @@ -29,47 +30,59 @@ pub struct P2PSharedData { } impl P2PSharedData { - pub fn new(username: String) -> P2PSharedData { + pub fn new(username: String) -> Result { let messages_list = HashMap::::new(); let username = String::from(username); let crypto_pair = CryptographicSignature::new(username); - let socket = UdpSocket::bind("0.0.0.0:0").expect("bind failed"); - + let socket = UdpSocket::bind("0.0.0.0:0")?; let shared_socket = Arc::new(socket); let shared_cryptopair = Arc::new(crypto_pair); let shared_messageslist = Arc::new(Mutex::new(messages_list)); let senders = MultipleSenders::new(1, &shared_socket); let shared_senders = Arc::new(senders); - P2PSharedData { + Ok(P2PSharedData { shared_socket: shared_socket, shared_cryptopair: shared_cryptopair, shared_messageslist: shared_messageslist, shared_senders: shared_senders, - } + }) + } + pub fn socket(&self) -> Arc { + self.shared_socket.clone() + } + + pub fn cryptopair(&self) -> Arc { + self.shared_cryptopair.clone() + } + + pub fn add_message(&self, id: i32, evt: EventType) { + let mut map = self.shared_messageslist.lock().unwrap(); + map.insert(id, evt); } } /// Messages sent to the Network thread by the GUI. pub enum NetworkCommand { - ConnectToServerPut(String), // ServerIP - ServerHandshake(String), // ServerName - FetchPeerList(String), // ServerIP + ConnectToServerPut(String, String), // ServerIP + ServerHandshake(String), // ServerName + FetchPeerList(String), // ServerIP RegisterAsPeer(String), Ping(), ConnectPeer(String), // IP:PORT RequestFileTree(String), // peer_id RequestDirectoryContent(String, String), RequestChunk(String, String), + Disconnect(), // ... } /// Messages sent to the GUI by the Network thread. pub enum NetworkEvent { - Connected(), + Connected(String), ConnectedHandshake(), Disconnected(), - Error(), + Error(String), PeerConnected(String), PeerListUpdated(Vec), FileTreeReceived(String, Vec), // peer_id, content @@ -102,7 +115,7 @@ pub fn calculate_chunk_id(data: &[u8]) -> String { pub fn start_p2p_executor( cmd_rx: Receiver, event_tx: Sender, - shared_data: Option, + mut shared_data: Option, ) -> tokio::task::JoinHandle<()> { // Use tokio to spawn the asynchronous networking logic tokio::task::spawn(async move { @@ -140,21 +153,23 @@ pub fn start_p2p_executor( 545, );*/ - let res = event_tx.send(NetworkEvent::Connected()); + //let res = event_tx.send(NetworkEvent::Connected()); } else { - let res = event_tx.send(NetworkEvent::Error()); + //let res = event_tx.send(NetworkEvent::Error()); eprintln!("no valid socket addresses found in: {}", s); } } Err(e) => { - let res = event_tx.send(NetworkEvent::Error()); + //let res = event_tx.send(NetworkEvent::Error()); eprintln!("invalid UTF-8 in socket address bytes: {}", e); } } } Err(e) => { - eprintln!("failed to retrieve socket address: {}", e); - let res = event_tx.send(NetworkEvent::Error()); + let mut err_msg = + String::from("failed to retrieve socket address:"); + err_msg += &e.to_string(); + let res = event_tx.send(NetworkEvent::Error(err_msg)); } } } @@ -174,35 +189,35 @@ pub fn start_p2p_executor( NetworkCommand::RequestChunk(_, _) => { println!("[Network] RequestChunk() called"); } - NetworkCommand::ConnectToServerPut(ip) => { + NetworkCommand::ConnectToServerPut(ip, name) => { println!("[Network] ConnectToServer() called"); // Actual server connection - let messages_list = HashMap::::new(); + shared_data = match P2PSharedData::new(name.clone()) { + Ok(sd) => Some(sd), + Err(e) => { + let mut err_msg = String::from("failed to initialize socket: "); + err_msg += &e.to_string(); + let res = event_tx.send(NetworkEvent::Error(err_msg)); + let res = event_tx.send(NetworkEvent::Disconnected()); + None + } + }; - let username = String::from("Gamemeixtreize"); - - let crypto_pair = CryptographicSignature::new(username); - - let socket = UdpSocket::bind("0.0.0.0:0").expect("bind failed"); - - let shared_socket = Arc::new(socket); - let shared_cryptopair = Arc::new(crypto_pair); - let shared_messageslist = Arc::new(Mutex::new(messages_list)); - - let senders = MultipleSenders::new(1, &shared_socket); - - let shared_senders = Arc::new(senders); - if let Err(e) = register_with_the_server(&shared_cryptopair, &ip).await { - let res = event_tx.send(NetworkEvent::Error()); - eprintln!("request failed: {}", e); + if let Some(sd) = shared_data.as_ref() { + if let Err(e) = register_with_the_server(&sd.cryptopair(), &ip).await { + let mut err_msg = String::from("request failed: "); + err_msg += &e.to_string(); + let res = event_tx.send(NetworkEvent::Error(err_msg)); + let res = event_tx.send(NetworkEvent::Disconnected()); + } else { + let res = event_tx.send(NetworkEvent::Connected(ip)); + println!("username created: {}", sd.cryptopair().username); + } + //println!("ip: {}", ip); } - let res = event_tx.send(NetworkEvent::Connected()); - - println!("ip: {}", ip); - //tokio::time::sleep(std::time::Duration::from_millis(5000)).await; /*let res = event_tx.send(NetworkEvent::Connected()); @@ -214,27 +229,34 @@ pub fn start_p2p_executor( }*/ } NetworkCommand::FetchPeerList(ip) => { - println!("cc"); - match get_peer_list(String::from("https://jch.irif.fr:8443")).await { - Ok(body) => match String::from_utf8(body.to_vec()) { - Ok(peers_list) => { - let mut peers: Vec = Vec::new(); - let mut current = String::new(); - for i in peers_list.chars() { - if i == '\n' { - peers.push(current.clone()); - current.clear(); - } else { - current.push(i); + if ip == "" { + let res = event_tx.send(NetworkEvent::Error( + "Not registered to any server".to_string(), + )); + } else { + println!("cc"); + 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 current = String::new(); + for i in peers_list.chars() { + if i == '\n' { + peers.push(current.clone()); + current.clear(); + } else { + current.push(i); + } } + let res = + event_tx.send(NetworkEvent::PeerListUpdated(peers)); } - let res = event_tx.send(NetworkEvent::PeerListUpdated(peers)); - } - Err(e) => { - eprintln!("invalid UTF-8 in socket address bytes: {}", e); - } - }, - Err(e) => println!("error"), + Err(e) => { + eprintln!("invalid UTF-8 in socket address bytes: {}", e); + } + }, + Err(e) => println!("error"), + } } println!("[Network] FetchPeerList() called"); } @@ -244,6 +266,15 @@ pub fn start_p2p_executor( NetworkCommand::Ping() => { println!("[Network] Ping() called"); } + NetworkCommand::Disconnect() => { + if let Some(sd) = shared_data.as_ref() { + println!("Disconnecting: {}", &sd.cryptopair().username); + shared_data = None; + let res = event_tx.send(NetworkEvent::Disconnected()); + } else { + println!("no p2p data"); + } + } } } diff --git a/client-network/src/registration.rs b/client-network/src/registration.rs index eca62be..c01645c 100644 --- a/client-network/src/registration.rs +++ b/client-network/src/registration.rs @@ -1,4 +1,5 @@ use bytes::Bytes; +use getrandom::Error; use crate::cryptographic_signature::{CryptographicSignature, formatPubKey, sign_message}; use crate::message_handling::EventType; @@ -23,15 +24,7 @@ pub async fn register_with_the_server( let pubkey_bytes = encoded_point.as_ref().to_vec(); let pubkey_bytes_minus = pubkey_bytes[1..].to_vec(); let res = client.put(uri).body(pubkey_bytes_minus).send().await?; - if res.status().is_success() { - let str = hex::encode(res.bytes().await?); - println!("Successfully registered with the server : {}", str); - } else { - eprintln!( - "Failed to register with the server. Status: {}", - res.status() - ); - } + let res = res.error_for_status()?; println!("register ip adresses"); Ok(()) }