From 7f978e2176c74075d5dbe8dfd6bc6e22383f6868 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Per=C5=BCy=C5=82o?= Date: Wed, 28 Jan 2026 16:08:24 +0100 Subject: [PATCH] Adds docs for data channels --- api/fishjam-server | 2 +- api/protos | 2 +- docs/explanation/data-channels.mdx | 190 +++++++++++++++++++++++++++++ docs/how-to/client/connecting.mdx | 1 + packages/js-server-sdk | 2 +- packages/python-server-sdk | 2 +- packages/web-client-sdk | 2 +- 7 files changed, 196 insertions(+), 5 deletions(-) create mode 100644 docs/explanation/data-channels.mdx diff --git a/api/fishjam-server b/api/fishjam-server index 65b3b4c..4d7c550 160000 --- a/api/fishjam-server +++ b/api/fishjam-server @@ -1 +1 @@ -Subproject commit 65b3b4cbbb5b26e21c6650bb62082668983f43e6 +Subproject commit 4d7c550873599856cece48d95be58b8636016dbd diff --git a/api/protos b/api/protos index 40f4ab8..1ff0f98 160000 --- a/api/protos +++ b/api/protos @@ -1 +1 @@ -Subproject commit 40f4ab8013644de2be5d7d7ff2652725935a2e92 +Subproject commit 1ff0f9806c53da1d29be98e14d31096cdabeffef diff --git a/docs/explanation/data-channels.mdx b/docs/explanation/data-channels.mdx new file mode 100644 index 0000000..2a4356e --- /dev/null +++ b/docs/explanation/data-channels.mdx @@ -0,0 +1,190 @@ +--- +type: explanation +sidebar_position: 7 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Data Channels + +Data channels allow you to send and receive arbitrary binary data between peers in a room. This is useful for implementing features like text chat, file sharing, game state synchronization, or real-time cursor positions. + +## Prerequisites + +Before using data channels, you must be [connected to a room](./connecting). Data channels only work after you have successfully joined a room. + +## Channel Types + +The SDK provides two types of data channels, each optimized for different use cases: + +### Reliable Channel + +- **Ordered delivery**: Messages arrive in the order they were sent +- **Guaranteed delivery**: All messages will be delivered, with automatic retransmission if needed +- **Use cases**: Chat messages, file transfers, commands, or any data that must not be lost + +### Lossy Channel + +- **Unordered delivery**: Messages may arrive out of order +- **No retransmission**: Messages may be dropped if the network is congested +- **Lower latency**: Faster delivery since there's no waiting for retransmissions +- **Use cases**: Real-time cursor positions, game state updates, live sensor data, or any data where the latest value matters more than every value + +## Broadcast Communication + +Data channels work in a **broadcast fashion** - when you publish data, it is sent to all other peers in the room. Additionally: + +- Messages sent on the **reliable channel** are only received by peers subscribed to the **reliable channel** +- Messages sent on the **lossy channel** are only received by peers subscribed to the **lossy channel** + +This separation allows you to use both channels simultaneously for different purposes without interference. + +## Using Data Channels + +Use the [`useDataChannel`](../../api/web/functions/useDataChannel) hook to work with data channels. The typical flow is: + +1. Initialize the data channel after connecting to a room +2. Subscribe to incoming messages +3. Publish messages to other peers + +### Example: Simple Chat Messages + + + + +```tsx +import { useConnection, useDataChannel } from "@fishjam-cloud/react-client"; +import { useCallback, useEffect, useState } from "react"; + +export function useChat() { + const { peerStatus } = useConnection(); + const { + initializeDataChannel, + publishData, + subscribeData, + dataChannelReady, + } = useDataChannel(); + + const [messages, setMessages] = useState([]); + + // Step 1: Initialize data channel when connected + useEffect(() => { + if (peerStatus === "connected") { + initializeDataChannel(); + } + }, [peerStatus, initializeDataChannel]); + + // Step 2: Subscribe to incoming messages + useEffect(() => { + if (!dataChannelReady) return; + + const unsubscribe = subscribeData( + (data: Uint8Array) => { + const message = new TextDecoder().decode(data); + setMessages((prev) => [...prev, message]); + }, + { reliable: true }, + ); + + return unsubscribe; + }, [subscribeData, dataChannelReady]); + + // Step 3: Publish messages + const sendMessage = useCallback( + (text: string) => { + if (!dataChannelReady) return; + + const encoded = new TextEncoder().encode(text); + publishData(encoded, { reliable: true }); + }, + [publishData, dataChannelReady], + ); + + return { messages, sendMessage, ready: dataChannelReady }; +} +``` + + + + +Mobile SDK support for data channels will be available in a future release. + + + + +### Example: Using the Lossy Channel + +For real-time data where low latency is more important than guaranteed delivery: + + + + +```tsx +import { useConnection, useDataChannel } from "@fishjam-cloud/react-client"; +import { useCallback, useEffect, useState } from "react"; + +interface CursorPosition { + peerId: string; + x: number; + y: number; +} + +export function useCursorSharing(peerId: string) { + const { peerStatus } = useConnection(); + const { + initializeDataChannel, + publishData, + subscribeData, + dataChannelReady, + } = useDataChannel(); + + const [cursors, setCursors] = useState>( + new Map(), + ); + + useEffect(() => { + if (peerStatus === "connected") { + initializeDataChannel(); + } + }, [peerStatus, initializeDataChannel]); + + useEffect(() => { + if (!dataChannelReady) return; + + const unsubscribe = subscribeData( + (data: Uint8Array) => { + const position: CursorPosition = JSON.parse( + new TextDecoder().decode(data), + ); + setCursors((prev) => new Map(prev).set(position.peerId, position)); + }, + { reliable: false }, // Lossy channel for low latency + ); + + return unsubscribe; + }, [subscribeData, dataChannelReady]); + + const updateCursor = useCallback( + (x: number, y: number) => { + if (!dataChannelReady) return; + + const encoded = new TextEncoder().encode( + JSON.stringify({ peerId, x, y }), + ); + publishData(encoded, { reliable: false }); + }, + [publishData, dataChannelReady, peerId], + ); + + return { cursors, updateCursor, ready: dataChannelReady }; +} +``` + + + + +Mobile SDK support for data channels will be available in a future release. + + + diff --git a/docs/how-to/client/connecting.mdx b/docs/how-to/client/connecting.mdx index 8aa59af..2cdfbf9 100644 --- a/docs/how-to/client/connecting.mdx +++ b/docs/how-to/client/connecting.mdx @@ -168,5 +168,6 @@ Now that you're connected to a room, you can explore additional features: - [Start Streaming](./start-streaming) - Enable your camera and microphone - [List Other Peers](./list-other-peers) - Display video from other participants +- [Data Channels](./data-channels) - Send and receive arbitrary data between peers (e.g., text chat) - [Picture in Picture](./picture-in-picture) - Allow users to watch video in a floating window (Mobile) - [Background Streaming](./background-streaming) - Keep calls active when the app is backgrounded (Mobile) diff --git a/packages/js-server-sdk b/packages/js-server-sdk index 22932e9..7aa9127 160000 --- a/packages/js-server-sdk +++ b/packages/js-server-sdk @@ -1 +1 @@ -Subproject commit 22932e9e40d6685e876f3295d34a2dc463114ca8 +Subproject commit 7aa91272ab7d18fdf42ce6de3cf7585b5d0dd285 diff --git a/packages/python-server-sdk b/packages/python-server-sdk index 8136187..fb05c3c 160000 --- a/packages/python-server-sdk +++ b/packages/python-server-sdk @@ -1 +1 @@ -Subproject commit 8136187b8912b35f6ff730144e69dc46c38939d7 +Subproject commit fb05c3cb78450e442ecd683e679e0d3654ac7f1d diff --git a/packages/web-client-sdk b/packages/web-client-sdk index 38c9582..52dcce8 160000 --- a/packages/web-client-sdk +++ b/packages/web-client-sdk @@ -1 +1 @@ -Subproject commit 38c95822d47e186878c38e0cd07cc5fdb317300c +Subproject commit 52dcce8e5d9028b4b4a64ceba99c1e70db0838ed