diff options
Diffstat (limited to 'digStatus.go')
| -rw-r--r-- | digStatus.go | 314 |
1 files changed, 314 insertions, 0 deletions
diff --git a/digStatus.go b/digStatus.go new file mode 100644 index 0000000..ffa9f2d --- /dev/null +++ b/digStatus.go @@ -0,0 +1,314 @@ +/* + '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 ( + "os" + "fmt" + "time" + "strings" + "reflect" + "errors" + + "go.wit.com/log" + "go.wit.com/gui/gui" + "go.wit.com/gui/gadgets" + "go.wit.com/shell" +) + +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 + + 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.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").Set("unknown") + ds.statusAAAA = gadgets.NewOneLiner(g, "IPv6 status").Set("unknown") + ds.statusHTTP = gadgets.NewOneLiner(g, "IPv6 via HTTP").Set("unknown") + ds.speed = gadgets.NewOneLiner(g, "speed").Set("unknown") + ds.speedActual = gadgets.NewOneLiner(g, "actual").Set("unknown") + + // make the area to store the raw details + ds.details = ds.window.Box().NewGroup("Details") + 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.Set(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.Set(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.Set(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.status.ValidHostname() { + if ds.checkLookupDoH(me.status.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) +} + +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 +} |
