protocol further implemented

This commit is contained in:
Phuntsok Drak-pa 2018-03-21 15:51:34 +01:00
parent 5de131064f
commit 50e4b6a380
2 changed files with 138 additions and 19 deletions

View File

@ -15,8 +15,12 @@ fn get_entry() -> String {
fn write_to_server(stream: TcpStream) { fn write_to_server(stream: TcpStream) {
let mut writer = BufWriter::new(&stream); let mut writer = BufWriter::new(&stream);
// entrée du nom d'utilisateur
loop { loop {
match &*get_entry() { match &*get_entry() {
"" => {
continue;
}
"/quit" => { "/quit" => {
println!("Disconnecting..."); println!("Disconnecting...");
writeln!(writer, "BYE").unwrap(); writeln!(writer, "BYE").unwrap();
@ -25,20 +29,50 @@ fn write_to_server(stream: TcpStream) {
return (); return ();
} }
line => { 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(); writeln!(writer, "{}", line).unwrap();
writer.flush().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) { fn exchange_with_server(stream: TcpStream) {
let server = stream.peer_addr().unwrap(); let server = stream.peer_addr().unwrap();
println!("Connected to {}", server); println!("Connected to {}", server);
// Buffered reading and writing
let stream_cpy = stream.try_clone().unwrap(); let stream_cpy = stream.try_clone().unwrap();
let mut reader = BufReader::new(&stream_cpy); let mut reader = BufReader::new(&stream_cpy);
// let mut writer = BufWriter::new(&stream);
println!("Enter `/quit` when you want to leave"); 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. // Reader is at EOF. Could use ErrorKind::UnexpectedEOF, but still unstable.
let ret = std::io::Error::new(std::io::ErrorKind::Other, "test"); let ret = std::io::Error::new(std::io::ErrorKind::Other, "test");
return Err(ret): std::result::Result<&str, std::io::Error>; return Err(ret): std::result::Result<&str, std::io::Error>;
// return Err(Error::new(ErrorKind::Other, "unexpected EOF"));
} }
line.pop(); line.pop();
} }
@ -66,8 +99,21 @@ fn exchange_with_server(stream: TcpStream) {
}); });
match (|| loop { match (|| loop {
let input = receive!(); let input: String = String::from(receive!());
println!("{}", input); 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(_) => { Ok(_) => {

View File

@ -4,18 +4,61 @@ use std::thread;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use std::collections::HashMap; 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 // Map for all connected clients containing their name and stream
type UserMapValue = (String, TcpStream); type UserMapValue = (String, TcpStream);
type UserMap = HashMap<SocketAddr, UserMapValue>; type UserMap = HashMap<SocketAddr, UserMapValue>;
fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard<UserMap>) { fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard<UserMap>) {
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() { for (other_client, entry) in (*lock).iter() {
if other_client != not_to { if other_client != not_to {
let other_name = &entry.0; let other_name = &entry.0;
let other_stream = &entry.1; let other_stream = &entry.1;
match (|| -> Result<()> { match (|| -> Result<()> {
let mut writer = BufWriter::new(other_stream); 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()); try!(writer.flush());
return Ok(()); return Ok(());
})() })()
@ -32,9 +75,28 @@ fn distribute_message(msg: &str, not_to: &SocketAddr, lock: &mut MutexGuard<User
} }
} }
fn send_clients_name(to: &SocketAddr, lock: &mut MutexGuard<UserMap>) {
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<UserMap>) { fn disconnect_user(name: &str, client: &SocketAddr, lock: &mut MutexGuard<UserMap>) {
(*lock).remove(&client); (*lock).remove(&client);
distribute_message(&format!("{} left", name), client, lock); distribute_message(&format!("LOGOUT {}", name), client, lock);
} }
fn handle_client(stream: TcpStream, clients: Arc<Mutex<UserMap>>) { fn handle_client(stream: TcpStream, clients: Arc<Mutex<UserMap>>) {
@ -97,23 +159,34 @@ fn handle_client(stream: TcpStream, clients: Arc<Mutex<UserMap>>) {
{ {
let mut lock = clients.lock().unwrap(); let mut lock = clients.lock().unwrap();
(*lock).insert(client, (name.clone(), stream.try_clone().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 // Chat loop: Receive messages from users
match (|| { match (|| loop {
loop { match receive!().as_str() {
let input = receive!(); "BYE" => {
if input == "BYE" { send!("BYE");
send!("Bye!");
return Ok(()); return Ok(());
} }
"PING" => {
// Distribute message send!("PONG");
println!("{} <{}>: {}", client, name, input); }
{ "REQ CLIENTS" => {
let mut lock = clients.lock().unwrap(); {
distribute_message(&format!("<{}>: {}", name, input), &client, &mut lock); 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);
}
} }
} }
})() })()