Skip to content

Instantly share code, notes, and snippets.

@woodsaj
Created September 11, 2020 10:37
Show Gist options
  • Save woodsaj/310ffafb1abde66b9373347d3eb12db9 to your computer and use it in GitHub Desktop.
Save woodsaj/310ffafb1abde66b9373347d3eb12db9 to your computer and use it in GitHub Desktop.
Example usage of github.com/woodsaj/go-pinger
package main
import (
"fmt"
"log"
"net"
"os"
"os/signal"
"strings"
"sync"
"time"
pinger "github.com/raintank/go-pinger"
)
type resultSet struct {
Host string
Success bool
}
func main() {
// initialize and start our pinger service that
// handles executing pings.
p, err := pinger.NewPinger("ipv4", 1000)
if err != nil {
log.Fatal(err)
}
p.Start()
// use channel to signal when all of our pings are complete
done := make(chan struct{})
// run our pings
go pinghosts(p, done)
// wait for our pings to be done or an interrupt to be received
waitforinterrupt(done)
fmt.Printf("\n")
}
func pinghosts(p *pinger.Pinger, done chan struct{}) {
defer close(done)
results := make(chan resultSet, 100)
host := "google.at"
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(host string) {
defer wg.Done()
r, err := ping(p, host)
if err != nil {
fmt.Printf("no results")
return
}
results <- r
}(host)
}
// wait for all spawned goroutines to finish, then close our
// results channel so we know not to expect any more results.
go func() {
wg.Wait()
close(results)
}()
i := 0
for v := range results {
fmt.Printf("%d - %+v\n", i, v)
i++
}
}
func ping(p *pinger.Pinger, host string) (resultSet, error) {
addr, err := resolveHost(host, "v4")
if err != nil {
log.Println(err)
return resultSet{}, err
}
stats, err := p.Ping(net.ParseIP(addr), 2, time.Second*2)
if err != nil {
log.Println(err)
return resultSet{}, err
}
res := resultSet{Host: host}
if stats.Sent != stats.Received {
res.Success = false
fmt.Printf("%s Sent: %d\n", host, stats.Sent)
fmt.Printf("%s Received: %d\n", host, stats.Received)
} else {
res.Success = true
}
return res, nil
}
func waitforinterrupt(done chan struct{}) {
var endwaiter sync.WaitGroup
endwaiter.Add(1)
var signalchannel chan os.Signal
signalchannel = make(chan os.Signal, 1)
signal.Notify(signalchannel, os.Interrupt)
go func() {
// wait for either an interrupt or "done" signal
select {
case <-signalchannel:
case <-done:
}
endwaiter.Done()
}()
endwaiter.Wait()
}
func resolveHost(host, ipversion string) (string, error) {
addrs, err := net.LookupHost(host)
if err != nil || len(addrs) < 1 {
return "", fmt.Errorf("failed to resolve hostname to IP")
}
for _, addr := range addrs {
if ipversion == "any" {
return addr, nil
}
if strings.Contains(addr, ":") || strings.Contains(addr, "%") {
if ipversion == "v6" {
return addr, nil
}
} else {
if ipversion == "v4" {
return addr, nil
}
}
}
return "", fmt.Errorf("failed to resolve hostname to valid IP")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment