better handling of quit/close+ add types+ fmt
This commit is contained in:
parent
01ae72c6cc
commit
2f66815631
@ -1,5 +1,5 @@
|
|||||||
use prompted::input;
|
use prompted::input;
|
||||||
use rust_irc::{codes, clear};
|
use rust_irc::{clear, codes};
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::net::TcpStream;
|
use std::net::TcpStream;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
@ -11,7 +11,7 @@ fn no_param_op(opcode: u8, stream: &mut TcpStream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn one_param_op(opcode: u8, stream: &mut TcpStream, param: &str) {
|
fn one_param_op(opcode: u8, stream: &mut TcpStream, param: &str) {
|
||||||
let size = param.to_string().capacity() + 1;
|
let size: usize = param.to_string().capacity() + 1;
|
||||||
let mut out_buf: Vec<u8> = vec![0; size];
|
let mut out_buf: Vec<u8> = vec![0; size];
|
||||||
out_buf[0] = opcode;
|
out_buf[0] = opcode;
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ fn one_param_op(opcode: u8, stream: &mut TcpStream, param: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn two_param_op(opcode: u8, stream: &mut TcpStream, param0: &str, param1: &str) {
|
fn two_param_op(opcode: u8, stream: &mut TcpStream, param0: &str, param1: &str) {
|
||||||
let size = param0.to_string().capacity() + param1.to_string().capacity() + 2;
|
let size: usize = param0.to_string().capacity() + param1.to_string().capacity() + 2;
|
||||||
let mut out_buf: Vec<u8> = vec![0; size];
|
let mut out_buf: Vec<u8> = vec![0; size];
|
||||||
let mut byte: usize = 0;
|
let mut byte: usize = 0;
|
||||||
out_buf[byte] = opcode;
|
out_buf[byte] = opcode;
|
||||||
@ -44,10 +44,11 @@ fn read_messages(mut stream: TcpStream, nick: &str) {
|
|||||||
let mut buffer: [u8; 1024] = [0; 1024];
|
let mut buffer: [u8; 1024] = [0; 1024];
|
||||||
loop {
|
loop {
|
||||||
match stream.read(&mut buffer) {
|
match stream.read(&mut buffer) {
|
||||||
Ok(size) => {
|
Ok(0) => {
|
||||||
if size == 0 {
|
println!("Server closed the connection. Shutting down client");
|
||||||
break; //Server closed connection
|
std::process::exit(0);
|
||||||
}
|
}
|
||||||
|
Ok(size) => {
|
||||||
let msg_bytes: &[u8] = &buffer[..size];
|
let msg_bytes: &[u8] = &buffer[..size];
|
||||||
process_message(msg_bytes, nick);
|
process_message(msg_bytes, nick);
|
||||||
}
|
}
|
||||||
@ -61,16 +62,12 @@ fn read_messages(mut stream: TcpStream, nick: &str) {
|
|||||||
fn process_message(msg_bytes: &[u8], nick: &str) {
|
fn process_message(msg_bytes: &[u8], nick: &str) {
|
||||||
println!();
|
println!();
|
||||||
match msg_bytes[0] {
|
match msg_bytes[0] {
|
||||||
codes::ERROR =>
|
codes::ERROR => match msg_bytes[1] {
|
||||||
{
|
|
||||||
match msg_bytes[1] {
|
|
||||||
codes::error::INVALID_ROOM => {
|
codes::error::INVALID_ROOM => {
|
||||||
println!("Operation Performed on an invalid room. Try again");
|
println!("Operation Performed on an invalid room. Try again");
|
||||||
}
|
}
|
||||||
codes::error::NICKNAME_COLLISION => {
|
codes::error::NICKNAME_COLLISION => {
|
||||||
println!(
|
println!("Nickname already in use on server. Connect again with a different one");
|
||||||
"Nickname already in use on server. Connect again with a different one"
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
codes::error::SERVER_FULL => {
|
codes::error::SERVER_FULL => {
|
||||||
println!("Server is full. Try again later");
|
println!("Server is full. Try again later");
|
||||||
@ -78,12 +75,11 @@ fn process_message(msg_bytes: &[u8], nick: &str) {
|
|||||||
_ => {
|
_ => {
|
||||||
println!("Error code: {:x?}", msg_bytes[1]);
|
println!("Error code: {:x?}", msg_bytes[1]);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
|
|
||||||
codes::client::MESSAGE => {
|
codes::client::MESSAGE => {
|
||||||
let message = String::from_utf8(msg_bytes[1..msg_bytes.len()].to_vec()).unwrap();
|
let message = String::from_utf8(msg_bytes[1..msg_bytes.len()].to_vec()).unwrap();
|
||||||
println!("{}", message);
|
println!("[server]:{}", message);
|
||||||
}
|
}
|
||||||
codes::client::MESSAGE_ROOM => {
|
codes::client::MESSAGE_ROOM => {
|
||||||
let params = String::from_utf8(msg_bytes[1..msg_bytes.len()].to_vec()).unwrap();
|
let params = String::from_utf8(msg_bytes[1..msg_bytes.len()].to_vec()).unwrap();
|
||||||
@ -151,9 +147,7 @@ pub fn start() {
|
|||||||
nick = input!("Enter your nickname : ");
|
nick = input!("Enter your nickname : ");
|
||||||
if nick.contains(" ") {
|
if nick.contains(" ") {
|
||||||
println!("May not contain spaces . Try again");
|
println!("May not contain spaces . Try again");
|
||||||
|
} else if nick.is_empty() {
|
||||||
}
|
|
||||||
else if nick.is_empty() {
|
|
||||||
println!("May not be empty . Try again");
|
println!("May not be empty . Try again");
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -168,7 +162,7 @@ pub fn start() {
|
|||||||
|
|
||||||
//another stream for reading messages
|
//another stream for reading messages
|
||||||
let stream_clone: TcpStream = stream.try_clone().expect("Failed to clone stream");
|
let stream_clone: TcpStream = stream.try_clone().expect("Failed to clone stream");
|
||||||
let nick_clone = nick.clone();
|
let nick_clone: String = nick.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
read_messages(stream_clone, &nick_clone);
|
read_messages(stream_clone, &nick_clone);
|
||||||
});
|
});
|
||||||
@ -185,7 +179,10 @@ pub fn start() {
|
|||||||
Some(cmd) => {
|
Some(cmd) => {
|
||||||
let param: Option<&str> = args.next();
|
let param: Option<&str> = args.next();
|
||||||
match cmd {
|
match cmd {
|
||||||
"/quit" => {disconnect(&mut stream); break},
|
"/quit" => {
|
||||||
|
disconnect(&mut stream);
|
||||||
|
break;
|
||||||
|
}
|
||||||
"/rooms" => no_param_op(codes::client::LIST_ROOMS, &mut stream),
|
"/rooms" => no_param_op(codes::client::LIST_ROOMS, &mut stream),
|
||||||
"/users" => no_param_op(codes::client::LIST_USERS, &mut stream),
|
"/users" => no_param_op(codes::client::LIST_USERS, &mut stream),
|
||||||
"/list" => match param {
|
"/list" => match param {
|
||||||
|
@ -8,7 +8,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use prompted::input;
|
use prompted::input;
|
||||||
use rust_irc::{codes, clear};
|
use rust_irc::{clear, codes};
|
||||||
|
|
||||||
const SERVER_ADDRESS: &str = "0.0.0.0:6667";
|
const SERVER_ADDRESS: &str = "0.0.0.0:6667";
|
||||||
const MAX_USERS: usize = 20;
|
const MAX_USERS: usize = 20;
|
||||||
@ -28,7 +28,6 @@ impl Server {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn message(room: &str, msg: &str, sender: &str, server: &Arc<Mutex<Server>>) {
|
fn message(room: &str, msg: &str, sender: &str, server: &Arc<Mutex<Server>>) {
|
||||||
let size = room.len() + msg.len() + sender.len() + 3;
|
let size = room.len() + msg.len() + sender.len() + 3;
|
||||||
let mut out_buf: Vec<u8> = vec![0; size];
|
let mut out_buf: Vec<u8> = vec![0; size];
|
||||||
@ -71,15 +70,15 @@ fn message(room: &str, msg: &str, sender: &str, server: &Arc<Mutex<Server>>) {
|
|||||||
str.write_all(&out_buf).unwrap();
|
str.write_all(&out_buf).unwrap();
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
//TODO send error msg to sender
|
||||||
eprintln!("Error: Invalid message from client");
|
eprintln!("Error: Invalid message from client");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
//TODO send error msg to sender
|
||||||
eprintln!("Error: Invalid message from client");
|
eprintln!("Error: Invalid message from client");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,20 +93,21 @@ fn broadcast(op: u8, server: &Arc<Mutex<Server>>, message: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
|
let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
|
||||||
let streams: std::collections::hash_map::ValuesMut<'_, String, TcpStream> = unlocked_server.users.values_mut();
|
let streams: std::collections::hash_map::ValuesMut<'_, String, TcpStream> =
|
||||||
|
unlocked_server.users.values_mut();
|
||||||
for stream in streams {
|
for stream in streams {
|
||||||
stream.write_all(&out_buf).unwrap();
|
stream.write_all(&out_buf).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn disconnect_all(server: &Arc<Mutex<Server>>,) {
|
fn disconnect_all(server: &Arc<Mutex<Server>>) {
|
||||||
let mut guard: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
|
let mut guard: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
|
||||||
let users: std::collections::hash_map::ValuesMut<'_, String, TcpStream> = guard.users.values_mut();
|
let users: std::collections::hash_map::ValuesMut<'_, String, TcpStream> =
|
||||||
|
guard.users.values_mut();
|
||||||
users.for_each(|user: &mut TcpStream| {
|
users.for_each(|user: &mut TcpStream| {
|
||||||
user.write(&[codes::QUIT]).unwrap();
|
user.write(&[codes::QUIT]).unwrap();
|
||||||
user.shutdown(std::net::Shutdown::Both);
|
user.shutdown(std::net::Shutdown::Both).unwrap();
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_client(
|
fn handle_client(
|
||||||
@ -188,8 +188,6 @@ fn handle_client(
|
|||||||
|
|
||||||
codes::client::MESSAGE_ROOM => {
|
codes::client::MESSAGE_ROOM => {
|
||||||
let p: String = String::from_utf8_lossy(param_bytes).to_string();
|
let p: String = String::from_utf8_lossy(param_bytes).to_string();
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
println!("MESSAGE_ROOM, {:?} ", p);
|
|
||||||
let params: Option<(&str, &str)> = p.split_once(" ");
|
let params: Option<(&str, &str)> = p.split_once(" ");
|
||||||
match params {
|
match params {
|
||||||
Some((room, msg)) => {
|
Some((room, msg)) => {
|
||||||
@ -223,7 +221,6 @@ fn remove_user(server: &Arc<Mutex<Server>>, nickname: &str, stream: &mut TcpStre
|
|||||||
});
|
});
|
||||||
let users: &mut HashMap<String, TcpStream> = &mut server.users;
|
let users: &mut HashMap<String, TcpStream> = &mut server.users;
|
||||||
users.remove(nickname);
|
users.remove(nickname);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn register_nick(server: &Arc<Mutex<Server>>, nickname: &str, stream: &mut TcpStream) {
|
fn register_nick(server: &Arc<Mutex<Server>>, nickname: &str, stream: &mut TcpStream) {
|
||||||
@ -275,8 +272,8 @@ fn leave_room(server: &Arc<Mutex<Server>>, user: &str, room: &str, stream: &mut
|
|||||||
let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
|
let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
|
||||||
match unlocked_server.rooms.get_mut(room) {
|
match unlocked_server.rooms.get_mut(room) {
|
||||||
Some(l) => {
|
Some(l) => {
|
||||||
let before_len = l.len();
|
let before_len: usize = l.len();
|
||||||
l.retain(|item| item != user);
|
l.retain(|item: &String| item != user);
|
||||||
if l.len() == 0 {
|
if l.len() == 0 {
|
||||||
unlocked_server.rooms.remove(room);
|
unlocked_server.rooms.remove(room);
|
||||||
stream.write_all(&[codes::RESPONSE_OK]).unwrap();
|
stream.write_all(&[codes::RESPONSE_OK]).unwrap();
|
||||||
@ -312,10 +309,16 @@ pub fn start() {
|
|||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let nickname: String;
|
let nickname: String;
|
||||||
println!("IP {} has connected", stream.peer_addr().unwrap().to_string());
|
println!(
|
||||||
|
"IP {} has connected",
|
||||||
|
stream.peer_addr().unwrap().to_string()
|
||||||
|
);
|
||||||
match stream.read(&mut buf_in) {
|
match stream.read(&mut buf_in) {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
println!("IP {} has closed the connection", stream.peer_addr().unwrap().to_string());
|
println!(
|
||||||
|
"IP {} has closed the connection",
|
||||||
|
stream.peer_addr().unwrap().to_string()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
Ok(size) => {
|
Ok(size) => {
|
||||||
let cmd_bytes: &[u8] = &buf_in[0..1];
|
let cmd_bytes: &[u8] = &buf_in[0..1];
|
||||||
@ -326,7 +329,8 @@ pub fn start() {
|
|||||||
loop {
|
loop {
|
||||||
match stream.read(&mut buf_in) {
|
match stream.read(&mut buf_in) {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
println!("IP {} wit nickname {} has closed the connection", stream.peer_addr().unwrap().to_string(), nickname);
|
println!("IP {} with nickname {} has closed the connection", stream.peer_addr().unwrap().to_string(), nickname);
|
||||||
|
remove_user(&server_inner, &nickname, &mut stream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Ok(size) => {
|
Ok(size) => {
|
||||||
@ -383,7 +387,6 @@ pub fn start() {
|
|||||||
println!("Stopping Server");
|
println!("Stopping Server");
|
||||||
disconnect_all(&server);
|
disconnect_all(&server);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
1 => println!("Users: {:?}", server.lock().unwrap().users),
|
1 => println!("Users: {:?}", server.lock().unwrap().users),
|
||||||
2 => println!("Rooms: {:?}", server.lock().unwrap().rooms),
|
2 => println!("Rooms: {:?}", server.lock().unwrap().rooms),
|
||||||
|
Reference in New Issue
Block a user