/
dht-util.go
114 lines (94 loc) · 2.66 KB
/
dht-util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package dht
import (
"github.com/hlandau/dht/krpc"
"github.com/hlandau/goutils/clock"
"net"
"time"
)
// Given a list of nodes, a wants string, and the address the request was
// received from, return a list of IPv4 and IPv6 node locators. The lists may
// be empty if that address family was not requested.
func formNodeList(nodes []*node, ws []string, addr net.UDPAddr) (nodes4 krNodesIPv4, nodes6 krNodesIPv6) {
v4, v6 := wants(ws, addr)
for _, n := range nodes {
nl := NodeLocator{
NodeID: n.NodeID,
Addr: n.Addr,
}
is4 := nl.Addr.IP.To4() != nil
if is4 && v4 {
nodes4 = append(nodes4, nl)
} else if !is4 && v6 {
nodes6 = append(nodes6, nl)
}
}
return
}
// Given a list of endpoints, a wants string, and the address the request was
// received from, return a list of IPv4 and IPv6 peer addresses.
func formPeerList(peerAddrs []net.UDPAddr, ws []string, addr net.UDPAddr) []krpc.Endpoint {
var endpoints []krpc.Endpoint
v4, v6 := wants(ws, addr)
for i := range peerAddrs {
is4 := peerAddrs[i].IP.To4() != nil
if (is4 && v4) || (!is4 && v6) {
endpoints = append(endpoints, krpc.Endpoint(peerAddrs[i]))
}
}
return endpoints
}
// Determine which address families a node is requesting or is assumed to
// support.
func wants(w []string, addr net.UDPAddr) (v4, v6 bool) {
v4 = hasItem(w, "n4")
v6 = hasItem(w, "n6")
if !v4 && !v6 {
v4 = (addr.IP.To4() != nil)
v6 = !v4
}
return
}
// Returns true if the list of strings contains the given item.
func hasItem(w []string, v string) bool {
if len(w) > 10 {
return false
}
for _, x := range w {
if x == v {
return true
}
}
return false
}
func timerAt(c clock.Clock, t time.Time) <-chan time.Time {
return c.After(t.Sub(c.Now()))
}
// Set whether an infohash is one we announce for.
func (dht *DHT) lSetLocallyOriginated(infoHash InfoHash, announce bool) {
if announce {
dht.locallyOriginated[infoHash] = struct{}{}
} else {
delete(dht.locallyOriginated, infoHash)
}
}
func (dht *DHT) lSetLocallyInterested(infoHash InfoHash, interested bool) {
if interested {
dht.locallyInterested[infoHash] = struct{}{}
} else {
delete(dht.locallyInterested, infoHash)
}
}
func (dht *DHT) needMoreNodes() bool {
numNodes := dht.neighbourhood.routingTable.Size()
return numNodes < dht.cfg.MinNodes || numNodes*2 < dht.cfg.MaxNodes
}
func (dht *DHT) acceptMoreNodes() bool {
numNodes := dht.neighbourhood.routingTable.Size()
return numNodes < dht.cfg.MaxNodes
}
func (dht *DHT) needMorePeers(infoHash InfoHash) bool {
return dht.peerStore.Count(infoHash) < dht.cfg.NumTargetPeers
}
func (dht *DHT) peersFor(infoHash InfoHash) []net.UDPAddr {
return dht.peerStore.Values(infoHash)
}