From f43ceb07df0f4048426930a5acd84f74cb79c4a4 Mon Sep 17 00:00:00 2001 From: michael bailey Date: Tue, 13 Apr 2021 21:54:20 +0100 Subject: [PATCH 1/2] Create rust.yml (#3) + added a workflow file for CI --- .github/workflows/rust.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 0000000..edf72fb --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,25 @@ +name: Rust + +on: + push: + branches: [ ref-method ] + pull_request: + branches: [ master ] + +env: + CARGO_TERM_COLOR: always + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + + steps: + - uses: actions/checkout@v2 + - name: check + run: cargo check --verbose + - name: Build + run: cargo build --verbose + -- 2.40.1 From 9299d2e335556894b626e89430c8948d9cf903bc Mon Sep 17 00:00:00 2001 From: michael-bailey Date: Wed, 21 Apr 2021 13:14:57 +0000 Subject: [PATCH 2/2] adding user update support --- foundation/src/lib.rs | 8 ++--- foundation/src/messages/client.rs | 2 +- rustfmt.toml | 2 +- server/Cargo.toml | 1 + server/src/client.rs | 53 ++++++++++++++++--------------- server/src/client_manager.rs | 37 +++++++++++---------- server/src/main.rs | 25 ++++++++------- server/src/messages.rs | 18 ++++++++--- server/src/network_manager.rs | 14 +++----- server/src/server.rs | 12 ++++--- 10 files changed, 92 insertions(+), 80 deletions(-) diff --git a/foundation/src/lib.rs b/foundation/src/lib.rs index 3ff3748..97dca2e 100644 --- a/foundation/src/lib.rs +++ b/foundation/src/lib.rs @@ -6,7 +6,7 @@ use uuid::Uuid; #[derive(Deserialize, Serialize, Debug, Clone)] pub struct ClientDetails { - pub uuid: Uuid, - pub username: String, - pub address: String, -} \ No newline at end of file + pub uuid: Uuid, + pub username: String, + pub address: String, +} diff --git a/foundation/src/messages/client.rs b/foundation/src/messages/client.rs index cabe3bc..2944a31 100644 --- a/foundation/src/messages/client.rs +++ b/foundation/src/messages/client.rs @@ -25,7 +25,7 @@ pub enum ClientStreamOut { UserMessage { from: Uuid, content: String }, GlobalMessage { content: String }, - ConnectedClients {clients: Vec}, + ConnectedClients { clients: Vec }, Disconnected, } diff --git a/rustfmt.toml b/rustfmt.toml index 779de58..544999c 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,2 +1,2 @@ hard_tabs = true -max_width = 90 \ No newline at end of file +max_width = 100 \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index a91dd21..e5701c5 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -13,6 +13,7 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" crossbeam = "0.8.0" crossbeam-channel = "0.5.0" +zeroize = "1.1.0" [dependencies.foundation] path = '../foundation' \ No newline at end of file diff --git a/server/src/client.rs b/server/src/client.rs index d5e1efd..bfd9bee 100644 --- a/server/src/client.rs +++ b/server/src/client.rs @@ -13,10 +13,11 @@ use std::sync::Mutex; use crossbeam_channel::{unbounded, Receiver, Sender}; use serde::Serialize; use uuid::Uuid; +use zeroize::Zeroize; -use foundation::ClientDetails; use foundation::messages::client::{ClientStreamIn, ClientStreamOut}; use foundation::prelude::IMessagable; +use foundation::ClientDetails; /// # Client /// This struct represents a connected user. @@ -117,7 +118,7 @@ impl IPreemptive for Client { let _ = std::thread::Builder::new() .name(format!("client thread recv [{:?}]", &arc.uuid)) .spawn(move || { - use ClientMessage::{Disconnect}; + use ClientMessage::Disconnect; let arc = arc1; let mut buffer = String::new(); @@ -131,6 +132,7 @@ impl IPreemptive for Client { } let command = serde_json::from_str::(buffer.as_str()); + println!("[Client {:?}]: recieved {}", arc.uuid, &buffer); match command { Ok(ClientStreamIn::Disconnect) => { println!("[Client {:?}]: Disconnect recieved", &arc.uuid); @@ -138,10 +140,7 @@ impl IPreemptive for Client { break 'main; } Ok(ClientStreamIn::SendMessage { to, content }) => { - println!( - "[Client {:?}]: send message to: {:?}", - &arc.uuid, &to - ); + println!("[Client {:?}]: send message to: {:?}", &arc.uuid, &to); let lock = arc.server_channel.lock().unwrap(); let sender = lock.as_ref().unwrap(); let _ = sender.send(ServerMessage::ClientSendMessage { @@ -150,8 +149,14 @@ impl IPreemptive for Client { content, }); } + Ok(ClientStreamIn::Update) => { + let lock = arc.server_channel.lock().unwrap(); + let sender = lock.as_ref().unwrap(); + let _ = sender.send(ServerMessage::ClientUpdate { to: arc.uuid }); + } _ => println!("[Client {:?}]: command not found", &arc.uuid), } + buffer.zeroize(); } println!("[Client {:?}] exited thread 1", &arc.uuid); }); @@ -175,7 +180,7 @@ impl IPreemptive for Client { 'main: loop { for message in arc.output.iter() { - use ClientMessage::{Disconnect,Message, Update}; + use ClientMessage::{Disconnect, Message, SendClients}; println!("[Client {:?}]: {:?}", &arc.uuid, message); match message { Disconnect => { @@ -184,35 +189,33 @@ impl IPreemptive for Client { .unwrap() .as_mut() .unwrap() - .send(ServerMessage::ClientDisconnected(arc.uuid)) + .send(ServerMessage::ClientDisconnected { id: arc.uuid }) .unwrap(); break 'main; } Message { from, content } => { - let _ = writeln!( - buffer, - "{}", - serde_json::to_string( - &ClientStreamOut::UserMessage { from, content } - ) - .unwrap() - ); + let msg = &ClientStreamOut::UserMessage { from, content }; + let _ = writeln!(buffer, "{}", serde_json::to_string(msg).unwrap()); let _ = writer.write_all(&buffer); let _ = writer.flush(); } - Update {clients} => { - let client_details_vec: Vec = clients.iter().map(|client| &client.details).cloned().collect(); - let _ = writeln!( - buffer, - "{}", - serde_json::to_string( - &ClientStreamOut::ConnectedClients {clients: client_details_vec} - ).unwrap() - ); + SendClients { clients } => { + let client_details_vec: Vec = clients + .iter() + .map(|client| &client.details) + .cloned() + .collect(); + + let msg = &ClientStreamOut::ConnectedClients { + clients: client_details_vec, + }; + + let _ = writeln!(buffer, "{}", serde_json::to_string(msg).unwrap()); let _ = writer.write_all(&buffer); let _ = writer.flush(); } } + buffer.zeroize(); } } println!("[Client {:?}]: exited thread 2", &arc.uuid); diff --git a/server/src/client_manager.rs b/server/src/client_manager.rs index a3f4d51..0c0cbef 100644 --- a/server/src/client_manager.rs +++ b/server/src/client_manager.rs @@ -39,6 +39,13 @@ impl ClientManager { receiver, }) } + + fn send_to_client(&self, id: &Uuid, msg: ClientMessage) { + let lock = self.clients.lock().unwrap(); + if let Some(client) = lock.get(id) { + client.send_message(msg) + } + } } impl IMessagable> for ClientManager { @@ -59,7 +66,7 @@ impl IPreemptive for ClientManager { if !arc.receiver.is_empty() { for message in arc.receiver.try_iter() { println!("[Client manager]: recieved message: {:?}", message); - use ClientMgrMessage::{Add, Remove, SendMessage, SendClients}; + use ClientMgrMessage::{Add, Remove, SendClients, SendMessage}; match message { Add(client) => { @@ -69,35 +76,27 @@ impl IPreemptive for ClientManager { if lock.insert(client.uuid, client).is_none() { println!("value is new"); } - }, + } Remove(uuid) => { println!("[Client Manager]: removing client: {:?}", &uuid); - if let Some(client) = - arc.clients.lock().unwrap().remove(&uuid) - { + if let Some(client) = arc.clients.lock().unwrap().remove(&uuid) { client.send_message(ClientMessage::Disconnect); } - }, + } SendMessage { to, from, content } => { + arc.send_to_client(&to, ClientMessage::Message { from, content }) + } + SendClients { to } => { let lock = arc.clients.lock().unwrap(); if let Some(client) = lock.get(&to) { - client.send_message(ClientMessage::Message { - from, - content, - }) - } - }, - SendClients {to} => { - let lock = arc.clients.lock().unwrap(); - if let Some(client) = lock.get(&to) { - let clients_vec: Vec> = lock.values().cloned().collect(); + let clients_vec: Vec> = + lock.values().cloned().collect(); - client.send_message(ClientMessage::Update { + client.send_message(ClientMessage::SendClients { clients: clients_vec, }) } - }, - + } #[allow(unreachable_patterns)] _ => println!("[Client manager]: not implemented"), diff --git a/server/src/main.rs b/server/src/main.rs index dfc409f..e90c6ac 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -11,17 +11,20 @@ use server::Server; fn main() { let _args = App::new("--rust chat server--") - .version("0.1.5") - .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::with_name("config") - .short("p") - .long("port") - .value_name("PORT") - .help("sets the port the server runs on.") - .takes_value(true)) - .get_matches(); + .version("0.1.5") + .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::with_name("config") + .short("p") + .long("port") + .value_name("PORT") + .help("sets the port the server runs on.") + .takes_value(true), + ) + .get_matches(); let server = Server::new(); diff --git a/server/src/messages.rs b/server/src/messages.rs index f5d2e11..2db937f 100644 --- a/server/src/messages.rs +++ b/server/src/messages.rs @@ -7,7 +7,7 @@ use crate::client::Client; pub enum ClientMessage { Message { from: Uuid, content: String }, - Update {clients: Vec>}, + SendClients { clients: Vec> }, Disconnect, } @@ -16,7 +16,9 @@ pub enum ClientMessage { pub enum ClientMgrMessage { Remove(Uuid), Add(Arc), - SendClients {to: Uuid}, + SendClients { + to: Uuid, + }, SendMessage { from: Uuid, to: Uuid, @@ -26,12 +28,18 @@ pub enum ClientMgrMessage { #[derive(Debug)] pub enum ServerMessage { - ClientConnected(Arc), + ClientConnected { + client: Arc, + }, ClientSendMessage { from: Uuid, to: Uuid, content: String, }, - ClientDisconnected(Uuid), - ClientUpdate(Uuid), + ClientDisconnected { + id: Uuid, + }, + ClientUpdate { + to: Uuid, + }, } diff --git a/server/src/network_manager.rs b/server/src/network_manager.rs index 5e450ac..5a1e0ee 100644 --- a/server/src/network_manager.rs +++ b/server/src/network_manager.rs @@ -19,10 +19,7 @@ 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); @@ -63,8 +60,7 @@ impl IPreemptive for NetworkManager { let _ = writeln!( out_buffer, "{}", - serde_json::to_string(&NetworkSockOut::Request) - .unwrap() + serde_json::to_string(&NetworkSockOut::Request).unwrap() ); let _ = writer.write_all(&out_buffer); @@ -112,9 +108,9 @@ impl IPreemptive for NetworkManager { server_channel.clone(), ); server_channel - .send(ServerMessage::ClientConnected( - new_client, - )) + .send(ServerMessage::ClientConnected { + client: new_client, + }) .unwrap_or_default(); } } diff --git a/server/src/server.rs b/server/src/server.rs index 2e7d7ec..cc62ec6 100644 --- a/server/src/server.rs +++ b/server/src/server.rs @@ -48,17 +48,19 @@ impl ICooperative for Server { for message in self.receiver.try_iter() { println!("[server]: received message {:?}", &message); match message { - ServerMessage::ClientConnected(client) => { + ServerMessage::ClientConnected { client } => { self.client_manager.send_message(Add(client)) } - ServerMessage::ClientDisconnected(uuid) => { - println!("disconnecting client {:?}", uuid); - self.client_manager.send_message(Remove(uuid)); + ServerMessage::ClientDisconnected { id } => { + println!("disconnecting client {:?}", id); + self.client_manager.send_message(Remove(id)); } ServerMessage::ClientSendMessage { from, to, content } => self .client_manager .send_message(SendMessage { from, to, content }), - ServerMessage::ClientUpdate (_uuid) => println!("not implemented"), + ServerMessage::ClientUpdate { to } => self + .client_manager + .send_message(ClientMgrMessage::SendClients { to }), } } } -- 2.40.1