mediasoup-ios-client
mediasoup-ios-client copied to clipboard
RecvTransport disconnects on .consume()
Whenever a new user joins the room and I connect the consumer logic via
guard let consumer = self.recvTransport?
.consume(self.consumerHandler,
id: id,
producerId: producerId,
kind: kind.rawValue,
rtpParameters: rtpParameters.description,
appData: appData.description) else { l.error("recvTransp consume failed");return }
The delegated transport-handler disconnects and reconnects for every new consumer. This doesn't happen with our web client, and probably shouldn't happen here.
2020-08-19 19:14:29.742 ⚪️ [RecvTransportHandler.swift:28] ** Recv Con change: disconnected
2020-08-19 19:14:30.051 ⚪️ [RecvTransportHandler.swift:28] ** Recv Con change: checking
2020-08-19 19:14:30.051 ⚪️ [RecvTransportHandler.swift:28] ** Recv Con change: connected
2020-08-19 19:14:30.052 ⚪️ [RecvTransportHandler.swift:28] ** Recv Con change: completed
Could you check if there's maybe something in your -(Consumer *)consume:(id<ConsumerListener>)listener id:(NSString *)id producerId:(NSString *)producerId kind:(NSString *)kind rtpParameters:(NSString *)rtpParameters appData:(NSString *)appData; implementation that would cause the transport to disconnect-checking-connected-completed every time it's called?
Sorry, will take a look when I get time. ><
Hi can you share how you handled group chat
I've faced same behaviour and found a workaround.
If you set a breakpoint inside the onConnectionStateChange, you'll see that all nonsense delegate calls are made during recvTransport.consume or sendTransport.produce calls.
Both methods are not really reentrant anyway (actual methods bodies are wrapped into a critical section), so we can put both of them onto a separate serial queue without any side effects. Then we asynchronously put onConnectionStateChange body onto same serial queue. Inside onConnectionStateChange handler body we don't use the incoming parameter, but read actual state from sendTransport or recvTransport itself. So we have a guarantee that we never read transport state during producer/consumer creation. To avoid checking the transport state 4-5 times after each consumer creation, I use additional willCheckTransportState flag.
Whole example would be too long, but here are some highlights:
func produce() {
transportCreationQueue.async { [weak self] in
...
producer = sendTransport.produce(...)
...
}
}
func consume() {
transportCreationQueue.async { [weak self] in
...
consumer = recvTransport.consume(...)
...
}
}
public func onConnectionStateChange(_ transportId: String, connectionState: String) {
...
if !self.willCheckTransportState {
self.willCheckTransportState = true
transportCreationQueue.async {
self.checkTransportState()
self.willCheckTransportState = false
}
}
}
@fedulvtubudul Can you elaborate on your last message?
@GEverding you can't rely on the connectionState value that is passed into onConnectionStateChange callback. While producers and consumers are created, this method may be called with all possible state values. But each time it "settles down" on the actual state. To have a reliable connection state value, you should avoid reading connection state value while a consumer or producer is being started. So you put producer/consumer creation onto a serial queue, and access the connection state only from the same serial queue, but not from onConnectionStateChange method.