ghost_sync/
handler.rs

1use std::net::SocketAddr;
2use uuid::Uuid;
3
4/// Optional hook trait for server lifecycle events.
5/// All methods have no-op defaults — implement only what you need.
6///
7/// # Composability
8///
9/// These hooks are the extension point for game logic. The library never
10/// interprets room metadata or makes game-specific decisions. Use the hooks
11/// to implement private rooms, max player limits, matchmaking, bans, etc.
12///
13/// # Security
14///
15/// Use [`on_connect`](ServerHandler::on_connect) to filter connections by address
16/// before they're fully accepted.
17///
18/// # Backpressure
19///
20/// When a client's write channel is full, the frame is dropped and
21/// [`on_backpressure`](ServerHandler::on_backpressure) is called. This is
22/// intentional for real-time game relay — a slow client shouldn't stall the server.
23pub trait ServerHandler: Send + Sync + 'static {
24    /// Called when a new TCP connection arrives. Return `false` to reject it.
25    /// Called before any resources are allocated for the connection.
26    fn on_connect(&self, _addr: SocketAddr) -> bool {
27        true
28    }
29
30    /// Called when a client requests to join a room.
31    ///
32    /// Return `(true, _)` to allow the join.
33    /// Return `(false, Some(reason))` to reject with a custom error message.
34    /// Return `(false, None)` to reject with the default "join rejected" message.
35    ///
36    /// Use this to implement private rooms (check password), max player limits (check client count)
37    /// or use payload_data field to validate any sort of tokens,
38    /// bans (check addr), add room_limit or any custom join logic you wish
39    fn on_join(
40        &self,
41        _client_id: Uuid,
42        _room_id: &str,
43        _addr: SocketAddr,
44        _data: &[u8],
45    ) -> (bool, Option<String>) {
46        (true, None)
47    }
48
49    /// Called when a client leaves a room (or disconnects).
50    fn on_leave(&self, _client_id: Uuid, _room_id: &str) {}
51
52    /// Called after a room is created (including via [`ServerHandle::create_room_runtime`](crate::ServerHandle::create_room)).
53    fn on_room_create(&self, _room_id: &str) {}
54
55    /// Called after a room is deleted.
56    fn on_room_delete(&self, _room_id: &str) {}
57
58    /// Called when a broadcast message is relayed.
59    /// client_id is the sender, and the message has already been relayed to all peers.
60    #[inline]
61    fn on_broadcast(&self, _client_id: Uuid, _room_id: &str, _data: &[u8]) {}
62
63    /// Called when a frame is dropped because a client's write channel is full.
64    /// The affected clients are identified by their UUIDs.
65    ///
66    /// NOTE: For auto-kicking or pausing slow clients, you need to monitor channel length via [`ServerHandle::get_client_channel_len`](crate::ServerHandle::get_client_channel_len)
67    /// or [`ServerHandle::get_room_channel_lens`](crate::ServerHandle::get_room_channel_lens) and implement your own logic in this hook.
68    /// The library does not auto-kick or pause clients on backpressure, as some games may prefer to drop frames silently.
69    #[inline]
70    fn on_backpressure(&self, _client_id: Uuid, _room_id: &str) {}
71
72    /// Called when server is shutdown via ctrl-c (shutdown signals)
73    /// Can be used as a graceful shutdown signal for any background tasks or post-shutdown cleanup or jobs
74    fn on_shutdown(&self) {}
75}
76
77/// Default no-op handler. Accepts all connections, ignores all events.
78pub struct NoopHandler;
79
80impl ServerHandler for NoopHandler {}