implemented basic messageing system for clients.

This commit is contained in:
michael-bailey 2021-03-18 08:53:06 +00:00
parent a493eddd50
commit e92096b6ad
3 changed files with 70 additions and 5 deletions

View File

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

View File

@ -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<Option<TcpStream>>,
#[serde(skip)]
stream_reader: Mutex<Option<BufReader<TcpStream>>>,
#[serde(skip)]
stream_writer: Mutex<Option<BufWriter<TcpStream>>>,
}
// client funciton implmentations
impl IClient<ClientMessage> for Client {
fn new(map: HashMap<String, String>, server_channel: Sender<ServerMessages> ) -> Arc<Client> {
fn new(map: HashMap<String, String>, stream: TcpStream, server_channel: Sender<ServerMessages> ) -> Arc<Client> {
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<ClientMessage> 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<ClientMessage> 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::<ClientSocketMessage>(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),
}
}
}

View File

@ -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<TClientMessage> {
fn new(map: HashMap<String, String>, server_channel: Sender<ServerMessages> ) -> Arc<Self>;
fn new(map: HashMap<String, String>, stream: TcpStream, server_channel: Sender<ServerMessages> ) -> Arc<Self>;
fn send(&self, bytes: Vec<u8>) -> Result<(), &str>;
fn recv(&self) -> Option<Vec<u8>>;