Documentation
¶
Overview ¶
Package transport provides the UDP transport layer for discv5.
The transport handles:
- UDP socket management (IPv4 and IPv6)
- Packet sending and receiving
- Per-IP rate limiting
- Metrics collection
- Graceful shutdown
Index ¶
- Constants
- type Config
- type Metrics
- func (m *Metrics) BytesReceived() uint64
- func (m *Metrics) BytesSent() uint64
- func (m *Metrics) IncrementDropped()
- func (m *Metrics) IncrementRateLimited()
- func (m *Metrics) IncrementReceiveErrors()
- func (m *Metrics) IncrementSendErrors()
- func (m *Metrics) PacketsReceived() uint64
- func (m *Metrics) PacketsSent() uint64
- func (m *Metrics) RateLimited() uint64
- func (m *Metrics) ReceiveErrors() uint64
- func (m *Metrics) RecordReceived(bytes uint64)
- func (m *Metrics) RecordSent(bytes uint64)
- func (m *Metrics) Reset()
- func (m *Metrics) SendErrors() uint64
- func (m *Metrics) Snapshot() MetricsSnapshot
- type MetricsSnapshot
- type PacketHandler
- type RateLimiter
- type RateLimiterStats
- type UDPTransport
- func (t *UDPTransport) AddHandler(handler func(data []byte, from *net.UDPAddr, localAddr *net.UDPAddr) bool)
- func (t *UDPTransport) Close() error
- func (t *UDPTransport) Conn() *net.UDPConn
- func (t *UDPTransport) LocalAddr() *net.UDPAddr
- func (t *UDPTransport) Metrics() *Metrics
- func (t *UDPTransport) Send(data []byte, to *net.UDPAddr, from *net.UDPAddr) error
- func (t *UDPTransport) SendTo(data []byte, to *net.UDPAddr) error
Constants ¶
const ( // MaxPacketSize is the maximum size of a UDP packet (1280 bytes for IPv6 MTU) MaxPacketSize = 1280 // DefaultReadBuffer is the default size for the UDP read buffer DefaultReadBuffer = 2 * 1024 * 1024 // 2 MB // DefaultWriteBuffer is the default size for the UDP write buffer DefaultWriteBuffer = 2 * 1024 * 1024 // 2 MB )
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// ListenAddr is the address to bind to (e.g., "0.0.0.0:9000")
// Ignored if Conn is provided.
ListenAddr string
// Conn is an optional existing UDP connection to use instead of creating a new one.
// When provided, ListenAddr, ReadBuffer, and WriteBuffer are ignored.
Conn *net.UDPConn
// Logger for debug and error messages (optional)
Logger logrus.FieldLogger
// RateLimitPerIP is the maximum packets per second per IP (0 = no limit)
RateLimitPerIP int
// ReadBuffer size in bytes (0 = use default)
// Ignored if Conn is provided.
ReadBuffer int
// WriteBuffer size in bytes (0 = use default)
// Ignored if Conn is provided.
WriteBuffer int
}
Config contains configuration for the UDP transport.
type Metrics ¶
type Metrics struct {
// contains filtered or unexported fields
}
Metrics tracks statistics for the UDP transport.
All operations are atomic and thread-safe.
func (*Metrics) BytesReceived ¶
BytesReceived returns the number of bytes received.
func (*Metrics) IncrementDropped ¶
func (m *Metrics) IncrementDropped()
IncrementDropped increments the dropped packet counter.
func (*Metrics) IncrementRateLimited ¶
func (m *Metrics) IncrementRateLimited()
IncrementRateLimited increments the rate-limited packet counter.
func (*Metrics) IncrementReceiveErrors ¶
func (m *Metrics) IncrementReceiveErrors()
IncrementReceiveErrors increments the receive error counter.
func (*Metrics) IncrementSendErrors ¶
func (m *Metrics) IncrementSendErrors()
IncrementSendErrors increments the send error counter.
func (*Metrics) PacketsReceived ¶
PacketsReceived returns the number of packets received.
func (*Metrics) PacketsSent ¶
PacketsSent returns the number of packets sent.
func (*Metrics) RateLimited ¶
RateLimited returns the number of rate-limited packets.
func (*Metrics) ReceiveErrors ¶
ReceiveErrors returns the number of receive errors.
func (*Metrics) RecordReceived ¶
RecordReceived records a received packet.
func (*Metrics) RecordSent ¶
RecordSent records a sent packet.
func (*Metrics) SendErrors ¶
SendErrors returns the number of send errors.
func (*Metrics) Snapshot ¶
func (m *Metrics) Snapshot() MetricsSnapshot
Snapshot returns a snapshot of the current metrics.
Example:
snapshot := transport.Metrics().Snapshot()
fmt.Printf("Packets sent: %d, received: %d\n",
snapshot.PacketsSent, snapshot.PacketsReceived)
type MetricsSnapshot ¶
type MetricsSnapshot struct {
PacketsSent uint64
PacketsReceived uint64
PacketsDropped uint64
BytesSent uint64
BytesReceived uint64
SendErrors uint64
ReceiveErrors uint64
RateLimited uint64
}
Snapshot returns a snapshot of the current metrics.
type PacketHandler ¶
PacketHandler is called when a packet is received.
The handler should process the packet and return quickly. Long-running operations should be done in a separate goroutine. Returns true if the packet was handled, false if not recognized. The localAddr parameter is the local address that received the packet (important for 0.0.0.0 bindings).
type RateLimiter ¶
type RateLimiter struct {
// contains filtered or unexported fields
}
RateLimiter implements per-IP rate limiting using a token bucket algorithm.
Each IP address gets its own bucket with a maximum number of tokens. Tokens are refilled at a constant rate. When a packet arrives, a token is consumed. If no tokens are available, the packet is rejected.
func NewRateLimiter ¶
func NewRateLimiter(rate int) *RateLimiter
NewRateLimiter creates a new per-IP rate limiter.
rate specifies the maximum number of packets per second per IP address.
Example:
// Allow 100 packets per second per IP limiter := NewRateLimiter(100) defer limiter.Stop()
func (*RateLimiter) Allow ¶
func (rl *RateLimiter) Allow(ip net.IP) bool
Allow checks if a packet from the given IP should be allowed.
Returns true if the packet should be processed, false if it should be dropped.
This method is thread-safe.
func (*RateLimiter) Stats ¶
func (rl *RateLimiter) Stats() RateLimiterStats
Stats returns current statistics about the rate limiter.
func (*RateLimiter) Stop ¶
func (rl *RateLimiter) Stop()
Stop stops the rate limiter and cleans up resources.
type RateLimiterStats ¶
type RateLimiterStats struct {
// ActiveIPs is the number of IPs currently being tracked
ActiveIPs int
// Rate is the configured rate limit per IP
Rate int
}
Stats returns statistics about the rate limiter.
type UDPTransport ¶
type UDPTransport struct {
// contains filtered or unexported fields
}
UDPTransport manages UDP socket I/O for the discv5 protocol.
It provides:
- Concurrent packet sending and receiving
- Per-IP rate limiting
- Metrics collection
- Graceful shutdown
- Multiple protocol handler support
func NewUDPTransport ¶
func NewUDPTransport(cfg *Config) (*UDPTransport, error)
NewUDPTransport creates a new UDP transport.
The transport starts listening immediately and spawns goroutines for packet reception. Use AddHandler() to register protocol handlers. Call Close() to shut down gracefully.
Example:
transport, err := NewUDPTransport(&Config{
ListenAddr: "0.0.0.0:9000",
})
if err != nil {
return err
}
defer transport.Close()
// Register handlers
transport.AddHandler(myHandler)
func (*UDPTransport) AddHandler ¶
func (t *UDPTransport) AddHandler(handler func(data []byte, from *net.UDPAddr, localAddr *net.UDPAddr) bool)
AddHandler registers a packet handler.
Handlers are called in the order they are registered. The first handler to return true stops the handler chain. If a handler returns false, the next handler in the chain is tried.
For optimal performance, register handlers in order of likelihood:
- Register discv5 before discv4 (discv5 has magic string, faster to validate)
- Each handler should quickly validate and return false if not their protocol
This is thread-safe and can be called while the transport is running.
Example:
transport.AddHandler(func(data []byte, from *net.UDPAddr, localAddr *net.UDPAddr) bool {
// Try to handle packet, return true if successful
err := myProtocol.HandlePacket(data, from, localAddr)
return err == nil
})
func (*UDPTransport) Close ¶
func (t *UDPTransport) Close() error
Close gracefully shuts down the transport.
It stops accepting new packets, waits for active handlers to complete (with a timeout), and closes the UDP socket.
Example:
if err := transport.Close(); err != nil {
log.Printf("Error closing transport: %v", err)
}
func (*UDPTransport) Conn ¶
func (t *UDPTransport) Conn() *net.UDPConn
Conn returns the underlying UDP connection.
func (*UDPTransport) LocalAddr ¶
func (t *UDPTransport) LocalAddr() *net.UDPAddr
LocalAddr returns the local UDP address being listened on.
func (*UDPTransport) Metrics ¶
func (t *UDPTransport) Metrics() *Metrics
Metrics returns the current transport metrics.
func (*UDPTransport) Send ¶
Send sends a packet to the specified address.
This is thread-safe and can be called concurrently. Returns an error if the transport is closed or if sending fails.
The from parameter can optionally specify the source address to send from. This is important when the socket is bound to 0.0.0.0 - the response should be sent from the same address that received the request.
Example:
err := transport.Send(packetData, remoteAddr, localAddr)
if err != nil {
log.Printf("Failed to send: %v", err)
}