Documentation
¶
Index ¶
- Constants
- Variables
- func CopyBuffered(dst io.Writer, src io.Reader) (int64, error)
- func DecodeMessage(payload []byte, msg interface{}) error
- func FragmentUDP(sessionID uint32, data []byte, fragIDCounter *uint16, enableFragmentation bool) ([][]byte, error)
- func GetBuffer() *bytes.Buffer
- func GetBufferWithSize(sizeHint int) *bytes.Buffer
- func GetCopyBuffer() *[]byte
- func GetDatagramBuffer() *[]byte
- func GetFragmentBuffer() *[]byte
- func GetReadBuffer() *[]byte
- func InitBufferPool(datagramSize, readSize, fragmentSize int)
- func ParseUDPDatagram(dgram []byte) (uint32, bool, uint16, uint8, uint8, []byte, error)
- func PutBuffer(buf *bytes.Buffer)
- func PutCopyBuffer(buf *[]byte)
- func PutDatagramBuffer(buf *[]byte)
- func PutFragmentBuffer(buf *[]byte)
- func PutReadBuffer(buf *[]byte)
- func ReadMessage(r io.Reader) (msgType byte, payload []byte, err error)
- func ReadTypedMessage(r io.Reader, expectedType byte, msg interface{}) error
- func Relay(a, b io.ReadWriter) error
- func ReleaseDatagramResults(results []DatagramResult)
- func WriteConnClose(w io.Writer, connID uint64, reason string) error
- func WriteError(w io.Writer, code uint32, message string) error
- func WriteHeartbeat(w io.Writer, timestamp int64) error
- func WriteMessage(w io.Writer, msgType byte, payload interface{}) error
- func WriteNewConn(w io.Writer, connID uint64, protocol, sourceAddr, destAddr string, ...) error
- func WriteRegister(w io.Writer, clientID, version string, capabilities []string) error
- func WriteRegisterAck(w io.Writer, success bool, message string) error
- type ConnCloseMsg
- type DatagramResult
- type ErrorMsg
- type FragmentAssembler
- type HeartbeatMsg
- type Message
- type NewConnMsg
- type RegisterAckMsg
- type RegisterMsg
- type ShardedFragmentAssembler
- type UDPBufferPool
Constants ¶
const ( SmallBufferSize = 256 // For heartbeats, errors MediumBufferSize = 4096 // For typical messages LargeBufferSize = 65536 // For large payloads CopyBufferSize = 512 * 1024 // 512KB for data copy operations MaxPooledBuffer = 1024 * 1024 // 1MB - don't pool larger buffers )
Buffer size constants for common message types
const ( MsgTypeRegister = 0x01 // Client registration MsgTypeRegisterAck = 0x02 // Server acknowledgment MsgTypeHeartbeat = 0x03 // Keepalive MsgTypeNewConn = 0x04 // New connection metadata MsgTypeConnClose = 0x06 // Connection closed MsgTypeError = 0xFF // Error message )
Message types
const ( // DefaultDatagramBufferSize is the default size for QUIC datagram buffers DefaultDatagramBufferSize = MaxDatagramSize // 1200 bytes // DefaultReadBufferSize is the default size for UDP read buffers DefaultReadBufferSize = 65535 // DefaultFragmentBufferSize is the default size for fragment storage // Calculated as: DatagramSize - FragmentHeaderSize (9 bytes) DefaultFragmentBufferSize = DefaultDatagramBufferSize - UDPFragHeaderSize )
Default UDP buffer size constants
const ( UDPHeaderSize = 4 // Session ID only (for unfragmented packets) UDPFragHeaderSize = 9 // Full fragment header MaxDatagramSize = 1200 // Safe QUIC datagram payload size MaxUDPPayload = MaxDatagramSize - UDPHeaderSize // Max payload for unfragmented MaxFragPayload = MaxDatagramSize - UDPFragHeaderSize // Max payload per fragment FragmentTimeout = 5 * time.Second // Timeout for incomplete fragments // DefaultShardCount is the default number of shards for the fragment assembler DefaultShardCount = 16 )
UDP fragment header format: [4 bytes session ID][2 bytes fragment ID][1 byte flags][1 byte fragment index][1 byte total fragments][payload] Flags: 0x01 = more fragments follow
const ( FlagMoreFragments = 0x01 FlagFragmented = 0x80 // Indicates this is a fragmented packet )
const ProtocolVersion = "1.0"
Variables ¶
var ( DatagramBufferSize = DefaultDatagramBufferSize ReadBufferSize = DefaultReadBufferSize FragmentBufferSize = DefaultFragmentBufferSize )
Current buffer sizes (can be configured via InitBufferPool)
var ( ErrPacketTooLarge = errors.New("packet too large to fragment") ErrSessionIDMismatch = errors.New("session ID mismatch") ErrInvalidFragIndex = errors.New("invalid fragment index") ErrDatagramTooShort = errors.New("datagram too short") ErrFragmentationDisabled = errors.New("fragmentation disabled, packet too large") )
Functions ¶
func CopyBuffered ¶ added in v1.0.5
CopyBuffered copies from src to dst using a pooled 512KB buffer for better throughput. Returns the number of bytes copied and any error encountered.
func DecodeMessage ¶
DecodeMessage decodes a payload into a message structure
func FragmentUDP ¶ added in v1.0.5
func FragmentUDP(sessionID uint32, data []byte, fragIDCounter *uint16, enableFragmentation bool) ([][]byte, error)
FragmentUDP splits a UDP packet into fragments if needed Returns a slice of datagrams ready to send If enableFragmentation is false and packet is too large, returns error
func GetBufferWithSize ¶
GetBufferWithSize retrieves a buffer from the pool and grows it to the specified size hint. This helps reduce reallocations when the approximate size is known.
func GetCopyBuffer ¶ added in v1.0.5
func GetCopyBuffer() *[]byte
GetCopyBuffer retrieves a copy buffer from the pool.
func GetDatagramBuffer ¶ added in v1.0.5
func GetDatagramBuffer() *[]byte
GetDatagramBuffer returns a buffer for datagram operations. The returned buffer has a length of exactly DatagramBufferSize. Callers must call PutDatagramBuffer when done to return the buffer to the pool.
func GetFragmentBuffer ¶ added in v1.0.5
func GetFragmentBuffer() *[]byte
GetFragmentBuffer returns a buffer for fragment storage. The returned buffer has a length of exactly FragmentBufferSize. Callers must call PutFragmentBuffer when done to return the buffer to the pool.
func GetReadBuffer ¶ added in v1.0.5
func GetReadBuffer() *[]byte
GetReadBuffer returns a buffer for UDP read operations. The returned buffer has a length of exactly ReadBufferSize. Callers must call PutReadBuffer when done to return the buffer to the pool.
func InitBufferPool ¶ added in v1.0.7
func InitBufferPool(datagramSize, readSize, fragmentSize int)
InitBufferPool initializes the buffer pool with custom sizes. This should be called once at startup before any buffer operations. If any size is <= 0, the default value will be used.
func ParseUDPDatagram ¶ added in v1.0.5
ParseUDPDatagram parses a UDP datagram header Returns sessionID, isFragmented, fragID, fragIndex, fragTotal, payload
func PutBuffer ¶
PutBuffer returns a buffer to the pool. Buffers larger than MaxPooledBuffer are not pooled to prevent memory bloat.
func PutCopyBuffer ¶ added in v1.0.5
func PutCopyBuffer(buf *[]byte)
PutCopyBuffer returns a copy buffer to the pool.
func PutDatagramBuffer ¶ added in v1.0.5
func PutDatagramBuffer(buf *[]byte)
PutDatagramBuffer returns a datagram buffer to the pool. If buf is nil or has incorrect size, it is silently discarded.
func PutFragmentBuffer ¶ added in v1.0.5
func PutFragmentBuffer(buf *[]byte)
PutFragmentBuffer returns a fragment buffer to the pool. If buf is nil, it is silently ignored.
func PutReadBuffer ¶ added in v1.0.5
func PutReadBuffer(buf *[]byte)
PutReadBuffer returns a read buffer to the pool. If buf is nil or has incorrect size, it is silently discarded.
func ReadMessage ¶
ReadMessage reads a message from the reader with optimized allocations. Uses a fixed header buffer to avoid allocations for header reading.
func ReadTypedMessage ¶
ReadTypedMessage reads and decodes a message in one call
func Relay ¶ added in v1.0.5
func Relay(a, b io.ReadWriter) error
Relay performs bidirectional copy between two io.ReadWriter. It uses optimized buffers and returns when either direction closes.
func ReleaseDatagramResults ¶ added in v1.0.5
func ReleaseDatagramResults(results []DatagramResult)
ReleaseDatagramResults returns all buffers to the pool. This function should be called after all datagrams have been sent to return the pooled buffers for reuse.
func WriteConnClose ¶
WriteConnClose writes a connection close message
func WriteError ¶
WriteError writes an error message
func WriteHeartbeat ¶
WriteHeartbeat writes a heartbeat message
func WriteMessage ¶
WriteMessage writes a message to the writer using buffer pooling to reduce allocations.
func WriteNewConn ¶
func WriteNewConn(w io.Writer, connID uint64, protocol, sourceAddr, destAddr string, timestamp int64) error
WriteNewConn writes a new connection message
func WriteRegister ¶
WriteRegister writes a registration message
Types ¶
type ConnCloseMsg ¶
ConnCloseMsg indicates connection closure
type DatagramResult ¶ added in v1.0.5
type DatagramResult struct {
Data []byte // Slice of the buffer containing the datagram
Buffer *[]byte // The underlying pooled buffer (nil if not pooled)
}
DatagramResult holds a datagram and its buffer for later release. Data is a slice of the buffer containing the actual datagram content. Buffer is the underlying pooled buffer (nil if not pooled).
func FragmentUDPPooled ¶ added in v1.0.5
func FragmentUDPPooled(sessionID uint32, data []byte, fragIDCounter *atomic.Uint32, enableFragmentation bool) ([]DatagramResult, error)
FragmentUDPPooled splits a UDP packet into fragments using pooled buffers. The caller MUST call ReleaseDatagramResults after sending all datagrams to return the buffers to the pool.
For unfragmented packets (data <= MaxUDPPayload), returns a single DatagramResult with a simple 4-byte header containing only the session ID.
For fragmented packets, returns multiple DatagramResults with 9-byte headers containing session ID, fragment ID, flags, fragment index, and total fragments.
type FragmentAssembler ¶ added in v1.0.5
type FragmentAssembler struct {
// contains filtered or unexported fields
}
FragmentAssembler reassembles fragmented UDP packets
func NewFragmentAssembler ¶ added in v1.0.5
func NewFragmentAssembler() *FragmentAssembler
NewFragmentAssembler creates a new fragment assembler
func (*FragmentAssembler) AddFragment ¶ added in v1.0.5
func (fa *FragmentAssembler) AddFragment(sessionID uint32, fragID uint16, index, total uint8, payload []byte) ([]byte, error)
AddFragment adds a fragment and returns the complete packet if all fragments received Returns (nil, nil) if more fragments are needed
type HeartbeatMsg ¶
type HeartbeatMsg struct {
Timestamp int64 // Unix timestamp
}
HeartbeatMsg is sent periodically to keep connection alive
type Message ¶
type Message struct {
Type byte
Payload interface{}
}
Message wraps a typed message with its type
type NewConnMsg ¶
type NewConnMsg struct {
ConnID uint64 // Unique connection ID
Protocol string // "tcp" or "udp"
SourceAddr string // Original client address (IP:port)
DestAddr string // Target address on traffic listener (IP:port)
Timestamp int64 // Connection timestamp
}
NewConnMsg is sent by server to client when new connection arrives
type RegisterAckMsg ¶
type RegisterAckMsg struct {
Success bool // Registration success
Message string // Optional message
}
RegisterAckMsg is sent by server to acknowledge registration
type RegisterMsg ¶
type RegisterMsg struct {
ClientID string // Unique client identifier
Version string // Protocol version
Capabilities []string // Supported features (e.g., "tcp", "udp")
}
RegisterMsg is sent by client to register with server
type ShardedFragmentAssembler ¶ added in v1.0.5
type ShardedFragmentAssembler struct {
// contains filtered or unexported fields
}
ShardedFragmentAssembler reassembles fragmented UDP packets with reduced lock contention
func NewShardedFragmentAssembler ¶ added in v1.0.5
func NewShardedFragmentAssembler(shardCount int) *ShardedFragmentAssembler
NewShardedFragmentAssembler creates a new sharded fragment assembler
func (*ShardedFragmentAssembler) AddFragment ¶ added in v1.0.5
func (sfa *ShardedFragmentAssembler) AddFragment(sessionID uint32, fragID uint16, index, total uint8, payload []byte) ([]byte, error)
AddFragment adds a fragment and returns the complete packet if all fragments received. It locks only the relevant shard for reduced contention. Uses pooled buffers for fragment storage and tracks them for cleanup. Returns (nil, nil) if more fragments are needed.
type UDPBufferPool ¶ added in v1.0.5
type UDPBufferPool struct {
// contains filtered or unexported fields
}
UDPBufferPool provides pooled buffers for UDP operations. It maintains three tiers of buffer pools optimized for different use cases: - Datagram pool: buffers for QUIC datagram operations - Read pool: buffers for UDP socket read operations - Fragment pool: buffers for fragment storage