versatica / libmediasoupclient

mediasoup client side C++ library

Home Page:https://mediasoup.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

DataProducer call RegisterObserver too late and may lose event

binxie33 opened this issue · comments

In Transport.cpp, DataProducer is constructed with parameter dataChannelId.get(), this will force the DataProducer to be constructed after the datachannel is created. In the DataProducer constuctor it will register RegisterObserver, but this may be too late and this may cause the datachannel open event to be lost.


auto dataProducer = new DataProducer(
		  this,
		  dataProducerListener,
		  dataChannelId.get(),
		  sendResult.dataChannel,
		  sendResult.sctpStreamParameters,
		  appData);

This is the debug log I captured when the issue happened:

[TRACE] DataProducer::mediasoupclient::DataProducer::DataProducer()
(thread.cc:668): Message took 157ms to dispatch. Posted from: webrtc::JsepTransportController::UpdateAggregateStates_n@../../pc/jsep_transport_controller.cc:1489
(thread.cc:668): Message took 157ms to dispatch. Posted from: webrtc::JsepTransportController::UpdateAggregateStates_n@../../pc/jsep_transport_controller.cc:1489
(peer_connection.cc:4717): Changing standardized IceConnectionState 2 => 3
(peer_connection.cc:4717): Changing standardized IceConnectionState 2 => 3
(data_channel.cc:575): DataChannel::SetState 1
(data_channel.cc:575): DataChannel::SetState 1
(data_channel.cc:583): DataChannel observer_ is not set 
(data_channel.cc:583): DataChannel observer_ is not set 
(data_channel.cc:234): DataChannel::RegisterObserver
(data_channel.cc:234): DataChannel::RegisterObserver
[TRACE] DataProducer::mediasoupclient::DataProducer::GetId()
[TRACE] DataProducer::mediasoupclient::DataProducer::GetLabel()

Propsoed Fix:

Manually called this->OnStateChange() in DataProducer constructor

	DataProducer::DataProducer(
	  DataProducer::PrivateListener* privateListener,
	  DataProducer::Listener* listener,
	  const std::string& id,
	  rtc::scoped_refptr<webrtc::DataChannelInterface> dataChannel,
	  const json& sctpStreamParameters,
	  const json& appData)
	  : privateListener(privateListener), listener(listener), id(id), dataChannel(dataChannel),
	    sctpStreamParameters(sctpStreamParameters), appData(appData), closed(false)
	{
		MSC_TRACE();

		this->dataChannel->RegisterObserver(this);
		// need to manually call OnStateChange once since RegisterObserver maybe too late
		this->OnStateChange();
	};

Hi @binxie33,

It may happen that before the Transport::OnProduceData() callback returns something like the state change happens in the datachannel as you see. In this case the observer is not yet added to the datachannel.

In this case, if you need it, you may just call DataProducer->GetReadyState() once you get the DataProducer out of Transport.ProduceData().

If you need to make sure no application data is received to the client until the app is ready for processing it, you may want to acknowledge your server app of the fact that you are ready to receive data once Transport.ProduceData() has returned the DataProducer.