tcp

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: Jun 9, 2026 License: Apache-2.0 Imports: 9 Imported by: 0

Documentation

Overview

Package tcp implements VORTEX's raw TCP tunnel engine (build plan M2.1): a bidirectional byte pump between a client connection and a backend connection, a per-backend connection pool, a weighted round-robin selector, and an accept loop that wires them together. It is the data plane for `protocol: "tcp"` routes. Standard library only (Non-Negotiable Rule #10).

Index

Constants

This section is empty.

Variables

View Source
var ErrIdleTimeout = errors.New("tcp tunnel: idle timeout")

ErrIdleTimeout is returned when a tunnel is closed because no bytes flowed in either direction within the configured IdleTimeout.

View Source
var ErrNoBackends = errors.New("tcp: no backends configured")

ErrNoBackends is returned when a selector is constructed or queried with no backends configured.

View Source
var ErrPoolClosed = errors.New("tcp pool: closed")

ErrPoolClosed is returned by Get after the pool has been closed.

Functions

func Tunnel

func Tunnel(ctx context.Context, client, backend net.Conn, cfg TunnelConfig) error

Tunnel copies bytes bidirectionally between client and backend until either side closes, an error occurs, the idle timeout fires, or ctx is cancelled.

Each direction runs in its own goroutine. When one direction finishes, the peer's write half is closed (CloseWrite on *net.TCPConn) so the other end observes EOF and drains cleanly; the function then waits for the second direction before returning. A non-nil result reports the first unexpected error; a clean close (EOF on both sides) returns nil. Idle timeout returns ErrIdleTimeout.

Types

type BackendAddr

type BackendAddr struct {
	// Addr is the dial target, "host:port".
	Addr string
	// Weight biases selection in weighted round-robin; <=0 is treated as 1.
	Weight int
}

BackendAddr is a backend target with a load-balancing weight. It is the shared backend descriptor used by the selector and the listener.

type Listener

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

Listener accepts client connections and tunnels each to a selected backend.

func NewListener

func NewListener(cfg ListenerConfig) (*Listener, error)

NewListener validates cfg and constructs a Listener.

func (*Listener) Listen

func (l *Listener) Listen(ctx context.Context) error

Listen binds the listener and serves until ctx is cancelled. On cancel it stops accepting, waits up to drainTimeout for active tunnels, then returns nil. It returns an error only on an unexpected bind/accept failure.

func (*Listener) Stats

func (l *Listener) Stats() ListenerStats

Stats returns a snapshot of the listener's counters.

func (*Listener) UpdateBackends

func (l *Listener) UpdateBackends(backends []BackendAddr) error

UpdateBackends atomically replaces the backend set for zero-downtime config reload. Existing tunnels are unaffected; new connections use the new set.

type ListenerConfig

type ListenerConfig struct {
	// ListenAddr is the local bind address, e.g. ":5432".
	ListenAddr string
	// Backends are the upstream targets (weighted).
	Backends []BackendAddr
	// Pool supplies backend connections. Required.
	Pool *Pool
	// Tunnel configures each bidirectional copy.
	Tunnel TunnelConfig
	// MaxConnections caps concurrent tunnels; 0 means unlimited.
	MaxConnections int
	// TLSConfig, when non-nil, wraps each accepted connection in a TLS server
	// handshake before tunneling — used for mTLS routes. Nil means plain TCP.
	TLSConfig *tls.Config
	// Logger receives tunnel/accept diagnostics; defaults to slog.Default.
	Logger *slog.Logger
}

ListenerConfig configures a TCP tunnel Listener.

type ListenerStats

type ListenerStats struct {
	Active   int64
	Total    int64
	Rejected int64
	BytesIn  int64 // stub — wired in M5 observability
	BytesOut int64 // stub — wired in M5 observability
}

ListenerStats is a point-in-time snapshot of listener counters.

type Pool

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

Pool is a per-backend-address connection pool. The zero value is not usable; construct one with NewPool. It is safe for concurrent use.

