mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-21 01:36:46 +00:00
[client] Fix/v4 stun routing (#4430)
Deduplicate STUN package sending. Originally, because every peer shared the same UDP address, the library could not distinguish which STUN message was associated with which candidate. As a result, the Pion library responded from all candidates for every STUN message.
This commit is contained in:
64
client/iface/udpmux/doc.go
Normal file
64
client/iface/udpmux/doc.go
Normal file
@@ -0,0 +1,64 @@
|
||||
// Package udpmux provides a custom implementation of a UDP multiplexer
|
||||
// that allows multiple logical ICE connections to share a single underlying
|
||||
// UDP socket. This is based on Pion's ICE library, with modifications for
|
||||
// NetBird's requirements.
|
||||
//
|
||||
// # Background
|
||||
//
|
||||
// In WebRTC and NAT traversal scenarios, ICE (Interactive Connectivity
|
||||
// Establishment) is responsible for discovering candidate network paths
|
||||
// and maintaining connectivity between peers. Each ICE connection
|
||||
// normally requires a dedicated UDP socket. However, using one socket
|
||||
// per candidate can be inefficient and difficult to manage.
|
||||
//
|
||||
// This package introduces SingleSocketUDPMux, which allows multiple ICE
|
||||
// candidate connections (muxed connections) to share a single UDP socket.
|
||||
// It handles demultiplexing of packets based on ICE ufrag values, STUN
|
||||
// attributes, and candidate IDs.
|
||||
//
|
||||
// # Usage
|
||||
//
|
||||
// The typical flow is:
|
||||
//
|
||||
// 1. Create a UDP socket (net.PacketConn).
|
||||
// 2. Construct Params with the socket and optional logger/net stack.
|
||||
// 3. Call NewSingleSocketUDPMux(params).
|
||||
// 4. For each ICE candidate ufrag, call GetConn(ufrag, addr, candidateID)
|
||||
// to obtain a logical PacketConn.
|
||||
// 5. Use the returned PacketConn just like a normal UDP connection.
|
||||
//
|
||||
// # STUN Message Routing Logic
|
||||
//
|
||||
// When a STUN packet arrives, the mux decides which connection should
|
||||
// receive it using this routing logic:
|
||||
//
|
||||
// Primary Routing: Candidate Pair ID
|
||||
// - Extract the candidate pair ID from the STUN message using
|
||||
// ice.CandidatePairIDFromSTUN(msg)
|
||||
// - The target candidate is the locally generated candidate that
|
||||
// corresponds to the connection that should handle this STUN message
|
||||
// - If found, use the target candidate ID to lookup the specific
|
||||
// connection in candidateConnMap
|
||||
// - Route the message directly to that connection
|
||||
//
|
||||
// Fallback Routing: Broadcasting
|
||||
// When candidate pair ID is not available or lookup fails:
|
||||
// - Collect connections from addressMap based on source address
|
||||
// - Find connection using username attribute (ufrag) from STUN message
|
||||
// - Remove duplicate connections from the list
|
||||
// - Send the STUN message to all collected connections
|
||||
//
|
||||
// # Peer Reflexive Candidate Discovery
|
||||
//
|
||||
// When a remote peer sends a STUN message from an unknown source address
|
||||
// (from a candidate that has not been exchanged via signal), the ICE
|
||||
// library will:
|
||||
// - Generate a new peer reflexive candidate for this source address
|
||||
// - Extract or assign a candidate ID based on the STUN message attributes
|
||||
// - Create a mapping between the new peer reflexive candidate ID and
|
||||
// the appropriate local connection
|
||||
//
|
||||
// This discovery mechanism ensures that STUN messages from newly discovered
|
||||
// peer reflexive candidates can be properly routed to the correct local
|
||||
// connection without requiring fallback broadcasting.
|
||||
package udpmux
|
||||
Reference in New Issue
Block a user