chainGroup now selects chains in two stages: a matcher filter (by host/network)
builds an eligible pool, then the group selector applies FailFilter + strategy.
Each entry carries its own failure marker so chain-level probe marking is
independent of node-level failCodes markers (probe Reset() can't undo a node
failCodes Mark()).
Config gains ChainGroupEntry (chain/matcher/probe) replacing the old []string,
with a mapstructure decode hook preserving backward-compatible "chains: [a, b]"
string lists and time.Duration string parsing. Probe goroutines run per-entry
and mark the entry on failure.
Co-Authored-By: Claude <noreply@anthropic.com>
Implements the cache.Cache interface with in-memory backend (TTL,
maxSize/maxBytes bounds, oldest/LRU eviction, background cleanup).
Adds httpcache layer for HTTP response policy (per-status TTL,
serve-stale, method/body filtering). Wires into config parser,
loader, registry, and all four sniffing handlers (forward/local,
forward/remote, sni, http) so HTTP responses are cached before
dialing upstream.
Bumps core dependency to v0.6.0 for the new cache.Cache interface.
The issue #777 analysis was written against v3.2.4; commits 5484717 and
9fab332 already fixed the global mutex stall, the no-timeout OpenStreamSync,
and the missing IsClosed reuse check. This addresses the remaining real
problems:
- P1 (HIGH): quicDialer.Dial received the Router's 15s-timeout ctx but
GetConn built its own context.Background()+30s, dropping request
cancellation/deadline. Thread ctx into GetConn so OpenStreamSync honors
the upstream deadline. Mirrored to the icmp dialer (identical structure).
- P2 (MEDIUM): listener QUIC keepalive defaulted OFF while the dialer
defaulted ON, so a server behind NAT without an explicit keepalive=true
could let its return-path mapping expire. Make the listener default ON
like the dialer.
- P3 (LOW): set an explicit MaxIdleTimeout default (90s) on both dialer
and listener so dead sessions are detected sooner; still overridable via
maxIdleTimeout=.
Docs updated to mark the already-fixed root causes and rename the remaining
items P1-P3.
Fixesgo-gost/gost#777
Convert the concrete *mux.Session into a mux.Session interface backed by
smux and yamux, selected via the `mux.type` metadata key. Empty/unspecified
defaults to "smux", so existing deployments are unchanged. Yamux's stream
window is exposed via `mux.maxStreamWindow`.
Also fix TestHandler_observeStats: the retry_after_observer_error subtest
hung because stats.Events() drains (IsUpdated is Swap(false)) and no fresh
event was generated for the recovery tick's fall-through flush. Inject a real
client2 event so the recovery tick has new data to flush.
Plan: docs/plans/2026-07-13-mux-pluggable-yamux.md
Add a new "utls" dialer type that uses the refraction-networking/utls
library to mimic browser TLS fingerprints (Chrome, Firefox, Safari, etc.).
- x/dialer/utls/dialer.go: Registered as "utls", mirrors the TLS dialer
with Handshake() using utls.UClient() for fingerprint emulation.
- x/dialer/utls/fingerprint.go: Maps string names (chrome, firefox, ios,
safari, edge, randomized, golang, custom) to utls.ClientHelloID presets.
- x/dialer/utls/metadata.go: Parses fingerprint from dialer metadata.
- go.mod: Add github.com/refraction-networking/utls v1.8.2.
The fingerprint is dialer-only metadata — the standard TLS dialer is
untouched. Falls back to crypto/tls if no fingerprint is configured.
Closesgo-gost/gost#31