Wire BEP 9 metadata exchange into wl get (peer fallback)#11
Merged
Conversation
Previously the BEP 9 ut_metadata implementation (FetchMetadata) was built and tested but never called — wl get always sourced the info dict from the registry API, so a magnet only resolved if it was registered, and the README's BEP 9 claim was effectively dead. Rather than delete a valid protocol path, wire it in. - wl get now tries the registry first, then falls back to BEP 9: announce → connect to peers → fetch the info dict via ut_metadata → parse → download. The whole client chain already existed and is exported (Connect → Handshake, which does the BEP 10 extended handshake inline → FetchMetadata). - torrent.ParseInfo: parse a bare info dict (what a peer serves) into TorrentMeta, sharing parseInfoMap with Parse. - torrent.BuildMetainfo: rebuild a saveable .torrent from peer-fetched info bytes via bencode.RawMessage, preserving the info hash exactly. Verification: - TestFetchMetadataEndToEnd: real wire protocol against a BEP 9-speaking mock peer (handshake + extended handshake with metadata_size + multi-piece ut_metadata data, 40 KB / 3 pieces). First real end-to-end test for the path. - TestParseInfoRoundTrip: ParseInfo on a bare info dict matches Parse on the full torrent, and BuildMetainfo round-trips with the v2 info hash preserved. Scope: BEP 9 fetch verifies against the v1 (SHA-1) hash, so v2-only magnets can't use it (errors clearly). Because weightless's own tracker is registry-only (registration stores the .torrent AND enables tracking), the fallback mainly helps in open-tracker mode or with external/public trackers — where peers exist but no registry entry does.
iksnerd
added a commit
that referenced
this pull request
Jun 21, 2026
Wire BEP 9 metadata exchange into wl get (peer fallback)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Code Nexus analysis flagged
FetchMetadataas dead code — the BEP 9ut_metadataimplementation was built and tested but never called, sowl getalways sourced the info dict from the registry API. A magnet only resolved if it was registered, and the README's BEP 9 claim was effectively dead. BEP 9 is a valid, core part of the magnet workflow, so this wires it in rather than deleting it.Changes
wl gettries the registry first, then falls back to BEP 9: announce → connect to peers → fetch the info dict viaut_metadata→ parse → download. The client chain already existed and is exported (Connect→Handshake, which does the BEP 10 extended handshake inline →FetchMetadata); this is the glue.torrent.ParseInfo— parse a bare info dict (what a peer serves over BEP 9) intoTorrentMeta, sharingparseInfoMapwithParse.torrent.BuildMetainfo— rebuild a saveable.torrentfrom peer-fetched info bytes viabencode.RawMessage, preserving the info hash exactly.Verification
TestFetchMetadataEndToEnd— real wire protocol against a BEP 9-speaking mock peer: BEP 3 handshake + BEP 10 extended handshake advertisingmetadata_size+ multi-pieceut_metadatadata (40 KB / 3 pieces). This is the first real end-to-end test for the metadata path (previously only a size-guard unit test existed — which is how it slipped to dead code).TestParseInfoRoundTrip—ParseInfoon a bare info dict matchesParseon the full torrent;BuildMetainforound-trips with the v2 info hash byte-preserved.go build/go vet/gofmtclean; fullgo test ./...green.Scope / honest notes
ut_metadataverifies against the v1 (SHA-1) info hash, so v2-only magnets can't use the fallback — it errors clearly rather than silently..torrentand enables peer tracking), so on it a registry miss also means no peers. The fallback therefore mainly helps in open-tracker mode or with external/public trackers — where peers exist but no registry entry does. Full multi-process verification (Transmission seeding via an open tracker) is the natural next manual step.🤖 Generated with Claude Code