Documentation
¶
Overview ¶
Package freeport provides a shared, dependency-free TCP host-port allocator: a dual-stack bindability probe and a predicate-injected free-port search. It is a leaf package (stdlib only) so both internal/cli (host-proxy dev servers) and internal/serviceops (the service port-ownership guard) can import it without an import cycle, and so the search logic stays unit-testable without binding real sockets.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Bindable ¶
Bindable reports whether a TCP port can be bound across the addresses lerd's published quadlets and host-proxy dev servers publish on. A bind test is stricter and more accurate than a dial test for "can we publish here": it catches a port reserved on any stack, not just one with a live listener.
Three probes must all succeed. The loopback specifics (127.0.0.1 and [::1]) catch a server on a specific loopback address, and the [::1] probe also catches a v6-only wildcard [::] since it covers ::1. The wildcard probe (net.Listen on "0.0.0.0", an IPv4 all-interfaces socket) catches a v4-wildcard server (e.g. a MySQL on bind-address 0.0.0.0) that a specific-address bind slips past under SO_REUSEADDR on BSD/macOS, which would otherwise read as free. On macOS a running lerd container's gvproxy holds the dual-stack wildcard, so the wildcard probe reports its port in use; gvproxy releases it synchronously when the container stops, so a reinstall still rebinds without a spurious shift. A host with no IPv6 loopback at all is tolerated — the v6 check is skipped rather than treated as busy.
The wildcard probe is released before the loopback pair is bound: on Linux a held wildcard listener blocks a subsequent specific bind in the same process (EADDRINUSE), so overlapping them would make every port read as busy. The loopback pair is still held atomically across the two stacks.
func FirstFree ¶
FirstFree returns the first port at or above start for which taken reports false. The predicate is injected so the search is unit-testable without binding real sockets; callers compose it from Bindable plus any reserved-port set of their own. start is clamped to >= 1. Returns 0 when nothing in [start, 65535] is free, so callers can decide their own fallback.
Types ¶
This section is empty.