Skip to content

Instantly share code, notes, and snippets.

@icsboyx
Created January 10, 2024 15:54
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save icsboyx/527f0352b0023b7b7101c8fe2b3c94ca to your computer and use it in GitHub Desktop.
Save icsboyx/527f0352b0023b7b7101c8fe2b3c94ca to your computer and use it in GitHub Desktop.
#![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