Documentation
¶
Overview ¶
Package discover finds an IB Gateway or TWS endpoint on the local host when the user hasn't pinned one in config. The probe is TCP-only with a short timeout — we do not exchange the IBKR handshake here. The actual handshake runs against the winner through the daemon's broker connector, whose bounded connect path reports non-responsive listeners explicitly.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var Probe = dialTCP
Probe tests TCP connectivity to host:port with the given timeout. Returns nil on success (the connection is closed immediately). Exposed as a package var so tests can stub it; production code uses dialTCP.
var ProcessLister = listProcesses
ProcessLister enumerates running processes as raw lines, one per process, each containing at least the PID and the command line. Exposed so tests can stub the OS query. Returning nil (no processes) is the correct fallback when the underlying lookup fails — callers treat that as "no info" rather than "no app running."
var StandardPorts = []int{4001, 4002, 7496, 7497}
StandardPorts is the IBKR-default probe order.
4001 IB Gateway live 4002 IB Gateway paper 7496 TWS live 7497 TWS paper
First-hit-wins. The user can override entirely by pinning a port in config; discovery then short-circuits.
Functions ¶
This section is empty.
Types ¶
type Endpoint ¶
type Endpoint struct {
Host string
Port int
PortOrigin Origin
// TLS is the mode the SDK should attempt first.
TLS bool
TLSOrigin Origin
// EnableTLSFallback flips the SDK's tlsAttempts to retry the alternate
// TLS mode on failure. We set this true only when the user left TLS
// unpinned (auto). Pinned tls (true or false) → strict, no fallback.
EnableTLSFallback bool
ClientID int
Account string
// Alternates lists other ports that responded during the probe but
// lost the first-hit race. Surface them in `canary status` so the user
// knows e.g. "I'm on Gateway live but TWS is also up." Empty when the
// port was pinned (discovery skipped) or no other ports responded.
Alternates []int
}
Endpoint is the post-discovery, fully-concrete connection spec the daemon hands to pkg/ibkr.
func Resolve ¶
func Resolve(ctx context.Context, g PartialGateway) (Endpoint, error)
Resolve produces a concrete Endpoint by combining pinned values from g with TCP-probe discovery for whichever dimension is left auto. The probe runs concurrently across all candidate ports; the lowest-index responder wins. Returns an error only if g.Host is unreachable for every candidate (i.e. no listeners at all) — in which case the daemon still starts but publishes the error via the watchdog.
type IBKRApp ¶
IBKRApp identifies which Interactive Brokers desktop app — if any — is running on the host. Used to enrich the "no listener found" error with a hint that distinguishes "no app running" (start one) from "app running but API socket closed" (check the API settings).
Name is one of "TWS", "IB Gateway", "IBKR Desktop", or "" (unknown / not found / lookup failed). PID is 0 when Name is "".
func DetectIBKRApp ¶
DetectIBKRApp returns the first matching IBKR desktop app found in the process list. Best-effort: any error or absence of a match yields a zero IBKRApp. Callers must treat the zero value as "no information available" rather than asserting nothing is running.
Matching is substring + case-insensitive against the full process command line so it works whether the OS reports `Trader Workstation.app/.../...`, `ibgateway`, or `IBKR Desktop`.
type Origin ¶
type Origin string
Origin records why a dimension has its current value: was it pinned in config (binding), discovered by probe, or filled from a built-in default.
type PartialGateway ¶
type PartialGateway struct {
Host string
Port *int
ClientID *int
Account string
TLS *bool
ProbePorts []int // override StandardPorts; empty → StandardPorts
ProbeTimeout time.Duration // per-port; 0 → 200ms
}
PartialGateway is the minimal subset of config.Gateway this package needs. Defined here (not imported) so internal/config doesn't get a dependency on internal/discover and so tests can construct one trivially.