chore: make message handlers and dispatcher generic

This commit is contained in:
michel
2025-01-06 22:49:19 +01:00
committed by Michel de Graaf
parent 766554134d
commit 066ddadaed
26 changed files with 787 additions and 121 deletions
+1 -24
View File
@@ -1,14 +1,8 @@
use std::collections::HashMap;
use crate::{message::Message, server::ServerOperation};
use crate::message::Message;
use std::sync::mpsc::Sender;
use super::server::{
ConnectToPeerHandler, ExcludedSearchPhrasesHandler, FileSearch, LoginHandler, MessageUser,
ParentMinSpeedHandler, ParentSpeedRatioHandler, PrivilegedUsersHandler, RoomListHandler,
WishListIntervalHandler,
};
pub trait MessageHandler<Op> {
fn get_code(&self) -> u8;
fn handle(&self, message: &mut Message, sender: Sender<Op>);
@@ -24,23 +18,6 @@ impl<Op> Handlers<Op> {
}
}
pub fn new_with_server_handlers() -> Self {
let mut handlers = Self::new();
handlers.register_handler(LoginHandler);
handlers.register_handler(RoomListHandler);
handlers.register_handler(ExcludedSearchPhrasesHandler);
handlers.register_handler(PrivilegedUsersHandler);
handlers.register_handler(MessageUser);
handlers.register_handler(WishListIntervalHandler);
handlers.register_handler(ParentMinSpeedHandler);
handlers.register_handler(ParentSpeedRatioHandler);
handlers.register_handler(PrivilegedUsersHandler);
handlers.register_handler(FileSearch);
handlers.register_handler(ConnectToPeerHandler);
handlers
}
/// Register a handler for this particular `Op`.
pub fn register_handler<H>(&mut self, handler: H) -> &mut Self
where
H: 'static + MessageHandler<Op> + Send + Sync,
+57 -45
View File
@@ -1,4 +1,4 @@
use std::str;
use std::{fmt::Display, str};
#[derive(Debug, PartialEq, Clone)]
pub struct Message {
@@ -14,49 +14,49 @@ impl Message {
}
}
// pub fn print_hex(&self) {
// let data = &self.data;
// const BYTES_PER_LINE: usize = 16;
//
// 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 = i + 1;
// if byte.is_ascii_graphic() || byte.is_ascii_whitespace() {
// print!("{}", byte as char);
// } else {
// print!(".");
// }
//
// if i == 8 {
// print!(" ");
// }
// }
//
// println!();
// }
// }
pub fn print_hex(&self) {
let data = &self.data;
const BYTES_PER_LINE: usize = 16;
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 = i + 1;
if byte.is_ascii_graphic() || byte.is_ascii_whitespace() {
print!("{}", byte as char);
} else {
print!(".");
}
if i == 8 {
print!(" ");
}
}
println!();
}
}
//
// pub fn print_hex2(&self) -> String {
// let data = &self.data;
@@ -105,6 +105,7 @@ impl Message {
pub fn get_message_code_u32(&self) -> u32 {
u32::from_le_bytes(self.data[4..8].try_into().unwrap())
}
pub fn get_message_code(&self) -> u8 {
self.data[4]
}
@@ -119,11 +120,22 @@ impl Message {
self.pointer = pointer;
}
// get's the message data
pub fn get_pointer(&mut self) -> usize {
self.pointer
}
pub fn get_size(&mut self) -> usize {
self.data.len()
}
pub fn get_data(&self) -> Vec<u8> {
self.data.clone()
}
pub fn get_slice(&self, from: usize, to: usize) -> Vec<u8> {
self.data[from..to].to_vec()
}
/// gets buffer with the message length prepended
pub fn get_buffer(&self) -> Vec<u8> {
let mut b = vec![0u8; 4];
+1
View File
@@ -1,6 +1,7 @@
pub mod handlers;
pub mod message;
pub mod message_reader;
pub mod peer;
pub mod server;
pub use handlers::*;
+117
View File
@@ -0,0 +1,117 @@
use crate::message::server::MessageFactory;
use crate::message::{Message, MessageHandler};
use crate::peer::PeerOperation;
use flate2::bufread::ZlibDecoder;
use std::collections::HashMap;
use std::io::Read;
use std::sync::mpsc::Sender;
#[derive(Debug)]
pub struct File {
pub username: String,
pub name: String,
pub size: i32,
pub attribs: HashMap<i32, i32>,
}
#[derive(Debug)]
pub struct FileSearch {
pub token: String,
pub files: Vec<File>,
pub slots: i8,
pub speed: i32,
}
fn unzip_buffer(buffer: &[u8]) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut z = ZlibDecoder::new(buffer);
let mut out: Vec<u8> = Vec::new();
z.read_to_end(&mut out).unwrap();
Ok(out)
}
impl FileSearch {
pub fn new_from_message(message: &mut Message) -> Self {
let pointer = message.get_pointer();
let size = message.get_size();
let data: Vec<u8> = message.get_slice(pointer, size);
let deflated = unzip_buffer(&data).unwrap();
let mut message = Message::new_with_data(deflated);
let username = message.read_string();
let token = message.read_raw_hex_str(4);
let n_files = message.read_int32();
let mut files: Vec<File> = Vec::new();
for _ in 0..n_files {
message.read_int8();
let name = message.read_string();
let size = message.read_int32();
message.read_int32();
message.read_string();
let n_attribs = message.read_int32();
let mut attribs: HashMap<i32, i32> = HashMap::new();
for _ in 0..n_attribs {
attribs.insert(message.read_int32(), message.read_int32());
}
files.push(File {
username: username.clone(),
name,
size,
attribs,
});
}
let slots = message.read_int8();
let speed = message.read_int32();
Self {
token,
files,
slots,
speed,
}
}
}
pub struct FileSearchResponse;
impl MessageHandler<PeerOperation> for FileSearchResponse {
fn get_code(&self) -> u8 {
9
}
fn handle(&self, message: &mut Message, sender: Sender<PeerOperation>) {
// println!("{:?}", message);
let file_search = FileSearch::new_from_message(message);
sender
.send(PeerOperation::FileSearchResult(file_search))
.unwrap();
}
}
#[test]
fn test_new_from_message() {
let data: Vec<u8> = [
229, 0, 0, 0, 9, 0, 0, 0, 120, 156, 99, 103, 96, 96, 72, 201, 79, 201, 76, 79, 204, 203,
213, 158, 98, 194, 4, 228, 50, 250, 3, 9, 7, 135, 162, 156, 148, 194, 188, 152, 228, 252,
220, 130, 156, 212, 146, 212, 24, 231, 196, 188, 228, 204, 252, 188, 212, 226, 152, 144,
162, 210, 226, 226, 212, 28, 93, 67, 75, 115, 75, 93, 119, 160, 144, 130, 91, 126, 145, 66,
72, 70, 170, 66, 120, 106, 106, 118, 106, 94, 138, 174, 161, 89, 82, 102, 137, 174, 137,
137, 142, 161, 119, 70, 149, 94, 90, 78, 98, 114, 203, 175, 243, 32, 163, 193, 128, 25,
100, 7, 16, 23, 0, 9, 22, 32, 237, 178, 134, 129, 129, 21, 72, 11, 128, 196, 243, 176, 217,
29, 156, 153, 151, 158, 147, 90, 12, 54, 95, 193, 216, 84, 193, 200, 192, 200, 36, 198, 45,
181, 168, 40, 53, 57, 91, 193, 37, 177, 60, 79, 71, 193, 55, 177, 44, 181, 40, 19, 200, 13,
78, 76, 42, 74, 85, 80, 83, 240, 75, 45, 7, 10, 38, 103, 100, 2, 221, 167, 139, 238, 66, 5,
13, 144, 17, 154, 96, 167, 173, 228, 215, 98, 68, 119, 218, 74, 6, 76, 167, 49, 60, 153,
202, 200, 160, 199, 128, 0, 0, 161, 99, 76, 142,
]
.to_vec();
let mut message = Message::new_with_data(data);
message.set_pointer(8);
let file_search = FileSearch::new_from_message(&mut message);
assert_eq!(file_search.token, "6d2b9434");
assert_eq!(file_search.files.len(), 2);
let file = &file_search.files[0];
assert_eq!(
file.name,
"@@rldqn\\complete\\Canciones\\Trussel-1979-Gone For The Weekend-16bit-44,1Khz.flac"
);
assert_eq!(file.username, "dodigan");
assert_eq!(file.size, 47184516);
}
+3
View File
@@ -0,0 +1,3 @@
pub mod file_search_response;
pub use self::file_search_response::*;
+1 -1
View File
@@ -3,7 +3,7 @@ use crate::peer::Peer;
use crate::server::ServerOperation;
use std::sync::mpsc::Sender;
pub struct ConnectToPeerHandler;
impl MessageHandler for ConnectToPeerHandler {
impl MessageHandler<ServerOperation> for ConnectToPeerHandler {
fn get_code(&self) -> u8 {
18
}
@@ -6,7 +6,7 @@ use std::sync::mpsc::Sender;
pub struct ExcludedSearchPhrasesHandler;
impl MessageHandler for ExcludedSearchPhrasesHandler {
impl MessageHandler<ServerOperation> for ExcludedSearchPhrasesHandler {
fn get_code(&self) -> u8 {
160
}
+2 -2
View File
@@ -5,9 +5,9 @@ use crate::{
server::ServerOperation,
};
pub struct FileSearch;
pub struct FileSearchHandler;
impl MessageHandler for FileSearch {
impl MessageHandler<ServerOperation> for FileSearchHandler {
fn get_code(&self) -> u8 {
26
}
+1 -1
View File
@@ -6,7 +6,7 @@ use std::sync::mpsc::Sender;
pub struct MessageUser;
impl MessageHandler for MessageUser {
impl MessageHandler<ServerOperation> for MessageUser {
fn get_code(&self) -> u8 {
22
}
+1 -1
View File
@@ -7,7 +7,7 @@ use crate::{
pub struct ParentMinSpeedHandler;
impl MessageHandler for ParentMinSpeedHandler {
impl MessageHandler<ServerOperation> for ParentMinSpeedHandler {
fn get_code(&self) -> u8 {
83
}
+1 -1
View File
@@ -8,7 +8,7 @@ use crate::{
pub struct ParentSpeedRatioHandler;
// The server sends us a speed ratio determining the number of children we can have in the distributed network. The maximum number of children is our upload speed divided by the speed ratio.
impl MessageHandler for ParentSpeedRatioHandler {
impl MessageHandler<ServerOperation> for ParentSpeedRatioHandler {
fn get_code(&self) -> u8 {
84
}
+1 -1
View File
@@ -7,7 +7,7 @@ use crate::{
pub struct PrivilegedUsersHandler;
impl MessageHandler for PrivilegedUsersHandler {
impl MessageHandler<ServerOperation> for PrivilegedUsersHandler {
fn get_code(&self) -> u8 {
69
}
+1 -1
View File
@@ -6,7 +6,7 @@ use std::sync::mpsc::Sender;
pub struct RoomListHandler;
impl MessageHandler for RoomListHandler {
impl MessageHandler<ServerOperation> for RoomListHandler {
fn get_code(&self) -> u8 {
64
}
+1 -1
View File
@@ -9,7 +9,7 @@ pub struct WishListIntervalHandler;
// The server tells us the wishlist search interval.
// This interval is almost always 12 minutes, or 2 minutes for privileged users.
impl MessageHandler for WishListIntervalHandler {
impl MessageHandler<ServerOperation> for WishListIntervalHandler {
fn get_code(&self) -> u8 {
104
}