pub use crate::{debug, error, info, trace, warn}; pub mod handlers; mod message_reader; pub mod peer; pub mod server; pub use handlers::{Handlers, MessageHandler}; pub use message_reader::MessageReader; use std::str; #[derive(Debug, PartialEq, Eq)] #[allow(dead_code)] pub enum MessageType { Server, Peer, PeerInit, Distributed, } #[derive(Debug)] pub struct Error(String); impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) } } impl std::error::Error for Error {} #[derive(Debug, PartialEq, Eq, Clone)] pub struct Message { data: Vec, pointer: usize, } impl Default for Message { fn default() -> Self { Self::new() } } impl Message { #[must_use] pub const fn new() -> Self { Self { data: Vec::new(), pointer: 0, } } pub fn print_hex(&self) { const BYTES_PER_LINE: usize = 16; let data = &self.data; let chunks = data.chunks(BYTES_PER_LINE); for (i, chunk) in chunks.enumerate() { // Print the offset print!("{:04x} ", i * BYTES_PER_LINE); // Print the hexadecimal part for j in 0..BYTES_PER_LINE { if j < chunk.len() { print!("{:02x} ", chunk[j]); } else { print!(" "); } // Add extra space in the middle if j == 7 { print!(" "); } } print!(" "); // Print the ASCII part let mut i = 0; for &byte in chunk { i += 1; if byte.is_ascii_graphic() || byte.is_ascii_whitespace() { print!("{}", byte as char); } else { print!("."); } if i == 8 { print!(" "); } } trace!(""); } } #[allow(dead_code)] #[must_use] pub fn get_message_code_u32(&self) -> u32 { if self.data.len() < 8 { return 0; } u32::from_le_bytes(self.data[4..8].try_into().unwrap()) } #[must_use] pub fn get_message_code(&self) -> u8 { if self.data.len() <= 4 { return 0; } self.data[4] } #[must_use] pub fn get_message_code_send(&self) -> u8 { if self.data.is_empty() { return 0; } self.data[0] } #[must_use] pub const fn new_with_data(data: Vec) -> Self { Self { data, pointer: 0 } } #[allow(dead_code)] pub const fn reset_pointer(&mut self) { self.pointer = 0; } pub const fn set_pointer(&mut self, pointer: usize) { self.pointer = pointer; } pub const fn get_pointer(&mut self) -> usize { self.pointer } pub const fn get_size(&mut self) -> usize { self.data.len() } #[must_use] pub fn get_data(&self) -> Vec { self.data.clone() } #[must_use] pub fn get_slice(&self, from: usize, to: usize) -> Vec { self.data[from..to].to_vec() } /// gets buffer with the message length prepended #[must_use] pub fn get_buffer(&self) -> Vec { let mut b = vec![0u8; 4]; let length = self.data.len() as u32; b[0..4].copy_from_slice(&length.to_le_bytes()); let mut combined = b; combined.extend(&self.data); combined } pub fn read_string(&mut self) -> String { if self.pointer + 4 > self.data.len() { self.pointer = self.data.len(); return String::new(); } let size = u32::from_le_bytes([ self.data[self.pointer], self.data[self.pointer + 1], self.data[self.pointer + 2], self.data[self.pointer + 3], ]) as usize; self.pointer += 4; // A truncated / malformed length field from an untrusted peer must not // slice past the buffer end; treat it as an empty string and consume // the rest of the message. if self.pointer + size > self.data.len() { self.pointer = self.data.len(); return String::new(); } let data = &self.data[self.pointer..self.pointer + size]; self.pointer += size; match String::from_utf8(data.to_vec()) { Ok(s) => s, Err(_) => data.iter().map(|&b| b as char).collect::(), } } pub fn read_int8(&mut self) -> u8 { if self.pointer >= self.data.len() { return 0; } let val = self.data[self.pointer]; self.pointer += 1; val } #[allow(dead_code)] pub fn read_int64(&mut self) -> u64 { if self.pointer + 8 > self.data.len() { return 0; } let val = u64::from_le_bytes([ self.data[self.pointer], self.data[self.pointer + 1], self.data[self.pointer + 2], self.data[self.pointer + 3], self.data[self.pointer + 4], self.data[self.pointer + 5], self.data[self.pointer + 6], self.data[self.pointer + 7], ]); self.pointer += 8; val } pub fn read_raw_byte(&mut self) -> Vec { if self.pointer + 4 > self.data.len() { return vec![]; } let val = vec![ self.data[self.pointer], self.data[self.pointer + 1], self.data[self.pointer + 2], self.data[self.pointer + 3], ]; self.pointer += 4; val } pub fn read_int32(&mut self) -> u32 { if self.pointer + 4 > self.data.len() { return 0; } let val = u32::from_le_bytes([ self.data[self.pointer], self.data[self.pointer + 1], self.data[self.pointer + 2], self.data[self.pointer + 3], ]); self.pointer += 4; val } pub fn read_bool(&mut self) -> bool { if self.pointer >= self.data.len() { return false; } let val = self.data[self.pointer] == 1; self.pointer += 1; val } pub fn write_string(&mut self, val: &str) -> &mut Self { let length = val.len() as u32; self.data.extend_from_slice(&length.to_le_bytes()); self.data.extend_from_slice(val.as_bytes()); self } pub fn write_int8(&mut self, value: u8) -> &mut Self { self.data.extend_from_slice(&value.to_le_bytes()); self } pub fn write_int32(&mut self, value: u32) -> &mut Self { self.data.extend_from_slice(&value.to_le_bytes()); self } #[allow(dead_code)] pub fn write_int64(&mut self, value: u64) -> &mut Self { self.data.extend_from_slice(&value.to_le_bytes()); self } pub fn write_raw_bytes(&mut self, value: Vec) -> &mut Self { self.data.extend_from_slice(&value); self } pub fn write_bool(&mut self, value: bool) -> &mut Self { self.data.push(u8::from(value)); self } #[allow(dead_code)] pub fn write_raw_hex_string(&mut self, val: &str) -> &mut Self { let mut b = Vec::new(); for i in (0..val.len()).step_by(2) { let byte_str = &val[i..i + 2]; let byte = u8::from_str_radix(byte_str, 16).expect("Invalid hex string"); b.push(byte); } self.data.extend_from_slice(&b); self.pointer += b.len(); self } pub fn get_message_name( &self, msg_type: MessageType, code: u32, ) -> Result<&str, Error> { match msg_type { MessageType::Server => match code { 1 => Ok("Login"), 2 => Ok("SetWaitPort"), 3 => Ok("GetPeerAddress"), 5 => Ok("WatchUser"), 6 => Ok("UnwatchUser"), 7 => Ok("GetUserStatus"), 13 => Ok("SayChatroom"), 14 => Ok("JoinRoom"), 15 => Ok("LeaveRoom"), 18 => Ok("ConnectToPeer"), 22 => Ok("MessageUser"), 23 => Ok("MessageAcked"), 26 => Ok("FileSearch"), 28 => Ok("SetStatus"), 32 => Ok("ServerPing"), 35 => Ok("SharedFoldersFiles"), 36 => Ok("GetUserStats"), 41 => Ok("Relogged"), 42 => Ok("UserSearch"), 64 => Ok("RoomList"), 69 => Ok("PrivilegedUsers"), 71 => Ok("HaveNoParent"), 83 => Ok("ParentMinSpeed"), 84 => Ok("ParentSpeedRatio"), 92 => Ok("CheckPrivileges"), 93 => Ok("EmbeddedMessage"), 100 => Ok("AcceptChildren"), 102 => Ok("PossibleParents"), 104 => Ok("WishlistInterval"), 160 => Ok("ExcludedSearchPhrases"), 1001 => Ok("CantConnectToPeer"), _ => Err(Error(format!("Unknown server message code: {code}"))), }, MessageType::PeerInit => match code { 0 => Ok("PierceFireWall"), 1 => Ok("PeerInit"), _ => Err(Error(format!( "Unknown peer init message code: {code}" ))), }, MessageType::Peer => match code { 1 => Ok("PeerInit"), 4 => Ok("GetShareFileList"), 5 => Ok("SharedFileListResponse"), 9 => Ok("FileSearchResponse"), 15 => Ok("UserInfoRequest"), 16 => Ok("UserInfoResponse"), 36 => Ok("FolderContentsRequest"), 37 => Ok("FolderContentsResponse"), 40 => Ok("TransferRequest"), 41 => Ok("TransferResponse"), 43 => Ok("QueueUpload"), 44 => Ok("PlaceInQueueResponse"), 46 => Ok("UploadFailed"), 50 => Ok("UploadDenied"), 51 => Ok("PlaceInQueueRequest"), _ => Err(Error(format!("Unknown peer message code: {code}"))), }, MessageType::Distributed => match code { 3 => Ok("SearchRequest"), 4 => Ok("BranchLevel"), 5 => Ok("BranchRoot"), 93 => Ok("EmbeddedMessage"), _ => Err(Error(format!( "Unknown distributed message code: {code}" ))), }, } } } #[test] fn test_get_buffer() { let message = Message::new_with_data( [ 26, 0, 0, 0, 219, 178, 47, 28, 11, 0, 0, 0, 116, 104, 101, 32, 119, 101, 101, 107, 101, 110, 100, ] .to_vec(), ); assert_eq!( message.get_buffer(), [ 23, 0, 0, 0, 26, 0, 0, 0, 219, 178, 47, 28, 11, 0, 0, 0, 116, 104, 101, 32, 119, 101, 101, 107, 101, 110, 100, ] .to_vec() ); let message = Message::new_with_data( [ 1, 0, 0, 0, 20, 0, 0, 0, 105, 110, 115, 97, 110, 101, 95, 105, 110, 95, 116, 104, 101, 95, 98, 114, 97, 105, 110, 50, 8, 0, 0, 0, 49, 51, 51, 55, 53, 49, 51, 55, 160, 0, 0, 0, 32, 0, 0, 0, 50, 101, 100, 102, 53, 49, 100, 48, 51, 55, 57, 52, 51, 55, 56, 102, 56, 98, 98, 54, 51, 49, 48, 100, 52, 54, 48, 99, 50, 50, 98, 49, 17, 0, 0, 0, ] .to_vec(), ); assert_eq!( message.get_buffer(), [ 84, 0, 0, 0, 1, 0, 0, 0, 20, 0, 0, 0, 105, 110, 115, 97, 110, 101, 95, 105, 110, 95, 116, 104, 101, 95, 98, 114, 97, 105, 110, 50, 8, 0, 0, 0, 49, 51, 51, 55, 53, 49, 51, 55, 160, 0, 0, 0, 32, 0, 0, 0, 50, 101, 100, 102, 53, 49, 100, 48, 51, 55, 57, 52, 51, 55, 56, 102, 56, 98, 98, 54, 51, 49, 48, 100, 52, 54, 48, 99, 50, 50, 98, 49, 17, 0, 0, 0, ] .to_vec() ); } #[test] fn test_read_string() { let data = vec![ 5, 0, 0, 0, // size = 5 72, 101, 108, 108, 111, // "Hello" ]; let mut test_data = Message::new_with_data(data); assert_eq!(test_data.read_string(), "Hello"); } // Robustness against malformed / truncated network input. A remote server or // peer is untrusted and can send a message whose declared field lengths exceed // the bytes actually present; parsing must not panic (which would unwind out of // the actor job and permanently kill a thread-pool worker). #[test] fn read_string_with_oversized_length_does_not_panic() { // size = 0xFFFFFFFF but no payload bytes follow. let mut msg = Message::new_with_data(vec![255, 255, 255, 255]); assert_eq!(msg.read_string(), ""); } #[test] fn read_string_with_truncated_payload_does_not_panic() { // size = 10 but only 2 payload bytes present. let mut msg = Message::new_with_data(vec![10, 0, 0, 0, 65, 66]); assert_eq!(msg.read_string(), ""); } #[test] fn read_string_with_missing_length_prefix_does_not_panic() { // Only 2 bytes: not even a full 4-byte length prefix. let mut msg = Message::new_with_data(vec![1, 2]); assert_eq!(msg.read_string(), ""); } #[test] fn get_message_code_on_short_message_does_not_panic() { // A zero-length frame drains to exactly the 4-byte length prefix, leaving // no room for a message code at data[4]. let msg = Message::new_with_data(vec![0, 0, 0, 0]); assert_eq!(msg.get_message_code(), 0); assert_eq!(msg.get_message_code_u32(), 0); let empty = Message::new_with_data(vec![]); assert_eq!(empty.get_message_code_send(), 0); } #[test] fn read_int_primitives_are_bounds_checked() { let mut msg = Message::new_with_data(vec![1, 2]); assert_eq!(msg.read_int64(), 0); let mut msg = Message::new_with_data(vec![]); assert_eq!(msg.read_int8(), 0); assert!(!msg.read_bool()); } #[test] fn test_read_string_2() { let data = vec![ 50, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 81, 170, 162, 77, 32, 0, 0, 0, 101, 102, 99, 97, 51, 52, 102, 99, 52, 99, 56, 98, 101, 56, 98, 55, 101, 102, 51, 56, 97, 102, 50, 54, 50, 52, 100, 101, 53, 52, 54, 52, 0, ]; let mut test_data = Message::new_with_data(data); test_data.set_pointer(9); assert_eq!(test_data.read_string(), ""); } #[test] fn test_read_string_invalid_utf82() { let data = [ 128, 0, 0, 0, 103, 58, 92, 100, 105, 115, 107, 52, 92, 115, 101, 109, 105, 114, 97, 109, 105, 115, 92, 99, 104, 105, 108, 108, 44, 32, 100, 117, 98, 44, 32, 100, 111, 119, 110, 98, 101, 97, 116, 44, 32, 97, 109, 98, 105, 101, 110, 116, 92, 118, 97, 114, 105, 111, 117, 115, 32, 97, 114, 116, 105, 115, 116, 115, 92, 112, 111, 116, 116, 32, 104, 101, 97, 100, 122, 32, 45, 32, 100, 111, 112, 101, 32, 115, 109, 111, 107, 105, 110, 180, 98, 101, 97, 116, 115, 32, 107, 98, 115, 32, 49, 50, 56, 32, 49, 57, 57, 54, 92, 48, 53, 32, 45, 32, 98, 108, 117, 101, 32, 116, 114, 97, 105, 110, 46, 109, 112, 51, ] .to_vec(); let mut test_data = Message::new_with_data(data); let str = test_data.read_string(); assert_eq!( str, r"g:\disk4\semiramis\chill, dub, downbeat, ambient\various artists\pott headz - dope smokin“beats kbs 128 1996\05 - blue train.mp3" ); }