use super::protocol::{WsInbound, WsOutbound};
use std::process::Child;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use tokio::sync::{broadcast, mpsc};
pub struct WsBridge {
inbound_rx: mpsc::Receiver<WsInbound>,
outbound_tx: broadcast::Sender<WsOutbound>,
pub client_connected: Arc<AtomicBool>,
_runtime: tokio::runtime::Runtime,
#[cfg(target_os = "macos")]
_caffeinate: Option<Child>,
}
impl WsBridge {
pub fn new(
runtime: tokio::runtime::Runtime,
) -> (Self, mpsc::Sender<WsInbound>, broadcast::Sender<WsOutbound>) {
let (inbound_tx, inbound_rx) = mpsc::channel::<WsInbound>(256);
let (outbound_tx, _) = broadcast::channel::<WsOutbound>(256);
let client_connected = Arc::new(AtomicBool::new(false));
#[cfg(target_os = "macos")]
let caffeinate = std::process::Command::new("caffeinate")
.arg("-s")
.spawn()
.ok();
let bridge = Self {
inbound_rx,
outbound_tx: outbound_tx.clone(),
client_connected,
_runtime: runtime,
#[cfg(target_os = "macos")]
_caffeinate: caffeinate,
};
(bridge, inbound_tx, outbound_tx)
}
pub fn try_recv(&mut self) -> Option<WsInbound> {
self.inbound_rx.try_recv().ok()
}
pub fn broadcast(&self, msg: WsOutbound) {
let _ = self.outbound_tx.send(msg);
}
pub fn has_client(&self) -> bool {
self.client_connected.load(Ordering::Relaxed)
}
pub fn block_on<F: std::future::Future>(&self, future: F) -> F::Output {
self._runtime.block_on(future)
}
pub fn spawn<F>(&self, future: F)
where
F: std::future::Future<Output = ()> + Send + 'static,
{
self._runtime.spawn(future);
}
}
impl Drop for WsBridge {
fn drop(&mut self) {
#[cfg(target_os = "macos")]
if let Some(ref mut child) = self._caffeinate {
let _ = child.kill();
}
}
}