Documentation
¶
Overview ¶
Package p2p provides peer-to-peer direct connection capabilities.
The p2p package implements NAT traversal techniques to establish direct connections between clients when possible, falling back to server relay when P2P fails.
Index ¶
- Variables
- type ConnectionMode
- type Endpoint
- type HolePunchConfig
- type HolePuncher
- type KeyPair
- type Manager
- func (m *Manager) AttemptP2P(ctx context.Context, peerEndpoint Endpoint, cipher *SessionCipher) (net.PacketConn, *net.UDPAddr, error)
- func (m *Manager) FallbackToRelay(reason string)
- func (m *Manager) Init(ctx context.Context) error
- func (m *Manager) IsEnabled() bool
- func (m *Manager) Mode() ConnectionMode
- func (m *Manager) NATInfo() *NATInfo
- type ManagerConfig
- type NATInfo
- type NATType
- type Predictor
- type STUNClient
- type STUNConfig
- type SessionCipher
- type Transport
- func (t *Transport) Close() error
- func (t *Transport) IsEncrypted() bool
- func (t *Transport) LocalAddr() net.Addr
- func (t *Transport) Read(buf []byte) (int, error)
- func (t *Transport) RemoteAddr() net.Addr
- func (t *Transport) Stats() TransportStats
- func (t *Transport) Write(data []byte) (int, error)
- type TransportConfig
- type TransportStats
- type UDPMux
- type UDPStream
Constants ¶
This section is empty.
Variables ¶
var ErrMuxClosed = errors.New("p2p: mux closed")
ErrMuxClosed is returned when operations are attempted on a closed mux.
Functions ¶
This section is empty.
Types ¶
type ConnectionMode ¶
type ConnectionMode int
ConnectionMode represents how the connection is established.
const ( // ModeRelay means traffic goes through the server (default). ModeRelay ConnectionMode = iota // ModeP2P means a direct UDP connection was established. ModeP2P )
func (ConnectionMode) String ¶
func (m ConnectionMode) String() string
String returns the connection mode name.
type HolePunchConfig ¶
type HolePunchConfig struct {
// MaxAttempts is the maximum number of punch attempts.
MaxAttempts int
// Interval is the delay between punch attempts.
Interval time.Duration
// Timeout is the overall timeout for the hole punch operation.
Timeout time.Duration
}
HolePunchConfig holds configuration for UDP hole punching.
func DefaultHolePunchConfig ¶
func DefaultHolePunchConfig() HolePunchConfig
DefaultHolePunchConfig returns sensible defaults.
type HolePuncher ¶
type HolePuncher struct {
// contains filtered or unexported fields
}
HolePuncher performs UDP hole punching between two peers.
func NewHolePuncher ¶
func NewHolePuncher(config HolePunchConfig) *HolePuncher
NewHolePuncher creates a new hole puncher.
func (*HolePuncher) Punch ¶
func (h *HolePuncher) Punch(ctx context.Context, localConn net.PacketConn, peerEndpoint Endpoint) (*net.UDPAddr, error)
Punch attempts to establish a UDP connection to the peer via hole punching. It sends probe packets to the peer's public endpoint while simultaneously listening for incoming probes. Returns the established connection if successful.
func (*HolePuncher) SetCipher ¶
func (h *HolePuncher) SetCipher(c *SessionCipher)
SetCipher sets the session cipher for authenticated hole punching.
type KeyPair ¶
type KeyPair struct {
// Private is the ECDH private key.
Private *ecdh.PrivateKey
// Public is the ECDH public key (raw 32-byte X25519 representation).
Public []byte
}
KeyPair holds an ECDH X25519 key pair for key exchange.
func GenerateKeyPair ¶
GenerateKeyPair generates a new X25519 ECDH key pair.
type Manager ¶
type Manager struct {
// contains filtered or unexported fields
}
Manager coordinates P2P connection establishment and fallback.
func NewManager ¶
func NewManager(config ManagerConfig) *Manager
NewManager creates a new P2P manager.
func (*Manager) AttemptP2P ¶
func (m *Manager) AttemptP2P(ctx context.Context, peerEndpoint Endpoint, cipher *SessionCipher) (net.PacketConn, *net.UDPAddr, error)
AttemptP2P tries to establish a P2P connection with a peer. It returns the established UDP connection or an error (caller should fallback to relay). If a SessionCipher is provided, hole-punch probes will be HMAC-authenticated.
func (*Manager) FallbackToRelay ¶
FallbackToRelay switches back to relay mode.
func (*Manager) Mode ¶
func (m *Manager) Mode() ConnectionMode
Mode returns the current connection mode.
type ManagerConfig ¶
type ManagerConfig struct {
// Enabled controls whether P2P is attempted.
Enabled bool
// STUNConfig is the STUN client configuration.
STUNConfig STUNConfig
// HolePunchConfig is the hole punch configuration.
HolePunchConfig HolePunchConfig
// FallbackTimeout is how long to wait before falling back to relay.
FallbackTimeout time.Duration
}
ManagerConfig holds configuration for the P2P manager.
func DefaultManagerConfig ¶
func DefaultManagerConfig() ManagerConfig
DefaultManagerConfig returns sensible defaults.
type NATInfo ¶
type NATInfo struct {
// Type is the detected NAT type.
Type NATType `json:"type"`
// PublicAddr is the public-facing endpoint as seen by the STUN server.
PublicAddr Endpoint `json:"public_addr"`
// LocalAddr is the local endpoint used for the STUN request.
LocalAddr Endpoint `json:"local_addr"`
}
NATInfo contains the results of NAT discovery.
type NATType ¶
type NATType int
NATType represents the type of NAT detected.
const ( // NATUnknown indicates the NAT type could not be determined. NATUnknown NATType = iota // NATNone indicates no NAT — the host has a public IP. NATNone // NATFullCone indicates a full cone (one-to-one) NAT. NATFullCone // NATRestrictedCone indicates a restricted cone NAT. NATRestrictedCone // NATPortRestricted indicates a port-restricted cone NAT. NATPortRestricted // NATSymmetric indicates a symmetric NAT (hardest to traverse). NATSymmetric )
func (NATType) IsTraversable ¶
IsTraversable returns whether P2P hole punching is likely to succeed.
type Predictor ¶
type Predictor struct {
// contains filtered or unexported fields
}
Predictor predicts the next external port for symmetric NAT traversal.
Symmetric NATs assign a new external port for each unique (dest IP, dest port) tuple. Some implementations increment ports sequentially, making prediction possible. This is a heuristic and may not work for all NAT implementations.
type STUNClient ¶
type STUNClient struct {
// contains filtered or unexported fields
}
STUNClient performs STUN binding requests to discover the public endpoint.
func NewSTUNClient ¶
func NewSTUNClient(config STUNConfig) *STUNClient
NewSTUNClient creates a new STUN client.
func (*STUNClient) Discover ¶
func (s *STUNClient) Discover(ctx context.Context) (*NATInfo, error)
Discover performs NAT discovery by querying STUN servers. It returns the detected NAT type and public endpoint.
func (*STUNClient) DiscoverEndpoint ¶
func (s *STUNClient) DiscoverEndpoint(ctx context.Context) (*Endpoint, error)
DiscoverEndpoint performs a simple STUN binding request to get the public endpoint. This is faster than full Discover() and sufficient when NAT type is not needed.
type STUNConfig ¶
type STUNConfig struct {
// Servers is a list of STUN server addresses.
Servers []string
// Timeout is the deadline for each STUN request.
Timeout time.Duration
// Retries is the number of retry attempts per server.
Retries int
}
STUNConfig holds STUN client configuration.
func DefaultSTUNConfig ¶
func DefaultSTUNConfig() STUNConfig
DefaultSTUNConfig returns sensible defaults for STUN discovery.
type SessionCipher ¶
type SessionCipher struct {
// contains filtered or unexported fields
}
SessionCipher provides authenticated encryption for a P2P session. It uses AES-256-GCM with a monotonic nonce derived from a sequence counter.
func DeriveSession ¶
func DeriveSession(localPriv *ecdh.PrivateKey, remotePubBytes []byte) (*SessionCipher, error)
DeriveSession performs ECDH key agreement and derives session keys. It takes the local private key and the remote peer's public key bytes, and returns a SessionCipher ready for encrypting/decrypting data.
func (*SessionCipher) Decrypt ¶
func (sc *SessionCipher) Decrypt(data []byte) ([]byte, error)
Decrypt decrypts data produced by Encrypt. Input format: [8-byte nonce counter][GCM ciphertext+tag].
func (*SessionCipher) Encrypt ¶
func (sc *SessionCipher) Encrypt(plaintext []byte) ([]byte, error)
Encrypt encrypts plaintext using AES-256-GCM with a unique nonce. The output format is: [8-byte nonce counter][GCM ciphertext+tag].
func (*SessionCipher) Overhead ¶
func (sc *SessionCipher) Overhead() int
Overhead returns the total byte overhead added by encryption. This is 8 (nonce counter) + GCM tag size (16) = 24 bytes.
func (*SessionCipher) SignProbe ¶
func (sc *SessionCipher) SignProbe(payload []byte) []byte
SignProbe creates an HMAC-SHA256 signature for a hole-punch probe payload. The caller should append this tag to the probe packet.
func (*SessionCipher) VerifyProbe ¶
func (sc *SessionCipher) VerifyProbe(payload, tag []byte) bool
VerifyProbe verifies the HMAC-SHA256 signature on a hole-punch probe.
type Transport ¶
type Transport struct {
// contains filtered or unexported fields
}
Transport provides a reliable stream-like interface over UDP. It implements a simple ARQ (Automatic Repeat reQuest) protocol for data reliability over the unreliable UDP connection. When a SessionCipher is set, all data packets are encrypted with AES-256-GCM, providing confidentiality and integrity.
func NewTransport ¶
func NewTransport(conn net.PacketConn, peerAddr *net.UDPAddr, config TransportConfig, cipher *SessionCipher) *Transport
NewTransport creates a new UDP transport. An optional SessionCipher enables end-to-end encryption for all data packets.
func (*Transport) IsEncrypted ¶
IsEncrypted returns whether this transport is using end-to-end encryption.
func (*Transport) RemoteAddr ¶
RemoteAddr returns the peer address.
func (*Transport) Stats ¶
func (t *Transport) Stats() TransportStats
Stats returns transport statistics.
type TransportConfig ¶
type TransportConfig struct {
// MaxPacketSize is the maximum UDP packet size.
MaxPacketSize int
// RetransmitTimeout is the timeout before retransmitting a packet.
RetransmitTimeout time.Duration
// MaxRetransmits is the maximum number of retransmissions before giving up.
MaxRetransmits int
// AckTimeout is the timeout for waiting for an ACK.
AckTimeout time.Duration
// RecvBufferSize is the size of the receive channel buffer.
RecvBufferSize int
}
TransportConfig holds configuration for the UDP transport.
func DefaultTransportConfig ¶
func DefaultTransportConfig() TransportConfig
DefaultTransportConfig returns sensible defaults.
type TransportStats ¶
TransportStats contains transport statistics.
type UDPMux ¶ added in v0.5.0
type UDPMux struct {
// contains filtered or unexported fields
}
UDPMux multiplexes multiple bidirectional streams over one UDP connection.
func NewUDPMux ¶ added in v0.5.0
func NewUDPMux(conn net.PacketConn, peerAddr *net.UDPAddr, config TransportConfig, cipher *SessionCipher, isInitiator bool) *UDPMux
NewUDPMux creates a multiplexer over conn/peerAddr. isInitiator must be true on exactly one side of a P2P connection to ensure stream-ID uniqueness; the other side must pass false.
func (*UDPMux) AcceptStream ¶ added in v0.5.0
AcceptStream blocks until an incoming stream is available.
func (*UDPMux) OpenStream ¶ added in v0.5.0
OpenStream creates a new outbound stream and performs the SYN handshake.
func (*UDPMux) RemoteAddr ¶ added in v0.5.0
RemoteAddr returns the peer UDP address.
type UDPStream ¶ added in v0.5.0
type UDPStream struct {
// contains filtered or unexported fields
}
UDPStream is a single logical stream within a UDPMux.
func (*UDPStream) Close ¶ added in v0.5.0
Close sends a FIN to the peer and marks this stream as closed.
func (*UDPStream) Read ¶ added in v0.5.0
Read blocks until data arrives from the peer. It honors the io.Reader contract: if the caller's buffer is smaller than one incoming segment, the remainder is buffered and returned on the next call.
func (*UDPStream) StreamID ¶ added in v0.5.0
StreamID returns the numeric identifier of this stream.