zerocopy

package
v1.10.1 Latest Latest
Warning

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

Go to latest
Published: Feb 22, 2024 License: AGPL-3.0 Imports: 13 Imported by: 0

Documentation

Overview

Package zerocopy defines interfaces and helper functions for zero-copy read/write operations.

Index

Constants

View Source
const (
	IPv4HeaderLength = 20
	IPv6HeaderLength = 40
	UDPHeaderLength  = 8

	// Next Header + Hdr Ext Len + Option Type + Opt Data Len + Jumbo Payload Length (u32be)
	JumboPayloadOptionLength = 8
)

Used in packet size calculations.

Variables

View Source
var (
	ErrPacketTooSmall = errors.New("packet too small to unpack")
	ErrPayloadTooBig  = errors.New("payload too big to pack")
)
View Source
var (
	ErrAcceptDoneNoRelay     = errors.New("the accepted connection has been handled without relaying")
	ErrAcceptRequiresTCPConn = errors.New("rawRW is required to be a *net.TCPConn")
)

Functions

func ClientServerPackerUnpackerTestFunc added in v1.4.0

func ClientServerPackerUnpackerTestFunc(t tester, clientPacker ClientPacker, clientUnpacker ClientUnpacker, serverPacker ServerPacker, serverUnpacker ServerUnpacker)

ClientServerPackerUnpackerTestFunc tests the client and server following these steps: 1. Client packer packs. 2. Server unpacker unpacks. 3. Server packer packs. 4. Client unpacker unpacks.

func CloseWriteDrain

func CloseWriteDrain(conn *net.TCPConn, logger *zap.Logger)

CloseWriteDrain closes the write end of the TCP connection, then drain the read end.

func CopyWriteOnce

func CopyWriteOnce(w Writer, b []byte) (n int, err error)

func DirectTwoWayRelay added in v1.4.0

func DirectTwoWayRelay(left, right DirectReadWriteCloser) (nl2r, nr2l int64, err error)

DirectTwoWayRelay relays data between left and right using io.Copy. It returns the number of bytes sent from left to right, from right to left, and any error occurred during transfer.

func ForceReset

func ForceReset(conn *net.TCPConn, logger *zap.Logger)

ForceReset forces a reset of the TCP connection, regardless of whether there's unread data or not.

func JustClose added in v1.3.0

func JustClose(conn *net.TCPConn, logger *zap.Logger)

JustClose closes the TCP connection without any special handling.

func MaxPacketSizeForAddr

func MaxPacketSizeForAddr(mtu int, addr netip.Addr) int

MaxPacketSizeForAddr calculates the maximum packet size for the given address based on the MTU and the address family.

func NoopClose added in v1.8.0

func NoopClose() error

NoopClose is a no-op close function.

func ReadWriterTestFunc

func ReadWriterTestFunc(t tester, l, r ReadWriter)

ReadWriterTestFunc tests the left and right ReadWriters by performing 2 writes on each ReadWriter and validating the read results.

The left and right ReadWriters must be connected with a duplex pipe.

func Relay

func Relay(w Writer, r Reader) (n int64, err error)

Relay reads from r and writes to w using zero-copy methods. It returns the number of bytes transferred, and any error occurred during transfer.

func ReplyWithGibberish added in v1.2.0

func ReplyWithGibberish(conn *net.TCPConn, logger *zap.Logger)

ReplyWithGibberish keeps reading and replying with random garbage until EOF or error.

func TwoWayRelay

func TwoWayRelay(left, right ReadWriter) (nl2r, nr2l int64, err error)

TwoWayRelay relays data between left and right using zero-copy methods. It returns the number of bytes sent from left to right, from right to left, and any error occurred during transfer.

Types

type ClientPackUnpacker added in v1.1.0

type ClientPackUnpacker interface {
	ClientPacker
	ClientUnpacker
}

ClientPackUnpacker implements both ClientPacker and ClientUnpacker interfaces.

type ClientPacker added in v1.1.0

