DataProducer/DataConsumer feature parity

Hi, I’m working with WebRTC DataChannel for an application that performs reception and sending of data directly to/from the app itself, respectively. And found a bit of confusing lack of symmetry in DataProducer/DataConsumer features, so let me ask about it:

A DataProducer:

  1. Lacks an event DataProducer.on("message", fn(message, ppid)) in SCTP transports. This could be useful to receive ingress data from a remote peer directly into the app. It would seem like there isn’t actually any technical reason to force it passing through the router towards a DataConsumer’s "message" event, is it?

  2. Has a method DataProducer.send(message, ppid) in DirectTransports. Used to inject data from the app into the router.

A DataConsumer:

  1. Has an event DataConsumer.on("message", fn(message, ppid)) in DirectTransports. Used to extract data from the router into the app.

  2. Also has a method DataConsumer.send(message, ppid) in SCTP transports. Useful to send egress data from the app directly to a remote peer.

Either the existence of (4) or the lack of (1) is what confused me (and I bet more users). I think there’s no harm in having more options instead of less, so would it make sense to consider adding (1) as a feature?

Extra question: Given that DataConsumer has DataConsumer.send(message, ppid) in SCTP transports, looks like it might make sense that it was able to work standalone and send data generated by the application, regardless of any DataProducer.

Would it make sense that mediasoup allowed just creating a DataConsumer without passing a DataProducer id (DataConsumerOptions.dataProducerId)? After all, if the need is only to egress in-app-generated SCTP data, no DataProducer is needed at all. Otherwise, a dummy of fake one can always be created, I guess.

All those are valid topics that we are aware of already. Thunders were added (such as DataConsumer.send) to optimize things and the resulting API become hell.

DataConsumer.send() was added to allow the app to send a message just to that endpoint regardless that DataConsumer is connected to a DataProducer that is connected to many other DataConsumers.

DataProducer doesn’t have a “message” event because that would involve that every datachannel message received by the worker must be routed to Node (via the UnixSocket) channel just in case the app added an event listener in the Node layer. That would be bad for performance.

And in flatbuffers branch (so soon in v3) we have added “subchannels” to dynamically decide which DataConsumers should receive a message sent by DataProducer.send() in server side (see Next section in CHANGELOG in flatbuffers branch).

Summary: all this is gonna be reconsidered from scratch for v4 but we cannot break things in v3 or add more controversial API just to make it more symmetric.

1 Like

Amazing. Thanks for the context and explanations.

Coincidentally, I was just now reading this,

So I was starting to think that you’d rather leave it as is until a later refactoring. Still, very good to know all the info, thanks again.