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) ClearMappingProbeV4()
- 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) RecordMappingProbeV4(symmetric bool)
- 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) ClearMappingProbeV4 ¶ added in v0.2.9
func (s *Sense) ClearMappingProbeV4()
ClearMappingProbeV4 discards the cached v4 mapping probe result.
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 any single public IPv4 address has been observed with ≥2 distinct ports in the live (non-expired) vote window. Used to overrule probe-based FullCone classification when there is live evidence that a single NAT device is assigning different external ports per destination (Symmetric NAT behavior).
Ports are only compared within the same public IP: a multi-homed host whose two NICs have different public IPs will each show one stable port and must NOT be treated as Symmetric. v6 GUA ports are also excluded.
func (*Sense) InferNATType ¶
InferNATType returns the best NAT classification for local operational use (punch strategy, session signalling). It is intentionally worst-case: symmetric detection considers ALL v4 paths — if any path shows symmetric behaviour the result is NATSymmetric, so the punch peer sprays ports. A false-positive symmetric here wastes spray bandwidth but never breaks connectivity; a false-negative would cause punch to miss.
Do NOT use this for publishing to the DHT — call PublishNatType() instead, which restricts symmetric detection to the STUN-confirmed path and uses the active mapping probe as the authoritative signal for that path.
Decision flow:
- Public bind (QUIC socket on a WAN IPv4) → NATFullCone.
- Symmetric (worst-case): passive all-path OR fresh mapping probe → NATSymmetric.
- 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 two ways:
Symmetric detection is restricted to the STUN-confirmed v4 path (trustedV4IPLocked). Other paths (VPN, private) are excluded so that a stable public endpoint is not mis-classified as Symmetric because of an unrelated path's NAT behaviour.
A fresh active mapping probe is authoritative for the STUN path: when one is available it overrides the passive vote analysis (which may be contaminated by UPnP session reuse). Without a fresh probe the passive analysis acts as a fallback.
When passive evidence is sufficient but the active probe has not yet completed, InferNATType returns NATRestricted; PublishNatType returns NATUnknown so that peers attempt direct-dial optimistically.
func (*Sense) RecordBindPublic
deprecated
added in
v0.1.4
func (*Sense) RecordMappingProbeV4 ¶ added in v0.2.9
RecordMappingProbeV4 records the result of the active v4 NAT port-consistency probe. symmetric=true means no single external port held a strict majority across probe targets (Symmetric NAT behaviour); false means one port dominated.
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.