Documentation ¶
Overview ¶
Package zerocopy defines interfaces and helper functions for zero-copy read/write operations.
Index ¶
- Constants
- Variables
- func ClientServerPackUnpackerTestFunc(t *testing.T, c ClientPackUnpacker, s ServerPackUnpacker)
- func CloseWriteDrain(conn *net.TCPConn, serverName, listenAddress, clientAddress string, ...)
- func CopyWriteOnce(rw ReadWriter, b []byte) (n int, err error)
- func ForceReset(conn *net.TCPConn, serverName, listenAddress, clientAddress string, ...)
- func MaxPacketSizeForAddr(mtu int, addr netip.Addr) int
- func ReadWriterTestFunc(t *testing.T, l, r ReadWriter)
- func Relay(w Writer, r Reader) (n int64, err error)
- func ReplyWithGibberish(conn *net.TCPConn, serverName, listenAddress, clientAddress string, ...)
- func TwoWayRelay(left, right ReadWriter) (nl2r, nr2l int64, err error)
- type ClientPackUnpacker
- type ClientPacker
- type ClientUnpacker
- type CloseRead
- type CloseWrite
- type CopyReadWriter
- type DirectReadCloser
- type DirectReadWriteCloser
- type DirectWriteCloser
- type Headroom
- type InitialPayloader
- type ReadWriter
- type Reader
- type ServerPackUnpacker
- type ServerPacker
- type ServerUnpacker
- type SimpleUDPClient
- type TCPClient
- type TCPConnCloser
- type TCPServer
- type UDPClient
- type UDPNATServer
- type UDPSessionServer
- type Writer
- type ZeroHeadroom
Constants ¶
const ( IPv4HeaderLength = 20 IPv6HeaderLength = 40 UDPHeaderLength = 8 )
Used in packet size calculations.
Variables ¶
var ( ErrPacketTooSmall = errors.New("packet too small to unpack") ErrPayloadTooBig = errors.New("payload too big to pack") )
var ErrAcceptDoneNoRelay = errors.New("the accepted connection has been handled without relaying")
Functions ¶
func ClientServerPackUnpackerTestFunc ¶ added in v1.1.0
func ClientServerPackUnpackerTestFunc(t *testing.T, c ClientPackUnpacker, s ServerPackUnpacker)
ClientServerPackUnpackerTestFunc tests the client pack-unpacker and the server pack-unpacker with the following precedure: 1. Client packer packs. 2. Server unpacker unpacks. 3. Server packer packs. 4. Client unpacker unpacks.
func CloseWriteDrain ¶
func CloseWriteDrain(conn *net.TCPConn, serverName, listenAddress, clientAddress string, logger *zap.Logger)
CloseWriteDrain closes the write end of the TCP connection, then drain the read end.
func CopyWriteOnce ¶
func CopyWriteOnce(rw ReadWriter, b []byte) (n int, err error)
func ForceReset ¶
func ForceReset(conn *net.TCPConn, serverName, listenAddress, clientAddress string, logger *zap.Logger)
ForceReset forces a reset of the TCP connection, regardless of whether there's unread data or not.
func MaxPacketSizeForAddr ¶
MaxPacketSizeForAddr calculates the maximum packet size for the given address based on the MTU and the address family.
func ReadWriterTestFunc ¶
func ReadWriterTestFunc(t *testing.T, 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 ¶
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, serverName, listenAddress, clientAddress string, 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 { Headroom // 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(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 ClientUnpacker ¶ added in v1.1.0
type ClientUnpacker interface { Headroom // 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 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.
type DirectReadCloser ¶
type DirectReadCloser interface { // DirectReadCloser returns the underlying reader for direct reads. DirectReadCloser() io.ReadCloser }
DirectReadCloser provides access to the underlying io.ReadCloser.
type DirectReadWriteCloser ¶
type DirectReadWriteCloser interface { io.ReadWriteCloser CloseRead CloseWrite }
DirectReadWriteCloser extends io.ReadWriteCloser with CloseRead and CloseWrite.
type DirectWriteCloser ¶
type DirectWriteCloser interface { // DirectWriteCloser returns the underlying writer for direct writes. DirectWriteCloser() io.WriteCloser }
DirectWriteCloser provides access to the underlying io.WriteCloser.
type Headroom ¶
type Headroom interface { // FrontHeadroom returns the minimum space required at the beginning of the buffer before payload. FrontHeadroom() int // RearHeadroom returns the minimum space required at the end of the buffer after payload. RearHeadroom() int }
Headroom is implemented by readers and writers that require extra buffer space as headroom in read/write calls.
type InitialPayloader ¶
type InitialPayloader interface { // NativeInitialPayload reports whether the protocol natively supports // sending the initial payload within or along with the request header. // // No matter true or false, the Dial method must process the initial payload. // // When false, the Accept method will not return non-empty initial payload. NativeInitialPayload() bool }
InitialPayloader is implemented by a protocol's TCP client or server when the protocol's initial handshake message can carry payload.
type ReadWriter ¶
type ReadWriter interface { Reader Writer CloseRead CloseWrite }
ReadWriter provides a stream interface for reading and writing.
type Reader ¶
type Reader interface { Headroom // MinPayloadBufferSizePerRead returns 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 // ReadZeroCopy uses b as buffer space to initiate a read operation. // // b must have at least FrontOverhead() bytes before payloadBufStart // and RearOverhead() bytes after payloadBufStart + payloadBufLen. // // payloadBufLen must be at least 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) io.Closer }
Reader provides a stream interface for reading.
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 { Headroom // 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 ServerUnpacker ¶ added in v1.1.0
type ServerUnpacker interface { Headroom // 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) }
ServerUnpacker processes packets received from the client into raw payload.
type SimpleUDPClient ¶
type SimpleUDPClient struct {
// contains filtered or unexported fields
}
SimpleUDPClient wraps a PackUnpacker and uses it for all sessions.
SimpleUDPClient implements the UDPClient interface.
func NewSimpleUDPClient ¶
func NewSimpleUDPClient(p ClientPackUnpacker, maxPacketSize, fwmark, frontHeadroom, rearHeadroom int) *SimpleUDPClient
NewSimpleUDPClient wraps a PackUnpacker into a UDPClient and uses it for all sessions.
func (*SimpleUDPClient) FrontHeadroom ¶
func (c *SimpleUDPClient) FrontHeadroom() int
FrontHeadroom implements the UDPClient FrontHeadroom method.
func (*SimpleUDPClient) LinkInfo ¶ added in v1.1.0
func (c *SimpleUDPClient) LinkInfo() (int, int)
LinkInfo implements the UDPClient LinkInfo method.
func (*SimpleUDPClient) NewSession ¶
func (c *SimpleUDPClient) NewSession() (ClientPacker, ClientUnpacker, error)
NewSession implements the UDPClient NewSession method.
func (*SimpleUDPClient) RearHeadroom ¶
func (c *SimpleUDPClient) RearHeadroom() int
RearHeadroom implements the UDPClient RearHeadroom method.
type TCPClient ¶
type TCPClient interface { InitialPayloader // 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(targetAddr conn.Addr, payload []byte) (tfoConn tfo.Conn, rw ReadWriter, err error) }
TCPClient is a protocol's TCP client.
type TCPConnCloser ¶
type TCPConnCloser func(conn *net.TCPConn, serverName, listenAddress, clientAddress string, 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, server TCPServer) (TCPConnCloser, error)
ParseRejectPolicy parses a string representation of a reject policy.
type TCPServer ¶
type TCPServer interface { InitialPayloader // Accept takes a newly-accepted TCP connection and wraps it into a // protocol stream server. // // If the returned error is ErrAcceptDoneNoRelay, the connection has been handled by this method. // Two-way relay is not needed. Accept(conn tfo.Conn) (rw ReadWriter, targetAddr conn.Addr, payload []byte, err error) // DefaultTCPConnCloser returns the default function to handle the closing // of a potentially malicious TCP connection. // // If no special handling is required, return nil. DefaultTCPConnCloser() TCPConnCloser }
TCPServer provides a protocol's TCP service.
type UDPClient ¶
type UDPClient interface { // Headroom reports client packer headroom requirements. Headroom // LinkInfo returns the maximum size of outgoing packets and fwmark. LinkInfo() (maxPacketSize, fwmark int) // NewSession creates a new session and returns the packet packer // and unpacker for the session, or an error. NewSession() (ClientPacker, ClientUnpacker, error) }
UDPClient stores information for creating new client sessions.
type UDPNATServer ¶ added in v1.1.0
type UDPNATServer interface { // Headroom reports server pack-unpacker headroom requirements. Headroom // NewSession creates a new session and returns the packet packer // and unpacker for the session, or an error. NewSession() (ServerPacker, ServerUnpacker, error) }
UDPNATServer stores information for creating new server sessions.
type UDPSessionServer ¶ added in v1.1.0
type UDPSessionServer interface { // Headroom reports server unpacker headroom requirements. Headroom // 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, NewPacker should be called to create a corresponding // server session. NewUnpacker(b []byte, csid uint64) (ServerUnpacker, error) // NewPacker creates a new server session for the specified client session // and returns the server session's packer, or an error. NewPacker(csid uint64) (ServerPacker, error) }
UDPSessionServer deals with incoming sessions.
type Writer ¶
type Writer interface { Headroom // MaxPayloadSizePerWrite returns 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. // // If there isn't a maximum limit, return 0. MaxPayloadSizePerWrite() int // WriteZeroCopy uses b as buffer space to initiate a write operation. // // b must have at least FrontOverhead() bytes before payloadBufStart // and RearOverhead() bytes after payloadBufStart + payloadBufLen. // // payloadLen must not be greater than MaxPayloadSizePerWrite(). // // The write operation may use the whole space of b. WriteZeroCopy(b []byte, payloadStart, payloadLen int) (payloadWritten int, err error) io.Closer }
Writer provides a stream interface for writing.
type ZeroHeadroom ¶
type ZeroHeadroom struct{}
ZeroHeadroom can be embedded by types that have zero headroom.
func (ZeroHeadroom) FrontHeadroom ¶
func (z ZeroHeadroom) FrontHeadroom() int
FrontHeadroom implements the Headroom FrontHeadroom method.
func (ZeroHeadroom) RearHeadroom ¶
func (z ZeroHeadroom) RearHeadroom() int
RearHeadroom implements the Headroom RearHeadroom method.