publicAddrs property
Returns only public/observed addresses suitable for holepunching. This includes:
- Observed addresses from identify service (external addresses seen by peers)
- Addresses that AutoNAT has verified as reachable (when AutoNAT status is public)
- Excludes private network addresses that are not reachable externally
Implementation
List<MultiAddr> get publicAddrs {
final publicAddresses = <MultiAddr>[];
// Get observed addresses from identify service
// These are addresses that other peers have seen us on, which should be public-facing
final observed = _idService.ownObservedAddrs();
publicAddresses.addAll(observed);
// AmbientAutoNATv2 provides reachability status automatically
// Only include addresses when we've confirmed public reachability
if (_autoNATService != null && _autoNATService!.status == Reachability.public) {
_log.fine('[BasicHost publicAddrs] AmbientAutoNATv2 status is public');
// When AutoNAT confirms we're publicly reachable, include public addresses
final candidateAddrs = allAddrs.where((addr) {
return addr.isPublic() && !isRelayAddress(addr);
}).toList();
_log.fine('[BasicHost publicAddrs] Adding ${candidateAddrs.length} verified public addresses');
publicAddresses.addAll(candidateAddrs);
}
// Remove duplicates and filter out any private addresses that may have slipped through
final uniqueAddrs = <String, MultiAddr>{};
for (final addr in publicAddresses) {
if (addr.isPublic()) {
uniqueAddrs[addr.toString()] = addr;
}
}
final result = uniqueAddrs.values.toList();
// TESTING FALLBACK: If no public addresses found, use non-relay addresses for testing
// This allows holepunching to work in controlled NAT environments like Docker
if (result.isEmpty) {
final fallbackAddrs = allAddrs.where((addr) => !isRelayAddress(addr)).toList();
_log.fine('[BasicHost publicAddrs] No public addresses found, using ${fallbackAddrs.length} fallback addresses for testing: $fallbackAddrs');
return fallbackAddrs;
}
_log.fine('[BasicHost publicAddrs] for host ${id.toString()} - Observed: ${observed.length}, Final result: ${result.length} addresses: $result');
return result;
}