root request

This commit is contained in:
TIBERGHIEN corentin
2026-01-13 17:13:35 +01:00
parent 98fcc1a0b2
commit c852c5bb4a
6 changed files with 210 additions and 78 deletions

View File

@@ -1,5 +1,5 @@
use client_network::{ use client_network::{
MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string, ChunkNode, MerkleNode, MerkleTree, NetworkCommand, NetworkEvent, NodeHash, filename_to_string,
node_hash_to_hex_string, node_hash_to_hex_string,
}; };
use crossbeam_channel::{Receiver, Sender}; use crossbeam_channel::{Receiver, Sender};
@@ -129,11 +129,28 @@ impl eframe::App for P2PClientApp {
NetworkEvent::FileTreeRootReceived(peer_id, root_hash) => { NetworkEvent::FileTreeRootReceived(peer_id, root_hash) => {
// todo!(); // todo!();
self.status_message = format!( /*self.status_message = format!(
"🔄 Received Merkle Root from {}: {}", "🔄 Received Merkle Root from {}: {}",
peer_id, peer_id,
&root_hash[..8] &root_hash[..8]
); );*/
if let Ok(chunknode) = ChunkNode::new(Vec::new()) {
let mut data_map: HashMap<NodeHash, MerkleNode> = HashMap::new();
data_map.insert(root_hash, MerkleNode::Chunk(chunknode));
let tree = MerkleTree {
data: data_map,
root: root_hash,
};
match &self.active_peer {
Some(activepeer) => {
self.loaded_fs.insert(activepeer.clone(), tree);
}
None => {}
}
println!("tree created");
}
//self.active_peer_id = Some(peer_id.clone()); //self.active_peer_id = Some(peer_id.clone());
@@ -365,6 +382,7 @@ impl eframe::App for P2PClientApp {
let _ = self.network_cmd_tx.send(NetworkCommand::Discover( let _ = self.network_cmd_tx.send(NetworkCommand::Discover(
peer.clone(), peer.clone(),
"root".to_string(), "root".to_string(),
self.connected_address.clone(),
)); ));
} }
} }

View File

@@ -12,7 +12,7 @@ use crate::{
cryptographic_signature::CryptographicSignature, cryptographic_signature::CryptographicSignature,
message_handling::EventType, message_handling::EventType,
messages_channels::{MultipleSenders, start_receving_thread}, messages_channels::{MultipleSenders, start_receving_thread},
messages_structure::construct_message, messages_structure::{ROOTREQUEST, construct_message},
peers_refresh::HandshakeHistory, peers_refresh::HandshakeHistory,
registration::{ registration::{
get_socket_address, parse_addresses, perform_handshake, register_with_the_server, get_socket_address, parse_addresses, perform_handshake, register_with_the_server,
@@ -123,7 +123,7 @@ pub enum NetworkCommand {
RequestChunk(String, String), RequestChunk(String, String),
Disconnect(), Disconnect(),
ResetServerPeer(), ResetServerPeer(),
Discover(String, String), Discover(String, String, String),
GetChildren(String, String), GetChildren(String, String),
// ... // ...
} }
@@ -138,7 +138,7 @@ pub enum NetworkEvent {
PeerListUpdated(Vec<String>), PeerListUpdated(Vec<String>),
FileTreeReceived(String, Vec<MerkleNode>), // peer_id, content FileTreeReceived(String, Vec<MerkleNode>), // peer_id, content
DataReceived(String, MerkleNode), DataReceived(String, MerkleNode),
FileTreeRootReceived(String, String), FileTreeRootReceived(String, NodeHash),
HandshakeFailed(), HandshakeFailed(),
ServerHandshakeFailed(String), ServerHandshakeFailed(String),
// ... // ...
@@ -173,6 +173,8 @@ pub fn start_p2p_executor(
// Use tokio to spawn the asynchronous networking logic // Use tokio to spawn the asynchronous networking logic
tokio::task::spawn(async move { tokio::task::spawn(async move {
// P2P/Networking Setup goes here // P2P/Networking Setup goes here
let handshake_history = Arc::new(Mutex::new(HandshakeHistory::new()));
let handshake_clone = handshake_history.clone();
println!("Network executor started."); println!("Network executor started.");
@@ -182,12 +184,13 @@ pub fn start_p2p_executor(
if let Ok(cmd) = cmd_rx.try_recv() { if let Ok(cmd) = cmd_rx.try_recv() {
match cmd { match cmd {
NetworkCommand::ServerHandshake(username, ip) => { NetworkCommand::ServerHandshake(username, ip) => {
println!("server handshake called");
if let Some(sd) = shared_data.as_ref() { if let Some(sd) = shared_data.as_ref() {
start_receving_thread( start_receving_thread(sd, event_tx.clone(), &handshake_clone);
sd, let res =
event_tx.clone(), // perform_handshake(&sd, username, ip, event_tx.clone(), true).await;
); } else {
perform_handshake(&sd, username, ip, event_tx.clone()); println!("no shared data");
} }
} }
NetworkCommand::ConnectPeer(addr) => { NetworkCommand::ConnectPeer(addr) => {
@@ -200,8 +203,52 @@ pub fn start_p2p_executor(
NetworkCommand::RequestFileTree(_) => { NetworkCommand::RequestFileTree(_) => {
println!("[Network] RequestFileTree() called"); println!("[Network] RequestFileTree() called");
} }
NetworkCommand::Discover(username, hash) => { NetworkCommand::Discover(username, hash, ip) => {
// envoie un handshake au peer, puis un root request // envoie un handshake au peer, puis un root request
if let Some(sd) = shared_data.as_ref() {
let res = {
let m = handshake_clone.lock().unwrap();
m.get_peer_info_username(username.clone()).cloned()
};
match res {
Some(peerinfo) => {
// envoyer un root request
let rootrequest = construct_message(
ROOTREQUEST,
Vec::new(),
generate_id(),
sd.cryptopair_ref(),
);
match rootrequest {
None => {}
Some(resp_msg) => {
println!("msg_sent:{:?}", resp_msg);
sd.senders_ref().send_via(
0,
resp_msg,
peerinfo.ip.to_string(),
false,
sd.messages_list_ref(),
);
}
}
}
None => {
// envoyer un handshake
let res = perform_handshake(
&sd,
username,
ip,
event_tx.clone(),
false,
)
.await;
}
}
} else {
println!("no shared data");
}
} }
NetworkCommand::GetChildren(username, hash) => { NetworkCommand::GetChildren(username, hash) => {
// envoie un datum request au peer // envoie un datum request au peer

View File

@@ -1,5 +1,5 @@
use crate::{ use crate::{
NetworkEvent, NetworkEvent, NodeHash,
cryptographic_signature::{ cryptographic_signature::{
CryptographicSignature, get_peer_key, sign_message, verify_signature, CryptographicSignature, get_peer_key, sign_message, verify_signature,
}, },
@@ -47,7 +47,7 @@ pub fn handle_recevied_message(
server_name: &String, server_name: &String,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>, cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr, ip: SocketAddr,
handshake_history: HandshakeHistory, handhsake_history: &Arc<Mutex<HandshakeHistory>>,
) { ) {
if recevied_message.len() < 4 { if recevied_message.len() < 4 {
return; return;
@@ -78,7 +78,7 @@ pub fn handle_recevied_message(
cmd_tx, cmd_tx,
ip, ip,
messages_list, messages_list,
handshake_history, handhsake_history,
); );
match resp { match resp {
@@ -168,8 +168,9 @@ pub fn parse_message(
cmd_tx: crossbeam_channel::Sender<NetworkEvent>, cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr, ip: SocketAddr,
messages_list: &Arc<Mutex<HashMap<i32, EventType>>>, messages_list: &Arc<Mutex<HashMap<i32, EventType>>>,
handhsake_history: HandshakeHistory, handhsake_history_mutex: &Arc<Mutex<HandshakeHistory>>,
) -> Option<Vec<u8>> { ) -> Option<Vec<u8>> {
let mut handhsake_history = handhsake_history_mutex.lock().unwrap();
let cmd_tx_clone = cmd_tx.clone(); let cmd_tx_clone = cmd_tx.clone();
let id_bytes: [u8; 4] = received_message[0..ID] let id_bytes: [u8; 4] = received_message[0..ID]
@@ -185,20 +186,27 @@ pub fn parse_message(
let msg_length = u16::from_be_bytes(length_bytes) as usize; let msg_length = u16::from_be_bytes(length_bytes) as usize;
// verify signature // verify signature
match msgtype { match msgtype {
HELLO | HELLOREPLY | ROOTREPLY | NODATUM | NATTRAVERSALREQUEST | NATTRAVERSALREQUEST2 => { HELLO | HELLOREPLY | NODATUM | NATTRAVERSALREQUEST | NATTRAVERSALREQUEST2 => {
let ilength = u16::from_be_bytes(length_bytes); let ilength = u16::from_be_bytes(length_bytes);
println!("name received length: {}", ilength); println!("name received length: {}", ilength);
let received_name = &received_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize]; let received_name = &received_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize];
let received_username = String::from_utf8(received_name.to_vec()); let received_username = String::from_utf8(received_name.to_vec());
match received_username { match received_username {
Ok(username) => { Ok(username) => {
let peer_pubkey = match handhsake_history.get_peer_info_username(username) { let peer_pubkey =
Some(peerinfo) => peerinfo.pubkey, match handhsake_history.get_peer_info_username(username.clone()) {
_ => tokio::runtime::Runtime::new() Some(peerinfo) => peerinfo.pubkey,
.unwrap() _ => tokio::runtime::Runtime::new()
.block_on(get_peer_key(&username)) .unwrap()
.expect("failed to retrieve public key"), .block_on(get_peer_key(&username))
}; .expect("failed to retrieve public key"),
};
match msgtype {
HELLOREPLY => {
handhsake_history.add_new_handshake(peer_pubkey, "".to_string(), ip);
}
_ => {}
}
let signature: [u8; SIGNATURE] = received_message let signature: [u8; SIGNATURE] = received_message
[LENGTH + msg_length..LENGTH + msg_length + SIGNATURE] [LENGTH + msg_length..LENGTH + msg_length + SIGNATURE]
.try_into() .try_into()
@@ -217,6 +225,22 @@ pub fn parse_message(
} }
} }
} }
ROOTREPLY => {
let ilength = u16::from_be_bytes(length_bytes);
println!("name received length: {}", ilength);
if let Some(peerinfo) = handhsake_history.get_peer_info_ip(ip.to_string()) {
if !verify_signature(peerinfo.pubkey, &received_message) {
println!(
"incorrect signature from given peer: {}, ignoring message of type {} with id {}",
&peerinfo.username, received_message[ID], id
);
return None;
} else {
println!("signature verified");
}
}
}
_ => {} _ => {}
} }
@@ -268,8 +292,18 @@ pub fn parse_message(
// //
// ajoute a la liste des peers handshake // ajoute a la liste des peers handshake
HELLOREPLY => { HELLOREPLY => {
// ajoute a la liste des peers handshake // ajoute l'username a la liste des peers handshake
handhsake_history.add_new_handshake(hash, username, ip); let received_length = u16::from_be_bytes(
received_message[TYPE..LENGTH]
.try_into()
.expect("incorrect size"),
);
let received_username =
&received_message[LENGTH + EXTENSIONS..LENGTH + received_length as usize];
handhsake_history.update_peer_info(
ip.to_string(),
String::from_utf8(received_username.to_vec()).expect("invalid conversion"),
);
// verifie s'il faut renvoyer un root request // verifie s'il faut renvoyer un root request
let guard = messages_list.lock().expect("Échec du verrouillage"); let guard = messages_list.lock().expect("Échec du verrouillage");
let res = guard.get(&id); let res = guard.get(&id);
@@ -300,15 +334,21 @@ pub fn parse_message(
// //
ROOTREPLY => { ROOTREPLY => {
// recuperer le pseudo du peers ayant repondu // recuperer le pseudo du peers ayant repondu
let peers_exist = handhsake_history.get_peer_info_ip(ip.to_string());
// envoyer le hash a la gui match peers_exist {
let received_hash = String::from_utf8(received_message[LENGTH..(32 + LENGTH)].to_vec()); Some(peerinfo) => {
match received_hash { // envoyer le hash a la gui
Ok(hash) => { let received_hash: NodeHash = received_message[LENGTH..(32 + LENGTH)]
cmd_tx_clone.send(NetworkEvent::FileTreeRootReceived()); .try_into()
.expect("incorrect size");
let res = cmd_tx_clone.send(NetworkEvent::FileTreeRootReceived(
peerinfo.username.clone(),
received_hash,
));
println!("file tree sent")
} }
Err(e) => { None => {
println!("{}", e); eprintln!("no peers found");
} }
} }
} }

View File

@@ -219,8 +219,11 @@ impl MultipleSenders {
}; };
if let Some(sender) = self.senders.get(channel_idx) { if let Some(sender) = self.senders.get(channel_idx) {
let _ = sender.send(msg_to_send); let _ = sender.send(msg_to_send);
let mut guard = messages_list.lock().expect("Échec du verrouillage"); }
let id = i32::from_be_bytes(data[..4].try_into().unwrap()); if !is_resp_to_server_handshake {
let mut guard = messages_list.lock().unwrap();
let message_id: [u8; 4] = data[0..4].try_into().expect("size error");
let id = i32::from_be_bytes(message_id);
guard.insert(id, EventType::SendRootRequest); guard.insert(id, EventType::SendRootRequest);
} }
} }
@@ -257,39 +260,41 @@ impl MultipleSenders {
} }
}); });
}*/ }*/
}
pub fn start_receving_thread(
shared_data: &P2PSharedData, pub fn start_receving_thread(
cmd_tx: crossbeam_channel::Sender<NetworkEvent>, shared_data: &P2PSharedData,
) { cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
let sock_clone = shared_data.socket(); handshake_history: &Arc<Mutex<HandshakeHistory>>,
let cryptopair_clone = shared_data.cryptopair(); ) {
let senders_clone = shared_data.senders(); let sock_clone = shared_data.socket();
let messages_clone = shared_data.messages_list(); let cryptopair_clone = shared_data.cryptopair();
let servername_clone = shared_data.servername(); let senders_clone = shared_data.senders();
let handshake_history = HandshakeHistory::new(); let messages_clone = shared_data.messages_list();
thread::spawn(move || { let servername_clone = shared_data.servername();
let mut buf = [0u8; 1024];
loop { let handshake_clone = handshake_history.clone();
match sock_clone.recv_from(&mut buf) { thread::spawn(move || {
Ok((amt, src)) => { let mut buf = [0u8; 1024];
let received_data = buf[..amt].to_vec(); loop {
match sock_clone.recv_from(&mut buf) {
println!("Reçu {} octets de {}: {:?}", amt, src, received_data); Ok((amt, src)) => {
handle_recevied_message( let received_data = buf[..amt].to_vec();
&messages_clone,
&received_data, println!("Reçu {} octets de {}: {:?}", amt, src, received_data);
&cryptopair_clone, handle_recevied_message(
&senders_clone, &messages_clone,
&servername_clone, &received_data,
cmd_tx.clone(), &cryptopair_clone,
src, &senders_clone,
handshake_history, &servername_clone,
); cmd_tx.clone(),
} src,
Err(e) => eprintln!("Erreur de réception: {}", e), &handshake_clone,
} );
} }
}); Err(e) => eprintln!("Erreur de réception: {}", e),
} }
}
});
} }

View File

@@ -3,7 +3,7 @@
use std::{ use std::{
collections::{HashMap, VecDeque}, collections::{HashMap, VecDeque},
net::{AddrParseError, SocketAddr}, net::{AddrParseError, Ipv4Addr, SocketAddr},
ops::Add, ops::Add,
process::Command, process::Command,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
@@ -21,7 +21,7 @@ use p256::ecdsa::VerifyingKey;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PeerInfo { pub struct PeerInfo {
username: String, pub username: String,
pub pubkey: VerifyingKey, pub pubkey: VerifyingKey,
pub ip: SocketAddr, pub ip: SocketAddr,
} }
@@ -82,6 +82,27 @@ impl HandshakeHistory {
}); });
} }
pub fn update_peer_info(&mut self, ip: String, username: String) {
let peerinfo = self.get_peer_info_ip(ip.clone());
match peerinfo {
Some(peer_info) => match ip.parse::<SocketAddr>() {
Ok(addr) => {
let new_peer_info = PeerInfo {
username: username.clone(),
pubkey: peer_info.pubkey,
ip: addr,
};
self.ip_k_peerinfo_v.insert(ip, new_peer_info.clone());
self.username_k_peerinfo_v.insert(username, new_peer_info);
}
Err(e) => eprintln!("parse error: {}", e),
},
None => {
eprintln!("no peer info found in hashmap")
}
}
}
pub fn add_new_handshake(&mut self, hash: VerifyingKey, username: String, ip: SocketAddr) { pub fn add_new_handshake(&mut self, hash: VerifyingKey, username: String, ip: SocketAddr) {
let peerinfo = PeerInfo { let peerinfo = PeerInfo {
username: username.clone(), username: username.clone(),
@@ -104,8 +125,8 @@ pub fn perform_discover(
) { ) {
// first, sends handshake // first, sends handshake
if hash == "root" { if hash == "root" {
perform_handshake(sd, username, server_ip, event_tx); perform_handshake(sd, username, server_ip, event_tx, false);
if let Some(data) = construct_message( /*if let Some(data) = construct_message(
messages_structure::ROOTREQUEST, messages_structure::ROOTREQUEST,
Vec::new(), Vec::new(),
generate_id(), generate_id(),
@@ -115,7 +136,7 @@ pub fn perform_discover(
sd.senders_ref() sd.senders_ref()
.send_via(0, data, peerinfo.ip.to_string(), false); .send_via(0, data, peerinfo.ip.to_string(), false);
} }
} }*/
} else { } else {
// envoyer un datum request // envoyer un datum request
} }

View File

@@ -75,13 +75,14 @@ pub async fn perform_handshake(
username: String, username: String,
ip: String, ip: String,
event_tx: Sender<NetworkEvent>, event_tx: Sender<NetworkEvent>,
is_server_handshake: bool,
) { ) {
println!("username: {}, ip: {}", username.clone(), ip.clone());
let crypto_pair = sd.cryptopair_ref(); let crypto_pair = sd.cryptopair_ref();
let senders = sd.senders_ref(); let senders = sd.senders_ref();
let messages_list = sd.messages_list_ref(); let messages_list = sd.messages_list_ref();
let id = generate_id(); let id = generate_id();
let server_addr_query = get_socket_address(username.clone(), ip.clone()); let server_addr_query = get_socket_address(username.clone(), ip.clone());
match server_addr_query.await { match server_addr_query.await {
Ok(sockaddr_bytes) => { Ok(sockaddr_bytes) => {
match String::from_utf8(sockaddr_bytes.to_vec()) { match String::from_utf8(sockaddr_bytes.to_vec()) {
@@ -100,7 +101,7 @@ pub async fn perform_handshake(
0, 0,
handshake_message, handshake_message,
first.to_string(), first.to_string(),
false, is_server_handshake,
messages_list, messages_list,
); );
} }