| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- // Copyright (C) 2019 The Syncthing Authors.
- //
- // This Source Code Form is subject to the terms of the Mozilla Public
- // License, v. 2.0. If a copy of the MPL was not distributed with this file,
- // You can obtain one at https://mozilla.org/MPL/2.0/.
- // Registry tracks connections/addresses on which we are listening on, to allow us to pick a connection/address that
- // has a NAT port mapping. This also makes our outgoing port stable and same as incoming port which should allow
- // better probability of punching through.
- package registry
- import (
- "sort"
- "strings"
- "github.com/syncthing/syncthing/lib/sync"
- )
- var (
- Default = New()
- )
- type Registry struct {
- mut sync.Mutex
- available map[string][]interface{}
- }
- func New() *Registry {
- return &Registry{
- mut: sync.NewMutex(),
- available: make(map[string][]interface{}),
- }
- }
- func (r *Registry) Register(scheme string, item interface{}) {
- r.mut.Lock()
- defer r.mut.Unlock()
- r.available[scheme] = append(r.available[scheme], item)
- }
- func (r *Registry) Unregister(scheme string, item interface{}) {
- r.mut.Lock()
- defer r.mut.Unlock()
- candidates := r.available[scheme]
- for i, existingItem := range candidates {
- if existingItem == item {
- copy(candidates[i:], candidates[i+1:])
- candidates[len(candidates)-1] = nil
- r.available[scheme] = candidates[:len(candidates)-1]
- break
- }
- }
- }
- func (r *Registry) Get(scheme string, less func(i, j interface{}) bool) interface{} {
- r.mut.Lock()
- defer r.mut.Unlock()
- candidates := make([]interface{}, 0)
- for availableScheme, items := range r.available {
- // quic:// should be considered ok for both quic4:// and quic6://
- if strings.HasPrefix(scheme, availableScheme) {
- candidates = append(candidates, items...)
- }
- }
- if len(candidates) == 0 {
- return nil
- }
- sort.Slice(candidates, func(i, j int) bool {
- return less(candidates[i], candidates[j])
- })
- return candidates[0]
- }
- func Register(scheme string, item interface{}) {
- Default.Register(scheme, item)
- }
- func Unregister(scheme string, item interface{}) {
- Default.Unregister(scheme, item)
- }
- func Get(scheme string, less func(i, j interface{}) bool) interface{} {
- return Default.Get(scheme, less)
- }
|