Cancel previous gathering routine on restart

Updated ICE agent restart method to cancel the
current gathering and then restart the candidate
gathering process.
This commit is contained in:
Will Forcey
2021-01-24 11:54:32 -05:00
committed by Steffen Vogel
parent 7f2d498367
commit 9ab8f71673
3 changed files with 21 additions and 12 deletions

View File

@@ -1196,8 +1196,10 @@ func (a *Agent) SetRemoteCredentials(remoteUfrag, remotePwd string) error {
// Restart restarts the ICE Agent with the provided ufrag/pwd // Restart restarts the ICE Agent with the provided ufrag/pwd
// If no ufrag/pwd is provided the Agent will generate one itself // If no ufrag/pwd is provided the Agent will generate one itself
// //
// Restart must only be called when GatheringState is GatheringStateComplete // If there is a gatherer routine currently running, Restart will
// a user must then call GatherCandidates explicitly to start generating new ones // cancel it.
// After a Restart, the user must then call GatherCandidates explicitly
// to start generating new ones.
func (a *Agent) Restart(ufrag, pwd string) error { func (a *Agent) Restart(ufrag, pwd string) error {
if ufrag == "" { if ufrag == "" {
var err error var err error
@@ -1224,8 +1226,7 @@ func (a *Agent) Restart(ufrag, pwd string) error {
var err error var err error
if runErr := a.run(a.context(), func(ctx context.Context, agent *Agent) { if runErr := a.run(a.context(), func(ctx context.Context, agent *Agent) {
if agent.gatheringState == GatheringStateGathering { if agent.gatheringState == GatheringStateGathering {
err = ErrRestartWhenGathering agent.gatherCandidateCancel()
return
} }
// Clear all agent needed to take back to fresh state // Clear all agent needed to take back to fresh state

View File

@@ -1375,13 +1375,24 @@ func TestAgentRestart(t *testing.T) {
oneSecond := time.Second oneSecond := time.Second
t.Run("Restart During Gather", func(t *testing.T) { t.Run("Restart During Gather", func(t *testing.T) {
agent, err := NewAgent(&AgentConfig{}) connA, connB := pipe(&AgentConfig{
assert.NoError(t, err) DisconnectedTimeout: &oneSecond,
FailedTimeout: &oneSecond,
})
agent.gatheringState = GatheringStateGathering ctx, cancel := context.WithCancel(context.Background())
assert.NoError(t, connB.agent.OnConnectionStateChange(func(c ConnectionState) {
if c == ConnectionStateFailed || c == ConnectionStateDisconnected {
cancel()
}
}))
assert.Equal(t, ErrRestartWhenGathering, agent.Restart("", "")) connA.agent.gatheringState = GatheringStateGathering
assert.NoError(t, agent.Close()) assert.NoError(t, connA.agent.Restart("", ""))
<-ctx.Done()
assert.NoError(t, connA.agent.Close())
assert.NoError(t, connB.agent.Close())
}) })
t.Run("Restart When Closed", func(t *testing.T) { t.Run("Restart When Closed", func(t *testing.T) {

View File

@@ -97,9 +97,6 @@ var (
// ErrInvalidMulticastDNSHostName indicates an invalid MulticastDNSHostName // ErrInvalidMulticastDNSHostName indicates an invalid MulticastDNSHostName
ErrInvalidMulticastDNSHostName = errors.New("invalid mDNS HostName, must end with .local and can only contain a single '.'") ErrInvalidMulticastDNSHostName = errors.New("invalid mDNS HostName, must end with .local and can only contain a single '.'")
// ErrRestartWhenGathering indicates Restart was called when Agent is in GatheringStateGathering
ErrRestartWhenGathering = errors.New("ICE Agent can not be restarted when gathering")
// ErrRunCanceled indicates a run operation was canceled by its individual done // ErrRunCanceled indicates a run operation was canceled by its individual done
ErrRunCanceled = errors.New("run was canceled by done") ErrRunCanceled = errors.New("run was canceled by done")