You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Adds bep_0014 (local peer discovery)
* Add BEP-14 Local Peer Discovery (LPD)
Implements BEP-14 Local Peer Discovery via UDP multicast, allowing
clients to discover peers on the local network without a tracker.
- Adds LPDServer with IPv4 (239.192.152.143:6771) and optional IPv6
(ff15::efc0:988f:6771) multicast support
- Announces active torrents periodically and on new torrent add
- Discovered peers are added to matching torrents and broadcast to all
active torrents (LPD is the only source of local IPs)
- Fixes self-message detection: compare source IP against publisher's
local address rather than broken string contains check
- Configurable via EnableLocalServiceDiscovery and
LocalServiceDiscoveryConfig (interface selection, IPv6 toggle)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add BEP-14 tests before refactor
Unit tests:
- TestLPDPeerDeduplication: same peer address added twice -> one entry
- TestLPDPeerExpiry: stale peers removed after 2*bep14LongTimeout
Integration tests:
- TestPeerAddedToAllTorrents: peer broadcast to all active torrents,
not only the one matching the announced infohash
- TestNewTorrentGetsExistingPeers: torrent added after discovery
immediately receives known peers via lpdPeers() in AddTorrentSpec
- TestReceiverMalformedMessages: wrong method / missing Infohash /
missing Port header all silently dropped with no peers added
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Refactor BEP-14: decouple LPD goroutines from *Client
- Define lpdClient interface so receiver/announcer goroutines never
touch *Client internals directly, eliminating interleaved lock ordering
- Replace missinggo.Event stop/force signals with context.Context and a
buffered chan struct{}, removing the missinggo dependency from bep14.go
- Change peers map from map[int64]string (timestamp key, address value)
to map[string]time.Time (address key) for O(1) deduplication and
straightforward expiry in refresh()
- Fix double-dial bug in lpdConnNew: the unconditional net.DialUDP call
before the interface-specific branch leaked a connection on every start
- Move OnLPDAnnouncement logic into (*Client).OnLPDAnnouncement and
TorrentInfohashesAndPort into (*Client).TorrentInfohashesAndPort,
keeping bep14.go free of metainfo/torrent-map access
- lpdForce uses non-blocking channel send; no mutex required
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Add torrent lpd subcommand for BEP-14 Local Peer Discovery
Two modes, no full client required:
torrent lpd listen [--ip6]
Joins the multicast group and prints every incoming BT-SEARCH
announcement (timestamp, source IP, peer port, infohash(es))
to stdout until Ctrl-C.
torrent lpd announce --port PORT [--ip6] INFOHASH [...]
Sends a single BT-SEARCH packet for the given infohash hex
strings and exits immediately.
Both modes optionally extend to the IPv6 group via --ip6.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Clean up BEP-14 branch for upstream PR
Drop leftover debug log.Println in torrent.go, apply gofmt to config.go
and torrent.go, and revert the go.work.sum churn so the rebase onto
upstream/master can apply cleanly.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Extract buildAnnouncePacket helper and add tests
Pull the packet-building loop out of lpdConn.announcer into a pure
buildAnnouncePacket function so it can be unit-tested directly. The
announcer now just feeds the helper the current queue and resumes from
the returned index on the next tick.
Tests added:
- TestBuildAnnouncePacketSingle: small queue fits in one packet and
completes a rotation.
- TestBuildAnnouncePacketFragments: a 40-infohash queue is split across
multiple packets, every infohash appears exactly once, and rotation is
reported only after the final packet.
- TestBuildAnnouncePacketEmptyQueue: empty queue yields nil packet and a
trivial rotation.
- TestMultiInfohash now asserts the parsed infohash list and port.
Also handles a shutdown race in announcer where a Write on the closed
multicast conn would log a spurious error, and drops a stale //hiiiii
comment.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Revert stray whitespace change in testutil/greeting.go
Unrelated to BEP-14; can be squashed into the prior cleanup commit
during rebase.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* whitespace and discovery info to peer.go
* Address PR #998 feedback: rename, MTU comment, attribution
- Rename LPDServer to lpdServer (package-internal, unexport).
- Add comment explaining the 1400-byte announce packet cap (typical
Ethernet MTU).
- Credit the original implementation at
gitlab.com/axet/libtorrent/lpd.go (LGPL-3).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* BEP-14: make LocalServiceDiscovery a *Config (nil = disabled)
Replace the EnableLocalServiceDiscovery bool + LocalServiceDiscoveryConfig
struct value pair with a single LocalServiceDiscovery *LocalServiceDiscoveryConfig
field. A nil pointer disables LPD; any non-nil value enables it with those
options. Addresses the config.go:49 feedback from PR #998: one source of
truth, no need for callers or internal code to track an enabled flag.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* BEP-14: take explicit ownership of the multicast packet conn
Replace setMulticastInterface's silent if/if dispatch with a switch-based
newMcPacketConn factory that returns an error on unsupported networks.
The returned *ipv4.PacketConn or *ipv6.PacketConn is stored on lpdConn
via a narrow mcPacketConn interface instead of being dropped on the floor
for GC to pick up. Addresses anacrolix's bep14.go:73 feedback from PR #998.
Also fixes a tab-before-comment nit on PeerSourceLPD to keep gofmt clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* BEP-14: make discovery tests independent of multicast delivery
TestDiscovery and related tests opened real multicast sockets and waited
for cross-client loopback, which hangs on GitHub's macOS runners (EPIPE
on writes, nothing delivered on reads) until the 10-minute test
timeout. Extract handleAnnouncePacket from receiver() so tests can drive
the receive path directly with crafted BT-SEARCH packets, and give
waitForPeers a 30s deadline via a timer-driven Broadcast so a missed
wakeup fails fast instead of hanging the whole suite.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* BEP-14: add MPL-2.0 headers to files derived from axet/libtorrent lpd.go
Alexey Kuznetsov granted permission to use lpd.go under MPL-2.0,
matching this project's license. Add the standard MPL-2.0 short
header to bep14.go, bep14_test.go, and cmd/torrent/lpd.go, with an
attribution note recording the relicensing grant. Drops the earlier
LGPL-3 note, which is superseded by the grant.
---------
Co-authored-by: Phil Cummins <philip.cummins@bsc.es>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Matt Joiner <anacrolix@gmail.com>
Co-authored-by: Vuzzy