use std::io::{Read, Write}; use std::net::{TcpListener, TcpStream}; use std::sync::{Arc, RwLock}; use anyhow::{bail, Result}; use bank::bank::Bank; use crate::commands::Commands; use crate::protocol; use crate::threadpool::ThreadPool; pub fn run(host: &str, threads: usize) -> Result<()> { let listener = TcpListener::bind(host)?; let pool = ThreadPool::new(threads); let cmds = Arc::new(Commands::new()); let bank = Arc::new(RwLock::new(Bank::new())); for stream in listener.incoming() { let cmds = cmds.clone(); let bank = bank.clone(); let stream = stream?; pool.execute(move || { if let Err(e) = handle_connection(bank, &cmds, stream) { error!("{}", e); } }); } Ok(()) } fn handle_connection( bank: Arc>, cmds: &Commands, mut stream: TcpStream, ) -> Result<()> { const BUF_SIZE: usize = 64; let mut data: Vec = vec![]; let mut buffer = [0; BUF_SIZE]; let mut read = stream.read(&mut buffer)?; while read > 0 { data.append(&mut buffer[..read].to_vec()); read = stream.read(&mut buffer)?; } if data[..2] != protocol::START { bail!("got {:?} as first bytes, not my problem", &data[..2]); } let cmd: u8 = (data[2] & 0b1111_0000) >> 4; trace!("got command {}", cmd); cmds.run(bank, cmd, &data[3..], &stream)?; stream.flush()?; Ok(()) }