Skip to content

Implement SPED (STUN Protocol for Embedding DTLS) - #876

Open
fippo wants to merge 4 commits into
pion:mainfrom
fippo:sped-remainder
Open

Implement SPED (STUN Protocol for Embedding DTLS)#876
fippo wants to merge 4 commits into
pion:mainfrom
fippo:sped-remainder

Conversation

@fippo

@fippo fippo commented Jan 19, 2026

Copy link
Copy Markdown
Contributor

(based on #914 )

Part of pion/webrtc#3335

@codecov

codecov Bot commented Jan 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.31034% with 30 lines in your changes missing coverage. Please review.
✅ Project coverage is 87.97%. Comparing base (c0c488f) to head (d0cc895).

Files with missing lines Patch % Lines
piggyback.go 77.19% 22 Missing and 4 partials ⚠️
agent.go 80.00% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #876      +/-   ##
==========================================
- Coverage   88.35%   87.97%   -0.39%     
==========================================
  Files          46       47       +1     
  Lines        6279     6409     +130     
==========================================
+ Hits         5548     5638      +90     
- Misses        498      532      +34     
- Partials      233      239       +6     
Flag Coverage Δ
go 87.97% <79.31%> (-0.39%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@fippo
fippo force-pushed the sped-remainder branch 5 times, most recently from 10ebcd0 to 53df31e Compare January 30, 2026 17:37
@fippo
fippo marked this pull request as ready for review March 26, 2026 18:53
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 24, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 25, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 25, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 25, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 25, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 25, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit to fippo/pion-ice that referenced this pull request Apr 25, 2026
which will be used in pion#876 where the presence of some
attributes depends on whether they were used in the
original request.
fippo added a commit that referenced this pull request Apr 25, 2026
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)
@fippo
fippo force-pushed the sped-remainder branch 2 times, most recently from 1ea6639 to c7f08eb Compare May 4, 2026 12:55
@fippo
fippo force-pushed the sped-remainder branch from 2f3305b to 95838f7 Compare May 15, 2026 17:49
@JoTurk
JoTurk self-requested a review June 2, 2026 12:59
@cnderrauber

Copy link
Copy Markdown
Member

Thank you for this great feature! I have integrated this into the livekit SFU and made some connectivity checks, found 2 regression cases:

  1. The ice-lite agent doesn't ping the remote actively, so the piggyback packets will be sent in response to the remote peer's connectivity check, cost longer than the non-sped case. Fixing this could conflict with spec, maybe we can mark it as an exception.
  2. When a remote peer sends a done signal after the agent is connected while still having inflight piggyback packets, it will mark the state to complete and doesn't have a chance to flush the packets. And also the Piggyback() will swallow all dtls packets but return true in this state (complete after connected).

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.

@fippo

fippo commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

@cnderrauber oops, forgot to respond.

(1) the tl;dr is that you can send DTLS unembedded once ice is writable which for lite means you can send after receiving the first valid binding check. https://fippo.github.io/warp-snap-sped/draft-hancke-webrtc-sped.html#section-3.3.1 bullet (3) covers that

(2) good catch!

@JoTurk JoTurk left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about ghosting this for too long, I have a few comments mainly about how Piggyback interacts with the agent.

Comment thread piggyback.go
Comment thread piggyback.go Outdated
Comment on lines +83 to +85
if a.piggyback.state == PiggybackingStateOff {
return a.connectionState != ConnectionStateConnected
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we queue / store packets before connected, wouldn't this affect early flight dtls packets?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, @zshang-oai found this too. This needs to go into the capture + flush part. I have a fix but keeping this open, this needs more 👀

Comment thread piggyback.go Outdated
Comment thread piggyback.go Outdated
@fippo
fippo force-pushed the sped-remainder branch 2 times, most recently from 5b98fcb to e6f721c Compare July 21, 2026 17:46
@fippo

fippo commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

updated!

Comment thread piggyback.go
defer a.piggyback.mu.Unlock()
if a.piggyback.state == PiggybackingStateOff && a.piggyback.connected {
return false
}

@JoTurk JoTurk Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also include complete to fix the issue reported / fixed by livekit with late retransmits? @cnderrauber livekit@85afccd this maybe should also extend to address packets that were already queued.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#876 (comment) -- was thinking of having that done as a f'up.

Comment thread piggyback.go
a.piggyback.packets = append(a.piggyback.packets, packetWithCrc{packet, crc})
} else if a.piggyback.state != PiggybackingStateOff {
a.piggyback.state = PiggybackingStatePending
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is triggered on dtls handshake right? from the comment "// A nil packet signals that the local DTLS handshake completed."
what happen if dtls handshake happens after complete? do we go back to pending or is it impossible because of something I'm missing?

https://github.com/pion/ice/pull/876/changes#diff-bed5e122cd63ea9db2c3fd9eb61077670debbebb87c1d898c640d9057f288842R146-R149

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wait, is this a deja-vu? #876 (comment) 😂

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry i misworded my comment, My concern here is different from my old comment, Is it possible for the state to be "complete" when (nil, true) gets called? and if that happens do we move back to pending?

@JoTurk JoTurk Aug 5, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Also from the glue this is called in completeStart which is called after full dtls handshake, this gets triggered after Finished in 1.2 and 1.3) so my concern is what happens if dtls handshake happens after sped handshake and is it possible?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In other words what happens if pion receives and process the stun message before the pion/dtls' hanshake channel unlocks? do we enter complete => pending race?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants