use std::fmt; use std::{collections::HashSet, sync::Arc}; use serde::Serialize; use serde_json::Value; use crate::{ adapter::BroadcastOptions, error::Result, packet::Packet, server::SocketIo, session::Session, }; #[derive(Clone)] pub struct Socket { pub io: SocketIo, pub session: Arc, pub namespace: String, pub sid: String, } #[derive(Clone, Debug, Eq, PartialEq)] pub enum DisconnectReason { Client, TransportClosed, PingTimeout, Server, } #[derive(Clone)] pub struct AckSender { session: Arc, namespace: String, id: u64, } impl fmt::Debug for AckSender { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("AckSender") .field("namespace", &self.namespace) .field("id", &self.id) .finish_non_exhaustive() } } impl AckSender { pub fn new(session: Arc, namespace: String, id: u64) -> Self { Self { session, namespace, id, } } pub async fn send(&self, data: T) -> Result<()> { let args = match serde_json::to_value(data)? { Value::Array(values) => values, value => vec![value], }; self.session .enqueue_socket_packet(Packet::ack(&self.namespace, self.id, args)) .await; Ok(()) } } impl Socket { pub fn id(&self) -> &str { &self.sid } pub fn namespace(&self) -> &str { &self.namespace } pub fn session_user(&self) -> Option { self.session .user .lock() .unwrap_or_else(|e| e.into_inner()) .clone() } pub fn set_user(&self, user: uuid::Uuid) { *self.session.user.lock().unwrap_or_else(|e| e.into_inner()) = Some(user); } pub async fn rooms(&self) -> HashSet { self.session .namespaces .lock() .await .get(&self.namespace) .map(|state| state.rooms.clone()) .unwrap_or_default() } pub async fn auth(&self) -> Option { self.session .namespaces .lock() .await .get(&self.namespace) .and_then(|state| state.auth.clone()) } pub async fn emit(&self, event: &str, data: T) -> Result<()> { self.io .emit_to_sid(&self.namespace, &self.session.engine_id, event, data) .await } pub async fn emit_with_ack( &self, event: &str, data: T, ) -> Result> { self.io .emit_to_sid_with_ack( &self.namespace, &self.session.engine_id, event, data, ) .await } pub async fn emit_binary( &self, event: &str, args: Vec, binary: Vec>, ) -> Result<()> { self.io .emit_binary_to_sid( &self.namespace, &self.session.engine_id, event, args, binary, ) .await } pub async fn broadcast( &self, event: &str, data: T, ) -> Result<()> { let opts = BroadcastOptions { namespace: self.namespace.clone(), skip_sid: Some(self.session.engine_id.clone()), ..BroadcastOptions::default() }; self.io.broadcast_with_opts(opts, event, data).await } pub async fn join(&self, room: impl Into) -> Result<()> { self.io .join(&self.namespace, &self.session.engine_id, room.into()) .await } pub async fn leave(&self, room: &str) -> Result<()> { self.io .leave(&self.namespace, &self.session.engine_id, room) .await } pub async fn disconnect(&self) -> Result<()> { self.session .enqueue_socket_packet(Packet::new( crate::packet::PacketType::Disconnect, &self.namespace, None, None, )) .await; self.io .disconnect_socket( &self.namespace, &self.session, DisconnectReason::Server, ) .await } }