Skip to content
José Luis Millán edited this page Jun 8, 2019 · 40 revisions

Here the roadmap for adding DataChannel support to mediasoup. It includes a preliminary architecture design among other considerations (below) such as implementation details.

Architecture

The DataChannel design and exposed API must follow the principles of the already exiting audio/video Producer and Consumer design in mediasoup v3. So, the DataChannel design must conform to the following requirements:

  • The DataChannel message unit is a SCTP packet (in the same way, the message unit in audio/video is a RTP packet).

  • There must two new classes: DataProducer and DataConsumer (in both mediasoup server and mediasoup-client).

    • A DataProducer represents a data channel source being injected into a mediasoup router. It's created on top of a transport that defines how the SCTP packets are carried.
    • DataProducers are created using the already existing transport.produce() JavaScript API with new arguments.
    • A DataConsumer represents a data channel source being forwarded from a mediasoup router to an endpoint. It's created on top of a transport that defines how the SCTP packets are carried.
    • DataConsumers are created using the already existing transport.consume() JavaScript API with new arguments.
  • STCP messages can be injected into a mediasoup router on top of a WebRtcTransport (so STCP over DTLS over UDP/TCP) and also on top of a PlainRtpTransport (so SCTP over UDP).

    • NOTE: We may want to rename PlainRtpTransport to PlainTransport.
  • Similar to audio/video Producers and Consumers, it must be possible for the Node.js app running mediasoup to decide which endpoints consume (by means of a DataConsumer) from a specific DataProducer. Once a DataConsumer is created, the Router (at C++ level) will route to it data messages from the associated DataProducer.

  • It must be possible for the Node.js app (the application that integrates mediasoup lib and uses its JS API) to inject data messages into a mediasoup router so those messages are routed to endpoints via WebRTC DataChannel. And vice-versa: the Node.js app must be able to receive data messages sent by endpoints to the mediasoup router. To do it, the Node.js app:

    • must create a PlainRtpTransport in the mediasoup router,
    • must call produce() on it with appropriate arguments to create a DataProducer instance,
    • must create a UDP+SCTP client that sends (and/or receives) SCTP packets (with the announced id) to the IP:port of the previously created mediasoup PlainRtpTransport.
  • Such a "UDP+SCTP client" could be a Node.js library/module which, for example, uses the Node.js UDP stack plus the node-sctp or @nodertc/sctp Node.js libraries.

    • Of course, we (the mediasoup team) will provide developers with such a client, probably as a separate library.
    • The node-sctp can, indeed, send SCTP packets over UDP: example.

Implementation at C++ level

The WebRtcTransport of mediasoup already has an (unused yet) API to send and receive DTLS application data:

(we would add the same OnDtlsApplicationData callback into the PlainRtpTransport for SCTP over UDP).

So we need to plug a C++ SCTP stack to handle SCTP packets. It would be done within a new C++ class named SctpHandler or whatever.

As per now there are three C or C++ SCTP stacks out there we can consider:

  • medooze/libdatachannels, whose API is exactly what we need (single thread, and provides an API to send and receive packets by letting the external application manage the socket, timers, the DTLS, etc). Unfortunately it's nor finished neither active.

  • sctplab/usrsctp, the "SCTP stack". Used by libwebrtc, Janus among many others. Problems:

    • It's multi-thread (question). We need a single-thread stack.
    • There is a Pull Request that makes it single thread, but was not merged.
    • Then @lgrahl said "No need to wait, you can use usrsctp-neat which will be merged back eventually", but that did never happen.
    • I also do not like the idea of integrating a library with more than 50 open issues, some of them definitively relevant as a memory leak.
    • It does not provide a GYP file, so we should do it (plus PR of course).
  • And then there is rawrtc/rawrtc-data-channel, which is a layer on top of usrsctp which, somehow, hiddes its multi-thread nature. Problems:

    • It depends on usrsctp, so same concerns as above apply (however my concerns could be wrong).
    • It also depends on re and rew C libraries (due the usage of some helpers and utils included in them). Not a super big problem, but I don't like the idea of having mediasoup depend on a C library that implements SIP, WebSocket, DNS, HTTP, etc.
    • It depends on meson and ninja for the building stage. This is a no-go for mediasoup. Users of mediasoup are supposed to just run npm install mediasoup and they are done. The "postinstall": "make -C worker" in package.json builds the mediasoup C++ code and its C/C++ deps (included in the source) by using gyp (which is also included in the package). All C/C++ dependencies of mediasoup include GYP files.
    • In other words, we should create GYP files for rawrtc-data-channel, usrsctp, re and rew libraries...

Specifications

Clone this wiki locally