Files
p2p/client-network/src/message_handling.rs
TIBERGHIEN corentin 92f38c9c12 fix name length issue
2026-01-10 20:34:51 +01:00

334 lines
10 KiB
Rust

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<Mutex<HashMap<i32, EventType>>>,
recevied_message: &Vec<u8>,
crypto_pair: &CryptographicSignature,
socket_addr: &SocketAddr,
senders: &MultipleSenders,
server_name: &String,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
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<u8>,
id: i32,
crypto_pair: &CryptographicSignature,
cmd_tx: crossbeam_channel::Sender<NetworkEvent>,
ip: SocketAddr,
) -> Option<Vec<u8>> {
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<Vec<u8>> = 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
}