mirror of
https://github.com/netbirdio/ice.git
synced 2026-05-22 17:10:58 -07:00
Add RemoteCandidateCache for better performance
Check sourceAddress from first packet validation of STUNTraffic. If validation is true, store it in the cache. Use cache for performance.
This commit is contained in:
@@ -3,7 +3,9 @@
|
||||
|
||||
package ice
|
||||
|
||||
import "net"
|
||||
import (
|
||||
"net"
|
||||
)
|
||||
|
||||
func parseMulticastAnswerAddr(in net.Addr) (net.IP, bool) {
|
||||
switch addr := in.(type) {
|
||||
@@ -49,3 +51,21 @@ func addrEqual(a, b net.Addr) bool {
|
||||
|
||||
return aType == bType && aIP.Equal(bIP) && aPort == bPort
|
||||
}
|
||||
|
||||
// AddrPort is an IP and a port number.
|
||||
type AddrPort [18]byte
|
||||
|
||||
func toAddrPort(addr net.Addr) AddrPort {
|
||||
var ap AddrPort
|
||||
switch addr := addr.(type) {
|
||||
case *net.UDPAddr:
|
||||
copy(ap[:16], addr.IP.To16())
|
||||
ap[16] = uint8(addr.Port >> 8)
|
||||
ap[17] = uint8(addr.Port)
|
||||
case *net.TCPAddr:
|
||||
copy(ap[:16], addr.IP.To16())
|
||||
ap[16] = uint8(addr.Port >> 8)
|
||||
ap[17] = uint8(addr.Port)
|
||||
}
|
||||
return ap
|
||||
}
|
||||
|
||||
@@ -1138,19 +1138,18 @@ func (a *Agent) handleInbound(m *stun.Message, local Candidate, remote net.Addr)
|
||||
|
||||
// validateNonSTUNTraffic processes non STUN traffic from a remote candidate,
|
||||
// and returns true if it is an actual remote candidate
|
||||
func (a *Agent) validateNonSTUNTraffic(local Candidate, remote net.Addr) bool {
|
||||
var isValidCandidate uint64
|
||||
func (a *Agent) validateNonSTUNTraffic(local Candidate, remote net.Addr) (Candidate, bool) {
|
||||
var remoteCandidate Candidate
|
||||
if err := a.run(local.context(), func(ctx context.Context, agent *Agent) {
|
||||
remoteCandidate := a.findRemoteCandidate(local.NetworkType(), remote)
|
||||
remoteCandidate = a.findRemoteCandidate(local.NetworkType(), remote)
|
||||
if remoteCandidate != nil {
|
||||
remoteCandidate.seen(false)
|
||||
atomic.AddUint64(&isValidCandidate, 1)
|
||||
}
|
||||
}); err != nil {
|
||||
a.log.Warnf("failed to validate remote candidate: %v", err)
|
||||
}
|
||||
|
||||
return atomic.LoadUint64(&isValidCandidate) == 1
|
||||
return remoteCandidate, remoteCandidate != nil
|
||||
}
|
||||
|
||||
// GetSelectedCandidatePair returns the selected pair or nil if there is none
|
||||
|
||||
+24
-3
@@ -41,6 +41,8 @@ type candidateBase struct {
|
||||
|
||||
foundationOverride string
|
||||
priorityOverride uint32
|
||||
|
||||
remoteCandidateCaches map[AddrPort]Candidate
|
||||
}
|
||||
|
||||
// Done implements context.Context
|
||||
@@ -234,6 +236,21 @@ func (c *candidateBase) recvLoop(initializedCh <-chan struct{}) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *candidateBase) validateSTUNTrafficCache(addr net.Addr) bool {
|
||||
if candidate, ok := c.remoteCandidateCaches[toAddrPort(addr)]; ok {
|
||||
candidate.seen(false)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *candidateBase) addRemoteCandidateCache(candidate Candidate, srcAddr net.Addr) {
|
||||
if c.validateSTUNTrafficCache(srcAddr) {
|
||||
return
|
||||
}
|
||||
c.remoteCandidateCaches[toAddrPort(srcAddr)] = candidate
|
||||
}
|
||||
|
||||
func (c *candidateBase) handleInboundPacket(buf []byte, srcAddr net.Addr) {
|
||||
a := c.agent()
|
||||
|
||||
@@ -259,9 +276,13 @@ func (c *candidateBase) handleInboundPacket(buf []byte, srcAddr net.Addr) {
|
||||
return
|
||||
}
|
||||
|
||||
if !a.validateNonSTUNTraffic(c, srcAddr) { //nolint:contextcheck
|
||||
a.log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr())
|
||||
return
|
||||
if !c.validateSTUNTrafficCache(srcAddr) {
|
||||
remoteCandidate, valid := a.validateNonSTUNTraffic(c, srcAddr) //nolint:contextcheck
|
||||
if !valid {
|
||||
a.log.Warnf("Discarded message from %s, not a valid remote candidate", c.addr())
|
||||
return
|
||||
}
|
||||
c.addRemoteCandidateCache(remoteCandidate, srcAddr)
|
||||
}
|
||||
|
||||
// Note: This will return packetio.ErrFull if the buffer ever manages to fill up.
|
||||
|
||||
+9
-8
@@ -37,14 +37,15 @@ func NewCandidateHost(config *CandidateHostConfig) (*CandidateHost, error) {
|
||||
|
||||
c := &CandidateHost{
|
||||
candidateBase: candidateBase{
|
||||
id: candidateID,
|
||||
address: config.Address,
|
||||
candidateType: CandidateTypeHost,
|
||||
component: config.Component,
|
||||
port: config.Port,
|
||||
tcpType: config.TCPType,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
id: candidateID,
|
||||
address: config.Address,
|
||||
candidateType: CandidateTypeHost,
|
||||
component: config.Component,
|
||||
port: config.Port,
|
||||
tcpType: config.TCPType,
|
||||
foundationOverride: config.Foundation,
|
||||
priorityOverride: config.Priority,
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
network: config.Network,
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ func NewCandidatePeerReflexive(config *CandidatePeerReflexiveConfig) (*Candidate
|
||||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ func NewCandidateRelay(config *CandidateRelayConfig) (*CandidateRelay, error) {
|
||||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
relayProtocol: config.RelayProtocol,
|
||||
onClose: config.OnClose,
|
||||
|
||||
@@ -55,6 +55,7 @@ func NewCandidateServerReflexive(config *CandidateServerReflexiveConfig) (*Candi
|
||||
Address: config.RelAddr,
|
||||
Port: config.RelPort,
|
||||
},
|
||||
remoteCandidateCaches: map[AddrPort]Candidate{},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user