diff --git a/client-gui/src/gui_app.rs b/client-gui/src/gui_app.rs index 3e380aa..ae916af 100644 --- a/client-gui/src/gui_app.rs +++ b/client-gui/src/gui_app.rs @@ -453,92 +453,103 @@ impl eframe::App for P2PClientApp { }); ui.separator(); - ScrollArea::vertical().show(ui, |ui| { - if self.known_peers.is_empty() { - ui.add_space(10.0); - ui.label("No active peers."); - } else { - for peer in &self.known_peers { - let is_active = - self.active_peer.as_ref().map_or(false, |id| id == &peer.0); // if peer.id == self.active_peer_id + ScrollArea::vertical() + .auto_shrink([false; 2]) + .show(ui, |ui| { + ui.style_mut().visuals.widgets.inactive.bg_fill = + ui.style().visuals.widgets.inactive.bg_fill; // no-op to get mutable borrow + if self.known_peers.is_empty() { + ui.add_space(10.0); + ui.label("No active peers."); + } else { + for peer in &self.known_peers { + let is_active = + self.active_peer.as_ref().map_or(false, |id| id == &peer.0); // if peer.id == self.active_peer_id - let selectable: Response; - // if &self.active_server == &peer.0 { - // // Create a frame with green background and render the selectable inside it. - // // Adjust rounding, padding and stroke as desired. - // let frame = Frame { - // fill: Color32::DARK_BLUE, - // stroke: Stroke::default(), - // corner_radius: CornerRadius::from(0.5), - // ..Default::default() - // }; - // let internal = frame.show(ui, |ui| { - // // horizontal row: label on the left, spinner on the right - // ui.horizontal(|ui| { - // // let selectable label take remaining space - // ui.with_layout(Layout::left_to_right(Align::Center), |ui| { - // ui.add_space(0.0); // ensure layout established - // return ui.selectable_label( - // is_active, - // format!("{}", peer.0), - // ); - // }) - // .inner // return Response from the inner closure if your egui version does so - // }) - // }); - // selectable = internal.inner.inner; - // } else { - // selectable = ui.selectable_label(is_active, format!("{}", peer.0)); - // } + let selectable: Response; + // if &self.active_server == &peer.0 { + // // Create a frame with green background and render the selectable inside it. + // // Adjust rounding, padding and stroke as desired. + // let frame = Frame { + // fill: Color32::DARK_BLUE, + // stroke: Stroke::default(), + // corner_radius: CornerRadius::from(0.5), + // ..Default::default() + // }; + // let internal = frame.show(ui, |ui| { + // // horizontal row: label on the left, spinner on the right + // ui.horizontal(|ui| { + // // let selectable label take remaining space + // ui.with_layout(Layout::left_to_right(Align::Center), |ui| { + // ui.add_space(0.0); // ensure layout established + // return ui.selectable_label( + // is_active, + // format!("{}", peer.0), + // ); + // }) + // .inner // return Response from the inner closure if your egui version does so + // }) + // }); + // selectable = internal.inner.inner; + // } else { + // selectable = ui.selectable_label(is_active, format!("{}", peer.0)); + // } - // place spinner to the right of the label - ui.horizontal(|ui| { - // Use same width for the label widget as the selectable we already created: - // Recreate selectable inline so both label and spinner share the same row. - let resp = if &self.active_server == &peer.0 { - // draw with frame inline - let frame = Frame { - fill: Color32::DARK_BLUE, - stroke: Stroke::default(), - corner_radius: CornerRadius::from(0.5), - ..Default::default() + // place spinner to the right of the label + ui.horizontal(|ui| { + // Use same width for the label widget as the selectable we already created: + // Recreate selectable inline so both label and spinner share the same row. + let resp = if &self.active_server == &peer.0 { + // draw with frame inline + let frame = Frame { + fill: Color32::DARK_BLUE, + stroke: Stroke::default(), + corner_radius: CornerRadius::from(0.5), + ..Default::default() + }; + frame + .show(ui, |ui| { + ui.selectable_label( + is_active, + format!("{}", peer.0), + ) + }) + .inner + } else { + ui.selectable_label(is_active, format!("{}", peer.0)) }; - frame - .show(ui, |ui| { - ui.selectable_label(is_active, format!("{}", peer.0)) - }) - .inner - } else { - ui.selectable_label(is_active, format!("{}", peer.0)) - }; - ui.add_space(4.0); // small gap + ui.add_space(4.0); // small gap - if self.loading_peers.contains(&peer.0) { - // push spinner to right by expanding a spacer before it - ui.with_layout(Layout::right_to_left(Align::Center), |ui| { - ui.spinner(); - }); - } - - // use resp (click handling etc.) - if resp.clicked() { - // switch to displaying this peer's tree - self.active_peer = Some(peer.0.clone()); - // Request root content if not loaded - if !self - .loaded_fs - .contains_key(self.active_peer.as_ref().unwrap()) - { - //todo!(); - let _ = self.network_cmd_tx.send(NetworkCommand::Discover( - peer.0.clone(), - "root".to_string(), - self.connected_address.clone(), - )); + if self.loading_peers.contains(&peer.0) { + // push spinner to right by expanding a spacer before it + ui.with_layout( + Layout::right_to_left(Align::Center), + |ui| { + ui.spinner(); + }, + ); } - } - resp.context_menu(|ui| { + + // use resp (click handling etc.) + if resp.clicked() { + // switch to displaying this peer's tree + self.active_peer = Some(peer.0.clone()); + // Request root content if not loaded + if !self + .loaded_fs + .contains_key(self.active_peer.as_ref().unwrap()) + { + //todo!(); + let _ = + self.network_cmd_tx.send(NetworkCommand::Discover( + peer.0.clone(), + "root".to_string(), + self.connected_address.clone(), + )); + } + } + resp.context_menu(|ui| { // ... action match self.server_status { ServerStatus::Connected => { @@ -589,78 +600,78 @@ impl eframe::App for P2PClientApp { // ... autres boutons }); - }); + }); - // if self.loading_peers.contains(&peer.0) { - // ui.spinner(); - // } + // if self.loading_peers.contains(&peer.0) { + // ui.spinner(); + // } - //if selectable.clicked() { - // switch to displaying this peer's tree - //self.active_peer = Some(peer.0.clone()); - //// Request root content if not loaded - //if !self - // .loaded_fs - // .contains_key(self.active_peer.as_ref().unwrap()) - //{ - // //todo!(); - // let _ = self.network_cmd_tx.send(NetworkCommand::Discover( - // peer.0.clone(), - // "root".to_string(), - // self.connected_address.clone(), - // )); - //} - //} - //selectable.context_menu(|ui| { - // // ... action - // match self.server_status { - // ServerStatus::Connected => { - // if ui - // .button("Utiliser le peer en tant que serveur") - // .clicked() - // { - // self.active_server = peer.0.to_string(); - // let res = self.network_cmd_tx.send( - // NetworkCommand::ServerHandshake( - // peer.0.to_string(), - // self.connected_address.clone(), - // ), - // ); - // } - // } - // _ => {} - // } - // if ui.button("Send Ping").clicked() { - // let res = self.network_cmd_tx.send(NetworkCommand::Ping( - // peer.0.to_string(), - // self.connected_address.clone(), - // )); + //if selectable.clicked() { + // switch to displaying this peer's tree + //self.active_peer = Some(peer.0.clone()); + //// Request root content if not loaded + //if !self + // .loaded_fs + // .contains_key(self.active_peer.as_ref().unwrap()) + //{ + // //todo!(); + // let _ = self.network_cmd_tx.send(NetworkCommand::Discover( + // peer.0.clone(), + // "root".to_string(), + // self.connected_address.clone(), + // )); + //} + //} + //selectable.context_menu(|ui| { + // // ... action + // match self.server_status { + // ServerStatus::Connected => { + // if ui + // .button("Utiliser le peer en tant que serveur") + // .clicked() + // { + // self.active_server = peer.0.to_string(); + // let res = self.network_cmd_tx.send( + // NetworkCommand::ServerHandshake( + // peer.0.to_string(), + // self.connected_address.clone(), + // ), + // ); + // } + // } + // _ => {} + // } + // if ui.button("Send Ping").clicked() { + // let res = self.network_cmd_tx.send(NetworkCommand::Ping( + // peer.0.to_string(), + // self.connected_address.clone(), + // )); - // self.loading_peers.push(peer.0.to_owned()); - // } - // 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(); - // } + // self.loading_peers.push(peer.0.to_owned()); + // } + // 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 - //}); + // // ... autres boutons + //}); + } } - } - }); + }); }); CentralPanel::default().show(ctx, |ui| { @@ -680,7 +691,11 @@ impl eframe::App for P2PClientApp { self.draw_file_tree(ui, tree); }); } else { - ui.label(format!("Loading root for peer: {}", active_peer)); + ui.horizontal(|ui| { + ui.label(format!("Loading root for peer: {}", active_peer)); + ui.add_space(8.0); + ui.spinner(); // or conditional: if is_loading { ui.spinner(); } + }); } } else { ui.label("Connect to a peer to view a file tree."); diff --git a/client-network/src/lib.rs b/client-network/src/lib.rs index d4d80b2..635eb34 100644 --- a/client-network/src/lib.rs +++ b/client-network/src/lib.rs @@ -340,9 +340,53 @@ pub fn start_p2p_executor( sd.messages_list(), sd.handshake_peers.get_username_peerinfo_map(), ); + let server_address = { + match get_server_address(username.to_owned(), ip.to_owned()).await { + Some(addr) => addr.to_string(), + None => { + match event_tx.send(NetworkEvent::Error( + "Couldn't fetch server socket address.".to_owned(), + username.to_owned(), + )) { + Ok(_) => {} + Err(e) => { + println!("Network Event Error : {}", e.to_string()); + } + } + "".to_owned() + } + } + }; + if server_address.to_owned().eq(&"".to_owned()) { + continue; + } - let res = - perform_handshake(&sd, username, ip, event_tx.clone(), true).await; + sd.set_servername(username.to_owned()); + sd.set_serveraddress(server_address.to_string()); + println!("SET SERVERADDRESS"); + + match perform_handshake( + &sd, + username.to_owned(), + ip, + event_tx.clone(), + (true, server_address.to_string()), + ) + .await + { + true => { + match event_tx.send(NetworkEvent::Success( + "Handshake established ✔️".to_string(), + username.to_owned(), + )) { + Ok(_) => {} + Err(err) => { + println!("Network Event Error : {}", err.to_string()); + } + }; + } + false => {} + }; } else { println!("no shared data"); } @@ -360,7 +404,9 @@ pub fn start_p2p_executor( NetworkCommand::Discover(username, hash, ip) => { // envoie un handshake au peer, puis un root request if let Some(sd) = shared_data.as_ref() { - let res = sd.handshake_peers.get_peer_info_username(username.clone()); + let res = sd + .handshake_peers + .get_peer_info_username(username.to_owned()); match res { Some(peerinfo) => { let id = generate_id(); @@ -395,14 +441,31 @@ pub fn start_p2p_executor( } None => { // envoyer un handshake - let res = perform_handshake( + match perform_handshake( &sd, - username, + username.to_owned(), ip, event_tx.clone(), - false, + (false, "".to_string()), ) - .await; + .await + { + true => { + match event_tx.send(NetworkEvent::Success( + "Handshake established ✔️".to_string(), + username.to_owned(), + )) { + Ok(_) => {} + Err(err) => { + println!( + "Network Event Error : {}", + err.to_string() + ); + } + }; + } + false => {} + } } } } else { @@ -756,7 +819,16 @@ pub async fn get_socket_address( } }; - let addresses = parse_addresses(&s); // assumes parse_addresses: &str -> Vec + let addresses: Vec = { + let temp = parse_addresses(&s); + temp.iter() + .filter_map(|a| match a { + SocketAddr::V4(_) => Some(*a), + SocketAddr::V6(_) => None, + }) + .collect() + }; + if addresses.is_empty() { return Err(FetchSocketAddressError::NoRegisteredAddresses); } else if !addresses.iter().any(|a| matches!(a, SocketAddr::V4(_))) { diff --git a/client-network/src/message_handling.rs b/client-network/src/message_handling.rs index 96a41db..c10530c 100644 --- a/client-network/src/message_handling.rs +++ b/client-network/src/message_handling.rs @@ -314,7 +314,7 @@ pub fn parse_message( ERROR => { if let Ok(err_received) = - String::from_utf8(received_message[LENGTH..(msg_length + LENGTH + 4)].to_vec()) + String::from_utf8(received_message[LENGTH..(msg_length + LENGTH)].to_vec()) { let err_msg = format!("Error received from peer {} : {}", ip, err_received); let _ = cmd_tx_clone.send(NetworkEvent::Error(err_msg, "".to_owned())); diff --git a/client-network/src/registration.rs b/client-network/src/registration.rs index 7df1e06..a94c11e 100644 --- a/client-network/src/registration.rs +++ b/client-network/src/registration.rs @@ -2,6 +2,7 @@ use crate::NetworkEvent; use crate::P2PSharedData; use crate::cryptographic_signature::CryptographicSignature; use crate::get_server_address; +use crate::get_socket_address; use crate::message_handling::EventType; use crate::messages_structure::construct_message; use crate::server_communication::generate_id; @@ -55,47 +56,71 @@ pub async fn perform_handshake( username: String, ip: String, event_tx: Sender, - is_server_handshake: bool, -) { + is_server_handshake: (bool, String), +) -> bool { println!("username: {}, ip: {}", username.clone(), ip.clone()); let crypto_pair = sd.cryptopair_ref(); let senders = sd.senders_ref(); let id = generate_id(); - let server_addr_query = get_server_address(username.clone(), ip.clone()); - match server_addr_query.await { - 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); - if is_server_handshake { - sd.add_message(id, EventType::Hello); - sd.set_serveraddress(sockaddr_bytes.to_string()); - } else { - sd.add_message(id, EventType::HelloThenRootRequest); - } - match hello_handshake { - Some(handshake_message) => { - senders.send_dispatch( - handshake_message, - sockaddr_bytes.to_string(), - is_server_handshake, - sd.messages_list(), - ); + let address = { + if is_server_handshake.0 { + is_server_handshake.1 + } else { + let server_addr_query = + get_socket_address(username.clone(), ip.clone(), Some(sd)).await; + + match server_addr_query { + Ok(sockaddr_bytes) => sockaddr_bytes.to_string(), + Err(err_msg) => { + match event_tx.send(NetworkEvent::Error( + err_msg.to_string(), + username.to_owned(), + )) { + Ok(_) => {} + Err(err) => { + println!("Network Event Error : {}", err.to_string()); + } + } + "".to_string() } - None => {} } } - None => { - let err_msg = format!("failed to retreive socket address:").to_string(); - let res = event_tx.send(NetworkEvent::Error(err_msg, "".to_owned())); - } + }; + + if address.eq(&"".to_string()) { + return false; } + 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); + if is_server_handshake.0 { + sd.add_message(id, EventType::Hello); + } else { + sd.add_message(id, EventType::HelloThenRootRequest); + } + + match hello_handshake { + Some(handshake_message) => { + senders.send_dispatch( + handshake_message, + address, + is_server_handshake.0, + sd.messages_list(), + ); + } + None => {} + } + + //let server_addr_query = get_socket_address(username.clone(), ip.clone(), Some(sd)).await; + //match server_addr_query { + // Ok(sockaddr_bytes) => {} + // Err(err_msg) => {} + //} + /*let mut list = messages_list.lock().expect("Failed to lock messages_list"); match list.get(&id) { Some(_) => { @@ -112,6 +137,7 @@ pub async fn perform_handshake( let hello_handshake_received = UDPMessage::parse(buf.to_vec()); hello_handshake_received.display();*/ //TODO + return true; } #[cfg(test)]