Skip to content

Conversation

@fippo
Copy link

@fippo fippo commented Dec 28, 2025

This commit adds a createAssociationWithOutOfBandTokens method that creates the SCTP association with a local and remote sctp-init token as described in draft-hancke-tsvwg-snap-00.

Tokens can be generated using the newly added GenerateOutOfBandToken method and set in the sctp.Config as LocalSctpInit and RemoteSctpInit.

This allows the peer connection to generate and negotiate the sctp-init in the SDP which skips two network round trips.

pion/WebRTC changes are in pion/webrtc#3327

@fippo fippo marked this pull request as draft December 28, 2025 15:56
@codecov
Copy link

codecov bot commented Dec 28, 2025

Codecov Report

❌ Patch coverage is 84.12698% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.69%. Comparing base (767b9c4) to head (888d784).

Files with missing lines Patch % Lines
association.go 84.12% 6 Missing and 4 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #449      +/-   ##
==========================================
- Coverage   83.79%   83.69%   -0.11%     
==========================================
  Files          52       52              
  Lines        4054     4108      +54     
==========================================
+ Hits         3397     3438      +41     
- Misses        481      488       +7     
- Partials      176      182       +6     
Flag Coverage Δ
go 83.69% <84.12%> (-0.11%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 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.

This commit adds a createAssociationWithOutOfBandTokens method
that creates the SCTP association with a local and remote sctp-init
token as described in draft-hancke-tsvwg-snap-00.

Tokens can be generated using the newly added GenerateOutOfBandToken
method and set in the sctp.Config as LocalSctpInit and RemoteSctpInit.

This allows the peer connection to generate and negotiate the
sctp-init attribute in the SDP which skips two network round trips.
Comment on lines +350 to +351
LocalSctpInit []byte
RemoteSctpInit []byte
Copy link
Member

@JoTurk JoTurk Dec 28, 2025

Choose a reason for hiding this comment

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

This will break the compatibility checks, but we plan to deprecate the config struct this week for the favor of options pattern so this could be WithSCTPInit when we update or something!

#446

Copy link
Author

Choose a reason for hiding this comment

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

overall this feels like we should separate options (configured by the API) from negotiated parameters (maxMessageSize, remote sctpPort, sctpInit). Still a breaking change but if we need one anyway...

Copy link
Member

Choose a reason for hiding this comment

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

association.go Outdated
assoc.setRWND(min32(localInit.advertisedReceiverWindowCredit, remoteInit.advertisedReceiverWindowCredit))
assoc.peerVerificationTag = remoteInit.initiateTag
assoc.sourcePort = defaultSCTPSrcDstPort
assoc.destinationPort = defaultSCTPSrcDstPort
Copy link
Author

Choose a reason for hiding this comment

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

a=sctp-port is currently ignored even from the remote SDP. Surprisingly with SNAP I don't think it matters anymore since it only shows up in one of the acks (so SCTP can detect NATs) but that is not relevant to WebRTC

Copy link
Author

@fippo fippo Dec 28, 2025

Choose a reason for hiding this comment

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

(added to SctpOptions which makes this fix-able in the future)

Copy link
Member

@JoTurk JoTurk Dec 28, 2025

Choose a reason for hiding this comment

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

We're currently updating this library to use Pion's options patterns, SctpOptions will not be needed after this is merged #450 🙏

Copy link
Author

Choose a reason for hiding this comment

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

Changed to SctpParameters which is more in line with terminology like RTCIceParameters and RTCDtlsParameters

association.go Outdated
Comment on lines 379 to 400
if len(config.RemoteSctpInit) != 0 && len(config.LocalSctpInit) != 0 {
// SNAP, aka sctp-init in the SDP.
remote := &chunkInit{}
err := remote.unmarshal(config.RemoteSctpInit)
if err != nil {
return nil, err
}
local := &chunkInit{}
err = local.unmarshal(config.LocalSctpInit)
if err != nil {
return nil, err
}
assoc = createAssociationWithOutOfBandTokens(config, local, remote)
assoc.lock.Lock()
assoc.setState(established)
defer assoc.lock.Unlock()

go assoc.readLoop()
go assoc.writeLoop()

return assoc, nil
}
Copy link
Member

Choose a reason for hiding this comment

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

I think this logic should be done in createAssociation and we prob should have one path to createAssociationWithTSN.

Copy link
Author

Choose a reason for hiding this comment

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

I didn't like that part either. Problem is that createAssociationWithOutOfBandTokens does too many tasks:

  • Validate the sctp-init's are ok
  • creating the association
  • setting some parameters which is usually in handleInit
  • updating the state (could probably move into createAssociationWithOutOfBandTokens and no lock required)
  • run the loop (normally done in init)
    The errors handled below this are basically the handshake being interrupted which can no longer happen.

🤔 but that means createAssociationWithOutOfBandTokens does things I don't want "createAssociation" to do... brb.

Copy link
Author

Choose a reason for hiding this comment

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

Slightly better. WDYT about renaming init() to sendInit() and only do as client, pulling the loop goroutines out?

Copy link
Member

Choose a reason for hiding this comment

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

a lot better yeah.

association.go Outdated
init.initialTSN = globalMathRandomGenerator.Uint32()
init.numOutboundStreams = math.MaxUint16
init.numInboundStreams = math.MaxUint16
init.initiateTag = globalMathRandomGenerator.Uint32()
Copy link
Member

Choose a reason for hiding this comment

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

This can return 0.

Copy link
Author

Choose a reason for hiding this comment

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

Good catch, also happens in existing code? Yay bugs that only happens once every 2^32 - 1 times... will update in both places.

return assoc, nil
}
assoc = createAssociation(config)
assoc.init(true)
Copy link
Member

Choose a reason for hiding this comment

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

Related to the previous comment but we skip assoc.init. So it's better overall if we try to make a single path for initialization. all of these APIs are private so feel free to refactor them.

@fippo fippo force-pushed the snap branch 2 times, most recently from b234227 to a41c9fd Compare December 28, 2025 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants