-
Notifications
You must be signed in to change notification settings - Fork 189
Add gathering generation extension to candidates #874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
agent.go
Outdated
| if prevState == GatheringStateGathering { | ||
| a.candidateNotifier.EnqueueCandidate(nil) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a slight departure from the previous behavior that was part of the base patch from @JoTurk
I'm not sure if this behavior (only send nil candidate when transitioning from Gathering to Complete) is more correct, or if we should keep the original behavior (send nil candidate anytime we transition into the Complete state)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, the reason i added this is because i just wanted to make the test pass (because the previous pr did close => complete), but sending nil regardless is correct i think.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is because we don't go to complete from close, like in the previous pr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I'm reading this right it looks like the previous behavior of sending the nil candidate anytime we enter Complete as long as the previous state wasn't also Complete is in line with Chrome's behavior.
|
Converted to draft since I missed that I should be piping generation through the call stack from |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #874 +/- ##
==========================================
- Coverage 88.27% 88.18% -0.09%
==========================================
Files 43 43
Lines 5509 5544 +35
==========================================
+ Hits 4863 4889 +26
- Misses 451 458 +7
- Partials 195 197 +2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
Thank you I'll check again how chrome and firefox handle generations and review this. this pr is continuation of pion/webrtc#3113 |
8b913a0 to
6f163a5
Compare
| generationChan <- newGen | ||
| }) | ||
| generation := <- generationChan | ||
| a.gatherCandidatesInternal(ctx, generation) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoTurk thoughts on this? It feels a bit janky, but I wasn't sure of a cleaner way. I'm assuming that re-triggering candidate gathering because of a network change should trigger a new generation. If not then I can revert this, but if so I'm open to recommendations on cleaner ways to run the bump and then gather candidates again, I didn't want to run the actual gatherCandidatesInternal method within the agent lock/loop as that seems like a major change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not entirely sure, since browsers don't do continual gathering and there isn't really a standard behavior to reference here. But I think this makes sense, we don't want the remote side attempting to connect to candidates before a network change. Also it's a way to signal that a gather did happen and how many gathers happend.
Kinda relates to this pion/webrtc#3323
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should bump the generation during continual gathering. Network changes can be additive, for example, if a peer on a mobile network connects to wifi, a new path becomes available while the old one remains valid. We want to allow the ICE agent to smoothly renominate the better path without tearing down the session.
My understanding is that generations are useful for hard resets, like ice restarts where credentials change, rendering previous candidates invalid. Since continual gathering uses existing credentials, the generation id must remain the same.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wrangelvid Generations aren't used to tear down or invalidate already-accepted candidates. They're used to reject new candidates from an older context when we call AddCandidates. In this module, once a candidate has been accepted, bumping the generation won't affect it at all so nothing to worry about.
During a network change we'll still generate candidates for all available paths, including additive, and the ICE agent can continue to smoothly renominate the better path without disrupting the existing session. It will just make sure to reject old generation candidates if they got sent late. and not waste time try to connect to most likely not working candidates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mhh, I might need a bit more help to understand this, but I don't see the advantage yet.
My understanding is that the receiver discards identical candidates automatically. Wouldn't bumping the generation break this deduplication and trigger redundant connectivity checks for paths that are already connected?
Regarding late candidates: if a candidate from the current session arrives late, wouldn't we actually want to accept it? Since the credentials haven't changed, it's a valid backup path that just arrived out of order. I thought we only needed to strictly reject late candidates during ICE restarts because the credentials become invalid.
Also, if an interface is truly gone (e.g. unplugged ethernet), we won't gather new candidates for it anyway, so there's nothing to filter there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have to decide here:
- Reject older generation candidates and save network time on most likely not valid network paths. and risk slight delay if we reject a valid candidate (we'll end up receving it again with the new generation anyway).
- Accept all candidates, in case some of the candidates are valid, and risk wasting a lot of time in cases the user switch between different networks really quick.
I think your scenario will be super rare in the real world, what will be most likely the case is like in whip/whep signaling where we collect many candidates and batch them in one response as in the original issue pion/webrtc#2993 and in cases like this we have candidates from both generations.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fair enough, that's a trade-off. We'll try it with generations on mobile robots when we get a chance and compare. Worst case, we'll vendor patch this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can always remove the generation extension from the candidate text, if you have a non standard signaling protocol :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, we should keep the generation extension for ice restarts ◡̈
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, seems like we've landed on trying the generation bump on network change for now. We can certainly reevaluate in the future.
With that agreement in place are there thoughts on whether there's a better way to be executing that on the Agent Loop and getting the generation value back to this go-routine?
6f163a5 to
ecd2263
Compare
Populate the generation extension on candidates added to ICE Agent.
ecd2263 to
d5aaf7d
Compare
| } | ||
|
|
||
| if newState == GatheringStateComplete && !a.gatherEndSent { | ||
| a.candidateNotifier.EnqueueCandidate(nil) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JoTurk I wonder if we should also be concerned about calling this from within the "Lock" / AgentLoop here. Specifically the fact that EnqueueCandidate starts by acquiring the handlerNotifier Lock. I'd be concerned that we could end up delaying the Agent Loop if not fully deadlocking it.
Description
Populate the generation extension on candidates added to ICE Agent.