improvements to join/leave room

This commit is contained in:
David Westgate 2023-11-25 17:18:16 -08:00
parent da336e41be
commit b7c7be8dca
2 changed files with 76 additions and 39 deletions

View File

@ -74,33 +74,56 @@ fn users(stream: &mut TcpStream) {
fn msg(stream: &mut TcpStream) {} fn msg(stream: &mut TcpStream) {}
fn join(nick: &str, room: &str, stream: &mut TcpStream) { fn join(nick: &str, room: &str, stream: &mut TcpStream) {
#[cfg(debug_assertions)]
println!("nick {} joining room s{} ", nick, room);
let size = room.to_string().capacity() + nick.to_string().capacity() + 2; let size = room.to_string().capacity() + nick.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] = codes::client::JOIN_ROOM; out_buf[byte] = codes::client::JOIN_ROOM;
byte+=1; byte += 1;
for i in 0..nick.len() { for i in 0..nick.len() {
out_buf[byte] = *nick.as_bytes().get(i).unwrap(); out_buf[byte] = *nick.as_bytes().get(i).unwrap();
byte+=1; byte += 1;
} }
out_buf[byte] = 0x20; out_buf[byte] = 0x20;
byte += 1; byte += 1;
for i in 0.. room.len() { for i in 0..room.len() {
out_buf[byte] = *room.as_bytes().get(i).unwrap(); out_buf[byte] = *room.as_bytes().get(i).unwrap();
byte+=1; byte += 1;
} }
stream.write(&out_buf); stream.write(&out_buf);
} }
fn show(stream: &mut TcpStream) {} fn show(stream: &mut TcpStream) {}
fn leave(stream: &mut TcpStream) {} fn leave(nick: &str, room: &str, stream: &mut TcpStream) {
let size = room.to_string().capacity() + nick.to_string().capacity() + 2;
let mut out_buf: Vec<u8> = vec![0; size];
let mut byte: usize = 0;
out_buf[byte] = codes::client::LEAVE_ROOM;
byte += 1;
for i in 0..nick.len() {
out_buf[byte] = *nick.as_bytes().get(i).unwrap();
byte += 1;
}
out_buf[byte] = 0x20;
byte += 1;
for i in 0..room.len() {
out_buf[byte] = *room.as_bytes().get(i).unwrap();
byte += 1;
}
stream.write(&out_buf);
}
pub fn start() { pub fn start() {
println!("Starting the IRC client"); println!("Starting the IRC client. No spaces allowed in nicknames or room names");
let nick: String = input!("Enter your nickname: "); let mut nick: String;
loop {
nick = input!("Enter your nickname : ");
if nick.contains(" ") {
println!("May not contain spaces. Try again");
} else {
break;
}
}
// let host: String = input!("Enter the server host: "); // let host: String = input!("Enter the server host: ");
let host: &str = "localhost"; let host: &str = "localhost";
@ -130,10 +153,13 @@ pub fn start() {
"/users" => users(&mut stream), "/users" => users(&mut stream),
"/join" => { "/join" => {
let room = *cmds.get(1).unwrap(); let room = *cmds.get(1).unwrap();
join(&nick,room ,&mut stream) join(&nick, room, &mut stream)
}, }
"/show" => show(&mut stream), "/show" => show(&mut stream),
"/leave" => leave(&mut stream), "/leave" => {
let room = *cmds.get(1).unwrap();
leave(&nick, room, &mut stream)
}
"/msg" => msg(&mut stream), "/msg" => msg(&mut stream),
_ => msg(&mut stream), _ => msg(&mut stream),

View File

@ -27,10 +27,6 @@ impl Server {
} }
} }
fn read_op() {}
fn write_op() {}
fn handle_client( fn handle_client(
server: &Arc<Mutex<Server>>, server: &Arc<Mutex<Server>>,
stream: &mut TcpStream, stream: &mut TcpStream,
@ -40,53 +36,47 @@ fn handle_client(
// handle user commands // handle user commands
match cmd_bytes[0] { match cmd_bytes[0] {
codes::client::REGISTER_NICK => { codes::client::REGISTER_NICK => {
#[cfg(debug_assertions)]
println!("REGISTER_NICK");
let nickname: String = String::from_utf8_lossy(param_bytes).to_string(); let nickname: String = String::from_utf8_lossy(param_bytes).to_string();
register_nick(server, nickname, stream); register_nick(server, nickname, stream);
} }
codes::client::LIST_ROOMS => { codes::client::LIST_ROOMS => {
let unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap(); let unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
#[cfg(debug_assertions)]
println!("LIST_ROOMS");
let mut buf_out: Vec<u8> = Vec::new(); let mut buf_out: Vec<u8> = Vec::new();
buf_out.extend_from_slice(&[codes::RESPONSE]); buf_out.extend_from_slice(&[codes::RESPONSE]);
for (room, user) in &unlocked_server.rooms { for (room, user) in &unlocked_server.rooms {
buf_out.extend_from_slice(room.as_bytes()); buf_out.extend_from_slice(room.as_bytes());
buf_out.extend_from_slice(&[0x20]);
} }
stream.write(&buf_out); stream.write(&buf_out);
} }
codes::client::LIST_USERS => { codes::client::LIST_USERS => {
let unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap(); let unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
#[cfg(debug_assertions)]
println!("LIST_USERS");
let mut buf_out: Vec<u8> = Vec::new(); let mut buf_out: Vec<u8> = Vec::new();
buf_out.extend_from_slice(&[codes::RESPONSE]); buf_out.extend_from_slice(&[codes::RESPONSE]);
for (user) in &unlocked_server.users { for (user) in &unlocked_server.users {
buf_out.extend_from_slice(user.as_bytes()); buf_out.extend_from_slice(user.as_bytes());
buf_out.extend_from_slice(&[0x20]);
} }
#[cfg(debug_assertions)]
println!("buf users list {:?}", buf_out);
stream.write(&buf_out); stream.write(&buf_out);
} }
codes::client::JOIN_ROOM => {
#[cfg(debug_assertions)]
println!("JOIN_ROOM ");
codes::client::JOIN_ROOM => {
let p: String = String::from_utf8_lossy(param_bytes).to_string(); let p: String = String::from_utf8_lossy(param_bytes).to_string();
let params: Vec<&str> = p.split(' ').collect(); let params: Vec<&str> = p.split(' ').collect();
let user = params.get(0).unwrap(); let user = params.get(0).unwrap();
let room = params.get(1).unwrap(); let room = params.get(1).unwrap();
join_room(server, *user, room, stream) join_room(server, *user, room, stream)
} }
codes::client::LEAVE_ROOM => { codes::client::LEAVE_ROOM => {
#[cfg(debug_assertions)] let p: String = String::from_utf8_lossy(param_bytes).to_string();
println!("LEAVE_ROOM"); let params: Vec<&str> = p.split(' ').collect();
let user = params.get(0).unwrap();
let room = params.get(1).unwrap();
leave_room(server, user, room, stream)
} }
codes::client::SEND_MESSAGE => { codes::client::SEND_MESSAGE => {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("SEND_MESSAGE"); println!("SEND_MESSAGE");
@ -105,7 +95,7 @@ fn register_nick(server: &Arc<Mutex<Server>>, nickname: String, stream: &mut Tcp
let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap(); let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
if unlocked_server.users.contains(&nickname) { if unlocked_server.users.contains(&nickname) {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
println!("nickname collision, {}", nickname); println!("Nickname Collision, {}", nickname);
stream.write_all(&[codes::ERROR, codes::error::NICKNAME_COLLISION]); stream.write_all(&[codes::ERROR, codes::error::NICKNAME_COLLISION]);
} else { } else {
// Add the user to the user list // Add the user to the user list
@ -128,6 +118,27 @@ fn join_room(server: &Arc<Mutex<Server>>, user: &str, room: &str, stream: &mut T
unlocked_server.rooms.insert(room.to_string(), list); unlocked_server.rooms.insert(room.to_string(), list);
} }
} }
stream.write_all(&[codes::RESPONSE_OK]);
}
fn leave_room(server: &Arc<Mutex<Server>>, user: &str, room: &str, stream: &mut TcpStream) {
let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap();
match unlocked_server.rooms.get_mut(room) {
Some(l) => {
let before_len = l.len();
l.retain(|item| item != user);
if l.len() == 0 {
unlocked_server.rooms.remove(room);
} else if l.len() == before_len {
stream.write_all(&[codes::ERROR, codes::error::INVALID_ROOM]);
} else {
stream.write_all(&[codes::RESPONSE_OK]);
}
}
None => {
stream.write_all(&[codes::ERROR, codes::error::INVALID_ROOM]);
}
}
} }
pub fn start() { pub fn start() {
@ -141,7 +152,7 @@ pub fn start() {
match tcpstream { match tcpstream {
Ok(mut stream) => { Ok(mut stream) => {
let mut buf_in: [u8; 1024] = [0; 1024]; let mut buf_in: [u8; 1024] = [0; 1024];
let server_inner = Arc::clone(&server_outer); let server_inner: Arc<Mutex<Server>> = Arc::clone(&server_outer);
thread::spawn(move || loop { thread::spawn(move || loop {
match stream.read(&mut buf_in) { match stream.read(&mut buf_in) {
@ -152,14 +163,14 @@ pub fn start() {
handle_client(&server_inner, &mut stream, cmd_bytes, param_bytes); handle_client(&server_inner, &mut stream, cmd_bytes, param_bytes);
} }
Err(_) => { Err(_) => {
println!("Error parsing client"); eprintln!("Error parsing client");
stream.write(&[codes::END]); stream.write(&[codes::END]);
break; break;
} }
} }
}); });
} }
Err(e) => { Err(_) => {
eprintln!("Error accepting connections!"); eprintln!("Error accepting connections!");
} }
} }