type ClientPacker interface {
	// ClientPackerInfo returns information about the client packer.
	ClientPackerInfo() ClientPackerInfo

	// PackInPlace packs the payload in-place into a packet ready for sending and returns
	// the destination address, packet start offset, packet length, or an error if packing fails.
	PackInPlace(ctx context.Context, b []byte, targetAddr conn.Addr, payloadStart, payloadLen int) (destAddrPort netip.AddrPort, packetStart, packetLen int, err error)
}

ClientPacker processes raw payload into packets ready to be sent to servers.

type ClientPackerInfo added in v1.6.0

type ClientPackerInfo struct {
	Headroom Headroom
}

ClientPackerInfo contains information about a client packer.

type ClientUnpacker added in v1.1.0

type ClientUnpacker interface {
	// ClientUnpackerInfo returns information about the client unpacker.
	ClientUnpackerInfo() ClientUnpackerInfo

	// UnpackInPlace unpacks the packet in-place and returns packet source address, payload start offset, payload length, or an error if unpacking fails.
	UnpackInPlace(b []byte, packetSourceAddrPort netip.AddrPort, packetStart, packetLen int) (payloadSourceAddrPort netip.AddrPort, payloadStart, payloadLen int, err error)
}

ClientUnpacker processes packets received from the server into raw payload.

type ClientUnpackerInfo added in v1.6.0

type ClientUnpackerInfo struct {
	Headroom Headroom
}

ClientUnpackerInfo contains information about a client unpacker.

type CloseRead

type CloseRead interface {
	// CloseRead indicates to the underlying reader that no further reads will happen.
	CloseRead() error
}

CloseRead provides the CloseRead method.

type CloseWrite

type CloseWrite interface {
	// CloseWrite indicates to the underlying writer that no further writes will happen.
	CloseWrite() error
}

CloseWrite provides the CloseWrite method.

type CopyReadWriter

type CopyReadWriter struct {
	ReadWriter
	// contains filtered or unexported fields
}

CopyReadWriter wraps a ReadWriter and provides the io.ReadWriter Read and Write methods by copying from and to internal buffers and using the zerocopy methods on them.

The io.ReaderFrom ReadFrom method is implemented using the internal write buffer without copying.

func NewCopyReadWriter

func NewCopyReadWriter(rw ReadWriter) *CopyReadWriter

func (*CopyReadWriter) Read

func (rw *CopyReadWriter) Read(b []byte) (n int, err error)

Read implements the io.Reader Read method.

func (*CopyReadWriter) ReadFrom added in v1.1.0

func (rw *CopyReadWriter) ReadFrom(r io.Reader) (n int64, err error)

ReadFrom implements the io.ReaderFrom ReadFrom method.

func (*CopyReadWriter) Write

func (rw *CopyReadWriter) Write(b []byte) (n int, err error)

Write implements the io.Writer Write method.

type DirectReadWriteCloser

type DirectReadWriteCloser interface {
	io.ReadWriteCloser
	CloseRead
	CloseWrite
}

DirectReadWriteCloser extends io.ReadWriteCloser with CloseRead and CloseWrite.

type DirectReadWriteCloserOpener added in v1.3.0

type DirectReadWriteCloserOpener interface {
	// Open opens a [DirectReadWriteCloser] with the specified initial payload.
	Open(ctx context.Context, b []byte) (DirectReadWriteCloser, error)
}

DirectReadWriteCloserOpener provides the Open method to open a DirectReadWriteCloser.

type DirectReader added in v1.5.1

type DirectReader interface {
	// DirectReader returns the underlying reader for direct reads.
	DirectReader() io.Reader
}

DirectReader provides access to the underlying io.Reader.

type DirectWriter added in v1.5.1

type DirectWriter interface {
	// DirectWriter returns the underlying writer for direct writes.
	DirectWriter() io.Writer
}

DirectWriter provides access to the underlying io.Writer.

type Headroom

