From f4bd223d1273d263f6b849db9a877e3384a930e5 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 11 Mar 2021 22:35:52 +0000 Subject: [PATCH 01/41] Created traits for struct ownership and impl them for client|manager --- src/lib/Foundation/mod.rs | 11 ++++++ src/lib/mod.rs | 1 + .../server/client_management/client/mod.rs | 34 +++++++++++++++---- src/lib/server/client_management/mod.rs | 12 +++++-- 4 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 src/lib/Foundation/mod.rs diff --git a/src/lib/Foundation/mod.rs b/src/lib/Foundation/mod.rs new file mode 100644 index 0000000..8e4f4b7 --- /dev/null +++ b/src/lib/Foundation/mod.rs @@ -0,0 +1,11 @@ +use std::sync::{Weak,Arc}; + +pub trait IOwned { + fn set_owner(&self, owner: Weak); +} + +pub trait IOwner { + fn add_child(&self, child: Arc); + fn get_ref(&self) -> Weak; +} + diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 3dbcdd0..6e06bd7 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -1,6 +1,7 @@ // pub mod commands; pub mod prelude; pub mod server; +pub mod Foundation; use std::sync::Arc; use std::sync::Mutex; diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index 2401199..d98a52f 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -2,13 +2,17 @@ // pub mod client_v3; pub mod traits; +use std::sync::Mutex; use serde::{Serialize, Deserialize}; use std::net::TcpStream; use std::sync::Weak; use std::sync::Arc; -use uuid::Uuid; use std::cmp::Ordering; +use std::mem; +use uuid::Uuid; + +use IOwned::lib::Foundation::IOwned; use super::ClientManager; use traits::TClient; @@ -27,21 +31,30 @@ pub enum ClientMessage { /// /// - stream: The socket for the connected client. /// - owner: An optional reference to the owning object. -#[derive(Serialize, Deserialize)] +#[derive(Serialize, Deserialize, Default)] pub struct Client { pub uuid: String, username: String, address: String, #[serde(skip)] - stream: Option, + stream: Mutex>, #[serde(skip)] - owner: Option> + owner: Mutex>> } impl TClient for Client { - fn new(uuid: Uuid, name: String, addr: String) -> Arc { todo!() } + fn new(uuid: Uuid, name: String, addr: String) -> Arc { + Arc::new(Client { + username: name, + uuid: uuid.to_string(), + address: addr, + + stream: Mutex::new(None), + owner: Mutex::new(None) + }) + } fn send(&self, bytes: Vec) -> Result<(), &str> { todo!() } fn recv(&self) -> Option> { todo!() } @@ -52,6 +65,14 @@ impl TClient for Client { fn tick(&self) { } } +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 PartialEq for Client { fn eq(&self, other: &Self) -> bool { self.uuid == other.uuid @@ -71,4 +92,5 @@ impl PartialOrd for Client { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } -} \ No newline at end of file +} + diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 8c3c640..9a8ffe0 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -6,9 +6,10 @@ use std::sync::Mutex; use std::sync::Weak; use crossbeam_channel::{unbounded, Receiver, Sender}; - use uuid::Uuid; +use IOwner::lib::Foundation::IOwner; +use IOwned::lib::Foundation::IOwned; use self::client::Client; use self::client::ClientMessage; // use client::client_v3::Client; @@ -65,7 +66,7 @@ impl ClientManager { impl TClientManager for ClientManager { fn add_client(&self, client: std::sync::Arc) { - self.clients.lock().unwrap().push(client); + self.add_child(client); } fn remove_client(&self, uuid: Uuid) { @@ -95,6 +96,13 @@ 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); + } +} + #[cfg(test)] mod test { use super::ClientManager; From 7731e18d8b7f00973997db543963e5482915e129 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Fri, 12 Mar 2021 17:17:48 +0000 Subject: [PATCH 02/41] implemeting client functionality and changed types --- Cargo.toml | 19 ++--- src/lib/Foundation/mod.rs | 7 ++ .../server/client_management/client/mod.rs | 83 ++++++++++++++----- .../server/client_management/client/traits.rs | 7 +- src/lib/server/client_management/mod.rs | 24 +++--- 5 files changed, 91 insertions(+), 49 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5227718..a2ee271 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,20 +8,19 @@ edition = "2018" [dependencies] regex = "1" -uuid = "0.8" -crossbeam = "0.7" -crossbeam-channel = "0.4" -crossbeam-utils = "0.7" -crossbeam-queue = "0.2" -parking_lot = "0.10" -dashmap = "3.11.4" +crossbeam = "0.8.0" +crossbeam-channel = "0.5.0" +crossbeam-queue = "0.3.1" +parking_lot = "0.11.1" +dashmap = "4.0.2" rayon = "1.3.1" zeroize = "1.1.0" -crossterm = "0.17.7" -clap = "3.0.0-beta.1" +crossterm = "0.19.0" +clap = "2.33.3" log = "0.4" -serde = { version = "1.0", features = ["derive"] } url = "2.2.0" +uuid = {version = "0.8", features = ["serde", "v4"]} +serde = { version = "1.0", features = ["derive"] } [profile.dev] diff --git a/src/lib/Foundation/mod.rs b/src/lib/Foundation/mod.rs index 8e4f4b7..6333649 100644 --- a/src/lib/Foundation/mod.rs +++ b/src/lib/Foundation/mod.rs @@ -9,3 +9,10 @@ pub trait IOwner { fn get_ref(&self) -> Weak; } +pub trait IMessagable { + fn send_message(&self, msg: M); +} + +pub trait ICooperative { + fn tick(&self); +} \ No newline at end of file diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index d98a52f..566eb3d 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -3,7 +3,6 @@ pub mod traits; use std::sync::Mutex; -use serde::{Serialize, Deserialize}; use std::net::TcpStream; use std::sync::Weak; use std::sync::Arc; @@ -11,10 +10,12 @@ use std::cmp::Ordering; use std::mem; use uuid::Uuid; +use serde::Serialize; +use crossbeam_channel::{Sender, Receiver, unbounded}; -use IOwned::lib::Foundation::IOwned; +use crate::lib::Foundation::{IOwned, ICooperative, IMessagable}; use super::ClientManager; -use traits::TClient; +use traits::IClient; pub enum ClientMessage { a, @@ -31,38 +32,49 @@ pub enum ClientMessage { /// /// - stream: The socket for the connected client. /// - owner: An optional reference to the owning object. -#[derive(Serialize, Deserialize, Default)] +#[derive(Serialize)] pub struct Client { - pub uuid: String, + pub uuid: Uuid, username: String, address: String, - #[serde(skip)] + // non serializable + #[serde(skip)] + output_channel: Mutex>, + + #[serde(skip)] + input_channel: Mutex>, + + #[serde(skip)] stream: Mutex>, - #[serde(skip)] + #[serde(skip)] owner: Mutex>> + } -impl TClient for Client { +// client funciton implmentations +impl IClient for Client { fn new(uuid: Uuid, name: String, addr: String) -> Arc { + let (sender, reciever) = unbounded(); + Arc::new(Client { username: name, - uuid: uuid.to_string(), + uuid: Uuid::new_v4(), address: addr, + output_channel: Mutex::new(reciever), + input_channel: Mutex::new(sender), + stream: Mutex::new(None), owner: Mutex::new(None) }) } + // MARK: - removeable fn send(&self, bytes: Vec) -> Result<(), &str> { todo!() } fn recv(&self) -> Option> { todo!() } - - fn send_msg(&self, msg: ClientMessage) -> Result<(), &str> { todo!() } - fn recv_msg(&self) -> Option { todo!() } - - fn tick(&self) { } + // Mark: end - } impl IOwned for Client { @@ -72,7 +84,37 @@ impl IOwned for Client { } } +impl IMessagable for Client{ + fn send_message(&self, msg: ClientMessage) { + self.input_channel.lock().unwrap().send(msg); + } +} +// cooperative multitasking implementation +impl ICooperative for Client { + fn tick(&self) { + } +} + +// default value implementation +impl Default for Client { + fn default() -> Self { + let (sender, reciever) = unbounded(); + return 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), + + stream: Mutex::new(None), + owner: Mutex::new(None) + } + } +} + +// MARK: - used for sorting. impl PartialEq for Client { fn eq(&self, other: &Self) -> bool { self.uuid == other.uuid @@ -82,15 +124,14 @@ impl PartialEq for Client { impl Eq for Client { } +impl PartialOrd for Client { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + impl Ord for Client { fn cmp(&self, other: &Self) -> Ordering { self.uuid.cmp(&other.uuid) } } - -impl PartialOrd for Client { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - diff --git a/src/lib/server/client_management/client/traits.rs b/src/lib/server/client_management/client/traits.rs index 9129eb6..c1b6c49 100644 --- a/src/lib/server/client_management/client/traits.rs +++ b/src/lib/server/client_management/client/traits.rs @@ -12,14 +12,9 @@ use uuid::Uuid; /// - recv: if there is a message in the queue, returns the message /// - send_msg: sends a event message to the client /// - recv_msg: used by the client to receive and process event messages -pub trait TClient { +pub trait IClient { fn new(uuid: Uuid, name: String, addr: String) -> Arc; fn send(&self, bytes: Vec) -> Result<(), &str>; fn recv(&self) -> Option>; - - fn send_msg(&self, msg: TClientMessage) -> Result<(), &str>; - fn recv_msg(&self) -> Option; - - fn tick(&self); } \ No newline at end of file diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 9a8ffe0..19f3b13 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -8,13 +8,12 @@ use std::sync::Weak; use crossbeam_channel::{unbounded, Receiver, Sender}; use uuid::Uuid; -use IOwner::lib::Foundation::IOwner; -use IOwned::lib::Foundation::IOwned; +use crate::lib::Foundation::{IOwner, IOwned}; use self::client::Client; use self::client::ClientMessage; -// use client::client_v3::Client; use self::traits::TClientManager; -use client::traits::TClient; +use crate::lib::Foundation::IMessagable; +use crate::lib::Foundation::ICooperative; enum ClientManagerMessages {} @@ -54,9 +53,7 @@ impl ClientManager { manager_ref } - pub fn get_ref(&self) -> Weak { - self.weak_self.lock().unwrap().clone().unwrap() - } + fn set_ref(&self, reference: Arc) { let mut lock = self.weak_self.lock().unwrap(); @@ -70,21 +67,19 @@ impl TClientManager for ClientManager { } fn remove_client(&self, uuid: Uuid) { - let uuid_str = uuid.to_string(); 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_str)) { + if let Ok(index) = client_list.binary_search_by(move |client| client.uuid.cmp(&uuid)) { client_list.remove(index); } } fn message_client(&self, id: Uuid, msg: ClientMessage) -> Result<(), &str> { - let uuid_str = id.to_string(); 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_str)) { + 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_msg(msg); + let _ = client.send_message(msg); } } Ok(()) @@ -100,6 +95,10 @@ 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().clone().unwrap() } } @@ -107,6 +106,7 @@ impl IOwner for ClientManager{ mod test { use super::ClientManager; use std::sync::Arc; + use crate::lib::Foundation::{IOwner}; #[test] fn test_get_ref() { From 4c7c68c2a5106d2ede239857f2bb1b879dab544d Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 15 Mar 2021 16:35:42 +0000 Subject: [PATCH 03/41] implementing common traits for server --- src/lib/mod.rs | 2 +- src/lib/server/client_management/mod.rs | 5 ++- src/lib/server/mod.rs | 47 +++++++++++++++++++++++-- src/main.rs | 10 +++--- 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 6e06bd7..0b03722 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -7,7 +7,7 @@ use std::sync::Arc; use std::sync::Mutex; use std::thread; -use crossbeam::{unbounded, Receiver, Sender}; +use crossbeam_channel::{unbounded, Receiver, Sender}; enum Message { NewJob(Job), diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 19f3b13..330a0ed 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -23,6 +23,7 @@ pub struct ClientManager { clients: Mutex>>, weak_self: Mutex>>, + server_ref: Mutex>, sender: Sender, receiver: Receiver, @@ -53,8 +54,6 @@ impl ClientManager { manager_ref } - - fn set_ref(&self, reference: Arc) { let mut lock = self.weak_self.lock().unwrap(); *lock = Some(Arc::downgrade(&reference)); @@ -98,7 +97,7 @@ impl IOwner for ClientManager{ } fn get_ref(&self) -> Weak { - self.weak_self.lock().unwrap().clone().unwrap() + self.weak_self.lock().unwrap().unwrap().clone() } } diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 5ab86fa..097b104 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,5 +1,46 @@ pub mod client_management; -// pub mod server; -// pub mod server_v3; -pub struct _Server {} +use std::sync::{Arc, Weak, Mutex}; +use std::net::TcpListener; + +use crate::lib::server::client_management::ClientManager; +use crate::lib::Foundation::{IOwner, IOwned, ICooperative}; + +pub struct Server { + server_socket: TcpListener, + + client_manager: Arc, +} + +impl Server { + pub fn new() -> Arc { + + let listener = TcpListener::bind("0.0.0.0:5600").expect("Could not bind to address"); + + let server: Arc = Arc::new(Server { + server_socket: listener, + weak_self: Mutex::new(None), + client_manager: ClientManager::new() + }); + + server. + } + + +} + +impl IOwner for Server { + fn add_child(&self, child: Arc) { + self.client_manager + } + + fn get_ref(&self) -> Weak { + self.weak_self.lock().unwrap().unwrap().clone() + } +} + +impl ICooperative for Server{ + fn tick(&self) { + + } +} diff --git a/src/main.rs b/src/main.rs index 57abb62..0f29b99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,8 @@ mod lib; use clap::{App, Arg}; + +use crate::lib::server::Server; fn main() { let _args = App::new("--rust chat server--") @@ -8,15 +10,15 @@ fn main() { .author("Mitchel Hardie , Michael Bailey ") .about("this is a chat server developed in rust, depending on the version one of two implementations will be used") .arg( - Arg::new("config") - .short('p') + Arg::with_name("config") + .short("p") .long("port") .value_name("PORT") - .about("sets the port the server listens on.") + .help("sets the port the server runs on.") .takes_value(true)) .get_matches(); - // creating the server object + let mut server = Server::new(); } From 962293b32f49b233d221dcf60f2d975d7d4e26ee Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 15 Mar 2021 17:11:50 +0000 Subject: [PATCH 04/41] added basic implementations for server --- src/lib/server/mod.rs | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 097b104..f18cc6f 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,41 +1,37 @@ pub mod client_management; +use crossbeam_channel::{Sender, Receiver, unbounded}; use std::sync::{Arc, Weak, Mutex}; use std::net::TcpListener; use crate::lib::server::client_management::ClientManager; use crate::lib::Foundation::{IOwner, IOwned, ICooperative}; +use client_management::client::Client; + +enum ServerMessages { + ClientConnected(Client), +} pub struct Server { server_socket: TcpListener, - client_manager: Arc, + + sender: Sender, + receiver: Receiver, } impl Server { pub fn new() -> Arc { - let listener = TcpListener::bind("0.0.0.0:5600").expect("Could not bind to address"); + let (sender, receiver) = unbounded(); - let server: Arc = Arc::new(Server { + Arc::new(Server { server_socket: listener, - weak_self: Mutex::new(None), - client_manager: ClientManager::new() - }); - - server. - } - - -} - -impl IOwner for Server { - fn add_child(&self, child: Arc) { - self.client_manager - } - - fn get_ref(&self) -> Weak { - self.weak_self.lock().unwrap().unwrap().clone() + client_manager: ClientManager::new(sender), + + sender, + receiver, + }) } } From 5e4905699258918503e1e3676b65006219860c65 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 11 Mar 2021 14:06:05 +0000 Subject: [PATCH 05/41] Fixed immediate warnings --- src/lib/server/client_management/mod.rs | 38 +++++----------------- src/lib/server/client_management/traits.rs | 2 +- src/lib/server/mod.rs | 2 +- 3 files changed, 10 insertions(+), 32 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 330a0ed..f95774c 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -23,7 +23,6 @@ pub struct ClientManager { clients: Mutex>>, weak_self: Mutex>>, - server_ref: Mutex>, sender: Sender, receiver: Receiver, @@ -62,26 +61,15 @@ impl ClientManager { 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 +78,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 +87,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..ce825a7 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -27,7 +27,7 @@ impl Server { Arc::new(Server { server_socket: listener, - client_manager: ClientManager::new(sender), + client_manager: ClientManager::new(/*sender*/), sender, receiver, From 585926ebed8a8af2783d3cf06e56cfc52f95da11 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 15 Mar 2021 17:15:31 +0000 Subject: [PATCH 06/41] moving server changes to client manager --- src/lib/server/client_management/mod.rs | 27 ++++++++++--------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index f95774c..c668a66 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -1,6 +1,7 @@ pub mod client; mod traits; +// use crate::lib::server::ServerMessages; use std::sync::Arc; use std::sync::Mutex; use std::sync::Weak; @@ -24,39 +25,33 @@ pub struct ClientManager { 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(), - sender: channels.0, - receiver: channels.1, - }); + // server_channel, - // 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 + sender, + receiver, + }) } fn set_ref(&self, reference: Arc) { let mut lock = self.weak_self.lock().unwrap(); *lock = Some(Arc::downgrade(&reference)); - } + } } impl TClientManager for ClientManager { From ca4b0259b9062c07bed8aaab0385b4348ceea7b4 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 09:40:34 +0000 Subject: [PATCH 07/41] 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 08/41] 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 09/41] 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 10/41] 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 9b5cb186932a0fbd7bd4897f89a9e9654b264bda Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 09:40:34 +0000 Subject: [PATCH 11/41] 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 5b7258d3abda96288854a7de75211dd56795013b Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:03 +0000 Subject: [PATCH 12/41] 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 14154ebd4e675305d5bbbded7f26de53140349b3 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:31 +0000 Subject: [PATCH 13/41] implemented basic connection handling in the server --- .../server/client_management/client/mod.rs | 2 +- src/lib/server/client_management/mod.rs | 17 +++----- src/lib/server/mod.rs | 43 +++++++++++++++++-- src/main.rs | 7 ++- 4 files changed, 52 insertions(+), 17 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 c668a66..532042f 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::sync::Weak; @@ -20,38 +21,32 @@ enum ClientManagerMessages {} /// # ClientManager /// This struct manages all connected users +#[derive(Debug)] pub struct ClientManager { clients: Mutex>>, - weak_self: Mutex>>, + // weak_self: Mutex>>, - // server_channel: Sender, + server_channel: Sender, sender: Sender, receiver: Receiver, } impl ClientManager { - pub fn new(/*server_channel: Sender */) -> Arc { + pub fn new(server_channel: Sender) -> Arc { let (sender, receiver) = unbounded(); Arc::new(ClientManager { clients: Mutex::default(), - weak_self: Mutex::default(), - - // server_channel, + server_channel, sender, receiver, }) } - - fn set_ref(&self, reference: Arc) { - let mut lock = self.weak_self.lock().unwrap(); - *lock = Some(Arc::downgrade(&reference)); - } } impl TClientManager for ClientManager { diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index ce825a7..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 5f6ecdd8394c50cda1be5b1f868ec8d4ee7c2d3f Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 17 Mar 2021 09:56:51 +0000 Subject: [PATCH 14/41] 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 f00d8cc7f78505d3a920c1fea127c45d6175a0eb Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Mon, 15 Mar 2021 17:15:31 +0000 Subject: [PATCH 15/41] 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 532042f..01ea2b2 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -29,6 +29,8 @@ pub struct ClientManager { server_channel: Sender, + // server_channel: Sender, + sender: Sender, receiver: Receiver, } From 194e95473364ce4e55c16d97884d7145a640b5bd Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 17 Mar 2021 10:08:39 +0000 Subject: [PATCH 16/41] 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 a493eddd50b39ace8ced9210af507f8369106b7e Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 17 Mar 2021 10:41:47 +0000 Subject: [PATCH 17/41] 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 e92096b6adf25d01716c4d74d76626d0e78790ee Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 08:53:06 +0000 Subject: [PATCH 18/41] 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 b1b8107ce7ac93b03524ad032caf3e615d78e8dd Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 09:20:39 +0000 Subject: [PATCH 19/41] implemented basic client manager functions for new architecture --- src/lib/server/client_management/mod.rs | 34 ++++++++++------------ src/lib/server/client_management/traits.rs | 6 ++-- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 01ea2b2..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,14 +22,10 @@ enum ClientManagerMessages {} /// This struct manages all connected users #[derive(Debug)] pub struct ClientManager { - clients: Mutex>>, - - // weak_self: Mutex>>, + clients: Mutex>>, server_channel: Sender, - // server_channel: Sender, - sender: Sender, receiver: Receiver, } @@ -53,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 b1be92ed02b50a3c71379ba024f40f6ce47cd880 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Tue, 16 Mar 2021 10:11:31 +0000 Subject: [PATCH 20/41] 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 042f7e1007cb5e5371d5b02957b96925151fa050 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 09:42:53 +0000 Subject: [PATCH 21/41] 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 965231cde9838b31c683f9e170ff1219dbf73294 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 10:36:18 +0000 Subject: [PATCH 22/41] added basic network manager implementation --- src/lib/server/mod.rs | 7 +++- src/lib/server/network_manager/mod.rs | 46 +++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/lib/server/network_manager/mod.rs diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 12bddf2..a6950c5 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,12 +1,14 @@ pub mod client_management; +pub mod network_manager; - +use crate::lib::server::network_manager::NetworkManager; 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}; @@ -27,6 +29,7 @@ pub enum ServerMessages { pub struct Server { server_socket: TcpListener, client_manager: Arc, + network_manager: Arc, sender: Sender, receiver: Receiver, @@ -40,6 +43,8 @@ impl Server { Arc::new(Server { server_socket: listener, client_manager: ClientManager::new(sender.clone()), + + network_manager: NetworkManager::new("5600".to_string(), sender.clone()), sender, receiver, diff --git a/src/lib/server/network_manager/mod.rs b/src/lib/server/network_manager/mod.rs new file mode 100644 index 0000000..a5aa7ec --- /dev/null +++ b/src/lib/server/network_manager/mod.rs @@ -0,0 +1,46 @@ + +use std::sync::Arc; +use crate::lib::server::ServerMessages; +use std::net::TcpListener; + +use serde::{Deserialize, Serialize}; +use crossbeam_channel::Sender; + +use crate::lib::Foundation::ICooperative; + +#[derive(Serialize, Deserialize)] +enum NetworkSocketMesssages { + Info {id: String}, + Connect {id: String, uuid: String, username: String, address: String}, +} + +pub enum NetworkMessages { + +} + +pub struct NetworkManager { + listener: TcpListener, + + server_channel: Sender, +} + +impl NetworkManager { + pub fn new(port: String, server_channel: Sender) -> Arc { + let mut address = "0.0.0.0:".to_string(); + address.push_str(&port); + + let listener = TcpListener::bind(address) + .expect("Could not bind to address"); + + Arc::new(NetworkManager { + listener, + server_channel, + }) + } +} + +impl ICooperative for NetworkManager { + fn tick(&self) { + println!("network manager tick") + } +} \ No newline at end of file From 546e566c9b113f571d0a1eb31d7684a15a19348e Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 11 Mar 2021 14:06:05 +0000 Subject: [PATCH 23/41] 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 24/41] 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 25/41] 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 26/41] 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 27/41] 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 28/41] 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 29/41] 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 30/41] 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 31/41] 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 32/41] 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 33/41] 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 34/41] 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{ From 436975e3c506a93bab8490f9c326b470991d3ef2 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 16:05:27 +0000 Subject: [PATCH 35/41] Moved TcpListender form Server To NetworkManage. --- src/lib/server/mod.rs | 34 +------------- src/lib/server/network_manager/mod.rs | 66 ++++++++++++++++++++++++--- 2 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index a6950c5..f7209fe 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -27,7 +27,6 @@ pub enum ServerMessages { } pub struct Server { - server_socket: TcpListener, client_manager: Arc, network_manager: Arc, @@ -37,11 +36,9 @@ pub struct Server { impl Server { pub fn new() -> Arc { - let listener = TcpListener::bind("0.0.0.0:5600").expect("Could not bind to address"); let (sender, receiver) = unbounded(); Arc::new(Server { - server_socket: listener, client_manager: ClientManager::new(sender.clone()), network_manager: NetworkManager::new("5600".to_string(), sender.clone()), @@ -59,36 +56,7 @@ impl Server { impl ICooperative for Server{ fn tick(&self) { - let mut buffer = vec![0; 64]; - - // 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 command = Commands::from(&mut buffer); - - 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), - - _ => {let _ = stream.write("not implemented!".as_bytes());} - } - }, - _ => println!("!connection error occured!"), - } - } + self.network_manager.tick(); // handle new messages loop for message in self.receiver.iter() { diff --git a/src/lib/server/network_manager/mod.rs b/src/lib/server/network_manager/mod.rs index a5aa7ec..4db6c2c 100644 --- a/src/lib/server/network_manager/mod.rs +++ b/src/lib/server/network_manager/mod.rs @@ -1,26 +1,41 @@ -use std::sync::Arc; -use crate::lib::server::ServerMessages; use std::net::TcpListener; +use std::sync::Arc; +use std::io::BufReader; +use std::io::BufWriter; +use std::io::Write; +use std::io::BufRead; use serde::{Deserialize, Serialize}; use crossbeam_channel::Sender; +use crate::lib::server::ServerMessages; use crate::lib::Foundation::ICooperative; + +/// # NetworkSockIn +/// these messages can be sent by a client on connecting #[derive(Serialize, Deserialize)] -enum NetworkSocketMesssages { - Info {id: String}, - Connect {id: String, uuid: String, username: String, address: String}, +enum NetworkSockIn { + Info, + Connect {uuid: String, username: String, address: String}, } +/// # NetworkSockOut +/// these messages are sent by the network manager on connecting and requesting +#[derive(Serialize, Deserialize)] +enum NetworkSockOut<'a> { + Request, + GotInfo {server_name: &'a str, server_owner: &'a str} +} + +// these are control signals from the server. pub enum NetworkMessages { } pub struct NetworkManager { listener: TcpListener, - server_channel: Sender, } @@ -41,6 +56,43 @@ impl NetworkManager { impl ICooperative for NetworkManager { fn tick(&self) { - println!("network manager tick") + // get all new connections + // handle each request + for connection in self.listener.incoming() { + if let Ok(stream) = connection { + + // create buffered writers + let mut reader = BufReader::new(stream.try_clone().unwrap()); + let mut writer = BufWriter::new(stream.try_clone().unwrap()); + + let mut buffer = String::new(); + + // request is always sent on new connection + writer.write_all(serde_json::to_string(&NetworkSockOut::Request).unwrap().as_bytes()).unwrap(); + writer.write_all(b"\n").unwrap(); + writer.flush().unwrap(); + + // read the new request into a buffer + reader.read_line(&mut buffer).unwrap(); + + // turn into enum for pattern matching + let request = serde_json::from_str::(&buffer).unwrap(); + + // perform action based on the enum + match request { + NetworkSockIn::Info => { + writer.write_all( + serde_json::to_string( + &NetworkSockOut::GotInfo {server_name: "oof", server_owner: "michael"} + ).unwrap().as_bytes() + ).unwrap(); + writer.flush().unwrap(); + } + NetworkSockIn::Connect { uuid, username, address } => { + println!("Connection requested") + } + } + } + } } } \ No newline at end of file From 7d749d0de020857786120caa72c1e264eae44b3b Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 16:05:27 +0000 Subject: [PATCH 36/41] Moved TcpListender form Server To NetworkManage. --- src/lib/server/mod.rs | 34 +------------- src/lib/server/network_manager/mod.rs | 67 ++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 40 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index a6950c5..f7209fe 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -27,7 +27,6 @@ pub enum ServerMessages { } pub struct Server { - server_socket: TcpListener, client_manager: Arc, network_manager: Arc, @@ -37,11 +36,9 @@ pub struct Server { impl Server { pub fn new() -> Arc { - let listener = TcpListener::bind("0.0.0.0:5600").expect("Could not bind to address"); let (sender, receiver) = unbounded(); Arc::new(Server { - server_socket: listener, client_manager: ClientManager::new(sender.clone()), network_manager: NetworkManager::new("5600".to_string(), sender.clone()), @@ -59,36 +56,7 @@ impl Server { impl ICooperative for Server{ fn tick(&self) { - let mut buffer = vec![0; 64]; - - // 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 command = Commands::from(&mut buffer); - - 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), - - _ => {let _ = stream.write("not implemented!".as_bytes());} - } - }, - _ => println!("!connection error occured!"), - } - } + self.network_manager.tick(); // handle new messages loop for message in self.receiver.iter() { diff --git a/src/lib/server/network_manager/mod.rs b/src/lib/server/network_manager/mod.rs index a5aa7ec..2e0a7b0 100644 --- a/src/lib/server/network_manager/mod.rs +++ b/src/lib/server/network_manager/mod.rs @@ -1,26 +1,41 @@ -use std::sync::Arc; -use crate::lib::server::ServerMessages; use std::net::TcpListener; +use std::sync::Arc; +use std::io::BufReader; +use std::io::BufWriter; +use std::io::Write; +use std::io::BufRead; use serde::{Deserialize, Serialize}; use crossbeam_channel::Sender; +use crate::lib::server::ServerMessages; use crate::lib::Foundation::ICooperative; + +/// # NetworkSockIn +/// these messages can be sent by a client on connecting #[derive(Serialize, Deserialize)] -enum NetworkSocketMesssages { - Info {id: String}, - Connect {id: String, uuid: String, username: String, address: String}, +enum NetworkSockIn { + Info, + Connect {uuid: String, username: String, address: String}, } +/// # NetworkSockOut +/// these messages are sent by the network manager on connecting and requesting +#[derive(Serialize, Deserialize)] +enum NetworkSockOut<'a> { + Request, + GotInfo {server_name: &'a str, server_owner: &'a str} +} + +// these are control signals from the server. pub enum NetworkMessages { } pub struct NetworkManager { listener: TcpListener, - server_channel: Sender, } @@ -41,6 +56,44 @@ impl NetworkManager { impl ICooperative for NetworkManager { fn tick(&self) { - println!("network manager tick") + // get all new connections + // handle each request + for connection in self.listener.incoming() { + if let Ok(stream) = connection { + + // create buffered writers + let mut reader = BufReader::new(stream.try_clone().unwrap()); + let mut writer = BufWriter::new(stream.try_clone().unwrap()); + + let mut buffer = String::new(); + + // request is always sent on new connection + writer.write_all(serde_json::to_string(&NetworkSockOut::Request).unwrap().as_bytes()).unwrap_or_default(); + writer.write_all(b"\n").unwrap_or_default(); + writer.flush().unwrap_or_default(); + + // read the new request into a buffer + let res = reader.read_line(&mut buffer); + if res.is_err() {continue;} + + // turn into enum for pattern matching + if let Ok(request) = serde_json::from_str::(&buffer) { + // perform action based on the enum + match request { + NetworkSockIn::Info => { + writer.write_all( + serde_json::to_string( + &NetworkSockOut::GotInfo {server_name: "oof", server_owner: "michael"} + ).unwrap().as_bytes() + ).unwrap(); + writer.flush().unwrap(); + } + NetworkSockIn::Connect { uuid, username, address } => { + println!("Connection requested") + } + } + } + } + } } } \ No newline at end of file From f3ab1f37dabe516d1e6c5ba7fcd1b2203c2f657f Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 17:06:31 +0000 Subject: [PATCH 37/41] Added client connecting condition to network manager --- .../server/client_management/client/mod.rs | 1 - src/lib/server/network_manager/mod.rs | 28 +++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index 4ca238a..e198e89 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -2,7 +2,6 @@ // pub mod client_v3; pub mod traits; -use std::collections::HashMap; use std::cmp::Ordering; use std::net::TcpStream; use std::sync::Mutex; diff --git a/src/lib/server/network_manager/mod.rs b/src/lib/server/network_manager/mod.rs index f85a0aa..d322707 100644 --- a/src/lib/server/network_manager/mod.rs +++ b/src/lib/server/network_manager/mod.rs @@ -1,4 +1,4 @@ - +use crate::lib::server::Client; use std::net::TcpListener; use std::sync::Arc; use std::io::BufReader; @@ -11,6 +11,7 @@ use crossbeam_channel::Sender; use crate::lib::server::ServerMessages; use crate::lib::Foundation::ICooperative; +use crate::lib::server::client_management::client::traits::IClient; /// # NetworkSockIn @@ -40,7 +41,10 @@ pub struct NetworkManager { } impl NetworkManager { - pub fn new(port: String, server_channel: Sender) -> Arc { + pub fn new( + port: String, + server_channel: Sender + ) -> Arc { let mut address = "0.0.0.0:".to_string(); address.push_str(&port); @@ -68,7 +72,9 @@ impl ICooperative for NetworkManager { let mut buffer = String::new(); // request is always sent on new connection - writer.write_all(serde_json::to_string(&NetworkSockOut::Request).unwrap().as_bytes()).unwrap_or_default(); + writer.write_all( + serde_json::to_string(&NetworkSockOut::Request).unwrap().as_bytes() + ).unwrap_or_default(); writer.write_all(b"\n").unwrap_or_default(); writer.flush().unwrap_or_default(); @@ -83,13 +89,25 @@ impl ICooperative for NetworkManager { NetworkSockIn::Info => { writer.write_all( serde_json::to_string( - &NetworkSockOut::GotInfo {server_name: "oof", server_owner: "michael"} + &NetworkSockOut::GotInfo { + server_name: "oof", + server_owner: "michael" + } ).unwrap().as_bytes() ).unwrap(); writer.flush().unwrap(); } NetworkSockIn::Connect { uuid, username, address } => { - self.server_channel.send().unwrap_or_default() + let new_client = Client::new( + uuid, + username, + address, + stream.try_clone().unwrap(), + self.server_channel.clone() + ); + self.server_channel.send( + ServerMessages::ClientConnected(new_client) + ).unwrap_or_default(); } } } From d6c4baf556a94951645b15be6a0405729f475e88 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 20:02:56 +0000 Subject: [PATCH 38/41] Implemented client add functionality in the server. --- src/lib/server/mod.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index f7209fe..5158058 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -47,23 +47,26 @@ impl Server { receiver, }) } - - pub fn send_message(&self, msg: ServerMessages) { - self.sender.send(msg).expect("!error sending message to server!") - } } impl ICooperative for Server{ fn tick(&self) { - self.network_manager.tick(); + // handle new messages loop + for message in self.receiver.iter() { + match message { + ServerMessages::ClientConnected(client) => { + self.client_manager.add_client(client); + }, + ServerMessages::ClientDisconnected(uuid) => { + self.client_manager.remove_client(uuid); + } + } + } + + // alocate time for other components + self.network_manager.tick(); + self.client_manager.tick(); - // handle new messages loop - 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 53ff1858f654f196b69a642c10f684b572db300d Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 20:27:12 +0000 Subject: [PATCH 39/41] implemented client manager tick function --- .gitignore | 1 + src/lib/server/client_management/mod.rs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index d422aab..ad414a9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ Cargo.lock .vscode/launch.json *.cer *.pem +.vscode/settings.json diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index 4c889f9..d092f8d 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -16,7 +16,10 @@ use crate::lib::server::ServerMessages; use crate::lib::Foundation::IMessagable; use crate::lib::Foundation::ICooperative; -enum ClientManagerMessages {} +enum ClientManagerMessages { + DropAll, + MessageClient, +} /// # ClientManager /// This struct manages all connected users @@ -65,6 +68,18 @@ impl TClientManager for ClientManager { impl ICooperative for ClientManager { fn tick(&self) { + for message in self.receiver.iter() { + match message { + ClientManagerMessages::DropAll => { + println!("cannot drop all clients yet") + } + _ => println!("[Client Manager]: method not implemented") + } + } + + // allocate time for clients. + let clients = self.clients.lock().unwrap(); + let _ = clients.iter().map(|(_uuid, client)| client.tick()); } } From 8f3d1549ca062cf5c2b78549dd7d1f50387fbfec Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Thu, 18 Mar 2021 23:37:48 +0000 Subject: [PATCH 40/41] fixed issue with channel blocking --- src/lib/server/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 5158058..06c5c4e 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -53,7 +53,7 @@ impl ICooperative for Server{ fn tick(&self) { // handle new messages loop - for message in self.receiver.iter() { + for message in self.receiver.try_iter() { match message { ServerMessages::ClientConnected(client) => { self.client_manager.add_client(client); From cf16367d51673aa578d69d24e83ad7e30a1cdd72 Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Sat, 20 Mar 2021 12:34:32 +0000 Subject: [PATCH 41/41] removing dead code --- src/lib/Foundation/mod.rs | 18 --------------- src/lib/foundation/mod.rs | 7 ++++++ src/lib/mod.rs | 2 +- .../server/client_management/client/mod.rs | 2 +- .../server/client_management/client/traits.rs | 1 - src/lib/server/client_management/mod.rs | 6 +++-- src/lib/server/mod.rs | 23 +++++++------------ src/lib/server/network_manager/mod.rs | 6 ++--- src/main.rs | 2 +- 9 files changed, 25 insertions(+), 42 deletions(-) delete mode 100644 src/lib/Foundation/mod.rs create mode 100644 src/lib/foundation/mod.rs diff --git a/src/lib/Foundation/mod.rs b/src/lib/Foundation/mod.rs deleted file mode 100644 index 6333649..0000000 --- a/src/lib/Foundation/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::sync::{Weak,Arc}; - -pub trait IOwned { - fn set_owner(&self, owner: Weak); -} - -pub trait IOwner { - fn add_child(&self, child: Arc); - fn get_ref(&self) -> Weak; -} - -pub trait IMessagable { - fn send_message(&self, msg: M); -} - -pub trait ICooperative { - fn tick(&self); -} \ No newline at end of file diff --git a/src/lib/foundation/mod.rs b/src/lib/foundation/mod.rs new file mode 100644 index 0000000..a5269c4 --- /dev/null +++ b/src/lib/foundation/mod.rs @@ -0,0 +1,7 @@ +pub trait IMessagable { + fn send_message(&self, msg: M); +} + +pub trait ICooperative { + fn tick(&self); +} \ No newline at end of file diff --git a/src/lib/mod.rs b/src/lib/mod.rs index 4ef91b1..1e515f8 100644 --- a/src/lib/mod.rs +++ b/src/lib/mod.rs @@ -1,7 +1,7 @@ // pub mod commands; pub mod prelude; pub mod server; -pub mod Foundation; +pub mod foundation; pub mod commands; use std::sync::Arc; diff --git a/src/lib/server/client_management/client/mod.rs b/src/lib/server/client_management/client/mod.rs index e198e89..d0ace26 100644 --- a/src/lib/server/client_management/client/mod.rs +++ b/src/lib/server/client_management/client/mod.rs @@ -14,7 +14,7 @@ use serde::{Serialize, Deserialize}; use crossbeam_channel::{Sender, Receiver, unbounded}; use traits::IClient; -use crate::lib::Foundation::{ICooperative, IMessagable}; +use crate::lib::foundation::{ICooperative, IMessagable}; use crate::lib::server::ServerMessages; /// # ClientMessage diff --git a/src/lib/server/client_management/client/traits.rs b/src/lib/server/client_management/client/traits.rs index 887a7b1..b0e3b23 100644 --- a/src/lib/server/client_management/client/traits.rs +++ b/src/lib/server/client_management/client/traits.rs @@ -1,6 +1,5 @@ use std::sync::Arc; use std::net::TcpStream; -use std::collections::HashMap; use crossbeam_channel::Sender; diff --git a/src/lib/server/client_management/mod.rs b/src/lib/server/client_management/mod.rs index d092f8d..206af7e 100644 --- a/src/lib/server/client_management/mod.rs +++ b/src/lib/server/client_management/mod.rs @@ -13,11 +13,13 @@ 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; +use crate::lib::foundation::IMessagable; +use crate::lib::foundation::ICooperative; enum ClientManagerMessages { + #[allow(dead_code)] DropAll, + #[allow(dead_code)] MessageClient, } diff --git a/src/lib/server/mod.rs b/src/lib/server/mod.rs index 06c5c4e..a2af064 100644 --- a/src/lib/server/mod.rs +++ b/src/lib/server/mod.rs @@ -1,36 +1,31 @@ pub mod client_management; pub mod network_manager; -use crate::lib::server::network_manager::NetworkManager; -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::network_manager::NetworkManager; +use std::sync::Arc; + +use crossbeam_channel::{Receiver, unbounded}; use crate::lib::server::client_management::ClientManager; use crate::lib::server::client_management::traits::TClientManager; -use crate::lib::Foundation::{ICooperative}; +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) + + #[allow(dead_code)] + ClientDisconnected(Uuid), } pub struct Server { client_manager: Arc, network_manager: Arc, - sender: Sender, receiver: Receiver, } @@ -42,8 +37,6 @@ impl Server { client_manager: ClientManager::new(sender.clone()), network_manager: NetworkManager::new("5600".to_string(), sender.clone()), - - sender, receiver, }) } diff --git a/src/lib/server/network_manager/mod.rs b/src/lib/server/network_manager/mod.rs index d322707..532b2a3 100644 --- a/src/lib/server/network_manager/mod.rs +++ b/src/lib/server/network_manager/mod.rs @@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize}; use crossbeam_channel::Sender; use crate::lib::server::ServerMessages; -use crate::lib::Foundation::ICooperative; +use crate::lib::foundation::ICooperative; use crate::lib::server::client_management::client::traits::IClient; @@ -31,9 +31,9 @@ enum NetworkSockOut<'a> { } // these are control signals from the server. -pub enum NetworkMessages { +// pub enum NetworkMessages { -} +// } pub struct NetworkManager { listener: TcpListener, diff --git a/src/main.rs b/src/main.rs index bdf0c97..1f92c55 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,7 +3,7 @@ mod lib; use clap::{App, Arg}; use crate::lib::server::Server; -use crate::lib::Foundation::ICooperative; +use crate::lib::foundation::ICooperative; fn main() { let _args = App::new("--rust chat server--")