use worker::{Error, Result as WorkerResult, State, WebSocket};
pub fn do_connect(state: &State, server: &WebSocket, tags: &[&str]) -> WorkerResult<()> {
if tags.is_empty() {
state.accept_web_socket(server);
} else {
state.accept_websocket_with_tags(server, tags);
}
Ok(())
}
pub fn do_broadcast(state: &State, bytes: &[u8]) {
for ws in state.get_websockets() {
let _ = ws.send_with_bytes(bytes.to_vec());
}
}
pub fn do_broadcast_tagged(state: &State, tag: &str, bytes: &[u8]) {
for ws in state.get_websockets_with_tag(tag) {
let _ = ws.send_with_bytes(bytes.to_vec());
}
}
pub fn do_broadcast_text(state: &State, text: &str) {
for ws in state.get_websockets() {
let _ = ws.send_with_str(text);
}
}
#[must_use]
pub fn connected_count(state: &State, tag: Option<&str>) -> usize {
match tag {
Some(t) => state.get_websockets_with_tag(t).len(),
None => state.get_websockets().len(),
}
}
pub trait WebSocketHub {
fn tag(&self) -> &'static str {
"user"
}
fn ping_interval_secs(&self) -> u32 {
15
}
fn on_alarm(&self, _state: &State) -> WorkerResult<()> {
Ok(())
}
}
#[derive(Default)]
pub struct WebSocketRegistry {
sockets: Vec<(String, WebSocket)>,
}
impl WebSocketRegistry {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn register(&mut self, client_id: String, ws: WebSocket) {
self.sockets.push((client_id, ws));
}
pub fn unregister(&mut self, client_id: &str) {
self.sockets.retain(|(id, ws)| {
if id == client_id {
let _ = ws.close(None::<u16>, None::<&str>);
false
} else {
true
}
});
}
pub fn send_to(&self, client_id: &str, bytes: &[u8]) {
for (id, ws) in &self.sockets {
if id == client_id {
let _ = ws.send_with_bytes(bytes.to_vec());
break;
}
}
}
pub fn broadcast(&self, bytes: &[u8]) {
for (_, ws) in &self.sockets {
let _ = ws.send_with_bytes(bytes.to_vec());
}
}
#[must_use]
pub fn len(&self) -> usize {
self.sockets.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.sockets.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn registry_register_unregister() {
let mut reg = WebSocketRegistry::new();
assert!(reg.is_empty());
assert_eq!(reg.len(), 0);
reg.sockets.push(("dev1".into(), unsafe {
std::mem::zeroed()
}));
assert_eq!(reg.len(), 1);
reg.unregister("dev1");
assert!(reg.is_empty());
}
}