diff options
Diffstat (limited to 'vendor/github.com/pion/turn/v2/internal/client/binding.go')
-rw-r--r-- | vendor/github.com/pion/turn/v2/internal/client/binding.go | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/vendor/github.com/pion/turn/v2/internal/client/binding.go b/vendor/github.com/pion/turn/v2/internal/client/binding.go new file mode 100644 index 0000000..ee52053 --- /dev/null +++ b/vendor/github.com/pion/turn/v2/internal/client/binding.go @@ -0,0 +1,151 @@ +package client + +import ( + "net" + "sync" + "sync/atomic" + "time" +) + +// Chanel number: +// 0x4000 through 0x7FFF: These values are the allowed channel +// numbers (16,383 possible values). +const ( + minChannelNumber uint16 = 0x4000 + maxChannelNumber uint16 = 0x7fff +) + +type bindingState int32 + +const ( + bindingStateIdle bindingState = iota + bindingStateRequest + bindingStateReady + bindingStateRefresh + bindingStateFailed +) + +type binding struct { + number uint16 // read-only + st bindingState // thread-safe (atomic op) + addr net.Addr // read-only + mgr *bindingManager // read-only + muBind sync.Mutex // thread-safe, for ChannelBind ops + _refreshedAt time.Time // protected by mutex + mutex sync.RWMutex // thread-safe +} + +func (b *binding) setState(state bindingState) { + atomic.StoreInt32((*int32)(&b.st), int32(state)) +} + +func (b *binding) state() bindingState { + return bindingState(atomic.LoadInt32((*int32)(&b.st))) +} + +func (b *binding) setRefreshedAt(at time.Time) { + b.mutex.Lock() + defer b.mutex.Unlock() + + b._refreshedAt = at +} + +func (b *binding) refreshedAt() time.Time { + b.mutex.RLock() + defer b.mutex.RUnlock() + + return b._refreshedAt +} + +// Thread-safe binding map +type bindingManager struct { + chanMap map[uint16]*binding + addrMap map[string]*binding + next uint16 + mutex sync.RWMutex +} + +func newBindingManager() *bindingManager { + return &bindingManager{ + chanMap: map[uint16]*binding{}, + addrMap: map[string]*binding{}, + next: minChannelNumber, + } +} + +func (mgr *bindingManager) assignChannelNumber() uint16 { + n := mgr.next + if mgr.next == maxChannelNumber { + mgr.next = minChannelNumber + } else { + mgr.next++ + } + return n +} + +func (mgr *bindingManager) create(addr net.Addr) *binding { + mgr.mutex.Lock() + defer mgr.mutex.Unlock() + + b := &binding{ + number: mgr.assignChannelNumber(), + addr: addr, + mgr: mgr, + _refreshedAt: time.Now(), + } + + mgr.chanMap[b.number] = b + mgr.addrMap[b.addr.String()] = b + return b +} + +func (mgr *bindingManager) findByAddr(addr net.Addr) (*binding, bool) { + mgr.mutex.RLock() + defer mgr.mutex.RUnlock() + + b, ok := mgr.addrMap[addr.String()] + return b, ok +} + +func (mgr *bindingManager) findByNumber(number uint16) (*binding, bool) { + mgr.mutex.RLock() + defer mgr.mutex.RUnlock() + + b, ok := mgr.chanMap[number] + return b, ok +} + +func (mgr *bindingManager) deleteByAddr(addr net.Addr) bool { + mgr.mutex.Lock() + defer mgr.mutex.Unlock() + + b, ok := mgr.addrMap[addr.String()] + if !ok { + return false + } + + delete(mgr.addrMap, addr.String()) + delete(mgr.chanMap, b.number) + return true +} + +func (mgr *bindingManager) deleteByNumber(number uint16) bool { + mgr.mutex.Lock() + defer mgr.mutex.Unlock() + + b, ok := mgr.chanMap[number] + if !ok { + return false + } + + delete(mgr.addrMap, b.addr.String()) + delete(mgr.chanMap, number) + return true +} + +func (mgr *bindingManager) size() int { + mgr.mutex.RLock() + defer mgr.mutex.RUnlock() + + return len(mgr.chanMap) +} |