2021-05-01 12:45:37 +02:00
|
|
|
package peer
|
|
|
|
|
|
|
|
import (
|
2024-06-13 01:20:46 +02:00
|
|
|
"context"
|
2021-06-10 17:08:40 +02:00
|
|
|
"sync"
|
2022-08-22 12:21:19 +02:00
|
|
|
"time"
|
2024-06-13 01:20:46 +02:00
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
|
|
|
|
"github.com/netbirdio/netbird/signal/metrics"
|
|
|
|
"github.com/netbirdio/netbird/signal/proto"
|
2021-05-01 12:45:37 +02:00
|
|
|
)
|
|
|
|
|
2021-05-15 12:20:49 +02:00
|
|
|
// Peer representation of a connected Peer
|
2021-05-01 12:45:37 +02:00
|
|
|
type Peer struct {
|
|
|
|
// a unique id of the Peer (e.g. sha256 fingerprint of the Wireguard public key)
|
|
|
|
Id string
|
|
|
|
|
2022-08-22 12:21:19 +02:00
|
|
|
StreamID int64
|
|
|
|
|
2024-08-30 15:44:07 +02:00
|
|
|
// a gRpc connection stream to the Peer
|
2021-05-01 12:45:37 +02:00
|
|
|
Stream proto.SignalExchange_ConnectStreamServer
|
2024-08-30 15:44:07 +02:00
|
|
|
|
|
|
|
// registration time
|
|
|
|
RegisteredAt time.Time
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
|
|
|
|
2021-05-15 12:20:49 +02:00
|
|
|
// NewPeer creates a new instance of a connected Peer
|
2021-05-01 12:45:37 +02:00
|
|
|
func NewPeer(id string, stream proto.SignalExchange_ConnectStreamServer) *Peer {
|
|
|
|
return &Peer{
|
2024-08-30 15:44:07 +02:00
|
|
|
Id: id,
|
|
|
|
Stream: stream,
|
|
|
|
StreamID: time.Now().UnixNano(),
|
|
|
|
RegisteredAt: time.Now(),
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-22 12:21:19 +02:00
|
|
|
// Registry that holds all currently connected Peers
|
2021-05-01 12:45:37 +02:00
|
|
|
type Registry struct {
|
|
|
|
// Peer.key -> Peer
|
2021-06-10 17:08:40 +02:00
|
|
|
Peers sync.Map
|
2022-08-22 12:21:19 +02:00
|
|
|
// regMutex ensures that registration and de-registrations are safe
|
|
|
|
regMutex sync.Mutex
|
2024-06-13 01:20:46 +02:00
|
|
|
metrics *metrics.AppMetrics
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
|
|
|
|
2021-05-15 12:20:49 +02:00
|
|
|
// NewRegistry creates a new connected Peer registry
|
2024-06-13 01:20:46 +02:00
|
|
|
func NewRegistry(metrics *metrics.AppMetrics) *Registry {
|
2022-08-22 12:21:19 +02:00
|
|
|
return &Registry{
|
|
|
|
regMutex: sync.Mutex{},
|
2024-06-13 01:20:46 +02:00
|
|
|
metrics: metrics,
|
2022-08-22 12:21:19 +02:00
|
|
|
}
|
2021-06-10 17:08:40 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Get gets a peer from the registry
|
|
|
|
func (registry *Registry) Get(peerId string) (*Peer, bool) {
|
|
|
|
if load, ok := registry.Peers.Load(peerId); ok {
|
|
|
|
return load.(*Peer), ok
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
2021-06-10 17:08:40 +02:00
|
|
|
return nil, false
|
|
|
|
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
|
|
|
|
2021-06-10 17:08:40 +02:00
|
|
|
func (registry *Registry) IsPeerRegistered(peerId string) bool {
|
|
|
|
if _, ok := registry.Peers.Load(peerId); ok {
|
|
|
|
return ok
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
2021-06-10 17:08:40 +02:00
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register registers peer in the registry
|
|
|
|
func (registry *Registry) Register(peer *Peer) {
|
2024-06-13 01:20:46 +02:00
|
|
|
start := time.Now()
|
|
|
|
|
2022-08-22 12:21:19 +02:00
|
|
|
registry.regMutex.Lock()
|
|
|
|
defer registry.regMutex.Unlock()
|
2021-06-10 17:08:40 +02:00
|
|
|
|
2022-08-22 12:21:19 +02:00
|
|
|
// can be that peer already exists, but it is fine (e.g. reconnect)
|
|
|
|
p, loaded := registry.Peers.LoadOrStore(peer.Id, peer)
|
|
|
|
if loaded {
|
|
|
|
pp := p.(*Peer)
|
|
|
|
log.Warnf("peer [%s] is already registered [new streamID %d, previous StreamID %d]. Will override stream.",
|
|
|
|
peer.Id, peer.StreamID, pp.StreamID)
|
|
|
|
registry.Peers.Store(peer.Id, peer)
|
2024-09-15 16:46:55 +02:00
|
|
|
return
|
2022-08-22 12:21:19 +02:00
|
|
|
}
|
2024-09-15 16:46:55 +02:00
|
|
|
|
2022-08-22 12:21:19 +02:00
|
|
|
log.Debugf("peer registered [%s]", peer.Id)
|
2024-09-15 16:46:55 +02:00
|
|
|
registry.metrics.ActivePeers.Add(context.Background(), 1)
|
2024-06-13 01:20:46 +02:00
|
|
|
|
|
|
|
// record time as milliseconds
|
|
|
|
registry.metrics.RegistrationDelay.Record(context.Background(), float64(time.Since(start).Nanoseconds())/1e6)
|
|
|
|
|
|
|
|
registry.metrics.Registrations.Add(context.Background(), 1)
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
|
|
|
|
2022-08-22 12:21:19 +02:00
|
|
|
// Deregister Peer from the Registry (usually once it disconnects)
|
2021-06-10 17:08:40 +02:00
|
|
|
func (registry *Registry) Deregister(peer *Peer) {
|
2022-08-22 12:21:19 +02:00
|
|
|
registry.regMutex.Lock()
|
|
|
|
defer registry.regMutex.Unlock()
|
|
|
|
|
|
|
|
p, loaded := registry.Peers.LoadAndDelete(peer.Id)
|
2021-06-10 17:08:40 +02:00
|
|
|
if loaded {
|
2022-08-22 12:21:19 +02:00
|
|
|
pp := p.(*Peer)
|
|
|
|
if peer.StreamID < pp.StreamID {
|
|
|
|
registry.Peers.Store(peer.Id, p)
|
|
|
|
log.Warnf("attempted to remove newer registered stream of a peer [%s] [newer streamID %d, previous StreamID %d]. Ignoring.",
|
|
|
|
peer.Id, pp.StreamID, peer.StreamID)
|
|
|
|
return
|
|
|
|
}
|
2024-09-15 16:46:55 +02:00
|
|
|
registry.metrics.ActivePeers.Add(context.Background(), -1)
|
|
|
|
log.Debugf("peer deregistered [%s]", peer.Id)
|
|
|
|
registry.metrics.Deregistrations.Add(context.Background(), 1)
|
2021-05-01 12:45:37 +02:00
|
|
|
}
|
|
|
|
}
|