package main import ( "fmt" "net/http" "html/template" "os" "os/exec" "regexp" "strconv" "bytes" "encoding/json" ) var indexTemplate = template.Must(template.ParseFiles("html/index.html")) var nodeList = []string{"higgsboson.vpn","turingmachine.vpn"} func stringInSlice(a string, list []string) bool { for _, b := range list { if b == a { return true } } return false } type IndexPage struct { Title string Nodes []string } type Status int const ( On Status = iota Off Slow ) func indexHandler(w http.ResponseWriter, r *http.Request) { indexTemplate.Execute(w, &IndexPage{Title: "VPN Node Status", Nodes: nodeList}) } func ping(node string) (int64) { cmd := exec.Command("fping", "-e", node) var out bytes.Buffer cmd.Stdout = &out err := cmd.Run() if err == nil { match := regexp.MustCompile("\\d+").Find(out.Bytes()) if (match != nil) { time, _ := strconv.ParseInt(string(match), 10, 0); return time; } return -1 } else { return -1 } } type NodeStatus struct { Domain string Status string Ping int64 } const lenPath = len("/status/") func statusHandler(w http.ResponseWriter, r *http.Request) { node := r.URL.Path[lenPath:]; if ! stringInSlice(node, nodeList) { w.WriteHeader(http.StatusNotFound) } else { var state string elapsed := ping(node); if elapsed == -1 { state = "DOWN" } else if elapsed > 200 { state = "SLOW" } else { state = "UP" } status := &NodeStatus{Domain: node, Status: state, Ping: elapsed} s, err := json.Marshal(status) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Printf("error while serializing json %s", err) } else { w.Write(s) } } } func main() { config, err := os.Open("./nodes.json") if err != nil { fmt.Printf("Cannot open nodes.json: '%s'", err) os.Exit(1); } jsonParser := json.NewDecoder(config) if err = jsonParser.Decode(&nodeList); err != nil { fmt.Printf("parsing config file: '%s'", err.Error()) os.Exit(1); } http.HandleFunc("/status/", statusHandler) http.Handle("/assets/", http.StripPrefix("/assets", http.FileServer(http.Dir("./assets/")))) http.HandleFunc("/", indexHandler) fmt.Printf("Running on http://0.0.0.0:8080\n") http.ListenAndServe(":8080", nil) }