Unreliable RTCDataChannel


I have a problem with big file transfers (> ~3MB). I am using only-udp WebRTCTransport. I create the DataProducer with the option ordered set to true (also, as documented the maxPacketLifeTime and maxRetransmits options are undefined).

For transmitting files, I split them to 64 KiB chunks and send them idividually. When the buffer hits 100KiB, I wait for the channel to send some chunks (80ms) and then I resume. The result is that the received messages are indeed in order, however not every message was received, which is contrary to the fact that datachannels are reliable.

Has anyone bumped into this issue? I experience this with both Chrome and Firefox.

Worth mentioning: in local it is working if I increase the waiting time, but it slows down the transfer significantly.

This is a known problem. Magic doe snot exist. mediasoup cannot buffer all data that receivers must receive.

  • Alice and Bob join the same mediasoup Router.
  • Alice create a WebRTC reliable DataProducer and Bob consumes its data by creating a WebRTC reliable DataConsumer.
  • Alice sends ton of data. Bob has poor downlink quality.
  • Eventually mediasoup (the SCTP stack) cannot send that many messages to Bob and its sending buffer gets filled so some messages are lost.

Workaround (the bad way)

Set a higher sctpSendBufferSize: mediasoup :: API

Proper solution

  • Create a DirectTransport in mediasoup and create a DataConsumer on it to consume from Alices WebRTC DataProducer`.
  • Create another DirectTransport and a fake DataProducer on it both associated to Bob (such a fake DataProducer is required due the design of producers and consumers).
  • Make the WebRTC DataConsumer of Bob consume from such a DataProducer instead of consuming from the original WebRTC DataProducer.
  • When a message is received in mediasoup by Alice’s direct DataConsumer, take the message and call dataConsumer.send(message or whatever) in the WebRTC DataConsumer of Bob.

And here the thing:

  • You must check the async result of dataConsumer.send() (see the API) and you must properly use the dataConsumer.getBufferedAmount() method and the dataConsumer.on(“bufferedamountlow”) event and buffer the messages in Node land (within your app) is needed, so if there is a memory leak it will be a failure in your Node app rather than in mediasoup.

PS: I know this is complex and that’s why this is gonna change in mediasoup v4 eventually, but unfortunately I cannot give more tips about this solution. Hope it helps.

Hi @ibc!

Sure, magic does not exist :slight_smile:! Thank you for your help, I will try to implement the proper solution.

When is the v4 is coming out? Just for consideration.

Anyway, I appreciate your fast reply and help. Thank you!

Not even planned.