type Headroom struct {
	// Front is the minimum space required at the beginning of the buffer before payload.
	Front int

	// Rear is the minimum space required at the end of the buffer after payload.
	Rear int
}

Headroom reports the amount of extra space required in read/write buffers besides the payload.

func MaxHeadroom added in v1.6.0

func MaxHeadroom(first, second Headroom) Headroom

MaxHeadroom returns the maximum front and rear headroom of the two headroom pairs.

func UDPRelayHeadroom added in v1.6.0

func UDPRelayHeadroom(packerHeadroom, unpackerHeadroom Headroom) Headroom

UDPRelayHeadroom returns the packer headroom subtracted by the unpacker headroom.

type ReadWriter

type ReadWriter interface {
	Reader
	Writer
	CloseRead
	CloseWrite
	io.Closer
}

ReadWriter provides a stream interface for reading and writing.

type Reader

type Reader interface {
	// ReaderInfo returns information about the reader.
	ReaderInfo() ReaderInfo

	// ReadZeroCopy uses b as buffer space to initiate a read operation.
	//
	// b must have at least [ReaderInfo.Headroom.Front] bytes before payloadBufStart
	// and [ReaderInfo.Headroom.Rear] bytes after payloadBufStart + payloadBufLen.
	//
	// payloadBufLen must be at least [ReaderInfo.MinPayloadBufferSizePerRead].
	//
	// The read operation may use the whole space of b.
	// The actual payload will be confined in [payloadBufStart, payloadBufLen).
	//
	// If no error occurs, the returned payload is b[payloadBufStart : payloadBufStart+payloadLen].
	ReadZeroCopy(b []byte, payloadBufStart, payloadBufLen int) (payloadLen int, err error)
}

Reader provides a stream interface for reading.

type ReaderInfo added in v1.6.0

type ReaderInfo struct {
	Headroom Headroom

	// MinPayloadBufferSizePerRead is the minimum size of payload buffer
	// the ReadZeroCopy method requires for an unbuffered read.
	//
	// This is usually required by chunk-based protocols to be able to read
	// whole chunks without needing internal caching.
	MinPayloadBufferSizePerRead int
}

ReaderInfo contains information about a reader.

type ServerPackUnpacker added in v1.1.0

type ServerPackUnpacker interface {
	ServerPacker
	ServerUnpacker
}

ServerPackUnpacker implements both ServerPacker and ServerUnpacker interfaces.

type ServerPacker added in v1.1.0

type ServerPacker interface {
	// ServerPackerInfo returns information about the server packer.
	ServerPackerInfo() ServerPackerInfo

	// PackInPlace packs the payload in-place into a packet ready for sending and returns
	// packet start offset, packet length, or an error if packing fails.
	PackInPlace(b []byte, sourceAddrPort netip.AddrPort, payloadStart, payloadLen, maxPacketLen int) (packetStart, packetLen int, err error)
}

ServerPacker processes raw payload into packets ready to be sent to clients.

type ServerPackerInfo added in v1.6.0

type ServerPackerInfo struct {
	Headroom Headroom
}

ServerPackerInfo contains information about a server packer.

type ServerUnpacker added in v1.1.0

type ServerUnpacker interface {
	// ServerUnpackerInfo returns information about the server unpacker.
	ServerUnpackerInfo() ServerUnpackerInfo

	// UnpackInPlace unpacks the packet in-place and returns target address, payload start offset, payload length, or an error if unpacking fails.
	UnpackInPlace(b []byte, sourceAddrPort netip.AddrPort, packetStart, packetLen int) (targetAddr conn.Addr, payloadStart, payloadLen int, err error)

	// NewPacker creates a new server session for the current client session and returns the server session's packer, or an error.
	NewPacker() (ServerPacker, error)
}

ServerUnpacker processes packets received from the client into raw payload.

type ServerUnpackerInfo added in v1.6.0

type ServerUnpackerInfo struct {
	Headroom Headroom
}

ServerUnpackerInfo contains information about a server unpacker.

