81db46b725
- Fix dead-code branch in bind.go host assignment (always use endpoint hash) - Return descriptive error on bypass match in connect.go (was masking as success) - Update bypass test in connect_test.go for new error behavior - Extract entrypoint subpackage from monolithic entrypoint.go (6 files) - Fix observeStats event-loss bug (break -> fallthrough on retry success) - Add 47 unit tests across handler, connect, bind, metadata packages - Add architecture doc comments to all key files - Build and vet clean, 173 tests pass with -race
87 lines
3.1 KiB
Go
87 lines
3.1 KiB
Go
package entrypoint
|
|
|
|
import (
|
|
"net"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/go-gost/core/ingress"
|
|
"github.com/go-gost/core/logger"
|
|
"github.com/go-gost/core/recorder"
|
|
"github.com/go-gost/core/sd"
|
|
)
|
|
|
|
// Config carries dependencies from the tunnel handler into the entrypoint.
|
|
//
|
|
// All fields must be set by the caller before calling New. The DialFunc
|
|
// bridges the package boundary to avoid an import cycle.
|
|
type Config struct {
|
|
// Node is the local tunnel node ID (from tunnelHandler.id).
|
|
Node string
|
|
// Service is the parent handler's service name, used for ingress lookups,
|
|
// logging, and TLS certificate selection.
|
|
Service string
|
|
Ingress ingress.Ingress
|
|
SD sd.SD
|
|
Logger logger.Logger
|
|
Recorder recorder.RecorderObject
|
|
SniffingWebsocket bool
|
|
WebsocketSampleRate float64
|
|
// ReadTimeout is applied as SetReadDeadline on upstream connections
|
|
// before sniffing HTTP/TLS reads. Also used as
|
|
// http.Transport.ResponseHeaderTimeout. 0 or negative defaults to 15s.
|
|
ReadTimeout time.Duration
|
|
// ProxyProtocol is the PROXY protocol version (1 or 2) for the listener.
|
|
ProxyProtocol int
|
|
// KeepAlive enables HTTP keep-alive for the transport. Disabled by default.
|
|
KeepAlive bool
|
|
// Compression enables HTTP transport-level compression. Disabled by default.
|
|
Compression bool
|
|
}
|
|
|
|
// DialFunc is the function signature for establishing a tunnel connection.
|
|
// Implemented by the parent package (tunnel) to avoid import cycles.
|
|
//
|
|
// ctx carries recorder objects and loggers for the tunnel connection.
|
|
// network is always "tcp" for entrypoint connections.
|
|
// tid is the string representation of the target tunnel ID.
|
|
type DialFunc func(ctx DialContext, network, tid string) (conn net.Conn, node, cid string, err error)
|
|
|
|
// DialContext carries metadata for a dial request.
|
|
// This interface satisfies the context.Context Value() contract,
|
|
// allowing the parent package to pass a real context.Context which is
|
|
// recovered via type assertion in the DialFunc implementation.
|
|
type DialContext interface {
|
|
Value(any) any
|
|
}
|
|
|
|
// New creates a new Entrypoint with the given config and dial function.
|
|
//
|
|
// The config fields are copied into the Entrypoint struct. The dial function
|
|
// is stored as-is — nil functions cause dial failures at runtime, not at
|
|
// construction time.
|
|
//
|
|
// The HTTP transport is initialized immediately with ep.dial as its
|
|
// DialContext; responses time out after cfg.ReadTimeout (default 15s).
|
|
func New(cfg *Config, dialFn DialFunc) *Entrypoint {
|
|
ep := &Entrypoint{
|
|
node: cfg.Node,
|
|
service: cfg.Service,
|
|
ingress: cfg.Ingress,
|
|
sd: cfg.SD,
|
|
log: cfg.Logger,
|
|
recorder: cfg.Recorder,
|
|
sniffingWebsocket: cfg.SniffingWebsocket,
|
|
websocketSampleRate: cfg.WebsocketSampleRate,
|
|
readTimeout: cfg.ReadTimeout,
|
|
dialFn: dialFn,
|
|
}
|
|
ep.transport = &http.Transport{
|
|
DialContext: ep.dial,
|
|
IdleConnTimeout: 30 * time.Second,
|
|
ResponseHeaderTimeout: cfg.ReadTimeout,
|
|
DisableKeepAlives: !cfg.KeepAlive,
|
|
DisableCompression: !cfg.Compression,
|
|
}
|
|
return ep
|
|
} |