vnc

package
v1.39.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 21, 2026 License: AGPL-3.0 Imports: 15 Imported by: 0

Documentation

Overview

Package vnc provides per-session virtual display and VNC server lifecycle management. On Linux, each session can own a dedicated Xvfb virtual framebuffer and a paired x11vnc server. On non-Linux platforms or when required binaries are absent, a no-op manager is returned and all VNC functionality is gracefully disabled.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type DepsResult

type DepsResult struct {
	// Available is true when all required binaries are present and the platform
	// is supported. Only when Available is true will New() return a live manager.
	Available bool
	// Missing lists the names of binaries that could not be found via LookPath.
	Missing []string
	// Reason is a human-readable explanation when Available is false.
	Reason string
}

DepsResult holds the outcome of a dependency check.

func CheckDependencies

func CheckDependencies() DepsResult

CheckDependencies checks whether all required VNC binaries are present and the current OS is Linux. It is safe to call multiple times; each call re-runs the LookPath checks (results are cached by New() callers).

type DisplayAllocator

type DisplayAllocator struct {
	// contains filtered or unexported fields
}

DisplayAllocator manages X11 display number allocation using the standard X11 lock-file protocol. Each allocated display number gets an exclusive lock at /tmp/.X<N>-lock. The POSIX O_EXCL flag makes the allocation atomic.

func NewDisplayAllocator

func NewDisplayAllocator(base, rangeMax int) *DisplayAllocator

NewDisplayAllocator creates a DisplayAllocator that searches display numbers in [base, base+rangeMax).

func (*DisplayAllocator) Allocate

func (d *DisplayAllocator) Allocate(sessionID string) (int, error)

Allocate finds an unused display number, creates the X11 lock file with O_EXCL to claim it atomically, and records the allocation. Returns the allocated display number or an error if none are free.

func (*DisplayAllocator) CleanupStaleDisplays

func (d *DisplayAllocator) CleanupStaleDisplays()

CleanupStaleDisplays scans all display numbers in the allocator's range and removes lock files whose recorded PID is no longer alive. This should be called at startup before any allocations to reclaim displays left behind by crashed processes.

func (*DisplayAllocator) Release

func (d *DisplayAllocator) Release(n int)

Release removes the Go-level allocation record and deletes the X11 lock file for display number n. It is safe to call even if the display was never successfully allocated by this process (it is a no-op in that case).

type VNCConfig

type VNCConfig struct {
	// DisplayBase is the first X11 display number to try allocating (e.g. 100).
	DisplayBase int
	// DisplayRangeMax is the number of display numbers to search above DisplayBase.
	// Displays DisplayBase through DisplayBase+DisplayRangeMax-1 are candidates.
	DisplayRangeMax int
	// Resolution is the Xvfb screen resolution string, e.g. "1280x800x24".
	Resolution string
	// MaxRestarts is the maximum number of x11vnc crash-restart attempts before
	// the manager sets VNCStatusUnavailable. Default 3.
	MaxRestarts int
	// SessionID is the identifier of the owning session; used by DisplayAllocator
	// to associate the display lock with a specific session.
	SessionID string
}

VNCConfig holds configuration for the VNC process manager. Populated from config.BrowserPassthroughConfig and passed to New().

func DefaultVNCConfig

func DefaultVNCConfig() VNCConfig

DefaultVNCConfig returns a VNCConfig with sensible defaults.

type VNCProcessManager

