Created
January 10, 2024 15:54
-
-
Save icsboyx/527f0352b0023b7b7101c8fe2b3c94ca to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![allow(dead_code)] | |
use anyhow::*; | |
use std::{ | |
collections::VecDeque, | |
net::TcpStream, | |
sync::{Arc, Mutex, RwLock}, | |
}; | |
#[derive(Debug, Clone)] | |
pub enum SvrCmd { | |
Nick(String), | |
Msg(Message), | |
Quit, | |
New, | |
} | |
impl Clone for Channel { | |
fn clone(&self) -> Self { | |
Channel { | |
name: self.name.clone(), | |
subscribers: self.subscribers.clone(), | |
} | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct ServerEngine { | |
pub clients: Clients, | |
pub channels: Channels, | |
} | |
impl ServerEngine { | |
pub fn new() -> Self { | |
ServerEngine { | |
clients: Clients::new(), | |
channels: Channels::new(), | |
} | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct Channels { | |
default: Channel, | |
channels: Vec<Channel>, | |
} | |
impl Channels { | |
pub fn new() -> Self { | |
Channels { | |
default: Channel::new("default".to_string()), | |
channels: Vec::new(), | |
} | |
} | |
pub fn default(&self) -> Channel { | |
self.default.clone() | |
} | |
pub fn add(&mut self, channel: Channel) -> Result<()> { | |
self.channels.push(channel); | |
Ok(()) | |
} | |
pub fn remove(&mut self, name: String) -> Result<()> { | |
self.channels.retain(|channel| channel.name != name); | |
Ok(()) | |
} | |
pub fn get(&self, name: String) -> Option<Channel> { | |
self.channels | |
.iter() | |
.find(|channel| channel.name == name) | |
.cloned() | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct Message { | |
pub sender: Client, | |
pub msg: Vec<u8>, | |
pub channel: Channel, | |
} | |
impl Message { | |
pub fn new(sender: Client, msg: Vec<u8>, channel: Channel) -> Self { | |
Message { | |
sender, | |
msg, | |
channel, | |
} | |
} | |
pub fn get_context(&self) -> Channel { | |
self.channel.clone() | |
} | |
} | |
#[derive(Debug)] | |
pub struct Channel { | |
pub name: String, | |
subscribers: Arc<RwLock<Vec<MessageBus<Message>>>>, | |
} | |
impl Channel { | |
pub fn new(name: String) -> Self { | |
Channel { | |
name, | |
subscribers: Arc::new(RwLock::new(Vec::new())), | |
} | |
} | |
pub fn add(&mut self, client_rx: MessageBus<Message>) -> Result<()> { | |
self.subscribers.write().unwrap().push(client_rx); | |
Ok(()) | |
} | |
pub fn subscribers(&self) -> usize { | |
self.subscribers.read().unwrap().len() | |
} | |
pub fn send_message(&self, msg: Message) -> Result<()> { | |
let mut subscribers = self.subscribers.write().unwrap(); | |
println!("Sending message to {} subscribers", subscribers.len()); | |
for subscriber in subscribers.iter_mut() { | |
subscriber.push_back(msg.clone())?; | |
} | |
Ok(()) | |
} | |
pub fn subscribe(&self, client_rx: MessageBus<Message>) -> Result<()> { | |
self.subscribers.write().unwrap().push(client_rx); | |
Ok(()) | |
} | |
} | |
#[derive(Debug)] | |
pub struct ClientStream { | |
pub tcp_stream: TcpStream, | |
} | |
impl ClientStream { | |
pub fn new(tcp_stream: TcpStream) -> Self { | |
ClientStream { tcp_stream } | |
} | |
} | |
impl Clone for ClientStream { | |
fn clone(&self) -> Self { | |
let cloned_stream = self.tcp_stream.try_clone().expect("Failed to clone stream"); | |
ClientStream { | |
tcp_stream: cloned_stream, | |
} | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct MessageBus<T> { | |
queue: Arc<RwLock<VecDeque<T>>>, | |
} | |
impl<T: Clone> MessageBus<T> { | |
pub fn new() -> Self { | |
MessageBus { | |
queue: Arc::new(RwLock::new(VecDeque::new())), | |
} | |
} | |
pub fn push_back(&mut self, msg: T) -> Result<()> { | |
let mut queue = self.queue.write().unwrap(); | |
queue.push_back(msg.clone()); | |
Ok(()) | |
} | |
pub fn pop_first(&mut self) -> Option<T> { | |
let mut queue = self.queue.write().unwrap(); | |
queue.pop_front() | |
} | |
pub fn len(&self) -> usize { | |
let queue = self.queue.read().unwrap(); | |
queue.len() | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct ServiceBus { | |
queue: Arc<Mutex<VecDeque<(SvrCmd, Client)>>>, | |
} | |
impl ServiceBus { | |
pub fn new() -> Self { | |
ServiceBus { | |
queue: Arc::new(Mutex::new(VecDeque::new())), | |
} | |
} | |
pub fn push_back(&mut self, command: SvrCmd, client: Client) -> Result<()> { | |
let mut queue = self.queue.lock().unwrap(); | |
queue.push_back((command, client)); | |
Ok(()) | |
} | |
pub fn pop_first(&mut self) -> Option<(SvrCmd, Client)> { | |
let mut queue = self.queue.lock().unwrap(); | |
queue.pop_front() | |
} | |
pub fn len(&self) -> usize { | |
let queue = self.queue.lock().unwrap(); | |
queue.len() | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct Clients { | |
pub clients: Arc<Mutex<Vec<Client>>>, | |
pub service_bus: ServiceBus, | |
} | |
impl Clients { | |
pub fn new() -> Self { | |
Clients { | |
clients: Arc::new(Mutex::new(Vec::new())), | |
service_bus: ServiceBus::new(), | |
} | |
} | |
pub fn len(&self) -> usize { | |
let clients = self.clients.lock().unwrap(); | |
clients.len() | |
} | |
pub fn add(&mut self, client: Client) -> Result<()> { | |
let mut clients = self.clients.lock().unwrap(); | |
clients.push(client); | |
Ok(()) | |
} | |
pub fn remove(&mut self, id: usize) -> Result<()> { | |
let mut clients = self.clients.lock().unwrap(); | |
clients.retain(|client| client.id() != id); | |
Ok(()) | |
} | |
} | |
#[derive(Debug, Clone)] | |
pub struct Client { | |
pub id: usize, | |
pub nick: String, | |
pub channel: Channel, | |
pub stream: ClientStream, | |
pub service_bus: ServiceBus, | |
pub rx: MessageBus<Message>, | |
pub tx: MessageBus<Message>, | |
} | |
impl Client { | |
pub fn new( | |
id: usize, | |
nick: String, | |
stream: ClientStream, | |
service_bus: ServiceBus, | |
channel: Channel, | |
) -> Self { | |
let inner_self = Client { | |
id, | |
nick, | |
stream, | |
channel, | |
service_bus, | |
rx: MessageBus::new(), | |
tx: MessageBus::new(), | |
}; | |
inner_self.channel.subscribe(inner_self.rx.clone()).unwrap(); | |
inner_self | |
} | |
pub fn id(&self) -> usize { | |
self.id | |
} | |
pub fn nick(&self) -> String { | |
self.nick.clone() | |
} | |
pub fn stream(&self) -> ClientStream { | |
self.stream.clone() | |
} | |
pub fn service_bus(&self) -> ServiceBus { | |
self.service_bus.clone() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment