mirror of https://github.com/balkian/pingish
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
2.9 KiB
Go
139 lines
2.9 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/tatsushid/go-fastping"
|
|
)
|
|
|
|
type Response struct {
|
|
Host string
|
|
Up bool
|
|
RTT []time.Duration `json:"RTT,omitempty"`
|
|
}
|
|
|
|
var PING_COUNT = 1
|
|
|
|
func homeHandler(w http.ResponseWriter, r *http.Request) {
|
|
fmt.Fprint(w, "<h1>Ping a hostname</h1>"+
|
|
"<form action=\"/ping/\" method=\"GET\">"+
|
|
"<input type=\"text\" name=\"host\"><br>"+
|
|
"<input type=\"submit\" value=\"Ping\">"+
|
|
"</form>")
|
|
return
|
|
}
|
|
|
|
func pingHandler(w http.ResponseWriter, r *http.Request) {
|
|
name := r.URL.Query().Get("host")
|
|
if name == "" {
|
|
tokens := strings.Split(r.URL.Path, "/")
|
|
if len(tokens) < 3 || tokens[2] == "" {
|
|
http.Error(w, "You have to specify a hostname to ping", http.StatusBadRequest)
|
|
return
|
|
}
|
|
name = tokens[2]
|
|
}
|
|
times := PING_COUNT
|
|
count := r.URL.Query().Get("count")
|
|
fmt.Printf("Requested %s %s times\n", name, count)
|
|
|
|
if count != "" {
|
|
if counts, err := strconv.Atoi(count); err == nil {
|
|
times = counts
|
|
}
|
|
}
|
|
|
|
up, rtt, err := CheckHost(name, times)
|
|
|
|
response := Response{Host: name, Up: up, RTT: rtt}
|
|
js, err := json.Marshal(response)
|
|
if err != nil {
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
if !up {
|
|
http.Error(w, string(js), http.StatusNotFound)
|
|
return
|
|
}
|
|
w.Write(js)
|
|
|
|
}
|
|
|
|
func CheckHost(name string, times int) (bool, []time.Duration, error) {
|
|
fmt.Printf("Checking %s\n", name)
|
|
adds, err := net.LookupHost(name)
|
|
if err != nil {
|
|
return false, nil, err
|
|
}
|
|
fmt.Println("List of addresses:")
|
|
for _, add := range adds {
|
|
fmt.Println("\t", add)
|
|
}
|
|
|
|
p := fastping.NewPinger()
|
|
ra, err := net.ResolveIPAddr("ip4:icmp", name)
|
|
if err != nil {
|
|
return false, nil, err
|
|
}
|
|
rtttimes := make([]time.Duration, 0)
|
|
recv := make(chan time.Duration)
|
|
p.AddIPAddr(ra)
|
|
p.OnRecv = func(addr *net.IPAddr, rtt time.Duration) {
|
|
fmt.Printf("IP Addr: %s receive, RTT: %v\n", addr.String(), rtt)
|
|
recv <- rtt
|
|
}
|
|
var wg sync.WaitGroup
|
|
wg.Add(1)
|
|
go func() {
|
|
// Do work
|
|
for t := range recv {
|
|
rtttimes = append(rtttimes, t)
|
|
fmt.Printf("Ping %s: %s\n", name, t)
|
|
}
|
|
wg.Done()
|
|
}()
|
|
|
|
for i := 0; i < times; i++ {
|
|
err = p.Run()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
}
|
|
close(recv)
|
|
wg.Wait()
|
|
fmt.Println("finished")
|
|
return len(rtttimes) > 0, rtttimes, nil
|
|
}
|
|
|
|
func main() {
|
|
name := flag.String("host", "www.google.es", "Hostname to ping")
|
|
count := flag.Int("c", 3, "Number of ping attempts")
|
|
serve := flag.Bool("server", false, "Start the http server")
|
|
address := flag.String("address", ":8080", "Host and port to start the http server on")
|
|
flag.Parse()
|
|
|
|
if !*serve {
|
|
_, _, err := CheckHost(*name, *count)
|
|
if err == nil {
|
|
fmt.Printf("could not find host %s: %s\n", *name, err)
|
|
os.Exit(1)
|
|
}
|
|
os.Exit(0)
|
|
}
|
|
http.HandleFunc("/", homeHandler)
|
|
http.HandleFunc("/ping/", pingHandler)
|
|
log.Fatal(http.ListenAndServe(*address, nil))
|
|
}
|