pub struct UDPMessage { id: u32, msg_type: u8, length: u16, body: Vec, signature: Vec, } pub struct HandshakeMessage { id: u32, msg_type: u8, length: u16, extensions: u32, name: Vec, signature: Vec, } 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..12 + msg_length as usize]; let signature_bytes = &received_message[12 + msg_length as usize..(13 + msg_length + 32) 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(); } }