Skip to content

Add StartContext to ICE and DTLS Transport#3371

Open
HashimTheArab wants to merge 7 commits into
pion:mainfrom
HashimTheArab:add-ice-transport-start-context
Open

Add StartContext to ICE and DTLS Transport#3371
HashimTheArab wants to merge 7 commits into
pion:mainfrom
HashimTheArab:add-ice-transport-start-context

Conversation

@HashimTheArab

@HashimTheArab HashimTheArab commented Feb 10, 2026

Copy link
Copy Markdown

Summary

  • Adds StartContext method to ICETransport that accepts a context.Context parameter, allowing callers to control cancellation and timeouts for ICE connectivity checks
  • Refactors Start to delegate to StartContext with context.Background(), maintaining full backwards compatibility

🤖 Generated with Claude Code

@Sean-Der

Copy link
Copy Markdown
Member

Seems useful @HashimTheArab! I’m curious what’s the bug/use case your solving for?

@codecov

codecov Bot commented Feb 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 66.66667% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.34%. Comparing base (f52b36d) to head (402eac2).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
dtlstransport.go 50.00% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3371      +/-   ##
==========================================
- Coverage   85.55%   85.34%   -0.21%     
==========================================
  Files          81       81              
  Lines        9856     9865       +9     
==========================================
- Hits         8432     8419      -13     
- Misses       1006     1022      +16     
- Partials      418      424       +6     
Flag Coverage Δ
go 85.34% <66.66%> (-0.21%) ⬇️

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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@RealSexMC

RealSexMC commented Feb 10, 2026

Copy link
Copy Markdown

We're using this for Minecraft Nethernet connections (https://github.com/lactyy/go-nethernet) and the transport methods can hang indefinitely if the remote peer never responds. Without this option we have to use this fragile hack:

func withContextCancel(ctx context.Context, f func() error, cancel func()) error {
	errCh := make(chan error, 1)
	go func() {
		errCh <- f()
	}()
	select {
	case <-ctx.Done():
		if cancel != nil {
			cancel()
		}
		go func() { <-errCh }()
		return ctx.Err()
	case err := <-errCh:
		return err
	}
}

Passing a context will allow us to simplify and improve all of the call sites:

  // Before
  if err := withContextCancel(ctx, func() error {
      return conn.ice.Start(nil, d.ice, &iceRole)
  }, func() {
      _ = conn.ice.Stop()
  }); err != nil {
      return fmt.Errorf("start ICE: %w", err)
  }

  // After
  if err := conn.ice.StartContext(ctx, nil, d.ice, &iceRole); err != nil {
      return fmt.Errorf("start ICE: %w", err)
  }

(I am not the author of the PR)

@JoTurk

JoTurk commented Feb 10, 2026

Copy link
Copy Markdown
Member

@RealSexMC this is interesting I'm curious why you don't use pion/ice directly? seems more fit for your use, but I might be missing something. We're currently working on improving pion/ice and making it more suitable for non-webrtc use.

@didntpot

Copy link
Copy Markdown

@RealSexMC that is very interesting, couldn't you

@HashimTheArab

Copy link
Copy Markdown
Author

NetherNet is a full WebRTC stack, it uses ICE + DTLS + SCTP with data channels (ReliableDataChannel and UnreliableDataChannel) negotiated via SDP. We use pion's ORTC API to set up each transport individually since the signaling is custom (not standard WebSocket/HTTP), but the transports themselves are standard WebRTC.

@HashimTheArab

Copy link
Copy Markdown
Author

Anything else required to get this merged?

@JoTurk

JoTurk commented Feb 15, 2026

Copy link
Copy Markdown
Member

Can you please fix the lint?

@HashimTheArab

Copy link
Copy Markdown
Author

Should be good now

@HashimTheArab HashimTheArab changed the title Add StartContext to ICETransport Add StartContext to ICE and DTLS Transport Feb 16, 2026
@HashimTheArab

Copy link
Copy Markdown
Author

I've updated this to also add a StartContext method to DTLS transport

@HashimTheArab

Copy link
Copy Markdown
Author

Hey is anything else needed to merge this?

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

lgtm.

@JoTurk JoTurk self-requested a review February 28, 2026 23:01
@JoTurk

JoTurk commented Feb 28, 2026

Copy link
Copy Markdown
Member

@HashimTheArab Can you please update this branch and fix the tests before we can merge this. thank you.

@HashimTheArab HashimTheArab force-pushed the add-ice-transport-start-context branch from edbbc65 to e615471 Compare February 28, 2026 23:07
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@HashimTheArab HashimTheArab force-pushed the add-ice-transport-start-context branch from 7cac620 to c9d2f4c Compare February 28, 2026 23:09
@HashimTheArab

