more modularization; add comments
This commit is contained in:
parent
60b5013337
commit
8f3dcaac5a
@ -1,5 +1,6 @@
|
||||
use prompted::input;
|
||||
use rust_irc::{clear, codes, one_op_buf, one_param_buf, two_param_buf, DEFAULT_PORT};
|
||||
use rust_irc::buf_helpers::{one_op_buf, one_param_buf, two_param_buf};
|
||||
use rust_irc::{clear, codes, DEFAULT_PORT};
|
||||
use std::io::{Read, Write};
|
||||
use std::net::TcpStream;
|
||||
use std::sync::{Arc, Mutex};
|
||||
@ -43,7 +44,7 @@ fn process_message(msg_bytes: &[u8], nick: &str) {
|
||||
eprintln!("Server is full. Try again later");
|
||||
}
|
||||
codes::error::NOT_IN_ROOM => {
|
||||
eprintln!("Cannot send a message before joining room. Use /join [room].")
|
||||
eprintln!("Cannot interact with a room you have not joined. Use /join [room].")
|
||||
}
|
||||
codes::error::EMPTY_ROOM => {
|
||||
eprintln!("Room is Empty");
|
||||
@ -200,7 +201,7 @@ pub fn start() {
|
||||
},
|
||||
"/msg" => match param.split_once(' ') {
|
||||
Some((room, msg)) => {
|
||||
let out_buf = two_param_buf(codes::MESSAGE_ROOM, room, msg);
|
||||
let out_buf: Vec<u8> = two_param_buf(codes::MESSAGE_ROOM, room, msg);
|
||||
stream.write_all(&out_buf).unwrap();
|
||||
}
|
||||
_ => {
|
||||
|
82
src/lib.rs
82
src/lib.rs
@ -29,50 +29,50 @@ pub mod codes {
|
||||
}
|
||||
|
||||
pub const DEFAULT_PORT: u16 = 6667;
|
||||
|
||||
pub fn clear() {
|
||||
print!("\x1B[2J");
|
||||
}
|
||||
pub mod buf_helpers {
|
||||
pub const SPACE_BYTES: &[u8] = &[0x20];
|
||||
|
||||
pub const SPACE_BYTES: &[u8] = &[0x20];
|
||||
pub fn one_op_buf(opcode: u8) -> [u8; 1] {
|
||||
[opcode]
|
||||
}
|
||||
|
||||
pub fn one_op_buf(opcode: u8) -> [u8; 1] {
|
||||
[opcode]
|
||||
}
|
||||
|
||||
pub fn two_op_buf(opcode0: u8, opcode1: u8) -> [u8; 2] {
|
||||
[opcode0, opcode1]
|
||||
}
|
||||
|
||||
pub fn one_param_buf(opcode: u8, param: &str) -> Vec<u8> {
|
||||
let opcode_buf: &[u8; 1] = &[opcode];
|
||||
let param_buf: &[u8] = param.as_bytes();
|
||||
let out_buf: Vec<u8> = [opcode_buf, param_buf].concat();
|
||||
out_buf
|
||||
}
|
||||
|
||||
pub fn two_param_buf(opcode: u8, param0: &str, param1: &str) -> Vec<u8> {
|
||||
let opcode_buf: &[u8; 1] = &[opcode];
|
||||
let param0_buf: &[u8] = param0.as_bytes();
|
||||
let param1_buf: &[u8] = param1.as_bytes();
|
||||
let out_buf: Vec<u8> = [opcode_buf, param0_buf, SPACE_BYTES, param1_buf].concat();
|
||||
out_buf
|
||||
}
|
||||
|
||||
pub fn three_param_buf(opcode: u8, param0: &str, param1: &str, param2: &str) -> Vec<u8> {
|
||||
let opcode_buf: &[u8; 1] = &[opcode];
|
||||
let param0_buf: &[u8] = param0.as_bytes();
|
||||
let param1_buf: &[u8] = param1.as_bytes();
|
||||
let param2_buf: &[u8] = param2.as_bytes();
|
||||
|
||||
let out_buf: Vec<u8> = [
|
||||
opcode_buf,
|
||||
param0_buf,
|
||||
SPACE_BYTES,
|
||||
param1_buf,
|
||||
SPACE_BYTES,
|
||||
param2_buf,
|
||||
]
|
||||
.concat();
|
||||
out_buf
|
||||
pub fn two_op_buf(opcode0: u8, opcode1: u8) -> [u8; 2] {
|
||||
[opcode0, opcode1]
|
||||
}
|
||||
|
||||
pub fn one_param_buf(opcode: u8, param: &str) -> Vec<u8> {
|
||||
let opcode_buf: &[u8; 1] = &[opcode];
|
||||
let param_buf: &[u8] = param.as_bytes();
|
||||
let out_buf: Vec<u8> = [opcode_buf, param_buf].concat();
|
||||
out_buf
|
||||
}
|
||||
|
||||
pub fn two_param_buf(opcode: u8, param0: &str, param1: &str) -> Vec<u8> {
|
||||
let opcode_buf: &[u8; 1] = &[opcode];
|
||||
let param0_buf: &[u8] = param0.as_bytes();
|
||||
let param1_buf: &[u8] = param1.as_bytes();
|
||||
let out_buf: Vec<u8> = [opcode_buf, param0_buf, SPACE_BYTES, param1_buf].concat();
|
||||
out_buf
|
||||
}
|
||||
|
||||
pub fn three_param_buf(opcode: u8, param0: &str, param1: &str, param2: &str) -> Vec<u8> {
|
||||
let opcode_buf: &[u8; 1] = &[opcode];
|
||||
let param0_buf: &[u8] = param0.as_bytes();
|
||||
let param1_buf: &[u8] = param1.as_bytes();
|
||||
let param2_buf: &[u8] = param2.as_bytes();
|
||||
|
||||
let out_buf: Vec<u8> = [
|
||||
opcode_buf,
|
||||
param0_buf,
|
||||
SPACE_BYTES,
|
||||
param1_buf,
|
||||
SPACE_BYTES,
|
||||
param2_buf,
|
||||
]
|
||||
.concat();
|
||||
out_buf
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,8 @@ use std::{
|
||||
};
|
||||
|
||||
use prompted::input;
|
||||
use rust_irc::{
|
||||
clear, codes, one_op_buf, one_param_buf, three_param_buf, two_op_buf, DEFAULT_PORT,
|
||||
};
|
||||
use rust_irc::buf_helpers::{one_op_buf, one_param_buf, three_param_buf, two_op_buf};
|
||||
use rust_irc::{clear, codes, DEFAULT_PORT};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Server {
|
||||
@ -43,10 +42,8 @@ fn message_room(room: &str, msg: &str, sender: &str, server: &Arc<Mutex<Server>>
|
||||
.unwrap()
|
||||
.try_clone()
|
||||
.expect("Clone issue");
|
||||
//1
|
||||
match room_users {
|
||||
Some(users) => {
|
||||
//2
|
||||
let mut is_member = false;
|
||||
for user in users {
|
||||
if user.eq(sender) {
|
||||
@ -57,12 +54,10 @@ fn message_room(room: &str, msg: &str, sender: &str, server: &Arc<Mutex<Server>>
|
||||
if is_member {
|
||||
for user in users {
|
||||
if user.eq(sender) {
|
||||
//4
|
||||
sender_stream
|
||||
.write_all(&one_op_buf(codes::RESPONSE_OK))
|
||||
.unwrap();
|
||||
} else {
|
||||
//3
|
||||
let recipient_stream: Option<&mut TcpStream> = server.users.get_mut(user);
|
||||
match recipient_stream {
|
||||
Some(str) => {
|
||||
@ -305,18 +300,15 @@ fn leave_room(server: &Arc<Mutex<Server>>, user: &str, room: &str, stream: &mut
|
||||
Some(l) => {
|
||||
let before_len: usize = l.len();
|
||||
l.retain(|item: &String| item != user);
|
||||
if l.is_empty() {
|
||||
unlocked_server.rooms.remove(room);
|
||||
drop(unlocked_server);
|
||||
let rooms: Vec<String> = get_rooms_of_user(server, user);
|
||||
let rooms_expanded: String = rooms.join(",");
|
||||
let response: String = format!("Left {}. Current rooms: {}", room, rooms_expanded);
|
||||
let out_buf: Vec<u8> = one_param_buf(codes::RESPONSE, &response);
|
||||
stream.write_all(&out_buf).unwrap();
|
||||
} else if l.len() == before_len {
|
||||
let err_buf: [u8; 2] = two_op_buf(codes::ERROR, codes::error::INVALID_ROOM);
|
||||
|
||||
// case when the user was not found to be in the room.
|
||||
if l.len() == before_len {
|
||||
let err_buf: [u8; 2] = two_op_buf(codes::ERROR, codes::error::NOT_IN_ROOM);
|
||||
stream.write_all(&err_buf).unwrap();
|
||||
} else {
|
||||
if l.is_empty() {
|
||||
unlocked_server.rooms.remove(room); //drop the room if this was the last member
|
||||
}
|
||||
drop(unlocked_server);
|
||||
let rooms: Vec<String> = get_rooms_of_user(server, user);
|
||||
let rooms_expanded: String = rooms.join(",");
|
||||
@ -350,6 +342,11 @@ fn get_rooms_of_user(server: &Arc<Mutex<Server>>, user: &str) -> Vec<String> {
|
||||
result
|
||||
}
|
||||
|
||||
/// Entrypoint for the server
|
||||
/// Main thread -> Main Menu
|
||||
/// We spawn one thread to manage the entire TCP incoming process (seperate from main thread)
|
||||
/// Each connected IP gets a spawned thread in the `for` loop
|
||||
/// Before looping to handle generic client input, we handle the special case of the nickname registration requirnment
|
||||
pub fn start() {
|
||||
let mut host: String = "0.0.0.0:".to_string();
|
||||
host.push_str(&DEFAULT_PORT.to_string());
|
||||
|
58
tests/test_lib.rs
Normal file
58
tests/test_lib.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use rust_irc::{
|
||||
buf_helpers::{
|
||||
one_op_buf, one_param_buf, three_param_buf, two_op_buf, two_param_buf, SPACE_BYTES,
|
||||
},
|
||||
codes,
|
||||
};
|
||||
|
||||
#[test]
|
||||
pub fn test_one_op_buf() {
|
||||
let buf_in: [u8; 1] = one_op_buf(codes::RESPONSE_OK);
|
||||
assert_eq!(buf_in, [codes::RESPONSE_OK])
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_two_op_buf() {
|
||||
let buf_in: [u8; 2] = two_op_buf(codes::ERROR, codes::error::ALREADY_IN_ROOM);
|
||||
assert_eq!(buf_in, [codes::ERROR, codes::error::ALREADY_IN_ROOM]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_one_param_buf() {
|
||||
let opcode_buf: &[u8; 1] = &[codes::MESSAGE];
|
||||
let string_buf: &[u8] = "hello world".as_bytes();
|
||||
let checker_buf: Vec<u8> = [opcode_buf, string_buf].concat();
|
||||
let result: Vec<u8> = one_param_buf(codes::MESSAGE, "hello world");
|
||||
assert_eq!(result, checker_buf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_two_param_buf() {
|
||||
let opcode_buf: &[u8; 1] = &[codes::MESSAGE];
|
||||
let string0_buf: &[u8] = "cat".as_bytes();
|
||||
let string1_buf: &[u8] = "dog".as_bytes();
|
||||
|
||||
let checker_buf: Vec<u8> = [opcode_buf, string0_buf, SPACE_BYTES, string1_buf].concat();
|
||||
let result: Vec<u8> = two_param_buf(codes::MESSAGE, "cat", "dog");
|
||||
assert_eq!(result, checker_buf);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_three_param_buf() {
|
||||
let opcode_buf: &[u8; 1] = &[codes::MESSAGE];
|
||||
let string0_buf: &[u8] = "cat".as_bytes();
|
||||
let string1_buf: &[u8] = "dog".as_bytes();
|
||||
let string2_buf: &[u8] = "frog".as_bytes();
|
||||
|
||||
let checker_buf: Vec<u8> = [
|
||||
opcode_buf,
|
||||
string0_buf,
|
||||
SPACE_BYTES,
|
||||
string1_buf,
|
||||
SPACE_BYTES,
|
||||
string2_buf,
|
||||
]
|
||||
.concat();
|
||||
let result: Vec<u8> = three_param_buf(codes::MESSAGE, "cat", "dog", "frog");
|
||||
assert_eq!(result, checker_buf);
|
||||
}
|
Reference in New Issue
Block a user