adding user update support #11

Closed
michael-bailey wants to merge 1 commits from Find-Clients into master
10 changed files with 92 additions and 80 deletions
Showing only changes of commit 9299d2e335 - Show all commits

View File

@ -6,7 +6,7 @@ use uuid::Uuid;
#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct ClientDetails {
pub uuid: Uuid,
pub username: String,
pub address: String,
}
pub uuid: Uuid,
pub username: String,
pub address: String,
}

View File

@ -25,7 +25,7 @@ pub enum ClientStreamOut {
UserMessage { from: Uuid, content: String },
GlobalMessage { content: String },
ConnectedClients {clients: Vec<ClientDetails>},
ConnectedClients { clients: Vec<ClientDetails> },
Disconnected,
}

View File

@ -1,2 +1,2 @@
hard_tabs = true
max_width = 90
max_width = 100

View File

@ -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'

View File

@ -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::<ClientStreamIn>(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<ClientDetails> = 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<ClientDetails> = 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);

View File

@ -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<ClientMgrMessage, Sender<ServerMessage>> 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<Arc<Client>> = lock.values().cloned().collect();
let clients_vec: Vec<Arc<Client>> =
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"),

View File

@ -11,17 +11,20 @@ use server::Server;
fn main() {
let _args = App::new("--rust chat server--")
.version("0.1.5")
.author("Mitchel Hardie <mitch161>, Michael Bailey <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 <mitch161>, Michael Bailey <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();

View File

@ -7,7 +7,7 @@ use crate::client::Client;
pub enum ClientMessage {
Message { from: Uuid, content: String },
Update {clients: Vec<Arc<Client>>},
SendClients { clients: Vec<Arc<Client>> },
Disconnect,
}
@ -16,7 +16,9 @@ pub enum ClientMessage {
pub enum ClientMgrMessage {
Remove(Uuid),
Add(Arc<Client>),
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<Client>),
ClientConnected {
client: Arc<Client>,
},
ClientSendMessage {
from: Uuid,
to: Uuid,
content: String,
},
ClientDisconnected(Uuid),
ClientUpdate(Uuid),
ClientDisconnected {
id: Uuid,
},
ClientUpdate {
to: Uuid,
},
}

View File

@ -19,10 +19,7 @@ pub struct NetworkManager {
}
impl NetworkManager {
pub fn new(
port: String,
server_channel: Sender<ServerMessage>,
) -> Arc<NetworkManager> {
pub fn new(port: String, server_channel: Sender<ServerMessage>) -> Arc<NetworkManager> {
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();
}
}

View File

@ -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 }),
}
}
}