-
Notifications
You must be signed in to change notification settings - Fork 0
/
discovery_dht.go
109 lines (100 loc) · 1.93 KB
/
discovery_dht.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
package discovery
import (
"github.com/iain17/dht"
"context"
"time"
"net"
"github.com/iain17/logger"
)
type DiscoveryDHT struct {
node *dht.Server
announce *dht.Announce
localNode *LocalNode
context context.Context
logger *logger.Logger
}
func (d *DiscoveryDHT) String() string {
return "DiscoveryDHT"
}
func (d *DiscoveryDHT) init(ctx context.Context) (err error) {
defer func() {
if d.localNode.wg != nil {
d.localNode.wg.Done()
}
}()
d.logger = logger.New(d.String())
d.context = ctx
conn, err := net.ListenPacket("udp", ":0")
if err != nil {
return err
}
d.node, err = dht.NewServer(&dht.ServerConfig{
Conn: conn,
StartingNodes: dht.GlobalBootstrapAddrs,
})
if err != nil {
return err
}
return
}
func (d *DiscoveryDHT) Serve(ctx context.Context) {
defer d.Stop()
d.localNode.waitTilCoreReady()
if err := d.init(ctx); err != nil {
d.localNode.lastError = err
panic(err)
}
d.localNode.WaitTilReady()
if d.node == nil {
panic("Can't initiate DHT.")
}
ticker := time.Tick(HEARTBEAT_DELAY * time.Second)
d.request()
for {
select {
case <-d.context.Done():
return
case _, ok := <-ticker:
if !ok {
break
}
d.request()
break
case v, ok := <-d.announce.Peers:
if !ok {
break
}
if !d.localNode.netTableService.isEnoughPeers() {
for _, peer := range v.Peers {
addr := &net.TCPAddr{
IP: peer.IP[:],
Port: int(peer.Port),
}
d.localNode.netTableService.Discovered(addr)
}
}
break
}
time.Sleep(1 * time.Second)
}
}
func (d *DiscoveryDHT) Stop() {
if d.announce != nil {
d.announce.Close()
}
if d.node != nil {
d.node.Close()
}
}
func (d *DiscoveryDHT) request() {
ih := d.localNode.discovery.network.InfoHash()
d.logger.Debugf("sending request '%x'", ih)
if d.announce != nil {
d.announce.Close()
}
var err error
d.announce, err = d.node.Announce(ih, d.localNode.port, false)
if err != nil {
logger.Warning(err)
}
}