Closed yuma-m closed 3 years ago
I assume you are using Trickle ICE.
Need to check the RFCs and the masters behavior to understand what's right.
One NOTE: I assume you are using the stock samples without any modifications - please confirm.
Hi @MushMal,
Thank you for your support. I didn't modify either C SDK or Android SDK, so I assume Trickle ICE is used.
Looking at the code I see that in case of Trickle ICE we do properly serialize the messages. First, we send the answer, next we spin up a timerqueue to handle the ice candidates.
However, we have an optimization by which if we have pending ice candidates, we immediately start sending those:
This can only happen if the viewer is using the same peerID in a multiple offers. If the peer (viewer) can not handle the ice candidates which we already have gathered in the previous session then it's OK, those candidates should be generated again in the new sessions ICE gathering.
This should affect latency only.
The other question is why in your experiments you are sending multiple offers? What scenario are you trying?
@yuma-m I am still not sure whether this will end up dropping the local/rflx candidates and why. Can you do a simple experiment by commenting these lines: https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c/blob/master/samples/Common.c#L1086-L1096
@MushMal I just tried connection between a C SDK peer and an Android SDK peer a few times and happened to reproduce this issue.
Is the order of messages kept? I confirmed C SDK sent SDP answer before sending any ICE candidate, but Android SDK received ICE candidate before SDP answer. I have the logs of both SDK and can share it if you need.
C SDK logs
2020-12-14 11:29:37 DEBUG writeLwsData(): Sending data over web socket: {
"action": "SDP_ANSWER",
"RecipientClientId": "f8ecae19-ce16-4b54-a6d0-4a870ea5e9da",
"MessagePayload": "eyJ0eXBlIjogIm..."
}
...
2020-12-14 11:29:37 DEBUG iceAgentLogNewCandidate(): New local ice candidate discovered. Id: a05KL2bPM. Ip: 172.31.22.0:52030. Type: host. Protocol: UDP.
2020-12-14 11:29:37 INFO signalingClientSendMessageSync(): Signaling Client Sending Message Sync
2020-12-14 11:29:37 DEBUG writeLwsData(): Sending data over web socket: {
"action": "ICE_CANDIDATE",
"RecipientClientId": "f8ecae19-ce16-4b54-a6d0-4a870ea5e9da",
"MessagePayload": "eyJjYW5kaWRhdGUiOiJjYW5kaWRhdGU6MCAxIHVkcCAyMTMwNzA2NDMxIDE3Mi4zMS4yMi4wIDUyMDMwIHR5cCBob3N0IHJhZGRyIDAuMC4wLjAgcnBvcnQgMCBnZW5lcmF0aW9uIDAgbmV0d29yay1jb3N0IDk5OSIsInNkcE1pZCI6IjAiLCJzZHBNTGluZUluZGV4IjowfQ=="
}
...
2020-12-14 11:29:37 DEBUG iceAgentLogNewCandidate(): New local ice candidate discovered. Id: 3/Vneri9L. Ip: 18.179.59.214:43733. Type: srflx. Protocol: UDP.
2020-12-14 11:29:37 INFO signalingClientSendMessageSync(): Signaling Client Sending Message Sync
2020-12-14 11:29:37 DEBUG writeLwsData(): Sending data over web socket: {
"action": "ICE_CANDIDATE",
"RecipientClientId": "f8ecae19-ce16-4b54-a6d0-4a870ea5e9da",
"MessagePayload": "eyJjYW5kaWRhdGUiOiJjYW5kaWRhdGU6MSAxIHVkcCAxNjk0NDk4ODE1IDE4LjE3OS41OS4yMTQgNDM3MzMgdHlwIHNyZmx4IHJhZGRyIDAuMC4wLjAgcnBvcnQgMCBnZW5lcmF0aW9uIDAgbmV0d29yay1jb3N0IDk5OSIsInNkcE1pZCI6IjAiLCJzZHBNTGluZUluZGV4IjowfQ=="
}
Android SDK Logs
D/CustomMessageHandler: Received message{"messagePayload":"eyJjYW5kaWRhdGUiOiJjYW5kaWRhdGU6MCAxIHVkcCAyMTMwNzA2NDMxIDE3Mi4zMS4yMi4wIDUyMDMwIHR5cCBob3N0IHJhZGRyIDAuMC4wLjAgcnBvcnQgMCBnZW5lcmF0aW9uIDAgbmV0d29yay1jb3N0IDk5OSIsInNkcE1pZCI6IjAiLCJzZHBNTGluZUluZGV4IjowfQ==","messageType":"ICE_CANDIDATE"}
D/CustomMessageHandler: Ice Candidate received: SenderClientId=null
{"candidate":"candidate:0 1 udp 2130706431 172.31.22.0 52030 typ host raddr 0.0.0.0 rport 0 generation 0 network-cost 999","sdpMid":"0","sdpMLineIndex":0}
D/KVSWebRtcActivity: Received IceCandidate from remote
D/KVSWebRtcActivity: Added ice candidate 0:0:candidate:0 1 udp 2130706431 172.31.22.0 52030 typ host raddr 0.0.0.0 rport 0 generation 0 network-cost 999: Failed
...
D/CustomMessageHandler: Received message{"messagePayload":"eyJ0eXBlIjogIm...
D/CustomMessageHandler: Answer received: SenderClientId=null
D/KVSWebRtcActivity: SDP answer received from signaling
D/Event: SDP answer received from master:v=0
...
D/CustomMessageHandler: Received message{"messagePayload":"eyJjYW5kaWRhdGUiOiJjYW5kaWRhdGU6MSAxIHVkcCAxNjk0NDk4ODE1IDE4LjE3OS41OS4yMTQgNDM3MzMgdHlwIHNyZmx4IHJhZGRyIDAuMC4wLjAgcnBvcnQgMCBnZW5lcmF0aW9uIDAgbmV0d29yay1jb3N0IDk5OSIsInNkcE1pZCI6IjAiLCJzZHBNTGluZUluZGV4IjowfQ==","messageType":"ICE_CANDIDATE"}
Ice Candidate received: SenderClientId=null
D/CustomMessageHandler: {"candidate":"candidate:1 1 udp 1694498815 18.179.59.214 43733 typ srflx raddr 0.0.0.0 rport 0 generation 0 network-cost 999","sdpMid":"0","sdpMLineIndex":0}
D/KVSWebRtcActivity: Received IceCandidate from remote
D/KVSWebRtcActivity: Added ice candidate 0:0:candidate:1 1 udp 1694498815 18.179.59.214 43733 typ srflx raddr 0.0.0.0 rport 0 generation 0 network-cost 999: Successfully
Messages should be delivered in order. Need to understand what's going on. Adding the logs might be useful (with log level = VERBOSE).
If this behavior actually happens, it will violate the following section.
https://datatracker.ietf.org/doc/html/draft-ietf-mmusic-trickle-ice-02#section-9.2
Obviously, agents MUST NOT send individual candidates prior to generating the corresponding SDP session description.
KVS does not guarantee in-order delivery of signaling messages. Due to processing time, dependencies, and network it is a best effort delivery.
Obviously, agents MUST NOT send individual candidates prior to generating the corresponding SDP session description.
The line linked from the RFC has specifications regarding the sending with the context of encoding the SDP, but not the delivery of those messages.
Were you able to confirm that the candidates that arrived before the SDP answer were dropped? You could run an experiment where you could disable relay candidates and see if there is connectivity from the candidate that arrived before the SDP answer.
A fix for this could be to "hold" that ICE candidate on the client side and wait to process it until the SDP answer is received.
@hatimkha aside from the network packet level issue, does the backend guarantee the ordering?
In the C webrtc SDK samples we do hold the ICE candidates but none of this happens in any other SDKs/samples.
@MushMal No, because message processing can be affected by our dependencies such as by cold start time or DDB latency. In general they should be in order but we do not provide strict guarantees.
Were you able to confirm that the candidates that arrived before the SDP answer were dropped?
@hatimkha I could only confirm the logs from Android SDK: Added ice candidate ... Failed
and Added ice candidate ... Successfully
. Are there any way to confirm whether it is actually dropped or not?
A fix for this could be to "hold" that ICE candidate on the client side and wait to process it until the SDP answer is received.
@MushMal Do you know why it is implemented in C SDK? Should it be implemented in other SDKs?
@yuma-m this must be implemented in the other SDK samples too. This is a sample-level handling of the discrepancy as we are not in the control of the actual WebRTC implementation on these platforms.
We will resolve this issue once we cut Enhancement issues in each of these repositories. The work will be properly scheduled and prioritized
Closing since an enhancement ticket is created.
https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-android/issues/47
Environment
kvsWebrtcClientMaster
, hash:5bc99c0fb
)a6da101
)When Android SDK receives ICE candidate before receiving SDP answer, it fails to add ICE candidate. (
Added ice candidate ... Failed
line below)After receiving SDP answer, it succeeds to add ICE candidate. (
Added ice candidate ... Successfully
line below)Does this behavior affect the Android SDK to ignore the ICE candidate which is received before SDP answer (maybe local or srflx candidate) and tend to choose relay candidate?