Grpc-manager #22

Merged
michael-bailey merged 28 commits from grpc-manager into master 2024-05-30 19:42:42 +00:00
8 changed files with 0 additions and 660 deletions
Showing only changes of commit a56070baac - Show all commits

View File

@ -1,22 +0,0 @@
[package]
name = "client"
version = "0.1.0"
authors = ["michael-bailey <mickyb18a@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cursive = "0.17"
uuid = {version = "1.1.2", features = ["serde", "v4"]}
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
crossbeam = "0.8.0"
crossbeam-channel = "0.5.0"
tokio = { version = "1.9.0", features = ["full"] }
futures = "0.3.16"
async-trait = "0.1.52"
server = {path = '../server'}
foundation = {path = '../foundation'}

View File

@ -1,34 +0,0 @@
mod managers;
mod worker;
mod worker_message;
use cursive::{
menu::{Item, Tree},
traits::Nameable,
views::{Dialog, TextView},
Cursive,
CursiveExt,
};
use worker::Worker;
fn main() {
let mut app = Cursive::default();
let worker_stream = Worker::new(app.cb_sink().clone()).start();
app.set_user_data(worker_stream);
app.add_layer(
Dialog::new()
.content(TextView::new("Hello world").with_name("TextView"))
.button("close", |s| s.quit()),
);
app.menubar().autohide = false;
app.menubar().add_subtree(
"Application",
Tree::new()
.item(Item::leaf("About", |s| s.quit()))
.delimiter()
.item(Item::leaf("Quit", |s| s.quit())),
);
app.set_fps(30);
app.run();
}

View File

@ -1,221 +0,0 @@
use std::{
io::{Error, ErrorKind},
mem,
sync::{atomic::AtomicBool, Arc},
};
use async_trait::async_trait;
use foundation::{
connection::Connection,
messages::{
client::{ClientStreamIn, ClientStreamOut},
network::{NetworkSockIn, NetworkSockOut},
},
prelude::IManager,
};
use tokio::{
net::ToSocketAddrs,
sync::{mpsc::Sender, Mutex},
};
use uuid::Uuid;
use crate::managers::NetworkManagerMessage;
pub struct NetworkManager<M>
where
M: From<NetworkManagerMessage>,
{
#[allow(unused)]
server_connection: Mutex<Option<Arc<Connection>>>,
#[allow(unused)]
cursive: Sender<M>,
is_logged_in: AtomicBool,
}
impl<M> NetworkManager<M>
where
M: From<NetworkManagerMessage>,
{
pub fn new(sender: Sender<M>) -> Arc<Self> {
Arc::new(NetworkManager {
server_connection: Mutex::new(None),
cursive: sender,
is_logged_in: AtomicBool::new(false),
})
}
#[allow(unused)]
pub async fn info<T: ToSocketAddrs>(
self: &Arc<Self>,
host: T,
) -> Result<NetworkManagerMessage, Error> {
let connection = Connection::new();
println!("Created connection");
connection.connect(host).await?;
let req = connection.read().await?;
println!("request: {:?}", req);
if let NetworkSockOut::Request = req {
connection
.write::<NetworkSockIn>(NetworkSockIn::Info)
.await?;
return Ok(connection.read::<NetworkSockOut>().await?.into());
} else {
Err(Error::new(
ErrorKind::ConnectionAborted,
"Request not received",
))
}
}
#[allow(unused)]
pub async fn login(
self: &Arc<Self>,
host: String,
uuid: Uuid,
username: String,
address: String,
) -> Result<(), Error> {
let connection = Connection::new();
let _ = connection.connect(host).await?;
println!("created connection");
let req = connection.read().await?;
println!("read request");
return if let NetworkSockOut::Request = req {
println!("got request");
connection
.write(NetworkSockIn::Connect {
username,
uuid,
address,
})
.await?;
let res = connection.read().await?;
// switch over to ClientStreamOut
if let ClientStreamOut::Connected = res {
let mut connection_lock = self.server_connection.lock().await;
let _ = mem::replace(&mut *connection_lock, Some(connection));
Ok(())
} else {
Err(Error::new(
ErrorKind::ConnectionRefused,
format!("expected connecting received: {:?}", res),
))
}
} else {
println!("request not found");
Err(Error::new(
ErrorKind::ConnectionAborted,
"Server did not send request",
))
};
}
#[allow(unused)]
pub async fn logout(self: &Arc<Self>) -> Result<(), Error> {
let mut connection_lock = self.server_connection.lock().await;
let connection = mem::replace(&mut *connection_lock, None).unwrap();
connection.write(ClientStreamIn::Disconnect).await?;
return if let ClientStreamOut::Disconnected = connection.read().await? {
Ok(())
} else {
Err(Error::new(
ErrorKind::InvalidData,
"disconnect failed, forcing disconnect",
))
};
}
}
#[async_trait]
impl<M: 'static> IManager for NetworkManager<M>
where
M: From<NetworkManagerMessage> + Send,
{
async fn run(self: &Arc<Self>) {
println!("networkManager tick")
}
}
#[cfg(test)]
mod test {
use std::future::Future;
use serverlib::Server;
use tokio::sync::mpsc::channel;
use uuid::Uuid;
use crate::managers::{network::NetworkManagerMessage, NetworkManager};
async fn wrap_setup<T, F>(test: T)
where
T: FnOnce(u16) -> F,
F: Future,
{
let server = Server::new().await.unwrap();
let port = server.port().await;
tokio::spawn(async move {
server.start().await;
});
test(port).await;
}
#[tokio::test]
async fn test_fetch_server_info() {
use NetworkManagerMessage::Info;
#[allow(unused)]
let (tx, rx) = channel::<NetworkManagerMessage>(16);
wrap_setup(|port| async move {
let network = NetworkManager::new(tx);
let info = network
.info(format!("localhost:{}", port))
.await
.expect("Failed to fetch info");
assert_eq!(
info,
Info {
server_name: "oof".to_string(),
server_owner: "michael".to_string()
}
);
})
.await;
}
#[tokio::test]
async fn test_login_and_logout_to_server() {
#[allow(unused)]
let (tx, rx) = channel::<NetworkManagerMessage>(16);
let network = NetworkManager::new(tx);
println!("created network manger");
wrap_setup(|port| async move {
network
.login(
format!("localhost:{}", port),
Uuid::default(),
"user1".to_string(),
"localhost".to_string(),
)
.await
.expect("login failed");
network.logout().await.expect("logout failed");
})
.await;
}
}

View File

@ -1,51 +0,0 @@
use foundation::{messages::network::NetworkSockOut, ClientDetails};
#[derive(Debug)]
pub enum NetworkManagerMessage {
#[allow(unused)]
Users(Vec<ClientDetails>),
Info {
server_name: String,
server_owner: String,
},
Error(&'static str),
}
impl From<NetworkSockOut> for NetworkManagerMessage {
fn from(other: NetworkSockOut) -> Self {
use NetworkManagerMessage::{Error, Info as NewInfo};
use NetworkSockOut::GotInfo as OldInfo;
match other {
OldInfo {
server_name,
server_owner,
} => NewInfo {
server_name,
server_owner,
},
_ => Error("Error occurred with conversion"),
}
}
}
impl PartialEq for NetworkManagerMessage {
fn eq(&self, other: &Self) -> bool {
use NetworkManagerMessage::Info;
match self {
Info {
server_owner,
server_name,
} => {
if let Info {
server_owner: other_owner,
server_name: other_name,
} = other
{
return server_owner == other_owner && server_name == other_name;
}
false
}
_ => false,
}
}
}

View File

@ -1,7 +0,0 @@
mod network;
#[path = "message.rs"]
mod message;
pub use message::NetworkManagerMessage;
pub use network::NetworkManager;

View File

@ -1,221 +0,0 @@
use std::{
io::{Error, ErrorKind},
mem,
sync::{atomic::AtomicBool, Arc},
};
use async_trait::async_trait;
use foundation::{
connection::Connection,
messages::{
client::{ClientStreamIn, ClientStreamOut},
network::{NetworkSockIn, NetworkSockOut},
},
prelude::IManager,
};
use tokio::{
net::ToSocketAddrs,
sync::{mpsc::Sender, Mutex},
};
use uuid::Uuid;
use crate::managers::NetworkManagerMessage;
pub struct NetworkManager<M>
where
M: From<NetworkManagerMessage>,
{
#[allow(unused)]
server_connection: Mutex<Option<Arc<Connection>>>,
#[allow(unused)]
cursive: Sender<M>,
is_logged_in: AtomicBool,
}
impl<M> NetworkManager<M>
where
M: From<NetworkManagerMessage>,
{
pub fn new(sender: Sender<M>) -> Arc<Self> {
Arc::new(NetworkManager {
server_connection: Mutex::new(None),
cursive: sender,
is_logged_in: AtomicBool::new(false),
})
}
#[allow(unused)]
pub async fn info<T: ToSocketAddrs>(
self: &Arc<Self>,
host: T,
) -> Result<NetworkManagerMessage, Error> {
let connection = Connection::new();
println!("Created connection");
connection.connect(host).await?;
let req = connection.read().await?;
println!("request: {:?}", req);
if let NetworkSockOut::Request = req {
connection
.write::<NetworkSockIn>(NetworkSockIn::Info)
.await?;
return Ok(connection.read::<NetworkSockOut>().await?.into());
} else {
Err(Error::new(
ErrorKind::ConnectionAborted,
"Request not received",
))
}
}
#[allow(unused)]
pub async fn login(
self: &Arc<Self>,
host: String,
uuid: Uuid,
username: String,
address: String,
) -> Result<(), Error> {
let connection = Connection::new();
let _ = connection.connect(host).await?;
println!("created connection");
let req = connection.read().await?;
println!("read request");
return if let NetworkSockOut::Request = req {
println!("got request");
connection
.write(NetworkSockIn::Connect {
username,
uuid,
address,
})
.await?;
let res = connection.read().await?;
// switch over to ClientStreamOut
if let ClientStreamOut::Connected = res {
let mut connection_lock = self.server_connection.lock().await;
let _ = mem::replace(&mut *connection_lock, Some(connection));
Ok(())
} else {
Err(Error::new(
ErrorKind::ConnectionRefused,
format!("expected connecting received: {:?}", res),
))
}
} else {
println!("request not found");
Err(Error::new(
ErrorKind::ConnectionAborted,
"Server did not send request",
))
};
}
#[allow(unused)]
pub async fn logout(self: &Arc<Self>) -> Result<(), Error> {
let mut connection_lock = self.server_connection.lock().await;
let connection = mem::replace(&mut *connection_lock, None).unwrap();
connection.write(ClientStreamIn::Disconnect).await?;
return if let ClientStreamOut::Disconnected = connection.read().await? {
Ok(())
} else {
Err(Error::new(
ErrorKind::InvalidData,
"disconnect failed, forcing disconnect",
))
};
}
}
#[async_trait]
impl<M: 'static> IManager for NetworkManager<M>
where
M: From<NetworkManagerMessage> + Send,
{
async fn run(self: &Arc<Self>) {
println!("networkManager tick")
}
}
#[cfg(test)]
mod test {
use std::future::Future;
use serverlib::Server;
use tokio::sync::mpsc::channel;
use uuid::Uuid;
use crate::managers::{network::NetworkManagerMessage, NetworkManager};
async fn wrap_setup<T, F>(test: T)
where
T: FnOnce(u16) -> F,
F: Future,
{
let server = Server::new().await.unwrap();
let port = server.port().await;
tokio::spawn(async move {
server.start().await;
});
test(port).await;
}
#[tokio::test]
async fn test_fetch_server_info() {
use NetworkManagerMessage::Info;
#[allow(unused)]
let (tx, rx) = channel::<NetworkManagerMessage>(16);
wrap_setup(|port| async move {
let network = NetworkManager::new(tx);
let info = network
.info(format!("localhost:{}", port))
.await
.expect("Failed to fetch info");
assert_eq!(
info,
Info {
server_name: "oof".to_string(),
server_owner: "michael".to_string()
}
);
})
.await;
}
#[tokio::test]
async fn test_login_and_logout_to_server() {
#[allow(unused)]
let (tx, rx) = channel::<NetworkManagerMessage>(16);
let network = NetworkManager::new(tx);
println!("created network manger");
wrap_setup(|port| async move {
network
.login(
format!("localhost:{}", port),
Uuid::default(),
"user1".to_string(),
"localhost".to_string(),
)
.await
.expect("login failed");
network.logout().await.expect("logout failed");
})
.await;
}
}

View File

@ -1,75 +0,0 @@
use std::{sync::Arc, thread::spawn, time::Duration};
use crossbeam_channel::Sender as CrossSender;
use foundation::ClientDetails;
use tokio::{
runtime::Runtime,
sync::{
mpsc::{channel, Sender as TokioSender},
Mutex,
},
time::sleep,
};
use crate::{
managers::NetworkManager,
worker_message::WorkerMessage,
Cursive,
TextView,
};
pub type CursiveSender = CrossSender<Box<dyn FnOnce(&mut Cursive) + Send>>;
pub struct Worker {
cursive_sender: CursiveSender,
network_manager: Arc<NetworkManager<WorkerMessage>>,
number: Arc<Mutex<usize>>,
#[allow(unused)]
user_details: Mutex<Option<ClientDetails>>,
}
impl Worker {
pub fn new(sender: CursiveSender) -> Worker {
#[allow(unused)]
let (tx, rx) = channel::<WorkerMessage>(16);
Worker {
network_manager: NetworkManager::new(tx.clone()),
number: Arc::new(Mutex::new(0)),
user_details: Mutex::new(None),
cursive_sender: sender,
}
}
pub fn start(self) -> TokioSender<WorkerMessage> {
#[allow(unused)]
let (tx, rx) = channel::<WorkerMessage>(16);
spawn(move || {
let sender = self.cursive_sender.clone();
let rt = Runtime::new().unwrap();
let tmp_num = self.number.clone();
#[allow(unused)]
let network_manager = self.network_manager.clone();
rt.block_on(async move {
let a = &tmp_num;
loop {
let num = Arc::clone(&a);
sleep(Duration::new(1, 0)).await;
let _ = sender.send(Box::new(move |s| {
let num = &num.clone();
let mut num_lock = num.blocking_lock();
*num_lock += 1;
let a = *num_lock;
s.find_name::<TextView>("TextView")
.unwrap()
.set_content(a.to_string());
}));
}
})
});
tx
}
}

View File

@ -1,29 +0,0 @@
use crate::managers::NetworkManagerMessage;
pub enum WorkerMessage {
Info {
server_name: String,
server_owner: String,
},
#[allow(unused)]
Error(String),
}
impl From<NetworkManagerMessage> for WorkerMessage {
fn from(other: NetworkManagerMessage) -> Self {
#[allow(unused)]
use NetworkManagerMessage::{Error, Info as OldInfo};
#[allow(unused)]
use WorkerMessage::{Error as NewError, Info as NewInfo};
match other {
OldInfo {
server_name,
server_owner,
} => NewInfo {
server_owner,
server_name,
},
_ => todo!(),
}
}
}