client broken (see TODO) but server pretty much complete
This commit is contained in:
parent
48e5c2825d
commit
4d51fef365
@ -10,9 +10,31 @@ use std::hash::{Hash, Hasher};
|
|||||||
use self::colored::*;
|
use self::colored::*;
|
||||||
use self::chrono::Local;
|
use self::chrono::Local;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
0.1 [ ]
|
||||||
|
1.1 [ ]
|
||||||
|
1.2 [ ]
|
||||||
|
1.3 [ ]
|
||||||
|
1.4 [ ]
|
||||||
|
1.5 [ ]
|
||||||
|
1.6 [ ]
|
||||||
|
1.7 [X]
|
||||||
|
1.8 [X]
|
||||||
|
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 [-]
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// TODO: Implement requests 1.x from protocol (connection currently is broken)
|
||||||
// TODO: Limit usernames to ascii
|
// TODO: Limit usernames to ascii
|
||||||
// TODO: Implement requests 1.x from protocol
|
|
||||||
// TODO: forbid usernames already in use
|
|
||||||
|
|
||||||
fn hash_name(name: &str) -> usize {
|
fn hash_name(name: &str) -> usize {
|
||||||
let mut s = DefaultHasher::new();
|
let mut s = DefaultHasher::new();
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#![feature(stmt_expr_attributes)]
|
#![feature(stmt_expr_attributes)]
|
||||||
use std::env;
|
use std::env;
|
||||||
|
|
||||||
|
static PROTOCOL: &'static str = "0.1";
|
||||||
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
|
||||||
|
@ -15,15 +15,16 @@ use self::chrono::Local;
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
1.1 [ ]
|
0.1 [X]
|
||||||
1.2 [ ]
|
1.1 [X]
|
||||||
1.3 [ ]
|
1.2 [X]
|
||||||
1.4 [ ]
|
1.3 [X]
|
||||||
1.5 [ ]
|
1.4 [X]
|
||||||
1.6 [ ]
|
1.5 [X]
|
||||||
|
1.6 [X]
|
||||||
1.7 [X]
|
1.7 [X]
|
||||||
1.8 [X]
|
1.8 [X]
|
||||||
1.9 [ ]
|
1.9 [X]
|
||||||
2.1 [X]
|
2.1 [X]
|
||||||
2.2 [X]
|
2.2 [X]
|
||||||
3.1 [ ] // pas utile avec Rust
|
3.1 [ ] // pas utile avec Rust
|
||||||
@ -163,23 +164,106 @@ fn handle_client(stream: TcpStream, clients: Arc<Mutex<UserMap>>) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialization: Ask user for his name
|
// // Initialization: Ask user for his name
|
||||||
let name = match (|| {
|
// let name = match (|| {
|
||||||
send!("Welcome!");
|
// send!("Welcome!");
|
||||||
send!("Please enter your name:");
|
// send!("Please enter your name:");
|
||||||
let name = receive!();
|
// let name = receive!();
|
||||||
println!("{} Client {} identified as {}", get_time(), client, name);
|
// println!("{} Client {} identified as {}", get_time(), client, name);
|
||||||
Ok(name)
|
// Ok(name)
|
||||||
|
// })()
|
||||||
|
// {
|
||||||
|
// Ok(name) => name,
|
||||||
|
// Err(e) => {
|
||||||
|
// println!(
|
||||||
|
// "{} Client {} disappeared during initialization: {}",
|
||||||
|
// get_time(),
|
||||||
|
// client,
|
||||||
|
// e
|
||||||
|
// );
|
||||||
|
// return ();
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
let name: String = match (|| loop {
|
||||||
|
match receive!() {
|
||||||
|
input => {
|
||||||
|
let spliced_input: Vec<&str> = input.split_whitespace().collect();
|
||||||
|
if spliced_input.len() != 4 && spliced_input.len() != 5
|
||||||
|
|| spliced_input[0] != "PROT"
|
||||||
|
{
|
||||||
|
// send!("BAD REQ");
|
||||||
|
return Err(Error::new(ErrorKind::Other, "BAD REQ"));
|
||||||
|
}
|
||||||
|
if spliced_input[1] != ::PROTOCOL {
|
||||||
|
// send!("BAD PROT");
|
||||||
|
return Err(Error::new(ErrorKind::Other, "BAD PROT"));
|
||||||
|
}
|
||||||
|
if spliced_input.len() == 5 {
|
||||||
|
if spliced_input[2] == "CONNECT" && spliced_input[3] == "USER" {
|
||||||
|
let username = String::from(spliced_input[4]);
|
||||||
|
let mut used = false;
|
||||||
|
{
|
||||||
|
let lock = clients.lock().unwrap();
|
||||||
|
for (_, entry) in (*lock).iter() {
|
||||||
|
if username == entry.0 {
|
||||||
|
used = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if used == false {
|
||||||
|
send!("NAME OK");
|
||||||
|
return Ok(username);
|
||||||
|
} else {
|
||||||
|
send!("NAME FAILURE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
send!("NAME REQ");
|
||||||
|
match receive!() {
|
||||||
|
input => {
|
||||||
|
let spliced_input: Vec<&str> = input.split_whitespace().collect();
|
||||||
|
if spliced_input.len() != 2 || spliced_input[0] != "NAME" {
|
||||||
|
return Err(Error::new(ErrorKind::Other, "BAD REQ"));
|
||||||
|
}
|
||||||
|
let username = String::from(spliced_input[1]);
|
||||||
|
let mut used = false;
|
||||||
|
{
|
||||||
|
let lock = clients.lock().unwrap();
|
||||||
|
for (_, entry) in (*lock).iter() {
|
||||||
|
if username == entry.0 {
|
||||||
|
used = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if used == false {
|
||||||
|
send!("NAME OK");
|
||||||
|
return Ok(username);
|
||||||
|
} else {
|
||||||
|
send!("NAME FAILURE");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// return Ok(String::new());
|
||||||
|
}
|
||||||
|
}
|
||||||
})()
|
})()
|
||||||
{
|
{
|
||||||
Ok(name) => name,
|
Ok(name) => name,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!(
|
println!(
|
||||||
"{} Client {} disappeared during initialization: {}",
|
"{time} Client {addr} encountered an error: {err}",
|
||||||
get_time(),
|
time = get_time(),
|
||||||
client,
|
addr = client,
|
||||||
e
|
err = e
|
||||||
);
|
);
|
||||||
|
writeln!(writer, "{}", e).unwrap();
|
||||||
|
writer.flush().unwrap();
|
||||||
return ();
|
return ();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -194,26 +278,63 @@ fn handle_client(stream: TcpStream, clients: Arc<Mutex<UserMap>>) {
|
|||||||
writeln!(writer, "WELCOME").unwrap();
|
writeln!(writer, "WELCOME").unwrap();
|
||||||
writer.flush().unwrap();
|
writer.flush().unwrap();
|
||||||
|
|
||||||
// Chat loop: Receive messages from users
|
// Chat loop: Receive messages from users once connected
|
||||||
match (|| loop {
|
match (|| loop {
|
||||||
match receive!().as_str() {
|
match receive!().as_str() {
|
||||||
"BYE" => {
|
|
||||||
send!("BYE");
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
"PING" => {
|
|
||||||
send!("PONG");
|
|
||||||
}
|
|
||||||
"REQ CLIENTS" => {
|
|
||||||
let mut lock = clients.lock().unwrap();
|
|
||||||
send_clients_name(&client, &mut lock);
|
|
||||||
}
|
|
||||||
input => {
|
input => {
|
||||||
println!("{} {} <{}>: {}", get_time(), client, name, input);
|
println!(
|
||||||
{
|
"{time} {nick}@{addr}: {message}",
|
||||||
let mut lock = clients.lock().unwrap();
|
time = get_time(),
|
||||||
distribute_message(&format!("{}", input), &client, &mut lock, true);
|
addr = client,
|
||||||
|
nick = name,
|
||||||
|
message = input
|
||||||
|
);
|
||||||
|
|
||||||
|
match input {
|
||||||
|
"BYE" => {
|
||||||
|
send!("BYE");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
"PING" => send!("PONG"),
|
||||||
|
|
||||||
|
"REQ CLIENTS" => {
|
||||||
|
let mut lock = clients.lock().unwrap();
|
||||||
|
send_clients_name(&client, &mut lock);
|
||||||
|
}
|
||||||
|
input => {
|
||||||
|
let spliced_input: Vec<&str> = input.split_whitespace().collect();
|
||||||
|
match spliced_input[0] {
|
||||||
|
"MSG" => {
|
||||||
|
let mut message = String::new();
|
||||||
|
for i in 1..spliced_input.len() {
|
||||||
|
message.push_str(spliced_input[i]);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut lock = clients.lock().unwrap();
|
||||||
|
distribute_message(
|
||||||
|
&format!("{}", input),
|
||||||
|
&client,
|
||||||
|
&mut lock,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!(
|
||||||
|
"{time} Sending: BAD REQ. Cause: {message}",
|
||||||
|
time = get_time(),
|
||||||
|
message = input
|
||||||
|
);
|
||||||
|
send!("BAD REQ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// {
|
||||||
|
// let mut lock = clients.lock().unwrap();
|
||||||
|
// distribute_message(&format!("{}", input), &client, &mut lock, true);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
|
Loading…
Reference in New Issue
Block a user