Skip to main content

signal_fish_client/
lib.rs

1//! # Signal Fish Client
2//!
3//! Transport-agnostic Rust client for the Signal Fish multiplayer signaling protocol.
4//!
5//! This crate provides a high-level async client that communicates with a Signal Fish
6//! signaling server using JSON text messages over any bidirectional transport.
7//!
8//! ## Features
9//!
10//! - **Transport-agnostic** — implement the [`Transport`] trait for any backend
11//! - **Wire-compatible** — all protocol types match the server's v2 format exactly
12//! - **WebSocket built-in** — default `transport-websocket` feature provides `WebSocketTransport`
13//! - **Event-driven** — receive typed `SignalFishEvent`s via a channel
14//!
15//! ## Quick Start
16//!
17//! ```rust,ignore
18//! use signal_fish_client::{
19//!     WebSocketTransport, SignalFishClient, SignalFishConfig,
20//!     JoinRoomParams, SignalFishEvent,
21//! };
22//!
23//! #[tokio::main]
24//! async fn main() -> Result<(), signal_fish_client::SignalFishError> {
25//!     // 1. Connect a WebSocket transport to the signaling server.
26//!     let transport = WebSocketTransport::connect("ws://localhost:3536/ws").await?;
27//!
28//!     // 2. Build a client config with your application ID.
29//!     let config = SignalFishConfig::new("mb_app_abc123");
30//!
31//!     // 3. Start the client — returns a handle and an event receiver.
32//!     //    The client automatically sends Authenticate on start.
33//!     let (mut client, mut event_rx) = SignalFishClient::start(transport, config);
34//!
35//!     // 4. Process events — wait for Authenticated before joining a room.
36//!     while let Some(event) = event_rx.recv().await {
37//!         match event {
38//!             SignalFishEvent::Authenticated { app_name, .. } => {
39//!                 println!("Authenticated as {app_name}");
40//!                 // Now it's safe to join a room.
41//!                 client.join_room(JoinRoomParams::new("my-game", "Alice"))?;
42//!             }
43//!             SignalFishEvent::RoomJoined { room_code, .. } => {
44//!                 println!("Joined room {room_code}");
45//!             }
46//!             SignalFishEvent::Disconnected { .. } => break,
47//!             _ => {}
48//!         }
49//!     }
50//!
51//!     // 5. Shut down gracefully.
52//!     client.shutdown().await;
53//!     Ok(())
54//! }
55//! ```
56
57pub mod client;
58pub mod error;
59pub mod error_codes;
60pub mod event;
61pub mod protocol;
62pub mod transport;
63pub mod transports;
64
65// Re-export primary types for ergonomic imports.
66pub use client::{JoinRoomParams, SignalFishClient, SignalFishConfig};
67pub use error::SignalFishError;
68pub use error_codes::ErrorCode;
69pub use event::SignalFishEvent;
70pub use protocol::{ClientMessage, ServerMessage};
71pub use transport::Transport;
72
73#[cfg(feature = "transport-websocket")]
74pub use transports::WebSocketTransport;
75
76#[cfg(feature = "polling-client")]
77pub mod polling_client;
78
79#[cfg(feature = "polling-client")]
80pub use polling_client::SignalFishPollingClient;
81
82// Re-export only on the correct target (see transports/mod.rs for rationale).
83#[cfg(all(feature = "transport-websocket-emscripten", target_os = "emscripten"))]
84pub use transports::EmscriptenWebSocketTransport;