]> Sergey Matveev's repositories - btrtrc.git/blob - cmd/dht-ping/main.go
dht: Make Msg a struct with bencode tags
[btrtrc.git] / cmd / dht-ping / main.go
1 // Pings DHT nodes with the given network addresses.
2 package main
3
4 import (
5         "flag"
6         "fmt"
7         "log"
8         "net"
9         "os"
10         "time"
11
12         "github.com/anacrolix/torrent/dht"
13 )
14
15 type pingResponse struct {
16         addr string
17         krpc dht.Msg
18         rtt  time.Duration
19 }
20
21 func main() {
22         log.SetFlags(log.LstdFlags | log.Lshortfile)
23         timeout := flag.Duration("timeout", -1, "maximum timeout")
24         flag.Parse()
25         pingStrAddrs := flag.Args()
26         if len(pingStrAddrs) == 0 {
27                 os.Stderr.WriteString("u must specify addrs of nodes to ping e.g. router.bittorrent.com:6881\n")
28                 os.Exit(2)
29         }
30         s, err := dht.NewServer(nil)
31         if err != nil {
32                 log.Fatal(err)
33         }
34         log.Printf("dht server on %s", s.Addr())
35         pingResponses := make(chan pingResponse)
36         timeoutChan := make(chan struct{})
37         go func() {
38                 for i, netloc := range pingStrAddrs {
39                         if i != 0 {
40                                 time.Sleep(1 * time.Millisecond)
41                         }
42                         addr, err := net.ResolveUDPAddr("udp4", netloc)
43                         if err != nil {
44                                 log.Fatal(err)
45                         }
46                         t, err := s.Ping(addr)
47                         if err != nil {
48                                 log.Fatal(err)
49                         }
50                         start := time.Now()
51                         t.SetResponseHandler(func(addr string) func(dht.Msg) {
52                                 return func(resp dht.Msg) {
53                                         pingResponses <- pingResponse{
54                                                 addr: addr,
55                                                 krpc: resp,
56                                                 rtt:  time.Now().Sub(start),
57                                         }
58                                 }
59                         }(netloc))
60                 }
61                 if *timeout >= 0 {
62                         time.Sleep(*timeout)
63                         close(timeoutChan)
64                 }
65         }()
66         responses := 0
67 pingResponses:
68         for _ = range pingStrAddrs {
69                 select {
70                 case resp := <-pingResponses:
71                         responses++
72                         fmt.Printf("%-65s %s\n", fmt.Sprintf("%x (%s):", resp.krpc.R.ID, resp.addr), resp.rtt)
73                 case <-timeoutChan:
74                         break pingResponses
75                 }
76         }
77         // timeouts := len(pingStrAddrs) - responses
78         fmt.Printf("%d/%d responses (%f%%)\n", responses, len(pingStrAddrs), 100*float64(responses)/float64(len(pingStrAddrs)))
79 }