|
|
|
@ -16,14 +16,32 @@ GNU Affero General Public License for more details.
|
|
|
|
|
use crate::util::error::Error; |
|
|
|
|
use crate::protocol::specs::PacketType; |
|
|
|
|
use crate::protocol::specs::Packet; |
|
|
|
|
use crate::protocol::packets::{read_next_packet, send_packet}; |
|
|
|
|
use crate::protocol::packets; |
|
|
|
|
use crate::protocol; |
|
|
|
|
use std::path; |
|
|
|
|
use std::net; |
|
|
|
|
use std::sync::mpsc::{Sender, Receiver}; |
|
|
|
|
use std::sync::mpsc; |
|
|
|
|
use std::thread; |
|
|
|
|
|
|
|
|
|
pub fn start(address_string: String, save_directory: path::PathBuf, verbose_output: bool) -> Option<Error> { |
|
|
|
|
pub struct RecvOptions { |
|
|
|
|
pub listen_address: String, |
|
|
|
|
pub save_directory: path::PathBuf, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl RecvOptions { |
|
|
|
|
pub fn new(addr: String, save_dir: path::PathBuf) -> RecvOptions { |
|
|
|
|
return RecvOptions{ |
|
|
|
|
listen_address: addr, |
|
|
|
|
save_directory: save_dir, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> { |
|
|
|
|
let listener: net::TcpListener; |
|
|
|
|
match net::TcpListener::bind(address_string) { |
|
|
|
|
match net::TcpListener::bind(options.listen_address) { |
|
|
|
|
Ok(l) => { |
|
|
|
|
listener = l; |
|
|
|
|
} |
|
|
|
@ -55,7 +73,7 @@ pub fn start(address_string: String, save_directory: path::PathBuf, verbose_outp
|
|
|
|
|
|
|
|
|
|
// read the first packet
|
|
|
|
|
let incoming_packet: Box<dyn Packet>; |
|
|
|
|
match protocol::packets::read_next_packet(&mut connection) { |
|
|
|
|
match read_next_packet(&mut connection) { |
|
|
|
|
Ok(packet) => { |
|
|
|
|
incoming_packet = packet; |
|
|
|
|
} |
|
|
|
@ -86,6 +104,16 @@ pub fn start(address_string: String, save_directory: path::PathBuf, verbose_outp
|
|
|
|
|
println!("Handshake from {}", address); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// accept handshake
|
|
|
|
|
match send_packet(&mut connection, &packets::HandshakeAccept{}) { |
|
|
|
|
Ok(()) => {} |
|
|
|
|
Err(error) => { |
|
|
|
|
return Some( |
|
|
|
|
Error::new(format!("error accepting handshake from {}: {}", address, error.text).as_str()) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// break out of loop
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -101,6 +129,93 @@ pub fn start(address_string: String, save_directory: path::PathBuf, verbose_outp
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// now read and process incoming packets; essentialy receiving something !
|
|
|
|
|
|
|
|
|
|
// launch a new packet reading thread
|
|
|
|
|
let (ch_send, ch_recv): (Sender<Box<dyn Packet + Send>>, Receiver<Box<dyn Packet + Send>>) = mpsc::channel(); |
|
|
|
|
|
|
|
|
|
let mut cloned_connection: net::TcpStream; |
|
|
|
|
match connection.try_clone() { |
|
|
|
|
Ok(cc) => { |
|
|
|
|
cloned_connection = cc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Err(_) => { |
|
|
|
|
return Some( |
|
|
|
|
Error::new("could not clone connection") |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
thread::spawn(move || { |
|
|
|
|
loop { |
|
|
|
|
match read_next_packet(&mut cloned_connection) { |
|
|
|
|
Ok(packet) => { |
|
|
|
|
if let Err(_) = ch_send.send(packet) { |
|
|
|
|
// the channel has been hung up
|
|
|
|
|
// return from this thread
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Err(error) => { |
|
|
|
|
if verbose_output { |
|
|
|
|
println!("Could not read packet: {}", error.text); |
|
|
|
|
} |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// handle incoming packets
|
|
|
|
|
loop { |
|
|
|
|
let incoming_packet: Box<dyn Packet>; |
|
|
|
|
match ch_recv.recv() { |
|
|
|
|
Ok(p) => { |
|
|
|
|
incoming_packet = p; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Err(error) => { |
|
|
|
|
return Some(Error::new( |
|
|
|
|
format!("error receiving a new packet from listener thread: {}", error).as_str() |
|
|
|
|
)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
match incoming_packet.get_type() { |
|
|
|
|
PacketType::ConnectionShutdown => { |
|
|
|
|
if verbose_output { |
|
|
|
|
println!("{} shuts down the connection", address); |
|
|
|
|
} |
|
|
|
|
connection.shutdown(net::Shutdown::Both); |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
PacketType::TextData => { |
|
|
|
|
let mut text_packet: packets::Text = packets::Text::empty(); |
|
|
|
|
match text_packet.from_bytes(incoming_packet.as_bytes()) { |
|
|
|
|
None => { |
|
|
|
|
// print received text !
|
|
|
|
|
println!("{}", text_packet.text); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Some(error) => { |
|
|
|
|
// close connection and exit
|
|
|
|
|
send_packet(&mut connection, &packets::ConnectionShutdown{}); |
|
|
|
|
connection.shutdown(net::Shutdown::Both); |
|
|
|
|
|
|
|
|
|
return Some( |
|
|
|
|
Error::new(format!("could not get text packet: {}", error.text).as_str()) |
|
|
|
|
); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_ => {} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return None; |
|
|
|
|
} |
|
|
|
|