further work on server and client cmd implementation
This commit is contained in:
parent
7e4a6578dc
commit
52c757ea3a
@ -1,6 +1,6 @@
|
|||||||
use prompted::input;
|
use prompted::input;
|
||||||
use rust_irc::codes::client::*;
|
use rust_irc::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;
|
||||||
|
|
||||||
@ -12,8 +12,8 @@ fn read_messages(mut stream: TcpStream) {
|
|||||||
if size == 0 {
|
if size == 0 {
|
||||||
break; //Server closed connection
|
break; //Server closed connection
|
||||||
}
|
}
|
||||||
let message: &[u8] = &buffer[..size];
|
let msg_bytes: &[u8] = &buffer[..size];
|
||||||
process_message(message);
|
process_message(msg_bytes);
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
break;
|
break;
|
||||||
@ -22,12 +22,62 @@ fn read_messages(mut stream: TcpStream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_message(message: &[u8]) {
|
fn process_message(msg_bytes: &[u8]) {
|
||||||
if let Ok(text) = String::from_utf8(message.to_vec()) {
|
match msg_bytes[0] {
|
||||||
println!("from serv: {}", text);
|
codes::ERROR => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("err: {:x?}", msg_bytes[1]);
|
||||||
|
match msg_bytes[1] {
|
||||||
|
codes::error::INVALID_ROOM => {
|
||||||
|
println!("Attempted to message non-existant room. Try again");
|
||||||
|
}
|
||||||
|
codes::error::NICKNAME_COLLISION => {
|
||||||
|
println!(
|
||||||
|
"Nickname already in use on server. Connect again with a different one"
|
||||||
|
);
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
codes::error::SERVER_FULL => {
|
||||||
|
println!("Server is full. Try again later");
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("Unknown error code {:x?}", msg_bytes[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
codes::RESPONSE_OK => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("RESPONSE_OK");
|
||||||
|
}
|
||||||
|
codes::RESPONSE => {
|
||||||
|
let message = String::from_utf8(msg_bytes[1..msg_bytes.len()].to_vec()).unwrap();
|
||||||
|
println!("{}", message);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("BAD RESPONSE = {:x?} ", msg_bytes[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn disconnect() {}
|
||||||
|
|
||||||
|
fn rooms(stream: &mut TcpStream) {
|
||||||
|
stream.write(&[codes::client::LIST_ROOMS]);
|
||||||
|
}
|
||||||
|
fn users(stream: &mut TcpStream) {
|
||||||
|
stream.write(&[codes::client::LIST_USERS]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn msg(stream: &mut TcpStream) {}
|
||||||
|
|
||||||
|
fn join(stream: &mut TcpStream) {}
|
||||||
|
|
||||||
|
fn show(stream: &mut TcpStream) {}
|
||||||
|
fn leave(stream: &mut TcpStream) {}
|
||||||
|
|
||||||
pub fn start() {
|
pub fn start() {
|
||||||
println!("Starting the IRC client");
|
println!("Starting the IRC client");
|
||||||
let nick: String = input!("Enter your nickname: ");
|
let nick: String = input!("Enter your nickname: ");
|
||||||
@ -37,34 +87,32 @@ pub fn start() {
|
|||||||
if let Ok(mut stream) = TcpStream::connect(host.to_owned() + ":6667") {
|
if let Ok(mut stream) = TcpStream::connect(host.to_owned() + ":6667") {
|
||||||
println!("Connected to {}", host);
|
println!("Connected to {}", host);
|
||||||
|
|
||||||
//try to register the nickname
|
|
||||||
let mut buf: Vec<u8> = vec![0; nick.capacity()];
|
|
||||||
buf[0] = REGISTER_NICK;
|
|
||||||
for i in 1..nick.len()+1 {
|
|
||||||
buf[i] = *nick.as_bytes().get(i - 1).unwrap();
|
|
||||||
}
|
|
||||||
stream.write(&buf);
|
|
||||||
|
|
||||||
//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");
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
read_messages(stream_clone);
|
read_messages(stream_clone);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//try to register the nickname
|
||||||
|
let mut buf: Vec<u8> = vec![0; nick.capacity()];
|
||||||
|
buf[0] = codes::client::REGISTER_NICK;
|
||||||
|
for i in 1..nick.len() + 1 {
|
||||||
|
buf[i] = *nick.as_bytes().get(i - 1).unwrap();
|
||||||
|
}
|
||||||
|
stream.write(&buf);
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let cmd: String = input!(":");
|
let cmd: String = input!(":");
|
||||||
match cmd.trim() {
|
match cmd.trim() {
|
||||||
"/quit" => {}
|
"/quit" => disconnect(),
|
||||||
"/list" => {}
|
"/rooms" => rooms(&mut stream),
|
||||||
"/msq" => {}
|
"/users" => users(&mut stream),
|
||||||
"/join" => {}
|
"/join" => join(&mut stream),
|
||||||
"/show" => {}
|
"/show" => show(&mut stream),
|
||||||
"/leave" => {}
|
"/leave" => leave(&mut stream),
|
||||||
"/msg" => {}
|
"/msg" => msg(&mut stream),
|
||||||
|
|
||||||
_ => {
|
_ => msg(&mut stream),
|
||||||
stream.write(cmd.as_bytes());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -7,6 +7,7 @@ pub mod codes {
|
|||||||
pub const LIST_ROOMS: u8 = 0x04;
|
pub const LIST_ROOMS: u8 = 0x04;
|
||||||
pub const SEND_MESSAGE: u8 = 0x05;
|
pub const SEND_MESSAGE: u8 = 0x05;
|
||||||
pub const REGISTER_NICK: u8 = 0x06;
|
pub const REGISTER_NICK: u8 = 0x06;
|
||||||
|
pub const LIST_USERS: u8 = 0x07;
|
||||||
}
|
}
|
||||||
pub const KEEP_ALIVE: u8 = 0x0C;
|
pub const KEEP_ALIVE: u8 = 0x0C;
|
||||||
pub const RESPONSE: u8 = 0x0D;
|
pub const RESPONSE: u8 = 0x0D;
|
||||||
|
@ -27,31 +27,90 @@ impl Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_client(&mut self, mut stream: TcpStream) {
|
fn handle_client(&mut self, mut stream: TcpStream) {
|
||||||
let mut buffer: [u8; 1024] = [0; 1024];
|
// handle user commands
|
||||||
let nickname: String;
|
|
||||||
|
|
||||||
// Read the nickname from the client
|
loop {
|
||||||
match stream.read(&mut buffer) {
|
let mut buf_in: [u8; 1024] = [0; 1024];
|
||||||
|
|
||||||
|
match stream.read(&mut buf_in) {
|
||||||
Ok(size) => {
|
Ok(size) => {
|
||||||
let nickname_bytes = &buffer[0..size];
|
let cmd_bytes: &[u8] = &buf_in[0..1];
|
||||||
nickname = String::from_utf8_lossy(nickname_bytes).to_string();
|
let param_bytes: &[u8] = &buf_in[1..size];
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("Stream in ");
|
||||||
|
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();
|
||||||
|
self.register_nick(nickname, &mut stream);
|
||||||
|
}
|
||||||
|
codes::client::LIST_ROOMS => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("LIST_ROOMS");
|
||||||
|
let mut buf_out: Vec<u8> = Vec::new();
|
||||||
|
buf_out.extend_from_slice(&[codes::RESPONSE]);
|
||||||
|
for (room, user) in &self.rooms {
|
||||||
|
buf_out.extend_from_slice(room.as_bytes());
|
||||||
|
}
|
||||||
|
stream.write(&buf_out);
|
||||||
|
}
|
||||||
|
codes::client::LIST_ROOMS => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("LIST_ROOMS");
|
||||||
|
let mut buf_out: Vec<u8> = Vec::new();
|
||||||
|
buf_out.extend_from_slice(&[codes::RESPONSE]);
|
||||||
|
for (room, user) in &self.rooms {
|
||||||
|
buf_out.extend_from_slice(room.as_bytes());
|
||||||
|
}
|
||||||
|
stream.write(&buf_out);
|
||||||
|
}
|
||||||
|
codes::client::LIST_USERS => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("LIST_USERS");
|
||||||
|
let mut buf_out: Vec<u8> = Vec::new();
|
||||||
|
buf_out.extend_from_slice(&[codes::RESPONSE]);
|
||||||
|
for (user) in &self.users {
|
||||||
|
buf_out.extend_from_slice(user.as_bytes());
|
||||||
|
}
|
||||||
|
stream.write(&buf_out);
|
||||||
|
}
|
||||||
|
codes::client::JOIN_ROOM => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("JOIN_ROOM");
|
||||||
|
}
|
||||||
|
codes::client::LEAVE_ROOM => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("LEAVE_ROOM");
|
||||||
|
}
|
||||||
|
codes::client::SEND_MESSAGE => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("SEND_MESSAGE");
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("Unspecified client Op");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// Check for nickname collision
|
|
||||||
if self.users.contains(&nickname) {
|
|
||||||
stream.write_all(&[codes::ERROR, codes::error::NICKNAME_COLLISION]);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn register_nick(&mut self, nickname: String, stream: &mut TcpStream) {
|
||||||
|
// Check for nickname collision
|
||||||
|
if self.users.contains(&nickname) {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("nickname collision, {}", nickname);
|
||||||
|
stream.write_all(&[codes::ERROR, codes::error::NICKNAME_COLLISION]);
|
||||||
|
} else {
|
||||||
// Add the user to the user list
|
// Add the user to the user list
|
||||||
self.users.insert(nickname.clone());
|
self.users.insert(nickname.clone());
|
||||||
|
|
||||||
// Send response ok
|
// Send response ok
|
||||||
stream.write_all(&[codes::RESPONSE_OK]);
|
stream.write_all(&[codes::RESPONSE_OK]);
|
||||||
|
}
|
||||||
// handle user commands
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +146,8 @@ pub fn start() {
|
|||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
let mut cmd_buf: [i32; 2] = [0; 2];
|
let mut cmd_buf: [i32; 2] = [0; 2];
|
||||||
let mut local_server = server_mutx.lock().unwrap();
|
let mut local_server = server_mutx.lock().unwrap();
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
println!("match stream");
|
||||||
if local_server.users.len() < MAX_USERS {
|
if local_server.users.len() < MAX_USERS {
|
||||||
local_server.handle_client(stream);
|
local_server.handle_client(stream);
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user