Copy link
Copy Markdown
Author

Fixed the issues. The test-i386 failure is from the master branch. Do I need to add additional testing for that codecov/patch?

@HashimTheArab

Copy link
Copy Markdown
Author

Hey @JoTurk please let me know what's needed to get this merged, the test coverage is failing due to 66% but I don't see any tests to meaningfully add?

@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 for ghosting this PR. I lost track.

Comment thread icetransport.go
Comment on lines 98 to 152
@@ -134,7 +147,7 @@ func (t *ICETransport) Start(gatherer *ICEGatherer, params ICEParameters, role *
}
t.role = *role

ctx, ctxCancel := context.WithCancel(context.Background())
ctx, ctxCancel := context.WithCancel(ctx)
t.ctxCancel = ctxCancel

@JoTurk JoTurk May 27, 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.

This is a problem in the current ICE design, but it affects this PR, currently https://github.com/pion/ice/blob/main/transport.go ICE just returns an error if the context is cancelled after the connection checks started, and it doesn't call agent's close by itself (we should change in the next major version). But for this PR we should also call close when the context get cancelled.

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.

Should be good now

@JoTurk JoTurk self-requested a review June 3, 2026 15:06
The review thread identified that pion/ice starts connectivity checks before context cancellation returns, leaving the agent running unless WebRTC closes it explicitly. This keeps the existing StartContext API shape and routes canceled starts through ICETransport Stop so the gatherer/agent are released.

Constraint: PR review requested closing the ICE agent when the StartContext context is canceled after checks begin.

Rejected: Changing pion/ice behavior in this PR | reviewer noted that belongs in the next major pion/ice version.

Confidence: high

Scope-risk: narrow

Directive: Keep StartContext cancellation tied to ICETransport shutdown until pion/ice owns cancellation cleanup itself.

Tested: go test ./ -run 'TestICETransport_StartContextClosesOnCancel|TestPeerConnection_Close$' -count=1; golangci-lint run --new-from-rev=HEAD; go test ./...
Comment thread icetransport.go
@JoTurk JoTurk self-requested a review June 4, 2026 20:21
Callers that cancel StartContext should receive the context cancellation error they can inspect, while WebRTC still closes the ICE transport to release the agent. Non-context start failures now clear the temporary internal cancel function instead of leaving it attached to a start that failed.

Constraint: PR review requested context cancellation semantics before merge.

Rejected: Returning the pion/ice cancellation error on caller cancellation | it hides the caller's context.Canceled or DeadlineExceeded signal.

Confidence: high

Scope-risk: narrow

Directive: Keep cancellation-return semantics aligned with context-aware Go APIs.

Tested: go test ./ -run 'TestICETransport_StartContextClosesOnCancel|TestPeerConnection_Close$' -count=1; golangci-lint run --new-from-rev=HEAD

Not-tested: go test ./... did not complete cleanly locally due existing network-sensitive mDNS/IPv6 failures in TestPeerConnectionTrickle and Test_IPv6.
Comment thread icetransport.go
Comment on lines +177 to +183
if ctxErr := ctx.Err(); ctxErr != nil {
t.lock.Unlock()
_ = t.Stop()
t.lock.Lock()

return ctxErr
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Use context.Cause(ctx) instead of ctx.Err()

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.

@sirzooro I don't think we would want a Pion api to return aribitary erros espically if this is used with third party created contexts, this will be kinda unpredicatable. and also sounds like a policy or API change across all of pion in a new major version and not just a single API and keep the rest.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This would be useful when used with complex context trees. Cancellation cause set few levels up the tree is propagated down when context is cancelled. This allows to improve logs, it is immediately obvious that connection was terminated due to something what happened elsewhere. Generic error "context cancelled" does not carry this information.

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

I see the point, but it's outside of the scope of this change, we shouldn't introduce a new pattern or error handling randomly in a single new API and keep the rest. Because having unpredictable APIs and maintaining different behaviors is way worse than losing some context, and If we would do it, we should do it across all of pion and we should use a linter to force it, and it should be in a new release.

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.

@sirzooro I made an issue #3446 does this look good for you?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks, I am ok with this.

Comment thread dtlstransport_test.go

func TestDTLSTransport_Start_ErrICEConnectionNotStarted(t *testing.T) {
transport := &DTLSTransport{state: DTLSTransportStateNew}
transport := &DTLSTransport{api: NewAPI(), state: DTLSTransportStateNew}

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'm sorry can we revert this and check if t.api is null? calls with t.api null shouldn't panic.

@JoTurk JoTurk self-requested a review June 5, 2026 08:41
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.

6 participants