feat(nat): absorb autonat / hole-punching into NATService#2604
feat(nat): absorb autonat / hole-punching into NATService#2604gmelodie wants to merge 10 commits into
Conversation
6b25e5a to
15de6e7
Compare
15de6e7 to
52b122b
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #2604 +/- ##
==========================================
- Coverage 84.98% 84.82% -0.17%
==========================================
Files 165 165
Lines 28229 28498 +269
Branches 7 7
==========================================
+ Hits 23991 24173 +182
- Misses 4238 4325 +87
🚀 New features to boost your workflow:
|
richard-ramos
left a comment
There was a problem hiding this comment.
I like the idea of moving NAT traversal setup out of SwitchBuilder. It makes sense that NATService owns this logic, but in general we should be more careful with breaking changes. I think this should be done in a backwards compatible way.
Previously (when discussing the removal of {.public.} pragma, it was said the following:
If we introduce breaking changes or things suddenly stop being backward compatible, lets bump major versions. Minor versions are for backward compatible additions only or just new stuff. And the patch version just for bugs (tbf, it's rarelly used). If we can avoid the breaking change via
{.deprecated.}, no need to increment new version
And this is for sure something that we can avoid in this PR. (Let's leave major version updates when they can cause more impact).
I do think as well that the API was made harder to understand with this PR, due to reasons described below
| if self.config.autonat == Opt.some(AutonatV2): | ||
| raise newException( | ||
| ServiceSetupError, | ||
| "NATService: enableHolePunching currently requires AutoNAT v1; " & | ||
| "set NATConfig.autonat to none or some(AutonatV1).", | ||
| ) |
There was a problem hiding this comment.
wth. Holepunching should be independent of the autonat version. This seems to be something happening prior to this PR. Seems like we missed it when we were working on Autonat. Not a blocker for this PR but please create a follow up issue.
344d57a to
b31796e
Compare
b31796e to
ec9cbcd
Compare
a2828b3 to
5517f5b
Compare
There was a problem hiding this comment.
Pull request overview
This PR consolidates NAT traversal wiring by moving AutoNAT v1/v2 and hole-punching composition out of SwitchBuilder and into NATService, making withNAT(NATConfig) the single entry point for NAT traversal configuration.
Changes:
- Refactors
NATConfiginto three independent optional concerns (portMapping,reachability,holePunching) with helper constructors (upnpConfig,natPmpConfig,explicitIpConfig,autonatConfig,holePunchingConfig) and merge semantics. - Updates
SwitchBuilder.withNATto merge distinct concerns across multiple calls; deprecateswithAutonatV2/withHolePunchingas wrappers overwithNAT. - Updates tests and C bindings to use the new
withNAT(autonatConfig(...))/NATServiceaccessors.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/libp2p/services/test_natservice.nim | Expands NATService test coverage for reachability (AutoNAT v1/v2), HP composition, and merged configs. |
| tests/libp2p/protocols/test_autonat_v2_service.nim | Switch creation now enables AutoNAT v2 via withNAT(autonatConfig(AutonatV2)). |
| tests/interop/test_autonatv2.nim | Interop switch setup updated to use withNAT(autonatConfig(...)) for v2 service configuration. |
| tests/interop/autonatv2.nim | Uses NATService.natService() + autonatV2Service accessor instead of relying on service ordering/casts. |
| libp2p/services/natservice.nim | Core refactor: splits config concerns, wires AutoNAT v1/v2 + HP internally, adds natService and autonatV2Service accessors. |
| libp2p/services/autorelayservice.nim | Exports OnReservationHandler so hole-punching config can reference it via NATService API. |
| libp2p/builders.nim | Removes AutoNAT v2/HP wiring from builder; adds config merging in withNAT; introduces deprecated wrappers. |
| cbind/libp2p_thread/inter_thread_communication/requests/libp2p_lifecycle_requests.nim | C bindings now enable AutoNAT v2 via withNAT(autonatConfig(AutonatV2)). |
| proc mergeInto*(dst: var NATConfig, src: NATConfig) = | ||
| ## Fold ``src``'s set concerns into ``dst``; setting one concern twice is a | ||
| ## programmer error (build-time misuse), so it fails fast with a Defect. | ||
| template mergeField(field: untyped) = | ||
| src.field.withValue(v): | ||
| doAssert dst.field.isNone(), | ||
| "withNAT: " & astToStr(field) & " configured more than once" | ||
| dst.field = Opt.some(v) | ||
|
|
||
| mergeField(portMapping) | ||
| mergeField(reachability) | ||
| mergeField(holePunching) |

Summary
Move AutoNAT (v1/v2) and hole-punching wiring out of the builder and into
NATService, sowithNAT(NATConfig)is the single entry point for all NATtraversal concerns.
NATConfigis now three independent, optional concerns:portMapping— UPnP / NAT-PMP / explicit-IP, built viaupnpConfig,natPmpConfig,explicitIpConfig.reachability— AutoNAT v1/v2 probing, built viaautonatConfig(version, …).holePunching— DCUtR + AutoRelay + AutoNAT v1, built viaholePunchingConfig(…).withNATmay be called once per distinct concern and merges them; configuringthe same concern twice is a programmer error.
reachabilityandholePunchingare mutually exclusive (hole-punching already drives its own AutoNAT v1) and
pairing them is rejected at setup with
ServiceSetupError.withAutonatV2andwithHolePunchingare deprecated — kept as thin wrappersover
withNAT, not removed.Affected Areas
Impact on Library Users
Breaking API changes:
NATModeis split intoPortMappingMode(ExplicitIp/Upnp/NatPmp) andAutonatVersion(AutonatV1/AutonatV2). The oldAutomode is gone — anempty
NATConfig()is the no-op.NATConfigvia the helper procs (upnpConfig/natPmpConfig/explicitIpConfig/autonatConfig/holePunchingConfig) instead ofNATConfig(mode: …).withAutonatV2(…)/withHolePunching(…)now emit deprecation warnings;migrate to
withNAT(autonatConfig(AutonatV2, …))/withNAT(holePunchingConfig(…)).NATService.newnow takesrngas a required second argument.PortMapperFactorynow receivesPortMappingModeinstead ofNATMode.autonatV2Service: Opt[AutonatV2Service]accessor onNATService(derivedfrom the active reachability service).
References
Follows on from the
feat/nat/upnp-pmpseries; replaces the standalonechore/nat/include-autonat-hole-punchingbranch.