transport

package
v0.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 9, 2025 License: MIT Imports: 10 Imported by: 0

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

View Source
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 NewMetrics

func NewMetrics() *Metrics

NewMetrics creates a new metrics tracker.

func (*Metrics) BytesReceived

func (m *Metrics) BytesReceived() uint64

BytesReceived returns the number of bytes received.

func (*Metrics) BytesSent

func (m *Metrics) BytesSent() uint64

BytesSent returns the number of bytes sent.

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

func (m *Metrics) PacketsReceived() uint64

PacketsReceived returns the number of packets received.

func (*Metrics) PacketsSent

func (m *Metrics) PacketsSent() uint64

PacketsSent returns the number of packets sent.

func (*Metrics) RateLimited

func (m *Metrics) RateLimited() uint64

RateLimited returns the number of rate-limited packets.

func (*Metrics) ReceiveErrors

func (m *Metrics) ReceiveErrors() uint64

ReceiveErrors returns the number of receive errors.

func (*Metrics) RecordReceived

func (m *Metrics) RecordReceived(bytes uint64)

RecordReceived records a received packet.

func (*Metrics) RecordSent

func (m *Metrics) RecordSent(bytes uint64)

RecordSent records a sent packet.

func (*Metrics) Reset

func (m *Metrics) Reset()

Reset resets all metrics to zero.

func (*Metrics) SendErrors

func (m *Metrics) SendErrors() uint64

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

type PacketHandler func(data []byte, from *net.UDPAddr, localAddr *net.UDPAddr) bool

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

func (t *UDPTransport) Send(data []byte, to *net.UDPAddr, from *net.UDPAddr) error

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)
}

func (*UDPTransport) SendTo

func (t *UDPTransport) SendTo(data []byte, to *net.UDPAddr) error

SendTo sends a packet to the specified address. This is the interface method required by protocol.Transport.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL