The WrapUDPConn constructor returns nil when either arg is nil, so
c.stats is always non-nil in all udpConn methods. Remove 8 redundant
nil guards that were inconsistent with packetConn (which already
skipped them).
Add 65 unit tests across plugin, stats, and wrapper packages covering
nil safety, race conditions, double-close, event marshaling, and
reset-traffic semantics. Replace magic numbers in tests with named
Kind constants.
- WrapUDPConn, WrapPacketConn, WrapListener: add nil guards for pc/ln params
- NewGRPCPlugin: return no-op observer instead of nil on connection error
- gRPC plugin: fix resource leak by wiring Close() through observerWrapper
and service.Close() lifecycle
- Both plugins: log unknown event types instead of silently dropping them
- httpPlugin: remove dead nil check for always-non-nil client field
- Stats.Reset: update core interface doc to match implementation behavior
- Add doc comments to all exported symbols across the observer package
- Add NewLimiterWithBurst(rate, burst) for independent burst control
- Extend parseLimit to accept optional 4th field as burst size
- Add DroppedPacketCounter interface with DroppedPackets() for packet/udp conns
- Export ErrRateLimited sentinel for rate-limit error checks
- Fix IP-level cache expiration (NoExpiration → defaultExpiration) to prevent
unbounded growth; reset TTL on access in In/Out
- Short-circuit single-limiter path to avoid limiterGroup allocation
- Add nil guard in cachedTrafficLimiter when both old and new values are nil
- Remove unused ctx field from wrapper structs
NewMetadata(nil) previously returned a nil Metadata interface, causing
panics on direct .Get()/.IsExists() calls. Now returns an empty map.
GetFloat added float32→float64 promotion, matching GetString behavior.
Doc comments for all 13 exported symbols across both packages.
41 unit tests (11 metadata + 30 util) at 100% coverage.
- limiterGroup.Allow(): return false immediately on first denial instead of
continuing through all limiters (wasting tokens on subsequent limiters).
Sort limiters by Limit() so most restrictive fires first.
- rateLimiter.Close(): add missing httpLoader.Close() to prevent resource leak.
- Add doc comments for all exported symbols (package, constants, Options,
NewRateLimiter, NewLimiter, ErrRateLimit, generators).
- Add rate_test.go with 59 unit tests covering generators, limiter groups,
parsing (limit/line/patterns), reload, loader merge, Close behavior,
and priority ordering (exact IP > CIDR > $$ > $).
Add package and exported symbol doc comments across conn, generator,
limiter, and wrapper packages. Fix nil receiver guard in
connLimitSingleGenerator.Limiter, add missing httpLoader.Close call,
return context.Background instead of nil in serverConn.Context, return
explicit error on connection limit exceeded, and simplify Allow logic.
matcher: fix IPv6 normalization via netip.ParseAddr, port-range overwrite
by switching to []*PortRange map, case-insensitive domain/host matching,
glob.MustCompile→Compile to avoid panic on invalid patterns.
plugin: guard nil *Options in NewGRPCConn and NewHTTPClient; add
HTTPClientTransport helper for idle-connection cleanup.
net/*: add doc comments for all exported symbols (no code changes).
Add 30 tests (matcher_test.go 22, plugin_test.go 8) covering all
matcher types, nil safety, case insensitivity, IPv6 normalization,
port ranges, and plugin option composition.
- entrypoint.go: guard ictx.RecorderObjectFromContext with nil checks on
ClientID and Redirect assignments
- io.go: fix CloseRead checking Writer instead of Reader, add Reader
fallback to CloseWrite, unwrap *readWriter/*readWriteCloser in
SetReadDeadline to reach underlying net.Conn
- docs: add package doc and exported symbol comments to internal/ctx
and internal/io
- hosts/hosts.go: add package and symbol doc comments, fix missing
httpLoader.Close() in Close()
- hosts/plugin: add doc comments for HTTP and gRPC plugin types
- hop/hop.go: add doc comments, accumulate reload/parse errors via errors.Join
instead of silently discarding them
- hop/plugin/http.go: add doc comments and missing Close() method
- Add unit tests for hosts (580 lines) and hop (991 lines)
Remove unused WithContext interface (zero references in codebase), add
doc comments for all 14 exported symbols, and simplify HashFromContext
to match the one-liner pattern used by the other four getters.
Add 22 unit tests covering round-trip, empty context, wrong type, nil
values, multiple values, independent keys, and the Context interface.
Add nil checks for connect-options dialer and logger to prevent
nil-pointer panics when Connect is called without a DialerConnectOption
or LoggerOption. Add package and NewConnector godoc comments.
Add 10 unit tests covering construction, Init metadata parsing,
Connect success/reject/dial-error paths, nil dialer, nil logger,
and the reject conn stub.
Add godoc comments for all 62 exported symbols across 20 files in
config/parsing/: 23 MDKey constants, 35 Parse*/List/Default* functions,
3 TLS helpers, 1 Args struct with 7 fields, and the package doc.
Prevent data loss and nil panics across 5 parse functions:
- chain: nil-guard hop entries to avoid deref on empty YAML lists
- hop: build merged metadata map instead of writing inherited values
into the original NodeConfig; swap+restore around ParseNode call
- node: use local connCfg/dialCfg instead of overwriting cfg.Connector
and cfg.Dialer fields; only fill in Type when empty
- parser: preserve existing config file fields when env vars override
Level/Addr (was replacing the entire struct)
- router: only update ipNet from dst CIDR if parse succeeds, keeping
the route.Net fallback instead of overwriting with nil
- Add 808-line loader_test.go covering registerGroup, register, and Load
- Add package and exported symbol doc comments to loader.go
- Fix fmt.Errorf(resp.Status) → errors.New(resp.Status) in sd/plugin/http.go
(resp.Status is a plain string, not a format string)
- loader: guard cfg == nil in Load() to prevent nil-pointer dereference on
cfg.Log / cfg.TLS access.
- loader: defer logger.SetDefault and parsing.SetDefaultTLSConfig until
after register() succeeds, so a failed reload does not leave global
state (logger, default TLS) pointing at the new config while components
remain from the old config.
- loader: extract registerGroup[T] helper to eliminate repeated
unregister-then-register boilerplate. Entries are parsed and collected
before unregistering; a parse error now preserves the previous group
(old code unregistered first, then parsed, leaving an empty registry on
parse failure).
- hop: move cfg.SockOpts.Mark extraction outside the cfg.Metadata != nil
block so the socket mark is read even when hop-level metadata is absent.
- hop: fix copy-paste error in netns inheritance: v.Name was incorrectly
stored as MDKeyNetns instead of v.Netns (introduced in f71351f).
Upgrade github.com/pion/dtls from v2.2.6 to v3.1.1 to fix nonce reuse
vulnerability in AES-GCM ciphers (GHSA-9f3f-wv7r-qc8r). Migrate from
deprecated Config-struct API to ListenWithOptions/ClientWithOptions
options-based API.
v2 Config fields mapped to v3 functional options:
- Certificates, InsecureSkipVerify, ExtendedMasterSecret, ServerName,
RootCAs, ClientCAs, ClientAuth, FlightInterval, MTU
ConnectContextMaker removed — no longer exists in v3; explicit
HandshakeContext(ctx) on *Conn is the replacement for timeout control.
Three bugs in CLI-to-config conversion:
1. Comma-separated -F nodes shared Connector/Dialer/Metadata pointers
due to struct value copy; add deep-copy helpers per node.
2. Port-range-expanded -L services shared Handler/Listener/Metadata
pointers; deep-copy per service so metadata mutations don't cross-talk.
3. buildServiceConfig's ?auth= query param unconditionally overwrote
URL-embedded auth; buildNodeConfig used fallback-only. Align both
on URL-auth-first semantics (query param as fallback).
Cover the three main abstractions (Router, Chain, Transport), route traversal
lifecycle (Dial → Handshake → Connect), and multiplexing sub-route splitting.
- transport.go: Copy() returned original pointer instead of the allocated copy,
causing data races and incorrect routing for multiplexed chains.
- route.go: Connect and Handshake failures in intermediate nodes leaked the
returned connection. Handshake fix preserves the original Connect result
(guaranteed non-nil) and closes both the Handshake return value and input.
- router.go: defer cancel() inside retry loops accumulated context timers
across iterations. Wrapped each loop body in an IIFE so defer scopes
per-iteration and timers are released immediately.
- 88 tests: 70 for core (96.8%), 12 for gRPC plugin, 14 for HTTP plugin
- Cover all matchers (IP, CIDR, wildcard, IP range), loader sources,
bypassGroup logic, periodReload, and plugin fail-open semantics
- Add nil-logger guard in httpPlugin.Contains to prevent panic
when logger is nil
Add Go doc comments for all exported symbols, option functions, and
internal types across the bypass package and plugin sub-package,
following the style of the admission package.
- redisLoader branch used fileLoader instead of redisLoader (copy-paste bug)
- Close() was missing httpLoader.Close() (resource leak vs admission pattern)
- reload() now preserves kvs on load() error instead of wiping to static-only
- load() propagates first loader error, reload() returns early on load failure
- parseAuths scanner errors now logged instead of silently discarded
- http plugin drains body on non-200 to allow keep-alive connection reuse
- Replace manual map-copy loops with maps.Copy
- Bump go-shadowsocks2 to v0.1.3 (new API symbols)
- Return error instead of nil when Target() is empty in TCP handler
- Reset wbuf unconditionally on write error to prevent unbounded growth
- Add nil guard on targetAddr before WriteTo to prevent panic
- Remove duplicate NewClientConfig call and dead ClientConfig literal
- Remove unused noDelay metadata field
- Fix buffer-size guard to catch negative values (len(b)==0 → bufSize<=0)
- Add address context to parse/session error messages
Add package-level documentation and Go doc comments for all exported
types, functions, and methods across the admission package, its plugin
sub-packages, and connection/listener wrappers.
- Use write lock (Lock) instead of read lock (RLock) in CloseOnIdle since
it modifies the close channel, preventing a race with Close() that could
panic on double-close of channel.
- Buffer sniffingWebsocketFrame errc to capacity 2 and close both
connections on first error to ensure the remaining copy goroutine
unblocks and exits cleanly.
- Use client address network instead of listener network in admission wrapper
- Return true (allow) when gRPC admission plugin client is nil to fail-open
- Add Close() to httpPlugin to close idle HTTP connections
- Close httpLoader in localAdmission.Close()
- Remove dead commented-out code in periodReload
- Return errors from MasqueConn.Read/Write instead of silently
succeeding (prevents infinite busy-loops and silent data loss
if these methods are accidentally called).
- Set recorder Network field in protocol dispatch switch rather
than hardcoding "udp", so early errors don't misreport type.
- Clarify that DatagramConn context-ID handling only supports
context ID 0 (sufficient for CONNECT-UDP per RFC 9298).
Merge beezly/fix/configurable-pipe-timeout with conflict resolution
in pipe.go (PipeOption/WithReadTimeout functional options pattern).
Fix pipe_test.go: update 4 pipeHalf() calls to pass readTimeout arg
matching the new signature.
Upgrade github.com/go-gost/core from v0.3.3 to v0.4.0, adapting to
interface changes:
- Admit(ctx, network, addr, opts) now accepts a network parameter
- Router.Dial now accepts variadic chain.DialOption, forwarded to
the route's Dial call along with router-level options
- gRPC/HTTP admission plugins include the new Network field
Also fix two typos: ResoloverNodeOption -> ResolverNodeOption,
WithHostOpton -> WithHostOption.
Fix setMark early-return conditions that were inverted relative to
Linux: on FreeBSD (SO_USER_COOKIE) and OpenBSD (SO_RTABLE), a
non-zero mark was short-circuited instead of applied, disabling
socket marking entirely.
Also fix GetClientIP to trim leading whitespace from X-Forwarded-For
entries (per RFC 7239), and fix Body.Read to subtract len(b) instead
of n from recordSize when a single read exceeds the remaining quota.
Add unit tests for internal/net/ (addr, dialer, http, ip, net, pipe,
transport, resolve, proxyproto, udp).
Pipe: remove context.WithCancel that caused premature ctx.Done()
before the second pipeHalf could return its error. Replace with a
completed counter that drains both errors even on cancellation.
Transport: increase error channel buffer from 1 to 2 to prevent
goroutine leak when both CopyBuffer goroutines complete.
Add configurable TCP keepalive (keepalive, keepalive.idle,
keepalive.interval, keepalive.count) to all TCP-based transport types:
tls, mtls, mtcp, ws/wss, mws/mwss, http2, ssh, sshd listeners and
tls, mtls, mtcp, ws/wss, mws/mwss, ssh, sshd dialers.
For types that already use "keepalive" for an app-level protocol
(grpc listener/dialer, ws/mws dialers, ssh/sshd dialers), the TCP
keepalive parameters are exposed under the tcp.keepalive.* prefix to
avoid ambiguity.
Also extract shared helpers into internal/net/keepalive.go:
- WrapKeepaliveListener: applies KeepAliveConfig on every accepted TCPConn
- ApplyKeepalive: applies KeepAliveConfig to a single TCPConn
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>