func NewPool

func NewPool(cfg PoolConfig) *Pool

NewPool constructs a Pool with cfg (zero fields take defaults).

func (*Pool) Close

func (p *Pool) Close() error

Close closes all idle connections and marks the pool closed. Subsequent Get calls return ErrPoolClosed. Borrowed (active) connections are the caller's responsibility to close.

func (*Pool) Get

func (p *Pool) Get(ctx context.Context, network, addr string) (net.Conn, error)

Get returns a connection to addr: a healthy idle one if available, otherwise a freshly dialed one. If MaxOpen connections are already open to addr, Get blocks until a Put frees a slot or ctx is cancelled.

func (*Pool) Put

func (p *Pool) Put(conn net.Conn, addr string)

Put returns conn (previously obtained from Get for addr) to the pool. If the idle pool is under MaxIdle and the connection is healthy it is retained; otherwise it is closed. Either way the open-connection slot accounting is updated so a blocked Get can proceed.

func (*Pool) Stats

func (p *Pool) Stats() PoolStats

Stats returns a snapshot of pool counters.

type PoolConfig

type PoolConfig struct {
	// MaxIdle is the maximum idle (kept-warm) connections retained per backend
	// address. Default 8.
	MaxIdle int
	// MaxOpen is the maximum total connections (idle + borrowed) per backend
	// address. Get blocks once this is reached until a Put or ctx cancel.
	// Default 64.
	MaxOpen int
	// IdleTimeout closes idle connections older than this. Default 90s.
	IdleTimeout time.Duration
	// DialTimeout bounds dialing a new connection. Default 10s.
	DialTimeout time.Duration
}

PoolConfig tunes a connection Pool.

type PoolStats

type PoolStats struct {
	Idle      int
	Active    int   // connections currently borrowed via Get (not yet Put back)
	WaitCount int64 // cumulative times Get blocked waiting on MaxOpen
}

PoolStats is a point-in-time snapshot of pool counters.

type TunnelConfig

type TunnelConfig struct {
	// DialTimeout bounds backend dialing (used by the pool/listener, kept here
	// so the whole tunnel behavior is configured in one place). Default 10s.
	DialTimeout time.Duration
	// IdleTimeout closes the tunnel if no bytes move in either direction for
	// this long. Default 90s.
	IdleTimeout time.Duration
	// MaxConnections is the per-route connection ceiling (enforced by the
	// listener). Default 1000.
	MaxConnections int
	// BufferSize is the copy buffer size per direction. Default 32KiB.
	BufferSize int
}

TunnelConfig tunes a single tunnel.

type WeightedRR

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

WeightedRR selects backends using smooth weighted round-robin — the algorithm Nginx uses. Compared to naive weighted RR (which bursts: A,A,A,A,A,B,C for weights 5,1,1), the smooth variant interleaves selections (A,A,B,A,A,C,A) so load is spread evenly over time rather than clumped.

It is safe for concurrent use. A single-backend selector takes a lock-free fast path.

func NewWeightedRR

func NewWeightedRR(backends []BackendAddr) (*WeightedRR, error)

NewWeightedRR builds a selector over backends. It returns ErrNoBackends if the list is empty. Any backend with Weight <= 0 is normalized to Weight 1.

func (*WeightedRR) Len

func (w *WeightedRR) Len() int

Len returns the number of configured backends.

func (*WeightedRR) Next

func (w *WeightedRR) Next() (BackendAddr, error)

Next returns the next backend to use. It is thread-safe. With a single backend it returns immediately without taking the lock.

func (*WeightedRR) Update

func (w *WeightedRR) Update(backends []BackendAddr) error

Update atomically replaces the backend list, used for config hot-reload so a route's backends can change without dropping traffic. CurrentWeight state is preserved for backends that remain (matched by Addr); new backends start at CurrentWeight 0. Returns ErrNoBackends if the new list is empty.

Jump to

Keyboard shortcuts

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