[Rust] Confusion about DataConsumers & DataProducers

Hello there,

I’m having some trouble setting up DataConsumers/DataProducers, here is what i’m trying to have:
I want to be able to send messages to a peer from Rust.

This is what I’ve done:
Created a DataProducer on a DirectTransport, so I can use the send() method.

let data_producer_options = mediasoup::data_producer::DataProducerOptions::new_direct();
let inner_data_producer = self
    .inner
    .direct_transport
    .produce_data(data_producer_options)
    .await?;

Then on the peer’s recv transport I created a DataConsumer

let inner_data_consumer = self
    .inner
    .webrtc_transport // The peer's RecV Transport
    .consume_data(
        mediasoup::data_consumer::DataConsumerOptions::new_sctp_ordered(
            inner_data_producer_id, // Id of the DataProducer I created earlier
        ),
     )
     .await?;

But I’m getting this runtime error when I call the consume_data method:

Request(Response { reason: "missing sctpStreamParameters [method:transport.consumeData]" }))

And I don’t get why it is asking me for some sctpStreamParameters :sweat_smile:, as the DataProducer was created on a direct transport it doesn’t have sctpStreamParameters? And I can’t use a DataProducer created on a Regular Transport because the DataProducer wouldn’t have a send() method, so I’m a bit confused on what I’m doing wrong here. I thought about creating a DataProducer on a direct transport and trying to consume it on the client but the client need sctpStreamParameters that the DirectDataProducer doesn’t have.

This works as expected in Node following the exact rationale and flow you said.

@nazar-pc perhaps a bug in Rust layer?

I just checked, while code is different, logic is the same: unless consumer is created on direct transport, implementation clones SCTP stream parameters from producer and does some tweaking to it. SCTP parameters themselves are an optional type, but expected for non-direct transport.

So what happens here is that your consumer transport is not direct, it needs SCTP parameters, but producer is on direct transport and doesn’t have them. I believe it will fail the same exact way in TypeScript too, I was translating logic from TypeScript in Rusty way, but at the same time following mechanics quite literally.

That’s what I gathered from reading the code, but then I don’t understand how I’m supposed to send a message to a peer, because a RegularDataProducer doesn’t have a send() method

I’m afraid that’s not correct. transport.consumeData() never requires sctpParameters. Those are generated by mediasoup in the returned DataConsumer and they are generated based on sctpParameters of the DataProducer. If the DataProducer is “direct” (it was created on a DirectTransport) the mediasoup generates sctpParameters for the non direct DataConsumer with appropriate values.

Indeed, I was deceived by clone in https://github.com/versatica/mediasoup/blob/7c04642c374b9ee78e46728b8f8fb5e2e27f57ff/node/src/Transport.ts#L866-L867, it not only clones objects, it returns {} for non-objects (like undefined). In fact it can send SCTP parameters with just streamId, which from Rust point of view is not a valid invariant, you need to set ordered to either true or false at very least.

I see how this can be fixed, will send a PR fix fix for this.

1 Like

This should fix it: Fix consuming data producer from direct transport by data consumer on non-direct transport by nazar-pc · Pull Request #1012 · versatica/mediasoup · GitHub