Hello,
We have observed a case where an Android client can break the whole session by attempting to publish video with a slightly faulty configuration.
We used openvidu-android client as the basis for our app:
We made some customisations/optimisations. One of them was using hardware video encoder. However, when we tested the app with an Android phone that does not have HW video encoder, the following happened:
-
In Android client, creating local description succeeded but setting it as the local description failed.
-
The created SDP was missing necessary fields. For example, there was
m=video 9 UDP/TLS/RTP/SAVPF 0
, while a successful SDP contains something like
m=video 9 UDP/TLS/RTP/SAVPF 96 100
, and there are also more lines that describe 96 and 100 as video codec options. -
Despite of the failure, the example code proceeded to attempt to publish video.
-
The client appeared in the session, without video. However, it also caused the following:
- various errors in server and client logs
- every participant’s video streams got stuck
- the session could not be properly closed (it became a ghost session, required OpenVidu server reboot to clear it)
Client errors:
code -1: org.kurento.client.internal.server.KurentoServerException:Connection with server have been closed
code 303: Unable to create subscriber endpoint. Code: 303
Server errors:
[nioEventLoopGroup-3-1] org.kurento.jsonrpc.client.JsonRpcClientNettyWebSocket - channel closed
[AbstractJsonRpcClientWebSocket-disconnectExec-e4-t0] org.kurento.jsonrpc.client.AbstractJsonRpcClientWebSocket - Exception trying to reconnect to server ws://localhost:8888/kurento. Notifying disconnection
org.kurento.jsonrpc.JsonRpcException: Exception connecting to WebSocket server ws://localhost:8888/kurento
openvidu-server_1 | at org.kurento.jsonrpc.client.AbstractJsonRpcClientWebSocket.internalConnectIfNecessary(AbstractJsonRpcClientWebSocket.java:735)
openvidu-server_1 | at org.kurento.jsonrpc.client.AbstractJsonRpcClientWebSocket.connectIfNecessary(AbstractJsonRpcClientWebSocket.java:847)
openvidu-server_1 | at org.kurento.jsonrpc.client.AbstractJsonRpcClientWebSocket$16.run(AbstractJsonRpcClientWebSocket.java:635)
openvidu-server_1 | at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
openvidu-server_1 | at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
openvidu-server_1 | at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
openvidu-server_1 | at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
openvidu-server_1 | at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
openvidu-server_1 | at java.base/java.lang.Thread.run(Thread.java:829)
openvidu-server_1 | Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:8888
openvidu-server_1 | Caused by: java.net.ConnectException: Connection refused
openvidu-server_1 | at java.base/sun.nio.ch.SocketChannelImpl.checkConnect(Native Method)
openvidu-server_1 | at java.base/sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:777)
openvidu-server_1 | at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:330)
openvidu-server_1 | at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:334)
openvidu-server_1 | at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:707)
openvidu-server_1 | at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:655)
openvidu-server_1 | at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:581)
openvidu-server_1 | at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
openvidu-server_1 | at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
openvidu-server_1 | at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
openvidu-server_1 | at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
openvidu-server_1 | at java.base/java.lang.Thread.run(Thread.java:829)
Etc. etc.
We have created a fix for the Android client, which should check if setting local description has failed:
However, a single client should not be able to crash a complete session like that. The server side code probably needs modifications, too.
Here’s an example of an SDP from an attempt to publish video that resulted to session crash. The client claims that it will publish video, but the SDP does not have any video codecs:
v=0
o=- 7719772216287633120 2 IN IP4 127.0.0.1
s=-
t=0 0
a=group:BUNDLE 0 1
a=msid-semantic: WMS
m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 102 0 8 106 105 13 110 112 113 126
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:c2WV
a=ice-pwd:GZ7nmy4N6x4Ca63YsFIPmJjj
a=ice-options:trickle renomination
a=fingerprint:sha-256 [REMOVED]
a=setup:actpass
a=mid:0
a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:- 101
a=rtcp-mux
a=rtpmap:111 opus/48000/2
a=rtcp-fb:111 transport-cc
a=fmtp:111 minptime=10;useinbandfec=1
a=rtpmap:103 ISAC/16000
a=rtpmap:104 ISAC/32000
a=rtpmap:9 G722/8000
a=rtpmap:102 ILBC/8000
a=rtpmap:0 PCMU/8000
a=rtpmap:8 PCMA/8000
a=rtpmap:106 CN/32000
a=rtpmap:105 CN/16000
a=rtpmap:13 CN/8000
a=rtpmap:110 telephone-event/48000
a=rtpmap:112 telephone-event/32000
a=rtpmap:113 telephone-event/16000
a=rtpmap:126 telephone-event/8000
a=ssrc:2314895369 cname:9Vpk6URscoMETSuX
a=ssrc:2314895369 msid:- 101
a=ssrc:2314895369 mslabel:-
a=ssrc:2314895369 label:101
m=video 9 UDP/TLS/RTP/SAVPF 0
c=IN IP4 0.0.0.0
a=rtcp:9 IN IP4 0.0.0.0
a=ice-ufrag:c2WV
a=ice-pwd:[REMOVED]
a=ice-options:trickle renomination
a=fingerprint:sha-256 [REMOVED]
a=setup:actpass
a=mid:1
a=extmap:14 urn:ietf:params:rtp-hdrext:toffset
a=extmap:2 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
a=extmap:13 urn:3gpp:video-orientation
a=extmap:3 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
a=extmap:12 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
a=extmap:11 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/color-space
a=extmap:4 urn:ietf:params:rtp-hdrext:sdes:mid
a=extmap:5 urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
a=extmap:6 urn:ietf:params:rtp-hdrext:sdes:repaired-rtp-stream-id
a=sendonly
a=msid:- 100
a=rtcp-mux
a=rtcp-rsize
a=ssrc:4108384921 cname:9Vpk6URscoMETSuX
a=ssrc:4108384921 msid:- 100
a=ssrc:4108384921 mslabel:-
a=ssrc:4108384921 label:100