Documentation
¶
Overview ¶
Package probe runs STUN Binding requests against one or more servers and captures mapping behavior (mapped endpoint, RTT, errors).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrFilteringNotSupported = errors.New("server did not advertise OTHER-ADDRESS")
ErrFilteringNotSupported is returned in FilteringResult.Err when the target server's BindingResponse does not include an OTHER-ADDRESS attribute, so the §4.4 sequence cannot be attempted.
var ErrTest1Failed = errors.New("initial probe failed; cannot run §4.4 sequence")
ErrTest1Failed wraps the underlying transport / parse error from the initial Binding probe. The §4.4 sequence is skipped when this error is returned.
Functions ¶
This section is empty.
Types ¶
type FilteringResult ¶ added in v0.1.2
type FilteringResult struct {
Server Server
Test1Mapped netip.AddrPort
Test1Other netip.AddrPort
Test2Received bool
Test3Received bool
Err error
}
FilteringResult captures the outcome of an RFC 5780 §4.4 three-step filtering classification. Test1Other.IsValid() == false means the server did not advertise OTHER-ADDRESS; in that case Test2Received and Test3Received are both false and Err wraps ErrFilteringNotSupported.
Server is the target of the §4.4 sequence (echoed from the ProbeFiltering argument so consumers can attribute the result without re-threading state).
func ProbeFiltering ¶ added in v0.1.2
ProbeFiltering runs RFC 5780 §4.4 against server. Uses one unconnected UDP socket for all three tests so (a) the NAT mapping stays stable across tests and (b) the socket can receive responses from the server's alt-IP/alt-port sources (a connected UDP socket would filter those out). Tests 2/3 are one-shot; "no response within timeout/2" is the verdict, not an error.
ctx governs the initial address resolution only; once resolution completes, per-test SetReadDeadline timers (timeout/2 each) drive the rest. Cancelling ctx mid-call has no effect on in-flight reads.
type HairpinningResult ¶ added in v0.1.4
HairpinningResult captures the outcome of an RFC 5780 §4.3 hairpinning detection probe. Detected is tri-state:
- nil: probe could not run end-to-end (socket allocation, DNS, or per-socket STUN probe failed); Err describes the underlying cause. Callers should emit WarnHairpinUntested at the classifier layer.
- &true: tagged loopback packet arrived on socket B; the NAT supports hairpinning for the (A→mB) path.
- &false: listen window elapsed with no tagged packet; either no hairpinning or a per-NAT filtering rule suppressed the loopback (spec-acknowledged false-negative case, see docs/design.md §4.3).
Server echoes the input so consumers can attribute the result without re-threading state, mirroring FilteringResult.
func ProbeHairpinning ¶ added in v0.1.4
ProbeHairpinning detects NAT hairpinning using two local UDP sockets:
- Allocate sockets A and B, unconnected, address family inherited from the resolved server IP.
- STUN-probe each socket in parallel against `server` to learn mapped endpoints mA and mB. Single-shot per probe — no retries. The wall-clock budget below depends on this.
- Send a 16-byte random nonce from A to mB.
- Listen on B for the nonce. Timeout: T_hairpin (= `timeout`).
Wall-clock budget: STUN phase (parallel) caps at min(timeout/2, 500ms); listen phase consumes up to `timeout`. Total ≤ 1.5 × timeout in the worst case. The caller orchestrates this in parallel with mapping probes; the non-functional target at docs/design.md:303 (<2s cold-start) is preserved for timeout ≤ 1s.
type Prober ¶
Prober performs one STUN Binding probe per call. Implementations must not panic on bad input and must respect context cancellation.
type Result ¶
type Result struct {
Server Server
Mapped netip.AddrPort
Other netip.AddrPort
RTT time.Duration
Err error
}
Result captures the outcome of a single probe. On success, Mapped and RTT are set and Err is nil. On failure, Err is non-nil and Mapped/RTT are zero.
Other carries the OTHER-ADDRESS attribute (RFC 5780 §7.4) when the server advertised one. Zero-value (Other.IsValid() == false) means the server's response did not include OTHER-ADDRESS, so it does not support the §4.4 filtering classification sequence.