forked from anacrolix/dht
/
ping.go
73 lines (69 loc) · 1.47 KB
/
ping.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
// Pings DHT nodes with the given network addresses.
package main
import (
"errors"
"fmt"
"log"
"net"
"sync"
"time"
"github.com/anacrolix/dht/v2"
)
type pingArgs struct {
Network string
Timeout time.Duration `help:"sets a timeout for all queries"`
Defaults bool `help:"include all the default bootstrap nodes"`
Nodes []string `arg:"positional" arity:"*" help:"nodes to ping e.g. router.bittorrent.com:6881"`
}
func ping(args pingArgs, s *dht.Server) error {
var wg sync.WaitGroup
defaults := dht.DefaultGlobalBootstrapHostPorts
if !args.Defaults {
defaults = nil
}
for _, a := range append(args.Nodes, defaults...) {
func(a string) {
ua, err := net.ResolveUDPAddr(args.Network, a)
if err != nil {
log.Fatal(err)
}
started := time.Now()
wg.Add(1)
go func() {
defer wg.Done()
res := s.Ping(ua)
err := res.Err
if err != nil {
fmt.Printf("%s: %s: %s\n", a, time.Since(started), err)
return
}
id := *res.Reply.SenderID()
fmt.Printf("%s: %x %c: %s\n", a, id, func() rune {
if dht.NodeIdSecure(id, ua.IP) {
return '✔'
} else {
return '✘'
}
}(), time.Since(started))
}()
}(a)
}
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
timeout := make(chan struct{})
if args.Timeout != 0 {
go func() {
time.Sleep(args.Timeout)
close(timeout)
}()
}
select {
case <-done:
return nil
case <-timeout:
return errors.New("timed out")
}
}