/
ping.go
65 lines (57 loc) · 1.21 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
package main
import (
"github.com/tatsushid/go-fastping"
"log"
"net"
"sync"
"time"
)
type response struct {
addr *net.IPAddr
rtt time.Duration
}
func ping(host string, ra *net.IPAddr, rtt time.Duration, c chan bool, lock *sync.RWMutex, store map[string]*HostStore) {
p := fastping.NewPinger()
results := make(map[string]*response)
results[ra.String()] = nil
p.AddIPAddr(ra)
onRecv, onIdle := make(chan *response), make(chan bool)
p.AddHandler("receive", func(addr *net.IPAddr, t time.Duration) {
onRecv <- &response{addr: addr, rtt: t}
})
p.AddHandler("idle", func() {
onIdle <- true
})
p.MaxRTT = rtt
quit, errch := p.RunLoop()
wait := make(chan bool)
loop:
for {
select {
case <-c:
log.Printf("get interrupted %v", ra)
quit <- wait
case res := <-onRecv:
if _, ok := results[res.addr.String()]; ok {
results[res.addr.String()] = res
}
case <-onIdle:
for v, r := range results {
lock.Lock()
if r == nil {
store[host].Insert(0)
} else {
store[host].Insert(r.rtt)
}
lock.Unlock()
results[v] = nil
}
case err := <-errch:
log.Println("%v failed: %v", ra, err)
c <- true
case <-wait:
break loop
}
}
log.Printf("exit %v", ra)
}