2019-02-01 07:28:17 -06:00
|
|
|
package main
|
|
|
|
|
|
|
|
import "log"
|
2019-05-24 02:04:37 -05:00
|
|
|
import "fmt"
|
2019-05-06 20:57:59 -05:00
|
|
|
import "os"
|
2019-05-06 19:42:59 -05:00
|
|
|
import "time"
|
2019-05-23 13:33:30 -05:00
|
|
|
import "os/user"
|
2019-05-23 18:38:51 -05:00
|
|
|
import "runtime"
|
|
|
|
import "runtime/debug"
|
2019-05-24 20:41:31 -05:00
|
|
|
|
2019-05-24 22:53:44 -05:00
|
|
|
// this is the king of dns libraries
|
|
|
|
import "github.com/miekg/dns"
|
|
|
|
|
2019-05-24 20:41:31 -05:00
|
|
|
import "git.wit.com/wit/gui"
|
|
|
|
import pb "git.wit.com/wit/witProtobuf"
|
2019-05-24 22:53:44 -05:00
|
|
|
import "git.wit.com/jcarr/dnssecsocket"
|
2019-02-01 07:28:17 -06:00
|
|
|
|
2019-05-23 11:47:48 -05:00
|
|
|
import "github.com/gobuffalo/packr"
|
2019-05-24 17:35:57 -05:00
|
|
|
import "github.com/davecgh/go-spew/spew"
|
2019-02-01 07:28:17 -06:00
|
|
|
|
2019-05-24 03:17:37 -05:00
|
|
|
// will try to get this hosts FQDN
|
|
|
|
import "github.com/Showmax/go-fqdn"
|
|
|
|
|
2019-05-23 02:11:49 -05:00
|
|
|
var GITCOMMIT string // this is passed in as an ldflag
|
|
|
|
var GOVERSION string // this is passed in as an ldflag
|
2019-05-24 02:21:15 -05:00
|
|
|
var BUILDTIME string // this is passed in as an ldflag
|
2019-06-01 03:19:51 -05:00
|
|
|
const VERSION = "0.2"
|
2019-05-23 02:11:49 -05:00
|
|
|
|
2019-02-01 07:28:17 -06:00
|
|
|
// use mergo to merge structs
|
|
|
|
// import "github.com/imdario/mergo"
|
|
|
|
// mergo.Merge(&dest, src)
|
|
|
|
|
|
|
|
// always sorted slice (new project)
|
|
|
|
// https://github.com/yaa110/sslice
|
|
|
|
|
2019-05-12 08:18:06 -05:00
|
|
|
// several smart slice functions (new project. April 2019)
|
|
|
|
// https://github.com/elliotchance/pie
|
|
|
|
|
2019-05-25 23:28:21 -05:00
|
|
|
// 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
|
2019-05-26 02:27:15 -05:00
|
|
|
// https://github.com/coredns/coredns/blob/master/pb/dns.proto
|
2019-05-25 23:28:21 -05:00
|
|
|
|
2019-05-26 03:05:28 -05:00
|
|
|
// cross platform openvpn that may work for IPv6
|
|
|
|
// https://github.com/mysteriumnetwork/go-openvpnwe
|
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
func onExit(err error) {
|
2019-05-12 01:21:57 -05:00
|
|
|
log.Println("Sleep for 1 second")
|
|
|
|
time.Sleep(1 * 1000 * 1000 * 1000)
|
|
|
|
|
2019-05-25 01:53:52 -05:00
|
|
|
// save the protobuf.Config as a JSON config file
|
|
|
|
saveConfig()
|
2019-05-12 01:21:57 -05:00
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
if (err != nil) {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2019-05-12 01:21:57 -05:00
|
|
|
os.Exit(0)
|
|
|
|
}
|
|
|
|
|
2019-05-24 13:32:26 -05:00
|
|
|
var packrBox packr.Box
|
|
|
|
|
2019-05-24 22:53:44 -05:00
|
|
|
func lookupAAAA(hostname string) string {
|
|
|
|
// lookup the IP address from DNS
|
|
|
|
dnsRR := dnssecsocket.Dnstrace(hostname, "AAAA")
|
|
|
|
spew.Dump(dnsRR)
|
2019-05-24 23:50:23 -05:00
|
|
|
if (dnsRR == nil) {
|
|
|
|
return "BROKEN"
|
|
|
|
}
|
2019-05-24 22:53:44 -05:00
|
|
|
ipaddr := dns.Field(dnsRR, 1)
|
|
|
|
log.Println("ipaddr", ipaddr)
|
|
|
|
return ipaddr
|
|
|
|
}
|
|
|
|
|
2019-05-10 03:21:32 -05:00
|
|
|
func main() {
|
2019-05-23 11:47:48 -05:00
|
|
|
// This puts all the files in that directory in the binary
|
|
|
|
// This directory includes the default config file if there is not already one
|
2019-05-24 13:32:26 -05:00
|
|
|
packrBox = packr.NewBox("./resources")
|
2019-05-24 19:39:05 -05:00
|
|
|
|
2019-05-24 20:41:31 -05:00
|
|
|
// This will parse the command line and config file
|
2019-05-25 01:53:52 -05:00
|
|
|
// 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()
|
|
|
|
|
|
|
|
for key, foo := range config.Accounts {
|
|
|
|
log.Println("FOUND ACCOUNT = ", key, foo)
|
2019-05-24 20:17:53 -05:00
|
|
|
}
|
2019-05-25 01:53:52 -05:00
|
|
|
// pass a pointer to the config so the gui can access it
|
|
|
|
gui.Data.Config = config
|
2019-05-24 20:17:53 -05:00
|
|
|
|
2019-05-11 09:53:32 -05:00
|
|
|
initChannel()
|
|
|
|
go processEvents()
|
|
|
|
|
2019-05-12 08:18:06 -05:00
|
|
|
go gorillaDial("v000185.testing.com.customers.wprod.wit.com:9000")
|
2019-05-23 00:33:16 -05:00
|
|
|
go watchGUI()
|
2019-05-07 16:54:08 -05:00
|
|
|
|
2019-05-23 13:33:30 -05:00
|
|
|
user, err := user.Current()
|
|
|
|
if err != nil {
|
|
|
|
onExit(err)
|
|
|
|
}
|
|
|
|
|
2019-05-30 02:50:57 -05:00
|
|
|
// gui.Data.Width = int(config.Width)
|
|
|
|
// gui.Data.Height = int(config.Height)
|
2019-05-24 00:47:26 -05:00
|
|
|
|
2019-05-24 23:50:23 -05:00
|
|
|
// use this to discover what the OS thinks it's hostname is
|
|
|
|
// seems to be cross platform (?)
|
2019-05-29 04:28:19 -05:00
|
|
|
// Windows: WMIC computersystem where caption='current_pc_name' rename new_pc_name
|
2019-05-24 03:17:37 -05:00
|
|
|
hostname := fqdn.Get()
|
|
|
|
log.Println("fqdn.Get() = ", hostname)
|
|
|
|
gui.Data.Hostname = hostname
|
2019-05-24 23:50:23 -05:00
|
|
|
|
|
|
|
// this is a recursive dig for the AAAA record
|
|
|
|
// TODO: check for dns hijacking
|
2019-05-24 22:53:44 -05:00
|
|
|
ipAAAA := lookupAAAA(hostname)
|
|
|
|
gui.Data.IPv6 = ipAAAA
|
2019-05-24 00:47:26 -05:00
|
|
|
|
2019-05-24 22:53:44 -05:00
|
|
|
gui.Data.MouseClick = mainMouseClick
|
2019-05-23 13:33:30 -05:00
|
|
|
gui.Data.HomeDir = user.HomeDir
|
2019-05-24 11:04:36 -05:00
|
|
|
|
|
|
|
// Set output debugging level
|
2019-05-28 19:24:45 -05:00
|
|
|
gui.Data.Debug = config.Debug
|
2019-05-25 01:53:52 -05:00
|
|
|
gui.Data.DebugTable = config.Debugtable
|
2019-05-23 15:14:57 -05:00
|
|
|
log.Println("gui.Data.Debug = ", gui.Data.Debug)
|
2019-05-24 11:04:36 -05:00
|
|
|
log.Println("gui.Data.DebugTable = ", gui.Data.DebugTable)
|
2019-05-23 13:33:30 -05:00
|
|
|
|
|
|
|
// Current User
|
|
|
|
log.Println("Hi " + user.Name + " (id: " + user.Uid + ")")
|
|
|
|
log.Println("Username: " + user.Username)
|
|
|
|
log.Println("Home Dir: " + user.HomeDir)
|
|
|
|
|
|
|
|
// Get "Real" User under sudo.
|
|
|
|
// More Info: https://stackoverflow.com/q/29733575/402585
|
|
|
|
log.Println("Real User: " + os.Getenv("SUDO_USER"))
|
2019-05-23 00:33:16 -05:00
|
|
|
|
2019-05-10 03:21:32 -05:00
|
|
|
// make this the main loop in an attempt to figure out the crashes
|
|
|
|
// do not change this until the GUI is stable
|
2019-06-01 03:19:51 -05:00
|
|
|
gui.StartNewWindow(config, false, "SPLASH", showSplashBox)
|
2019-05-23 00:33:16 -05:00
|
|
|
}
|
2019-05-10 03:21:32 -05:00
|
|
|
|
2019-05-24 22:53:44 -05:00
|
|
|
// This is the handler for all mosue clicks (buttons, areas, etc))
|
2019-05-26 00:07:58 -05:00
|
|
|
//
|
|
|
|
// This is massive for a reason. EVERY MOUSE CLICK COMES HERE
|
|
|
|
// the 'gui' code is kinda just a holder. It will pass everything
|
|
|
|
// here and we have to sort out what to do with the click
|
|
|
|
// at least, that is the current design because I thought it
|
|
|
|
// might be a good approach. Time will tell...
|
|
|
|
//
|
2019-05-30 10:55:46 -05:00
|
|
|
func mainMouseClick(b *gui.GuiButton) {
|
2019-05-26 04:58:29 -05:00
|
|
|
defer r() // a golang trick to try to not crash on certain errors
|
|
|
|
|
2019-05-23 15:45:11 -05:00
|
|
|
if (b == nil) {
|
2019-05-26 04:58:29 -05:00
|
|
|
log.Println("mainMouseClick() BACK IN MAIN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?")
|
|
|
|
log.Println("mainMouseClick() BACK IN MAIN CONTROL PANEL CODE (button is nil) WHY DID THIS HAPPEN?")
|
2019-05-26 00:07:58 -05:00
|
|
|
onExit(fmt.Errorf("mainMouseClick() got b = nil"))
|
2019-05-25 23:28:21 -05:00
|
|
|
}
|
2019-05-31 22:14:33 -05:00
|
|
|
spew.Dump(b.Account)
|
2019-05-26 04:19:23 -05:00
|
|
|
log.Println("mainMouseClick() b.Action =", b.Action)
|
2019-05-31 19:37:24 -05:00
|
|
|
log.Println("mainMouseClick() b.Account =", b.Account)
|
2019-05-31 22:14:33 -05:00
|
|
|
log.Println("mainMouseClick() b.Box =", b.Box)
|
2019-05-25 23:28:21 -05:00
|
|
|
|
2019-05-31 19:37:24 -05:00
|
|
|
var gw *gui.GuiWindow
|
2019-05-31 22:14:33 -05:00
|
|
|
if (b.GW != nil) {
|
|
|
|
gw = b.GW
|
|
|
|
} else {
|
|
|
|
if (b.Box != nil) {
|
2019-06-01 15:42:03 -05:00
|
|
|
gw = b.Box.Window
|
2019-05-31 22:14:33 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (gw == nil) {
|
|
|
|
log.Println("THIS BUTTON IS BROKEN gw = nil")
|
|
|
|
log.Println("THIS BUTTON IS BROKEN gw = nil")
|
|
|
|
log.Println("THIS BUTTON IS BROKEN gw = nil")
|
|
|
|
panic("something")
|
|
|
|
}
|
2019-05-29 22:04:45 -05:00
|
|
|
|
2019-05-26 16:48:46 -05:00
|
|
|
// gui.Data.Current = b.Account
|
2019-05-31 19:37:24 -05:00
|
|
|
log.Println("mainMouseClick() BACK IN CONTROL PANEL CODE b =", b)
|
2019-05-26 04:19:23 -05:00
|
|
|
if (b.Account != nil) {
|
|
|
|
log.Println("\tmainMouseClick() setting current account = ", b.Account.Nick)
|
|
|
|
}
|
2019-05-29 17:46:37 -05:00
|
|
|
if (b.Action == "NEWTEXT") {
|
2019-05-31 19:37:24 -05:00
|
|
|
if (b.Box == nil) {
|
|
|
|
log.Println("\tmainMouseClick() b.Box = nil")
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
2019-06-01 15:42:03 -05:00
|
|
|
if (gw.Area == nil) {
|
|
|
|
log.Println("\tmainMouseClick() gw.Area = nil")
|
2019-05-31 19:37:24 -05:00
|
|
|
os.Exit(-1)
|
|
|
|
}
|
2019-06-01 15:42:03 -05:00
|
|
|
gw.Area.UiAttrstr = getNEWTEXT()
|
|
|
|
log.Println("Area.UiAttrstr = ", gw.Area.UiAttrstr)
|
|
|
|
gw.Area.UiArea.QueueRedrawAll()
|
2019-05-29 17:46:37 -05:00
|
|
|
} else if (b.Action == "AREA") {
|
2019-05-27 12:55:28 -05:00
|
|
|
if (config == nil) {
|
|
|
|
log.Println("gui.State = splash BUT SOMETHING HAS GONE VERY WRONG")
|
|
|
|
log.Println("gui.State = splash BUT SOMETHING HAS GONE VERY WRONG")
|
|
|
|
log.Println("gui.State = splash config = nil")
|
|
|
|
os.Exit(-1)
|
|
|
|
}
|
|
|
|
for key, _ := range config.Accounts {
|
|
|
|
log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Account = ", config.Accounts[key])
|
|
|
|
// log.Println("gui.State = splash BUT THERE IS AN ACCOUNT Username = ", config.Accounts[key])
|
|
|
|
log.Println("SETTING gui.State = main")
|
|
|
|
gui.Data.State = "main";
|
|
|
|
if (config.Accounts[key] == nil) {
|
|
|
|
log.Println("THIS IS LAME. CONFIG FILE MADE NULL ACCOUNTS key =", key)
|
|
|
|
}
|
|
|
|
}
|
2019-05-27 20:03:21 -05:00
|
|
|
if (gui.Data.State == "splash") {
|
2019-06-01 13:45:35 -05:00
|
|
|
gw.MakeWindow = addSubdomainQuestionBox
|
2019-06-01 17:38:32 -05:00
|
|
|
gw = gui.ShowTab(gw, "Box2", "New Account?")
|
2019-05-27 20:03:21 -05:00
|
|
|
gui.Data.State = "account1"
|
|
|
|
return
|
|
|
|
}
|
2019-05-27 17:25:50 -05:00
|
|
|
if (gui.Data.State == "main") {
|
2019-05-29 22:04:45 -05:00
|
|
|
log.Println("gui.Data.State == main b =", b)
|
2019-05-31 19:37:24 -05:00
|
|
|
log.Println("gui.Data.State == main gw =", gw)
|
2019-06-01 13:45:35 -05:00
|
|
|
makeCloudInfoBox(gw)
|
|
|
|
// gw.MakeWindow = makeCloudInfoBox
|
|
|
|
// gui.ShowMainTab(gw)
|
2019-05-27 17:25:50 -05:00
|
|
|
gui.Data.State = "done"
|
|
|
|
return
|
|
|
|
} else if (gui.Data.State == "account1") {
|
2019-06-01 03:32:45 -05:00
|
|
|
// gui.ShowAccountTab(gw, 0)
|
2019-05-27 17:25:50 -05:00
|
|
|
gui.Data.State = "main"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
} else if (b.Action == "ADD TAB") {
|
|
|
|
log.Println("\tADD TAB TRY b.Action = ", b.Action)
|
|
|
|
log.Println("\tADD TAB TRY gui.ShowAccountTab(-1)")
|
2019-06-01 03:32:45 -05:00
|
|
|
// gui.ShowAccountTab(gw, -1)
|
2019-05-27 17:25:50 -05:00
|
|
|
gui.Data.State = "done"
|
|
|
|
return
|
2019-05-25 23:28:21 -05:00
|
|
|
} else if (b.Action == "QUIT") {
|
|
|
|
onExit(nil)
|
|
|
|
} else if (b.Action == "CREATE") {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tTRY TO ADD A NEW VIRTUAL MACHINE")
|
2019-05-25 23:28:21 -05:00
|
|
|
log.Println("\tTRIGGER CREATE VM")
|
|
|
|
gui.Data.State = "CREATE"
|
2019-05-27 12:55:28 -05:00
|
|
|
event := pb.MakeAddVmEvent()
|
2019-05-27 23:29:17 -05:00
|
|
|
for key, entry := range gui.Data.AllEntries {
|
|
|
|
log.Println("\tdefaultEntryChange() Data.AllEntries =", key, entry)
|
|
|
|
log.Println("\tdefaultEntryChange() Data.AllEntries[key].Action =", entry.Action)
|
|
|
|
if (entry.Action == "Hostname") {
|
2019-06-01 00:27:52 -05:00
|
|
|
event.Vms[0].Hostname = entry.UiEntry.Text()
|
2019-05-27 23:29:17 -05:00
|
|
|
}
|
|
|
|
if (entry.Action == "Memory") {
|
2019-06-01 00:27:52 -05:00
|
|
|
event.Vms[0].Memory = pint64(entry.UiEntry.Text())
|
2019-05-27 23:29:17 -05:00
|
|
|
}
|
2019-06-01 00:27:52 -05:00
|
|
|
log.Println("\tdefaultEntryChange() Data.AllEntries[key].E =", entry.UiEntry.Text())
|
2019-05-27 23:29:17 -05:00
|
|
|
log.Println("\tdefaultEntryChange() Data.AllEntries[key].B =", entry.B)
|
|
|
|
if entry.B == b {
|
|
|
|
log.Println("defaultEntryChange() FOUND. Entry assigned to Button", b)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
event.Account = b.Account
|
|
|
|
log.Println("\tTRIGGERING CREATE event=", event)
|
|
|
|
log.Println("\tTRIGGERING CREATE event.Account=", event.Account)
|
2019-05-27 12:55:28 -05:00
|
|
|
prepareAndSend(event)
|
2019-05-25 23:28:21 -05:00
|
|
|
} else if (b.Action == "CONFIG") {
|
2019-05-28 19:22:10 -05:00
|
|
|
newConfig := loadDefaultConfig()
|
|
|
|
config.Accounts = newConfig.Accounts
|
2019-05-25 23:28:21 -05:00
|
|
|
gui.Data.State = "done"
|
|
|
|
} else if (b.Action == "DEBUG") {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tdebug.PrintStack() (SHOULD BE JUST THIS goroutine)")
|
2019-05-25 23:28:21 -05:00
|
|
|
debug.PrintStack()
|
|
|
|
} else if (b.Action == "DEBUG FULL") {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tATTEMPT FULL STACK DUMP")
|
2019-05-25 23:28:21 -05:00
|
|
|
buf := make([]byte, 1<<16)
|
|
|
|
runtime.Stack(buf, true)
|
|
|
|
log.Printf("%s", buf)
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tFINISHED FULL STACK DUMP")
|
2019-05-25 23:28:21 -05:00
|
|
|
} else if (b.Action == "LOGIN") {
|
2019-06-01 19:53:30 -05:00
|
|
|
/*
|
2019-05-25 23:28:21 -05:00
|
|
|
log.Println("\tTRIGGER LOGIN ACCOUNT")
|
|
|
|
gui.Data.State = "SEND LOGIN"
|
2019-05-26 02:27:15 -05:00
|
|
|
|
|
|
|
// TODO: move this into a seperate goroutine
|
|
|
|
event := pb.MakeLoginEvent()
|
|
|
|
event.Account = b.Account
|
|
|
|
prepareAndSend(event)
|
|
|
|
|
2019-05-26 13:54:53 -05:00
|
|
|
count := 0
|
2019-05-25 23:28:21 -05:00
|
|
|
for {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tSleep() in buttonClick() gui.Data.State =", gui.Data.State)
|
2019-05-26 13:54:53 -05:00
|
|
|
time.Sleep(200 * time.Millisecond)
|
2019-05-25 23:28:21 -05:00
|
|
|
if (gui.Data.State == "NEW PROTOBUF") {
|
|
|
|
if (currentMessage == nil) {
|
2019-06-01 01:29:46 -05:00
|
|
|
gui.ErrorWindow(gw,
|
|
|
|
"There was a socket error",
|
|
|
|
"More detailed information can be shown here.")
|
2019-05-25 23:28:21 -05:00
|
|
|
gui.Data.State = "done"
|
|
|
|
} else {
|
|
|
|
log.Println("LOGIN currentMessage =", currentMessage)
|
|
|
|
if (currentMessage.Type == pb.Event_OK) {
|
|
|
|
msg := "On account " + b.Account.Nick + "\n"
|
2019-05-26 04:19:23 -05:00
|
|
|
log.Println("\tLOGIN WAS OK!", msg)
|
|
|
|
log.Println("\tLOGIN WAS OK! old button.Account was =", b.Account)
|
|
|
|
log.Println("\tLOGIN WAS OK! currentMessage.Account =", currentMessage.Account)
|
2019-05-26 13:54:53 -05:00
|
|
|
if (b.Account.Id == currentMessage.Account.Id) {
|
|
|
|
if (b.Account.Token != currentMessage.Account.Token) {
|
|
|
|
log.Println("\tLOGIN SENT NEW TOKEN")
|
|
|
|
b.Account.Token = currentMessage.Account.Token
|
|
|
|
log.Println("\tLOGIN WAS OK! old button.Account is now =", b.Account)
|
|
|
|
}
|
|
|
|
}
|
2019-05-26 04:19:23 -05:00
|
|
|
log.Println("\tLOGIN WAS OK!")
|
2019-05-31 19:37:24 -05:00
|
|
|
gui.MessageWindow(gw, "Login OK", msg)
|
2019-05-26 04:19:23 -05:00
|
|
|
} else if (currentMessage.Type == pb.Event_FAIL) {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tLOGIN FAILED")
|
|
|
|
log.Println("\tLOGIN FAILED")
|
|
|
|
log.Println("\tLOGIN FAILED")
|
2019-05-25 23:28:21 -05:00
|
|
|
msg := "On account " + b.Account.Nick + "\n"
|
|
|
|
msg += "pb.Comment = " + currentMessage.Comment + "\n"
|
|
|
|
msg += "pb.Id = " + fmt.Sprintf("%d", currentMessage.Id) + "\n"
|
2019-05-26 03:05:28 -05:00
|
|
|
msg += "pb.Email = " + b.Account.Email + "\n"
|
|
|
|
msg += "pb.Username = " + b.Account.Username + "\n"
|
2019-05-31 19:37:24 -05:00
|
|
|
gui.ErrorWindow(gw, "Login Failed", msg)
|
2019-05-24 00:47:26 -05:00
|
|
|
}
|
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
}
|
2019-05-25 23:28:21 -05:00
|
|
|
return
|
|
|
|
}
|
2019-05-26 13:54:53 -05:00
|
|
|
// TODO: fix this with an actual timeout
|
2019-05-25 23:28:21 -05:00
|
|
|
count += 1
|
|
|
|
if (count > 10) {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tERROR: waited too long for a resposne")
|
2019-05-25 23:28:21 -05:00
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
return
|
2019-05-24 00:47:26 -05:00
|
|
|
}
|
2019-05-25 23:28:21 -05:00
|
|
|
}
|
2019-06-01 19:53:30 -05:00
|
|
|
*/
|
2019-05-26 19:29:01 -05:00
|
|
|
} else if (b.Action == "SHOW VM") {
|
2019-05-30 00:24:22 -05:00
|
|
|
// gui.Data.CurrentVM = b.VM
|
2019-05-26 19:29:01 -05:00
|
|
|
if (gui.Data.Debug) {
|
2019-05-31 22:14:33 -05:00
|
|
|
// log.Println("\tATTEMPTING TO SHOW VM IN WINDOW")
|
2019-05-29 22:04:45 -05:00
|
|
|
// go gui.GoShowVM()
|
2019-05-31 22:14:33 -05:00
|
|
|
|
|
|
|
log.Println("\tATTEMPTING TO SHOW VM TAB gw = ", gw)
|
2019-06-01 05:24:53 -05:00
|
|
|
createVmBox(gw, b.VM)
|
2019-05-26 19:29:01 -05:00
|
|
|
} else {
|
2019-05-31 22:14:33 -05:00
|
|
|
log.Println("\tATTEMPTING TO SHOW VM TAB gw = ", gw)
|
2019-06-01 05:24:53 -05:00
|
|
|
createVmBox(gw, b.VM)
|
2019-05-26 19:29:01 -05:00
|
|
|
}
|
2019-05-25 23:28:21 -05:00
|
|
|
} else if (b.Action == "SHOW") {
|
|
|
|
log.Println("\tTRIGGER DISPLAY ACCOUNT")
|
|
|
|
gui.Data.State = "SEND WEBSOCKET"
|
2019-05-26 13:54:53 -05:00
|
|
|
|
|
|
|
event := pb.MakeGetEvent()
|
|
|
|
event.Account = b.Account
|
|
|
|
prepareAndSend(event)
|
|
|
|
|
2019-05-25 23:28:21 -05:00
|
|
|
count := 0
|
|
|
|
for {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tSleep() in buttonClick() gui.Data.State =", gui.Data.State)
|
2019-05-25 23:28:21 -05:00
|
|
|
time.Sleep(200 * time.Millisecond)
|
|
|
|
if (gui.Data.State == "NEW PROTOBUF") {
|
|
|
|
if (currentMessage == nil) {
|
2019-06-01 01:29:46 -05:00
|
|
|
gui.ErrorWindow(gw,
|
|
|
|
"There was a socket error",
|
|
|
|
"More detailed information can be shown here.")
|
2019-05-25 23:28:21 -05:00
|
|
|
gui.Data.State = "done"
|
|
|
|
} else {
|
|
|
|
count := countVMS(currentMessage)
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tSHOW VMS currentMessage =", currentMessage)
|
|
|
|
log.Println("\tSHOW VMS count =", count)
|
2019-05-28 17:48:28 -05:00
|
|
|
// TODO: make sure login worked & the account really has zero VMs
|
|
|
|
// if (count != 0) {
|
2019-05-25 23:28:21 -05:00
|
|
|
name := "Virtual Machines (" + b.Account.Nick + ")"
|
2019-06-01 01:45:28 -05:00
|
|
|
mh := addVmsTab(gw, name, count, b.Account)
|
2019-05-31 22:46:23 -05:00
|
|
|
ReadReceivedData(currentMessage, mh, b.GW)
|
2019-05-28 17:48:28 -05:00
|
|
|
// }
|
2019-05-23 21:36:20 -05:00
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
}
|
2019-05-25 23:28:21 -05:00
|
|
|
return
|
|
|
|
}
|
|
|
|
count += 1
|
|
|
|
if (count > 10) {
|
2019-05-26 00:07:58 -05:00
|
|
|
log.Println("\tERROR: waited too long for a resposne")
|
2019-05-25 23:28:21 -05:00
|
|
|
currentMessage = nil
|
|
|
|
gui.Data.State = "done"
|
|
|
|
return
|
2019-05-23 18:38:51 -05:00
|
|
|
}
|
|
|
|
}
|
2019-05-23 00:33:16 -05:00
|
|
|
}
|
|
|
|
}
|
2019-05-09 08:52:51 -05:00
|
|
|
|
2019-05-28 18:47:16 -05:00
|
|
|
//
|
|
|
|
// This is GO language concept for 'recover' to keep an app from completely crashing
|
2019-05-26 05:13:09 -05:00
|
|
|
//
|
2019-05-26 04:58:29 -05:00
|
|
|
// Doing this can sometimes avoid a panic() on things like:
|
|
|
|
// panic: runtime error: slice bounds out of range
|
2019-05-26 05:13:09 -05:00
|
|
|
//
|
|
|
|
// In debugging mode, always panic() and never try to recover()
|
|
|
|
//
|
2019-05-26 04:58:29 -05:00
|
|
|
func r() {
|
2019-05-26 05:13:09 -05:00
|
|
|
if (gui.Data.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)
|
2019-05-31 22:14:33 -05:00
|
|
|
panic("something")
|
2019-05-26 05:13:09 -05:00
|
|
|
}
|
2019-05-26 04:58:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-25 23:28:21 -05:00
|
|
|
func prepareAndSend(event *pb.Event) {
|
2019-05-26 03:05:28 -05:00
|
|
|
if (event.Account == nil) {
|
|
|
|
log.Println("\tmain.prepareAndSend() ERROR event.Token = nil")
|
|
|
|
log.Println("\tmain.prepareAndSend() ERROR event.Token = nil")
|
|
|
|
log.Println("\tmain.prepareAndSend() ERROR event.Token = nil")
|
|
|
|
} else {
|
2019-05-26 04:19:23 -05:00
|
|
|
s := event.Account.Token
|
2019-05-26 05:41:51 -05:00
|
|
|
log.Println("\tmain.prepareAndSend() event.Token =", s) // s[len(s)-24:]) // this can panic because strings.() is stupid
|
2019-05-26 03:05:28 -05:00
|
|
|
}
|
2019-05-25 23:28:21 -05:00
|
|
|
gorillaSendProtobuf(event)
|
|
|
|
gui.Data.State = "READ PROTOBUF"
|
|
|
|
}
|
|
|
|
|
2019-05-24 00:47:26 -05:00
|
|
|
// this watches the GUI primarily to process protobuf's
|
2019-05-27 17:25:50 -05:00
|
|
|
// maybe this is pointless or wrong
|
2019-05-23 00:33:16 -05:00
|
|
|
func watchGUI() {
|
2019-05-23 15:27:05 -05:00
|
|
|
count := 0
|
2019-05-23 00:33:16 -05:00
|
|
|
|
|
|
|
for {
|
2019-05-23 15:27:05 -05:00
|
|
|
if (count > 10) {
|
|
|
|
log.Println("Sleep() in watchGUI() gui.Data.State =", gui.Data.State)
|
2019-06-01 15:42:03 -05:00
|
|
|
for i, window := range gui.Data.Windows {
|
2019-06-01 19:53:30 -05:00
|
|
|
log.Println("watchGUI() gui.Data.Windows i =", i, "Action =", window.Action)
|
|
|
|
for name, _ := range window.BoxMap {
|
|
|
|
log.Println("\twatchGUI() name =", name)
|
2019-05-31 22:14:33 -05:00
|
|
|
}
|
2019-05-31 15:15:10 -05:00
|
|
|
}
|
2019-05-23 15:27:05 -05:00
|
|
|
count = 0
|
|
|
|
}
|
|
|
|
count += 1
|
|
|
|
time.Sleep(200 * time.Millisecond)
|
2019-05-23 00:33:16 -05:00
|
|
|
|
|
|
|
if (gui.Data.State == "kill") {
|
|
|
|
log.Println("gui.State = kill")
|
|
|
|
log.Println("gui.State = kill")
|
|
|
|
log.Println("gui.State = kill")
|
2019-05-26 02:27:15 -05:00
|
|
|
onExit(nil)
|
2019-05-29 17:46:37 -05:00
|
|
|
} else if (gui.Data.State == "HIDE") {
|
|
|
|
time.Sleep(20 * time.Millisecond) // maybe required for macos & windows refresh to work?
|
2019-05-31 15:15:10 -05:00
|
|
|
// gui.Data.Windows[0].Box1.Show()
|
|
|
|
// gui.Data.Windows[0].Box2.Show()
|
|
|
|
for key, element := range gui.Data.Windows {
|
|
|
|
log.Println("watchGUI() gui.Data.Windows =", key, element.Action)
|
|
|
|
element.UiTab.Show()
|
|
|
|
}
|
2019-05-29 17:46:37 -05:00
|
|
|
gui.Data.State = "done"
|
2019-05-23 00:33:16 -05:00
|
|
|
}
|
2019-05-07 16:54:08 -05:00
|
|
|
}
|
2019-05-07 07:02:39 -05:00
|
|
|
}
|