mirror of
https://github.com/taigrr/go-fastping
synced 2025-01-18 05:03:15 -08:00
Stop to use panic
This commit is contained in:
parent
85b47b7a02
commit
f81b4cf5d3
@ -40,7 +40,7 @@ func main() {
|
|||||||
})
|
})
|
||||||
|
|
||||||
p.MaxRTT = time.Second
|
p.MaxRTT = time.Second
|
||||||
quit := p.RunLoop()
|
quit, errch := p.RunLoop()
|
||||||
|
|
||||||
c := make(chan os.Signal, 1)
|
c := make(chan os.Signal, 1)
|
||||||
signal.Notify(c, os.Interrupt)
|
signal.Notify(c, os.Interrupt)
|
||||||
@ -65,6 +65,9 @@ loop:
|
|||||||
}
|
}
|
||||||
results[host] = nil
|
results[host] = nil
|
||||||
}
|
}
|
||||||
|
case err := <-errch:
|
||||||
|
fmt.Println("Ping failed: %v", err)
|
||||||
|
break loop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wait := make(chan bool)
|
wait := make(chan bool)
|
||||||
|
66
fastping.go
66
fastping.go
@ -151,11 +151,11 @@ func (p *Pinger) AddHandler(event string, handler interface{}) error {
|
|||||||
// Invoke a single send/receive procedure. It sends packets to all hosts which
|
// Invoke a single send/receive procedure. It sends packets to all hosts which
|
||||||
// have already been added by AddIP() etc. and wait those responses. When it
|
// have already been added by AddIP() etc. and wait those responses. When it
|
||||||
// receives a response, it calls "receive" handler registered by AddHander().
|
// receives a response, it calls "receive" handler registered by AddHander().
|
||||||
// After MaxRTT seconds, it calls "idle" handler and returns to caller. It
|
// After MaxRTT seconds, it calls "idle" handler and returns to caller with
|
||||||
// means it blocks until MaxRTT seconds passed. For the purpose of
|
// an error value. It means it blocks until MaxRTT seconds passed. For the
|
||||||
// sending/receiving packets over and over, use RunLoop().
|
// purpose of sending/receiving packets over and over, use RunLoop().
|
||||||
func (p *Pinger) Run() {
|
func (p *Pinger) Run() error {
|
||||||
p.run(true, make(chan chan<- bool))
|
return p.run(true, make(chan chan<- bool))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invode send/receive procedure repeatedly. It sends packets to all hosts which
|
// Invode send/receive procedure repeatedly. It sends packets to all hosts which
|
||||||
@ -164,33 +164,42 @@ func (p *Pinger) Run() {
|
|||||||
// After MaxRTT seconds, it calls "idle" handler, resend packets and wait those
|
// After MaxRTT seconds, it calls "idle" handler, resend packets and wait those
|
||||||
// response. MaxRTT works as an interval time.
|
// response. MaxRTT works as an interval time.
|
||||||
//
|
//
|
||||||
// This is a non-blocking method so immediately returns with a channel value.
|
// This is a non-blocking method so immediately returns with channel values.
|
||||||
// If you want to stop sending packets, send a channel value of bool type to it
|
// If you want to stop sending packets, send a channel value of bool type to it
|
||||||
// and wait for graceful shutdown. For example,
|
// and wait for graceful shutdown. For example,
|
||||||
//
|
//
|
||||||
// quit := p.RunLoop()
|
|
||||||
// wait := make(chan bool)
|
// wait := make(chan bool)
|
||||||
// quit <- wait
|
// quit, errch := p.RunLoop()
|
||||||
// <-wait
|
// ticker := time.NewTicker(time.Millisecond * 250)
|
||||||
|
// select {
|
||||||
|
// case err := <-errch:
|
||||||
|
// log.Fatalf("Ping failed: %v", err)
|
||||||
|
// case <-ticker.C:
|
||||||
|
// quit <- wait
|
||||||
|
// case <-wait:
|
||||||
|
// break
|
||||||
|
// }
|
||||||
//
|
//
|
||||||
// For more detail, please see "cmd/ping/ping.go".
|
// For more detail, please see "cmd/ping/ping.go".
|
||||||
func (p *Pinger) RunLoop() chan<- chan<- bool {
|
func (p *Pinger) RunLoop() (chan<- chan<- bool, <-chan error) {
|
||||||
quit := make(chan chan<- bool)
|
quit := make(chan chan<- bool)
|
||||||
go p.run(false, quit)
|
errch := make(chan error)
|
||||||
return quit
|
go func(ch chan<- error) {
|
||||||
|
err := p.run(false, quit)
|
||||||
|
if err != nil {
|
||||||
|
ch <- err
|
||||||
|
}
|
||||||
|
}(errch)
|
||||||
|
return quit, errch
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pinger) run(once bool, quit <-chan chan<- bool) {
|
func (p *Pinger) run(once bool, quit <-chan chan<- bool) error {
|
||||||
p.debugln("Run(): Start")
|
p.debugln("Run(): Start")
|
||||||
conn, err := net.ListenIP("ip4:icmp", &net.IPAddr{IP: net.IPv4zero})
|
conn, err := net.ListenIP("ip4:icmp", &net.IPAddr{IP: net.IPv4zero})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
return err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer conn.Close()
|
||||||
if err := conn.Close(); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var join chan<- bool
|
var join chan<- bool
|
||||||
recv, stoprecv, waitjoin := make(chan *packet), make(chan chan<- bool), make(chan bool)
|
recv, stoprecv, waitjoin := make(chan *packet), make(chan chan<- bool), make(chan bool)
|
||||||
@ -199,7 +208,7 @@ func (p *Pinger) run(once bool, quit <-chan chan<- bool) {
|
|||||||
go p.recvICMP4(conn, recv, stoprecv)
|
go p.recvICMP4(conn, recv, stoprecv)
|
||||||
|
|
||||||
p.debugln("Run(): call sendICMP4()")
|
p.debugln("Run(): call sendICMP4()")
|
||||||
queue := p.sendICMP4(conn)
|
queue, err := p.sendICMP4(conn)
|
||||||
|
|
||||||
ticker := time.NewTicker(p.MaxRTT)
|
ticker := time.NewTicker(p.MaxRTT)
|
||||||
|
|
||||||
@ -217,13 +226,13 @@ mainloop:
|
|||||||
hdl()
|
hdl()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if once {
|
if once || err != nil {
|
||||||
p.debugln("Run(): stoprecv <- waitjoin")
|
p.debugln("Run(): stoprecv <- waitjoin")
|
||||||
stoprecv <- waitjoin
|
stoprecv <- waitjoin
|
||||||
break mainloop
|
break mainloop
|
||||||
}
|
}
|
||||||
p.debugln("Run(): call sendICMP4()")
|
p.debugln("Run(): call sendICMP4()")
|
||||||
queue = p.sendICMP4(conn)
|
queue, err = p.sendICMP4(conn)
|
||||||
case r := <-recv:
|
case r := <-recv:
|
||||||
p.debugln("Run(): <-recv")
|
p.debugln("Run(): <-recv")
|
||||||
p.procRecv(r, queue)
|
p.procRecv(r, queue)
|
||||||
@ -239,10 +248,10 @@ mainloop:
|
|||||||
join <- true
|
join <- true
|
||||||
}
|
}
|
||||||
p.debugln("Run(): End")
|
p.debugln("Run(): End")
|
||||||
return
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pinger) sendICMP4(conn *net.IPConn) map[string]*net.IPAddr {
|
func (p *Pinger) sendICMP4(conn *net.IPConn) (map[string]*net.IPAddr, error) {
|
||||||
p.debugln("sendICMP4(): Start")
|
p.debugln("sendICMP4(): Start")
|
||||||
p.id = rand.Intn(0xffff)
|
p.id = rand.Intn(0xffff)
|
||||||
p.seq = rand.Intn(0xffff)
|
p.seq = rand.Intn(0xffff)
|
||||||
@ -258,7 +267,12 @@ func (p *Pinger) sendICMP4(conn *net.IPConn) map[string]*net.IPAddr {
|
|||||||
},
|
},
|
||||||
}).Marshal()
|
}).Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
for i := 0; i < qlen; i++ {
|
||||||
|
p.debugln("sendICMP4(): wait goroutine")
|
||||||
|
<-sent
|
||||||
|
p.debugln("sendICMP4(): join goroutine")
|
||||||
|
}
|
||||||
|
return queue, err
|
||||||
}
|
}
|
||||||
|
|
||||||
queue[k] = v
|
queue[k] = v
|
||||||
@ -286,7 +300,7 @@ func (p *Pinger) sendICMP4(conn *net.IPConn) map[string]*net.IPAddr {
|
|||||||
p.debugln("sendICMP4(): join goroutine")
|
p.debugln("sendICMP4(): join goroutine")
|
||||||
}
|
}
|
||||||
p.debugln("sendICMP4(): End")
|
p.debugln("sendICMP4(): End")
|
||||||
return queue
|
return queue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Pinger) recvICMP4(conn *net.IPConn, recv chan<- *packet, stoprecv <-chan chan<- bool) {
|
func (p *Pinger) recvICMP4(conn *net.IPConn, recv chan<- *packet, stoprecv <-chan chan<- bool) {
|
||||||
|
@ -61,7 +61,10 @@ func TestRun(t *testing.T) {
|
|||||||
p.AddHandler("idle", func() {
|
p.AddHandler("idle", func() {
|
||||||
idle = true
|
idle = true
|
||||||
})
|
})
|
||||||
p.Run()
|
err := p.Run()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("Pinger returns error: %v", err)
|
||||||
|
}
|
||||||
if !called {
|
if !called {
|
||||||
t.Fatalf("Pinger didn't get any responses")
|
t.Fatalf("Pinger didn't get any responses")
|
||||||
}
|
}
|
||||||
@ -104,7 +107,9 @@ func TestMultiRun(t *testing.T) {
|
|||||||
})
|
})
|
||||||
p1.MaxRTT, p2.MaxRTT = time.Millisecond*100, time.Millisecond*100
|
p1.MaxRTT, p2.MaxRTT = time.Millisecond*100, time.Millisecond*100
|
||||||
|
|
||||||
p1.Run()
|
if err := p1.Run(); err != nil {
|
||||||
|
t.Fatalf("Pinger 1 returns error: %v", err)
|
||||||
|
}
|
||||||
if res1 == 0 {
|
if res1 == 0 {
|
||||||
t.Fatalf("Pinger 1 didn't get any responses")
|
t.Fatalf("Pinger 1 didn't get any responses")
|
||||||
}
|
}
|
||||||
@ -113,7 +118,9 @@ func TestMultiRun(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res1, res2 = 0, 0
|
res1, res2 = 0, 0
|
||||||
p2.Run()
|
if err := p2.Run(); err != nil {
|
||||||
|
t.Fatalf("Pinger 2 returns error: %v", err)
|
||||||
|
}
|
||||||
if res1 > 0 {
|
if res1 > 0 {
|
||||||
t.Fatalf("Pinger 1 got response")
|
t.Fatalf("Pinger 1 got response")
|
||||||
}
|
}
|
||||||
@ -122,9 +129,28 @@ func TestMultiRun(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
res1, res2 = 0, 0
|
res1, res2 = 0, 0
|
||||||
go p1.Run()
|
errch1, errch2 := make(chan error), make(chan error)
|
||||||
go p2.Run()
|
go func(ch chan error) {
|
||||||
time.Sleep(time.Millisecond * 200)
|
err := p1.Run()
|
||||||
|
if err != nil {
|
||||||
|
ch <- err
|
||||||
|
}
|
||||||
|
}(errch1)
|
||||||
|
go func(ch chan error) {
|
||||||
|
err := p2.Run()
|
||||||
|
if err != nil {
|
||||||
|
ch <- err
|
||||||
|
}
|
||||||
|
}(errch2)
|
||||||
|
ticker := time.NewTicker(time.Millisecond * 200)
|
||||||
|
select {
|
||||||
|
case err := <-errch1:
|
||||||
|
t.Fatalf("Pinger 1 returns error: %v", err)
|
||||||
|
case err := <-errch2:
|
||||||
|
t.Fatalf("Pinger 2 returns error: %v", err)
|
||||||
|
case <-ticker.C:
|
||||||
|
break
|
||||||
|
}
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
if res1 != 1 {
|
if res1 != 1 {
|
||||||
t.Fatalf("Pinger 1 didn't get correct response")
|
t.Fatalf("Pinger 1 didn't get correct response")
|
||||||
@ -151,11 +177,17 @@ func TestRunLoop(t *testing.T) {
|
|||||||
idleCount++
|
idleCount++
|
||||||
})
|
})
|
||||||
|
|
||||||
quit := p.RunLoop()
|
|
||||||
time.Sleep(time.Millisecond * 250)
|
|
||||||
wait := make(chan bool)
|
wait := make(chan bool)
|
||||||
quit <- wait
|
quit, errch := p.RunLoop()
|
||||||
<-wait
|
ticker := time.NewTicker(time.Millisecond * 250)
|
||||||
|
select {
|
||||||
|
case err := <-errch:
|
||||||
|
t.Fatalf("Pinger returns error %v", err)
|
||||||
|
case <-ticker.C:
|
||||||
|
quit <- wait
|
||||||
|
case <-wait:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
if recvCount < 2 {
|
if recvCount < 2 {
|
||||||
t.Fatalf("Pinger recieve count less than 2")
|
t.Fatalf("Pinger recieve count less than 2")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user