Skip to content

Expose APIs for handling streamId alloc and re-use#463

Open
pando-emil wants to merge 5 commits into
pion:mainfrom
pando-emil:stream-properties-api
Open

Expose APIs for handling streamId alloc and re-use#463
pando-emil wants to merge 5 commits into
pion:mainfrom
pando-emil:stream-properties-api

Conversation

@pando-emil

@pando-emil pando-emil commented Apr 4, 2026

Copy link
Copy Markdown

This commit is a preparation step for making webrtc able to properly determine max number of datachannels that can be used for a specific session.

It also adds an event subscription for when a stream has been completely resetted, so that webrtc knows when it is possible to re-use a streamId.

Corresponding PR in webrtc repo: pion/webrtc#3405

This commit is a preparation step for making webrtc able to properly
determine max number of datachannels that can be used for a specific
session.

It also adds an event subscription for when a stream has been completely
resetted, so that webrtc knows when it is possible to re-use a streamId.
@codecov

codecov Bot commented Apr 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.03%. Comparing base (31120e8) to head (8cbd9d5).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #463      +/-   ##
==========================================
+ Coverage   83.92%   84.03%   +0.11%     
==========================================
  Files          54       54              
  Lines        4366     4384      +18     
==========================================
+ Hits         3664     3684      +20     
+ Misses        508      507       -1     
+ Partials      194      193       -1     
Flag Coverage Δ
go 84.03% <100.00%> (+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.

@JoTurk JoTurk self-requested a review April 7, 2026 14:15
@JoTurk

JoTurk commented May 3, 2026

Copy link
Copy Markdown
Member

Thank you @pando-emil sorry I missed this, I'll review both your PRs today.

@pando-emil

Copy link
Copy Markdown
Author

@JoTurk did you manage to review this? Just let me know if you have any questions!

@JoTurk

JoTurk commented May 10, 2026

Copy link
Copy Markdown
Member

@pando-emil sorry i got busy with some stuff at my work, I'll check this PR. this morning.
Thank you.

@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.

Thank you and sorry i took time to get back to you.

Comment thread association.go
Comment on lines +3622 to +3640
// NumInboundStreams returns the maximum number of inbound streams for this association.
// The number of inbound streams is determined by looking at the peer's INIT or INIT ACK chunk,
// so it is not available until the handshake completes.
func (a *Association) NumInboundStreams() uint16 {
a.lock.RLock()
defer a.lock.RUnlock()

return a.myMaxNumInboundStreams
}

// NumOutboundStreams returns the maximum number of outbound streams for this association.
// The number of outbound streams is determined by looking at the peer's INIT or INIT ACK chunk,
// so it is not available until the handshake completes.
func (a *Association) NumOutboundStreams() uint16 {
a.lock.RLock()
defer a.lock.RUnlock()

return a.myMaxNumOutboundStreams
}

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.

I think this in-correct for the purpose of this PR because both values are from our direction

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The myMaxNumInboundStreams and myMaxNumOutboundStreams is dynamically changed to the min of our local max and the remotes max in initWithOutOfBandTokens() and handleInitAck(). The added tests in association_test.go should actually verify this.

But maybe we should change name of the variable, "myMax" gets a bit confusing...

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.

The myMaxNumInboundStreams and myMaxNumOutboundStreams is dynamically changed to the min of our local max and the remotes max in initWithOutOfBandTokens() and handleInitAck().

This isn't the problem, the problem is that myMaxNumInboundStreams and myMaxNumOutboundStreams are set to one direction, they are just internally values to hold the remote limits, they are confusing and named incorrectly and we should change them if we were to use them in a public API, And provide an option API to set our own max.

sctp/association.go

Lines 779 to 780 in 2e80e82

a.myMaxNumInboundStreams = min16(localInit.numInboundStreams, remoteInit.numInboundStreams)
a.myMaxNumOutboundStreams = min16(localInit.numOutboundStreams, remoteInit.numOutboundStreams)

sctp/association.go

Lines 1720 to 1721 in 2e80e82

a.myMaxNumInboundStreams = min16(initChunk.numInboundStreams, a.myMaxNumInboundStreams)
a.myMaxNumOutboundStreams = min16(initChunk.numOutboundStreams, a.myMaxNumOutboundStreams)

And how we make init chunks (which is incorrect btw, if we use anything other than MaxUint16 in the future):

sctp/association.go

Lines 1762 to 1763 in 2e80e82

initAck.numOutboundStreams = a.myMaxNumOutboundStreams
initAck.numInboundStreams = a.myMaxNumInboundStreams

Another issue is that they are inverted in this PR, NumInboundStreams should have been min(inbound, and the peer's outbound), but currently it's the remote peer's numInboundStreams.

I think if we were to expose APIs or options, we should have, localOS, localMIS, peerOS, peerMIS and drive the max values from min(localOS, peerMIS) and min(localMIS, peerOS).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I wanted to keep the patch to a minimum to not mess with namings etc I don't know the original intentions behind. But I do agree with your comments. I'll try to rework the internal states and update the PR.

But I think the addition of an API to set the local max can be saved for a separate PR, that is a new feature.

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.

Sounds good, thank you.

@JoTurk

JoTurk commented May 17, 2026

Copy link
Copy Markdown
Member

@pando-emil I'm thinking about this again, because in interleaving i want to expose an API so the end user can tell if interleaving is enabled and negotiated or not, and since we're going to export multiple methods that are only meaningful after handshake I think we should have a metadata struct and a way to register a callback or even blocking function that returns all the assoc metadata.

Added a few more tests validating the number of streams negotiation.
@pando-emil

Copy link
Copy Markdown
Author

@JoTurk that sounds reasonable! I'll adopt to those changes as soon as they are merged. In the meantime I have updated with a reworked representation within association.

@JoTurk

JoTurk commented Jun 3, 2026

Copy link
Copy Markdown
Member

@pando-emil the metadata API is merged and released btw if you want to update your PR to adds stats to it.

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