summaryrefslogtreecommitdiff
path: root/digStatusWindow.go
diff options
context:
space:
mode:
Diffstat (limited to 'digStatusWindow.go')
-rw-r--r--digStatusWindow.go357
1 files changed, 357 insertions, 0 deletions
diff --git a/digStatusWindow.go b/digStatusWindow.go
new file mode 100644
index 0000000..5722f47
--- /dev/null
+++ b/digStatusWindow.go
@@ -0,0 +1,357 @@
+/*
+ 'dig'
+
+ This is essentially doing what the command 'dig' does
+ It performing DNS queries on TCP and UDP
+ against localhost, cloudflare & google
+
+ IPv4() and IPv6() return true if they are working
+
+ with the 'gui' package, it can also display the results
+*/
+
+package main
+
+import (
+ "errors"
+ "fmt"
+ "os"
+ "reflect"
+ "time"
+
+ "go.wit.com/gui"
+ "go.wit.com/lib/gadgets"
+ "go.wit.com/lib/gui/shell"
+ "go.wit.com/log"
+)
+
+type digStatus struct {
+ ready bool
+ hidden bool
+ statusIPv4 string
+ statusIPv6 string
+
+ parent *gui.Node
+ window *gadgets.BasicWindow
+ group *gui.Node
+ grid *gui.Node
+
+ summary *gui.Node
+ status *gadgets.OneLiner
+ statusAAAA *gadgets.OneLiner
+ speed *gadgets.OneLiner
+ speedActual *gadgets.OneLiner
+
+ detailsGroup *gui.Node
+ details *gui.Node
+ dsLocalhost *resolverStatus
+ dsLocalNetwork *resolverStatus
+ dsCloudflare *resolverStatus
+ dsGoogle *resolverStatus
+ DnsDigUDP *gui.Node
+ DnsDigTCP *gui.Node
+
+ httpGoWitCom *gadgets.OneLiner
+ statusHTTP *gadgets.OneLiner
+}
+
+func NewDigStatusWindow(p *gui.Node) *digStatus {
+ var ds *digStatus
+ ds = new(digStatus)
+
+ ds.ready = false
+ ds.hidden = true
+
+ ds.window = gadgets.NewBasicWindow(p, "DNS Resolver Status")
+ ds.window.Make()
+ // ds.window.Draw()
+ // ds.window.Hide()
+
+ // summary of the current state of things
+ ds.summary = ds.window.Box().NewGroup("Summary")
+ g := ds.summary.NewGrid("LookupStatus", 2, 2)
+ g.Pad()
+
+ ds.status = gadgets.NewOneLiner(g, "status").SetText("unknown")
+ ds.statusAAAA = gadgets.NewOneLiner(g, "IPv6 status").SetText("unknown")
+ ds.statusHTTP = gadgets.NewOneLiner(g, "IPv6 via HTTP").SetText("unknown")
+ ds.speed = gadgets.NewOneLiner(g, "speed").SetText("unknown")
+ ds.speedActual = gadgets.NewOneLiner(g, "actual").SetText("unknown")
+
+ // make the area to store the raw details
+ ds.detailsGroup = ds.window.Box().NewGroup("Details")
+ ds.details = ds.detailsGroup.NewBox("bw vbox", false)
+ ds.dsLocalhost = NewResolverStatus(ds.details, "(localhost)", "127.0.0.1:53", "go.wit.com")
+ ds.dsLocalNetwork = NewResolverStatus(ds.details, "(Local Network)", "192.168.86.1:53", "go.wit.com")
+ ds.dsCloudflare = NewResolverStatus(ds.details, "(cloudflare)", "1.1.1.1:53", "go.wit.com")
+ ds.dsGoogle = NewResolverStatus(ds.details, "(google)", "8.8.8.8:53", "go.wit.com")
+ ds.makeDnsStatusGrid()
+ ds.makeHttpStatusGrid()
+
+ ds.hidden = false
+ ds.ready = true
+ return ds
+}
+
+func (ds *digStatus) Update() {
+ log.Info("digStatus() Update() START")
+ if ds == nil {
+ log.Error(errors.New("digStatus() Update() ds == nil"))
+ return
+ }
+ duration := timeFunction(func() {
+ ds.updateDnsStatus()
+ })
+ s := fmt.Sprint(duration)
+ // ds.speedActual.SetText(s)
+ me.digStatus.set(ds.speedActual, s)
+
+ if duration > 500*time.Millisecond {
+ me.digStatus.set(ds.speed, "SLOW")
+ } else if duration > 100*time.Millisecond {
+ me.digStatus.set(ds.speed, "OK")
+ } else {
+ me.digStatus.set(ds.speed, "FAST")
+ }
+ log.Info("digStatus() Update() END")
+}
+
+// Returns true if the status is valid
+func (ds *digStatus) Ready() bool {
+ if ds == nil {
+ return false
+ }
+ return ds.ready
+}
+
+// Returns true if IPv4 is working
+func (ds *digStatus) IPv4() bool {
+ if !ds.Ready() {
+ return false
+ }
+ if ds.statusIPv4 == "OK" {
+ return true
+ }
+ if ds.statusIPv4 == "GOOD" {
+ return true
+ }
+ return false
+}
+
+// Returns true if IPv6 is working
+func (ds *digStatus) IPv6() bool {
+ if !ds.Ready() {
+ return false
+ }
+ if ds.statusIPv6 == "GOOD" {
+ return true
+ }
+ return false
+}
+
+func (ds *digStatus) setIPv4status(s string) {
+ ds.statusIPv4 = s
+ if !ds.Ready() {
+ return
+ }
+ me.digStatus.set(ds.status, s)
+}
+
+func (ds *digStatus) setIPv6status(s string) {
+ ds.statusIPv6 = s
+ if !ds.Ready() {
+ return
+ }
+ me.digStatus.set(ds.statusAAAA, s)
+}
+
+/*
+func (ds *digStatus) SetIPv6(s string) {
+ if ! ds.Ready() {return}
+ log.Warn("Should SetIPv6() here to", s)
+ log.Warn("Should SetIPv6() here to", s)
+ log.Warn("Should SetIPv6() here to", s)
+ log.Warn("Should SetIPv6() here to", s)
+ me.DnsAAAA.SetText(s)
+ // me.digStatus.set(ds.httpGoWitCom, addr)
+}
+*/
+
+func (ds *digStatus) set(a any, s string) {
+ if !ds.Ready() {
+ return
+ }
+ if ds.hidden {
+ return
+ }
+ if a == nil {
+ return
+ }
+ var n *gui.Node
+ if reflect.TypeOf(a) == reflect.TypeOf(n) {
+ n = a.(*gui.Node)
+ n.SetText(s)
+ return
+ }
+ var ol *gadgets.OneLiner
+ if reflect.TypeOf(a) == reflect.TypeOf(ol) {
+ ol = a.(*gadgets.OneLiner)
+ ol.SetText(s)
+ return
+ }
+ log.Warn("unknown type TypeOf(a) =", reflect.TypeOf(a), "a =", a)
+ os.Exit(0)
+}
+
+func (ds *digStatus) updateDnsStatus() {
+ var cmd, out string
+ var ipv4, ipv6 bool
+
+ log.Info("updateDnsStatus() START")
+ if ds == nil {
+ log.Error(errors.New("updateDnsStatus() not initialized yet. ds == nil"))
+ return
+ }
+
+ if !ds.ready {
+ log.Error(errors.New("updateDnsStatus() not ready yet"))
+ return
+ }
+
+ ipv4, ipv6 = ds.dsLocalhost.update()
+ ipv4, ipv6 = ds.dsLocalNetwork.update()
+ ipv4, ipv6 = ds.dsCloudflare.update()
+ ipv4, ipv6 = ds.dsGoogle.update()
+
+ if me.statusOS.ValidHostname() {
+ if ds.checkLookupDoH(me.statusOS.GetHostname()) {
+ log.Log(DNS, "updateDnsStatus() HTTP DNS lookups working")
+ me.digStatus.set(ds.statusHTTP, "WORKING")
+ } else {
+ log.Log(DNS, "updateDnsStatus() HTTP DNS lookups not working")
+ log.Log(DNS, "updateDnsStatus() It's really unlikely you are on the internet")
+ me.digStatus.set(ds.statusHTTP, "BROKEN")
+ }
+ } else {
+ me.digStatus.set(ds.statusHTTP, "INVALID HOSTNAME")
+ }
+
+ if ipv4 {
+ log.Log(DNS, "updateDnsStatus() IPv4 A lookups working")
+ ds.setIPv4status("OK")
+ } else {
+ log.Log(DNS, "updateDnsStatus() IPv4 A lookups not working. No internet?")
+ ds.setIPv4status("No Internet?")
+ }
+ if ipv6 {
+ log.Log(DNS, "updateDnsStatus() IPv6 AAAA lookups working")
+ ds.setIPv4status("GOOD")
+ ds.setIPv6status("GOOD")
+ } else {
+ log.Log(DNS, "updateDnsStatus() IPv6 AAAA lookups are not working")
+ ds.setIPv6status("Need VPN")
+ }
+
+ cmd = "dig +noall +answer www.wit.com A"
+ out = shell.Run(cmd)
+ log.Log(DNS, "makeDnsStatusGrid() dig", out)
+ me.digStatus.set(ds.DnsDigUDP, out)
+
+ cmd = "dig +noall +answer www.wit.com AAAA"
+ out = shell.Run(cmd)
+ log.Log(DNS, "makeDnsStatusGrid() dig", out)
+ me.digStatus.set(ds.DnsDigTCP, out)
+
+ /*
+ g2.NewButton("dig +trace", func () {
+ log.Log(NOW, "TODO: redo this")
+ // o := shell.Run("dig +trace +noadditional DS " + me.hostname + " @8.8.8.8")
+ // log.Println(o)
+ })
+ */
+}
+
+func (ds *digStatus) makeHttpStatusGrid() {
+ group := ds.details.NewGroup("dns.google.com via HTTPS")
+ grid := group.NewGrid("LookupStatus", 2, 2)
+
+ ds.httpGoWitCom = gadgets.NewOneLiner(grid, "go.wit.com")
+ me.digStatus.set(ds.httpGoWitCom, "unknown")
+
+ group.Pad()
+ grid.Pad()
+}
+
+func (ds *digStatus) makeDnsStatusGrid() {
+ var cmd, out string
+ group := ds.details.NewGroup("dig results")
+ grid := group.NewGrid("LookupStatus", 2, 2)
+
+ cmd = "dig +noall +answer go.wit.com A"
+ grid.NewLabel(cmd)
+ ds.DnsDigUDP = grid.NewLabel("?")
+ out = shell.Run(cmd)
+ log.Log(DNS, "makeDnsStatusGrid() dig", out)
+ me.digStatus.set(ds.DnsDigUDP, out)
+
+ cmd = "dig +noall +answer go.wit.com AAAA"
+ grid.NewLabel(cmd)
+ ds.DnsDigTCP = grid.NewLabel("?")
+ out = shell.Run(cmd)
+ log.Log(DNS, "makeDnsStatusGrid() dig", out)
+ me.digStatus.set(ds.DnsDigTCP, out)
+
+ group.Pad()
+ grid.Pad()
+}
+
+func (ds *digStatus) checkLookupDoH(hostname string) bool {
+ var status bool = false
+
+ ipv6Addresses := lookupDoH(hostname, "AAAA")
+
+ log.Log(DNS, "IPv6 Addresses for ", hostname)
+ var s []string
+ for _, addr := range ipv6Addresses {
+ log.Log(DNS, addr)
+ s = append(s, addr)
+ status = true
+ }
+ // me.digStatus.SetIPv6(strings.Join(s, "\n"))
+ return status
+}
+
+func (ds *digStatus) Show() {
+ log.Info("digStatus.Show() window")
+ if me.digStatus.hidden {
+ me.digStatus.window.Show()
+ }
+ me.digStatus.hidden = false
+}
+
+func (ds *digStatus) Hide() {
+ log.Info("digStatus.Hide() window")
+ if !me.digStatus.hidden {
+ me.digStatus.window.Hide()
+ }
+ me.digStatus.hidden = true
+}
+
+func digLoop() {
+ me.digStatus.Update()
+
+ if me.digStatus.Ready() {
+ current := me.statusIPv6.String()
+ if me.digStatus.IPv6() {
+ if current != "WORKING" {
+ log.Log(CHANGE, "IPv6 resolution is WORKING")
+ me.statusIPv6.SetText("WORKING")
+ }
+ } else {
+ if current != "Need VPN" {
+ log.Log(CHANGE, "IPv6 resolution seems to have broken")
+ me.statusIPv6.SetText("Need VPN")
+ }
+ }
+ }
+}