use crate::{ NetworkEvent, cryptographic_signature::{ CryptographicSignature, get_peer_key, sign_message, verify_signature, }, messages_channels::MultipleSenders, messages_structure::construct_message, registration, }; use std::{collections::HashMap, net::SocketAddr}; use std::{ net::IpAddr, sync::{Arc, Mutex}, }; pub enum EventType { ServerHelloReply, PeerHelloReply, PeerHello, } const ID: usize = 4; const TYPE: usize = 5; 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 fn handle_recevied_message( messages_list: &Arc>>, recevied_message: &Vec, crypto_pair: &CryptographicSignature, socket_addr: &SocketAddr, senders: &MultipleSenders, server_name: &String, cmd_tx: crossbeam_channel::Sender, ip: SocketAddr, ) { if recevied_message.len() < 4 { return; } // Basic safety check let message_id: [u8; 4] = recevied_message[0..4].try_into().expect("size error"); let id = i32::from_be_bytes(message_id); let mut is_resp_to_server_handshake = false; if recevied_message[4] == HELLO { let length_bytes: [u8; 2] = recevied_message[TYPE..LENGTH] .try_into() .expect("Taille incorrecte"); let msg_length = u16::from_be_bytes(length_bytes) as usize; let ilength = u16::from_be_bytes(length_bytes); let received_name = &recevied_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize]; let name = String::from_utf8(received_name.to_vec()).expect("wrong name"); if name.clone() == server_name.clone() { is_resp_to_server_handshake = true; } } let resp = parse_message(recevied_message.to_vec(), id, crypto_pair, cmd_tx, ip); match resp { None => {} Some(resp_msg) => { println!("msg_sent:{:?}", resp_msg); senders.send_via(0, resp_msg, ip.to_string(), is_resp_to_server_handshake); } } // Lock the mutex to access the HashMap /*let list = messages_list.lock().unwrap(); let eventtype = list.get(&id); // Clone the enum so we can release the lock if needed match eventtype { Some(EventType::ServerHelloReply) => { /*registration::register_ip_addresses( crypto_pair, socket_addr.to_string(), senders, &messages_list, // Pass the mutable reference inside the lock 546, );*/ } Some(_) => print!("Not implemented"), None => { let message_type = recevied_message[4]; // Handle handshake if message_type == 1 { let mut resp_to_serv = false; println!("verify the signature"); let parsed_received_message = HandshakeMessage::parse(recevied_message.to_vec()); let received_name = String::from_utf8(parsed_received_message.name).expect("error"); let peer_pubkey = tokio::runtime::Runtime::new() .unwrap() .block_on(get_peer_key(&received_name)) .expect("failed to retrieve public key"); if received_name == server_name.to_string() { resp_to_serv = true; } if !verify_signature(peer_pubkey, recevied_message) { println!( "incorrect signature from given peer: {}, ignoring message {}", &received_name, id ); } else { // verify if this is a server handshake request let username_size = crypto_pair.username.len(); let hello_handshake = HandshakeMessage::helloReply( id as u32, username_size as u16 + 4, crypto_pair.username.clone(), ); //HandshakeMessage::display(&hello_handshake); let hello_handshake_serialized = hello_handshake.serialize(); let message_signed = sign_message(crypto_pair, &hello_handshake_serialized); senders.send_via(0, message_signed, socket_addr.to_string(), resp_to_serv); let mut list = messages_list.lock().expect("Failed to lock messages_list"); match list.get(&id) { Some(_) => { list.remove(&id); } None => { list.insert(id, EventType::ServerHelloReply); } } } } print!("Message not found for ID: {}", id) } }*/ } pub fn parse_message( received_message: Vec, id: i32, crypto_pair: &CryptographicSignature, cmd_tx: crossbeam_channel::Sender, ip: SocketAddr, ) -> Option> { let cmd_tx_clone = cmd_tx.clone(); let id_bytes: [u8; 4] = received_message[0..ID] .try_into() .expect("Taille incorrecte"); let msgtype = received_message[ID]; let length_bytes: [u8; 2] = received_message[TYPE..LENGTH] .try_into() .expect("Taille incorrecte"); let msg_length = u16::from_be_bytes(length_bytes) as usize; // verify signature match msgtype { HELLO | HELLOREPLY | ROOTREPLY | NODATUM | NATTRAVERSALREQUEST | NATTRAVERSALREQUEST2 => { let ilength = u16::from_be_bytes(length_bytes); println!("name received length: {}", ilength); let received_name = &received_message[LENGTH + EXTENSIONS..LENGTH + ilength as usize]; let received_username = String::from_utf8(received_name.to_vec()); match received_username { Ok(username) => { let peer_pubkey = tokio::runtime::Runtime::new() .unwrap() .block_on(get_peer_key(&username)) .expect("failed to retrieve public key"); let signature: [u8; SIGNATURE] = received_message [LENGTH + msg_length..LENGTH + msg_length + SIGNATURE] .try_into() .expect("Taille incorrecte"); if !verify_signature(peer_pubkey, &received_message) { println!( "incorrect signature from given peer: {}, ignoring message of type {} with id {}", &username, received_message[ID], id ); return None; } } Err(e) => { println!("incorrect name: {}", e); return None; } } } _ => {} } // Message handling let mut constructed_message: Option> = None; match msgtype { // PING // // envoie un OK PING => { constructed_message = construct_message(OK, Vec::new(), id, crypto_pair); } // // OK // // rien ? // si NATTRAVERSALREQUEST alors // // ERROR // // affiche un msg d'erreur ERROR => { if let Ok(err_received) = 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)); } else { let err_msg = format!("Error received from peer {} : N/A", ip,); let _ = cmd_tx_clone.send(NetworkEvent::Error(err_msg)); } } // HELLO // // envoie une hello reply // HELLO => { let mut payload = Vec::new(); payload.extend_from_slice(&0u32.to_be_bytes()); payload.extend_from_slice(&crypto_pair.username.clone().as_bytes()); let helloreply = construct_message(HELLOREPLY, payload, id, crypto_pair); return helloreply; } // HELLOREPLY // // // ajoute a la liste des peers handshake HELLOREPLY => {} // // ROOTREQUEST // // envoie un root reply // // ROOTREPLY // // envoie un datum request // // DATUMREQUEST // // envoie le datum // // NODATUM // // affiche un msg d'erreur // // DATUM // // parcourt le directory recu ou le big directory et renvoie une DATUMREQUEST pour chaque // directory ou big directory lu // // NATTRAVERSALREQUEST // // repond OK et envoie un NATTRAVERSALREQUEST2 au pair B // // NATTRAVERSALREQUEST2 // // envoie OK à S puis envoie un ping à S // PING // // envoie un OK // // OK // // si NATTRAVERSALREQUEST alors // // ERROR // // affiche un msg d'erreur // // HELLO // // envoie une hello reply // // HELLOREPLY // // envoie un root request // // ROOTREQUEST // // envoie un root reply // // ROOTREPLY // // envoie un datum request // // DATUMREQUEST // // envoie le datum // // NODATUM // // affiche un msg d'erreur // // DATUM // // parcourt le directory recu ou le big directory et renvoie une DATUMREQUEST pour chaque // directory ou big directory lu // // NATTRAVERSALREQUEST // // repond OK et envoie un NATTRAVERSALREQUEST2 au pair B // // NATTRAVERSALREQUEST2 // // envoie OK à S puis envoie un ping à S _ => return None, } constructed_message }