type SimpleDirectReadWriteCloserOpener added in v1.3.0

type SimpleDirectReadWriteCloserOpener struct {
	DirectReadWriteCloser
}

SimpleDirectReadWriteCloserOpener wraps a DirectReadWriteCloser for the Open method to return.

func (*SimpleDirectReadWriteCloserOpener) Open added in v1.3.0

Open implements the DirectReadWriteCloserOpener Open method.

type TCPClient

type TCPClient interface {
	// ClientInfo returns information about the TCP client.
	Info() TCPClientInfo

	// Dial creates a connection to the target address under the protocol's
	// encapsulation and returns the established connection and a ReadWriter for read-write access.
	Dial(ctx context.Context, targetAddr conn.Addr, payload []byte) (rawRW DirectReadWriteCloser, rw ReadWriter, err error)
}

TCPClient is a protocol's TCP client.

type TCPClientInfo added in v1.6.0

type TCPClientInfo struct {
	// Name is the name of the TCP client.
	Name string

	// NativeInitialPayload reports whether the protocol natively supports
	// sending the initial payload within or along with the request header.
	NativeInitialPayload bool
}

TCPClientInfo contains information about a TCP client.

type TCPConnCloser

type TCPConnCloser func(conn *net.TCPConn, logger *zap.Logger)

TCPConnCloser handles a potentially malicious TCP connection. Upon returning, the TCP connection is safe to close.

func ParseRejectPolicy

func ParseRejectPolicy(rejectPolicy string, serverDefault TCPConnCloser) (TCPConnCloser, error)

ParseRejectPolicy parses a string representation of a reject policy.

type TCPConnOpener added in v1.3.0

type TCPConnOpener struct {
	// contains filtered or unexported fields
}

TCPConnOpener stores information for opening TCP connections.

TCPConnOpener implements the DirectReadWriteCloserOpener interface.

func NewTCPConnOpener added in v1.3.0

func NewTCPConnOpener(dialer conn.Dialer, network, address string) *TCPConnOpener

NewTCPConnOpener returns a new TCPConnOpener using the specified dialer, network and address.

func (*TCPConnOpener) Open added in v1.3.0

Open implements the DirectReadWriteCloserOpener Open method.

type TCPServer

type TCPServer interface {
	// ServerInfo returns information about the TCP server.
	Info() TCPServerInfo

	// Accept takes a newly-accepted TCP connection and wraps it into a protocol stream server.
	//
	// To make it easier to write tests, rawRW is of type [DirectReadWriteCloser].
	// If the stream server needs to access TCP-specific features, it must type-assert and return
	// [ErrAcceptRequiresTCPConn] on error.
	//
	// If the returned error is [ErrAcceptDoneNoRelay], the connection has been handled by this method.
	// Two-way relay is not needed.
	//
	// If accept fails, the returned payload must be either nil/empty or the data that has been read
	// from the connection.
	Accept(rawRW DirectReadWriteCloser) (rw ReadWriter, targetAddr conn.Addr, payload []byte, username string, err error)
}

TCPServer provides a protocol's TCP service.

type TCPServerInfo added in v1.6.0

type TCPServerInfo struct {
	// NativeInitialPayload reports whether the protocol natively supports
	// sending the initial payload within or along with the request header.
	NativeInitialPayload bool

	// DefaultTCPConnCloser is the server's default function for handling a potentially malicious TCP connection.
	DefaultTCPConnCloser TCPConnCloser
}

TCPServerInfo contains information about a TCP server.

type UDPClient

type UDPClient interface {
	// Info returns information about the client.
	Info() UDPClientInfo

	// NewSession creates a new client session, and returns the session info or an error.
	// The returned [UDPClientInfo] is always valid, even when session creation fails.
	NewSession(ctx context.Context) (UDPClientInfo, UDPClientSession, error)
}

UDPClient stores information for creating new client sessions.

type UDPClientInfo added in v1.6.0

