From b66a9f1b797552590a4a4c9d2a5eeaf4c67f8000 Mon Sep 17 00:00:00 2001 From: Septias Date: Mon, 1 Apr 2024 17:43:50 +0200 Subject: [PATCH 01/23] add page --- src-docs/SUMMARY.md | 13 ++++++++----- src-docs/spec/sendEphemeralUpdate.md | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) create mode 100644 src-docs/spec/sendEphemeralUpdate.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index a945103..ff7b8e9 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -3,16 +3,19 @@ - [Get Started](./get_started.md) - [Webxdc Specification](./spec/README.md) + - [Container file format (`.xdc`)](./spec/format.md) - [Javascript API](./spec/api.md) - - [sendUpdate](./spec/sendUpdate.md) - - [setUpdateListener](./spec/setUpdateListener.md) - - [sendToChat](./spec/sendToChat.md) - - [importFiles](./spec/importFiles.md) - - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) + - [sendUpdate](./spec/sendUpdate.md) + - [sendEphemeralUpdate](./spec/sendEphemeralUpdate.md) + - [setUpdateListener](./spec/setUpdateListener.md) + - [sendToChat](./spec/sendToChat.md) + - [importFiles](./spec/importFiles.md) + - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) - [Messenger implementations](./spec/messenger.md) - [Shared Web Application state](./shared_state/README.md) + - [Detecting conflicts](./shared_state/conflicts.md) - [Theory of Conflict-free Replicated Data Types (CRDTs)](./shared_state/crdts.md) - [Practical CRDT usage](./shared_state/practical.md) diff --git a/src-docs/spec/sendEphemeralUpdate.md b/src-docs/spec/sendEphemeralUpdate.md new file mode 100644 index 0000000..f756b02 --- /dev/null +++ b/src-docs/spec/sendEphemeralUpdate.md @@ -0,0 +1 @@ +hiiiiii \ No newline at end of file From e72ac9961984112a78e2254c15fff63ad230df0d Mon Sep 17 00:00:00 2001 From: Septias Date: Tue, 2 Apr 2024 10:08:30 +0200 Subject: [PATCH 02/23] more docs --- src-docs/SUMMARY.md | 5 ++--- src-docs/spec/ephemeralSideChannels.md | 10 ++++++++++ src-docs/spec/sendEphemeralUpdate.md | 10 +++++++++- src-docs/spec/setEphemeralUpdateListener.md | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) create mode 100644 src-docs/spec/ephemeralSideChannels.md create mode 100644 src-docs/spec/setEphemeralUpdateListener.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index ff7b8e9..d9c8f4d 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -3,19 +3,18 @@ - [Get Started](./get_started.md) - [Webxdc Specification](./spec/README.md) - - [Container file format (`.xdc`)](./spec/format.md) + - [Ephemeral side channels](./spec/ephemeralSideChannels.md) - [Javascript API](./spec/api.md) - [sendUpdate](./spec/sendUpdate.md) - [sendEphemeralUpdate](./spec/sendEphemeralUpdate.md) - [setUpdateListener](./spec/setUpdateListener.md) + - [setEphemeralUpdateListener](./spec/setEphemeralUpdateListener.md) - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) - [Messenger implementations](./spec/messenger.md) - - [Shared Web Application state](./shared_state/README.md) - - [Detecting conflicts](./shared_state/conflicts.md) - [Theory of Conflict-free Replicated Data Types (CRDTs)](./shared_state/crdts.md) - [Practical CRDT usage](./shared_state/practical.md) diff --git a/src-docs/spec/ephemeralSideChannels.md b/src-docs/spec/ephemeralSideChannels.md new file mode 100644 index 0000000..b145426 --- /dev/null +++ b/src-docs/spec/ephemeralSideChannels.md @@ -0,0 +1,10 @@ +# Ephemeral side channels + +### WebXDC Ephemeral Channels API + +The WebXDC ephemeral API has two methods `sendEphemeralUpdate(payload: T)` and `setEphemeralUpdateListener((payload: T) => void)` which allow one to explicitly send and receive data over an "ephemeral" channel. This data only has to be serializable by js. + +Ephemeral channels provide a fast transport layer, ideally directly between machines collaborating on the same WebXDC app, improving performance significantly. The purpose of this is application state syncing for real time games or collaborative applications. It could for example be used to sync to display the cursor of all peers in an collaborative editor. The gossip layer should be much faster than normal messages but has the downside that messages are _not_ persist like regular WebXDC messages. WebXDC application developers need to explicitly handle persistence if desired (for example by sending regular messages), but ideally only use ephemeral channels for non-critical data. + +### Iroh +DeltaChat uses the ephemeral-channel provider [Iroh](https://iroh.computer/), which attempts to establish direct p2p connections between peers (QUIC), using PlumTree as a gossiping protocol for efficient peer sampling. Iroh falls back to relay nodes when a direct connection can not be established. Even a relayed connection is faster than sending single WebXDC messages via mail. \ No newline at end of file diff --git a/src-docs/spec/sendEphemeralUpdate.md b/src-docs/spec/sendEphemeralUpdate.md index f756b02..f57de3b 100644 --- a/src-docs/spec/sendEphemeralUpdate.md +++ b/src-docs/spec/sendEphemeralUpdate.md @@ -1 +1,9 @@ -hiiiiii \ No newline at end of file +# sendEphemeralUpdate + +```js +window.webxdc.sendUpdate(payload); +``` + +Send an ephemeral update to all peers. [setEphemeralUpdateListener](./setEphemeralUpdateListener.md) has to be called first in order to join the gossip swarm and make it operational. + +- `payload` any js object that can be given to `JSON.stringify` diff --git a/src-docs/spec/setEphemeralUpdateListener.md b/src-docs/spec/setEphemeralUpdateListener.md new file mode 100644 index 0000000..d65d2f5 --- /dev/null +++ b/src-docs/spec/setEphemeralUpdateListener.md @@ -0,0 +1,14 @@ +# setEphemeralUpdateListener + +```js +window.webxdc.setEphemeralUpdateListener((payload) => {}); +``` + +With `setEphemeralUpdateListener()` you define a callback that receives the _ephemeral_ updates +sent by [`sendEphemeralUpdate()`](./setEphemeralUpdateListener.md). The callback is called for updates sent _only_ by other peers. + +- `payload`: + +Calling `setEphemeralUpdateListener()` multiple times is undefined behavior: in current implementations the callback is simply replaced. + +[`sendEphemeralUpdate()`]: ./sendEphemeralUpdate.html From 863632445e1b84bb192f83d08ca1a15fa011bd9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= Date: Tue, 9 Apr 2024 11:57:43 +0200 Subject: [PATCH 03/23] improve docs --- src-docs/spec/sendEphemeralUpdate.md | 2 +- src-docs/spec/setEphemeralUpdateListener.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src-docs/spec/sendEphemeralUpdate.md b/src-docs/spec/sendEphemeralUpdate.md index f57de3b..7fc9422 100644 --- a/src-docs/spec/sendEphemeralUpdate.md +++ b/src-docs/spec/sendEphemeralUpdate.md @@ -4,6 +4,6 @@ window.webxdc.sendUpdate(payload); ``` -Send an ephemeral update to all peers. [setEphemeralUpdateListener](./setEphemeralUpdateListener.md) has to be called first in order to join the gossip swarm and make it operational. +Send an ephemeral update to all peers. [setEphemeralUpdateListener](./setEphemeralUpdateListener.md) has to be called first in order to join the gossip swarm and make it operational. Only after the promisle from [setEphemeralUpdateListener](./setEphemeralUpdateListener.md) resolves, the sent updates are able to reache a peer. - `payload` any js object that can be given to `JSON.stringify` diff --git a/src-docs/spec/setEphemeralUpdateListener.md b/src-docs/spec/setEphemeralUpdateListener.md index d65d2f5..8a77512 100644 --- a/src-docs/spec/setEphemeralUpdateListener.md +++ b/src-docs/spec/setEphemeralUpdateListener.md @@ -5,7 +5,8 @@ window.webxdc.setEphemeralUpdateListener((payload) => {}); ``` With `setEphemeralUpdateListener()` you define a callback that receives the _ephemeral_ updates -sent by [`sendEphemeralUpdate()`](./setEphemeralUpdateListener.md). The callback is called for updates sent _only_ by other peers. +sent by [`sendEphemeralUpdate()`](./setEphemeralUpdateListener.md). The callback is _only_ called for updates sent by other peers. +The returned promise resolves as soon as at least one peer connection is established, making the swarm operational. Sending updates before this will not result in a hard error, but these messages will never arrive anywhere. - `payload`: From 18c9bf4992bc2f8282de0d67d559ee18e2e0c036 Mon Sep 17 00:00:00 2001 From: Septias Date: Wed, 10 Apr 2024 14:57:34 +0200 Subject: [PATCH 04/23] restructuring --- src-docs/SUMMARY.md | 5 ++-- src-docs/spec/ephemeralSideChannels.md | 10 ------- src-docs/spec/sendEphemeral.md | 9 ++++++ src-docs/spec/sendEphemeralUpdate.md | 9 ------ src-docs/spec/setEphemeralListener.md | 31 +++++++++++++++++++++ src-docs/spec/setEphemeralUpdateListener.md | 15 ---------- 6 files changed, 42 insertions(+), 37 deletions(-) delete mode 100644 src-docs/spec/ephemeralSideChannels.md create mode 100644 src-docs/spec/sendEphemeral.md delete mode 100644 src-docs/spec/sendEphemeralUpdate.md create mode 100644 src-docs/spec/setEphemeralListener.md delete mode 100644 src-docs/spec/setEphemeralUpdateListener.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index d9c8f4d..d165d8a 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -4,12 +4,11 @@ - [Webxdc Specification](./spec/README.md) - [Container file format (`.xdc`)](./spec/format.md) - - [Ephemeral side channels](./spec/ephemeralSideChannels.md) - [Javascript API](./spec/api.md) - [sendUpdate](./spec/sendUpdate.md) - - [sendEphemeralUpdate](./spec/sendEphemeralUpdate.md) - [setUpdateListener](./spec/setUpdateListener.md) - - [setEphemeralUpdateListener](./spec/setEphemeralUpdateListener.md) + - [sendEphemeral](./spec/sendEphemeral.md) + - [setEphemeralListener](./spec/setEphemeralListener.md) - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) diff --git a/src-docs/spec/ephemeralSideChannels.md b/src-docs/spec/ephemeralSideChannels.md deleted file mode 100644 index b145426..0000000 --- a/src-docs/spec/ephemeralSideChannels.md +++ /dev/null @@ -1,10 +0,0 @@ -# Ephemeral side channels - -### WebXDC Ephemeral Channels API - -The WebXDC ephemeral API has two methods `sendEphemeralUpdate(payload: T)` and `setEphemeralUpdateListener((payload: T) => void)` which allow one to explicitly send and receive data over an "ephemeral" channel. This data only has to be serializable by js. - -Ephemeral channels provide a fast transport layer, ideally directly between machines collaborating on the same WebXDC app, improving performance significantly. The purpose of this is application state syncing for real time games or collaborative applications. It could for example be used to sync to display the cursor of all peers in an collaborative editor. The gossip layer should be much faster than normal messages but has the downside that messages are _not_ persist like regular WebXDC messages. WebXDC application developers need to explicitly handle persistence if desired (for example by sending regular messages), but ideally only use ephemeral channels for non-critical data. - -### Iroh -DeltaChat uses the ephemeral-channel provider [Iroh](https://iroh.computer/), which attempts to establish direct p2p connections between peers (QUIC), using PlumTree as a gossiping protocol for efficient peer sampling. Iroh falls back to relay nodes when a direct connection can not be established. Even a relayed connection is faster than sending single WebXDC messages via mail. \ No newline at end of file diff --git a/src-docs/spec/sendEphemeral.md b/src-docs/spec/sendEphemeral.md new file mode 100644 index 0000000..8200b8c --- /dev/null +++ b/src-docs/spec/sendEphemeral.md @@ -0,0 +1,9 @@ +# sendEphemeral + +```js +window.webxdc.sendEphemeral(payload); +``` + +Send an ephemeral message to all peers. [setEphemeralListener](./setEphemeralListener.md) has to be called first to create a connection to at least on peer. See the documentation for [setEphemeralListener](./setEphemeralListener.md) to find out more. + +- `payload` any javascript object that can be given to `JSON.stringify` diff --git a/src-docs/spec/sendEphemeralUpdate.md b/src-docs/spec/sendEphemeralUpdate.md deleted file mode 100644 index 7fc9422..0000000 --- a/src-docs/spec/sendEphemeralUpdate.md +++ /dev/null @@ -1,9 +0,0 @@ -# sendEphemeralUpdate - -```js -window.webxdc.sendUpdate(payload); -``` - -Send an ephemeral update to all peers. [setEphemeralUpdateListener](./setEphemeralUpdateListener.md) has to be called first in order to join the gossip swarm and make it operational. Only after the promisle from [setEphemeralUpdateListener](./setEphemeralUpdateListener.md) resolves, the sent updates are able to reache a peer. - -- `payload` any js object that can be given to `JSON.stringify` diff --git a/src-docs/spec/setEphemeralListener.md b/src-docs/spec/setEphemeralListener.md new file mode 100644 index 0000000..c30144b --- /dev/null +++ b/src-docs/spec/setEphemeralListener.md @@ -0,0 +1,31 @@ +# setEphemeralListener + +```js +window.webxdc.setEphemeralListener((payload) => {}); +``` + +`setEphemeralListener` can be used to set a callback that receives the _ephemeral_ messages +sent by [`sendEphemeral`](./sendEphemeral.md). Ephemeral messages are messages that are delivered only to peers that are currently connected with a direct connection to the sender. These messages are not persisted and should thus only be used for unimportant synchronization like cursor positions and live game data. Members of a chat that are not currently connected will never receive these messages. +The `setEphemeralListener` function returnes a promise that resolves as soon as at least one peer is online. The completion of the promise thus signales that the connection is usable for message delivery. Messages that are send with [`sendEphemeral`](./sendEphemeral.md) before this promise resolves are discarded and will never reach any peer. + +- `payload`: Any json object deserialized by `JSON.parse`. + +Calling `setEphemeralListener()` multiple times is undefined behavior: in current implementations the callback is simply replaced. + + +## Example +```js +// stub implementation until the channel is ready +let sendGossip = () => { console.error("transport not ready") } + +window.webxdc.setEphemeralListener(function (message) { + console.log("Received ephemeral message: ", message); + /* Application code */ +}).then(() => { + // Replace `sendGossip` with proper implementation + sendGossip = () => { + console.log("New ephemeral message: ", msg); + window.webxdc.sendEphemeral(msg); + } +}); +``` \ No newline at end of file diff --git a/src-docs/spec/setEphemeralUpdateListener.md b/src-docs/spec/setEphemeralUpdateListener.md deleted file mode 100644 index 8a77512..0000000 --- a/src-docs/spec/setEphemeralUpdateListener.md +++ /dev/null @@ -1,15 +0,0 @@ -# setEphemeralUpdateListener - -```js -window.webxdc.setEphemeralUpdateListener((payload) => {}); -``` - -With `setEphemeralUpdateListener()` you define a callback that receives the _ephemeral_ updates -sent by [`sendEphemeralUpdate()`](./setEphemeralUpdateListener.md). The callback is _only_ called for updates sent by other peers. -The returned promise resolves as soon as at least one peer connection is established, making the swarm operational. Sending updates before this will not result in a hard error, but these messages will never arrive anywhere. - -- `payload`: - -Calling `setEphemeralUpdateListener()` multiple times is undefined behavior: in current implementations the callback is simply replaced. - -[`sendEphemeralUpdate()`]: ./sendEphemeralUpdate.html From d9b0fb85fd31b6b03f0666c7d1c2f099f21c7ff5 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 19 Apr 2024 12:04:26 +0200 Subject: [PATCH 05/23] sna --- src-docs/SUMMARY.md | 4 +-- src-docs/spec/sendEphemeral.md | 9 ------- src-docs/spec/sendRealtime.md | 20 +++++++++++++++ src-docs/spec/setEphemeralListener.md | 31 ------------------------ src-docs/spec/setRealtimeListener.md | 35 +++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 42 deletions(-) delete mode 100644 src-docs/spec/sendEphemeral.md create mode 100644 src-docs/spec/sendRealtime.md delete mode 100644 src-docs/spec/setEphemeralListener.md create mode 100644 src-docs/spec/setRealtimeListener.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index d165d8a..cc1dafd 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -7,8 +7,8 @@ - [Javascript API](./spec/api.md) - [sendUpdate](./spec/sendUpdate.md) - [setUpdateListener](./spec/setUpdateListener.md) - - [sendEphemeral](./spec/sendEphemeral.md) - - [setEphemeralListener](./spec/setEphemeralListener.md) + - [sendRealtime](./spec/sendRealtime.md) + - [setRealtimeListener](./spec/setRealtimeListener.md) - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) diff --git a/src-docs/spec/sendEphemeral.md b/src-docs/spec/sendEphemeral.md deleted file mode 100644 index 8200b8c..0000000 --- a/src-docs/spec/sendEphemeral.md +++ /dev/null @@ -1,9 +0,0 @@ -# sendEphemeral - -```js -window.webxdc.sendEphemeral(payload); -``` - -Send an ephemeral message to all peers. [setEphemeralListener](./setEphemeralListener.md) has to be called first to create a connection to at least on peer. See the documentation for [setEphemeralListener](./setEphemeralListener.md) to find out more. - -- `payload` any javascript object that can be given to `JSON.stringify` diff --git a/src-docs/spec/sendRealtime.md b/src-docs/spec/sendRealtime.md new file mode 100644 index 0000000..f4a6606 --- /dev/null +++ b/src-docs/spec/sendRealtime.md @@ -0,0 +1,20 @@ +# sendRealtimeMessage + +```js +window.webxdc.sendRealtimeDataToConnectedPeers(data); +``` + +Send realtime data to all connected peers. +Note that you must first call [joinRealtimeMessaging](./setRealtimeListener.md) once +and wait for the returned promise to resolve which indicates a first connected peer +who can receive a realtime data message. + +- `data` is an `Uint8Array` + +- Any peer that is not connected at the time of calling `sendRealtimeDataToConnectedPeers` + will not receive the realtime data payload. + +- If you want to send data that reaches all chat peers independent of + their connection status, use [`sendUpdate`](./sendUpdate.md). + Realtime messages are not persisted or retried and maybe dropped + if the connection is lost. diff --git a/src-docs/spec/setEphemeralListener.md b/src-docs/spec/setEphemeralListener.md deleted file mode 100644 index c30144b..0000000 --- a/src-docs/spec/setEphemeralListener.md +++ /dev/null @@ -1,31 +0,0 @@ -# setEphemeralListener - -```js -window.webxdc.setEphemeralListener((payload) => {}); -``` - -`setEphemeralListener` can be used to set a callback that receives the _ephemeral_ messages -sent by [`sendEphemeral`](./sendEphemeral.md). Ephemeral messages are messages that are delivered only to peers that are currently connected with a direct connection to the sender. These messages are not persisted and should thus only be used for unimportant synchronization like cursor positions and live game data. Members of a chat that are not currently connected will never receive these messages. -The `setEphemeralListener` function returnes a promise that resolves as soon as at least one peer is online. The completion of the promise thus signales that the connection is usable for message delivery. Messages that are send with [`sendEphemeral`](./sendEphemeral.md) before this promise resolves are discarded and will never reach any peer. - -- `payload`: Any json object deserialized by `JSON.parse`. - -Calling `setEphemeralListener()` multiple times is undefined behavior: in current implementations the callback is simply replaced. - - -## Example -```js -// stub implementation until the channel is ready -let sendGossip = () => { console.error("transport not ready") } - -window.webxdc.setEphemeralListener(function (message) { - console.log("Received ephemeral message: ", message); - /* Application code */ -}).then(() => { - // Replace `sendGossip` with proper implementation - sendGossip = () => { - console.log("New ephemeral message: ", msg); - window.webxdc.sendEphemeral(msg); - } -}); -``` \ No newline at end of file diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md new file mode 100644 index 0000000..73538c3 --- /dev/null +++ b/src-docs/spec/setRealtimeListener.md @@ -0,0 +1,35 @@ +# joinRealtimeMessaging + +```js +window.webxdc.joinRealtimeMessaging((data) => {}); +``` + +Announce availability and participation in realtime messaging to peers +and return a promise that resolves when at least one peer is connected. +The callback provided to `joinRealtimeMessaging` will subsequently receive data +sent by any connected peers. + +Notes: + +- `data` is an `Uint8Array`. + +- It is up the application to provide sender identification inside `data` payloads if needed. + +- `joinRealtime` should only be called once during the lifetime of an + application. Subsequent invocations cause undefined behaviour. + + +## Example +```js + +window.webxdc.joinRealtimeMessaging(function (data) { + console.log("Received realtime data: ", data); + msg = new TextDecoder().decode(data); + console.log("decoded message: ", msg); +}).then(() => { + const data = new TextEncoder().encode('hello world'); + console.log("Sending message", data) + window.webxdc.sendRealtimeDataToConnectedPeers(data); + } +}); +``` From 1b1443d3e6756a16f243ab9d2a97dacf4715e6c4 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 19 Apr 2024 18:01:27 +0200 Subject: [PATCH 06/23] new draft of API after discussion with adz --- src-docs/SUMMARY.md | 3 +- src-docs/spec/joinRealtimeSession.md | 45 ++++++++++++++++++++++++++++ src-docs/spec/sendRealtime.md | 20 ------------- src-docs/spec/setRealtimeListener.md | 35 ---------------------- 4 files changed, 46 insertions(+), 57 deletions(-) create mode 100644 src-docs/spec/joinRealtimeSession.md delete mode 100644 src-docs/spec/sendRealtime.md delete mode 100644 src-docs/spec/setRealtimeListener.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index cc1dafd..484eee5 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -7,8 +7,7 @@ - [Javascript API](./spec/api.md) - [sendUpdate](./spec/sendUpdate.md) - [setUpdateListener](./spec/setUpdateListener.md) - - [sendRealtime](./spec/sendRealtime.md) - - [setRealtimeListener](./spec/setRealtimeListener.md) + - [joinRealtimeSession](./spec/joinRealtimeSession.md) - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md new file mode 100644 index 0000000..8f3aa46 --- /dev/null +++ b/src-docs/spec/joinRealtimeSession.md @@ -0,0 +1,45 @@ +# joinRealtimeSession + +```js +window.webxdc.joinRealtimeSession(); +``` + +Announce availability and participation in realtime messaging to chat peers +and return a promise that resolves to a `realtimeSession` object +once the announcement was sent out. + +The `realtimeSession` object provides the following methods: + +**`realtimeSession.on(event, callback)`** + +Register an event handler callback for a realtimeSession event. +Current supported event types are: + +- `ready`: indicating there is at least one connected chat peer + +- `data`: indicating receiving of a `Uint8Array` sent from a peer + + +**`realtimeSession.sendToConnectedPeers(data)`** + +Send a `Unit8Array` data item to all connected peers. + +## Example + +```js + +const realtimeSession = await window.webxdc.joinRealtimeMessaging(); + +realtimeSession.on("ready", () => { + const myId = window.webxdc.selfAddr; + const data = new TextEncoder().encode('hello world from ' + myId); + console.log("Sending message", data); + realtimeSession.sendToConnectedPeers(data); +}) + +realtimeSession.on("data", (data) => { + console.log("Received realtime data: ", data); + msg = new TextDecoder().decode(data); + console.log("decoded message: ", msg); +}) +``` diff --git a/src-docs/spec/sendRealtime.md b/src-docs/spec/sendRealtime.md deleted file mode 100644 index f4a6606..0000000 --- a/src-docs/spec/sendRealtime.md +++ /dev/null @@ -1,20 +0,0 @@ -# sendRealtimeMessage - -```js -window.webxdc.sendRealtimeDataToConnectedPeers(data); -``` - -Send realtime data to all connected peers. -Note that you must first call [joinRealtimeMessaging](./setRealtimeListener.md) once -and wait for the returned promise to resolve which indicates a first connected peer -who can receive a realtime data message. - -- `data` is an `Uint8Array` - -- Any peer that is not connected at the time of calling `sendRealtimeDataToConnectedPeers` - will not receive the realtime data payload. - -- If you want to send data that reaches all chat peers independent of - their connection status, use [`sendUpdate`](./sendUpdate.md). - Realtime messages are not persisted or retried and maybe dropped - if the connection is lost. diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md deleted file mode 100644 index 73538c3..0000000 --- a/src-docs/spec/setRealtimeListener.md +++ /dev/null @@ -1,35 +0,0 @@ -# joinRealtimeMessaging - -```js -window.webxdc.joinRealtimeMessaging((data) => {}); -``` - -Announce availability and participation in realtime messaging to peers -and return a promise that resolves when at least one peer is connected. -The callback provided to `joinRealtimeMessaging` will subsequently receive data -sent by any connected peers. - -Notes: - -- `data` is an `Uint8Array`. - -- It is up the application to provide sender identification inside `data` payloads if needed. - -- `joinRealtime` should only be called once during the lifetime of an - application. Subsequent invocations cause undefined behaviour. - - -## Example -```js - -window.webxdc.joinRealtimeMessaging(function (data) { - console.log("Received realtime data: ", data); - msg = new TextDecoder().decode(data); - console.log("decoded message: ", msg); -}).then(() => { - const data = new TextEncoder().encode('hello world'); - console.log("Sending message", data) - window.webxdc.sendRealtimeDataToConnectedPeers(data); - } -}); -``` From daff2c2fb69291e76df17962dc9b7be4fe01b2b5 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 19 Apr 2024 18:08:32 +0200 Subject: [PATCH 07/23] clarify --- src-docs/spec/joinRealtimeSession.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md index 8f3aa46..4ed2ec7 100644 --- a/src-docs/spec/joinRealtimeSession.md +++ b/src-docs/spec/joinRealtimeSession.md @@ -15,9 +15,9 @@ The `realtimeSession` object provides the following methods: Register an event handler callback for a realtimeSession event. Current supported event types are: -- `ready`: indicating there is at least one connected chat peer +- `ready`: indicates there is at least one connected realtime peer -- `data`: indicating receiving of a `Uint8Array` sent from a peer +- `data`: on receiving a `Uint8Array` that was sent from a realtime peer **`realtimeSession.sendToConnectedPeers(data)`** From a0dca14e7ab612ccf0c2b359b5edd86a8737a663 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 14:13:04 +0200 Subject: [PATCH 08/23] some more precision in the API definition --- src-docs/spec/joinRealtimeSession.md | 38 ++++++++++++++++++---------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md index 4ed2ec7..8cb36f5 100644 --- a/src-docs/spec/joinRealtimeSession.md +++ b/src-docs/spec/joinRealtimeSession.md @@ -1,34 +1,46 @@ -# joinRealtimeSession +# joinRealtimeSession() ```js window.webxdc.joinRealtimeSession(); ``` -Announce availability and participation in realtime messaging to chat peers -and return a promise that resolves to a `realtimeSession` object -once the announcement was sent out. +*NOTE: (April 2024) this API is experimental and subject to change without further notice* -The `realtimeSession` object provides the following methods: +Return a `realtimeSession` object that allows to send and receive data +using direct connections with other joining chat peers. +Calling `joinRealtimeSession()` a second time returns the same singleton object. +Realtime sessions are -**`realtimeSession.on(event, callback)`** +- **private to the chat**: Only chat members can connect. + +- **scoped to the app from which they are started**: different apps in a + chat can not discover, listen to, or interfere with realtime sessions + of other apps in the same chat. + +- **ephemeral**: any sent data will only be received by the currently + connected chat peers but not by peers joining later. -Register an event handler callback for a realtimeSession event. -Current supported event types are: -- `ready`: indicates there is at least one connected realtime peer +## `realtimeSession.on(event, callback)` -- `data`: on receiving a `Uint8Array` that was sent from a realtime peer +Register an event handler callback for a realtimeSession event. +Currently supported event types are: + +- `ready`: fired once if at least one realtime peer is connected. +- `data`: fired on receiving a `Uint8Array` that was sent from a realtime peer. + The callback will only receive `data` that arrived after its registration. -**`realtimeSession.sendToConnectedPeers(data)`** +## `realtimeSession.sendToConnectedPeers(data)` Send a `Unit8Array` data item to all connected peers. + ## Example ```js -const realtimeSession = await window.webxdc.joinRealtimeMessaging(); +const realtimeSession = window.webxdc.joinRealtimeSession(); realtimeSession.on("ready", () => { const myId = window.webxdc.selfAddr; @@ -39,7 +51,7 @@ realtimeSession.on("ready", () => { realtimeSession.on("data", (data) => { console.log("Received realtime data: ", data); - msg = new TextDecoder().decode(data); + const msg = new TextDecoder().decode(data); console.log("decoded message: ", msg); }) ``` From 2874e93039c9add038fbbba2bce5ad71fb51a467 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 15:34:43 +0200 Subject: [PATCH 09/23] revert back to send/setlistener api, no events anymore --- src-docs/SUMMARY.md | 3 +- src-docs/spec/joinRealtimeSession.md | 57 ---------------------------- src-docs/spec/sendRealtimeData.md | 39 +++++++++++++++++++ src-docs/spec/setRealtimeListener.md | 34 +++++++++++++++++ 4 files changed, 75 insertions(+), 58 deletions(-) delete mode 100644 src-docs/spec/joinRealtimeSession.md create mode 100644 src-docs/spec/sendRealtimeData.md create mode 100644 src-docs/spec/setRealtimeListener.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index 484eee5..863b209 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -7,10 +7,11 @@ - [Javascript API](./spec/api.md) - [sendUpdate](./spec/sendUpdate.md) - [setUpdateListener](./spec/setUpdateListener.md) - - [joinRealtimeSession](./spec/joinRealtimeSession.md) - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) + - [setRealtimeListener](./spec/setRealtimeListener.md) + - [sendRealtimeData](./spec/sendRealtimeData.md) - [Messenger implementations](./spec/messenger.md) - [Shared Web Application state](./shared_state/README.md) - [Detecting conflicts](./shared_state/conflicts.md) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md deleted file mode 100644 index 8cb36f5..0000000 --- a/src-docs/spec/joinRealtimeSession.md +++ /dev/null @@ -1,57 +0,0 @@ -# joinRealtimeSession() - -```js -window.webxdc.joinRealtimeSession(); -``` - -*NOTE: (April 2024) this API is experimental and subject to change without further notice* - -Return a `realtimeSession` object that allows to send and receive data -using direct connections with other joining chat peers. -Calling `joinRealtimeSession()` a second time returns the same singleton object. -Realtime sessions are - -- **private to the chat**: Only chat members can connect. - -- **scoped to the app from which they are started**: different apps in a - chat can not discover, listen to, or interfere with realtime sessions - of other apps in the same chat. - -- **ephemeral**: any sent data will only be received by the currently - connected chat peers but not by peers joining later. - - -## `realtimeSession.on(event, callback)` - -Register an event handler callback for a realtimeSession event. -Currently supported event types are: - -- `ready`: fired once if at least one realtime peer is connected. - -- `data`: fired on receiving a `Uint8Array` that was sent from a realtime peer. - The callback will only receive `data` that arrived after its registration. - -## `realtimeSession.sendToConnectedPeers(data)` - -Send a `Unit8Array` data item to all connected peers. - - -## Example - -```js - -const realtimeSession = window.webxdc.joinRealtimeSession(); - -realtimeSession.on("ready", () => { - const myId = window.webxdc.selfAddr; - const data = new TextEncoder().encode('hello world from ' + myId); - console.log("Sending message", data); - realtimeSession.sendToConnectedPeers(data); -}) - -realtimeSession.on("data", (data) => { - console.log("Received realtime data: ", data); - const msg = new TextDecoder().decode(data); - console.log("decoded message: ", msg); -}) -``` diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md new file mode 100644 index 0000000..236f464 --- /dev/null +++ b/src-docs/spec/sendRealtimeData.md @@ -0,0 +1,39 @@ +# sendRealtimeData() + +```js +window.webxdc.sendRealtimeData(data); +``` + +Send `Uint8Array` data to other realtime peers for this app. +You must first call [`setRealtimeListener`](./setRealtimeListener.md) +and wait for the returned promise to resolve before sending. + +Any sent data is + +- **private to the chat**: Only chat members can receive realtime data. + +- **scoped to the app**: different apps in a + chat can not discover or receive realtime data of other apps in the chat. + +- **ephemeral**: any sent data will only be received by the currently + connected chat peers but not by peers joining later. + There is no guarantee anyone is receiving the sent data + because for example there might be no currently listening peers + or there is no network at all. + +## Example + +```js + +window.webxdc.setRealtimeListener((data) => { + console.log("Received realtime data: ", data); + const msg = new TextDecoder().decode(data); + console.log("decoded message: ", msg); +}).then(() => { + const myId = window.webxdc.selfAddr; + const data = new TextEncoder().encode('hello world from ' + myId); + console.log("Sending message", data); + window.webxdc.sendRealtimeData(data); +}) + +``` diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md new file mode 100644 index 0000000..0e2f972 --- /dev/null +++ b/src-docs/spec/setRealtimeListener.md @@ -0,0 +1,34 @@ +# setRealtimeListener + +```js +window.webxdc.setRealtimeListener((data) => {}); +``` + +Announce participation in realtime data sending and receiving +and return a promise that resolves when at least one peer is connected. + +The `setRealtimeListener` callback receives all `Uint8Array` data items +that were sent from a peer through [`sendRealtimeData(data)`](./sendRealtimeData.md). + +Note that sending data before the promise is resolved will discard the sent data. + +Calling `setRealtimeListener` with a `null` value will disconnect from receiving +and sending realtime data. You may afterwards call `setRealtimeListener` again +to re-establish participation in realtime sending and receiving. + +## Example + +```js + +window.webxdc.setRealtimeListener((data) => { + console.log("Received realtime data: ", data); + const msg = new TextDecoder().decode(data); + console.log("decoded message: ", msg); +}).then(() => { + const myId = window.webxdc.selfAddr; + const data = new TextEncoder().encode('hello world from ' + myId); + console.log("Sending message", data); + window.webxdc.sendRealtimeData(data); +}) + +``` From a83cfba1e95b124cc6f28a266718161083a45343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= <39526136+Septias@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:48:49 +0200 Subject: [PATCH 10/23] Update example --- src-docs/spec/sendRealtimeData.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md index 236f464..35a563f 100644 --- a/src-docs/spec/sendRealtimeData.md +++ b/src-docs/spec/sendRealtimeData.md @@ -24,16 +24,20 @@ Any sent data is ## Example ```js - +let timeout window.webxdc.setRealtimeListener((data) => { console.log("Received realtime data: ", data); const msg = new TextDecoder().decode(data); console.log("decoded message: ", msg); -}).then(() => { +}) + +let pings = 0 +setInterval(() => { const myId = window.webxdc.selfAddr; - const data = new TextEncoder().encode('hello world from ' + myId); + const data = new TextEncoder().encode(`[${pings}] hello from ${myId}`); + pings += 1 console.log("Sending message", data); window.webxdc.sendRealtimeData(data); -}) - +}, 1000) +``` ``` From e93b7db27cbc1a2480e3a6ce6ff2c498557b950e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= <39526136+Septias@users.noreply.github.com> Date: Mon, 22 Apr 2024 15:49:27 +0200 Subject: [PATCH 11/23] Update example --- src-docs/spec/setRealtimeListener.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md index 0e2f972..c0132dd 100644 --- a/src-docs/spec/setRealtimeListener.md +++ b/src-docs/spec/setRealtimeListener.md @@ -4,14 +4,11 @@ window.webxdc.setRealtimeListener((data) => {}); ``` -Announce participation in realtime data sending and receiving -and return a promise that resolves when at least one peer is connected. +Announce participation in realtime data sending and receiving to other peers. The `setRealtimeListener` callback receives all `Uint8Array` data items that were sent from a peer through [`sendRealtimeData(data)`](./sendRealtimeData.md). -Note that sending data before the promise is resolved will discard the sent data. - Calling `setRealtimeListener` with a `null` value will disconnect from receiving and sending realtime data. You may afterwards call `setRealtimeListener` again to re-establish participation in realtime sending and receiving. @@ -19,16 +16,19 @@ to re-establish participation in realtime sending and receiving. ## Example ```js - +let timeout window.webxdc.setRealtimeListener((data) => { console.log("Received realtime data: ", data); const msg = new TextDecoder().decode(data); console.log("decoded message: ", msg); -}).then(() => { +}) + +let pings = 0 +setInterval(() => { const myId = window.webxdc.selfAddr; - const data = new TextEncoder().encode('hello world from ' + myId); + const data = new TextEncoder().encode(`[${pings}] hello from ${myId}`); + pings += 1 console.log("Sending message", data); window.webxdc.sendRealtimeData(data); -}) - +}, 1000) ``` From 646c2ed4c274da826dc5d3511ef7136c7610f5f7 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 16:26:23 +0200 Subject: [PATCH 12/23] try to finalize the api draft --- src-docs/spec/sendRealtimeData.md | 7 ++++++- src-docs/spec/setRealtimeListener.md | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md index 35a563f..2b33568 100644 --- a/src-docs/spec/sendRealtimeData.md +++ b/src-docs/spec/sendRealtimeData.md @@ -4,9 +4,14 @@ window.webxdc.sendRealtimeData(data); ``` +**Note that this API is experimental and not fully settled (April 2024)** + Send `Uint8Array` data to other realtime peers for this app. You must first call [`setRealtimeListener`](./setRealtimeListener.md) -and wait for the returned promise to resolve before sending. +to announce participation in realtime data transmission. +Note that any data sent before a first peer is connected might not arrive. +It is up to the app to implement a "synchronization" protocol +so that peers can detect each other presences. Any sent data is diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md index c0132dd..7dd3364 100644 --- a/src-docs/spec/setRealtimeListener.md +++ b/src-docs/spec/setRealtimeListener.md @@ -4,13 +4,16 @@ window.webxdc.setRealtimeListener((data) => {}); ``` +**Note that this API is experimental and not fully settled (April 2024)** + Announce participation in realtime data sending and receiving to other peers. The `setRealtimeListener` callback receives all `Uint8Array` data items that were sent from a peer through [`sendRealtimeData(data)`](./sendRealtimeData.md). -Calling `setRealtimeListener` with a `null` value will disconnect from receiving -and sending realtime data. You may afterwards call `setRealtimeListener` again +Calling `setRealtimeListener` with a `null` value +will disconnect from receiving and sending realtime data. +You may afterwards call `setRealtimeListener` again with a callback to re-establish participation in realtime sending and receiving. ## Example From 227c520eb3437eed44531d6ff90f4ce8933edf4a Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 16:29:50 +0200 Subject: [PATCH 13/23] ominimize diff --- src-docs/SUMMARY.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index 863b209..ce92107 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -5,13 +5,13 @@ - [Webxdc Specification](./spec/README.md) - [Container file format (`.xdc`)](./spec/format.md) - [Javascript API](./spec/api.md) - - [sendUpdate](./spec/sendUpdate.md) - - [setUpdateListener](./spec/setUpdateListener.md) - - [sendToChat](./spec/sendToChat.md) - - [importFiles](./spec/importFiles.md) - - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) - - [setRealtimeListener](./spec/setRealtimeListener.md) - - [sendRealtimeData](./spec/sendRealtimeData.md) + - [sendUpdate](./spec/sendUpdate.md) + - [setUpdateListener](./spec/setUpdateListener.md) + - [sendToChat](./spec/sendToChat.md) + - [importFiles](./spec/importFiles.md) + - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) + - [setRealtimeListener](./spec/setRealtimeListener.md) + - [sendRealtimeData](./spec/sendRealtimeData.md) - [Messenger implementations](./spec/messenger.md) - [Shared Web Application state](./shared_state/README.md) - [Detecting conflicts](./shared_state/conflicts.md) From f9149eacad323fef437d8f8459dc5899b98f1bfd Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 16:31:21 +0200 Subject: [PATCH 14/23] better formulation --- src-docs/spec/setRealtimeListener.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md index 7dd3364..24b2894 100644 --- a/src-docs/spec/setRealtimeListener.md +++ b/src-docs/spec/setRealtimeListener.md @@ -8,8 +8,8 @@ window.webxdc.setRealtimeListener((data) => {}); Announce participation in realtime data sending and receiving to other peers. -The `setRealtimeListener` callback receives all `Uint8Array` data items -that were sent from a peer through [`sendRealtimeData(data)`](./sendRealtimeData.md). +The `setRealtimeListener` callback receives `Uint8Array` data items +that were sent from connected peers by [`sendRealtimeData(data)`](./sendRealtimeData.md). Calling `setRealtimeListener` with a `null` value will disconnect from receiving and sending realtime data. From 069fcafb6b739c2dd95aeb822873753770261800 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 16:35:48 +0200 Subject: [PATCH 15/23] clarify network broken sentence --- src-docs/spec/sendRealtimeData.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md index 2b33568..f82b86b 100644 --- a/src-docs/spec/sendRealtimeData.md +++ b/src-docs/spec/sendRealtimeData.md @@ -23,8 +23,8 @@ Any sent data is - **ephemeral**: any sent data will only be received by the currently connected chat peers but not by peers joining later. There is no guarantee anyone is receiving the sent data - because for example there might be no currently listening peers - or there is no network at all. + because there might be no currently listening peers, + or network connections broke. ## Example From 7827b2cf82eaf09330a1e8d61e3f21ab4f26f416 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 17:37:31 +0200 Subject: [PATCH 16/23] remove left-over --- src-docs/spec/sendRealtimeData.md | 2 +- src-docs/spec/setRealtimeListener.md | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md index f82b86b..c1ac0ca 100644 --- a/src-docs/spec/sendRealtimeData.md +++ b/src-docs/spec/sendRealtimeData.md @@ -29,7 +29,7 @@ Any sent data is ## Example ```js -let timeout + window.webxdc.setRealtimeListener((data) => { console.log("Received realtime data: ", data); const msg = new TextDecoder().decode(data); diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md index 24b2894..ec57954 100644 --- a/src-docs/spec/setRealtimeListener.md +++ b/src-docs/spec/setRealtimeListener.md @@ -19,7 +19,6 @@ to re-establish participation in realtime sending and receiving. ## Example ```js -let timeout window.webxdc.setRealtimeListener((data) => { console.log("Received realtime data: ", data); const msg = new TextDecoder().decode(data); From 1047a63e481398a07c289e9dfab7d2585f168b41 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 17:38:05 +0200 Subject: [PATCH 17/23] fix typo --- src-docs/spec/sendRealtimeData.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md index c1ac0ca..a81eee7 100644 --- a/src-docs/spec/sendRealtimeData.md +++ b/src-docs/spec/sendRealtimeData.md @@ -45,4 +45,3 @@ setInterval(() => { window.webxdc.sendRealtimeData(data); }, 1000) ``` -``` From 42efb76a708f87f67ead2887979ef50b8f160719 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Mon, 22 Apr 2024 18:09:53 +0200 Subject: [PATCH 18/23] let both methods trigger the realtime participation --- src-docs/spec/sendRealtimeData.md | 7 ++++--- src-docs/spec/setRealtimeListener.md | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md index a81eee7..2f4828d 100644 --- a/src-docs/spec/sendRealtimeData.md +++ b/src-docs/spec/sendRealtimeData.md @@ -7,11 +7,12 @@ window.webxdc.sendRealtimeData(data); **Note that this API is experimental and not fully settled (April 2024)** Send `Uint8Array` data to other realtime peers for this app. -You must first call [`setRealtimeListener`](./setRealtimeListener.md) -to announce participation in realtime data transmission. +This will implicitely trigger the setup of realtime connections +if they are not established yet. Note that any data sent before a first peer is connected might not arrive. +See [`setRealtimeListener`](./setRealtimeListener.md) for how data can be received. It is up to the app to implement a "synchronization" protocol -so that peers can detect each other presences. +so that peers can detect each other's presence. Any sent data is diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md index ec57954..b5ca3fd 100644 --- a/src-docs/spec/setRealtimeListener.md +++ b/src-docs/spec/setRealtimeListener.md @@ -6,10 +6,12 @@ window.webxdc.setRealtimeListener((data) => {}); **Note that this API is experimental and not fully settled (April 2024)** -Announce participation in realtime data sending and receiving to other peers. - +Register a listener callback for realtime data arriving from other peers. +This will implicitely trigger the setup of realtime connections +if they were not established yet. The `setRealtimeListener` callback receives `Uint8Array` data items -that were sent from connected peers by [`sendRealtimeData(data)`](./sendRealtimeData.md). +that were sent from connected peers. +See [`sendRealtimeData(data)`](./sendRealtimeData.md) for more info. Calling `setRealtimeListener` with a `null` value will disconnect from receiving and sending realtime data. From cad0ced93ad68dae87af466311540c7d74df46d7 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Tue, 23 Apr 2024 00:09:57 +0200 Subject: [PATCH 19/23] coalesce all functionality to a `joinRealtimeSession` factory method --- src-docs/SUMMARY.md | 3 +- src-docs/spec/joinRealtimeSession.md | 64 ++++++++++++++++++++++++++++ src-docs/spec/sendRealtimeData.md | 48 --------------------- src-docs/spec/setRealtimeListener.md | 38 ----------------- 4 files changed, 65 insertions(+), 88 deletions(-) create mode 100644 src-docs/spec/joinRealtimeSession.md delete mode 100644 src-docs/spec/sendRealtimeData.md delete mode 100644 src-docs/spec/setRealtimeListener.md diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index ce92107..556cb68 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -10,8 +10,7 @@ - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) - - [setRealtimeListener](./spec/setRealtimeListener.md) - - [sendRealtimeData](./spec/sendRealtimeData.md) + - [joinRealtimeSession](./spec/joinRealtimeSession.md) - [Messenger implementations](./spec/messenger.md) - [Shared Web Application state](./shared_state/README.md) - [Detecting conflicts](./shared_state/conflicts.md) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md new file mode 100644 index 0000000..35160a7 --- /dev/null +++ b/src-docs/spec/joinRealtimeSession.md @@ -0,0 +1,64 @@ +# joinRealtimeSession (experimental API as of April 2024) + +```js +const realtimeSession = window.webxdc.joinRealtimeSession((data) => {}); +``` + +Join an app-specific realtime session with chat peers and +return a `realtimeSession` object with `send` and `leave` methods. + +The callback receives `Uint8Array` data items that were sent from connected peers. + +Calling `joinRealtimeSession` while another `realtimeSession` is active +will not cause any action and returns a `null` value. + +Any transmitted realtime data is + +- **private to the chat**: Only chat members can receive realtime data + and data can only be sent to connected chat members. + +- **scoped to the app**: different apps in a + chat can not discover or receive realtime data of other apps in the chat. + +- **ephemeral**: any sent data will only be received by the currently + connected chat peers but not by peers joining later. + +## `realtimeSession.send(data)` + +Send a `Uint8Array` data item to connected peers. +There is no guarantee anyone is receiving sent data +because there might be no currently listening peers, +or network connections fail. +It is up to the app to determine connectivity status with other peers. + +## `realtimeSession.leave()` + +Leave the realtime session and disconnect from all peers. +Afterwards the `realtimeSession` is invalid and +can not be used anymore for sending or receiving data. +You need to call `window.webxdc.joinRealtimeSession()` +to re-initiate real time connectivity. + +## Example + +```js +const realtimeSession = window.webxdc.joinRealtimeSession((data) => { + console.log("Received realtime data: ", data); + const msg = new TextDecoder().decode(data); + console.log("decoded message: ", msg); +}) + +let pings = 0 +const refreshIntervalId = setInterval(() => { + const myId = window.webxdc.selfAddr; + const data = new TextEncoder().encode(`[${pings}] hello from ${myId}`); + pings += 1 + console.log("Sending message", data); + realtimeSession.send(data); + if (pings >= 100) { + realtimeSession.leave(); + clearInterval(refreshIntervalId); + } + +}, 1000) +``` diff --git a/src-docs/spec/sendRealtimeData.md b/src-docs/spec/sendRealtimeData.md deleted file mode 100644 index 2f4828d..0000000 --- a/src-docs/spec/sendRealtimeData.md +++ /dev/null @@ -1,48 +0,0 @@ -# sendRealtimeData() - -```js -window.webxdc.sendRealtimeData(data); -``` - -**Note that this API is experimental and not fully settled (April 2024)** - -Send `Uint8Array` data to other realtime peers for this app. -This will implicitely trigger the setup of realtime connections -if they are not established yet. -Note that any data sent before a first peer is connected might not arrive. -See [`setRealtimeListener`](./setRealtimeListener.md) for how data can be received. -It is up to the app to implement a "synchronization" protocol -so that peers can detect each other's presence. - -Any sent data is - -- **private to the chat**: Only chat members can receive realtime data. - -- **scoped to the app**: different apps in a - chat can not discover or receive realtime data of other apps in the chat. - -- **ephemeral**: any sent data will only be received by the currently - connected chat peers but not by peers joining later. - There is no guarantee anyone is receiving the sent data - because there might be no currently listening peers, - or network connections broke. - -## Example - -```js - -window.webxdc.setRealtimeListener((data) => { - console.log("Received realtime data: ", data); - const msg = new TextDecoder().decode(data); - console.log("decoded message: ", msg); -}) - -let pings = 0 -setInterval(() => { - const myId = window.webxdc.selfAddr; - const data = new TextEncoder().encode(`[${pings}] hello from ${myId}`); - pings += 1 - console.log("Sending message", data); - window.webxdc.sendRealtimeData(data); -}, 1000) -``` diff --git a/src-docs/spec/setRealtimeListener.md b/src-docs/spec/setRealtimeListener.md deleted file mode 100644 index b5ca3fd..0000000 --- a/src-docs/spec/setRealtimeListener.md +++ /dev/null @@ -1,38 +0,0 @@ -# setRealtimeListener - -```js -window.webxdc.setRealtimeListener((data) => {}); -``` - -**Note that this API is experimental and not fully settled (April 2024)** - -Register a listener callback for realtime data arriving from other peers. -This will implicitely trigger the setup of realtime connections -if they were not established yet. -The `setRealtimeListener` callback receives `Uint8Array` data items -that were sent from connected peers. -See [`sendRealtimeData(data)`](./sendRealtimeData.md) for more info. - -Calling `setRealtimeListener` with a `null` value -will disconnect from receiving and sending realtime data. -You may afterwards call `setRealtimeListener` again with a callback -to re-establish participation in realtime sending and receiving. - -## Example - -```js -window.webxdc.setRealtimeListener((data) => { - console.log("Received realtime data: ", data); - const msg = new TextDecoder().decode(data); - console.log("decoded message: ", msg); -}) - -let pings = 0 -setInterval(() => { - const myId = window.webxdc.selfAddr; - const data = new TextEncoder().encode(`[${pings}] hello from ${myId}`); - pings += 1 - console.log("Sending message", data); - window.webxdc.sendRealtimeData(data); -}, 1000) -``` From 6aca2d2b6a2f7d22bda317211d92d6c79a8d5739 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 24 Apr 2024 08:53:37 +0200 Subject: [PATCH 20/23] address review feedback --- src-docs/spec/joinRealtimeSession.md | 61 +++++++++++++++------------- 1 file changed, 33 insertions(+), 28 deletions(-) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md index 35160a7..eff1911 100644 --- a/src-docs/spec/joinRealtimeSession.md +++ b/src-docs/spec/joinRealtimeSession.md @@ -1,62 +1,67 @@ -# joinRealtimeSession (experimental API as of April 2024) +# joinRealtimeChannel (experimental) ```js -const realtimeSession = window.webxdc.joinRealtimeSession((data) => {}); +const realtimeChannel = window.webxdc.joinRealtimeChannel(); ``` -Join an app-specific realtime session with chat peers and -return a `realtimeSession` object with `send` and `leave` methods. +Setup and return the realtime channel for this app, +with methods for listening and sending data as well as leaving the channel. +Per-app realtime channels are: -The callback receives `Uint8Array` data items that were sent from connected peers. +- **private**: No one outside the chat can participate in realtime channels. -Calling `joinRealtimeSession` while another `realtimeSession` is active -will not cause any action and returns a `null` value. +- **isolated**: apps can not participate in realtime channels of other apps. + +- **ephemeral**: any sent data will only be received by currently + connected peers but not by peers connecting later. -Any transmitted realtime data is +Calling `joinRealtimeChannel` a second time without leaving the prior one +will not cause any action and returns a `null` value. -- **private to the chat**: Only chat members can receive realtime data - and data can only be sent to connected chat members. +## `realtimeChannel.setListener((data) => {})` -- **scoped to the app**: different apps in a - chat can not discover or receive realtime data of other apps in the chat. +Start listening on the realtime channel using the specified callback. +The callback receives `Uint8Array` data items that were sent from connected peers. +Calling `setListener` a second time will replace the previous listener. -- **ephemeral**: any sent data will only be received by the currently - connected chat peers but not by peers joining later. -## `realtimeSession.send(data)` +## `realtimeChannel.send(data)` Send a `Uint8Array` data item to connected peers. There is no guarantee anyone is receiving sent data because there might be no currently listening peers, or network connections fail. -It is up to the app to determine connectivity status with other peers. +It is up to the app to determine connectivity status with other peers +by monitoring and triggering data messages. + -## `realtimeSession.leave()` +## `realtimeChannel.leave()` -Leave the realtime session and disconnect from all peers. -Afterwards the `realtimeSession` is invalid and +Leave the realtime channel. +Afterwards the `realtimeChannel` is invalid and can not be used anymore for sending or receiving data. -You need to call `window.webxdc.joinRealtimeSession()` -to re-initiate real time connectivity. +You need to call `window.webxdc.joinRealtimeChannel()` again +to re-join the per-app realtime channel. ## Example ```js -const realtimeSession = window.webxdc.joinRealtimeSession((data) => { +const realtimeChannel = window.webxdc.joinRealtimeChannel(); +realtimeChannel.setListener((data) => { console.log("Received realtime data: ", data); const msg = new TextDecoder().decode(data); console.log("decoded message: ", msg); }) -let pings = 0 +let numMsgs = 0 const refreshIntervalId = setInterval(() => { const myId = window.webxdc.selfAddr; - const data = new TextEncoder().encode(`[${pings}] hello from ${myId}`); - pings += 1 + const data = new TextEncoder().encode(`[${numMsgs}] hello from ${myId}`); + numMsgs += 1 console.log("Sending message", data); - realtimeSession.send(data); - if (pings >= 100) { - realtimeSession.leave(); + realtimeChannel.send(data); + if (numMsgs >= 100) { + realtimeChannel.leave(); clearInterval(refreshIntervalId); } From f99cca321c0552162d4c74ca8ef5617937016ac8 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 24 Apr 2024 16:01:30 +0200 Subject: [PATCH 21/23] Update src-docs/spec/joinRealtimeSession.md Co-authored-by: link2xt --- src-docs/spec/joinRealtimeSession.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeSession.md index eff1911..f128f52 100644 --- a/src-docs/spec/joinRealtimeSession.md +++ b/src-docs/spec/joinRealtimeSession.md @@ -8,7 +8,7 @@ Setup and return the realtime channel for this app, with methods for listening and sending data as well as leaving the channel. Per-app realtime channels are: -- **private**: No one outside the chat can participate in realtime channels. +- **private**: no one outside the chat can participate in realtime channels. - **isolated**: apps can not participate in realtime channels of other apps. From b6f78d4913e913e603215a69f9ea02799cc5132c Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 24 Apr 2024 16:01:08 +0200 Subject: [PATCH 22/23] rename file --- src-docs/SUMMARY.md | 2 +- .../spec/{joinRealtimeSession.md => joinRealtimeChannel.md} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src-docs/spec/{joinRealtimeSession.md => joinRealtimeChannel.md} (100%) diff --git a/src-docs/SUMMARY.md b/src-docs/SUMMARY.md index 556cb68..76ed3b5 100644 --- a/src-docs/SUMMARY.md +++ b/src-docs/SUMMARY.md @@ -10,7 +10,7 @@ - [sendToChat](./spec/sendToChat.md) - [importFiles](./spec/importFiles.md) - [selfAddr & selfName](./spec/selfAddr_and_selfName.md) - - [joinRealtimeSession](./spec/joinRealtimeSession.md) + - [joinRealtimeChannel](./spec/joinRealtimeChannel.md) - [Messenger implementations](./spec/messenger.md) - [Shared Web Application state](./shared_state/README.md) - [Detecting conflicts](./shared_state/conflicts.md) diff --git a/src-docs/spec/joinRealtimeSession.md b/src-docs/spec/joinRealtimeChannel.md similarity index 100% rename from src-docs/spec/joinRealtimeSession.md rename to src-docs/spec/joinRealtimeChannel.md From ac52c6f85dc79962bc9accb7d8772daf3315735b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kl=C3=A4hn?= <39526136+Septias@users.noreply.github.com> Date: Mon, 13 May 2024 21:10:58 +0200 Subject: [PATCH 23/23] add error to spec --- src-docs/spec/joinRealtimeChannel.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-docs/spec/joinRealtimeChannel.md b/src-docs/spec/joinRealtimeChannel.md index f128f52..f7fa6aa 100644 --- a/src-docs/spec/joinRealtimeChannel.md +++ b/src-docs/spec/joinRealtimeChannel.md @@ -16,7 +16,7 @@ Per-app realtime channels are: connected peers but not by peers connecting later. Calling `joinRealtimeChannel` a second time without leaving the prior one -will not cause any action and returns a `null` value. +will throw an error. ## `realtimeChannel.setListener((data) => {})`