mirror of
https://github.com/netbirdio/netbird.git
synced 2025-06-21 18:22:37 +02:00
Fix chicken-egg problem in the ice agent creation
This commit is contained in:
parent
48310ef99c
commit
2f32e0d8cf
@ -393,7 +393,7 @@ func (conn *Conn) iCEConnectionIsReady(priority ConnPriority, iceConnInfo ICECon
|
|||||||
}
|
}
|
||||||
|
|
||||||
endpointUdpAddr, _ := net.ResolveUDPAddr(endpoint.Network(), endpoint.String())
|
endpointUdpAddr, _ := net.ResolveUDPAddr(endpoint.Network(), endpoint.String())
|
||||||
conn.log.Debugf("Conn resolved IP for %s: %s", endpoint, endpointUdpAddr.IP)
|
conn.log.Debugf("Conn resolved IP is %s for endopint %s", endpoint, endpointUdpAddr.IP)
|
||||||
|
|
||||||
conn.connID = nbnet.GenerateConnID()
|
conn.connID = nbnet.GenerateConnID()
|
||||||
for _, hook := range conn.beforeAddPeerHooks {
|
for _, hook := range conn.beforeAddPeerHooks {
|
||||||
@ -461,20 +461,20 @@ func (conn *Conn) doHandshake() (*OfferAnswer, error) {
|
|||||||
return nil, ErrSignalIsNotReady
|
return nil, ErrSignalIsNotReady
|
||||||
}
|
}
|
||||||
|
|
||||||
uFreg, pwd, err := conn.workerICE.GetLocalUserCredentials()
|
var (
|
||||||
|
ha HandshakeArgs
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
ha.IceUFrag, ha.IcePwd, err = conn.workerICE.GetLocalUserCredentials()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
conn.log.Errorf("failed to get local user credentials: %v", err)
|
conn.log.Errorf("failed to get local user credentials: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := conn.workerRelay.RelayAddress()
|
addr, err := conn.workerRelay.RelayAddress()
|
||||||
if err != nil {
|
if err == nil {
|
||||||
conn.log.Errorf("failed to get local relay address: %v", err)
|
ha.RelayAddr = addr.String()
|
||||||
}
|
}
|
||||||
return conn.handshaker.Handshake(HandshakeArgs{
|
return conn.handshaker.Handshake(ha)
|
||||||
uFreg,
|
|
||||||
pwd,
|
|
||||||
addr.String(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (conn *Conn) evalStatus() ConnStatus {
|
func (conn *Conn) evalStatus() ConnStatus {
|
||||||
|
@ -13,6 +13,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pion/ice/v3"
|
"github.com/pion/ice/v3"
|
||||||
|
"github.com/pion/randutil"
|
||||||
"github.com/pion/stun/v2"
|
"github.com/pion/stun/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
@ -27,6 +28,14 @@ const (
|
|||||||
iceDisconnectedTimeoutDefault = 6 * time.Second
|
iceDisconnectedTimeoutDefault = 6 * time.Second
|
||||||
// iceRelayAcceptanceMinWaitDefault is the same as in the Pion ICE package
|
// iceRelayAcceptanceMinWaitDefault is the same as in the Pion ICE package
|
||||||
iceRelayAcceptanceMinWaitDefault = 2 * time.Second
|
iceRelayAcceptanceMinWaitDefault = 2 * time.Second
|
||||||
|
|
||||||
|
lenUFrag = 16
|
||||||
|
lenPwd = 32
|
||||||
|
runesAlpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
failedTimeout = 6 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type ICEConfig struct {
|
type ICEConfig struct {
|
||||||
@ -74,11 +83,13 @@ type WorkerICE struct {
|
|||||||
selectedPriority ConnPriority
|
selectedPriority ConnPriority
|
||||||
|
|
||||||
agent *ice.Agent
|
agent *ice.Agent
|
||||||
muxAgent sync.RWMutex
|
muxAgent sync.Mutex
|
||||||
|
|
||||||
StunTurn []*stun.URI
|
StunTurn []*stun.URI
|
||||||
|
|
||||||
sentExtraSrflx bool
|
sentExtraSrflx bool
|
||||||
|
localUfrag string
|
||||||
|
localPwd string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewWorkerICE(ctx context.Context, log *log.Entry, config ConnConfig, configICE ICEConfig, signaler *Signaler, ifaceDiscover stdnet.ExternalIFaceDiscover, statusRecorder *Status, onICEConnReady OnICEConnReadyCallback, onStatusChanged func(ConnStatus), doHandshakeFn DoHandshake) *WorkerICE {
|
func NewWorkerICE(ctx context.Context, log *log.Entry, config ConnConfig, configICE ICEConfig, signaler *Signaler, ifaceDiscover stdnet.ExternalIFaceDiscover, statusRecorder *Status, onICEConnReady OnICEConnReadyCallback, onStatusChanged func(ConnStatus), doHandshakeFn DoHandshake) *WorkerICE {
|
||||||
@ -127,13 +138,22 @@ func (w *WorkerICE) SetupICEConnection(hasRelayOnLocally bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctx, ctxCancel := context.WithCancel(w.ctx)
|
ctx, ctxCancel := context.WithCancel(w.ctx)
|
||||||
|
w.muxAgent.Lock()
|
||||||
agent, err := w.reCreateAgent(ctxCancel, preferredCandidateTypes)
|
agent, err := w.reCreateAgent(ctxCancel, preferredCandidateTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctxCancel()
|
ctxCancel()
|
||||||
|
w.muxAgent.Unlock()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
w.muxAgent.Lock()
|
|
||||||
w.agent = agent
|
w.agent = agent
|
||||||
|
// generate credentials for the next loop. Important the credentials are generated before handshake, because
|
||||||
|
// the handshake could provide a cached offer-answer
|
||||||
|
w.localUfrag, w.localPwd, err = generateICECredentials()
|
||||||
|
if err != nil {
|
||||||
|
ctxCancel()
|
||||||
|
w.muxAgent.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
w.muxAgent.Unlock()
|
w.muxAgent.Unlock()
|
||||||
|
|
||||||
err = w.agent.GatherCandidates()
|
err = w.agent.GatherCandidates()
|
||||||
@ -191,8 +211,8 @@ func (w *WorkerICE) SetupICEConnection(hasRelayOnLocally bool) {
|
|||||||
|
|
||||||
// OnRemoteCandidate Handles ICE connection Candidate provided by the remote peer.
|
// OnRemoteCandidate Handles ICE connection Candidate provided by the remote peer.
|
||||||
func (w *WorkerICE) OnRemoteCandidate(candidate ice.Candidate, haRoutes route.HAMap) {
|
func (w *WorkerICE) OnRemoteCandidate(candidate ice.Candidate, haRoutes route.HAMap) {
|
||||||
w.muxAgent.RLocker()
|
w.muxAgent.Lock()
|
||||||
defer w.muxAgent.RUnlock()
|
defer w.muxAgent.Unlock()
|
||||||
w.log.Debugf("OnRemoteCandidate from peer %s -> %s", w.config.Key, candidate.String())
|
w.log.Debugf("OnRemoteCandidate from peer %s -> %s", w.config.Key, candidate.String())
|
||||||
if w.agent == nil {
|
if w.agent == nil {
|
||||||
return
|
return
|
||||||
@ -210,14 +230,18 @@ func (w *WorkerICE) OnRemoteCandidate(candidate ice.Candidate, haRoutes route.HA
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorkerICE) GetLocalUserCredentials() (frag string, pwd string, err error) {
|
func (w *WorkerICE) GetLocalUserCredentials() (frag string, pwd string, err error) {
|
||||||
if w.agent == nil {
|
w.muxAgent.Lock()
|
||||||
return "", "", errors.New("ICE Agent is not initialized")
|
defer w.muxAgent.Unlock()
|
||||||
|
|
||||||
|
if w.localUfrag != "" && w.localPwd != "" {
|
||||||
|
return w.localUfrag, w.localPwd, nil
|
||||||
}
|
}
|
||||||
return w.agent.GetLocalUserCredentials()
|
|
||||||
|
w.localUfrag, w.localPwd, err = generateICECredentials()
|
||||||
|
return w.localUfrag, w.localPwd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *WorkerICE) reCreateAgent(ctxCancel context.CancelFunc, relaySupport []ice.CandidateType) (*ice.Agent, error) {
|
func (w *WorkerICE) reCreateAgent(ctxCancel context.CancelFunc, relaySupport []ice.CandidateType) (*ice.Agent, error) {
|
||||||
failedTimeout := 6 * time.Second
|
|
||||||
transportNet, err := w.newStdNet()
|
transportNet, err := w.newStdNet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.log.Errorf("failed to create pion's stdnet: %s", err)
|
w.log.Errorf("failed to create pion's stdnet: %s", err)
|
||||||
@ -232,15 +256,17 @@ func (w *WorkerICE) reCreateAgent(ctxCancel context.CancelFunc, relaySupport []i
|
|||||||
NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4, ice.NetworkTypeUDP6},
|
NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4, ice.NetworkTypeUDP6},
|
||||||
Urls: w.configICE.StunTurn.Load().([]*stun.URI),
|
Urls: w.configICE.StunTurn.Load().([]*stun.URI),
|
||||||
CandidateTypes: relaySupport,
|
CandidateTypes: relaySupport,
|
||||||
FailedTimeout: &failedTimeout,
|
|
||||||
InterfaceFilter: stdnet.InterfaceFilter(w.configICE.InterfaceBlackList),
|
InterfaceFilter: stdnet.InterfaceFilter(w.configICE.InterfaceBlackList),
|
||||||
UDPMux: w.configICE.UDPMux,
|
UDPMux: w.configICE.UDPMux,
|
||||||
UDPMuxSrflx: w.configICE.UDPMuxSrflx,
|
UDPMuxSrflx: w.configICE.UDPMuxSrflx,
|
||||||
NAT1To1IPs: w.configICE.NATExternalIPs,
|
NAT1To1IPs: w.configICE.NATExternalIPs,
|
||||||
Net: transportNet,
|
Net: transportNet,
|
||||||
|
FailedTimeout: &failedTimeout,
|
||||||
DisconnectedTimeout: &iceDisconnectedTimeout,
|
DisconnectedTimeout: &iceDisconnectedTimeout,
|
||||||
KeepaliveInterval: &iceKeepAlive,
|
KeepaliveInterval: &iceKeepAlive,
|
||||||
RelayAcceptanceMinWait: &iceRelayAcceptanceMinWait,
|
RelayAcceptanceMinWait: &iceRelayAcceptanceMinWait,
|
||||||
|
LocalUfrag: w.localUfrag,
|
||||||
|
LocalPwd: w.localPwd,
|
||||||
}
|
}
|
||||||
|
|
||||||
if w.configICE.DisableIPv6Discovery {
|
if w.configICE.DisableIPv6Discovery {
|
||||||
@ -448,3 +474,17 @@ func isRelayed(pair *ice.CandidatePair) bool {
|
|||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func generateICECredentials() (string, string, error) {
|
||||||
|
ufrag, err := randutil.GenerateCryptoRandomString(lenUFrag, runesAlpha)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd, err := randutil.GenerateCryptoRandomString(lenPwd, runesAlpha)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return ufrag, pwd, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user