From 50e4b6a38085571a1d5b5dbdae37b3222e3f6d55 Mon Sep 17 00:00:00 2001 From: Phuntsok Drak-pa Date: Wed, 21 Mar 2018 15:51:34 +0100 Subject: [PATCH] protocol further implemented --- Lucien/Rust/src/client.rs | 56 +++++++++++++++++++-- Lucien/Rust/src/server.rs | 101 ++++++++++++++++++++++++++++++++------ 2 files changed, 138 insertions(+), 19 deletions(-) diff --git a/Lucien/Rust/src/client.rs b/Lucien/Rust/src/client.rs index 694ba30..ac866d2 100644 --- a/Lucien/Rust/src/client.rs +++ b/Lucien/Rust/src/client.rs @@ -15,8 +15,12 @@ fn get_entry() -> String { fn write_to_server(stream: TcpStream) { let mut writer = BufWriter::new(&stream); + // entrée du nom d'utilisateur loop { match &*get_entry() { + "" => { + continue; + } "/quit" => { println!("Disconnecting..."); writeln!(writer, "BYE").unwrap(); @@ -25,20 +29,50 @@ fn write_to_server(stream: TcpStream) { return (); } line => { + let line_str : String = String::from(line); + // let spliced: Vec<&str> = line_str.split(" ").collect(); + let spliced: Vec<&str> = line_str.split_whitespace().collect(); + if spliced.len() > 1 { + println!("Cannot use whitespace in username."); + continue; + } writeln!(writer, "{}", line).unwrap(); writer.flush().unwrap(); } } + break; + } + + loop { + match &*get_entry() { + "" => { + ; + } + "/quit" => { + println!("Disconnecting..."); + writeln!(writer, "BYE").unwrap(); + writer.flush().unwrap(); + println!("Disconnected!"); + return (); + } + "/clients" => { + writeln!(writer, "REQ CLIENTS").unwrap(); + writer.flush().unwrap(); + } + line => { + writeln!(writer, "MSG {}", line).unwrap(); + writer.flush().unwrap(); + } + } } } fn exchange_with_server(stream: TcpStream) { let server = stream.peer_addr().unwrap(); println!("Connected to {}", server); - // Buffered reading and writing + let stream_cpy = stream.try_clone().unwrap(); let mut reader = BufReader::new(&stream_cpy); - // let mut writer = BufWriter::new(&stream); println!("Enter `/quit` when you want to leave"); @@ -51,7 +85,6 @@ fn exchange_with_server(stream: TcpStream) { // Reader is at EOF. Could use ErrorKind::UnexpectedEOF, but still unstable. let ret = std::io::Error::new(std::io::ErrorKind::Other, "test"); return Err(ret): std::result::Result<&str, std::io::Error>; - // return Err(Error::new(ErrorKind::Other, "unexpected EOF")); } line.pop(); } @@ -66,8 +99,21 @@ fn exchange_with_server(stream: TcpStream) { }); match (|| loop { - let input = receive!(); - println!("{}", input); + let input: String = String::from(receive!()); + let spliced_input: Vec<&str> = input.split(" ").collect(); + // if spliced_input[0] == "FROM" { + // println!("<{}>: {}", spliced_input[1], spliced_input[3]); + // continue; + // } + match spliced_input[0] { + "FROM" => { + println!("<{}>: {}", spliced_input[1], spliced_input[3]); + } + _ => { + println!("{}", input); + } + } + // println!("{}", input); })() { Ok(_) => { diff --git a/Lucien/Rust/src/server.rs b/Lucien/Rust/src/server.rs index 175d294..8053f2e 100644 --- a/Lucien/Rust/src/server.rs +++ b/Lucien/Rust/src/server.rs @@ -4,18 +4,61 @@ use std::thread; use std::sync::{Arc, Mutex, MutexGuard}; use std::collections::HashMap; +/////////////////////////////////////////////////////////////////////////////// +// Evolution implementation protocole // +/////////////////////////////////////////////////////////////////////////////// + +/* + +1.1 [ ] +1.2 [ ] +1.3 [ ] +1.4 [ ] +1.5 [ ] +1.6 [ ] +1.7 [X] +1.8 [ ] +1.9 [ ] +2.1 [X] +2.2 [X] +3.1 [ ] // pas utile avec Rust +3.2 [X] +4.1.1 [X] +4.1.2 [X] +4.2.1 [X] +4.2.2 [X] + +*/ + +/////////////////////////////////////////////////////////////////////////////// +// code // +/////////////////////////////////////////////////////////////////////////////// + // Map for all connected clients containing their name and stream type UserMapValue = (String, TcpStream); type UserMap = HashMap; fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard) { + let mut name = String::new(); + for (client, entry) in (*lock).iter() { + if client == not_to { + name = entry.0.clone(); + break; + } + } for (other_client, entry) in (*lock).iter() { if other_client != not_to { let other_name = &entry.0; let other_stream = &entry.1; match (|| -> Result<()> { let mut writer = BufWriter::new(other_stream); - try!(writeln!(writer, "{}", msg)); + // test if message begins with "MSG " ///////////////////////// + if &msg[..4] == "MSG " { + try!(writeln!(writer, "FROM {} {}", name, msg)); + } else { + try!(writeln!(writer, "{}", msg)); + } + /////////////////////////////////////////////////////////////// try!(writer.flush()); return Ok(()); })() @@ -32,9 +75,28 @@ fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard) { + let mut clients = String::new(); + for (client, entry) in (*lock).iter() { + if client != to { + clients.push_str(&format!("{} ", &entry.0)); + } + } + println!("{}", clients); + for (client, entry) in (*lock).iter() { + if client == to { + let stream = &entry.1; + let mut writer = BufWriter::new(stream); + writeln!(writer, "{}", clients).unwrap(); + writer.flush().unwrap(); + return; + } + } +} + fn disconnect_user(name: &str, client: &SocketAddr, lock: &mut MutexGuard) { (*lock).remove(&client); - distribute_message(&format!("{} left", name), client, lock); + distribute_message(&format!("LOGOUT {}", name), client, lock); } fn handle_client(stream: TcpStream, clients: Arc>) { @@ -97,23 +159,34 @@ fn handle_client(stream: TcpStream, clients: Arc>) { { let mut lock = clients.lock().unwrap(); (*lock).insert(client, (name.clone(), stream.try_clone().unwrap())); - distribute_message(&format!("{} joined", name), &client, &mut lock); + distribute_message(&format!("JOIN {}", name), &client, &mut lock); } + writeln!(writer, "WELCOME").unwrap(); + writer.flush().unwrap(); + // Chat loop: Receive messages from users - match (|| { - loop { - let input = receive!(); - if input == "BYE" { - send!("Bye!"); + match (|| loop { + match receive!().as_str() { + "BYE" => { + send!("BYE"); return Ok(()); } - - // Distribute message - println!("{} <{}>: {}", client, name, input); - { - let mut lock = clients.lock().unwrap(); - distribute_message(&format!("<{}>: {}", name, input), &client, &mut lock); + "PING" => { + send!("PONG"); + } + "REQ CLIENTS" => { + { + let mut lock = clients.lock().unwrap(); + send_clients_name(&client, &mut lock); + } + } + input => { + println!("{} <{}>: {}", client, name, input); + { + let mut lock = clients.lock().unwrap(); + distribute_message(&format!("{}", input), &client, &mut lock); + } } } })()