Documentation
¶
Overview ¶
Package natsense implements observed address consensus (spec Phase 2a: ≥3 distinct reporters). For tests or small networks, set MinAgreeingPeers to 1.
Index ¶
- Constants
- type Sense
- func (s *Sense) ClearProbeResult()
- func (s *Sense) ClearV4ProbeResult()
- func (s *Sense) ClearV6ProbeResult()
- func (s *Sense) HasMultiPortEvidence() bool
- func (s *Sense) InferNATType() uint8
- func (s *Sense) InferV6Reach() V6Reach
- func (s *Sense) InvalidateObservations()
- func (s *Sense) IsBindPublic() booldeprecated
- func (s *Sense) IsV4BindPublic() bool
- func (s *Sense) IsV6GUABind() bool
- func (s *Sense) MinAgreeing() int
- func (s *Sense) PublishNatType() uint8
- func (s *Sense) Record(reporter a2al.NodeID, observed []byte)
- func (s *Sense) RecordBindPublic(isPublic bool)deprecated
- func (s *Sense) RecordProbeResult(reachable bool)deprecated
- func (s *Sense) RecordV4BindPublic(isPublic bool)
- func (s *Sense) RecordV4ProbeResult(reachable bool)
- func (s *Sense) RecordV6GUABind(hasGUA bool)
- func (s *Sense) RecordV6ProbeResult(reachable bool)
- func (s *Sense) SetMinAgreeing(n int)
- func (s *Sense) TrustedUDP() (host string, port uint16, ok bool)
- func (s *Sense) TrustedUDPAll() []string
- func (s *Sense) TrustedWire() ([]byte, bool)
- func (s *Sense) TrustedWireV4() ([]byte, bool)
- func (s *Sense) TrustedWireV6() ([]byte, bool)
- type V6Reach
Constants ¶
const ( NATUnknown uint8 = 0 NATFullCone uint8 = 1 NATRestricted uint8 = 2 NATPortRestrict uint8 = 3 NATSymmetric uint8 = 4 )
NAT type constants (mirror protocol.NAT* for convenience).
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Sense ¶
type Sense struct {
// contains filtered or unexported fields
}
Sense tracks distinct peers that reported the same reflected UDP endpoint (wire bytes) and infers NAT type from both passive mapping observation and active probe results.
v4 and v6 state are maintained independently. InferNATType covers v4 only; use InferV6Reach for v6 reachability classification.
func (*Sense) ClearProbeResult ¶ added in v0.1.4
func (s *Sense) ClearProbeResult()
ClearProbeResult discards cached active-probe classification so the next probe result is used immediately after network changes. Deprecated: use ClearV4ProbeResult / ClearV6ProbeResult as needed.
func (*Sense) ClearV4ProbeResult ¶ added in v0.2.6
func (s *Sense) ClearV4ProbeResult()
ClearV4ProbeResult discards the cached v4 probe result.
func (*Sense) ClearV6ProbeResult ¶ added in v0.2.6
func (s *Sense) ClearV6ProbeResult()
ClearV6ProbeResult discards the cached v6 probe result.
func (*Sense) HasMultiPortEvidence ¶ added in v0.2.1
HasMultiPortEvidence reports whether ≥2 distinct external IPv4 ports have been observed in the live (non-expired) vote window. Used to overrule probe-based FullCone classification when there is any indication of port-varying (Symmetric) NAT behavior. Only v4 entries are considered; v6 GUA ports are stable by nature and must not contribute to this signal.
func (*Sense) InferNATType ¶
InferNATType returns the best NAT classification for local operational use (punch strategy, session signalling). It is intentionally conservative: when the active probe has not yet run it returns NATRestricted so that punch and ICE paths are prepared even before confirmation.
Do NOT use this for publishing to the DHT — call PublishNatType() instead, which returns NATUnknown in the unconfirmed case rather than NATRestricted, so that connecting peers treat us optimistically until we have real evidence.
Decision flow:
- Public bind (QUIC socket on a WAN IPv4) → NATFullCone.
- Symmetric mapping: ≥2 well-supported v4 observed ports → NATSymmetric. (v6 votes are excluded: GUA ports are stable and must not bias this check.)
- Insufficient passive evidence → NATUnknown.
- Active probe result (RecordV4ProbeResult): reachable=true → NATFullCone (any peer can initiate; Full Cone or cloud NAT) reachable=false → NATRestricted
- No probe result yet → NATRestricted (conservative default).
func (*Sense) InferV6Reach ¶ added in v0.2.6
InferV6Reach returns the current best classification of local IPv6 reachability. Decision flow:
- GUA bind confirmed → Direct (globally routable, no NAT).
- Active v6 probe result available → Direct or Firewalled.
- No information → Unknown.
func (*Sense) InvalidateObservations ¶ added in v0.1.4
func (s *Sense) InvalidateObservations()
InvalidateObservations clears passive observed_addr votes after confirmed network changes so old mappings do not bias the next consensus cycle.
func (*Sense) IsBindPublic
deprecated
added in
v0.1.4
func (*Sense) IsV4BindPublic ¶ added in v0.2.6
IsV4BindPublic reports whether the local socket is bound to a public WAN IPv4 address.
func (*Sense) IsV6GUABind ¶ added in v0.2.6
IsV6GUABind reports whether a local GUA was detected.
func (*Sense) MinAgreeing ¶
MinAgreeing returns the configured threshold.
func (*Sense) PublishNatType ¶ added in v0.2.6
PublishNatType returns the NAT capability value to embed in a published DHT endpoint record. It differs from InferNATType in exactly one case:
- When passive evidence is sufficient (stable single-port mapping) but the active probe has not yet completed, InferNATType returns NATRestricted as a conservative local hint; PublishNatType returns NATUnknown instead.
The rationale: a published NATRestricted causes connecting peers to skip v4 direct-dial and go straight to ICE, which is wasteful if we later confirm full-cone reachability. NATUnknown instructs peers to try direct optimistically while keeping ICE ready — the correct behaviour when we simply don't know yet.
All other cases (public bind, Symmetric, confirmed probe results, insufficient evidence) return the same value as InferNATType.
func (*Sense) RecordBindPublic
deprecated
added in
v0.1.4
func (*Sense) RecordProbeResult
deprecated
added in
v0.1.4
func (*Sense) RecordV4BindPublic ¶ added in v0.2.6
RecordV4BindPublic records whether the local UDP socket is bound to a public WAN IPv4 address. Called by host.RunNATProbe after inspecting the QUIC listen address.
func (*Sense) RecordV4ProbeResult ¶ added in v0.2.6
RecordV4ProbeResult records the outcome of an active v4 reachability probe. reachable=true means ≥1 remote peer successfully echoed our claimed v4 address.
func (*Sense) RecordV6GUABind ¶ added in v0.2.6
RecordV6GUABind records whether the local interface has an IPv6 Globally Unique Address (GUA). A GUA bind implies v6 direct reachability absent a stateful firewall. Called by host.RunNATProbe.
func (*Sense) RecordV6ProbeResult ¶ added in v0.2.6
RecordV6ProbeResult records the outcome of an active v6 reachability probe. reachable=true means ≥1 remote peer echoed our v6 address (Direct); false means a stateful firewall is blocking unsolicited inbound v6.
func (*Sense) SetMinAgreeing ¶
SetMinAgreeing updates the threshold (e.g. 1 for integration tests).
func (*Sense) TrustedUDP ¶
TrustedUDP returns host and port if some observed key has >= min distinct reporters whose votes are younger than voteTTL.
func (*Sense) TrustedUDPAll ¶ added in v0.2.6
TrustedUDPAll returns all observed keys (host:port strings) that have reached the minimum-agreement threshold. Unlike TrustedUDP it does not stop at the first match, so callers receive both IPv4 and IPv6 consensus entries when a dual-stack node is observed from multiple reporters.
func (*Sense) TrustedWire ¶
TrustedWire returns the first trusted observed_addr wire form (6 or 18 bytes), for any address family. Deprecated: prefer TrustedWireV4 / TrustedWireV6 for family-specific probing.
func (*Sense) TrustedWireV4 ¶ added in v0.2.6
TrustedWireV4 returns the wire-encoded trusted IPv4 external address, if any. Only v4 consensus entries are considered.
func (*Sense) TrustedWireV6 ¶ added in v0.2.6
TrustedWireV6 returns the wire-encoded trusted IPv6 external address, if any. Only v6 consensus entries are considered.