Communication Interfaces
DATEX communication is not restricted to a specific underlying communication channel.
DATEX blocks can be transmitted via WebSockets, TCP, WebRTC, HTTP or with Channel Messaging between browser workers or windows.
The DATEX JS Library provides a CommunicationInterface
API which allows the implementation of other custom communication channels.
Connecting communication interfaces
When calling Supranet.connect()
, the DATEX Runtime automatically creates a connection with a communication interface.
Per default, WebSocket communication interfaces for public unyt.org relay endpoints (https://unyt.cc/nodes.dx) are used.
To establish a connection over another communiction channel, you need to create a new instance of the corresponding CommunicationInterface
and add it to the communicationHub
:
import { WebSocketClientInterface } from "datex-core-legacy/network/communication-interfaces/websocket-client-interface.ts";
import { communicationHub } from "datex-core-legacy/network/communication-hub.ts";
// create a new WebSocketClientInterface connected to wss://example.com
const webSocketInterface = new WebSocketClientInterface("wss://example.com");
// add the interface to the communication hub
const connected = await communicationHub.addInterface(webSocketInterface)
// true if connection could be establised:
console.log("connected:", connected);
The interface constructor signature can be different for other communication interfaces, but everything else works the same way.
Builtin commmunication interfaces
WebSocket
HTTP
Worker
Window
DATEX provides a simple communication interface that makes use of the globalThis.postMessage() API to enable cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.
The WindowInterface.createWindow
method can open a window (page, popup or tab) and behaves similar to the globalThis.open API with the difference that it is asynchronously and returns an object including the remote endpoint (the endpoint of the popup) and the actual Window containing the DOM document.
import { WindowInterface } from "datex-core-legacy/network/communication-interfaces/window-interface.ts";
const { endpoint, window } = await WindowInterface.createWindow(
"https://popup.com", // URL of our window
"MyWindow", // Target specifying the name of the context
`popup=yes` // Window feature list
);
The window site can connect to the host window by creating a parent interface via WindowInterface.createParentInterface
:
const parentInterface = WindowInterface.createParentInterface(
globalThis.opener, // Parent window instance (app)
"https://myapp.com" // URL of the parent window (app)
);
// The connection event is fired if we got a response from the app
parentInterface.addEventListener("connect", (event) => {
// connection is established
// event.endpoint gives us the endpoint of the host side
});
When the createWindow
call of the parent did resolve, all DATEX traffic of the host side directed to the endpoint of the window is directly routed via postMessage API without using the network layer.
The createWindow
utility is a wrapper method that opens the new window by passing it's URL and registers the attached WindowInterface. It automatically handles the removal of the interface when the window is closed. We can also manually create and register the interface via WindowInterface.createChildWindowInterface
by passing the window object and the window origin URL. In this case we need to make sure to remove the interface on window close.
const url = new URL("https://popup.com");
const myWindow = globalThis.open(url);
const windowInterface = WindowInterface.createChildWindowInterface(myWindow, url);
const connected = await communicationHub.addInterface(windowInterface);
IFrame
The DATEX API for IFrame communication behaves pretty similar to the window API.
We can pass an iframe from the host side to the WindowInterface.bindIFrame
call together with an optional connection timeout:
const endpoint = await WindowInterface.bindIFrame(
iframe, // Iframe DOM element
10_000 // optional timeout
);
The DATEX API inside of the IFrame can establish the interface to the host similar to the window using WindowInterface.createParentInterface
.
WebRTC
Legend
Establishing a WebRTC connection
To establish a WebRTC connection between two endpoints, each endpoint first gets its own public IP address from a STUN Server (Step 1 and 3).
The two endpoints then negotiate a session by exchanging SDP offers and answers (Step 2 and 4). The DATEX WebRTC communication interface does not require an explicit signaling server. Instead, SDP negotation happens directly between the two endpoints via DATEX (this might require a relay endpoint, which could be regarded as a kind of signaling server).
The negotiated session can either use a direct or an indirect connection via a TURN server.
Direct WebRTC connection
If the two clients are in the same network or if NAT traversal is possible using public ip addresses of the two clients, a direct connection can be established:
Indirect WebRTC connection
As a fallback, WebRTC connections are relayed using a public TURN server.
WebRTC data exchange
Once a connection is established, it can be used to transmit video or audio streams, as well as DATEX blocks using a data channel.
MediaStream
tracks are transmitted directly via WebRTC, any other data is transmitted via the DATEX data channel.
Implementing custom communication interfaces
Help us improving our docs
Our documentations are fully open source. Something is wrong or unclear?