type UDPClientInfo struct {
	// Name is the name of the UDP client.
	Name string

	// PackerHeadroom is the headroom required by the packet packer.
	PackerHeadroom Headroom

	// MTU is the MTU of the client's designated network path.
	MTU int

	// ListenConfig is the [conn.ListenConfig] for opening client sockets.
	ListenConfig conn.ListenConfig
}

UDPClientInfo contains information about a UDP client.

type UDPClientSession added in v1.8.0

type UDPClientSession struct {
	// MaxPacketSize is the maximum size of outgoing packets.
	MaxPacketSize int

	// Packer is the packet packer for the session.
	Packer ClientPacker

	// Unpacker is the packet unpacker for the session.
	Unpacker ClientUnpacker

	// Close closes the session.
	Close func() error
}

UDPClientSession contains information about a UDP client session.

type UDPNATServer added in v1.1.0

type UDPNATServer interface {
	// Info returns information about the server.
	Info() UDPNATServerInfo

	// NewUnpacker creates a new packet unpacker for the session.
	//
	// The returned unpacker is then used by the caller to unpack the incoming packet.
	// Upon successful unpacking, the unpacker's NewPacker method can be called to create
	// a corresponding packet packer.
	NewUnpacker() (ServerUnpacker, error)
}

UDPNATServer stores information for creating new server sessions.

type UDPNATServerInfo added in v1.6.0

type UDPNATServerInfo struct {
	// UnpackerHeadroom is the headroom required by the packet unpacker.
	UnpackerHeadroom Headroom
}

UDPNATServerInfo contains information about a UDP NAT server.

type UDPSessionServer added in v1.1.0

type UDPSessionServer interface {
	sync.Locker

	// Info returns information about the server.
	Info() UDPSessionServerInfo

	// SessionInfo extracts session ID from a received packet b.
	//
	// The returned session ID is then used by the caller to look up the session table.
	// If no matching entries were found, NewUnpacker should be called to create a new
	// packet unpacker for the packet.
	SessionInfo(b []byte) (csid uint64, err error)

	// NewUnpacker creates a new packet unpacker for the specified client session.
	//
	// The returned unpacker is then used by the caller to unpack the incoming packet.
	// Upon successful unpacking, the unpacker's NewPacker method can be called to create
	// a corresponding server session.
	NewUnpacker(b []byte, csid uint64) (serverUnpacker ServerUnpacker, username string, err error)
}

UDPSessionServer deals with incoming sessions.

type UDPSessionServerInfo added in v1.6.0

type UDPSessionServerInfo struct {
	// UnpackerHeadroom is the headroom required by the packet unpacker.
	UnpackerHeadroom Headroom

	// MinNATTimeout is the server's minimum allowed NAT timeout.
	// 0 means no requirement.
	MinNATTimeout time.Duration
}

UDPSessionServerInfo contains information about a UDP session server.

type Writer

type Writer interface {
	// WriterInfo returns information about the writer.
	WriterInfo() WriterInfo

	// WriteZeroCopy uses b as buffer space to initiate a write operation.
	//
	// b must have at least [WriterInfo.Headroom.Front] bytes before payloadBufStart
	// and [WriterInfo.Headroom.Rear] bytes after payloadBufStart + payloadBufLen.
	//
	// payloadLen must not exceed [WriterInfo.MaxPayloadSizePerWrite].
	//
	// The write operation may use the whole space of b.
	WriteZeroCopy(b []byte, payloadStart, payloadLen int) (payloadWritten int, err error)
}

Writer provides a stream interface for writing.

type WriterInfo added in v1.6.0

type WriterInfo struct {
	Headroom Headroom

	// MaxPayloadSizePerWrite is the maximum size of payload
	// the WriteZeroCopy method can write at a time.
	//
	// This is usually required by chunk-based protocols to be able to write
	// one chunk at a time without needing to break up the payload.
	//
	// 0 means no size limit.
	MaxPayloadSizePerWrite int
}

WriterInfo contains information about a writer.

Jump to

Keyboard shortcuts

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