From ca4b0259b9062c07bed8aaab0385b4348ceea7b4 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 09:40:34 +0000 Subject: [PATCH 01/16] moved commands into lib module --- src/{ => lib}/commands/behaviors.rs | 0 src/{ => lib}/commands/mod.rs | 0 src/lib/mod.rs | 1 + 3 files changed, 1 insertion(+) rename src/{ => lib}/commands/behaviors.rs (100%) rename src/{ => lib}/commands/mod.rs (100%) diff --git a/src/commands/behaviors.rs b/src/lib/commands/behaviors.rs similarity index 100% rename from src/commands/behaviors.rs rename to src/lib/commands/behaviors.rs diff --git a/src/commands/mod.rs b/src/lib/commands/mod.rs similarity index 100% rename from src/commands/mod.rs rename to src/lib/commands/mod.rs diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 0b03722..4ef91b1 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -2,6 +2,7 @@ pub mod prelude; pub mod server; pub mod Foundation; +pub mod commands; use std::sync::Arc; use std::sync::Mutex; From 6c89f341518d4edaa60009b7f819e88f70c736d8 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:03 +0000 Subject: [PATCH 02/16] added from vector trait to commands --- src/lib/commands/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/lib/commands/mod.rs b/src/lib/commands/mod.rs index a4a50a2..6d88eee 100644 --- a/src/lib/commands/mod.rs +++ b/src/lib/commands/mod.rs @@ -230,6 +230,14 @@ impl From<&mut [u8; 1024]> for Commands { } } +impl From<&mut Vec> for Commands { + fn from(data: &mut Vec) -> Self { + let incoming_message = String::from(String::from_utf8_lossy(data)); + data.zeroize(); + Commands::from(incoming_message) + } +} + // TODO: check if unit tests still work /*#[cfg(test)] mod test_commands_v2 { From 71fe467ca2b7b0d2446d051ca1bb836b317d610f Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:31 +0000 Subject: [PATCH 03/16] implemented basic connection handling in the server --- .../server/client_management/client/mod.rs | 2 +- src/lib/server/client_management/mod.rs | 74 ++++++------------- src/lib/server/client_management/traits.rs | 2 +- src/lib/server/mod.rs | 43 ++++++++++- src/main.rs | 7 +- 5 files changed, 68 insertions(+), 60 deletions(-) diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index 566eb3d..f69220d 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -32,7 +32,7 @@ pub enum ClientMessage { /// /// - stream: The socket for the connected client. /// - owner: An optional reference to the owning object. -#[derive(Serialize)] +#[derive(Debug, Serialize)] pub struct Client { pub uuid: Uuid, username: String, diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 330a0ed..532042f 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -1,6 +1,8 @@ pub mod client; mod traits; +// use crate::lib::server::ServerMessages; +use crate::lib::server::ServerMessages; use std::sync::Arc; use std::sync::Mutex; use std::sync::Weak; @@ -19,69 +21,45 @@ enum ClientManagerMessages {} /// # ClientManager /// This struct manages all connected users +#[derive(Debug)] pub struct ClientManager { clients: Mutex>>, - weak_self: Mutex>>, - server_ref: Mutex>, + // weak_self: Mutex>>, + + server_channel: Sender, sender: Sender, receiver: Receiver, } impl ClientManager { - pub fn new() -> Arc { + pub fn new(server_channel: Sender) -> Arc { - let channels = unbounded(); + let (sender, receiver) = unbounded(); - let manager_ref: Arc = Arc::new(ClientManager { + Arc::new(ClientManager { clients: Mutex::default(), - weak_self: Mutex::default(), + server_channel, - sender: channels.0, - receiver: channels.1, - }); - - // get the reference - { - let mut lock = manager_ref.weak_self.lock().unwrap(); - let tmp = manager_ref.clone(); - *lock = Some(Arc::downgrade(&tmp)); - } - - manager_ref.set_ref(manager_ref.clone()); - manager_ref - } - - fn set_ref(&self, reference: Arc) { - let mut lock = self.weak_self.lock().unwrap(); - *lock = Some(Arc::downgrade(&reference)); + sender, + receiver, + }) } } impl TClientManager for ClientManager { fn add_client(&self, client: std::sync::Arc) { - self.add_child(client); + self.clients.lock().unwrap().push(client); } - fn remove_client(&self, uuid: Uuid) { - let mut client_list = self.clients.lock().unwrap(); - client_list.sort(); - if let Ok(index) = client_list.binary_search_by(move |client| client.uuid.cmp(&uuid)) { - client_list.remove(index); - } + fn remove_client(&self, _uuid: Uuid) { + self.clients.lock().unwrap().sort(); } - fn message_client(&self, id: Uuid, msg: ClientMessage) -> Result<(), &str> { - let mut client_list = self.clients.lock().unwrap(); - client_list.sort(); - if let Ok(index) = client_list.binary_search_by(move |client| client.uuid.cmp(&id)) { - if let Some(client) = client_list.get(index) { - let _ = client.send_message(msg); - } - } - Ok(()) + fn message_client(&self, _id: Uuid, _msg: ClientMessage) { + todo!() } fn tick(&self) { @@ -90,16 +68,6 @@ impl TClientManager for ClientManager { } } -impl IOwner for ClientManager{ - fn add_child(&self, child: Arc) { - child.set_owner(self.get_ref()); - self.clients.lock().unwrap().push(child); - } - - fn get_ref(&self) -> Weak { - self.weak_self.lock().unwrap().unwrap().clone() - } -} #[cfg(test)] mod test { @@ -109,9 +77,9 @@ mod test { #[test] fn test_get_ref() { - let client_manager = ClientManager::new(); - let _cm_ref = client_manager.get_ref(); - assert_eq!(Arc::weak_count(&client_manager), 2); + // let client_manager = ClientManager::new(); + // let _cm_ref = client_manager.get_ref(); + // assert_eq!(Arc::weak_count(&client_manager), 2); } #[test] diff --git a/src/lib/server/client_management/traits.rs b/src/lib/server/client_management/traits.rs index 06c6243..a48af0a 100644 --- a/src/lib/server/client_management/traits.rs +++ b/src/lib/server/client_management/traits.rs @@ -8,6 +8,6 @@ use uuid::Uuid; pub trait TClientManager { fn add_client(&self, client: Arc); fn remove_client(&self, id: Uuid); - fn message_client(&self, id: Uuid, msg: TClientMessage) -> Result<(), &str>; + fn message_client(&self, id: Uuid, msg: TClientMessage); fn tick(&self, ); } \ No newline at end of file diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index f18cc6f..4b7edcc 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,15 +1,21 @@ pub mod client_management; -use crossbeam_channel::{Sender, Receiver, unbounded}; + use std::sync::{Arc, Weak, Mutex}; use std::net::TcpListener; +use std::io::Write; +use std::io::Read; + +use crossbeam_channel::{Sender, Receiver, unbounded}; use crate::lib::server::client_management::ClientManager; use crate::lib::Foundation::{IOwner, IOwned, ICooperative}; use client_management::client::Client; +use crate::lib::commands::Commands; -enum ServerMessages { - ClientConnected(Client), +#[derive(Debug)] +pub enum ServerMessages { + ClientConnected(Arc), } pub struct Server { @@ -27,7 +33,7 @@ impl Server { Arc::new(Server { server_socket: listener, - client_manager: ClientManager::new(sender), + client_manager: ClientManager::new(sender.clone()), sender, receiver, @@ -38,5 +44,34 @@ impl Server { impl ICooperative for Server{ fn tick(&self) { + let mut buffer = vec![0; 1024]; + + // get connections + for connection in self.server_socket.incoming() { + match connection { + Ok(mut stream) => { + let _ = stream.write(Commands::Request(None).to_string().as_bytes()); + let _ = stream.read(&mut buffer); + + let command = Commands::from(&mut buffer); + + match command { + Commands::Info(None) => {let _ = stream.write("todo".as_bytes());} + _ => {let _ = stream.write("not implemented!".as_bytes());} + } + + }, + _ => println!("!connection error occured!"), + } + } + + + + // message loop + for message in self.receiver.iter() { + match message { + ServerMessages::ClientConnected(client) => println!("client connected: {:?}", client), + } + } } } diff --git a/src/main.rs b/src/main.rs index 0f29b99..bdf0c97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ mod lib; use clap::{App, Arg}; use crate::lib::server::Server; +use crate::lib::Foundation::ICooperative; fn main() { let _args = App::new("--rust chat server--") @@ -18,7 +19,11 @@ fn main() { .takes_value(true)) .get_matches(); - let mut server = Server::new(); + let server = Server::new(); + + loop { + server.tick(); + } } From b66fdd62b3c7493a2a65dc8bf01a30a01d5feb92 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 17 Mar 2021 09:56:51 +0000 Subject: [PATCH 04/16] added implemetation of info command on te server --- src/lib/server/mod.rs | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 4b7edcc..49a5374 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -2,6 +2,7 @@ pub mod client_management; use std::sync::{Arc, Weak, Mutex}; +use std::collections::HashMap; use std::net::TcpListener; use std::io::Write; use std::io::Read; @@ -44,30 +45,38 @@ impl Server { impl ICooperative for Server{ fn tick(&self) { - let mut buffer = vec![0; 1024]; + let mut buffer = vec![0; 64]; - // get connections + // handle new connections for connection in self.server_socket.incoming() { match connection { Ok(mut stream) => { - let _ = stream.write(Commands::Request(None).to_string().as_bytes()); - let _ = stream.read(&mut buffer); + stream.write_all(Commands::Request(None).to_string().as_bytes()).expect("error writing socket"); + stream.read_to_end(&mut buffer).expect("error reading sokcet"); + + println!("buffer: {:?}", &buffer); let command = Commands::from(&mut buffer); match command { - Commands::Info(None) => {let _ = stream.write("todo".as_bytes());} + Commands::Info(None) => { + let server_config = vec![ + ("name".to_string(), "Test server".to_string()) + ]; + let map: HashMap = server_config.into_iter().collect(); + stream.write_all(Commands::Success(Some(map)).to_string().as_bytes()) + .expect("error sending response"); + } + Commands::Connect(Some(map)) => println!("connect command: {:?}", &map), + _ => {let _ = stream.write("not implemented!".as_bytes());} } - }, _ => println!("!connection error occured!"), } } - - - // message loop + // handle new messages loop for message in self.receiver.iter() { match message { ServerMessages::ClientConnected(client) => println!("client connected: {:?}", client), From 546e566c9b113f571d0a1eb31d7684a15a19348e Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 11 Mar 2021 14:06:05 +0000 Subject: [PATCH 05/16] Fixed immediate warnings --- src/lib/server/client_management/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 532042f..b8fc090 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -25,8 +25,6 @@ enum ClientManagerMessages {} pub struct ClientManager { clients: Mutex>>, - // weak_self: Mutex>>, - server_channel: Sender, sender: Sender, From 1966f80bc6a28c13fc5c99a3283f1947500c5533 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 15 Mar 2021 17:15:31 +0000 Subject: [PATCH 06/16] moving server changes to client manager --- src/lib/server/client_management/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index b8fc090..cd226b6 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -27,6 +27,8 @@ pub struct ClientManager { server_channel: Sender, + // server_channel: Sender, + sender: Sender, receiver: Receiver, } From 5b9d91e44ec16acc31cc067f9709d7645777fcd4 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:31 +0000 Subject: [PATCH 07/16] implemented basic connection handling in the server --- src/lib/server/client_management/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index cd226b6..b8fc090 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -27,8 +27,6 @@ pub struct ClientManager { server_channel: Sender, - // server_channel: Sender, - sender: Sender, receiver: Receiver, } From 3ff3e531a19571d08d93219c8f57cccad34be782 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 15 Mar 2021 17:15:31 +0000 Subject: [PATCH 08/16] moving server changes to client manager --- src/lib/server/client_management/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index b8fc090..cd226b6 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -27,6 +27,8 @@ pub struct ClientManager { server_channel: Sender, + // server_channel: Sender, + sender: Sender, receiver: Receiver, } From db72977d2f5efa74005d7d0967de63b497469bfa Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 17 Mar 2021 10:08:39 +0000 Subject: [PATCH 09/16] fixing owner structure. --- src/lib/server/client_management/client/mod.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index f69220d..aceb674 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -40,10 +40,7 @@ pub struct Client { // non serializable #[serde(skip)] - output_channel: Mutex>, - - #[serde(skip)] - input_channel: Mutex>, + server_channel: Sender, #[serde(skip)] stream: Mutex>, @@ -77,13 +74,6 @@ impl IClient for Client { // Mark: end - } -impl IOwned for Client { - fn set_owner(&self, owner: Weak) { - let mut owner_mut = self.owner.lock().unwrap(); - let _ = mem::replace(&mut *owner_mut, Some(owner)); - } -} - impl IMessagable for Client{ fn send_message(&self, msg: ClientMessage) { self.input_channel.lock().unwrap().send(msg); From cd81b1e25025fae5f682d1323cc362fe73011db2 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 17 Mar 2021 10:41:47 +0000 Subject: [PATCH 10/16] redesigned client for the new exec structure --- .../server/client_management/client/mod.rs | 60 +++++++++---------- .../server/client_management/client/traits.rs | 7 ++- 2 files changed, 35 insertions(+), 32 deletions(-) diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index aceb674..6dd9d14 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -2,25 +2,21 @@ // pub mod client_v3; pub mod traits; -use std::sync::Mutex; -use std::net::TcpStream; -use std::sync::Weak; -use std::sync::Arc; +use std::collections::HashMap; use std::cmp::Ordering; -use std::mem; +use std::net::TcpStream; +use std::sync::Mutex; +use std::sync::Arc; use uuid::Uuid; use serde::Serialize; use crossbeam_channel::{Sender, Receiver, unbounded}; -use crate::lib::Foundation::{IOwned, ICooperative, IMessagable}; -use super::ClientManager; use traits::IClient; +use crate::lib::Foundation::{ICooperative, IMessagable}; +use crate::lib::server::ServerMessages; -pub enum ClientMessage { - a, - b, -} +pub enum ClientMessage {} /// # Client /// This struct represents a connected user. @@ -40,43 +36,46 @@ pub struct Client { // non serializable #[serde(skip)] - server_channel: Sender, + server_channel: Option>, + + #[serde(skip)] + input: Sender, + + #[serde(skip)] + output: Receiver, #[serde(skip)] stream: Mutex>, - - #[serde(skip)] - owner: Mutex>> - } // client funciton implmentations impl IClient for Client { - fn new(uuid: Uuid, name: String, addr: String) -> Arc { - let (sender, reciever) = unbounded(); + fn new(map: HashMap, server_channel: Sender ) -> Arc { + let (sender, receiver) = unbounded(); Arc::new(Client { - username: name, - uuid: Uuid::new_v4(), - address: addr, + username: map.get(&"name".to_string()).unwrap().clone(), + uuid: Uuid::parse_str(map.get(&"uuid".to_string()).unwrap().as_str()).expect("invalid id"), + address: map.get(&"host".to_string()).unwrap().clone(), - output_channel: Mutex::new(reciever), - input_channel: Mutex::new(sender), + server_channel: Some(server_channel), + + input: sender, + output: receiver, stream: Mutex::new(None), - owner: Mutex::new(None) }) } // MARK: - removeable - fn send(&self, bytes: Vec) -> Result<(), &str> { todo!() } + fn send(&self, _bytes: Vec) -> Result<(), &str> { todo!() } fn recv(&self) -> Option> { todo!() } // Mark: end - } impl IMessagable for Client{ fn send_message(&self, msg: ClientMessage) { - self.input_channel.lock().unwrap().send(msg); + self.input.send(msg).expect("failed to send message to client."); } } @@ -90,16 +89,17 @@ impl ICooperative for Client { impl Default for Client { fn default() -> Self { let (sender, reciever) = unbounded(); - return Client { + Client { username: "generic_client".to_string(), uuid: Uuid::new_v4(), address: "127.0.0.1".to_string(), - output_channel: Mutex::new(reciever), - input_channel: Mutex::new(sender), + output: reciever, + input: sender, + + server_channel: None, stream: Mutex::new(None), - owner: Mutex::new(None) } } } diff --git a/src/lib/server/client_management/client/traits.rs b/src/lib/server/client_management/client/traits.rs index c1b6c49..07cc9a4 100644 --- a/src/lib/server/client_management/client/traits.rs +++ b/src/lib/server/client_management/client/traits.rs @@ -1,6 +1,9 @@ use std::sync::Arc; +use std::collections::HashMap; -use uuid::Uuid; +use crossbeam_channel::Sender; + +use crate::lib::server::ServerMessages; /// # TClient /// This trait represents the methods that a client must implement @@ -13,7 +16,7 @@ use uuid::Uuid; /// - send_msg: sends a event message to the client /// - recv_msg: used by the client to receive and process event messages pub trait IClient { - fn new(uuid: Uuid, name: String, addr: String) -> Arc; + fn new(map: HashMap, server_channel: Sender ) -> Arc; fn send(&self, bytes: Vec) -> Result<(), &str>; fn recv(&self) -> Option>; From 22a0d682556af9e60fd9491e94a146e3741cebe5 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 08:53:06 +0000 Subject: [PATCH 11/16] implemented basic messageing system for clients. --- Cargo.toml | 1 + .../server/client_management/client/mod.rs | 71 +++++++++++++++++-- .../server/client_management/client/traits.rs | 3 +- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a2ee271..4d850dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ log = "0.4" url = "2.2.0" uuid = {version = "0.8", features = ["serde", "v4"]} serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" [profile.dev] diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index 6dd9d14..416177f 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -7,16 +7,39 @@ use std::cmp::Ordering; use std::net::TcpStream; use std::sync::Mutex; use std::sync::Arc; +use std::io::{BufReader, BufWriter}; +use std::io::BufRead; use uuid::Uuid; -use serde::Serialize; +use serde::{Serialize, Deserialize}; use crossbeam_channel::{Sender, Receiver, unbounded}; use traits::IClient; use crate::lib::Foundation::{ICooperative, IMessagable}; use crate::lib::server::ServerMessages; -pub enum ClientMessage {} +/// # ClientMessage +/// This enum defined the message that a client can receive from the server +/// This uses the serde library to transform to and from json. +#[derive(Serialize, Deserialize)] +pub enum ClientMessage { + Disconnect {id: String}, + Update {id: String}, + + ServerMessage {id: String, msg: String}, + + NewMessage {id: String, from_user_id: String, msg: String}, + NewgroupMessage {id: String, from_group_id: String, from_user_id: String, msg: String}, +} + +/// # ClientSocketMessage +/// This enum defines a message that can be sent from a client to the server once connected +/// This uses the serde library to transform to and from json. +#[derive(Serialize, Deserialize)] +pub enum ClientSocketMessage { + Disconnect {id: String}, + SendMessage {id: String, to_user_id: String, msg: String} +} /// # Client /// This struct represents a connected user. @@ -46,13 +69,23 @@ pub struct Client { #[serde(skip)] stream: Mutex>, + + #[serde(skip)] + stream_reader: Mutex>>, + + #[serde(skip)] + stream_writer: Mutex>>, + } // client funciton implmentations impl IClient for Client { - fn new(map: HashMap, server_channel: Sender ) -> Arc { + fn new(map: HashMap, stream: TcpStream, server_channel: Sender ) -> Arc { let (sender, receiver) = unbounded(); + let out_stream = stream.try_clone().unwrap(); + let in_stream = stream.try_clone().unwrap(); + Arc::new(Client { username: map.get(&"name".to_string()).unwrap().clone(), uuid: Uuid::parse_str(map.get(&"uuid".to_string()).unwrap().as_str()).expect("invalid id"), @@ -63,7 +96,10 @@ impl IClient for Client { input: sender, output: receiver, - stream: Mutex::new(None), + stream: Mutex::new(Some(stream)), + + stream_reader: Mutex::new(Some(BufReader::new(in_stream))), + stream_writer: Mutex::new(Some(BufWriter::new(out_stream))), }) } @@ -82,6 +118,30 @@ impl IMessagable for Client{ // cooperative multitasking implementation impl ICooperative for Client { fn tick(&self) { + // aquire locks (so value isn't dropped) + let mut reader_lock = self.stream_reader.lock().unwrap(); + let mut writer_lock = self.stream_writer.lock().unwrap(); + + // aquiring mutable buffers + let reader = reader_lock.as_mut().unwrap(); + let _writer = writer_lock.as_mut().unwrap(); + + // create buffer + let mut buffer = String::new(); + + // loop over all lines that have been sent. + while let Ok(_size) = reader.read_line(&mut buffer) { + let command = serde_json::from_str::(buffer.as_str()).unwrap(); + + match command { + ClientSocketMessage::Disconnect {id} => println!("got Disconnect from id: {:?}", id), + _ => println!("New command found"), + } + } + + + // handle incomming messages + } } @@ -100,6 +160,9 @@ impl Default for Client { server_channel: None, stream: Mutex::new(None), + + stream_reader: Mutex::new(None), + stream_writer: Mutex::new(None), } } } diff --git a/src/lib/server/client_management/client/traits.rs b/src/lib/server/client_management/client/traits.rs index 07cc9a4..20a0fe8 100644 --- a/src/lib/server/client_management/client/traits.rs +++ b/src/lib/server/client_management/client/traits.rs @@ -1,4 +1,5 @@ use std::sync::Arc; +use std::net::TcpStream; use std::collections::HashMap; use crossbeam_channel::Sender; @@ -16,7 +17,7 @@ use crate::lib::server::ServerMessages; /// - send_msg: sends a event message to the client /// - recv_msg: used by the client to receive and process event messages pub trait IClient { - fn new(map: HashMap, server_channel: Sender ) -> Arc; + fn new(map: HashMap, stream: TcpStream, server_channel: Sender ) -> Arc; fn send(&self, bytes: Vec) -> Result<(), &str>; fn recv(&self) -> Option>; From a8c37225aea05a1c297e17e2f2f73f8e97acadd8 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 09:20:39 +0000 Subject: [PATCH 12/16] implemented basic client manager functions for new architecture --- src/lib/server/client_management/mod.rs | 32 +++++++++++----------- src/lib/server/client_management/traits.rs | 6 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index cd226b6..032c0bc 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -2,18 +2,17 @@ pub mod client; mod traits; // use crate::lib::server::ServerMessages; -use crate::lib::server::ServerMessages; use std::sync::Arc; use std::sync::Mutex; -use std::sync::Weak; +use std::collections::HashMap; use crossbeam_channel::{unbounded, Receiver, Sender}; use uuid::Uuid; -use crate::lib::Foundation::{IOwner, IOwned}; use self::client::Client; use self::client::ClientMessage; use self::traits::TClientManager; +use crate::lib::server::ServerMessages; use crate::lib::Foundation::IMessagable; use crate::lib::Foundation::ICooperative; @@ -23,12 +22,10 @@ enum ClientManagerMessages {} /// This struct manages all connected users #[derive(Debug)] pub struct ClientManager { - clients: Mutex>>, + clients: Mutex>>, server_channel: Sender, - // server_channel: Sender, - sender: Sender, receiver: Receiver, } @@ -51,29 +48,32 @@ impl ClientManager { impl TClientManager for ClientManager { fn add_client(&self, client: std::sync::Arc) { - self.clients.lock().unwrap().push(client); + self.clients.lock().unwrap().insert(client.uuid, client); } - fn remove_client(&self, _uuid: Uuid) { - self.clients.lock().unwrap().sort(); + fn remove_client(&self, uuid: Uuid) { + let _ = self.clients.lock().unwrap().remove(&uuid); } - fn message_client(&self, _id: Uuid, _msg: ClientMessage) { - todo!() + fn send_message_to_client(&self, uuid: Uuid, msg: ClientMessage) { + let clients = self.clients.lock().unwrap(); + let client = clients.get(&uuid).unwrap(); + client.send_message(msg); } +} +impl ICooperative for ClientManager { fn tick(&self) { - let client_list = self.clients.lock().unwrap(); - let _ = client_list.iter().map(|client| client.tick()); + } } #[cfg(test)] mod test { - use super::ClientManager; - use std::sync::Arc; - use crate::lib::Foundation::{IOwner}; + // use super::ClientManager; + // use std::sync::Arc; + // use crate::lib::Foundation::{IOwner}; #[test] fn test_get_ref() { diff --git a/src/lib/server/client_management/traits.rs b/src/lib/server/client_management/traits.rs index a48af0a..d2bc94a 100644 --- a/src/lib/server/client_management/traits.rs +++ b/src/lib/server/client_management/traits.rs @@ -1,3 +1,4 @@ +use crate::lib::server::client_management::client::ClientMessage; use std::sync::Arc; use uuid::Uuid; @@ -7,7 +8,6 @@ use uuid::Uuid; */ pub trait TClientManager { fn add_client(&self, client: Arc); - fn remove_client(&self, id: Uuid); - fn message_client(&self, id: Uuid, msg: TClientMessage); - fn tick(&self, ); + fn remove_client(&self, uuid: Uuid); + fn send_message_to_client(&self, uuid: Uuid, msg: ClientMessage); } \ No newline at end of file From 232effad14e46bf9b77758458d0e7aca6d21756c Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:31 +0000 Subject: [PATCH 13/16] implemented basic connection handling in the server --- src/lib/server/client_management/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 032c0bc..ce814c4 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -2,6 +2,7 @@ pub mod client; mod traits; // use crate::lib::server::ServerMessages; +use crate::lib::server::ServerMessages; use std::sync::Arc; use std::sync::Mutex; use std::collections::HashMap; From 19832f0aa1476a6fc27d97934eb46e05c3b2889d Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 09:42:53 +0000 Subject: [PATCH 14/16] added basic server messages. --- src/lib/server/client_management/mod.rs | 3 +-- src/lib/server/mod.rs | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index ce814c4..4c889f9 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -1,8 +1,7 @@ pub mod client; -mod traits; +pub mod traits; // use crate::lib::server::ServerMessages; -use crate::lib::server::ServerMessages; use std::sync::Arc; use std::sync::Mutex; use std::collections::HashMap; diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 49a5374..12bddf2 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,22 +1,27 @@ pub mod client_management; -use std::sync::{Arc, Weak, Mutex}; use std::collections::HashMap; use std::net::TcpListener; +use std::sync::Arc; use std::io::Write; use std::io::Read; +use uuid::Uuid; use crossbeam_channel::{Sender, Receiver, unbounded}; use crate::lib::server::client_management::ClientManager; -use crate::lib::Foundation::{IOwner, IOwned, ICooperative}; +use crate::lib::server::client_management::traits::TClientManager; +use crate::lib::Foundation::{ICooperative}; use client_management::client::Client; use crate::lib::commands::Commands; +/// # ServerMessages +/// This is used internally #[derive(Debug)] pub enum ServerMessages { ClientConnected(Arc), + ClientDisconnected(Uuid) } pub struct Server { @@ -40,6 +45,10 @@ impl Server { receiver, }) } + + pub fn send_message(&self, msg: ServerMessages) { + self.sender.send(msg).expect("!error sending message to server!") + } } impl ICooperative for Server{ @@ -80,6 +89,7 @@ impl ICooperative for Server{ for message in self.receiver.iter() { match message { ServerMessages::ClientConnected(client) => println!("client connected: {:?}", client), + ServerMessages::ClientDisconnected(uuid) => {self.client_manager.remove_client(uuid);} } } } From b53a63fd546a12ee31c78106afa416c350446bcd Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 11:50:12 +0000 Subject: [PATCH 15/16] setting up json based message protocol --- src/lib/server/mod.rs | 50 +++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 12bddf2..24b4883 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,20 +1,21 @@ pub mod client_management; -use std::collections::HashMap; +use std::io::BufWriter; +use std::io::BufReader; use std::net::TcpListener; use std::sync::Arc; use std::io::Write; -use std::io::Read; +use std::io::BufRead; use uuid::Uuid; use crossbeam_channel::{Sender, Receiver, unbounded}; +use serde::{Serialize, Deserialize}; use crate::lib::server::client_management::ClientManager; use crate::lib::server::client_management::traits::TClientManager; use crate::lib::Foundation::{ICooperative}; use client_management::client::Client; -use crate::lib::commands::Commands; /// # ServerMessages /// This is used internally @@ -24,6 +25,13 @@ pub enum ServerMessages { ClientDisconnected(Uuid) } +#[derive(Serialize, Deserialize, Debug)] +pub enum ServerSocketMessages { + Request, + Info, + Connect {uuid: Uuid, username: String, address: String} +} + pub struct Server { server_socket: TcpListener, client_manager: Arc, @@ -54,35 +62,25 @@ impl Server { impl ICooperative for Server{ fn tick(&self) { - let mut buffer = vec![0; 64]; + let mut buffer = String::new(); // handle new connections for connection in self.server_socket.incoming() { - match connection { - Ok(mut stream) => { - stream.write_all(Commands::Request(None).to_string().as_bytes()).expect("error writing socket"); - stream.read_to_end(&mut buffer).expect("error reading sokcet"); - - println!("buffer: {:?}", &buffer); + let (mut reader, mut writer) = match connection { + Ok(mut stream) => (BufReader::new(stream.try_clone().unwrap()), BufWriter::new(stream.try_clone().unwrap())), + Err(_) => break, + }; - let command = Commands::from(&mut buffer); + writer.write_all(serde_json::to_string(&ServerSocketMessages::Request).unwrap().as_bytes()); + writer.flush(); - match command { - Commands::Info(None) => { - let server_config = vec![ - ("name".to_string(), "Test server".to_string()) - ]; - let map: HashMap = server_config.into_iter().collect(); - stream.write_all(Commands::Success(Some(map)).to_string().as_bytes()) - .expect("error sending response"); - } - Commands::Connect(Some(map)) => println!("connect command: {:?}", &map), + reader.read_line(&mut buffer); - _ => {let _ = stream.write("not implemented!".as_bytes());} - } - }, - _ => println!("!connection error occured!"), - } + println!("recieved: {:?}", &buffer); + + let msg: ServerSocketMessages = serde_json::from_str(&buffer).unwrap(); + + println!("got msg: {:?}", msg) } // handle new messages loop From bb5fbdc43ba2b3466857737438b1621f54fa248b Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 15:57:34 +0000 Subject: [PATCH 16/16] removed redundant function --- src/lib/server/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 24b4883..d3a868c 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -23,6 +23,8 @@ use client_management::client::Client; pub enum ServerMessages { ClientConnected(Arc), ClientDisconnected(Uuid) + + } #[derive(Serialize, Deserialize, Debug)] @@ -53,10 +55,6 @@ impl Server { receiver, }) } - - pub fn send_message(&self, msg: ServerMessages) { - self.sender.send(msg).expect("!error sending message to server!") - } } impl ICooperative for Server{