diff --git a/main.go b/main.go index 99644d5..bc25004 100644 --- a/main.go +++ b/main.go @@ -29,17 +29,12 @@ func main() { // Check if we're running as a Windows service if isWindowsService() { runService("OlmWireguardService", false) - fmt.Println("Service started successfully") + fmt.Println("Running as Windows service") return } // Handle service management commands on Windows - // print the args - for i, arg := range os.Args { - fmt.Printf("Arg %d: %s\n", i, arg) - } if runtime.GOOS == "windows" && len(os.Args) > 1 { - fmt.Println("Handling Windows service management command:", os.Args[1]) switch os.Args[1] { case "install": err := installService() @@ -107,6 +102,9 @@ func main() { } func runOlmMain(ctx context.Context) { + // Log that we've entered the main function + fmt.Printf("runOlmMain() called - starting main logic\n") + // Setup Windows event logging if on Windows if runtime.GOOS == "windows" { setupWindowsEventLog() @@ -147,6 +145,9 @@ func runOlmMain(ctx context.Context) { pingIntervalStr := os.Getenv("PING_INTERVAL") pingTimeoutStr := os.Getenv("PING_TIMEOUT") + // Debug: Print all environment variables we're checking + fmt.Printf("Environment variables: PANGOLIN_ENDPOINT='%s', OLM_ID='%s', OLM_SECRET='%s'\n", endpoint, id, secret) + if endpoint == "" { flag.StringVar(&endpoint, "endpoint", "", "Endpoint of your Pangolin server") } @@ -207,6 +208,9 @@ func runOlmMain(ctx context.Context) { flag.Parse() + // Debug: Print final values after flag parsing + fmt.Printf("After flag parsing: endpoint='%s', id='%s', secret='%s'\n", endpoint, id, secret) + if *version { fmt.Println("Olm version replaceme") os.Exit(0) @@ -216,6 +220,11 @@ func runOlmMain(ctx context.Context) { loggerLevel := parseLogLevel(logLevel) logger.GetLogger().SetLevel(parseLogLevel(logLevel)) + // Log startup information + logger.Info("Olm service starting...") + logger.Info("Parameters: endpoint='%s', id='%s', secret='%s'", endpoint, id, secret) + logger.Info("HTTP enabled: %v, HTTP addr: %s", enableHTTP, httpAddr) + // Handle test mode if testMode { if testTarget == "" { @@ -264,10 +273,55 @@ func runOlmMain(ctx context.Context) { } }() } + + // Check if required parameters are missing and provide helpful guidance + missingParams := []string{} + if id == "" { + missingParams = append(missingParams, "id (use -id flag or OLM_ID env var)") + } + if secret == "" { + missingParams = append(missingParams, "secret (use -secret flag or OLM_SECRET env var)") + } + if endpoint == "" { + missingParams = append(missingParams, "endpoint (use -endpoint flag or PANGOLIN_ENDPOINT env var)") + } + + if len(missingParams) > 0 { + logger.Error("Missing required parameters: %v", missingParams) + logger.Error("Either provide them as command line flags or set as environment variables") + fmt.Printf("ERROR: Missing required parameters: %v\n", missingParams) + fmt.Printf("Please provide them as command line flags or set as environment variables\n") + if !enableHTTP { + logger.Error("HTTP server is disabled, cannot receive parameters via API") + fmt.Printf("HTTP server is disabled, cannot receive parameters via API\n") + return + } + } + // wait until we have a client id and secret and endpoint + waitCount := 0 for id == "" || secret == "" || endpoint == "" { - logger.Debug("Waiting for client ID, secret, and endpoint...") - time.Sleep(1 * time.Second) + select { + case <-ctx.Done(): + logger.Info("Context cancelled while waiting for credentials") + return + default: + missing := []string{} + if id == "" { + missing = append(missing, "id") + } + if secret == "" { + missing = append(missing, "secret") + } + if endpoint == "" { + missing = append(missing, "endpoint") + } + waitCount++ + if waitCount%10 == 1 { // Log every 10 seconds instead of every second + logger.Debug("Waiting for missing parameters: %v (waiting %d seconds)", missing, waitCount) + } + time.Sleep(1 * time.Second) + } } // parse the mtu string into an int @@ -748,4 +802,7 @@ func runOlmMain(ctx context.Context) { if dev != nil { dev.Close() } + + logger.Info("runOlmMain() exiting") + fmt.Printf("runOlmMain() exiting\n") } diff --git a/service_windows.go b/service_windows.go index ec9bdbf..0cbc7bd 100644 --- a/service_windows.go +++ b/service_windows.go @@ -32,10 +32,17 @@ func (s *olmService) Execute(args []string, r <-chan svc.ChangeRequest, changes const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown changes <- svc.Status{State: svc.StartPending} + s.elog.Info(1, "Service Execute called, starting main logic") + // Start the main olm functionality - go s.runOlm() + olmDone := make(chan struct{}) + go func() { + s.runOlm() + close(olmDone) + }() changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} + s.elog.Info(1, "Service status set to Running") for { select { @@ -46,11 +53,24 @@ func (s *olmService) Execute(args []string, r <-chan svc.ChangeRequest, changes case svc.Stop, svc.Shutdown: s.elog.Info(1, "Service stopping") changes <- svc.Status{State: svc.StopPending} - s.stop() + if s.stop != nil { + s.stop() + } + // Wait for main logic to finish or timeout + select { + case <-olmDone: + s.elog.Info(1, "Main logic finished gracefully") + case <-time.After(10 * time.Second): + s.elog.Info(1, "Timeout waiting for main logic to finish") + } return false, 0 default: s.elog.Error(1, fmt.Sprintf("Unexpected control request #%d", c)) } + case <-olmDone: + s.elog.Info(1, "Main olm logic completed, stopping service") + changes <- svc.Status{State: svc.StopPending} + return false, 0 } } } @@ -59,21 +79,31 @@ func (s *olmService) runOlm() { // Create a context that can be cancelled when the service stops s.ctx, s.stop = context.WithCancel(context.Background()) - // Run the main olm logic in a separate goroutine + // Setup logging for service mode + setupWindowsEventLog() + s.elog.Info(1, "Starting Olm main logic") + + // Run the main olm logic and wait for it to complete + done := make(chan struct{}) go func() { defer func() { if r := recover(); r != nil { s.elog.Error(1, fmt.Sprintf("Olm panic: %v", r)) } + close(done) }() // Call the main olm function runOlmMain(s.ctx) }() - // Wait for context cancellation - <-s.ctx.Done() - s.elog.Info(1, "Olm service context cancelled") + // Wait for either context cancellation or main logic completion + select { + case <-s.ctx.Done(): + s.elog.Info(1, "Olm service context cancelled") + case <-done: + s.elog.Info(1, "Olm main logic completed") + } } func runService(name string, isDebug bool) { @@ -82,9 +112,11 @@ func runService(name string, isDebug bool) { if isDebug { elog = debug.New(name) + fmt.Printf("Starting %s service in debug mode\n", name) } else { elog, err = eventlog.Open(name) if err != nil { + fmt.Printf("Failed to open event log: %v\n", err) return } } @@ -100,9 +132,15 @@ func runService(name string, isDebug bool) { err = run(name, service) if err != nil { elog.Error(1, fmt.Sprintf("%s service failed: %v", name, err)) + if isDebug { + fmt.Printf("Service failed: %v\n", err) + } return } elog.Info(1, fmt.Sprintf("%s service stopped", name)) + if isDebug { + fmt.Printf("%s service stopped\n", name) + } } func installService() error { @@ -292,18 +330,25 @@ func getServiceStatus() (string, error) { } func isWindowsService() bool { - interactive, err := svc.IsWindowsService() - return err == nil && interactive + isWindowsService, err := svc.IsWindowsService() + return err == nil && isWindowsService } func setupWindowsEventLog() { // Create log directory if it doesn't exist logDir := filepath.Join(os.Getenv("PROGRAMDATA"), "Olm", "logs") - os.MkdirAll(logDir, 0755) + err := os.MkdirAll(logDir, 0755) + if err != nil { + fmt.Printf("Failed to create log directory: %v\n", err) + return + } logFile := filepath.Join(logDir, "olm.log") file, err := os.OpenFile(logFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) - if err == nil { - log.SetOutput(file) + if err != nil { + fmt.Printf("Failed to open log file: %v\n", err) + return } + log.SetOutput(file) + log.Printf("Olm service logging initialized - log file: %s", logFile) }