chore: make message handlers and dispatcher generic
This commit is contained in:
+1
-24
@@ -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
@@ -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,6 +1,7 @@
|
||||
pub mod handlers;
|
||||
pub mod message;
|
||||
pub mod message_reader;
|
||||
pub mod peer;
|
||||
pub mod server;
|
||||
|
||||
pub use handlers::*;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod file_search_response;
|
||||
|
||||
pub use self::file_search_response::*;
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
|
||||
pub struct ParentMinSpeedHandler;
|
||||
|
||||
impl MessageHandler for ParentMinSpeedHandler {
|
||||
impl MessageHandler<ServerOperation> for ParentMinSpeedHandler {
|
||||
fn get_code(&self) -> u8 {
|
||||
83
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::{
|
||||
|
||||
pub struct PrivilegedUsersHandler;
|
||||
|
||||
impl MessageHandler for PrivilegedUsersHandler {
|
||||
impl MessageHandler<ServerOperation> for PrivilegedUsersHandler {
|
||||
fn get_code(&self) -> u8 {
|
||||
69
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user