Documentation ¶
Overview ¶
Package zerocopy defines interfaces and helper functions for zero-copy read/write operations.
Index ¶
- Constants
- Variables
- 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 PackerUnpackerTestFunc(t *testing.T, packer Packer, unpacker Unpacker)
- func ReadWriterTestFunc(t *testing.T, l, r ReadWriter)
- func Relay(w Writer, r Reader) (n int64, err error)
- func TwoWayRelay(left, right ReadWriter) (nl2r, nr2l int64, err error)
- type CloseRead
- type CloseWrite
- type CopyReadWriter
- type DirectReadCloser
- type DirectReadWriteCloser
- type DirectWriteCloser
- type Headroom
- type InitialPayloader
- type PackUnpacker
- type Packer
- type ReadWriter
- type Reader
- type SimpleUDPClient
- type TCPClient
- type TCPConnCloser
- type TCPServer
- type UDPClient
- type UDPServer
- type Unpacker
- 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 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 PackerUnpackerTestFunc ¶
PackerUnpackerTestFunc tests the packer and the unpacker by using the packer to pack a random payload and using the unpacker to unpack the packed packet.
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 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 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.
func NewCopyReadWriter ¶
func NewCopyReadWriter(rw ReadWriter) *CopyReadWriter
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 PackUnpacker ¶
PackUnpacker implements both Packer and Unpacker interfaces.
type Packer ¶
type Packer interface { Headroom // PackInPlace packs the payload in-place into a packet and returns packet start offset, packet length, // or an error if packing fails. PackInPlace(b []byte, targetAddr socks5.Addr, payloadStart, payloadLen, maxPacketLen int) (packetStart, packetLen int, err error) }
Packer processes raw payload into packets.
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 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 PackUnpacker, addrPort netip.AddrPort, hasAddrPort bool, mtu, 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) NewSession ¶
func (c *SimpleUDPClient) NewSession() (Packer, Unpacker, 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 socks5.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 socks5.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 // NewSession creates a new session and returns the packet packer // and unpacker for the session, or an error. NewSession() (Packer, Unpacker, error) // AddrPort returns the fixed target address and port of packed outgoing packets, // or false if individual packet's target address should be used. AddrPort() (addrPort netip.AddrPort, mtu, fwmark int, ok bool) }
UDPClient stores the necessary information for creating new sessions.
type UDPServer ¶
type UDPServer 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) (Unpacker, 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) (Packer, error) }
UDPServer deals with incoming sessions.
type Unpacker ¶
type Unpacker interface { Headroom // UnpackInPlace unpacks the packet in-place and returns target address, payload start offset, payload length, // or an error if unpacking fails. // // If the packed packet does not contain information about the target address, hasTargetAddr should be false, // and the packet's source address should be used instead. UnpackInPlace(b []byte, packetStart, packetLen int) (targetAddr socks5.Addr, hasTargetAddr bool, payloadStart, payloadLen int, err error) }
Unpacker processes packets into raw payload.
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.