type VNCProcessManager interface {
	// StartDisplay allocates an X11 display number and starts Xvfb.
	// Call this BEFORE the tmux session is created so DISPLAY can be injected
	// at new-session time via ExtraEnv. Returns 0 (no-op) on unsupported platforms.
	StartDisplay(ctx context.Context) error

	// StartServer starts x11vnc and the window tracker goroutine.
	// Call this AFTER the tmux session is live.
	StartServer(ctx context.Context) error

	// Stop tears down x11vnc and Xvfb and releases the display number.
	// Safe to call if Start was never called or already stopped.
	Stop()
	// State returns a snapshot of the current VNC state.
	State() VNCState
	// DisplayNumber returns the allocated X11 display number (e.g. 100 for :100).
	// Returns 0 if no display has been allocated.
	DisplayNumber() int
	// DisplayEnv returns the DISPLAY environment variable assignment for this
	// session's display, e.g. "DISPLAY=:101" or "DISPLAY=:0". Returns "" if no
	// display is available. Prefer this over DisplayNumber for env injection.
	DisplayEnv() string
	// Port returns the localhost TCP port on which x11vnc is listening.
	// Returns 0 if x11vnc is not running.
	Port() int
	// SetStateChangeCallback registers a callback that is invoked (in a goroutine)
	// each time the VNC state changes. Replaces any previously registered callback.
	SetStateChangeCallback(func(VNCState))
	// ReconcileOrphans scans X11 lock files in the allocator's range and removes
	// stale locks left behind by crashed processes from a previous run.
	ReconcileOrphans()
}

VNCProcessManager is the interface satisfied by both the real VNC manager (vncProcessManager) and the no-op manager (noopVNCManager). The session layer holds this interface so it can be swapped out on non-Linux hosts or when required binaries are absent.

func New

New returns a VNCProcessManager appropriate for the current host. If dependency checks fail (missing binaries or non-Linux platform), a noopVNCManager is returned that satisfies the interface with all no-ops. cfg.SessionID must be set before calling New.

type VNCState

type VNCState struct {
	// Status is the current operational status.
	Status VNCStatus
	// DisplayNumber is the allocated X11 display number (e.g. 100 for :100).
	// Zero if no display has been allocated.
	DisplayNumber int
	// Port is the localhost TCP port that x11vnc is listening on.
	// Zero if x11vnc is not running.
	Port int
	// BrowserWindowDetected is true when a browser window has been found on the
	// virtual display and x11vnc has been restarted in -id mode targeting it.
	BrowserWindowDetected bool
}

VNCState is the Go-native (non-proto) runtime state of the VNC subsystem. It is periodically mapped to the proto VNCState by the session service layer.

type VNCStatus

type VNCStatus int

VNCStatus represents the operational state of the VNC subsystem for a session.

const (
	// VNCStatusUnspecified is the zero value; not yet initialized.
	VNCStatusUnspecified VNCStatus = iota
	// VNCStatusStarting means Xvfb/x11vnc processes are launching.
	VNCStatusStarting
	// VNCStatusReady means a browser window has been detected and x11vnc is
	// focused on it via -id <windowID>.
	VNCStatusReady
	// VNCStatusNoBrowser means VNC is running (full display mode) but no browser
	// window has been detected yet on the virtual display.
	VNCStatusNoBrowser
	// VNCStatusPassthrough means a pre-existing X display was detected and reused;
	// x11vnc is not running in this mode.
	VNCStatusPassthrough
	// VNCStatusUnavailable means VNC is not available for this session — either
	// required binaries are missing, the platform is not Linux, or startup failed
	// after all retry attempts.
	VNCStatusUnavailable
)

func (VNCStatus) String

func (s VNCStatus) String() string

String returns a human-readable name for the VNCStatus.

type WindowTracker

type WindowTracker struct {
	// contains filtered or unexported fields
}

WindowTracker polls the virtual display for a Chrome browser window using xdotool and calls registered callbacks when a window appears or disappears.

func NewWindowTracker

func NewWindowTracker(displayN int, onWindowDetected func(windowID string), onWindowLost func()) *WindowTracker

NewWindowTracker creates a WindowTracker for the given X11 display number. onWindowDetected is called (in the polling goroutine) when a new Chrome window appears or the tracked window ID changes. onWindowLost is called when the previously tracked window disappears.

func (*WindowTracker) Start

func (wt *WindowTracker) Start(ctx context.Context)

Start launches the window tracking goroutine. It exits when ctx is cancelled. The goroutine polls at 500ms when no window is tracked, or 2s when a window is stable, matching the plan specification.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL