Start working on structure

This commit is contained in:
Michael Mikovsky
2025-06-04 22:52:20 -06:00
parent 1f1cb6952f
commit 8adfc68854
19 changed files with 461 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
use crate::layers::Layer;
use base64;
#[derive(Default)]
pub struct Base64;
impl Layer for Base64 {
fn encode(&mut self, data: &[u8]) -> Vec<u8> {
#[allow(deprecated)]
base64::encode(str::from_utf8(data).unwrap()).into_bytes()
}
fn decode(&mut self, data: &[u8]) -> Vec<u8> {
#[allow(deprecated)]
base64::decode(str::from_utf8(data).unwrap()).unwrap()
}
}
+8
View File
@@ -0,0 +1,8 @@
pub trait Layer {
fn encode(&mut self, data: &[u8]) -> Vec<u8>;
fn decode(&mut self, data: &[u8]) -> Vec<u8>;
}
pub mod base64;
pub use base64::Base64;
+5
View File
@@ -0,0 +1,5 @@
pub mod layers;
pub mod listeners;
pub mod networkers;
pub mod packets;
pub mod payload;
+9
View File
@@ -0,0 +1,9 @@
pub struct Client<C> {
pub stream: C,
}
impl<C> Client<C> {
pub fn new(stream: C) -> Self {
Self { stream }
}
}
+4
View File
@@ -0,0 +1,4 @@
mod client;
mod server;
pub use server::Listener;
+49
View File
@@ -0,0 +1,49 @@
use log::{info, trace, warn};
use std::{
io::{self, Write},
sync::{Arc, Mutex},
thread,
};
use crate::{
listeners::client::{self, Client},
networkers::{Connection, ServerTrait},
packets::Packet,
};
pub struct Listener<S, C> {
pub server: Arc<Mutex<S>>,
pub clients: Arc<Mutex<Vec<Client<C>>>>,
}
impl<S, C> Listener<S, C> {
pub fn new(server: S) -> Self {
Self {
server: Arc::new(Mutex::new(server)),
clients: Arc::new(Mutex::new(Vec::new())),
}
}
pub fn run_listener(&mut self) -> Result<(), Box<dyn std::error::Error>>
where
S: ServerTrait<C>,
C: Connection + 'static,
S::Error: std::error::Error + 'static,
C::Error: std::error::Error + 'static,
{
loop {
let mut conn_lock = self.server.lock().unwrap();
match conn_lock.accept() {
Ok(conn) => {
let mut clients_lock = self.clients.lock().unwrap();
clients_lock.push(Client::new(conn));
}
Err(e) => {
eprintln!("Failed to accept connection: {:?}", e);
}
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
/// This is the lowset-level data transmission type
pub trait Connection: Send + Sync {
type Error: std::fmt::Debug;
fn read(&mut self) -> Result<String, Self::Error>;
fn write(&mut self, data: &str) -> Result<(), Self::Error>;
}
pub trait ServerTrait<C: Connection> {
type Error: std::fmt::Debug;
fn accept(&mut self) -> Result<C, Self::Error>;
fn bind(address: &str) -> Result<Self, Self::Error>
where
Self: Sized;
}
pub trait ClientTrait<C: Connection> {
type Error: std::fmt::Debug;
fn connect(address: &str) -> Result<C, Self::Error>;
}
mod tcp;
pub use tcp::TCPClient;
pub use tcp::TCPConnection;
pub use tcp::TCPServer;
+57
View File
@@ -0,0 +1,57 @@
use std::{
io::{self, BufRead, BufReader, Write},
net::{TcpListener, TcpStream},
};
use crate::networkers::{ClientTrait, Connection, ServerTrait};
pub struct TCPConnection {
stream: TcpStream,
reader: BufReader<TcpStream>,
}
impl Connection for TCPConnection {
type Error = io::Error;
fn read(&mut self) -> Result<String, Self::Error> {
let mut line = String::new();
self.reader.read_line(&mut line)?;
Ok(line.trim_end().to_string())
}
fn write(&mut self, data: &str) -> Result<(), Self::Error> {
writeln!(self.stream, "{}", data)?;
self.stream.flush()
}
}
pub struct TCPServer {
listener: TcpListener,
}
impl ServerTrait<TCPConnection> for TCPServer {
type Error = io::Error;
fn accept(&mut self) -> Result<TCPConnection, Self::Error> {
let (stream, _) = self.listener.accept()?;
let reader = BufReader::new(stream.try_clone()?);
Ok(TCPConnection { stream, reader })
}
fn bind(address: &str) -> Result<Self, Self::Error> {
let listener = TcpListener::bind(address)?;
Ok(Self { listener })
}
}
pub struct TCPClient;
impl ClientTrait<TCPConnection> for TCPClient {
type Error = io::Error;
fn connect(address: &str) -> Result<TCPConnection, Self::Error> {
let stream = TcpStream::connect(address)?;
let reader = BufReader::new(stream.try_clone()?);
Ok(TCPConnection { stream, reader })
}
}
+9
View File
@@ -0,0 +1,9 @@
use serde::{Deserialize, Serialize};
mod sysinfo;
#[derive(Serialize, Deserialize, Debug)]
pub enum Packet {
Heartbeat,
Sysinfo(sysinfo::Sysinfo),
}
+6
View File
@@ -0,0 +1,6 @@
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug)]
pub struct Sysinfo {
hostname: String,
}
+80
View File
@@ -0,0 +1,80 @@
use std::{
sync::{Arc, Mutex},
thread,
time::Duration,
};
use crate::{
networkers::{ClientTrait, Connection},
packets::Packet,
};
// Generic client function
pub fn run_client<C, Cl>(address: &str) -> Result<(), Box<dyn std::error::Error>>
where
Cl: ClientTrait<C>,
C: Connection + 'static,
Cl::Error: std::error::Error + 'static,
C::Error: std::error::Error + 'static,
{
let recv_conn = Arc::new(Mutex::new(Cl::connect(address)?));
let transmit_vec: Arc<Mutex<Vec<Packet>>> = Arc::new(Mutex::new(Vec::new()));
let transmit_conn = Arc::clone(&recv_conn);
let transmit_vec_clone = Arc::clone(&transmit_vec);
thread::spawn(move || {
loop {
let mut transmit_vec_lock = transmit_vec.lock().unwrap();
if transmit_vec_lock.len() > 0 {
let mut conn_lock = recv_conn.lock().unwrap();
if let Ok(json) = serde_json::to_string(&transmit_vec_lock.pop().unwrap()) {
conn_lock.write(&json).expect("Failed to send packet!");
}
} else {
thread::sleep(Duration::from_millis(10));
}
}
});
loop {
let mut conn_lock = transmit_conn.lock().unwrap();
let data = conn_lock.read();
drop(conn_lock);
match data {
Ok(data_json) => {
if data_json.is_empty() {
continue;
}
let packet = serde_json::from_str::<Packet>(data_json.as_str());
println!("{:?}", packet);
}
Err(e) => {
eprintln!("Error reading, {}", e);
}
}
}
// loop {
// let mut input = String::new();
// stdin.read_line(&mut input)?;
// let input = input.trim();
// if input == "quit" {
// conn.write(input)?;
// break;
// }
// if !input.is_empty() {
// conn.write(input)?;
// match conn.read() {
// Ok(response) => println!("Server: {}", response),
// Err(e) => {
// eprintln!("Failed to read response: {:?}", e);
// break;
// }
// }
// }
// }
}