dispatcher

package
v0.36.0 Latest Latest
Warning

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

Go to latest
Published: Jul 7, 2026 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package dispatcher implements L4 TCP dispatching based on TLS SNI.

When a service has routes with action type "pass", the dispatcher intercepts connections before TLS termination. It peeks at the TLS ClientHello to extract the SNI hostname, matches it against configured domain patterns, and either relays the raw TCP connection to the upstream (for "pass" routes) or feeds it to the HTTP server (for regular L7 routes).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func PeekSNI

func PeekSNI(r io.Reader) (sni string, buf []byte, err error)

PeekSNI reads the TLS ClientHello from a connection and extracts the SNI hostname. Returns the SNI (empty if not found) and all bytes read (for replay to upstream or TLS server). Does not consume the connection beyond the first TLS record.

func Relay

func Relay(client, upstream net.Conn) (rxBytes, txBytes int64)

Relay copies data bidirectionally between two connections. It blocks until both directions finish (EOF or error). Caller is responsible for closing both connections.

Types

type Dispatcher

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

Dispatcher intercepts raw TCP connections on a listener, peeks the TLS ClientHello for SNI, and dispatches: "pass" routes get a raw TCP relay; everything else is fed to the HTTP server via a synthetic net.Listener.

func New

func New(routes []*Route, plugins *plugin.Manager) *Dispatcher

New creates a Dispatcher with the given pre-compiled routes. Routes are evaluated in order — first domain match wins.

func (*Dispatcher) Close

func (d *Dispatcher) Close()

Close forcefully closes all active relay connections, causing their io.Copy goroutines to unblock and return. Called during shutdown to prevent the process from hanging on long-lived connections.

func (*Dispatcher) Serve

func (d *Dispatcher) Serve(ln net.Listener) net.Listener

Serve starts the dispatcher in the background. It accepts connections from ln, peeks SNI, and dispatches. Connections that are not "pass" are sent to the returned net.Listener for consumption by http.Server.Serve / ServeTLS.

func (*Dispatcher) SwapRoutes

func (d *Dispatcher) SwapRoutes(routes []*Route)

SwapRoutes atomically replaces the dispatcher's route table. Active connections are not affected — new routes take effect on the next incoming connection.

func (*Dispatcher) Wait

func (d *Dispatcher) Wait()

Wait blocks until all active pass relays have finished.

type Route

type Route struct {
	RouteID        string            // e.g. "gateway:0" — matches plugin binding key
	Domain         string            // original pattern (e.g. "*.cdn.example.com")
	DomainSegments []string          // split + lowered segments for glob matching
	DomainGlob     bool              // true when pattern ends with "**"
	IsPass         bool              // true for action type "pass"
	IsDrop         bool              // true for action type "drop"
	Upstream       string            // dial address for pass routes (static)
	UpstreamTpl    string            // upstream template with {target} for balanced pass routes
	Bal            balancer.Balancer // nil = no balancing
}

Route is a pre-compiled L4 route for domain-based dispatching.

Jump to

Keyboard shortcuts

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