package main import "log" import "os" import "time" import "reflect" // import "os/signal" // import "syscall" // import "runtime" // import "fmt" // this is the king of dns libraries import "github.com/miekg/dns" import "git.wit.com/wit/gui" import pb "git.wit.com/wit/witProtobuf" import "git.wit.com/jcarr/dnssecsocket" import "git.wit.com/wit/shell" import "github.com/gobuffalo/packr" import "github.com/davecgh/go-spew/spew" // var GITCOMMIT string // this is passed in as an ldflag var State string // used as a State machine var sigChan chan os.Signal var errChan chan interface{} type myButtonInfo struct { Account *pb.Account // associated with what account? Accounts []*pb.Account // associated with what account? VM *pb.Event_VM // associated with which VM? Custom func (*gui.GuiButton) ADD func (*gui.GuiButton) Name string Action string } // use mergo to merge structs // import "github.com/imdario/mergo" // mergo.Merge(&dest, src) // always sorted slice (new project) // https://github.com/yaa110/sslice // several smart slice functions (new project. April 2019) // https://github.com/elliotchance/pie // look into this for dns if possible // https://en.wikipedia.org/wiki/DNSCrypt // https://en.wikipedia.org/wiki/DNS_over_HTTPS // DNS over TLS plugin for coredns // uses protobuf's and gRPC in pb/dns.proto // https://github.com/coredns/coredns/tree/master/plugin/tls // https://github.com/coredns/coredns/blob/master/pb/dns.proto // cross platform openvpn that may work for IPv6 // https://github.com/mysteriumnetwork/go-openvpnwe // i18n with 'po' file support // https://github.com/leonelquinteros/gotext // a good example of using interface{} // https://github.com/Jeffail/tunny func onExit(err error) { log.Println("Sleep for 1 second") time.Sleep(1 * 1000 * 1000 * 1000) // save the protobuf.Config as a JSON config file saveConfig() if (err != nil) { panic(err) } os.Exit(0) } var packrBox packr.Box func lookupAAAA(hostname string) string { // lookup the IP address from DNS dnsRR := dnssecsocket.Dnstrace(hostname, "AAAA") spew.Dump(dnsRR) if (dnsRR == nil) { return "BROKEN" } ipaddr := dns.Field(dnsRR, 1) log.Println("ipaddr", ipaddr) return ipaddr } func main() { go handleErrors() // This puts all the files in that directory in the binary // This directory includes the default config file if there is not already one packrBox = packr.NewBox("./resources") // This will parse the command line and config file // This uses a protobuf definition and then Marshal's // and unmarshal's that into a JSON config file // that is human readable and editable. This is the easy way // to pass around a configuration structure throughout a // golang application IMHO parseConfig() // this checks to see if there is a newer upstream version upgrade() for key, foo := range config.Accounts { log.Println("FOUND ACCOUNT = ", key, foo) } initChannel() go processEvents() v185AAAA := lookupAAAA("v000185.testing.com.customers.wprod.wit.com") log.Println("v185AAA = ", v185AAAA) go gorillaDial("ccp.wit.com:9000") // go gorillaDial("stackapi-ccp.stackapi.customers.wit.com:9000") go gui.WatchGUI() // use this to discover what the OS thinks it's hostname is // seems to be cross platform (?) // Windows: WMIC computersystem where caption='current_pc_name' rename new_pc_name hostname := fqdnGet() log.Println("fqdnGet() = ", hostname) config.Hostname = hostname // this is a recursive dig for the AAAA record // TODO: check for dns hijacking ipAAAA := lookupAAAA(hostname) config.IPv6 = ipAAAA gui.Data.MouseClick = mainMouseClick gui.Config.Width = int(config.Width) gui.Config.Height = int(config.Height) // Set output debugging level gui.Config.Debug = config.Debug gui.Config.DebugTable = config.Debugtable log.Println("gui.Config.Debug = ", gui.Config.Debug) log.Println("gui.Config.DebugTable = ", gui.Config.DebugTable) // Get "Real" User under sudo. // More Info: https://stackoverflow.com/q/29733575/402585 log.Println("Real User: " + os.Getenv("SUDO_USER")) // make this the main loop in an attempt to figure out the crashes // do not change this until the GUI is stable gui.StartNewWindow(false, "Cloud Control Panel", gui.Yaxis, showSplashBox) if (os.Getenv("DISPLAY") == "") { log.Println("gui.StartNewWindow() END DISPLAY =", os.Getenv("DISPLAY")) log.Println("gui.StartNewWindow() Probably this died because your DISPLAY is not set") } log.Println("gui.StartNewWindow() END") } // // This is GO language concept for 'recover' to keep an app from completely crashing // // Doing this can sometimes avoid a panic() on things like: // panic: runtime error: slice bounds out of range // // In debugging mode, always panic() and never try to recover() // func r() { if (gui.Config.Debug == false) { if r := recover(); r != nil { log.Println("recover() SOMETHING IS REALLY BROKEN r =", r) log.Println("recover() SOMETHING IS REALLY BROKEN r =", r) log.Println("recover() SOMETHING IS REALLY BROKEN r =", r) panic("something") } } } func init() { log.Println("init() WAS HERE") log.Println("init() WAS HERE") log.Println("init() WAS HERE") errChan = make(chan interface{}, 3) shell.InitCallback(handleShell) // asks for all the shell errors to be sent here /* sigChan = make(chan os.Signal, 3) if runtime.GOOS != "windows" { log.Println("loadConfigFile() OS: Windows") signal.Notify(sigChan, syscall.SIGUSR1) } */ } // get's sent the return values and errors from git.wit.com/wit/shell/ func handleShell(err interface{}, ret int) { log.Println("handleShell() shell.Run() END Returned ", ret) errChan <- err } func handleErrors() { for val := range errChan { log.Println("handleErrors() val =", val) log.Println("handleErrors() reflect.TypeOf(val) =", reflect.TypeOf(val)) log.Printf("handleErrors() val type T = %T\n", val) } } // trap signals /* go func() { s := make(chan os.Signal, 1) signal.Notify(s, syscall.SIGQUIT) <-s panic("give me the stack") }() */