protocol further implemented
This commit is contained in:
parent
5de131064f
commit
50e4b6a380
@ -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(_) => {
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
Loading…
Reference in New Issue
Block a user