From 71316d91229a1b44ee5be8e05116049c4152a3f7 Mon Sep 17 00:00:00 2001 From: Zechao Shang Date: Thu, 7 May 2026 21:57:11 -0700 Subject: [PATCH] Return ErrNoCandidatePairs before ICE connects --- connectivity_vnet_test.go | 5 ++++- selection_test.go | 6 ++++-- transport.go | 2 +- transport_test.go | 32 ++++++++++++++++++++++++++++++++ 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/connectivity_vnet_test.go b/connectivity_vnet_test.go index e8f73d58..5caae917 100644 --- a/connectivity_vnet_test.go +++ b/connectivity_vnet_test.go @@ -7,6 +7,7 @@ package ice import ( "context" + "errors" "fmt" "net" "sync/atomic" @@ -790,7 +791,9 @@ func TestWriteUseValidPair(t *testing.T) { go func() { for { if _, writeErr := (&Conn{agent: controllingAgent}).Write(testMessage); writeErr != nil { - return + if !errors.Is(writeErr, ErrNoCandidatePairs) { + return + } } time.Sleep(20 * time.Millisecond) diff --git a/selection_test.go b/selection_test.go index 0a1c5836..f50410bd 100644 --- a/selection_test.go +++ b/selection_test.go @@ -141,8 +141,10 @@ func TestBindingRequestHandler(t *testing.T) { assert.NotNil(t, candidatePair) assert.NoError(t, err) - // Sending will fail, we no longer have a selected candidate pair - require.False(t, sendUntilDone(t, controlledConn, controllingConn, 20)) + // Sending will fail, we no longer have a selected candidate pair. + n, writeErr := controlledConn.Write([]byte("Hello World")) + require.Zero(t, n) + require.ErrorIs(t, writeErr, ErrNoCandidatePairs) // Send STUN Binding requests until a new Selected Candidate Pair has been set by BindingRequestHandler switchToNewCandidatePair.Store(true) diff --git a/transport.go b/transport.go index 19b30eff..f6267046 100644 --- a/transport.go +++ b/transport.go @@ -141,7 +141,7 @@ func (c *Conn) Write(packet []byte) (int, error) { } if pair == nil { - return 0, err + return 0, ErrNoCandidatePairs } } diff --git a/transport_test.go b/transport_test.go index b36f4023..41f264ef 100644 --- a/transport_test.go +++ b/transport_test.go @@ -443,6 +443,38 @@ func TestConn_Write_RejectsSTUN(t *testing.T) { require.ErrorIs(t, werr, errWriteSTUNMessageToIceConn) } +func TestStartDialConnWriteBeforeConnectReturnsError(t *testing.T) { + defer test.CheckRoutines(t)() + defer test.TimeOut(10 * time.Second).Stop() + + cfg := &AgentConfig{ + NetworkTypes: supportedNetworkTypes(), + MulticastDNSMode: MulticastDNSModeDisabled, + } + a, err := NewAgent(cfg) + require.NoError(t, err) + defer func() { + require.NoError(t, a.Close()) + }() + + b, err := NewAgent(cfg) + require.NoError(t, err) + defer func() { + require.NoError(t, b.Close()) + }() + + bUfrag, bPwd, err := b.GetLocalUserCredentials() + require.NoError(t, err) + + conn, err := a.StartDial(bUfrag, bPwd) + require.NoError(t, err) + + n, werr := conn.Write([]byte("early application data")) + require.Zero(t, n) + require.ErrorIs(t, werr, ErrNoCandidatePairs) + require.Zero(t, conn.BytesSent()) +} + func TestConn_GetCandidatePairsInfo(t *testing.T) { defer test.CheckRoutines(t)() defer test.TimeOut(10 * time.Second).Stop()