Workflow status is tracked in GitHub: https://github.com/emulebb/emulebb-rust/issues/159. This local document is retained as the durable engineering spec and evidence record.
RUST-BUG-134 - Own MiniUPnPc URL allocations across fallible discovery¶
Summary¶
Wrap every successfully initialized MiniUPnPc UPNPUrls value in an immediate
RAII owner so every fallible discovery and conversion path frees native URL
buffers exactly once.
Current State¶
gateway_from_url and build_gateway_from_devlist pass zeroed UPNPUrls
storage to MiniUPnPc. Successful native calls populate heap-owned URL pointers,
but Rust does not place them under Drop ownership until build_gateway
returns a Gateway. Missing or unusable URL/service fields and other errors in
that interval return early without calling FreeUPNPUrls.
MiniUPnPc documents that nonzero UPNP_GetValidIGD results initialize the URL
structure and require FreeUPNPUrls; UPNP_GetIGDFromUrl likewise calls
GetUPNPUrls before returning success.
Why This Matters¶
Discovery runs against network devices and malformed or unusual IGD metadata is an expected failure boundary. Repeated retries must not leak native allocations or make cleanup depend on every future early-return path remembering a manual free.
Representative Sites¶
crates/emulebb-miniupnpc/src/lib.rsgateway_from_url.crates/emulebb-miniupnpc/src/lib.rsbuild_gateway_from_devlist.crates/emulebb-miniupnpc/src/lib.rsbuild_gatewayandGateway::drop.- Vendored MiniUPnPc
miniupnpc.hownership contract.
Intended Shape¶
- Introduce a private
OwnedUpnpUrlsor equivalent guard whoseDropinvokesFreeUPNPUrlsexactly once. - Establish ownership immediately after a native call reports initialized URLs, before parsing or constructing Rust strings.
- Move the guard into
Gatewayonly after all fallible validation succeeds. - Represent the zero/uninitialized state explicitly enough that failure returns cannot double-free or free foreign storage.
- Keep raw pointers and release calls inside the smallest FFI ownership module.
Scope Constraints¶
- Preserve MiniUPnPc discovery status mapping and eMuleBB NAT backend order.
- Do not paper over malformed gateway data with empty strings; validation should remain fallible and cleanup should remain unconditional.
- Do not add
SendorSyncto the native gateway owner without a separate upstream thread-safety proof. - This changes Rust ownership only, not UPnP wire behavior.
Acceptance Criteria¶
- [ ] Every native call that initializes
UPNPUrlstransfers it immediately to one RAII owner. - [ ] Every success, validation error, unexpected-status error, and constructor error frees the URLs exactly once.
- [ ] Moving URLs into a live
Gatewayprevents the temporary guard from releasing them early. - [ ] Null, partial, and malformed gateway metadata remain recoverable errors without leaks or double frees.
- [ ] No unsafe
Send/Syncimplementation is introduced for the gateway.
Validation¶
- FFI seam tests with stubbed successful, partial, malformed, and unexpected discovery results plus an exact free-call counter.
- Repeated discovery-failure test under a native leak detector where available.
- Existing MiniUPnPc, NAT backend, and daemon startup tests on all supported operating systems.