package neko import ( "fmt" "os" "os/signal" "runtime" "demodesk/neko/internal/broadcast" "demodesk/neko/internal/http" "demodesk/neko/internal/remote" "demodesk/neko/internal/session" "demodesk/neko/internal/types/config" "demodesk/neko/internal/webrtc" "demodesk/neko/internal/websocket" "github.com/rs/zerolog" "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) const Header = `&34 _ __ __ / | / /__ / /______ \ /\ / |/ / _ \/ //_/ __ \ ) ( ') / /| / __/ ,< / /_/ / ( / ) /_/ |_/\___/_/|_|\____/ \(__)| &1&37 nurdism/neko &33%s v%s&0 ` var ( // buildDate = "dev" // gitCommit = "dev" // gitBranch = "dev" // Major version when you make incompatible API changes, major = "dev" // Minor version when you add functionality in a backwards-compatible manner, and minor = "dev" // Patch version when you make backwards-compatible bug fixeneko. patch = "dev" ) var Service *Neko func init() { Service = &Neko{ Version: &Version{ Major: major, Minor: minor, Patch: patch, GitCommit: gitCommit, GitBranch: gitBranch, BuildDate: buildDate, GoVersion: runtime.Version(), Compiler: runtime.Compiler, Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH), }, Root: &config.Root{}, Server: &config.Server{}, Remote: &config.Remote{}, Broadcast: &config.Broadcast{}, WebRTC: &config.WebRTC{}, WebSocket: &config.WebSocket{}, } } type Version struct { Major string Minor string Patch string GitCommit string GitBranch string BuildDate string GoVersion string Compiler string Platform string } func (i *Version) String() string { return fmt.Sprintf("%s.%s.%s %s", i.Major, i.Minor, i.Patch, i.GitCommit) } func (i *Version) Details() string { return fmt.Sprintf( "%s\n%s\n%s\n%s\n%s\n%s\n%s\n", fmt.Sprintf("Version %s.%s.%s", i.Major, i.Minor, i.Patch), fmt.Sprintf("GitCommit %s", i.GitCommit), fmt.Sprintf("GitBranch %s", i.GitBranch), fmt.Sprintf("BuildDate %s", i.BuildDate), fmt.Sprintf("GoVersion %s", i.GoVersion), fmt.Sprintf("Compiler %s", i.Compiler), fmt.Sprintf("Platform %s", i.Platform), ) } type Neko struct { Version *Version Root *config.Root Remote *config.Remote Broadcast *config.Broadcast Server *config.Server WebRTC *config.WebRTC WebSocket *config.WebSocket logger zerolog.Logger server *http.Server sessionManager *session.SessionManager remoteManager *remote.RemoteManager broadcastManager *broadcast.BroadcastManager webRTCManager *webrtc.WebRTCManager webSocketHandler *websocket.WebSocketHandler } func (neko *Neko) Preflight() { neko.logger = log.With().Str("service", "neko").Logger() } func (neko *Neko) Start() { broadcastManager := broadcast.New(neko.Remote, neko.Broadcast) remoteManager := remote.New(neko.Remote, broadcastManager) remoteManager.Start() sessionManager := session.New(remoteManager) webRTCManager := webrtc.New(sessionManager, remoteManager, neko.WebRTC) webRTCManager.Start() webSocketHandler := websocket.New(sessionManager, remoteManager, broadcastManager, webRTCManager, neko.WebSocket) webSocketHandler.Start() server := http.New(neko.Server, webSocketHandler) server.Start() neko.sessionManager = sessionManager neko.remoteManager = remoteManager neko.broadcastManager = broadcastManager neko.webRTCManager = webRTCManager neko.webSocketHandler = webSocketHandler neko.server = server } func (neko *Neko) Shutdown() { if err := neko.remoteManager.Shutdown(); err != nil { neko.logger.Err(err).Msg("remote manager shutdown with an error") } else { neko.logger.Debug().Msg("remote manager shutdown") } if err := neko.webRTCManager.Shutdown(); err != nil { neko.logger.Err(err).Msg("webrtc manager shutdown with an error") } else { neko.logger.Debug().Msg("webrtc manager shutdown") } if err := neko.webSocketHandler.Shutdown(); err != nil { neko.logger.Err(err).Msg("websocket handler shutdown with an error") } else { neko.logger.Debug().Msg("websocket handler shutdown") } if err := neko.server.Shutdown(); err != nil { neko.logger.Err(err).Msg("server shutdown with an error") } else { neko.logger.Debug().Msg("server shutdown") } } func (neko *Neko) ServeCommand(cmd *cobra.Command, args []string) { neko.logger.Info().Msg("starting neko server") neko.Start() neko.logger.Info().Msg("neko ready") quit := make(chan os.Signal, 1) signal.Notify(quit, os.Interrupt) sig := <-quit neko.logger.Warn().Msgf("received %s, attempting graceful shutdown: \n", sig) neko.Shutdown() neko.logger.Info().Msg("shutdown complete") }