mirror of
https://github.com/getcompanion-ai/computer-host.git
synced 2026-04-15 03:00:42 +00:00
87 lines
2.1 KiB
Go
87 lines
2.1 KiB
Go
package daemon
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
contracthost "github.com/getcompanion-ai/computer-host/contract"
|
|
)
|
|
|
|
func waitForGuestReady(ctx context.Context, host string, ports []contracthost.MachinePort) error {
|
|
host = strings.TrimSpace(host)
|
|
if host == "" {
|
|
return fmt.Errorf("guest runtime host is required")
|
|
}
|
|
|
|
waitContext, cancel := context.WithTimeout(ctx, defaultGuestReadyTimeout)
|
|
defer cancel()
|
|
|
|
for _, port := range ports {
|
|
if err := waitForGuestPort(waitContext, host, port); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func waitForGuestPort(ctx context.Context, host string, port contracthost.MachinePort) error {
|
|
address := net.JoinHostPort(host, strconv.Itoa(int(port.Port)))
|
|
ticker := time.NewTicker(defaultGuestReadyPollInterval)
|
|
defer ticker.Stop()
|
|
|
|
var lastErr error
|
|
for {
|
|
probeCtx, cancel := context.WithTimeout(ctx, defaultGuestDialTimeout)
|
|
ready, err := guestPortReady(probeCtx, host, port)
|
|
cancel()
|
|
if err == nil && ready {
|
|
return nil
|
|
}
|
|
lastErr = err
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return fmt.Errorf("wait for guest port %q on %s: %w (last_err=%v)", port.Name, address, ctx.Err(), lastErr)
|
|
case <-ticker.C:
|
|
}
|
|
}
|
|
}
|
|
|
|
func guestPortsReady(ctx context.Context, host string, ports []contracthost.MachinePort) (bool, error) {
|
|
host = strings.TrimSpace(host)
|
|
if host == "" {
|
|
return false, fmt.Errorf("guest runtime host is required")
|
|
}
|
|
|
|
for _, port := range ports {
|
|
probeCtx, cancel := context.WithTimeout(ctx, defaultGuestDialTimeout)
|
|
ready, err := guestPortReady(probeCtx, host, port)
|
|
cancel()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if !ready {
|
|
return false, nil
|
|
}
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
func guestPortReady(ctx context.Context, host string, port contracthost.MachinePort) (bool, error) {
|
|
address := net.JoinHostPort(host, strconv.Itoa(int(port.Port)))
|
|
dialer := net.Dialer{Timeout: defaultGuestDialTimeout}
|
|
|
|
connection, err := dialer.DialContext(ctx, string(port.Protocol), address)
|
|
if err == nil {
|
|
_ = connection.Close()
|
|
return true, nil
|
|
}
|
|
if ctx.Err() != nil {
|
|
return false, nil
|
|
}
|
|
return false, nil
|
|
}
|