diff --git a/src/main.rs b/src/main.rs index c57557f..80a26ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,90 +17,75 @@ */ use std::{ - io::Read, - net::{ TcpListener, TcpStream }, - thread, + io::{ self, BufRead, BufReader, Write }, + net::{ TcpListener, TcpStream }, + thread, }; -use serde_derive::Deserialize; - -#[derive(Debug, Deserialize)] -struct MessageOuter { - auth: Option, - message: Message, - to: String, -} - -#[derive(Debug, Deserialize)] struct Message { - body: String, - from: Option, + from: Option, + body: Option, } -fn parse_message(input: &str) -> MessageOuter { - let mut auth: Option = None; - let mut body = String::new(); - let mut from = None; - let mut to = String::new(); +fn handle_client(stream: TcpStream) { + let mut reader = BufReader::new(&stream); + let mut writer = &stream; - for line in input.lines() { - let mut parts = line.split_whitespace(); - if let Some(field) = parts.next() { - if let Some(value) = parts.next() { - match field { - "AUTH" => auth = Some(value.to_string()), - "BODY" => body = value.to_string(), - "FROM" => from = Some(value.to_string()), - "TO" => to = value.to_string(), - _ => {}, - } - } - } - } + let mut message = Message { + from: None, + body: None, + }; - let message_outer = MessageOuter { - auth, - message: Message { body, from }, - to, - }; + loop { + let mut send = false; + let mut buffer = String::new(); + if reader.read_line(&mut buffer).is_err() { + println!( + "{} disconnected.", + message.from.unwrap_or_else(|| { format!("anon") }), + ); + break; + } - message_outer -} + let words: Vec<&str> = buffer.split_whitespace().collect(); + if words.is_empty() { + continue; + } -fn read_from(mut stream: TcpStream) { - let mut buf = Vec::new(); + match words[0] { + "FROM" => { + message.from = Some(words[1..].join(" ")); + } + "BODY" => { + message.body = Some(words[1..].join(" ")); + send = true; + } + _ => {} + } - while let Ok(bytes_read) = stream.read_to_end(&mut buf) { - if bytes_read == 0 { break } - - let message_outer = parse_message( - String::from_utf8(buf.clone()).as_ref().unwrap() - ); - - let user = message_outer.message.from.unwrap_or_else(|| { - format!("anon") - }); - - println!("{}: {}", user, message_outer.message.body); - } + if send { + println!( + "{}: {}", + message.from.clone().unwrap_or_else(|| { format!("anon") }), + message.body.take().unwrap(), + ); + } + } } fn main() { - let listener = TcpListener::bind("127.0.0.1:8080") - .expect("Failed to bind address"); + let listener = TcpListener::bind("0.0.0.0:8080") + .expect("Failed to bind to port 8080."); + println!("Server listening on port 8080."); - println!("Server listening on 127.0.0.1:8080"); - - for stream in listener.incoming() { - match stream { - Ok(stream) => { - thread::spawn(move || { - read_from(stream); - }); - } - Err(err) => { - eprintln!("Error accepting client connection: {}", err); - } - } - } + for stream in listener.incoming() { + match stream { + Ok(stream) => { + thread::spawn(move || handle_client(stream)); + } + Err(e) => { + eprintln!("Error accepting client connection: {}", e); + } + } + } } diff --git a/temp.rs b/temp.rs new file mode 100644 index 0000000..a131a58 --- /dev/null +++ b/temp.rs @@ -0,0 +1,123 @@ +use std::io::{Read, Write}; +use std::net::{TcpListener, TcpStream}; +use std::sync::{Arc, Mutex}; +use std::thread; + +#[derive(Debug, Deserialize)] +struct MessageOuter { + auth: Option, + message: Message, + to: String, +} + +#[derive(Debug, Deserialize)] +struct Message { + body: String, + from: Option, +} + +fn parse_message(input: &str) -> MessageOuter { + let mut auth: Option = None; + let mut body = String::new(); + let mut from = None; + let mut to = String::new(); + + for line in input.lines() { + let mut parts = line.split_whitespace(); + if let Some(field) = parts.next() { + if let Some(value) = parts.next() { + match field { + "AUTH" => auth = Some(value.to_string()), + "BODY" => body = value.to_string(), + "FROM" => from = Some(value.to_string()), + "TO" => to = value.to_string(), + _ => {} + } + } + } + } + + let message_outer = MessageOuter { + auth, + message: Message { body, from }, + to, + }; + + message_outer +} + +fn read_from(mut stream: TcpStream) -> MessageOuter { + let mut buf = Vec::new(); + let mut message_outer = MessageOuter { + auth: None, + message: Message { + body: "".to_string(), + from: None, + }, + to: "".to_string(), + }; + + while let Ok(bytes_read) = stream.read_to_end(&mut buf) { + if bytes_read == 0 { + break; + } + + message_outer = parse_message( + String::from_utf8(buf.clone()).as_ref().unwrap() + ); + } + + message_outer.message.from = Some( + message_outer.message.from.unwrap_or_else(|| "anon".to_string()) + ); + + message_outer +} + +fn main() { + let listener = TcpListener::bind("127.0.0.1:8080") + .expect("Failed to bind address"); + + println!("Server listening on 127.0.0.1:8080"); + + let client_list: Arc>> = Arc::new( + Mutex::new(vec![]) + ); + + for stream in listener.incoming() { + match stream { + Ok(stream) => { + let client_list = Arc::clone(&client_list); + thread::spawn(move || { + // Add the client's stream to the client list + client_list.lock().unwrap().push(stream.try_clone().unwrap()); + + let message = read_from(stream); + + // Send the received message to all connected clients + let serialized_message = serde_json::to_string(&message).unwrap(); + let client_list = client_list.lock().unwrap(); + for client in &*client_list { + if let Err(e) = client.write_all(serialized_message.as_bytes()) { + eprintln!("Failed to write to client: {}", e); + } + if let Err(e) = client.flush() { + eprintln!("Failed to flush stream: {}", e); + } + } + + // Remove the client's stream from the client list + client_list + .lock() + .unwrap() + .retain(|client| client + .peer_addr() + .unwrap() != stream.peer_addr().unwrap()); + }); + } + Err(err) => { + eprintln!("Error accepting client connection: {}"); + } + } + } +}