Skip to content

Commit 37fb5d2

Browse files
authored
Always send KeepAlives (#767)
Pion incorrectly resets the consent timer when sending any traffic. The consent timer must only be reset on STUN traffic. RFC 7675 > Consent expires after 30 seconds. That is, if a valid STUN binding > response has not been received from the remote peer's transport > address in 30 seconds, the endpoint MUST cease transmission on that > 5-tuple. STUN consent responses received after consent expiry do not > re-establish consent and may be discarded or cause an ICMP error.
1 parent f92d05f commit 37fb5d2

File tree

2 files changed

+40
-3
lines changed

2 files changed

+40
-3
lines changed

agent.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -594,9 +594,7 @@ func (a *Agent) checkKeepalive() {
594594
return
595595
}
596596

597-
if (a.keepaliveInterval != 0) &&
598-
((time.Since(selectedPair.Local.LastSent()) > a.keepaliveInterval) ||
599-
(time.Since(selectedPair.Remote.LastReceived()) > a.keepaliveInterval)) {
597+
if a.keepaliveInterval != 0 {
600598
// We use binding request instead of indication to support refresh consent schemas
601599
// see https://tools.ietf.org/html/rfc7675
602600
a.selector.PingCandidate(selectedPair.Local, selectedPair.Remote)

agent_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2121,3 +2121,42 @@ func TestSetCandidatesUfrag(t *testing.T) {
21212121
require.Equal(t, agent.localUfrag, ext.Value)
21222122
}
21232123
}
2124+
2125+
func TestAlwaysSentKeepAlive(t *testing.T) { //nolint:cyclop
2126+
defer test.CheckRoutines(t)()
2127+
2128+
// Avoid deadlocks?
2129+
defer test.TimeOut(1 * time.Second).Stop()
2130+
2131+
agent, err := NewAgent(&AgentConfig{})
2132+
if err != nil {
2133+
t.Fatalf("Failed to create agent: %s", err)
2134+
}
2135+
defer func() {
2136+
require.NoError(t, agent.Close())
2137+
}()
2138+
2139+
log := logging.NewDefaultLoggerFactory().NewLogger("agent")
2140+
agent.selector = &controllingSelector{agent: agent, log: log}
2141+
pair := makeCandidatePair(t)
2142+
if s, ok := pair.Local.(*CandidateHost); ok {
2143+
s.conn = &fakenet.MockPacketConn{}
2144+
} else {
2145+
t.Fatalf("Invalid local candidate")
2146+
}
2147+
agent.setSelectedPair(pair)
2148+
2149+
pair.Remote.seen(false)
2150+
2151+
lastSent := pair.Local.LastSent()
2152+
agent.checkKeepalive()
2153+
newLastSent := pair.Local.LastSent()
2154+
require.NotEqual(t, lastSent, newLastSent)
2155+
lastSent = newLastSent
2156+
2157+
// sleep, so there is difference in sent time of local candidate
2158+
time.Sleep(10 * time.Millisecond)
2159+
agent.checkKeepalive()
2160+
newLastSent = pair.Local.LastSent()
2161+
require.NotEqual(t, lastSent, newLastSent)
2162+
}

0 commit comments

Comments
 (0)