diff --git a/agent_test.go b/agent_test.go index 4272f11..bc010c7 100644 --- a/agent_test.go +++ b/agent_test.go @@ -599,3 +599,17 @@ func TestConnectionStateCallback(t *testing.T) { <-isClosed } + +func TestInvalidGather(t *testing.T) { + t.Run("Gather with Trickle enable and no OnCandidate should error", func(t *testing.T) { + a, err := NewAgent(&AgentConfig{Trickle: true}) + if err != nil { + t.Fatalf("Error constructing ice.Agent") + } + + err = a.GatherCandidates() + if err != ErrNoOnCandidateHandler { + t.Fatal("trickle GatherCandidates succeeded without OnCandidate") + } + }) +} diff --git a/errors.go b/errors.go index f5e98ce..e39f4ab 100644 --- a/errors.go +++ b/errors.go @@ -46,6 +46,9 @@ var ( // while running in trickle mode. ErrNoOnCandidateHandler = errors.New("no OnCandidate provided") + // ErrMultipleGatherAttempted indicates GatherCandidates has been called multiple times + ErrMultipleGatherAttempted = errors.New("attempting to gather candidates during gathering state") + // ErrUsernameEmpty indicates agent was give TURN URL with an empty Username ErrUsernameEmpty = errors.New("username is empty") diff --git a/gather.go b/gather.go index 997e9b1..3efec15 100644 --- a/gather.go +++ b/gather.go @@ -92,17 +92,38 @@ func listenUDP(portMax, portMin int, network string, laddr *net.UDPAddr) (*net.U // GatherCandidates initiates the trickle based gathering process. func (a *Agent) GatherCandidates() error { + gatherErrChan := make(chan error, 1) + + runErr := a.run(func(agent *Agent) { if a.gatheringState == GatheringStateGathering { - a.log.Warnf("Attempting to gather candidates during gathering state\n") + gatherErrChan <- ErrMultipleGatherAttempted + return + } else if a.onCandidateHdlr == nil { + gatherErrChan <- ErrNoOnCandidateHandler return } go a.gatherCandidates() + + gatherErrChan <- nil }) + if runErr != nil { + return runErr + } + return <-gatherErrChan } func (a *Agent) gatherCandidates() { - a.gatheringState = GatheringStateGathering + gatherStateUpdated := make(chan bool) + if err := a.run(func(agent *Agent) { + a.gatheringState = GatheringStateGathering + close(gatherStateUpdated) + }); err != nil { + a.log.Warnf("failed to set gatheringState to GatheringStateGathering for gatherCandidates: %v", err) + return + } + <-gatherStateUpdated + a.gatherCandidatesLocal(a.networkTypes) a.gatherCandidatesSrflx(a.urls, a.networkTypes) if err := a.run(func(agent *Agent) {