1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//! # ws-kit
//!
//! Generic authenticated typed WebSocket toolkit.
//!
//! Provides:
//! - [`config::WsConfig`] — heartbeat, broadcast capacity, connection limits, Origin allow-list with builder.
//! - [`hub::BroadcastHub`] — typed `broadcast::Sender<T>` wrapper with connection counting, generic over `T: Clone + Serialize`.
//! - [`room::RoomManager`] / [`room::Room`] — DashMap-backed room isolation with participant tracking, over the [`codec::Frame`] message model (text **and** binary).
//! - [`room::RoomRegistry`] — the room-collection trait; swap the in-memory manager for a multi-node backend.
//! - [`extractor::TokenExtractor`] — configurable token extraction (`Authorization: Bearer`, `?token=`, `?access_token=`, `Cookie`).
//! - [`origin_allowed_in_parts`] — Origin validation for the upgrade handshake (CSWSH defense, REQ-WSKIT-200).
//! - [`codec::Codec`] / [`codec::JsonCodec`] — JSON encode/decode via serde.
//! - [`stats::StatsRecorder`] — backpressure/traffic counters (connections, rooms, bytes/messages in/out, drops), global + per-room, optional `metrics`-facade emission.
//! - With `compression`: [`compression::FrameCompressor`] — application-layer DEFLATE for `Frame`s (not `permessage-deflate`; the module docs explain why).
//! - With `redis`: [`redis_rooms::RedisRoomRegistry`] — multi-node room fan-out over Redis pub/sub (at-most-once; the module docs explain the topology).
//!
//! ## Quick start
//!
//! ```rust
//! use ws_kit::{config::WsConfig, hub::BroadcastHub, room::RoomManager, codec::Codec};
//! use serde::{Serialize, Deserialize};
//!
//! #[derive(Clone, Serialize, Deserialize, Debug, PartialEq)]
//! struct ChatMsg { user: String, body: String }
//!
//! # tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(async {
//! let hub = BroadcastHub::<ChatMsg>::new(1024);
//! let mut rx = hub.subscribe();
//! hub.broadcast(ChatMsg { user: "alice".into(), body: "hi".into() }).unwrap();
//! let msg = rx.recv().await.unwrap();
//! assert_eq!(msg.user, "alice");
//! # });
//! ```
//!
//! ## Binary messages (0.4.0)
//!
//! ```rust
//! use ws_kit::codec::Frame;
//! use ws_kit::room::RoomManager;
//!
//! # tokio::runtime::Builder::new_current_thread().enable_all().build().unwrap().block_on(async {
//! let m = RoomManager::new();
//! let room = m.get_or_create("media");
//! let mut rx = room.subscribe();
//! room.broadcast(Frame::binary(vec![0xde_u8, 0xad, 0xbe, 0xef])).unwrap();
//! assert!(rx.recv().await.unwrap().is_binary());
//! # });
//! ```
//!
//! Binary payloads are carried opaquely — ws-kit never parses them as
//! text/JSON; [`codec::Frame::Text`] and [`codec::Frame::Binary`] are kept
//! distinct end to end. Authentication (`TokenExtractor`) operates on the
//! HTTP upgrade request and is frame-kind-agnostic.
//!
//! ## Features
//!
//! - `axum` (default): enables `axum` WebSocket and `tower` deps, and `TokenExtractor::extract_token(&Parts, _)`
//! - `compression`: application-layer DEFLATE for `Frame` payloads (see [`compression`] for the layer assessment)
//! - `redis`: multi-node room fan-out via [`redis_rooms::RedisRoomRegistry`] (at-most-once pub/sub)
//! - `metrics`: emit [`stats`] counters through the `metrics` facade
//! - `tracing`: deprecated no-op kept for 0.3.x compatibility
// Model-checking tests for `counter` — compiled only under `--cfg loom`.
// Re-exports for ergonomic use
pub use ;
pub use ;
pub use WsError;
pub use ;
pub use BroadcastHub;
pub use ;
pub use ;
pub use ;
pub use origin_allowed_in_parts;
pub use ;
pub use RedisRoomRegistry;