2020-12-29 17:52:15 +00:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"flag"
|
2020-12-31 11:20:58 +00:00
|
|
|
|
"fmt"
|
2023-04-28 14:47:15 +00:00
|
|
|
|
"io"
|
2020-12-29 17:52:15 +00:00
|
|
|
|
"log"
|
|
|
|
|
"net/http"
|
2021-02-05 23:15:25 +00:00
|
|
|
|
"net/http/cookiejar"
|
2021-02-06 21:32:24 +00:00
|
|
|
|
"os"
|
2024-09-25 15:53:38 +00:00
|
|
|
|
"sync"
|
2020-12-29 17:52:15 +00:00
|
|
|
|
"time"
|
2021-02-10 18:31:31 +00:00
|
|
|
|
|
|
|
|
|
_ "git.nils.zone/nils/prettify"
|
2020-12-29 17:52:15 +00:00
|
|
|
|
)
|
|
|
|
|
|
2021-02-10 18:31:31 +00:00
|
|
|
|
const (
|
2024-09-25 15:53:38 +00:00
|
|
|
|
iso8601 = "2006-01-02T15:04:05-0700"
|
|
|
|
|
fetchInterval = 1 * time.Minute
|
2021-02-10 18:31:31 +00:00
|
|
|
|
)
|
2020-12-29 17:52:15 +00:00
|
|
|
|
|
|
|
|
|
// flags
|
2024-09-25 15:53:38 +00:00
|
|
|
|
var (
|
|
|
|
|
lastFetchTime time.Time
|
|
|
|
|
cacheMutex sync.Mutex
|
|
|
|
|
cacheNodes []node
|
|
|
|
|
cacheLinks []link
|
|
|
|
|
)
|
2021-02-06 21:32:24 +00:00
|
|
|
|
var configPath = flag.String("configPath", "config.json", "Path to config.json")
|
2021-01-02 11:32:38 +00:00
|
|
|
|
var version = "development"
|
2021-05-06 12:49:44 +00:00
|
|
|
|
var delay time.Duration = 60 * time.Second
|
2021-02-10 18:31:31 +00:00
|
|
|
|
var conf = loadconfig(*configPath)
|
2020-12-29 17:52:15 +00:00
|
|
|
|
|
|
|
|
|
func main() {
|
2021-01-02 21:16:07 +00:00
|
|
|
|
log.Printf("starting version %s...\n", version)
|
2020-12-29 17:52:15 +00:00
|
|
|
|
// parse all flags
|
|
|
|
|
flag.Parse()
|
2021-02-06 10:46:08 +00:00
|
|
|
|
|
|
|
|
|
// check if flags are set
|
2023-03-20 14:38:48 +00:00
|
|
|
|
if *configPath == "" {
|
|
|
|
|
log.Fatalln("Please specify path to config.json flag '-configPath'")
|
|
|
|
|
}
|
2023-04-28 14:47:15 +00:00
|
|
|
|
|
2021-01-02 21:16:07 +00:00
|
|
|
|
// start API processing (runs in a loop)
|
2023-04-28 14:47:15 +00:00
|
|
|
|
go func() {
|
|
|
|
|
if err := processAPIs(); err != nil {
|
2023-05-14 09:44:20 +00:00
|
|
|
|
log.Fatalln("API processing failed, error is: ", err)
|
2023-04-28 14:47:15 +00:00
|
|
|
|
}
|
|
|
|
|
tick := time.Tick(delay)
|
|
|
|
|
for range tick {
|
|
|
|
|
if err := processAPIs(); err != nil {
|
2023-05-14 09:44:20 +00:00
|
|
|
|
log.Fatalln("API processing failed, error is: ", err)
|
2023-04-28 14:47:15 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
2021-02-06 10:46:08 +00:00
|
|
|
|
// start webserver on Port 3000
|
2021-01-02 21:16:07 +00:00
|
|
|
|
serveJSON()
|
|
|
|
|
}
|
2020-12-29 17:52:15 +00:00
|
|
|
|
|
2023-04-28 14:47:15 +00:00
|
|
|
|
func processAPIs() error {
|
|
|
|
|
var nodes []node
|
|
|
|
|
var links []link
|
2020-12-31 11:20:58 +00:00
|
|
|
|
|
2024-03-19 17:43:09 +00:00
|
|
|
|
if conf.UISP.Enabled {
|
|
|
|
|
log.Println("Processing UISP")
|
|
|
|
|
//Process UISP RiFu Nodes
|
|
|
|
|
uispNodes, uispLinks, err := processUISPRiFu()
|
2023-05-14 09:44:20 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
2024-03-19 17:43:09 +00:00
|
|
|
|
//Process UISP Routers (like EDGE Router)
|
|
|
|
|
uispRouters, err := processUISPRouter()
|
2021-04-05 10:52:35 +00:00
|
|
|
|
if err != nil {
|
2023-04-28 14:47:15 +00:00
|
|
|
|
return err
|
2021-04-05 10:52:35 +00:00
|
|
|
|
}
|
2024-03-19 17:43:09 +00:00
|
|
|
|
nodes = append(nodes, uispNodes...)
|
|
|
|
|
nodes = append(nodes, uispRouters...)
|
|
|
|
|
links = append(links, uispLinks...)
|
2023-04-28 14:47:15 +00:00
|
|
|
|
}
|
2024-09-25 15:53:38 +00:00
|
|
|
|
if len(conf.Unifi) > 0 {
|
|
|
|
|
log.Println("Anazahl der Unifi Server:", len(conf.Unifi))
|
|
|
|
|
for i := range conf.Unifi {
|
|
|
|
|
if conf.Unifi[i].Enabled {
|
|
|
|
|
log.Println("Processing Unifi-Server: ", conf.Unifi[i].Name)
|
|
|
|
|
//Process Unifi Nodes
|
|
|
|
|
unifiNodes, _, err := processUnifiAPI(i)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
nodes = append(nodes, unifiNodes...)
|
|
|
|
|
}
|
2023-05-14 09:44:20 +00:00
|
|
|
|
}
|
2023-04-28 14:47:15 +00:00
|
|
|
|
}
|
|
|
|
|
if conf.Meshviewer.Enabled {
|
|
|
|
|
log.Println("Processing Meshviewer")
|
|
|
|
|
mvNodes, mvLinks := getMeshviewer()
|
|
|
|
|
nodes = append(nodes, mvNodes...)
|
|
|
|
|
links = append(links, mvLinks...)
|
|
|
|
|
}
|
2023-05-11 19:38:10 +00:00
|
|
|
|
if conf.Gateways.Enabled {
|
|
|
|
|
log.Println("Processing Gateways")
|
2024-03-19 17:43:09 +00:00
|
|
|
|
//Process Static Gateways from Json
|
2023-05-11 19:38:10 +00:00
|
|
|
|
gwNodes := processGateways()
|
|
|
|
|
nodes = append(nodes, gwNodes...)
|
|
|
|
|
}
|
2023-04-28 14:47:15 +00:00
|
|
|
|
// assemble final struct
|
|
|
|
|
o := output{
|
|
|
|
|
Timestamp: time.Now().Format(iso8601),
|
|
|
|
|
Nodes: nodes,
|
|
|
|
|
Links: links,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// create file output
|
|
|
|
|
log.Println("writing json file")
|
|
|
|
|
|
|
|
|
|
if err := o.writeToFile(); err != nil {
|
|
|
|
|
log.Fatalln(err)
|
|
|
|
|
}
|
2024-03-19 17:43:09 +00:00
|
|
|
|
|
2023-04-28 14:47:15 +00:00
|
|
|
|
// we're done here
|
|
|
|
|
log.Println("...done")
|
|
|
|
|
return nil
|
2020-12-29 17:52:15 +00:00
|
|
|
|
}
|
2021-05-18 19:17:09 +00:00
|
|
|
|
|
2023-05-14 09:44:20 +00:00
|
|
|
|
func loadconfig(file string) config {
|
|
|
|
|
var config config
|
|
|
|
|
configFile, err := os.Open(file)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalln("Failed loding Config file: ", err)
|
|
|
|
|
}
|
|
|
|
|
jsonParse := json.NewDecoder(configFile)
|
|
|
|
|
if err := jsonParse.Decode(&config); err != nil {
|
|
|
|
|
log.Fatalln(err)
|
|
|
|
|
}
|
|
|
|
|
return config
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// int to bool converter
|
|
|
|
|
func itob(i int) bool {
|
|
|
|
|
return i == 1
|
|
|
|
|
}
|
|
|
|
|
|
2023-04-28 13:20:42 +00:00
|
|
|
|
// function to get file from meshviewer
|
2021-02-05 23:57:51 +00:00
|
|
|
|
func getFile(url string) []byte {
|
|
|
|
|
resp, err := http.Get(url)
|
2020-12-29 17:52:15 +00:00
|
|
|
|
if err != nil {
|
2021-04-05 10:52:35 +00:00
|
|
|
|
log.Println("Error getting file from:", url)
|
2020-12-29 17:52:15 +00:00
|
|
|
|
}
|
2021-02-05 23:57:51 +00:00
|
|
|
|
data := resp.Body
|
2023-04-28 14:47:15 +00:00
|
|
|
|
byteValue, _ := io.ReadAll(data)
|
2021-02-05 23:57:51 +00:00
|
|
|
|
return byteValue
|
|
|
|
|
}
|
2021-02-06 10:46:08 +00:00
|
|
|
|
|
2023-03-20 14:38:48 +00:00
|
|
|
|
// get devices from devices file on webserver (config)
|
2021-02-13 15:10:41 +00:00
|
|
|
|
func getDevices(url string) devices {
|
2021-02-05 23:57:51 +00:00
|
|
|
|
// get devices from JSON file
|
2021-02-06 21:44:05 +00:00
|
|
|
|
jsonFile := getFile(url)
|
2020-12-29 17:52:15 +00:00
|
|
|
|
// read file to bytes
|
|
|
|
|
// variable for d
|
|
|
|
|
var d devices
|
|
|
|
|
// unmarshal to struct
|
2021-02-06 21:32:24 +00:00
|
|
|
|
err := json.Unmarshal(jsonFile, &d)
|
|
|
|
|
if err != nil {
|
2021-02-06 21:44:05 +00:00
|
|
|
|
fmt.Println("can´t get devices file from " + url)
|
2021-02-06 21:32:24 +00:00
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
2021-02-13 15:10:41 +00:00
|
|
|
|
return d
|
2020-12-29 17:52:15 +00:00
|
|
|
|
}
|
|
|
|
|
|
2023-03-20 14:38:48 +00:00
|
|
|
|
// check for MAC Adress in current Devices
|
2020-12-29 17:52:15 +00:00
|
|
|
|
func isRemoteMACpublished(mac string, devices []device) bool {
|
|
|
|
|
for i := range devices {
|
|
|
|
|
if devices[i].MAC == mac {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2021-01-02 21:16:07 +00:00
|
|
|
|
func serveJSON() {
|
|
|
|
|
fs := http.FileServer(http.Dir("./output"))
|
|
|
|
|
http.Handle("/", fs)
|
|
|
|
|
|
|
|
|
|
log.Println("Listening on :3000...")
|
|
|
|
|
err := http.ListenAndServe(":3000", nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatalln(err)
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-02-05 23:15:25 +00:00
|
|
|
|
|
|
|
|
|
func httpClient() *http.Client {
|
|
|
|
|
jar, err := cookiejar.New(nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
log.Fatal(err)
|
|
|
|
|
}
|
|
|
|
|
client := &http.Client{Jar: jar}
|
|
|
|
|
return client
|
|
|
|
|
}
|