diff --git a/src/client.rs b/src/client.rs index 7a6b522..dd97ecc 100644 --- a/src/client.rs +++ b/src/client.rs @@ -74,33 +74,56 @@ fn users(stream: &mut TcpStream) { fn msg(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 mut out_buf: Vec = vec![0; size]; - let mut byte:usize = 0; + let mut byte: usize = 0; out_buf[byte] = codes::client::JOIN_ROOM; - byte+=1; - for i in 0..nick.len() { + byte += 1; + for i in 0..nick.len() { out_buf[byte] = *nick.as_bytes().get(i).unwrap(); - byte+=1; + byte += 1; } out_buf[byte] = 0x20; byte += 1; - for i in 0.. room.len() { + for i in 0..room.len() { out_buf[byte] = *room.as_bytes().get(i).unwrap(); - byte+=1; + byte += 1; } stream.write(&out_buf); - } 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 = 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() { - println!("Starting the IRC client"); - let nick: String = input!("Enter your nickname: "); + println!("Starting the IRC client. No spaces allowed in nicknames or room names"); + 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: &str = "localhost"; @@ -130,10 +153,13 @@ pub fn start() { "/users" => users(&mut stream), "/join" => { let room = *cmds.get(1).unwrap(); - join(&nick,room ,&mut stream) - }, + join(&nick, room, &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(&mut stream), diff --git a/src/server.rs b/src/server.rs index 67a03df..852b412 100644 --- a/src/server.rs +++ b/src/server.rs @@ -27,10 +27,6 @@ impl Server { } } -fn read_op() {} - -fn write_op() {} - fn handle_client( server: &Arc>, stream: &mut TcpStream, @@ -40,53 +36,47 @@ fn handle_client( // handle user commands match cmd_bytes[0] { codes::client::REGISTER_NICK => { - #[cfg(debug_assertions)] - println!("REGISTER_NICK"); let nickname: String = String::from_utf8_lossy(param_bytes).to_string(); register_nick(server, nickname, stream); } codes::client::LIST_ROOMS => { let unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap(); - - #[cfg(debug_assertions)] - println!("LIST_ROOMS"); let mut buf_out: Vec = Vec::new(); buf_out.extend_from_slice(&[codes::RESPONSE]); for (room, user) in &unlocked_server.rooms { buf_out.extend_from_slice(room.as_bytes()); + buf_out.extend_from_slice(&[0x20]); } stream.write(&buf_out); } codes::client::LIST_USERS => { let unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap(); - - #[cfg(debug_assertions)] - println!("LIST_USERS"); let mut buf_out: Vec = Vec::new(); buf_out.extend_from_slice(&[codes::RESPONSE]); for (user) in &unlocked_server.users { 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); } - 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 params: Vec<&str> = p.split(' ').collect(); let user = params.get(0).unwrap(); let room = params.get(1).unwrap(); join_room(server, *user, room, stream) } + codes::client::LEAVE_ROOM => { - #[cfg(debug_assertions)] - println!("LEAVE_ROOM"); + let p: String = String::from_utf8_lossy(param_bytes).to_string(); + 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 => { #[cfg(debug_assertions)] println!("SEND_MESSAGE"); @@ -105,7 +95,7 @@ fn register_nick(server: &Arc>, nickname: String, stream: &mut Tcp let mut unlocked_server: std::sync::MutexGuard<'_, Server> = server.lock().unwrap(); if unlocked_server.users.contains(&nickname) { #[cfg(debug_assertions)] - println!("nickname collision, {}", nickname); + println!("Nickname Collision, {}", nickname); stream.write_all(&[codes::ERROR, codes::error::NICKNAME_COLLISION]); } else { // Add the user to the user list @@ -128,6 +118,27 @@ fn join_room(server: &Arc>, user: &str, room: &str, stream: &mut T unlocked_server.rooms.insert(room.to_string(), list); } } + stream.write_all(&[codes::RESPONSE_OK]); +} + +fn leave_room(server: &Arc>, 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() { @@ -141,7 +152,7 @@ pub fn start() { match tcpstream { Ok(mut stream) => { let mut buf_in: [u8; 1024] = [0; 1024]; - let server_inner = Arc::clone(&server_outer); + let server_inner: Arc> = Arc::clone(&server_outer); thread::spawn(move || loop { match stream.read(&mut buf_in) { @@ -152,14 +163,14 @@ pub fn start() { handle_client(&server_inner, &mut stream, cmd_bytes, param_bytes); } Err(_) => { - println!("Error parsing client"); + eprintln!("Error parsing client"); stream.write(&[codes::END]); break; } } }); } - Err(e) => { + Err(_) => { eprintln!("Error accepting connections!"); } }