package kvm import ( "context" "net/http" "os" "os/signal" "syscall" "time" "github.com/gwatts/rootcerts" ) var appCtx context.Context func Main() { SyncConfigSD(true) LoadConfig() var cancel context.CancelFunc appCtx, cancel = context.WithCancel(context.Background()) defer cancel() systemVersionLocal, appVersionLocal, err := GetLocalVersion() if err != nil { logger.Warn().Err(err).Msg("failed to get local version") } logger.Info(). Interface("system_version", systemVersionLocal). Interface("app_version", appVersionLocal). Msg("starting KVM") go runWatchdog() go confirmCurrentSystem() //A/B system http.DefaultClient.Timeout = 1 * time.Minute err = rootcerts.UpdateDefaultTransport() if err != nil { logger.Warn().Err(err).Msg("failed to load Root CA certificates") } logger.Info(). Int("ca_certs_loaded", len(rootcerts.Certs())). Msg("loaded Root CA certificates") // Initialize network if err := initNetwork(); err != nil { logger.Error().Err(err).Msg("failed to initialize network") os.Exit(1) } // Initialize time sync initTimeSync() timeSync.Start() // Initialize mDNS if err := initMdns(); err != nil { logger.Error().Err(err).Msg("failed to initialize mDNS") os.Exit(1) } //if mDNS != nil { // _ = mDNS.SetListenOptions(config.NetworkConfig.GetMDNSMode()) // _ = mDNS.SetLocalNames([]string{ // networkState.GetHostname(), // networkState.GetFQDN(), // }, true) //} // Initialize native ctrl socket server StartVideoCtrlSocketServer() // Initialize native video socket server StartVideoDataSocketServer() // Initialize native audio socket server StartAudioCtrlSocketServer() StartVpnCtrlSocketServer() StartDisplayCtrlSocketServer() initPrometheus() go func() { err = ExtractAndRunVideoBin() if err != nil { logger.Warn().Err(err).Msg("failed to extract and run video bin") //TODO: prepare an error message screen buffer to show on kvm screen } err = ExtractAndRunDisplayBin() if err != nil { logger.Warn().Err(err).Msg("failed to extract and run display bin") //TODO: prepare an error message screen buffer to show on kvm screen } err = ExtractAndRunAudioBin() if err != nil { logger.Warn().Err(err).Msg("failed to extract and run audio bin") //TODO: prepare an error message screen buffer to show on kvm screen } err = ExtractAndRunVpnBin() if err != nil { logger.Warn().Err(err).Msg("failed to extract and run vpn bin") //TODO: prepare an error message screen buffer to show on kvm screen } }() // initialize usb gadget initUsbGadget() // initialize GPIO initGPIO() if err := setInitialVirtualMediaState(); err != nil { logger.Warn().Err(err).Msg("failed to set initial virtual media state") } if err := initImagesFolder(); err != nil { logger.Warn().Err(err).Msg("failed to init images folder") } initJiggler() // initialize display initDisplay() // Initialize VPN initVPN() initSystemInfo() //Auto update //go func() { // time.Sleep(15 * time.Minute) // for { // logger.Debug().Bool("auto_update_enabled", config.AutoUpdateEnabled).Msg("UPDATING") // if !config.AutoUpdateEnabled { // return // } // if currentSession != nil { // logger.Debug().Msg("skipping update since a session is active") // time.Sleep(1 * time.Minute) // continue // } // includePreRelease := config.IncludePreRelease // err = TryUpdate(context.Background(), GetDeviceID(), includePreRelease) // if err != nil { // logger.Warn().Err(err).Msg("failed to auto update") // } // time.Sleep(1 * time.Hour) // } //}() //go RunFuseServer() go RunWebServer() go RunWebSecureServer() // Web secure server is started only if TLS mode is enabled if config.TLSMode != "" { startWebSecureServer() } initSerialPort() sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM) <-sigs logger.Info().Msg("KVM Shutting Down") //if fuseServer != nil { // err := setMassStorageImage(" ") // if err != nil { // logger.Infof("Failed to unmount mass storage image: %v", err) // } // err = fuseServer.Unmount() // if err != nil { // logger.Infof("Failed to unmount fuse: %v", err) // } // os.Exit(0) }