From effba3b690c2172c6177f21029460c322e208941 Mon Sep 17 00:00:00 2001 From: ginuerzh Date: Sun, 24 May 2026 13:58:37 +0800 Subject: [PATCH] docs(parsing): add package and symbol doc comments 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. --- config/parsing/admission/parse.go | 7 +++ config/parsing/auth/parse.go | 12 ++++ config/parsing/bypass/parse.go | 5 ++ config/parsing/chain/parse.go | 3 + config/parsing/hop/parse.go | 4 ++ config/parsing/hosts/parse.go | 3 + config/parsing/ingress/parse.go | 3 + config/parsing/limiter/parse.go | 7 +++ config/parsing/logger/parse.go | 5 ++ config/parsing/node/parse.go | 5 ++ config/parsing/observer/parse.go | 3 + config/parsing/parse.go | 93 ++++++++++++++++++++++++++----- config/parsing/parser/parser.go | 33 +++++++++-- config/parsing/recorder/parse.go | 5 ++ config/parsing/resolver/parse.go | 4 ++ config/parsing/router/parse.go | 3 + config/parsing/sd/parse.go | 2 + config/parsing/selector/parse.go | 10 ++++ config/parsing/service/parse.go | 7 +++ config/parsing/tls.go | 10 ++++ 20 files changed, 203 insertions(+), 21 deletions(-) diff --git a/config/parsing/admission/parse.go b/config/parsing/admission/parse.go index 36bbe62f..fd6a1390 100644 --- a/config/parsing/admission/parse.go +++ b/config/parsing/admission/parse.go @@ -14,6 +14,10 @@ import ( "github.com/go-gost/x/registry" ) +// ParseAdmission converts an AdmissionConfig into an admission.Admission. It +// resolves plugin backends (HTTP or gRPC) when cfg.Plugin is set, or +// constructs an in-process admission controller with optional file, Redis, and +// HTTP hot-reload support. func ParseAdmission(cfg *config.AdmissionConfig) admission.Admission { if cfg == nil { return nil @@ -74,6 +78,9 @@ func ParseAdmission(cfg *config.AdmissionConfig) admission.Admission { return xadmission.NewAdmission(opts...) } +// List resolves one or more admission controller names from the registry. It +// returns only the controllers that were found, skipping any that are not +// registered. func List(name string, names ...string) []admission.Admission { var admissions []admission.Admission if adm := registry.AdmissionRegistry().Get(name); adm != nil { diff --git a/config/parsing/auth/parse.go b/config/parsing/auth/parse.go index 9cd9f2a9..bf413b7d 100644 --- a/config/parsing/auth/parse.go +++ b/config/parsing/auth/parse.go @@ -18,6 +18,9 @@ import ( "github.com/go-gost/x/registry" ) +// ParseAuther converts an AutherConfig into an auth.Authenticator. It handles +// plugin backends (HTTP or gRPC), inline auth credentials, and optional file, +// Redis, and HTTP hot-reload sources. func ParseAuther(cfg *config.AutherConfig) auth.Authenticator { if cfg == nil { return nil @@ -85,6 +88,9 @@ func ParseAuther(cfg *config.AutherConfig) auth.Authenticator { return xauth.NewAuthenticator(opts...) } +// ParseAutherFromAuth creates a simple authenticator from a single +// username/password pair in an AuthConfig. Returns nil if the config is nil or +// has no username. func ParseAutherFromAuth(au *config.AuthConfig) auth.Authenticator { if au == nil || au.Username == "" { return nil @@ -101,6 +107,9 @@ func ParseAutherFromAuth(au *config.AuthConfig) auth.Authenticator { ) } +// Info extracts authentication credentials from an AuthConfig as a +// url.Userinfo. It supports reading the first line from a password file when +// cfg.File is set, or falls back to inline username/password fields. func Info(cfg *config.AuthConfig) *url.Userinfo { if cfg == nil { return nil @@ -158,6 +167,9 @@ func parseInfo(r io.Reader, max int) (infos []*url.Userinfo, err error) { return } +// List resolves one or more authenticator names from the registry. It returns +// only the authenticators that were found, skipping any that are not +// registered. func List(name string, names ...string) []auth.Authenticator { var authers []auth.Authenticator if auther := registry.AutherRegistry().Get(name); auther != nil { diff --git a/config/parsing/bypass/parse.go b/config/parsing/bypass/parse.go index f0c141c4..5c62aa01 100644 --- a/config/parsing/bypass/parse.go +++ b/config/parsing/bypass/parse.go @@ -14,6 +14,9 @@ import ( "github.com/go-gost/x/registry" ) +// ParseBypass converts a BypassConfig into a bypass.Bypass. It resolves plugin +// backends (HTTP or gRPC) when cfg.Plugin is set, or constructs an in-process +// bypass with optional file, Redis, and HTTP hot-reload support. func ParseBypass(cfg *config.BypassConfig) bypass.Bypass { if cfg == nil { return nil @@ -74,6 +77,8 @@ func ParseBypass(cfg *config.BypassConfig) bypass.Bypass { return xbypass.NewBypass(opts...) } +// List resolves one or more bypass names from the registry. It returns only +// the bypasses that were found, skipping any that are not registered. func List(name string, names ...string) []bypass.Bypass { var bypasses []bypass.Bypass if bp := registry.BypassRegistry().Get(name); bp != nil { diff --git a/config/parsing/chain/parse.go b/config/parsing/chain/parse.go index 7a9b3e91..2568d7df 100644 --- a/config/parsing/chain/parse.go +++ b/config/parsing/chain/parse.go @@ -12,6 +12,9 @@ import ( "github.com/go-gost/x/registry" ) +// ParseChain converts a ChainConfig into a chain.Chainer. Each hop reference +// is either looked up from the registry (by name) or parsed inline via +// ParseHop. Returns nil with no error when cfg is nil. func ParseChain(cfg *config.ChainConfig, log logger.Logger) (chain.Chainer, error) { if cfg == nil { return nil, nil diff --git a/config/parsing/hop/parse.go b/config/parsing/hop/parse.go index e7ebf2d8..092ca516 100644 --- a/config/parsing/hop/parse.go +++ b/config/parsing/hop/parse.go @@ -21,6 +21,10 @@ import ( mdutil "github.com/go-gost/x/metadata/util" ) +// ParseHop converts a HopConfig into a hop.Hop. It resolves plugin backends +// (HTTP or gRPC), parses inline nodes with metadata inheritance from the parent +// hop, wires up a node selector, and configures optional file, Redis, and HTTP +// hot-reload sources. Returns nil with no error when cfg is nil. func ParseHop(cfg *config.HopConfig, log logger.Logger) (hop.Hop, error) { if cfg == nil { return nil, nil diff --git a/config/parsing/hosts/parse.go b/config/parsing/hosts/parse.go index 76aa8e5c..a574b0ec 100644 --- a/config/parsing/hosts/parse.go +++ b/config/parsing/hosts/parse.go @@ -14,6 +14,9 @@ import ( "github.com/go-gost/x/internal/plugin" ) +// ParseHostMapper converts a HostsConfig into a hosts.HostMapper. It resolves +// plugin backends (HTTP or gRPC), parses inline IP→hostname mappings, and +// configures optional file, Redis, and HTTP hot-reload support. func ParseHostMapper(cfg *config.HostsConfig) hosts.HostMapper { if cfg == nil { return nil diff --git a/config/parsing/ingress/parse.go b/config/parsing/ingress/parse.go index e90709f2..5f5679d8 100644 --- a/config/parsing/ingress/parse.go +++ b/config/parsing/ingress/parse.go @@ -13,6 +13,9 @@ import ( "github.com/go-gost/x/internal/plugin" ) +// ParseIngress converts an IngressConfig into an ingress.Ingress. It resolves +// plugin backends (HTTP or gRPC), parses inline hostname→endpoint rules, and +// configures optional file, Redis, and HTTP hot-reload support. func ParseIngress(cfg *config.IngressConfig) ingress.Ingress { if cfg == nil { return nil diff --git a/config/parsing/limiter/parse.go b/config/parsing/limiter/parse.go index 3ba4affa..419b8710 100644 --- a/config/parsing/limiter/parse.go +++ b/config/parsing/limiter/parse.go @@ -17,6 +17,9 @@ import ( traffic_plugin "github.com/go-gost/x/limiter/traffic/plugin" ) +// ParseTrafficLimiter converts a LimiterConfig into a traffic.TrafficLimiter. +// It resolves plugin backends (HTTP or gRPC), inline rate limits, and optional +// file, Redis, and HTTP hot-reload support. func ParseTrafficLimiter(cfg *config.LimiterConfig) (lim traffic.TrafficLimiter) { if cfg == nil { return nil @@ -89,6 +92,8 @@ func ParseTrafficLimiter(cfg *config.LimiterConfig) (lim traffic.TrafficLimiter) return xtraffic.NewTrafficLimiter(opts...) } +// ParseConnLimiter converts a LimiterConfig into a conn.ConnLimiter with +// inline limits and optional file, Redis, and HTTP hot-reload support. func ParseConnLimiter(cfg *config.LimiterConfig) (lim conn.ConnLimiter) { if cfg == nil { return nil @@ -137,6 +142,8 @@ func ParseConnLimiter(cfg *config.LimiterConfig) (lim conn.ConnLimiter) { return xconn.NewConnLimiter(opts...) } +// ParseRateLimiter converts a LimiterConfig into a rate.RateLimiter with +// inline limits and optional file, Redis, and HTTP hot-reload support. func ParseRateLimiter(cfg *config.LimiterConfig) (lim rate.RateLimiter) { if cfg == nil { return nil diff --git a/config/parsing/logger/parse.go b/config/parsing/logger/parse.go index 210edc89..46f18669 100644 --- a/config/parsing/logger/parse.go +++ b/config/parsing/logger/parse.go @@ -12,6 +12,9 @@ import ( "gopkg.in/natefinch/lumberjack.v2" ) +// ParseLogger converts a LoggerConfig into a logger.Logger. It configures +// output destination (stderr, stdout, file, or discard), log level, format, +// and optional log rotation via lumberjack. func ParseLogger(cfg *config.LoggerConfig) logger.Logger { if cfg == nil || cfg.Log == nil { return nil @@ -55,6 +58,8 @@ func ParseLogger(cfg *config.LoggerConfig) logger.Logger { return xlogger.NewLogger(opts...) } +// List resolves one or more logger names from the registry. It returns only +// the loggers that were found, skipping any that are not registered. func List(name string, names ...string) []logger.Logger { var loggers []logger.Logger if adm := registry.LoggerRegistry().Get(name); adm != nil { diff --git a/config/parsing/node/parse.go b/config/parsing/node/parse.go index d1d9fc32..5c536c6f 100644 --- a/config/parsing/node/parse.go +++ b/config/parsing/node/parse.go @@ -24,6 +24,11 @@ import ( "github.com/go-gost/x/routing" ) +// ParseNode converts a NodeConfig into a *chain.Node. It resolves the +// connector and dialer from their registries, applies TLS settings, extracts +// metadata-driven options (so_mark, interface, netns, proxy protocol), sets up +// bypass rules, node filters, HTTP settings, and TLS node settings. The hop +// parameter is used only for logging context. func ParseNode(hop string, cfg *config.NodeConfig, log logger.Logger) (*chain.Node, error) { if cfg == nil { return nil, nil diff --git a/config/parsing/observer/parse.go b/config/parsing/observer/parse.go index 16661578..e83c408d 100644 --- a/config/parsing/observer/parse.go +++ b/config/parsing/observer/parse.go @@ -10,6 +10,9 @@ import ( observer_plugin "github.com/go-gost/x/observer/plugin" ) +// ParseObserver converts an ObserverConfig into an observer.Observer. It only +// supports plugin backends (HTTP or gRPC); returns nil when cfg or cfg.Plugin +// is nil. func ParseObserver(cfg *config.ObserverConfig) observer.Observer { if cfg == nil || cfg.Plugin == nil { return nil diff --git a/config/parsing/parse.go b/config/parsing/parse.go index 87b7eb49..11a0eab1 100644 --- a/config/parsing/parse.go +++ b/config/parsing/parse.go @@ -1,32 +1,95 @@ +// Package parsing converts user-facing configuration structs into registered +// runtime components. Each sub-package (service, hop, chain, auth, …) owns the +// parsing logic for its corresponding core interface. +// +// Metadata keys defined below bridge the gap between named config fields and +// generic key-value metadata. When a value is not represented by an explicit +// field on a config struct it flows through the metadata system instead and +// these keys are used to look it up at component Init time. package parsing const ( + // MDKeyProxyProtocol sets the HAProxy proxy-protocol version on a listener. MDKeyProxyProtocol = "proxyProtocol" - MDKeyInterface = "interface" - MDKeySoMark = "so_mark" - MDKeyHash = "hash" - MDKeyPreUp = "preUp" - MDKeyPreDown = "preDown" - MDKeyPostUp = "postUp" - MDKeyPostDown = "postDown" - MDKeyIgnoreChain = "ignoreChain" - MDKeyEnableStats = "enableStats" - MDKeyRecorderDirection = "direction" + // MDKeyInterface binds the outbound connection to a specific network interface. + MDKeyInterface = "interface" + + // MDKeySoMark sets the SO_MARK socket option on outbound connections. + MDKeySoMark = "so_mark" + + // MDKeyHash selects the hash source used by hash-based selectors. + MDKeyHash = "hash" + + // MDKeyPreUp is a shell command executed when a service starts listening. + MDKeyPreUp = "preUp" + + // MDKeyPreDown is a shell command executed immediately before a service + // stops listening. + MDKeyPreDown = "preDown" + + // MDKeyPostUp is a shell command executed after a service has successfully + // started listening. + MDKeyPostUp = "postUp" + + // MDKeyPostDown is a shell command executed after a service has stopped + // listening. + MDKeyPostDown = "postDown" + + // MDKeyIgnoreChain disables chain routing for a service. When set the + // listener/handler will not prepend a chain, which is useful for services + // that handle routing themselves (e.g. DNS, TUN). + MDKeyIgnoreChain = "ignoreChain" + + // MDKeyEnableStats enables per-service connection statistics collection. + MDKeyEnableStats = "enableStats" + + // MDKeyRecorderDirection toggles whether traffic direction (client→server or + // server→client) is recorded alongside the payload. + MDKeyRecorderDirection = "direction" + + // MDKeyRecorderTimestampFormat sets the timestamp layout used in recorder + // output (Go time.Format layout). MDKeyRecorderTimestampFormat = "timeStampFormat" - MDKeyRecorderHexdump = "hexdump" - MDKeyRecorderHTTPBody = "http.body" + + // MDKeyRecorderHexdump enables hexadecimal dump output in recorders. + MDKeyRecorderHexdump = "hexdump" + + // MDKeyRecorderHTTPBody enables capturing the HTTP request/response body in + // HTTP-based recorders. + MDKeyRecorderHTTPBody = "http.body" + + // MDKeyRecorderHTTPMaxBodySize limits the maximum body size (in bytes) that + // an HTTP recorder will capture. MDKeyRecorderHTTPMaxBodySize = "http.maxBodySize" + // MDKeyLimiterRefreshInterval sets how often a limiter reloads its + // configuration from an external source. MDKeyLimiterRefreshInterval = "limiter.refreshInterval" + + // MDKeyLimiterCleanupInterval sets how often a limiter purges expired + // entries from its internal state. MDKeyLimiterCleanupInterval = "limiter.cleanupInterval" - MDKeyLimiterScope = "limiter.scope" + // MDKeyLimiterScope controls whether a cached traffic limiter's scope is + // per-service ("service") or per-client ("client"). + MDKeyLimiterScope = "limiter.scope" + + // MDKeyObserverResetTraffic requests a traffic counter reset each time the + // observer reports. MDKeyObserverResetTraffic = "observer.resetTraffic" - MDKeyObserverPeriod = "observer.period" - MDKeyNetns = "netns" + // MDKeyObserverPeriod sets the interval between observer reports. + MDKeyObserverPeriod = "observer.period" + + // MDKeyNetns is the network namespace name or path used for the listener + // side (inbound). + MDKeyNetns = "netns" + + // MDKeyNetnsOut is the network namespace name or path used for the handler + // (outbound) side. MDKeyNetnsOut = "netns.out" + // MDKeyDialTimeout sets the dial timeout for outbound connections. MDKeyDialTimeout = "dialTimeout" ) diff --git a/config/parsing/parser/parser.go b/config/parsing/parser/parser.go index dcb0e1e9..765ef416 100644 --- a/config/parsing/parser/parser.go +++ b/config/parsing/parser/parser.go @@ -17,23 +17,44 @@ var ( defaultParser = &parser{} ) +// Init stores the parsed CLI arguments so that subsequent calls to Parse can +// merge them with config-file and environment-variable sources. func Init(args Args) { defaultParser = &parser{ args: args, } } +// Parse reads configuration from the sources specified during Init (config +// file, CLI services/nodes, and environment variables) and returns a merged +// Config ready for loading. func Parse() (*config.Config, error) { return defaultParser.Parse() } +// Args holds the raw CLI flags and positional arguments that Init will merge +// into the final configuration. type Args struct { - CfgFile string - Services []string - Nodes []string - Debug bool - Trace bool - ApiAddr string + // CfgFile is the path to a YAML or JSON config file, "-" for stdin, or + // an inline JSON string. + CfgFile string + + // Services is the list of service definitions from -L flags. + Services []string + + // Nodes is the list of chain-node definitions from -F flags. + Nodes []string + + // Debug toggles debug-level logging. + Debug bool + + // Trace toggles trace-level logging (supersedes Debug). + Trace bool + + // ApiAddr is the address for the HTTP API server. + ApiAddr string + + // MetricsAddr is the address for the Prometheus metrics endpoint. MetricsAddr string } diff --git a/config/parsing/recorder/parse.go b/config/parsing/recorder/parse.go index 107a6446..637ac0af 100644 --- a/config/parsing/recorder/parse.go +++ b/config/parsing/recorder/parse.go @@ -22,6 +22,11 @@ type discardCloser struct{} func (discardCloser) Write(p []byte) (n int, err error) { return len(p), nil } func (discardCloser) Close() error { return nil } +// ParseRecorder converts a RecorderConfig into a recorder.Recorder. It +// supports plugin backends (HTTP or gRPC), file output (with optional +// rotation), TCP syslog-style delivery, HTTP POST delivery, and Redis storage +// (set, list, or sorted set). Returns nil when cfg is nil or no backend is +// configured. func ParseRecorder(cfg *config.RecorderConfig) (r recorder.Recorder) { if cfg == nil { return nil diff --git a/config/parsing/resolver/parse.go b/config/parsing/resolver/parse.go index 0d759d00..18be9151 100644 --- a/config/parsing/resolver/parse.go +++ b/config/parsing/resolver/parse.go @@ -14,6 +14,10 @@ import ( resolver_plugin "github.com/go-gost/x/resolver/plugin" ) +// ParseResolver converts a ResolverConfig into a resolver.Resolver. It +// supports plugin backends (HTTP or gRPC) and inline nameserver definitions +// with optional chain-based upstream routing, TTL, timeout, and +// prefer/async/only settings. Returns nil with no error when cfg is nil. func ParseResolver(cfg *config.ResolverConfig) (resolver.Resolver, error) { if cfg == nil { return nil, nil diff --git a/config/parsing/router/parse.go b/config/parsing/router/parse.go index bf295626..de06d3b7 100644 --- a/config/parsing/router/parse.go +++ b/config/parsing/router/parse.go @@ -14,6 +14,9 @@ import ( router_plugin "github.com/go-gost/x/router/plugin" ) +// ParseRouter converts a RouterConfig into a router.Router. It supports plugin +// backends (HTTP or gRPC) or inline static route definitions with optional +// file, Redis, and HTTP hot-reload support. func ParseRouter(cfg *config.RouterConfig) router.Router { if cfg == nil { return nil diff --git a/config/parsing/sd/parse.go b/config/parsing/sd/parse.go index c46c33a4..9c55520d 100644 --- a/config/parsing/sd/parse.go +++ b/config/parsing/sd/parse.go @@ -10,6 +10,8 @@ import ( sd_plugin "github.com/go-gost/x/sd/plugin" ) +// ParseSD converts an SDConfig into an sd.SD. It only supports plugin backends +// (HTTP or gRPC); returns nil when cfg or cfg.Plugin is nil. func ParseSD(cfg *config.SDConfig) sd.SD { if cfg == nil || cfg.Plugin == nil { return nil diff --git a/config/parsing/selector/parse.go b/config/parsing/selector/parse.go index 6f3e63bf..4197316b 100644 --- a/config/parsing/selector/parse.go +++ b/config/parsing/selector/parse.go @@ -7,6 +7,9 @@ import ( xs "github.com/go-gost/x/selector" ) +// ParseChainSelector creates a chain-level selector from a SelectorConfig. If +// cfg is nil it returns nil. Strategy defaults to round-robin when unrecognized +// or unset. func ParseChainSelector(cfg *config.SelectorConfig) selector.Selector[chain.Chainer] { if cfg == nil { return nil @@ -32,6 +35,9 @@ func ParseChainSelector(cfg *config.SelectorConfig) selector.Selector[chain.Chai ) } +// ParseNodeSelector creates a node-level selector from a SelectorConfig. If +// cfg is nil it returns nil. Supported strategies: round/rr, random/rand, +// fifo/ha, hash, and parallel. Defaults to round-robin. func ParseNodeSelector(cfg *config.SelectorConfig) selector.Selector[*chain.Node] { if cfg == nil { return nil @@ -60,6 +66,8 @@ func ParseNodeSelector(cfg *config.SelectorConfig) selector.Selector[*chain.Node ) } +// DefaultNodeSelector returns a node selector using round-robin strategy with +// default fail filter settings. func DefaultNodeSelector() selector.Selector[*chain.Node] { return xs.NewSelector( xs.RoundRobinStrategy[*chain.Node](), @@ -68,6 +76,8 @@ func DefaultNodeSelector() selector.Selector[*chain.Node] { ) } +// DefaultChainSelector returns a chain selector using round-robin strategy +// with default fail filter settings. func DefaultChainSelector() selector.Selector[chain.Chainer] { return xs.NewSelector( xs.RoundRobinStrategy[chain.Chainer](), diff --git a/config/parsing/service/parse.go b/config/parsing/service/parse.go index 4ff061f6..96359e41 100644 --- a/config/parsing/service/parse.go +++ b/config/parsing/service/parse.go @@ -38,6 +38,13 @@ import ( "github.com/vishvananda/netns" ) +// ParseService constructs a fully-wired service.Service from a ServiceConfig. +// It defaults the listener to "tcp" and the handler to "auto", resolves named +// components from the registry (authers, admissions, bypasses, resolvers, +// hosts, chains, hops, limiters, recorders, observers), composes TLS settings, +// and applies metadata-driven options (proxy protocol, netns, sockopts, +// pre/post hooks, stats, etc.). It returns an error if the listener or handler +// type is unknown or if construction of any sub-component fails. func ParseService(cfg *config.ServiceConfig) (service.Service, error) { if cfg.Listener == nil { cfg.Listener = &config.ListenerConfig{} diff --git a/config/parsing/tls.go b/config/parsing/tls.go index 7df2b1ad..84f81556 100644 --- a/config/parsing/tls.go +++ b/config/parsing/tls.go @@ -24,15 +24,25 @@ var ( defaultTLSConfig atomic.Value ) +// DefaultTLSConfig returns the global default TLS configuration used as a +// fallback when a listener or handler does not specify its own TLS settings. +// The returned config is a shared instance; callers that need to mutate it +// should clone it first. func DefaultTLSConfig() *tls.Config { v, _ := defaultTLSConfig.Load().(*tls.Config) return v } +// SetDefaultTLSConfig replaces the global default TLS configuration. It is safe +// to call from multiple goroutines. func SetDefaultTLSConfig(cfg *tls.Config) { defaultTLSConfig.Store(cfg) } +// BuildDefaultTLSConfig loads or generates the default TLS certificate and key +// from the given config. If cfg is nil it attempts to load well-known files +// ("cert.pem", "key.pem", "ca.pem"). On failure it generates a self-signed +// ECDSA P-256 certificate valid for one year. func BuildDefaultTLSConfig(cfg *config.TLSConfig) (*tls.Config, error) { log := logger.Default()