use std::net::{IpAddr, SocketAddr};
use std::sync::Arc;
use std::time::Duration;
use async_trait::async_trait;
use bytes::Bytes;
use parking_lot::Mutex;
use tokio::sync::{broadcast, mpsc};
use crate::error::SteamError;
use super::disconnected_event_args::DisconnectedEventArgs;
use super::net_msg_event_args::NetMsgEventArgs;
use super::protocol_type::ProtocolTypes;
pub const CONNECTION_EVENT_CAPACITY: usize = 64;
#[async_trait]
pub trait IConnection: Send + Sync {
fn current_end_point(&self) -> Option<SocketAddr>;
fn protocol_types(&self) -> ProtocolTypes;
async fn connect(&self, end_point: SocketAddr, timeout: Duration) -> Result<(), SteamError>;
async fn disconnect(&self, user_initiated: bool);
async fn send(&self, data: Bytes) -> Result<(), SteamError>;
fn local_ip(&self) -> Option<IpAddr>;
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConnectionEvent {
NetMsgReceived(NetMsgEventArgs),
Connected,
Disconnected(DisconnectedEventArgs),
}
pub trait ConnectionEvents: Send + Sync {
fn events(&self) -> mpsc::UnboundedReceiver<ConnectionEvent>;
fn net_msg_received(&self) -> broadcast::Receiver<NetMsgEventArgs>;
fn connected(&self) -> broadcast::Receiver<()>;
fn disconnected(&self) -> broadcast::Receiver<DisconnectedEventArgs>;
}
pub trait Connection: IConnection + ConnectionEvents {}
impl<T> Connection for T where T: IConnection + ConnectionEvents + ?Sized {}
#[derive(Clone, Debug)]
pub struct ConnectionEventSenders {
net_msg_received: broadcast::Sender<NetMsgEventArgs>,
connected: broadcast::Sender<()>,
disconnected: broadcast::Sender<DisconnectedEventArgs>,
subscribers: Arc<Mutex<Vec<mpsc::UnboundedSender<ConnectionEvent>>>>,
}
impl ConnectionEventSenders {
pub fn new(capacity: usize) -> Self {
let (net_msg_received, _) = broadcast::channel(capacity);
let (connected, _) = broadcast::channel(capacity);
let (disconnected, _) = broadcast::channel(capacity);
Self {
net_msg_received,
connected,
disconnected,
subscribers: Arc::new(Mutex::new(Vec::new())),
}
}
pub fn with_default_capacity() -> Self {
Self::new(CONNECTION_EVENT_CAPACITY)
}
pub fn subscribe_events(&self) -> mpsc::UnboundedReceiver<ConnectionEvent> {
let (sender, receiver) = mpsc::unbounded_channel();
self.subscribers.lock().push(sender);
receiver
}
pub fn event_subscriber_count(&self) -> usize {
let mut subscribers = self.subscribers.lock();
subscribers.retain(|subscriber| !subscriber.is_closed());
subscribers.len()
}
pub fn subscribe_net_msg_received(&self) -> broadcast::Receiver<NetMsgEventArgs> {
self.net_msg_received.subscribe()
}
pub fn subscribe_connected(&self) -> broadcast::Receiver<()> {
self.connected.subscribe()
}
pub fn subscribe_disconnected(&self) -> broadcast::Receiver<DisconnectedEventArgs> {
self.disconnected.subscribe()
}
pub fn emit_net_msg_received(&self, args: NetMsgEventArgs) {
let mut subscribers = self.subscribers.lock();
if self.net_msg_received.receiver_count() > 0 {
let _ = self.net_msg_received.send(args.clone());
}
publish(&mut subscribers, ConnectionEvent::NetMsgReceived(args));
}
pub fn emit_connected(&self) {
let mut subscribers = self.subscribers.lock();
let _ = self.connected.send(());
publish(&mut subscribers, ConnectionEvent::Connected);
}
pub fn emit_disconnected(&self, args: DisconnectedEventArgs) {
let mut subscribers = self.subscribers.lock();
let _ = self.disconnected.send(args);
publish(&mut subscribers, ConnectionEvent::Disconnected(args));
}
}
fn publish(subscribers: &mut Vec<mpsc::UnboundedSender<ConnectionEvent>>, event: ConnectionEvent) {
if let [only] = subscribers.as_slice() {
if only.send(event).is_err() {
subscribers.clear();
}
return;
}
subscribers.retain(|subscriber| subscriber.send(event.clone()).is_ok());
}
impl Default for ConnectionEventSenders {
fn default() -> Self {
Self::with_default_capacity()
}
}