use crate::cryptographic_signature::{CryptographicSignature, sign_message}; const ID: usize = 4; const TYPE: usize = 5; const LENGTH: usize = 7; const EXTENSIONS: usize = 4; const SIGNATURE: usize = 64; pub(crate) const PING: u8 = 0; pub(crate) const OK: u8 = 128; pub(crate) const ERROR: u8 = 129; pub(crate) const HELLO: u8 = 1; pub(crate) const HELLOREPLY: u8 = 130; pub(crate) const ROOTREQUEST: u8 = 2; pub(crate) const ROOTREPLY: u8 = 131; pub(crate) const DATUMREQUEST: u8 = 3; pub(crate) const NODATUM: u8 = 133; pub(crate) const DATUM: u8 = 132; pub(crate) const NATTRAVERSALREQUEST: u8 = 4; pub(crate) const NATTRAVERSALREQUEST2: u8 = 5; pub fn construct_message( msgtype: u8, payload: Vec, id: i32, crypto_pair: &CryptographicSignature, ) -> Option> { let mut message = Vec::new(); // ID // type message.extend_from_slice(&id.to_be_bytes()); message.push(msgtype); match msgtype { HELLO | HELLOREPLY => { // length let a = payload.len() as u16; println!("payload size:{}", a); message.extend_from_slice(&a.to_be_bytes()); message.extend_from_slice(&payload); let signature = sign_message(crypto_pair, &message); return Some(signature); } PING | OK | ROOTREQUEST => { message.extend_from_slice(&0u16.to_be_bytes()); return Some(message); } ERROR | DATUMREQUEST => { let a = payload.len() as u16; println!("payload size:{}", a); message.extend_from_slice(&a.to_be_bytes()); message.extend_from_slice(&payload); return Some(message); } ROOTREPLY | NODATUM | DATUM | NATTRAVERSALREQUEST => { println!("payload:{:?}", &payload); let a = payload.len() as u16; println!("payload size:{}", a); message.extend_from_slice(&a.to_be_bytes()); message.extend_from_slice(&payload); println!("payload:{:?}", &message); let signature = sign_message(crypto_pair, &message); message.extend_from_slice(&signature); println!("message_to_send_len:{}", &message.len()); return Some(signature); } _ => {} } None } pub struct UDPMessage { id: u32, msg_type: u8, length: u16, body: Vec, signature: Vec, } pub struct HandshakeMessage { pub id: u32, msg_type: u8, length: u16, extensions: u32, pub name: Vec, pub signature: Vec, } pub struct NatTraversal {} impl UDPMessage { pub fn ping(id: u32) -> UDPMessage { UDPMessage { id: id, msg_type: 0, length: 0, body: vec![0; 985], signature: vec![0; 32], } } pub fn error(id: u32) -> UDPMessage { UDPMessage { id: id, msg_type: 129, length: 0, body: vec![0; 985], signature: vec![0; 32], } } pub fn parse(received_message: Vec) -> UDPMessage { let id_bytes: [u8; 4] = received_message[0..4] .try_into() .expect("Taille incorrecte"); let length_bytes: [u8; 2] = received_message[5..7] .try_into() .expect("Taille incorrecte"); let msg_length = u16::from_be_bytes(length_bytes); let name_bytes = &received_message[7..msg_length as usize + 8]; let signature_bytes = &received_message[msg_length as usize + 8..msg_length as usize + 9 + 32]; UDPMessage { id: u32::from_be_bytes(id_bytes), msg_type: received_message[4], length: u16::from_be_bytes(length_bytes), body: name_bytes.to_vec(), signature: signature_bytes.to_vec(), } } pub fn display(&self) { println!("ID: {:?}", self.id); println!("Message Type: {}", self.msg_type); println!("Length: {:?}", self.length); let good_length = usize::min(self.length as usize, 985); println!("name: {:?}", &self.body[..good_length]); println!("Signature: {:?}", self.signature); } } impl HandshakeMessage { pub fn display(&self) { println!("ID: {:?}", self.id); println!("Message Type: {}", self.msg_type); println!("Length: {:?}", self.length); println!("extensions: {:?}", self.extensions); println!("name: {:?}", &self.name[..(self.length - 4) as usize]); println!("Signature: {:?}", self.signature); } pub fn hello(id: u32, length: u16, username: String) -> HandshakeMessage { let name_vec = username.trim_end_matches(char::from(0)).as_bytes().to_vec(); HandshakeMessage { id: id, msg_type: 1, length: length, extensions: 0, name: name_vec, signature: vec![0; 64], } } pub fn helloReply(id: u32, length: u16, username: String) -> HandshakeMessage { let name_vec = username.trim_end_matches(char::from(0)).as_bytes().to_vec(); HandshakeMessage { id: id, msg_type: 130, length: length, extensions: 0, name: name_vec, signature: vec![0; 64], } } pub fn serialize(&self) -> Vec { let mut out = Vec::with_capacity(4 + 1 + 2 + 4 + self.name.len() + self.signature.len()); // id: u32 little-endian out.extend_from_slice(&self.id.to_be_bytes()); // msg_type: u8 out.push(self.msg_type); out.extend_from_slice(&self.length.to_be_bytes()); out.extend_from_slice(&self.extensions.to_be_bytes()); out.extend_from_slice(&self.name); out.extend_from_slice(&self.signature); out } pub fn parse(received_message: Vec) -> HandshakeMessage { let id_bytes: [u8; 4] = received_message[0..4] .try_into() .expect("Taille incorrecte"); let length_bytes: [u8; 2] = received_message[5..7] .try_into() .expect("Taille incorrecte"); let msg_length = u16::from_be_bytes(length_bytes); let extensions_bytes: [u8; 4] = received_message[7..11] .try_into() .expect("Taille incorrecte"); let name_bytes = &received_message[11..(11 + msg_length - 4) as usize]; let signature_bytes = &received_message[(11 + msg_length - 4) as usize..(11 + msg_length - 4 + 64) as usize]; HandshakeMessage { id: u32::from_be_bytes(id_bytes), msg_type: received_message[4], length: u16::from_be_bytes(length_bytes), extensions: u32::from_be_bytes(extensions_bytes), name: name_bytes.to_vec(), signature: signature_bytes.to_vec(), } } } #[cfg(test)] mod tests { // Note this useful idiom: importing names from outer (for mod tests) scope. use super::*; /* /// creates an handshake message #[tokio::test] async fn creating_handshake_msg() { let username = String::from("charlie_kirk"); let handshake = HandshakeMessage::hello(0, 12, username); handshake.display(); } /// parses an handshake message #[tokio::test] async fn parse_handshakemessage() { let username = String::from("charlie_kirk"); let handshake = HandshakeMessage::hello(0, 12, username); let ser = handshake.serialize(); let parsed = HandshakeMessage::parse(ser); handshake.display(); parsed.display(); }*/ }