-
Notifications
You must be signed in to change notification settings - Fork 160
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
Support active TCP candidates (RFC6544) #565
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #565 +/- ##
==========================================
+ Coverage 77.84% 78.44% +0.59%
==========================================
Files 41 41
Lines 4215 4272 +57
==========================================
+ Hits 3281 3351 +70
+ Misses 726 714 -12
+ Partials 208 207 -1
Flags with carried forward coverage won't be shown. Click here to find out more.
☔ View full report in Codecov by Sentry. |
5e6c8d0
to
9afe3ad
Compare
Hi @ashellunts, its really cool to see some progress here :) 🥳 |
Another thing I am thinking. Would it be a good idea to test in different network conditions using vnet? @stv0g |
@ashellunts Unfortuantely, I also dont expect this to land soon. Hence, we should proceed without vnet tests for now.. |
Amazing work @ashellunts so happy to see this land. Huge thank you @stv0g for being a great reviewer :) Passive requires using a Mux. I think that makes sense. TCP is only preferable in restrictive environments. Those environments usually only allow a few TCP ports. I think we can put this behind Type+NetworkTypes in Config! If Host+TCP is enabled we should have Active TCP. My only call out is we should prefer Host+Srflx UDP over TCP. TCP I think is preferable to Relay IMO I would love to see this land ASAP! If it has bugs/TODOs we can always fix those :) |
Hi @Sean-Der, thanks for your feedback!
I assumed that we will see the passive side usually deployed at a Pion agent running at some public server.
Good point. Actually RFC6544 Section 4.2 specifies this behaviour:
(The RFC continues to elaborate here...)
I agree :) We just need to get the API right :-S |
Currently passive candidates are collected when Host+TCP is used. Do you suggest to enable active ones always together with passive ones, when Host+TCP is enabled? Does it make sense to have option to choose from following cases:
|
I think we should do this. Enable Active by default. If AgentConfig has This will have zero effect on most users today. If the remote only publishes UDP candidates no TCP connections will be made. If the remote publishes a TCP candidate we will attempt a connection. Leave Passive disabled (same behavior we have now). Don't modify any passive UDP code and leave UDP Mux etc.. as it is. Passive candidates require special configuration. You usually want them on :80 or :443 and you want all your ICE Agents sharing that. If we just listen on random TCP ports I don't think we are giving users the best experience possible. I also believe that listening on a new random TCP Port would be confusing to users. |
👍
👍 |
I think also local LAN connectivity can profit from TCP candidates if requested. And while pion/ice is mainly used for pion/webrtc, WebRTC is not the only use case (I have others :D) |
OK, let me try to summarize:
I have checked: UDP host+srflx has less priority than TCP host+prflx (active/passive pair). |
@ashellunts summary sounds great to me! If you have a PR that does that would approve. @stv0g totally agree. If we prioritize WebRTC it makes everything worse :( We should write a ‘best configuration guide’. So developers know the best way to build their systems for connectivity success. If they are doing cross subnet TCP they probably want on a known part. Things like that could help a lot . |
459f146
to
e4e2848
Compare
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.
Hey, good work :)
I think we are not yet following the RFC in terms of type and local preferences.
candidatetype.go
Outdated
@@ -38,7 +38,21 @@ func (c CandidateType) String() string { | |||
// The RECOMMENDED values are 126 for host candidates, 100 | |||
// for server reflexive candidates, 110 for peer reflexive candidates, | |||
// and 0 for relayed candidates. | |||
func (c CandidateType) Preference() uint16 { | |||
func (c CandidateType) Preference(networkType NetworkType) uint16 { |
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 dont think this exactly reflects the recommendation of RFC6544 Section 4.2:
When both UDP and TCP candidates are offered for the same media stream, and one transport protocol should be preferred over the other, the type preferences for the preferred transport protocol candidates SHOULD be increased and/or the type preferences for the other transport protocol candidates SHOULD be decreased.
So I think we should have a user-configurable offset which is added/substracted from the type-dependent preference.
How much the values should be increased or decreased depends on whether it is more important to choose a certain transport protocol or a certain candidate type. If the candidate type is more important (e.g., even if UDP is preferred, TCP host candidates are preferred over UDP server reflexive candidates) changing type preference values by one for the other transport protocol candidates is enough. On the other hand, if the transport protocol is more important (e.g., any UDP candidate is preferred over any TCP candidate), all the preferred transport protocol candidates SHOULD have type preference higher than the other transport protocol candidates. However, it is RECOMMENDED that the relayed candidates are still preferred lower than the other candidate types. For RTP-based media streams, it is RECOMMENDED that UDP candidates are preferred over TCP 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.
That would mean we need to change existing default type priority for UDP.
Because currently host UDP type priority is 126, max value. So we can't increase it anymore.
If we want to use offsets, we need to make lower.
That may affect existing applications. Personally I would not want to affect existing library clients if they don't use TCP at all.
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.
See also 92be181
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.
Though we may use offset to reduce TCP priorities and not change UDP ones. That would conform to the standard.
gather.go
Outdated
@@ -225,7 +199,7 @@ func (a *Agent) gatherCandidatesLocal(ctx context.Context, networkTypes []Networ | |||
Address: address, | |||
Port: connAndPort.port, | |||
Component: ComponentRTP, | |||
TCPType: tcpType, | |||
TCPType: connAndPort.tcpType, |
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 we rename this simply to cfg
? And the corresponding conns
to cfgs
?
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 prefer more verbose naming. What about connectionConfiguration?
I have added tests that check if both TCP/UDP are enabled, UDP is selected pair but the test fails sometime. Not sure why... any ideas? @stv0g Looks like if TCP is selected at first, later it is not changed to UDP (I have added sleep and selected candidate does not change), though UDP pair priority is higher. |
dbdde52
to
268fff8
Compare
Looks like it is expected behavior. If I add timeout for host candidate, UDP is always selected. |
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.
Fantastic work! I am all for merging this @ashellunts
We should then cut a release and reach out to the user that was looking to use Active TCP. Tell me if there is anything I can do to help :)
Added user option to configure relative offset of TCP candidate type priority. By default it is set to 27 so that UDP+srlfx > TCP+host. |
@ashellunts mind just squashing into one commit? Just to make debugging easier! really excited to see this long standing issue resolved:) |
By default TCP candidate type priority is UDP one minus 27 (except relay), so that UDP+srlfx priority > TCP+host priority. That priority offset can be configured using AgentConfig. Ipv6 TCP candidates are also supported. Open issue: local active TCP candidate can be connected only with 1 remote passive candidate.
Sure, I like to make smaller commits during review phases, so that reviewer can see difference pushed.
Yes, I am also glad to finish the feature, especially when there are people waiting for it. Off topic: what percentage in codecov/patch report means? |
This PR implements support for active TCP candidates as specified in RFC6544
Open issue: local active TCP candidate can be connected only with 1 remote.