#![feature(try_from)]
pub mod protocol;
use std::convert::TryFrom;
use std::io::{Read, Write};
use std::thread;
use std::time::Duration;
use std::net::TcpStream;
use std::sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender};
pub struct TobyMessenger {
tcp_stream: TcpStream,
}
impl TobyMessenger {
pub fn new(tcp_stream: TcpStream) -> TobyMessenger {
TobyMessenger { tcp_stream: tcp_stream }
}
pub fn start(&mut self) -> (Sender<Vec<u8>>, Receiver<Vec<u8>>) {
let (inbound_sender, inbound_receiver) = channel();
match self.tcp_stream.try_clone() {
Ok(stream) => {
thread::spawn(move || receive_data(stream, inbound_sender));
}
Err(e) => println!("Error cloning stream for consumer {}", e),
}
let (outbound_sender, outbound_receiver) = channel();
match self.tcp_stream.try_clone() {
Ok(stream) => {
thread::spawn(move ||
send_data(stream, outbound_receiver, Duration::from_millis(100))
);
}
Err(e) => println!("Error cloning stream for sender {}", e),
}
return (outbound_sender, inbound_receiver);
}
}
fn receive_data(mut stream: TcpStream, sender: Sender<Vec<u8>>) {
let mut raw_buff = Vec::new();
let mut curr_size: Option<u64> = None;
loop {
let mut tcpbuf = [0u8; 256];
match stream.read(&mut tcpbuf) {
Ok(bytes) => {
if bytes > 0 {
raw_buff.append(&mut tcpbuf[0..bytes].to_vec());
} else {
continue;
}
}
Err(e) => println!("Error reading from stream {}", e),
}
curr_size = compute_curr_size(curr_size, &mut raw_buff);
while curr_size.is_some() && raw_buff.len() >= to_usize(curr_size.unwrap()) {
let parsed_message = raw_buff.drain(0..to_usize(curr_size.unwrap())).collect();
raw_buff.shrink_to_fit();
curr_size = compute_curr_size(None, &mut raw_buff);
match sender.send(parsed_message) {
Ok(_) => {} Err(_) => {
println!("Error sending data to client's receiver, shutting down inbound message consumer thread");
return;
}
}
}
}
}
fn compute_curr_size(curr_size: Option<u64>, buf: &mut Vec<u8>) -> Option<u64> {
if curr_size.is_none() {
if buf.len() >= 8 {
let size = Some(bytes_to(&buf[0..8]));
buf.drain(0..8);
return size;
}
None
} else {
curr_size
}
}
fn send_data(mut stream: TcpStream, receiver: Receiver<Vec<u8>>, timeout: Duration) {
loop {
match receiver.recv_timeout(timeout) {
Ok(buf) => {
let encoded = protocol::encode_tobytcp(buf);
match stream.write_all(encoded.as_slice()) {
Ok(_) => {} Err(e) => println!("Error sending data over tcp stream {}", e), }
}
Err(e) => {
match e {
RecvTimeoutError::Timeout => continue, RecvTimeoutError::Disconnected => {
println!("Error waiting for messages to send from client, shutting down outbound message consumer thread");
return;
}
}
}
}
}
}
fn bytes_to(bytes: &[u8]) -> u64 {
let mut ret = 0u64;
let mut i = 0; for byte in bytes {
ret = ret | u64::try_from(*byte).unwrap();
if i < 7 {
ret = ret << 8;
}
i = i + 1;
}
ret
}
fn to_usize(num: u64) -> usize {
usize::try_from(num).unwrap()
}