package vsockping import ( "bufio" "context" "fmt" "io" "log/slog" "net" "strings" "time" sdkvsock "github.com/firecracker-microvm/firecracker-go-sdk/vsock" ) const ( Port uint32 = 42070 RequestLine = "PING\n" ResponseLine = "PONG\n" GuestBinaryName = "banger-vsock-pingd" GuestInstallPath = "/usr/local/bin/" + GuestBinaryName ServiceName = "banger-vsock-pingd.service" serviceUnit = `[Unit] Description=Banger vsock ping responder After=network.target [Service] Type=simple ExecStart=/usr/local/bin/banger-vsock-pingd Restart=on-failure RestartSec=1 [Install] WantedBy=multi-user.target ` modulesLoadConfig = "vsock\nvmw_vsock_virtio_transport\n" ) func Ping(ctx context.Context, logger *slog.Logger, socketPath string) error { conn, err := sdkvsock.DialContext( ctx, socketPath, Port, sdkvsock.WithRetryTimeout(3*time.Second), sdkvsock.WithRetryInterval(100*time.Millisecond), ) if err != nil { return err } defer conn.Close() if deadline, ok := ctx.Deadline(); ok { _ = conn.SetDeadline(deadline) } else { _ = conn.SetDeadline(time.Now().Add(3 * time.Second)) } if _, err := io.WriteString(conn, RequestLine); err != nil { return err } line, err := bufio.NewReader(conn).ReadString('\n') if err != nil { return err } if strings.TrimSpace(line) != strings.TrimSpace(ResponseLine) { return fmt.Errorf("unexpected vsock ping response %q", strings.TrimSpace(line)) } if logger != nil { logger.Debug("vsock ping ok", "vsock_path", socketPath, "vsock_port", Port) } return nil } func ServiceUnit() string { return serviceUnit } func ModulesLoadConfig() string { return modulesLoadConfig } func ReminderMessage(name string) string { return fmt.Sprintf("session ended; %s is still running (stop it with 'banger vm stop %s')", name, name) } func WarningMessage(name string, err error) string { if err == nil { return "" } return fmt.Sprintf("warning: failed to check whether %s is still running: %v", name, err) } func ServeConn(conn net.Conn) error { defer conn.Close() _ = conn.SetDeadline(time.Now().Add(5 * time.Second)) line, err := bufio.NewReader(conn).ReadString('\n') if err != nil { return err } if strings.TrimSpace(line) != strings.TrimSpace(RequestLine) { return fmt.Errorf("unexpected request %q", strings.TrimSpace(line)) } _, err = io.WriteString(conn, ResponseLine) return err }