Implement SPED (STUN Protocol for Embedding DTLS) - #876
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #876 +/- ##
==========================================
+ Coverage 88.25% 88.65% +0.39%
==========================================
Files 46 47 +1
Lines 6293 6459 +166
==========================================
+ Hits 5554 5726 +172
+ Misses 504 499 -5
+ Partials 235 234 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
10ebcd0 to
53df31e
Compare
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in pion#876 where the presence of some attributes depends on whether they were used in the original request.
which will be used in #876 where the presence of some attributes depends on whether they were used in the original request. (split from that to make review simpler, no functional changes)
0ab695f to
e9d8b98
Compare
1ea6639 to
c7f08eb
Compare
|
Thank you for this great feature! I have integrated this into the livekit SFU and made some connectivity checks, found 2 regression cases:
Both are fixed in our fork livekit@85afccd, livekit@5eec925. Will merge them back to upstream once this PR is merged if they make sense. |
ec416a1 to
3d4ec7a
Compare
|
I gave up and resynced with C++ logic ... |
There was a problem hiding this comment.
Pull request overview
Implements SPED by embedding DTLS handshake packets and acknowledgements in ICE STUN exchanges.
Changes:
- Adds the SPED piggybacking state machine and public DTLS hooks.
- Integrates SPED attributes into connectivity checks and responses.
- Adds state-machine, fallback, and integration tests.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
agent.go |
Initializes SPED and flushes fallback packets. |
selection.go |
Processes SPED attributes during ICE selection. |
piggyback.go |
Implements SPED packet and ACK handling. |
piggyback_test.go |
Tests SPED negotiation and fallback behavior. |
Suppressed comments (2)
piggyback.go:188
- This transition can leave an unacknowledged local flight in
packets, butCompleteprevents it from being embedded again. If ICE is already connected,flushOnConnectedhas already run, so the flight is stranded and the peer's DTLS handshake can stall. Drain outstanding packets as plain DTLS when completing an already-connected controller, and makeflushOnConnectedalso drainCompletefor the opposite event ordering.
if packet == nil && acks == nil && a.piggyback.state == PiggybackingStatePending {
a.log.Info("Done with the SPED handshake")
a.piggyback.acks = nil
a.piggyback.state = PiggybackingStateComplete
piggyback.go:216
- A non-nil ACK attribute is treated as final even when it is empty or acknowledges only older packets. After ACK deletion, verify that the outgoing queue is empty before entering
Complete; otherwise a reordered connectivity check can permanently stop retransmission of the still-unacknowledged flight.
// The response to the final flight will not contain DTLS data but an ack.
if packet == nil && acks != nil && a.piggyback.state == PiggybackingStatePending {
a.log.Info("Done with the SPED handshake")
a.piggyback.acks = nil
a.piggyback.state = PiggybackingStateComplete
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| for _, p := range packets { | ||
| _, _ = pair.Write(p.data) | ||
| } |
JoTurk
left a comment
There was a problem hiding this comment.
sorry for all the back and forth :(
|
still reasonable given the amount of cross-repo work required. Now it also seems we need to plumb ice-options if this is to be negotiated with ice-options ... |
JoTurk
left a comment
There was a problem hiding this comment.
Just two nits, looks great, thank you and sorry again
| // flight has to keep it around until it gets acknowledged; that is the server | ||
| // in DTLS 1.2 and the client in DTLS 1.3. The other party has nothing more to | ||
| // send and drops its outgoing packets. | ||
| func (a *Agent) SetDtlsHandshakeComplete(isClient, isDtls13 bool) { |
There was a problem hiding this comment.
Maybe instead of isdtls13 we should just have uint16 value of the version as a go "enum"
type dtlsVersion uint16
const (
DTLS12 dtlsVersion = 0xfefd
DTLS13 dtlsVersion = 0xfefc
)There was a problem hiding this comment.
this becomes an export hassle and I do not think we will have DTLS 1.4 anytime soon (and nobody likes 1.0)
There was a problem hiding this comment.
I agree but isdtls13 just doesn't feel "right" for a public api, but I don't have a hard feeling about this :)
There was a problem hiding this comment.
yeah but ideally DTLS defines its version but ice can't import from DTLS and lots of conversion and ... :-|
There was a problem hiding this comment.
We export the versions in dtls/pkg/protocol https://github.com/pion/dtls/blob/main/pkg/protocol/version.go and ice can import them and they are released with v3 so we don't have to wait for v4 :)
There was a problem hiding this comment.
yes but that creates a rather awkward dep from ice on dtls...
There was a problem hiding this comment.
Ice already imports dtls directly xd https://github.com/pion/ice/blob/main/go.mod
There was a problem hiding this comment.
whyyyyyyyyy...
(will update, awkwardness is not on me!)
|
Also I wonder if we should move the sped methods into a new optional object that the user can pass to options With sped(controller) so we don't have methods on agents but this isn't a big deal because ice is a due for an api rework and refactor and we can do all of this in the next major release. And release this for now. |
|
From my Codex and internal security tool, just for your reference @fippo
|
|
pion/stun#273 should be on by default? |
|
@fippo we're going to tag a new major release for STUN soon because of pion/stun#284 maybe we can switch strict mode to be on by default? |
|
@JoTurk ah... we didn't ship that. Yes, lets do it as part of a breaking change. |
(based on #914 )
Part of pion/webrtc#3335