Work on tree and routing

This commit is contained in:
Michael Mikovsky
2025-06-10 06:12:18 -06:00
parent a148e4e0a8
commit c5f6e2920c
18 changed files with 543 additions and 238 deletions
+1
View File
@@ -13,6 +13,7 @@ serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
# slint = "1.11.0"
unshell-rs-lib = { path = "./unshell-rs-lib" }
uuid = { version = "1.17.0", features = ["v4"] }
# [build-dependencies]
+50 -11
View File
@@ -1,24 +1,51 @@
use std::{error::Error, io::Write, net::SocketAddr};
use std::{io::Write, net::SocketAddr, thread};
use unshell_rs_lib::{
layers::{LayerConfig, build_client},
Error,
connection::{PacketError, Packets},
layers::build_client,
networkers::{ClientTrait, Connection, TCPClient},
};
use crate::client;
pub struct Cli;
impl Cli {
pub fn connect(addr: SocketAddr) -> Result<(), Box<dyn Error>> {
let mut client = build_client(
TCPClient::connect(&addr)?,
vec![LayerConfig::Handshake, LayerConfig::Base64],
)?;
pub fn connect(addr: SocketAddr) -> Result<(), Error> {
let mut client = build_client(TCPClient::connect(&addr)?, vec![])?;
let stdin = std::io::stdin();
let mut stdout = std::io::stdout();
let mut client_clone = client.try_clone()?;
thread::spawn(move || {
// let data = client.read()?;
let packet = Packets::decode(client_clone.read().unwrap().as_str()).unwrap();
match packet {
Packets::UpdateConnections(items) => {
for item in items {
println!("{}", item);
}
}
Packets::UpdateRoutes(items) => {
for item in items {
println!("{}", item);
}
}
_ => {
client_clone
.write(
Packets::Error(PacketError::UnsupportedType)
.encode()
.unwrap()
.as_str(),
)
.unwrap();
warn!("Invalid packet: {:?}", packet)
}
}
});
loop {
print!("> ");
stdout.flush()?;
@@ -27,7 +54,19 @@ impl Cli {
stdin.read_line(&mut input)?;
let input = input.trim();
client.write(input)?;
match input.split(" ").nth(0).unwrap() {
"clients" => {
client.write(Packets::GetConnections.encode()?.as_str())?;
}
"routes" => {
client.write(Packets::GetRoutes.encode()?.as_str())?;
}
_ => {
warn!("Invalid command!")
}
}
// client.write(input)?;
}
}
}
-1
View File
@@ -1,3 +1,2 @@
mod cli;
pub use cli::Cli;
+62 -38
View File
@@ -8,9 +8,10 @@ use std::{
use clap::{Parser, Subcommand};
use log::error;
use unshell_rs::Cli;
use unshell_rs_lib::connection::Node;
// use unshell_rs::{UnshellClient, UnshellGui, UnshellServer};
// use unshell_rs
use unshell_rs_lib::{
connection::{ConnectionConfig, Node},
layers::LayerConfig,
};
pub static DEFAULT_CONFIG_FILEPATH: &'static str = "server_config.json";
@@ -32,23 +33,27 @@ struct Args {
#[derive(Debug, Subcommand)]
enum Commands {
/// Run as a service, and potentially hosting a website
#[command(arg_required_else_help = true)]
Relay {
/// IPv4 to listen for clients on.
host: String,
Start,
Middle,
End,
/// Port listen to for command clients
#[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
port: u16,
// Run as a service, and potentially hosting a website
// #[command(arg_required_else_help = true)]
// Relay {
// /// IPv4 to listen for clients on.
// host: String,
/// Json file to store config
#[arg(short, long, default_value_t = DEFAULT_CONFIG_FILEPATH.to_string())]
config_filepath: String,
// /// Port to listen for website traffic (0 is disabled)
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// web_port: u16,
},
// /// Port listen to for command clients
// #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// port: u16,
// /// Json file to store config
// #[arg(short, long, default_value_t = DEFAULT_CONFIG_FILEPATH.to_string())]
// config_filepath: String,
// // /// Port to listen for website traffic (0 is disabled)
// // #[arg(short, long, default_value_t = DEFAULT_SERVICE_PORT)]
// // web_port: u16,
// },
/// Connect to remote server
Connect {
/// Remote server to connect to
@@ -68,33 +73,52 @@ fn main() -> Result<(), Box<dyn Error>> {
pretty_env_logger::init();
let args = Args::parse();
match args.command {
Commands::Relay {
host,
port,
config_filepath,
} => {
let addr = SocketAddr::from_str(format!("{}:{}", host, port).as_str());
if let Err(e) = Node::run(if let Ok(addr) = addr {
addr
} else {
error!("Could not parse address!");
return Ok(());
}) {
error!("{}", e);
}
}
if let Err(e) = match args.command {
// Commands::Relay { host, port, .. } => {
// let addr = SocketAddr::from_str(format!("{}:{}", host, port).as_str());
// if let Err(e) = Node::run() {
// error!("{}", e);
// }
// }
Commands::Start {} => Node::run_master(
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13370")?,
layers: vec![],
},
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13371")?,
layers: vec![],
}],
),
Commands::Middle {} => Node::run_node(
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13371")?,
layers: vec![],
},
vec![ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13372")?,
layers: vec![LayerConfig::Base64],
}],
),
Commands::End {} => Node::run_node(
ConnectionConfig {
socket: SocketAddr::from_str("127.0.0.1:13372")?,
layers: vec![LayerConfig::Base64],
},
vec![],
),
Commands::Connect { host, port } => {
let addr = SocketAddr::from_str(format!("{}:{}", host, port).as_str());
if let Err(e) = Cli::connect(if let Ok(addr) = addr {
Cli::connect(if let Ok(addr) = addr {
addr
} else {
error!("Could not parse address!");
return Ok(());
}) {
error!("{}", e);
}
})
}
} {
error!("{}", e);
};
Ok(())
+3
View File
@@ -0,0 +1,3 @@
mod cli;
pub use cli::Cli;
+1
View File
@@ -8,3 +8,4 @@ crossbeam-channel = "0.5.15"
log = "0.4.27"
serde = { version = "1.0.219", features = ["derive"] }
serde_json = "1.0.140"
uuid = { version = "1.17.0", features = ["v4"] }
+11
View File
@@ -0,0 +1,11 @@
use std::net::SocketAddr;
use serde::{Deserialize, Serialize};
use crate::layers::LayerConfig;
#[derive(Serialize, Deserialize, Debug)]
pub struct ConnectionConfig {
pub socket: SocketAddr,
pub layers: Vec<LayerConfig>,
}
+6
View File
@@ -1,2 +1,8 @@
mod listener;
mod node;
mod packets;
pub use listener::ConnectionConfig;
pub use node::Node;
pub use packets::PacketError;
pub use packets::Packets;
+252 -26
View File
@@ -1,37 +1,263 @@
use std::{net::SocketAddr, thread};
use std::{
f32::consts::PI,
sync::{Arc, Mutex},
thread,
time::Duration,
};
use uuid::Uuid;
use crate::{
Error,
layers::LayerConfig,
networkers::{Connection, ServerTrait, TCPConnection, TCPServer, run_listener},
connection::{listener::ConnectionConfig, packets::Packets},
layers::build_client,
networkers::{ClientTrait, Connection, ServerTrait, TCPClient, TCPServer, run_listener_state},
};
pub struct Node;
pub struct Node {
// parent: Box<dyn Connection + Send + Sync>,
clients: Vec<Client>,
}
pub struct Client {
connection: Box<dyn Connection + Send>,
uuid: String,
route: Vec<String>,
}
impl Client {
pub fn get_info(&self) -> String {
format!("{} ({})", self.uuid, self.route.join("->"))
}
}
fn read(c: &mut Box<dyn Connection + Send>) -> Result<Packets, Error> {
Packets::decode(c.read()?.as_str())
}
fn write(c: &mut Box<dyn Connection + Send>, packet: Packets) -> Result<(), Error> {
c.write(packet.encode()?.as_str())
}
impl Node {
pub fn run(addr: SocketAddr) -> Result<(), Error> {
let layers = vec![LayerConfig::Handshake, LayerConfig::Base64];
run_listener(
TCPServer::bind(&addr)?,
layers,
|connection: Box<dyn Connection + Send + 'static>| {
thread::spawn(move || {
let mut connection = connection;
loop {
if let Ok(data) = connection.read() {
if !connection.is_alive() {
warn!("{} Disconnected!", connection.get_info());
break;
}
println!("Data: {}", data);
}
}
});
},
);
fn run_listeners(
state: &Arc<Mutex<Self>>,
listeners: Vec<ConnectionConfig>,
) -> Result<(), Error> {
// Start server listeners
for listener in listeners {
run_listener_state(
TCPServer::bind(&listener.socket)?,
listener.layers,
Self::on_listener_client,
Arc::clone(state),
);
}
Ok(())
}
pub fn run_node(
parent: ConnectionConfig,
listeners: Vec<ConnectionConfig>,
) -> Result<(), Error> {
let mut parent = build_client(TCPClient::connect(&parent.socket)?, parent.layers)?;
let state = Arc::new(Mutex::new(Self {
// parent: parent_clone,
clients: Vec::new(),
}));
Self::run_listeners(&state, listeners)?;
while parent.is_alive() {
match read(&mut parent) {
Ok(packet) => match packet {
Packets::GetRoutes => write(
&mut parent,
Packets::UpdateRoutes(state.lock().unwrap().get_routes()),
)?,
_ => {}
},
Err(e) => {
error!("Error: {}", e)
}
}
}
Ok(())
}
pub fn run_master(
server: ConnectionConfig,
listeners: Vec<ConnectionConfig>,
) -> Result<(), Error> {
// let mut parent = build_client(TCPClient::connect(&parent.socket)?, parent.layers)?;
let state = Arc::new(Mutex::new(Self {
// parent: parent_clone,
clients: Vec::new(),
}));
run_listener_state(
TCPServer::bind(&server.socket)?,
server.layers,
Self::on_command_client,
Arc::clone(&state),
);
Self::run_listeners(&state, listeners)?;
thread::sleep(Duration::MAX);
Ok(())
}
fn on_command_client(
connection: Box<dyn Connection + Send + 'static>,
state: Arc<Mutex<Node>>,
) {
thread::spawn(move || {
let mut connection = connection;
loop {
match read(&mut connection) {
Ok(packet) => {
let result = match packet {
Packets::GetConnections => write(
&mut connection,
Packets::UpdateConnections(state.lock().unwrap().get_clients()),
),
Packets::GetRoutes => write(
&mut connection,
Packets::UpdateRoutes(state.lock().unwrap().get_routes()),
),
_ => {
error!("Unsupported packet: {:?}", packet);
Ok(())
}
};
if let Err(e) = result {
error!("Got error: {}", e);
}
}
Err(e) => {
if !connection.is_alive() {
warn!("Connection {} disconnected!", connection.get_info());
break;
} else {
error!("Got error: {}", e);
}
}
}
}
});
}
fn on_listener_client(
connection: Box<dyn Connection + Send + 'static>,
state: Arc<Mutex<Node>>,
) {
thread::spawn(move || {
let mut connection = connection;
let mut s = state.lock().unwrap();
let index = s.clients.len();
let uuid = Uuid::new_v4().to_string(); //TODO: Calling an OS RNG can pose a problem for security;
s.clients.push(Client {
uuid: uuid.clone(),
connection: connection.try_clone().unwrap(),
route: vec![uuid],
});
write(
&mut connection,
Packets::OnClientConnect {
id: s.clients.last().unwrap().uuid.clone(),
route: s.clients.last().unwrap().route.clone(),
},
)
.unwrap();
std::mem::drop(s);
// let is_root = s.parent.is_none();
loop {
match read(&mut connection) {
Ok(packet) => {
let result = match packet {
Packets::GetConnections => write(
&mut connection,
Packets::UpdateConnections(state.lock().unwrap().get_clients()),
),
Packets::GetRoutes => write(
&mut connection,
Packets::UpdateRoutes(state.lock().unwrap().get_routes()),
),
Packets::OnClientConnect { id, route } => Ok(()),
_ => {
error!("Unsupported packet: {:?}", packet);
Ok(())
}
};
if let Err(e) = result {
error!("Got error: {}", e);
}
}
Err(e) => {
if !connection.is_alive() {
(&mut state.lock().unwrap()).clients.remove(index);
warn!("Connection {} Disconnected!", connection.get_info());
break;
}
error!("Got error: {}", e);
}
}
}
});
}
fn get_clients(&self) -> Vec<String> {
self.clients
.iter()
.map(|c| format!("Client {}", c.get_info()))
.collect()
}
fn get_routes(&mut self) -> Vec<String> {
let mut routes = Vec::new();
for client in &mut self.clients {
let prefix = client.connection.get_info();
routes.push(prefix.clone());
if let Err(e) = write(&mut client.connection, Packets::GetRoutes) {
error!("Failed to send packet: {}", e);
}
if let Ok(Packets::UpdateRoutes(new_routes)) = read(&mut client.connection) {
routes.append(
new_routes
.iter()
.map(|c| format!("{} -> {}", prefix, c))
.collect::<Vec<String>>()
.as_mut(),
);
}
}
routes
// self.clients
// .iter()
// .map(|c| format!("Client {}", c.get_info()))
// .collect()
}
}
+31
View File
@@ -0,0 +1,31 @@
use serde::{Deserialize, Serialize};
use crate::Error;
#[derive(Debug, Serialize, Deserialize)]
pub enum Packets {
GetConnections,
UpdateConnections(Vec<String>),
GetRoutes,
UpdateRoutes(Vec<String>),
OnClientConnect { id: String, route: Vec<String> },
OnClientDisconnect { id: String },
Error(PacketError),
}
#[derive(Debug, Serialize, Deserialize)]
pub enum PacketError {
UnsupportedType,
}
impl Packets {
pub fn encode(&self) -> Result<String, Error> {
Ok(serde_json::to_string(self)?)
}
pub fn decode(string: &str) -> Result<Self, Error> {
Ok(serde_json::from_str::<Self>(string)?)
}
}
+11 -10
View File
@@ -3,13 +3,12 @@ use crate::{
networkers::{Connection, ProtocolLayer},
};
use base64::{Engine as _, engine::general_purpose};
use serde::{Deserialize, Serialize};
pub struct Base64Layer<C: Connection> {
inner: C,
pub struct Base64Layer {
inner: Box<dyn Connection>,
}
impl<C: Connection> Connection for Base64Layer<C> {
impl Connection for Base64Layer {
fn get_info(&self) -> String {
format!("b64->{}", self.inner.get_info())
}
@@ -29,16 +28,18 @@ impl<C: Connection> Connection for Base64Layer<C> {
}
fn write(&mut self, data: &str) -> Result<(), Error> {
info!("Bsae");
self.inner.write(&general_purpose::STANDARD.encode(data))
}
self.inner.write(&general_purpose::STANDARD.encode(data))?;
Ok(())
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, Error> {
Ok(Box::new(Self {
inner: self.inner.try_clone()?,
}))
}
}
impl<C: Connection> ProtocolLayer<C> for Base64Layer<C> {
fn new(inner: C) -> Result<Self, Error> {
impl ProtocolLayer for Base64Layer {
fn new(inner: Box<dyn Connection>) -> Result<Self, Error> {
Ok(Base64Layer { inner })
}
}
+9 -2
View File
@@ -4,7 +4,7 @@ use crate::{
networkers::{Connection, ProtocolLayer},
};
impl Connection for Box<dyn Connection + Send> {
impl Connection for Box<dyn Connection + Send + Sync> {
fn get_info(&self) -> String {
(**self).get_info()
}
@@ -20,9 +20,16 @@ impl Connection for Box<dyn Connection + Send> {
fn write(&mut self, data: &str) -> Result<(), Error> {
(**self).write(data)
}
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, Error> {
Ok(Box::new((**self).try_clone()?))
}
}
pub fn build_client<C>(base_conn: C, layers: Vec<LayerConfig>) -> Result<Box<dyn Connection>, Error>
pub fn build_client<C>(
base_conn: C,
layers: Vec<LayerConfig>,
) -> Result<Box<dyn Connection + Send>, Error>
where
C: Connection + 'static,
{
+26 -27
View File
@@ -1,17 +1,19 @@
use crate::{
layers::Base64Layer,
networkers::{Connection, ProtocolLayer},
use std::sync::{
Arc,
atomic::{AtomicBool, Ordering},
};
use crate::networkers::{Connection, ProtocolLayer};
type Error = Box<dyn std::error::Error>;
// 4-Way Handshake Layer
pub struct HandshakeLayer<C: Connection> {
inner: C,
finished_handshake: bool,
pub struct HandshakeLayer {
inner: Box<dyn Connection>,
finished_handshake: Arc<AtomicBool>,
}
impl<C: Connection> Connection for HandshakeLayer<C> {
impl Connection for HandshakeLayer {
fn get_info(&self) -> String {
format!("handshake->{}", self.inner.get_info())
}
@@ -21,83 +23,80 @@ impl<C: Connection> Connection for HandshakeLayer<C> {
}
fn read(&mut self) -> Result<String, Error> {
if !self.finished_handshake {
if !self.finished_handshake.load(Ordering::Relaxed) {
return Err("NotComplete".into());
}
self.inner.read()
}
fn write(&mut self, data: &str) -> Result<(), Error> {
if !self.finished_handshake {
if !self.finished_handshake.load(Ordering::Relaxed) {
return Err("NotComplete".into());
}
self.inner.write(data)
}
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, crate::Error> {
Ok(Box::new(Self {
inner: self.inner.try_clone()?,
finished_handshake: Arc::clone(&self.finished_handshake.clone()),
}))
}
}
impl<C: Connection + 'static> ProtocolLayer<C> for HandshakeLayer<C> {
fn new(inner: C) -> Result<Self, Error> {
impl ProtocolLayer for HandshakeLayer {
fn new(inner: Box<dyn Connection>) -> Result<Self, Error> {
Ok(HandshakeLayer {
inner,
finished_handshake: false,
finished_handshake: Arc::new(AtomicBool::new(false)),
})
}
fn initialize_client(&mut self) -> Result<(), Error> {
println!("Starting client handshake...");
// Step 1: Client sends SYN
self.inner.write("SYN")?;
println!("Client: Sent SYN");
// Step 2: Client receives SYN-ACK
let response = self.inner.read()?;
if response != "SYN-ACK" {
return Err(format!("Expected SYN-ACK, got: {}", response).into());
}
println!("Client: Received SYN-ACK");
// Step 3: Client sends ACK
self.inner.write("ACK")?;
println!("Client: Sent ACK");
// Step 4: Client receives FIN (final confirmation)
let response = self.inner.read()?;
if response != "FIN" {
return Err(format!("Expected FIN, got: {}", response).into());
}
println!("Client: Received FIN - Handshake complete!");
self.finished_handshake = true;
info!("Handshake complete!");
self.finished_handshake.swap(true, Ordering::Relaxed);
Ok(())
}
fn initialize_server(&mut self) -> Result<(), Error> {
println!("Starting server handshake...");
// Step 1: Server receives SYN
let request = self.inner.read()?;
if request != "SYN" {
return Err(format!("Expected SYN, got: {}", request).into());
}
println!("Server: Received SYN");
// Step 2: Server sends SYN-ACK
self.inner.write("SYN-ACK")?;
println!("Server: Sent SYN-ACK");
// Step 3: Server receives ACK
let response = self.inner.read()?;
if response != "ACK" {
return Err(format!("Expected ACK, got: {}", response).into());
}
println!("Server: Received ACK");
// Step 4: Server sends FIN (final confirmation)
self.inner.write("FIN")?;
println!("Server: Sent FIN - Handshake complete!");
info!("Handshake complete!");
self.finished_handshake = true;
self.finished_handshake.swap(true, Ordering::Relaxed);
Ok(())
}
}
+6 -2
View File
@@ -1,11 +1,15 @@
use serde::Deserialize;
use serde::Serialize;
#[derive(Serialize, Deserialize, Debug)]
pub enum LayerConfig {
Base64,
Handshake,
}
pub mod base64;
mod base64;
mod builder;
pub mod handshake;
mod handshake;
pub use base64::Base64Layer;
pub use handshake::HandshakeLayer;
+1
View File
@@ -13,3 +13,4 @@ pub use traits::ProtocolLayer;
pub use traits::ServerTrait;
pub use server::run_listener;
pub use server::run_listener_state;
+46 -49
View File
@@ -1,54 +1,48 @@
use std::sync::Arc;
use std::thread;
use std::{sync::Arc, thread};
use crate::{
layers::{LayerConfig, create_server_builder},
networkers::{Connection, ServerTrait},
};
// Helper macros for building layered connections
macro_rules! build_layered_connection {
($base:expr) => {
$base
};
($base:expr, $layer:ty) => {
<$layer>::new($base)?
};
($base:expr, $layer:ty, $($layers:ty),+) => {
build_layered_connection!(<$layer>::new($base)?, $($layers),+)
};
}
pub fn run_listener_state<S, C, R, A>(server: S, on_connect_callback: R, state: Arc<A>)
#[allow(dead_code)]
pub fn run_listener_state<S, C, R, A>(
server: S,
layers: Vec<LayerConfig>,
on_connect_callback: R,
state: Arc<A>,
)
/*-> Arc<Mutex<Vec<C>>>*/
where
S: ServerTrait<C> + Sync + Send + 'static,
C: Connection + 'static,
R: Fn(C, Arc<A>) + Sync + Send + 'static,
R: Fn(Box<dyn Connection + Send + 'static>, Arc<A>) + Sync + Send + 'static,
A: Sync + Send + 'static,
{
info!("Started listener {}", server.get_info());
// let clients: Arc<Mutex<Vec<C>>> = Arc::new(Mutex::new(Vec::new()));
// let clients_clone = Arc::clone(&clients);
thread::spawn(move || {
let layer_builder = create_server_builder::<C>(layers).unwrap();
info!("Started listener {}", server.get_info());
loop {
match server.accept() {
Ok(conn) => match layer_builder(conn) {
Ok(conn) => {
info!("New connection ({})", conn.get_info());
on_connect_callback(conn, Arc::clone(&state));
}
Err(e) => {
error!("Failed to create layers: {:?}", e);
}
},
loop {
match server.accept() {
Ok(conn) => {
info!("New connection ({})", conn.get_info());
on_connect_callback(conn, Arc::clone(&state));
// OnConnectCallback::on_connect(&mut on_connect_callback, conn);
// let mut clients_lock = clients_clone.lock().unwrap();
// clients_lock.push(conn);
}
Err(e) => {
error!("Failed to accept connection: {:?}", e);
Err(e) => {
error!("Failed to accept connection: {:?}", e);
}
}
}
}
});
}
#[allow(dead_code)]
pub fn run_listener<S, C, R>(server: S, layers: Vec<LayerConfig>, on_connect_callback: R)
/*-> Arc<Mutex<Vec<C>>>*/
where
@@ -56,26 +50,29 @@ where
C: Connection + 'static,
R: Fn(Box<dyn Connection + Send + 'static>) + Sync + Send + 'static,
{
let layer_builder = create_server_builder::<C>(layers).unwrap();
info!("Started listener {}", server.get_info());
// let clients: Arc<Mutex<Vec<C>>> = Arc::new(Mutex::new(Vec::new()));
// let clients_clone = Arc::clone(&clients);
loop {
match server.accept() {
Ok(conn) => match layer_builder(conn) {
Ok(conn) => {
info!("New connection ({})", conn.get_info());
on_connect_callback(conn);
}
thread::spawn(move || {
let layer_builder = create_server_builder::<C>(layers).unwrap();
info!("Started listener {}", server.get_info());
loop {
match server.accept() {
Ok(conn) => match layer_builder(conn) {
Ok(conn) => {
let con_info = conn.get_info();
info!("New connection ({})", con_info);
on_connect_callback(conn);
}
Err(e) => {
error!("Failed to create layers: {:?}", e);
}
},
Err(e) => {
error!("Failed to create layers: {:?}", e);
error!("Failed to accept connection: {:?}", e);
}
},
Err(e) => {
error!("Failed to accept connection: {:?}", e);
}
}
}
});
}
+21 -66
View File
@@ -1,6 +1,10 @@
use std::{
io::{self, BufRead, BufReader, Write},
io::{BufRead, BufReader, Write},
net::{SocketAddr, TcpListener, TcpStream},
sync::{
Arc,
atomic::{AtomicBool, Ordering},
},
};
use crate::{
@@ -11,7 +15,7 @@ use crate::{
pub struct TCPConnection {
stream: TcpStream,
reader: BufReader<TcpStream>,
is_alive: bool,
is_alive: Arc<AtomicBool>,
}
impl Connection for TCPConnection {
@@ -27,7 +31,7 @@ impl Connection for TCPConnection {
}
fn is_alive(&self) -> bool {
self.is_alive
self.is_alive.load(Ordering::Relaxed)
}
fn read(&mut self) -> Result<String, Error> {
@@ -36,79 +40,30 @@ impl Connection for TCPConnection {
// Stream sends a null buffer if it is disconnected
if n == 0 {
self.is_alive = false;
self.is_alive.swap(false, Ordering::Relaxed);
}
// println!("Recieved: {}", line.trim_end().to_string());
Ok(line.trim_end().to_string())
}
fn write(&mut self, data: &str) -> Result<(), Error> {
info!("Sent: {}", data);
// println!("Recsent: {}", data);
writeln!(self.stream, "{}", data)?;
self.stream.flush()?;
Ok(())
}
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, Error> {
Ok(Box::new(Self {
stream: self.stream.try_clone()?,
reader: BufReader::new(self.stream.try_clone()?),
is_alive: Arc::clone(&self.is_alive),
}))
}
}
// impl AsyncConnection<TCPConnection> for TCPConnection {
// type Error = io::Error;
// fn as_async<T: Serialize + DeserializeOwned + Send + 'static>(
// connection: TCPConnection,
// ) -> (Sender<T>, Receiver<T>) {
// let (send_tx, send_rx) = crossbeam_channel::unbounded::<T>();
// let (recv_tx, recv_rx) = crossbeam_channel::unbounded::<T>();
// thread::spawn(move || {
// let mut reader = connection.reader;
// let mut read = || -> Result<String, Self::Error> {
// let mut line = String::new();
// let _ = reader.read_line(&mut line)?;
// Ok(line.trim_end().to_string())
// };
// loop {
// if let Ok(data) = read() {
// if data.is_empty() {
// break;
// }
// info!("Got {}", data);
// if let Ok(decoded) = serde_json::from_str::<T>(&data) {
// if let Err(e) = send_tx.send(decoded) {
// error!("Got error: {}", e);
// }
// }
// }
// }
// });
// thread::spawn(move || {
// let mut stream = connection.stream;
// let mut write = |data: String| -> Result<(), Self::Error> {
// writeln!(stream, "{}", data)?;
// stream.flush()?;
// Ok(())
// };
// loop {
// if let Ok(data) = recv_rx.recv() {
// if let Ok(encoded) = serde_json::to_string(&data) {
// info!("Write {}", encoded);
// if let Err(e) = write(encoded) {
// error!("Got error: {}", e);
// }
// }
// }
// }
// });
// (recv_tx, send_rx)
// }
// }
pub struct TCPServer {
listener: TcpListener,
}
@@ -131,7 +86,7 @@ impl ServerTrait<TCPConnection> for TCPServer {
Ok(TCPConnection {
stream,
reader,
is_alive: true,
is_alive: Arc::new(AtomicBool::new(true)),
})
}
@@ -150,7 +105,7 @@ impl ClientTrait<TCPConnection> for TCPClient {
let conn = TCPConnection {
stream,
reader,
is_alive: true,
is_alive: Arc::new(AtomicBool::new(true)),
};
Ok(conn)
}
+6 -6
View File
@@ -1,21 +1,21 @@
use std::net::SocketAddr;
use std::ops::Deref;
use std::ops::DerefMut;
use crate::Error;
// This is the lowset-level data transmission type
pub trait Connection: Send {
// This is the data transmission type
pub trait Connection: Send + Sync {
fn get_info(&self) -> String;
fn is_alive(&self) -> bool;
fn read(&mut self) -> Result<String, Error>;
fn write(&mut self, data: &str) -> Result<(), Error>;
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, Error>;
}
// Trait for protocol layers that can be initialized
pub trait ProtocolLayer<C: Connection>: Connection {
fn new(inner: C) -> Result<Self, Error>
pub trait ProtocolLayer: Connection {
fn new(inner: Box<dyn Connection>) -> Result<Self, Error>
where
Self: Sized;
fn initialize_client(&mut self) -> Result<(), Error> {