diff --git a/agent.go b/agent.go index 0ad6ff2..5350330 100644 --- a/agent.go +++ b/agent.go @@ -358,7 +358,13 @@ func NewAgent(config *AgentConfig) (*Agent, error) { //nolint:gocognit } go a.taskLoop() - a.startOnConnectionStateChangeRoutine() + + // CandidatePair and ConnectionState are usually changed at once. + // Blocking one by the other one causes deadlock. + // Hence, we call handlers from independent Goroutines. + go a.candidatePairRoutine() + go a.connectionStateRoutine() + go a.candidateRoutine() // Restart is also used to initialize the agent for the first time if err := a.Restart(config.LocalUfrag, config.LocalPwd); err != nil { diff --git a/agent_handlers.go b/agent_handlers.go index f7b6247..c5a5ec0 100644 --- a/agent_handlers.go +++ b/agent_handlers.go @@ -41,39 +41,20 @@ func (a *Agent) onConnectionStateChange(s ConnectionState) { } } -func (a *Agent) startOnConnectionStateChangeRoutine() { - go func() { - for { - // CandidatePair and ConnectionState are usually changed at once. - // Blocking one by the other one causes deadlock. - p, isOpen := <-a.chanCandidatePair - if !isOpen { - return - } - a.onSelectedCandidatePairChange(p) - } - }() - go func() { - for { - select { - case s, isOpen := <-a.chanState: - if !isOpen { - for c := range a.chanCandidate { - a.onCandidate(c) - } - return - } - go a.onConnectionStateChange(s) +func (a *Agent) candidatePairRoutine() { + for p := range a.chanCandidatePair { + a.onSelectedCandidatePairChange(p) + } +} - case c, isOpen := <-a.chanCandidate: - if !isOpen { - for s := range a.chanState { - go a.onConnectionStateChange(s) - } - return - } - a.onCandidate(c) - } - } - }() +func (a *Agent) connectionStateRoutine() { + for s := range a.chanState { + go a.onConnectionStateChange(s) + } +} + +func (a *Agent) candidateRoutine() { + for c := range a.chanCandidate { + a.onCandidate(c) + } }