gitdataai/lib/socketio/socket.rs

187 lines
4.4 KiB
Rust

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<Session>,
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<Session>,
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<Session>, namespace: String, id: u64) -> Self {
Self {
session,
namespace,
id,
}
}
pub async fn send<T: Serialize>(&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<uuid::Uuid> {
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<String> {
self.session
.namespaces
.lock()
.await
.get(&self.namespace)
.map(|state| state.rooms.clone())
.unwrap_or_default()
}
pub async fn auth(&self) -> Option<Value> {
self.session
.namespaces
.lock()
.await
.get(&self.namespace)
.and_then(|state| state.auth.clone())
}
pub async fn emit<T: Serialize>(&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<T: Serialize>(
&self,
event: &str,
data: T,
) -> Result<Vec<Value>> {
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<Value>,
binary: Vec<Vec<u8>>,
) -> Result<()> {
self.io
.emit_binary_to_sid(
&self.namespace,
&self.session.engine_id,
event,
args,
binary,
)
.await
}
pub async fn broadcast<T: Serialize>(
&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<String>) -> 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
}
}