use std::{ io::{prelude::*, BufReader, Lines}, net::{TcpListener, TcpStream}, }; use std::sync::{Arc, Mutex}; use std::thread::available_parallelism; use crate::connection_pool::ConnectionPool; use crate::thread_pool::ThreadPool; mod thread_pool; mod connection_pool; fn main() { // start server on localhost (for remote access use: 0.0.0.0) let listener = TcpListener::bind("127.0.0.1:7878").unwrap(); // create thread pool (size = no. of cpu cores) let pool = ThreadPool::new(available_parallelism().unwrap().get()); //let pool = ThreadPool::new(2); let conn_pool = Arc::new(Mutex::new(ConnectionPool::new())); let mut cc: u32 = 0; // handling function for incoming requests for stream in listener.incoming() { let stream = stream.unwrap(); conn_pool.lock().unwrap().add_connection(cc, stream.try_clone().unwrap()); let ccc = cc; let cconn_pool = conn_pool.clone(); // pass request to thread pool pool.execute(move || { handle_connection(stream, ccc, cconn_pool); }); cc += 1; } println!("Shutting down."); } fn handle_connection(mut stream: TcpStream, iid: u32, conn_pool: Arc>) { // clone TcpStream for simultaneous receiving and sending //let mut stream2 = stream.try_clone().unwrap(); // initialize reading buffer (for better performance!) let buf_reader: BufReader<&mut TcpStream> = BufReader::new(&mut stream); // request: read received text line by line (continuous until connection closed) let request: Lines> = buf_reader.lines(); // let request: Bytes> = buf_reader.bytes(); println!("Request: {:#?}", request); // processing function for every text line received by request (terminates when conn closed) for elem in request { // store received line in variable s let s = elem.unwrap(); println!("{:?}", s); conn_pool.lock().unwrap().broadcast(&iid, &s); // send received line back to sender (append LF) //stream2.write_all(s.as_bytes()).unwrap(); //stream2.write_all(b"\n").unwrap(); } }