Documentation
¶
Overview ¶
Package netmux multiplexes network connections and packet connections based on their payload.
ConnMux turns a single net.Listener into multiple virtual listeners, dispatching each accepted connection to the first virtual listener whose matchers (ConnMatcher / ConnMatchWriter) accept it. Built-in matchers cover HTTP/1 (optimistic method matching) and SOCKS, plus generic Any/Prefix matchers.
PacketConnMux turns a single net.PacketConn into multiple virtual packet conns, dispatching each datagram to the first virtual conn whose matchers (PacketConnMatcher) accept it. Built-in matchers cover QUIC, STUN and TURN, plus generic Any/Prefix/Exact matchers.
The package also provides portable socket helpers (Listen, ListenPacket, Dial, DialTimeout, ResolveAddr) that set SO_REUSEADDR and SO_REUSEPORT on the underlying sockets via the platform-specific Control function.
Index ¶
- Variables
- func Control(network, address string, c syscall.RawConn) (err error)
- func Dial(network, laddr, raddr string) (net.Conn, error)
- func DialTimeout(network, laddr, raddr string, timeout time.Duration) (net.Conn, error)
- func Listen(network, address string) (net.Listener, error)
- func ListenPacket(network, address string) (net.PacketConn, error)
- func ResolveAddr(network, address string) (net.Addr, error)
- type ConnMatchWriter
- type ConnMatcher
- type ConnMux
- type ErrConnNotMatched
- type ErrorHandler
- type PacketConnMatcher
- type PacketConnMux
Constants ¶
This section is empty.
Variables ¶
var ( // ListenConfig is a net.ListenConfig with Control function set to Control, // which sets SO_REUSEADDR and SO_REUSEPORT options on the socket. ListenConfig = net.ListenConfig{Control: Control} // ResolveIPAddr resolves an IP address. ResolveIPAddr func(network, address string) (*net.IPAddr, error) = net.ResolveIPAddr // ResolveTCPAddr resolves a TCP address. ResolveTCPAddr func(network, address string) (*net.TCPAddr, error) = net.ResolveTCPAddr // ResolveUDPAddr resolves a UDP address. ResolveUDPAddr func(network, address string) (*net.UDPAddr, error) = net.ResolveUDPAddr // ResolveUnixAddr resolves a Unix address. ResolveUnixAddr func(network, address string) (*net.UnixAddr, error) = net.ResolveUnixAddr )
var ErrConnListenerClosed = errListenerClosed("mux: listener closed")
ErrConnListenerClosed is returned from connListener.Accept when the underlying listener is closed.
var ErrConnMuxClosed = errServerClosed("mux: server closed")
ErrConnMuxClosed is returned from connListener.Accept when mux server is closed.
Functions ¶
func Control ¶
Control sets the SO_REUSEADDR and SO_REUSEPORT options on the socket. It is used as the Control function in net.ListenConfig and net.Dialer to enable address and port reuse for network connections.
func DialTimeout ¶
DialTimeout creates a network connection with SO_REUSEADDR and SO_REUSEPORT options set, with a specified timeout.
func ListenPacket ¶
func ListenPacket(network, address string) (net.PacketConn, error)
ListenPacket creates a packet network listener with SO_REUSEADDR and SO_REUSEPORT options set.
Types ¶
type ConnMatchWriter ¶
ConnMatchWriter is a match that can also write response (say to do handshake).
type ConnMatcher ¶
ConnMatcher matches a connection based on its content and the remote address of the connection.
func ConnHTTP1 ¶
func ConnHTTP1(extMethods ...string) ConnMatcher
ConnHTTP1 only matches the methods in the HTTP request.
This matcher is very optimistic: if it returns true, it does not mean that the request is a valid HTTP response. See the "Advanced matcher examples" section in the README for stricter self-contained HTTP/1 and HTTP/2 matchers.
func ConnPrefixMatcher ¶
func ConnPrefixMatcher(strs ...string) ConnMatcher
ConnPrefixMatcher returns a matcher that matches a connection if it starts with any of the strings in strs.
func ConnSOCKS ¶
func ConnSOCKS(version byte, nmethods byte, methods ...byte) ConnMatcher
ConnSOCKS matches SOCKS client greetings by their initial bytes.
The prefix is built from the version, the number of authentication methods advertised (nmethods) and the offered method bytes, so a greeting must start with exactly these bytes to match. Only the greeting is sniffed; the SOCKS handshake reply is the caller's responsibility. For example:
ConnSOCKS(5, 1, 0) // SOCKS5, 1 method, NO AUTHENTICATION REQUIRED ConnSOCKS(5, 1) // SOCKS5, any single offered method
type ConnMux ¶
type ConnMux struct {
// contains filtered or unexported fields
}
ConnMux is a multiplexer for network connections. It turns a single net.Listener into multiple virtual listeners, each serving the connections matched by the matchers registered with Match/MatchWithWriters (first match wins, in registration order).
func NewConnMux ¶
NewConnMux instantiates a new connection multiplexer.
func (*ConnMux) Close ¶
func (m *ConnMux) Close()
Close stops the multiplexer: every Accept on current and future virtual listeners returns ErrConnMuxClosed. Close does NOT close the root listener, which is owned by the caller; close it yourself to make Serve return.
func (*ConnMux) HandleError ¶
func (m *ConnMux) HandleError(h ErrorHandler)
HandleError replaces the default error handler. The handler returns whether the mux should keep serving (true) or stop (false) after an error. The default keeps serving whenever possible: unmatched connections are closed, transient accept errors are retried, and only a closed root listener (or a handler veto) stops Serve.
Call it before Serve: the handler is read from the hot path without synchronization.
func (*ConnMux) Match ¶
func (m *ConnMux) Match(matchers ...ConnMatcher) net.Listener
Match registers a virtual listener for connections accepted by any of the given matchers. Matchers are evaluated in registration order and the first match wins, so register specific matchers before catch-alls. The returned net.Listener delivers matched connections with the bytes sniffed during matching replayed, so the protocol handler sees the exact byte stream.
func (*ConnMux) MatchWithWriters ¶
func (m *ConnMux) MatchWithWriters(matchers ...ConnMatchWriter) net.Listener
MatchWithWriters is like Match, but each matcher also receives a writer that can send bytes to the peer before the connection is delivered to the application (e.g. a server-initiated protocol handshake). The writer is the raw connection and is only valid during the matcher call; do not retain it.
func (*ConnMux) Serve ¶
Serve accepts connections from the root listener and dispatches each one to the first virtual listener whose matcher accepts it. It returns when the root listener fails with an error the error handler does not veto — normally because the root listener was closed. Run Serve in its own goroutine once all virtual listeners are registered.
func (*ConnMux) SetReadTimeout ¶
SetReadTimeout bounds how long a matcher may spend sniffing a connection's initial bytes: a matcher that needs more than t of reads fails to match.
Call it before Serve: the value is read from the hot path without synchronization and must not change while connections are being dispatched. A zero duration disables the timeout, which is the default.
type ErrConnNotMatched ¶
type ErrConnNotMatched struct {
// contains filtered or unexported fields
}
ErrConnNotMatched is returned whenever a connection is not matched by any of the matchers registered in the multiplexer.
func (ErrConnNotMatched) Error ¶
func (e ErrConnNotMatched) Error() string
Error returns a message identifying the remote address of the unmatched connection.
func (ErrConnNotMatched) Temporary ¶
func (e ErrConnNotMatched) Temporary() bool
Temporary implements the net.Error interface.
func (ErrConnNotMatched) Timeout ¶
func (e ErrConnNotMatched) Timeout() bool
Timeout implements the net.Error interface.
type ErrorHandler ¶
ErrorHandler decides what happens after an error: it returns whether the mux should continue serving (true) or stop (false).
type PacketConnMatcher ¶
PacketConnMatcher returns true when a packet belongs to a virtual PacketConn.
Matchers are invoked synchronously from the demux loop (under the PacketConnMux read lock), so they must be fast and non-blocking.
func PacketExact ¶
func PacketExact(payload []byte) PacketConnMatcher
Exact matches packets equal to payload.
func PacketPrefix ¶
func PacketPrefix(prefix []byte) PacketConnMatcher
Prefix matches packets starting with prefix.
func PacketQUIC ¶
func PacketQUIC() PacketConnMatcher
PacketQUIC matches QUIC packets. QUIC's fixed header bit (0x40) is set in both long-header (0xC0-0xFF, incl. Initial/Handshake) and short-header (0x40-0x7F, post-handshake) packets, so this matcher claims every QUIC packet regardless of handshake state. (Version Negotiation packets may clear the fixed bit, but they only occur during version mismatch.) Note that TURN ChannelData messages (RFC 5766 §11.4) share the 0x40-0x7F first byte range and therefore also match — see the README for ordering guidance when combining QUIC and TURN on one mux.
func PacketSTUN ¶
func PacketSTUN() PacketConnMatcher
PacketSTUN matches STUN (RFC 5389) messages: the first two bits of the first byte are 00, and the magic cookie 0x2112A442 sits at bytes 4-7 followed by a 12-byte transaction id. Requires at least 20 bytes.
func PacketTURN ¶
func PacketTURN() PacketConnMatcher
PacketTURN matches TURN (RFC 5766) packets: STUN-formatted messages (same shape as PacketSTUN) plus ChannelData messages, whose first two bits are 01 (RFC 5766 §11.4). Note that PacketTURN is a superset of PacketSTUN — when both matchers are registered on the same mux, register PacketSTUN first so STUN messages reach the STUN conn.
type PacketConnMux ¶
type PacketConnMux struct {
// contains filtered or unexported fields
}
PacketConnMux multiplexes one PacketConn into multiple virtual PacketConns.
func NewPacketConnMux ¶
func NewPacketConnMux(conn net.PacketConn) *PacketConnMux
NewPacketConnMux creates a packet multiplexer around conn.
func (*PacketConnMux) Close ¶
func (m *PacketConnMux) Close() error
Close closes the multiplexer and the base PacketConn.
func (*PacketConnMux) Match ¶
func (m *PacketConnMux) Match(matchers ...PacketConnMatcher) net.PacketConn
Match registers a virtual PacketConn for packets that match one of matchers.
Match order matters: PacketConnMux dispatches the packet to the first registered virtual PacketConn whose matchers accept the packet.
func (*PacketConnMux) Serve ¶
func (m *PacketConnMux) Serve() error
Serve starts reading packets from the base PacketConn and dispatches them.
It returns when the base PacketConn returns an error or Close is called.
func (*PacketConnMux) WaitUntilServing ¶
func (m *PacketConnMux) WaitUntilServing(timeout time.Duration) error
WaitUntilServing blocks until Serve has started reading packets.