mirror of
https://github.com/netbirdio/ice.git
synced 2026-05-22 17:10:58 -07:00
Deliver Candidates and Selected CandidatePairs using the same queue. This means that things are delivered in order and we don't have to worry about blocking
137 lines
3.0 KiB
Go
137 lines
3.0 KiB
Go
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package ice
|
|
|
|
import "sync"
|
|
|
|
// OnConnectionStateChange sets a handler that is fired when the connection state changes
|
|
func (a *Agent) OnConnectionStateChange(f func(ConnectionState)) error {
|
|
a.onConnectionStateChangeHdlr.Store(f)
|
|
return nil
|
|
}
|
|
|
|
// OnSelectedCandidatePairChange sets a handler that is fired when the final candidate
|
|
// pair is selected
|
|
func (a *Agent) OnSelectedCandidatePairChange(f func(Candidate, Candidate)) error {
|
|
a.onSelectedCandidatePairChangeHdlr.Store(f)
|
|
return nil
|
|
}
|
|
|
|
// OnCandidate sets a handler that is fired when new candidates gathered. When
|
|
// the gathering process complete the last candidate is nil.
|
|
func (a *Agent) OnCandidate(f func(Candidate)) error {
|
|
a.onCandidateHdlr.Store(f)
|
|
return nil
|
|
}
|
|
|
|
func (a *Agent) onSelectedCandidatePairChange(p *CandidatePair) {
|
|
if h, ok := a.onSelectedCandidatePairChangeHdlr.Load().(func(Candidate, Candidate)); ok {
|
|
h(p.Local, p.Remote)
|
|
}
|
|
}
|
|
|
|
func (a *Agent) onCandidate(c Candidate) {
|
|
if onCandidateHdlr, ok := a.onCandidateHdlr.Load().(func(Candidate)); ok {
|
|
onCandidateHdlr(c)
|
|
}
|
|
}
|
|
|
|
func (a *Agent) onConnectionStateChange(s ConnectionState) {
|
|
if hdlr, ok := a.onConnectionStateChangeHdlr.Load().(func(ConnectionState)); ok {
|
|
hdlr(s)
|
|
}
|
|
}
|
|
|
|
type handlerNotifier struct {
|
|
sync.Mutex
|
|
running bool
|
|
|
|
connectionStates []ConnectionState
|
|
connectionStateFunc func(ConnectionState)
|
|
|
|
candidates []Candidate
|
|
candidateFunc func(Candidate)
|
|
|
|
selectedCandidatePairs []*CandidatePair
|
|
candidatePairFunc func(*CandidatePair)
|
|
}
|
|
|
|
func (h *handlerNotifier) EnqueueConnectionState(s ConnectionState) {
|
|
h.Lock()
|
|
defer h.Unlock()
|
|
|
|
notify := func() {
|
|
for {
|
|
h.Lock()
|
|
if len(h.connectionStates) == 0 {
|
|
h.running = false
|
|
h.Unlock()
|
|
return
|
|
}
|
|
notification := h.connectionStates[0]
|
|
h.connectionStates = h.connectionStates[1:]
|
|
h.Unlock()
|
|
h.connectionStateFunc(notification)
|
|
}
|
|
}
|
|
|
|
h.connectionStates = append(h.connectionStates, s)
|
|
if !h.running {
|
|
h.running = true
|
|
go notify()
|
|
}
|
|
}
|
|
|
|
func (h *handlerNotifier) EnqueueCandidate(c Candidate) {
|
|
h.Lock()
|
|
defer h.Unlock()
|
|
|
|
notify := func() {
|
|
for {
|
|
h.Lock()
|
|
if len(h.candidates) == 0 {
|
|
h.running = false
|
|
h.Unlock()
|
|
return
|
|
}
|
|
notification := h.candidates[0]
|
|
h.candidates = h.candidates[1:]
|
|
h.Unlock()
|
|
h.candidateFunc(notification)
|
|
}
|
|
}
|
|
|
|
h.candidates = append(h.candidates, c)
|
|
if !h.running {
|
|
h.running = true
|
|
go notify()
|
|
}
|
|
}
|
|
|
|
func (h *handlerNotifier) EnqueueSelectedCandidatePair(p *CandidatePair) {
|
|
h.Lock()
|
|
defer h.Unlock()
|
|
|
|
notify := func() {
|
|
for {
|
|
h.Lock()
|
|
if len(h.selectedCandidatePairs) == 0 {
|
|
h.running = false
|
|
h.Unlock()
|
|
return
|
|
}
|
|
notification := h.selectedCandidatePairs[0]
|
|
h.selectedCandidatePairs = h.selectedCandidatePairs[1:]
|
|
h.Unlock()
|
|
h.candidatePairFunc(notification)
|
|
}
|
|
}
|
|
|
|
h.selectedCandidatePairs = append(h.selectedCandidatePairs, p)
|
|
if !h.running {
|
|
h.running = true
|
|
go notify()
|
|
}
|
|
}
|