Return error from Run() (#81)

* Return error to caller and let them handle it
* Use explicit return in Run()
* Silence linter for not handling recvICMP error
This commit is contained in:
maddie 2020-09-17 22:08:15 +08:00 committed by GitHub
parent 83991da571
commit e9da6dae98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 24 deletions

View File

@ -82,5 +82,8 @@ func main() {
pinger.SetPrivileged(*privileged) pinger.SetPrivileged(*privileged)
fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr()) fmt.Printf("PING %s (%s):\n", pinger.Addr(), pinger.IPAddr())
pinger.Run() err = pinger.Run()
if err != nil {
fmt.Printf("Failed to ping target host: %s", err)
}
} }

48
ping.go
View File

@ -295,28 +295,28 @@ func (p *Pinger) Privileged() bool {
// Run runs the pinger. This is a blocking function that will exit when it's // Run runs the pinger. This is a blocking function that will exit when it's
// done. If Count or Interval are not specified, it will run continuously until // done. If Count or Interval are not specified, it will run continuously until
// it is interrupted. // it is interrupted.
func (p *Pinger) Run() { func (p *Pinger) Run() error {
var conn *icmp.PacketConn var conn *icmp.PacketConn
var err error var err error
if p.ipaddr == nil { if p.ipaddr == nil {
err = p.Resolve() err = p.Resolve()
} }
if err != nil { if err != nil {
return return err
} }
if p.ipv4 { if p.ipv4 {
if conn = p.listen(ipv4Proto[p.protocol]); conn == nil { if conn, err = p.listen(ipv4Proto[p.protocol]); err != nil {
return return err
} }
if conn.IPv4PacketConn().SetControlMessage(ipv4.FlagTTL, true) != nil { if err = conn.IPv4PacketConn().SetControlMessage(ipv4.FlagTTL, true); err != nil {
return return err
} }
} else { } else {
if conn = p.listen(ipv6Proto[p.protocol]); conn == nil { if conn, err = p.listen(ipv6Proto[p.protocol]); err != nil {
return return err
} }
if conn.IPv6PacketConn().SetControlMessage(ipv6.FlagHopLimit, true) != nil { if err = conn.IPv6PacketConn().SetControlMessage(ipv6.FlagHopLimit, true); err != nil {
return return err
} }
} }
defer conn.Close() defer conn.Close()
@ -326,11 +326,12 @@ func (p *Pinger) Run() {
recv := make(chan *packet, 5) recv := make(chan *packet, 5)
defer close(recv) defer close(recv)
wg.Add(1) wg.Add(1)
//nolint:errcheck
go p.recvICMP(conn, recv, &wg) go p.recvICMP(conn, recv, &wg)
err = p.sendICMP(conn) err = p.sendICMP(conn)
if err != nil { if err != nil {
fmt.Println(err.Error()) return err
} }
timeout := time.NewTicker(p.Timeout) timeout := time.NewTicker(p.Timeout)
@ -342,29 +343,31 @@ func (p *Pinger) Run() {
select { select {
case <-p.done: case <-p.done:
wg.Wait() wg.Wait()
return return nil
case <-timeout.C: case <-timeout.C:
close(p.done) close(p.done)
wg.Wait() wg.Wait()
return return nil
case <-interval.C: case <-interval.C:
if p.Count > 0 && p.PacketsSent >= p.Count { if p.Count > 0 && p.PacketsSent >= p.Count {
continue continue
} }
err = p.sendICMP(conn) err = p.sendICMP(conn)
if err != nil { if err != nil {
// FIXME: this logs as FATAL but continues
fmt.Println("FATAL: ", err.Error()) fmt.Println("FATAL: ", err.Error())
} }
case r := <-recv: case r := <-recv:
err := p.processPacket(r) err := p.processPacket(r)
if err != nil { if err != nil {
// FIXME: this logs as FATAL but continues
fmt.Println("FATAL: ", err.Error()) fmt.Println("FATAL: ", err.Error())
} }
} }
if p.Count > 0 && p.PacketsRecv >= p.Count { if p.Count > 0 && p.PacketsRecv >= p.Count {
close(p.done) close(p.done)
wg.Wait() wg.Wait()
return return nil
} }
} }
} }
@ -426,16 +429,16 @@ func (p *Pinger) recvICMP(
conn *icmp.PacketConn, conn *icmp.PacketConn,
recv chan<- *packet, recv chan<- *packet,
wg *sync.WaitGroup, wg *sync.WaitGroup,
) { ) error {
defer wg.Done() defer wg.Done()
for { for {
select { select {
case <-p.done: case <-p.done:
return return nil
default: default:
bytes := make([]byte, 512) bytes := make([]byte, 512)
if conn.SetReadDeadline(time.Now().Add(time.Millisecond*100)) != nil { if err := conn.SetReadDeadline(time.Now().Add(time.Millisecond * 100)); err != nil {
return return err
} }
var n, ttl int var n, ttl int
var err error var err error
@ -459,7 +462,7 @@ func (p *Pinger) recvICMP(
continue continue
} else { } else {
close(p.done) close(p.done)
return return err
} }
} }
} }
@ -586,14 +589,13 @@ func (p *Pinger) sendICMP(conn *icmp.PacketConn) error {
return nil return nil
} }
func (p *Pinger) listen(netProto string) *icmp.PacketConn { func (p *Pinger) listen(netProto string) (*icmp.PacketConn, error) {
conn, err := icmp.ListenPacket(netProto, p.Source) conn, err := icmp.ListenPacket(netProto, p.Source)
if err != nil { if err != nil {
fmt.Printf("Error listening for ICMP packets: %s\n", err.Error())
close(p.done) close(p.done)
return nil return nil, err
} }
return conn return conn, nil
} }
func bytesToTime(b []byte) time.Time { func bytesToTime(b []byte) time.Time {