feat: add missing message handlers
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
use crate::message::server::MessageFactory;
|
||||
use crate::message::{Message, MessageReader};
|
||||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::thread::{self};
|
||||
|
||||
use super::peer::Peer;
|
||||
use crate::client::ClientOperation;
|
||||
use std::io::{self, Write};
|
||||
use std::net::TcpStream;
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::time::Duration;
|
||||
|
||||
pub struct DefaultPeer {
|
||||
peer: Peer,
|
||||
// client_channel: Sender<ClientOperation>,
|
||||
peer_channel: Option<Sender<PeerOperation>>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum PeerOperation {
|
||||
SendMessage(Message),
|
||||
}
|
||||
impl DefaultPeer {
|
||||
pub fn new(peer: Peer, _client_channel: Sender<ClientOperation>) -> Self {
|
||||
Self {
|
||||
peer,
|
||||
// client_channel,
|
||||
peer_channel: None,
|
||||
}
|
||||
}
|
||||
pub fn connect(mut self) -> Result<Self, io::Error> {
|
||||
// println!("Connecting to peer {:?}", self.peer);
|
||||
let socket_address = format!("{}:{}", self.peer.host, self.peer.port)
|
||||
.to_socket_addrs()?
|
||||
.next()
|
||||
.ok_or_else(|| io::Error::new(io::ErrorKind::InvalidInput, "Invalid address"))?;
|
||||
|
||||
let mut stream = TcpStream::connect_timeout(&socket_address, Duration::from_secs(10))?;
|
||||
|
||||
stream.set_read_timeout(Some(Duration::from_secs(5)))?;
|
||||
stream.set_write_timeout(Some(Duration::from_secs(5)))?;
|
||||
if let Some(token) = self.peer.token.clone() {
|
||||
stream
|
||||
.write_all(&MessageFactory::build_watch_user(&token).get_data())
|
||||
.unwrap();
|
||||
// self.queue_message(build_watch_user(&token));
|
||||
}
|
||||
self.start_read_write_loops(stream).unwrap();
|
||||
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn start_read_write_loops(&mut self, stream: TcpStream) -> Result<(), io::Error> {
|
||||
let (peer_sender, peer_reader): (Sender<PeerOperation>, Receiver<PeerOperation>) =
|
||||
mpsc::channel();
|
||||
self.peer_channel = Some(peer_sender);
|
||||
|
||||
let barrier = Arc::new(Barrier::new(3));
|
||||
let read_barrier = barrier.clone();
|
||||
let write_barrier = barrier.clone();
|
||||
let done_barrier = barrier.clone();
|
||||
|
||||
let mut read_stream = stream.try_clone()?;
|
||||
let mut write_stream = stream.try_clone()?;
|
||||
|
||||
let peer = self.peer.clone();
|
||||
thread::spawn(move || {
|
||||
read_barrier.wait();
|
||||
let mut buffered_reader = MessageReader::new();
|
||||
loop {
|
||||
match buffered_reader.read_from_socket(&mut read_stream) {
|
||||
Ok(_) => {}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => continue,
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => continue,
|
||||
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {
|
||||
println!(
|
||||
"Read operation timed out in default peer {:}:{:}",
|
||||
peer.host, peer.port
|
||||
);
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from peer: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
match buffered_reader.extract_message() {
|
||||
Ok(Some(message)) => {
|
||||
println!(
|
||||
"Received message in default peer: {:?}",
|
||||
message.get_message_code_u32()
|
||||
);
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error extracting message in default peer: {}", e)
|
||||
}
|
||||
Ok(None) => continue,
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// thread::spawn(move || loop {
|
||||
// thread::sleep(Duration::from_secs(1));
|
||||
// // println!(
|
||||
// // "Default peer ({}) - stream state: connected={}",
|
||||
// // px.host,
|
||||
// // stream.peer_addr().is_ok()
|
||||
// // );
|
||||
// });
|
||||
thread::spawn(move || {
|
||||
write_barrier.wait();
|
||||
loop {
|
||||
if let Ok(operation) = peer_reader.recv() {
|
||||
match operation {
|
||||
PeerOperation::SendMessage(message) => {
|
||||
match write_stream.write_all(&message.get_buffer()) {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
eprintln!("Error writing message to stream : {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
done_barrier.wait();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub fn queue_message(&self, message: Message) {
|
||||
// if let Some(sender) = self.peer_channel.clone() {
|
||||
// if let Err(e) = sender.send(PeerOperation::SendMessage(message)) {
|
||||
// eprintln!("Failed to send: {}", e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
use std::{io, net::TcpListener};
|
||||
|
||||
use crate::message::MessageReader;
|
||||
|
||||
pub struct Listen {}
|
||||
|
||||
impl Listen {
|
||||
pub fn new(port: u32) {
|
||||
println!("starting listener on port {port}");
|
||||
let listener = TcpListener::bind(format!("0.0.0.0:{port}")).unwrap();
|
||||
for stream in listener.incoming() {
|
||||
let mut read_stream = stream.unwrap();
|
||||
|
||||
let mut buffered_reader = MessageReader::new();
|
||||
loop {
|
||||
match buffered_reader.read_from_socket(&mut read_stream) {
|
||||
Ok(_) => {}
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => continue,
|
||||
Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => continue,
|
||||
Err(ref e) if e.kind() == io::ErrorKind::TimedOut => {
|
||||
println!("Read operation timed out");
|
||||
continue;
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Error reading from server: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
match buffered_reader.extract_message() {
|
||||
Ok(Some(message)) => {
|
||||
println!("Received message: {:?}", message.get_message_code_u32());
|
||||
println!("{:?}", message.get_data());
|
||||
}
|
||||
Err(e) => {
|
||||
println!("Error extracting message: {}", e)
|
||||
}
|
||||
Ok(None) => continue,
|
||||
}
|
||||
}
|
||||
|
||||
println!("Connection established!");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
pub mod default_peer;
|
||||
pub mod listen;
|
||||
pub mod peer;
|
||||
@@ -0,0 +1,153 @@
|
||||
use core::fmt;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::message::Message;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum ConnectionType {
|
||||
P,
|
||||
F,
|
||||
D,
|
||||
}
|
||||
|
||||
// Define the error type
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseConnectionTypeError;
|
||||
|
||||
impl fmt::Display for ParseConnectionTypeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "invalid connection type")
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for ParseConnectionTypeError {}
|
||||
|
||||
// Implement FromStr for ConnectionType
|
||||
impl FromStr for ConnectionType {
|
||||
type Err = ParseConnectionTypeError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"P" => Ok(ConnectionType::P),
|
||||
"F" => Ok(ConnectionType::F),
|
||||
"D" => Ok(ConnectionType::D),
|
||||
_ => Err(ParseConnectionTypeError),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct Peer {
|
||||
pub username: String,
|
||||
pub connection_type: ConnectionType,
|
||||
pub host: String,
|
||||
pub port: i32,
|
||||
pub token: Option<String>,
|
||||
pub privileged: i8,
|
||||
pub unknown: i8,
|
||||
pub obfuscated_port: i8,
|
||||
}
|
||||
impl Peer {
|
||||
#[allow(dead_code)]
|
||||
pub fn new(
|
||||
username: String,
|
||||
connection_type: ConnectionType,
|
||||
host: String,
|
||||
port: i32,
|
||||
token: String,
|
||||
privileged: i8,
|
||||
unknown: i8,
|
||||
obfuscated_port: i8,
|
||||
) -> Self {
|
||||
Self {
|
||||
username,
|
||||
connection_type,
|
||||
host,
|
||||
port,
|
||||
token: Some(token),
|
||||
privileged,
|
||||
unknown,
|
||||
obfuscated_port,
|
||||
}
|
||||
}
|
||||
#[allow(dead_code)]
|
||||
pub fn new_from_message(message: &mut Message) -> Self {
|
||||
let username = message.read_string();
|
||||
let connection_type: ConnectionType = message.read_string().parse().unwrap();
|
||||
|
||||
let mut ip: Vec<i32> = vec![];
|
||||
for _ in 0..4 {
|
||||
ip.push(message.read_int8().into());
|
||||
}
|
||||
let host: String = format!(
|
||||
"{}.{}.{}.{}",
|
||||
ip[3].abs(),
|
||||
ip[2].abs(),
|
||||
ip[1].abs(),
|
||||
ip[0].abs()
|
||||
);
|
||||
|
||||
let (port, token, privileged, unknown, obfuscated_port) = (
|
||||
message.read_int32(),
|
||||
message.read_raw_hex_str(4),
|
||||
message.read_int8(),
|
||||
message.read_int8(),
|
||||
message.read_int8(),
|
||||
);
|
||||
|
||||
Self {
|
||||
username,
|
||||
connection_type,
|
||||
host,
|
||||
port,
|
||||
token: Some(token),
|
||||
privileged,
|
||||
unknown,
|
||||
obfuscated_port,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn test_new_from_message() {
|
||||
let data: Vec<u8> = [
|
||||
36, 0, 0, 0, 18, 0, 0, 0, 2, 0, 0, 0, 100, 112, 1, 0, 0, 0, 80, 27, 231, 37, 45, 186, 8, 0,
|
||||
0, 178, 78, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
]
|
||||
.to_vec();
|
||||
let mut message = Message::new_with_data(data);
|
||||
message.set_pointer(8);
|
||||
|
||||
let peer = Peer::new_from_message(&mut message);
|
||||
|
||||
assert_eq!(peer.username, "dp");
|
||||
assert!(matches!(peer.connection_type, ConnectionType::P));
|
||||
assert_eq!(peer.host, "45.37.25.27");
|
||||
assert_eq!(peer.port, 2234);
|
||||
assert_eq!(peer.token, Some("b24e1900".to_string()));
|
||||
assert_eq!(peer.privileged, 0);
|
||||
assert_eq!(peer.unknown, 0);
|
||||
assert_eq!(peer.obfuscated_port, 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_from_message2() {
|
||||
let data: Vec<u8> = [
|
||||
42, 0, 0, 0, 18, 0, 0, 0, 8, 0, 0, 0, 103, 114, 97, 110, 100, 112, 97, 103, 1, 0, 0, 0, 80,
|
||||
137, 128, 193, 68, 187, 8, 0, 0, 58, 16, 0, 0, 0, 1, 0, 0, 0, 188, 8, 0, 0,
|
||||
]
|
||||
.to_vec();
|
||||
let mut message = Message::new_with_data(data);
|
||||
message.set_pointer(8);
|
||||
|
||||
let peer = Peer::new_from_message(&mut message);
|
||||
|
||||
assert_eq!(peer.username, "grandpag");
|
||||
assert!(matches!(peer.connection_type, ConnectionType::P));
|
||||
assert_eq!(peer.host, "68.63.128.119");
|
||||
assert_eq!(peer.port, 2235);
|
||||
assert_eq!(peer.token, Some("3a100000".to_string()));
|
||||
assert_eq!(peer.privileged, 0);
|
||||
assert_eq!(peer.unknown, 1);
|
||||
assert_eq!(peer.obfuscated_port, 0);
|
||||
}
|
||||
Reference in New Issue
Block a user