2
0
mirror of synced 2025-02-24 14:48:27 +00:00

Restart DHT announces at regular intervals

The existing implementation would crawl the DHT until the address bloom filter was full. This could take ages unless enough peers were found to fill the pending nodes for the torrent to the high water mark. Fixes #301.
This commit is contained in:
Matt Joiner 2019-01-21 03:46:26 +01:00
parent 25cd79aa1c
commit 69c39f0036

View File

@ -8,7 +8,6 @@ import (
"io" "io"
"math" "math"
"math/rand" "math/rand"
"net"
"net/url" "net/url"
"os" "os"
"sync" "sync"
@ -1319,55 +1318,38 @@ func (t *Torrent) announceRequest() tracker.AnnounceRequest {
// Adds peers revealed in an announce until the announce ends, or we have // Adds peers revealed in an announce until the announce ends, or we have
// enough peers. // enough peers.
func (t *Torrent) consumeDHTAnnounce(pvs <-chan dht.PeersValues) { func (t *Torrent) consumeDhtAnnouncePeers(pvs <-chan dht.PeersValues) {
cl := t.cl cl := t.cl
// Count all the unique addresses we got during this announce. for v := range pvs {
allAddrs := make(map[string]struct{}) cl.lock()
for {
select {
case v, ok := <-pvs:
if !ok {
return
}
addPeers := make([]Peer, 0, len(v.Peers))
for _, cp := range v.Peers { for _, cp := range v.Peers {
if cp.Port == 0 { if cp.Port == 0 {
// Can't do anything with this. // Can't do anything with this.
continue continue
} }
addPeers = append(addPeers, Peer{ t.addPeer(Peer{
IP: cp.IP[:], IP: cp.IP[:],
Port: cp.Port, Port: cp.Port,
Source: peerSourceDHTGetPeers, Source: peerSourceDHTGetPeers,
}) })
key := (&net.UDPAddr{
IP: cp.IP[:],
Port: cp.Port,
}).String()
allAddrs[key] = struct{}{}
} }
cl.lock()
t.addPeers(addPeers)
numPeers := t.peers.Len()
cl.unlock() cl.unlock()
if numPeers >= cl.config.TorrentPeersHighWater {
return
}
case <-t.closed.LockedChan(cl.locker()):
return
}
} }
} }
func (t *Torrent) announceDHT(impliedPort bool, s *dht.Server) (err error) { func (t *Torrent) announceToDht(impliedPort bool, s *dht.Server) error {
cl := t.cl ps, err := s.Announce(t.infoHash, t.cl.incomingPeerPort(), impliedPort)
ps, err := s.Announce(t.infoHash, cl.incomingPeerPort(), impliedPort)
if err != nil { if err != nil {
return return err
}
go t.consumeDhtAnnouncePeers(ps.Peers)
select {
case <-t.closed.LockedChan(t.cl.locker()):
case <-time.After(5 * time.Minute):
case <-t.wantPeersEvent.LockedChan(t.cl.locker()):
} }
t.consumeDHTAnnounce(ps.Peers)
ps.Close() ps.Close()
return return nil
} }
func (t *Torrent) dhtAnnouncer(s *dht.Server) { func (t *Torrent) dhtAnnouncer(s *dht.Server) {
@ -1378,7 +1360,7 @@ func (t *Torrent) dhtAnnouncer(s *dht.Server) {
case <-t.closed.LockedChan(cl.locker()): case <-t.closed.LockedChan(cl.locker()):
return return
} }
err := t.announceDHT(true, s) err := t.announceToDht(true, s)
func() { func() {
cl.lock() cl.lock()
defer cl.unlock() defer cl.unlock()
@ -1388,11 +1370,6 @@ func (t *Torrent) dhtAnnouncer(s *dht.Server) {
t.logger.Printf("error announcing %q to DHT: %s", t, err) t.logger.Printf("error announcing %q to DHT: %s", t, err)
} }
}() }()
select {
case <-t.closed.LockedChan(cl.locker()):
return
case <-time.After(5 * time.Minute):
}
} }
} }