package wol import ( "context" "fmt" "net" "time" ) var ErrTimeout = fmt.Errorf("timeout waiting for machine to respond") func WaitUntilReady(ctx context.Context, host string, sshPort int, maxWait, checkInterval time.Duration) error { deadline := time.Now().Add(maxWait) interval := checkInterval ticker := time.NewTicker(checkInterval) defer ticker.Stop() for { select { case <-ctx.Done(): return ctx.Err() case <-ticker.C: } addr := fmt.Sprintf("%s:%d", host, sshPort) dialer := net.Dialer{Timeout: 3 * time.Second} conn, err := dialer.DialContext(ctx, "tcp", addr) if err == nil { conn.Close() return nil } if time.Now().After(deadline) { return ErrTimeout } elapsed := time.Since(time.Now().Add(-maxWait)) if elapsed > maxWait/2 && interval < 10*time.Second { interval = interval * 3 / 2 if interval > 10*time.Second { interval = 10 * time.Second } ticker.Reset(interval) } } } func IsReachable(ctx context.Context, host string, port int, timeout time.Duration) bool { ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() addr := fmt.Sprintf("%s:%d", host, port) dialer := net.Dialer{Timeout: timeout} conn, err := dialer.DialContext(ctx, "tcp", addr) if err != nil { return false } conn.Close() return true }