Documentation
¶
Overview ¶
Example ¶
// Create a VNC error with context
err := NewVNCError("handshake", ErrNetwork, "connection timeout", fmt.Errorf("dial tcp: timeout"))
fmt.Println("Error:", err)
fmt.Println("Is network error:", IsVNCError(err, ErrNetwork))
fmt.Println("Error code:", GetErrorCode(err))
Output: Error: vnc network: handshake: connection timeout: dial tcp: timeout Is network error: true Error code: network
Index ¶
- Constants
- Variables
- func ConvertPixelFormat(ctx context.Context, srcData []byte, srcFormat, dstFormat *PixelFormat) ([]byte, error)
- func IsVNCError(err error, code ...ErrorCode) bool
- func WrapError(op string, code ErrorCode, message string, err error) error
- type AuthFactory
- type AuthRegistry
- func (r *AuthRegistry) CreateAuth(securityType uint8) (ClientAuth, error)
- func (r *AuthRegistry) GetSupportedTypes() []uint8
- func (r *AuthRegistry) IsSupported(securityType uint8) bool
- func (r *AuthRegistry) NegotiateAuth(ctx context.Context, serverTypes []uint8, preferredOrder []uint8) (ClientAuth, uint8, error)
- func (r *AuthRegistry) Register(securityType uint8, factory AuthFactory)
- func (r *AuthRegistry) SetLogger(logger Logger)
- func (r *AuthRegistry) Unregister(securityType uint8) bool
- func (r *AuthRegistry) ValidateAuthMethod(auth ClientAuth) error
- type BellMessage
- type ButtonMask
- type ClientAuth
- type ClientAuthNone
- type ClientConfig
- type ClientConn
- func (c *ClientConn) Close() error
- func (c *ClientConn) CutText(text string) error
- func (c *ClientConn) FramebufferUpdateRequest(incremental bool, x, y, width, height uint16) error
- func (c *ClientConn) GetDesktopName() string
- func (c *ClientConn) GetFrameBufferSize() (width, height uint16)
- func (c *ClientConn) GetPixelFormat() PixelFormat
- func (c *ClientConn) KeyEvent(keysym uint32, down bool) error
- func (c *ClientConn) PointerEvent(mask ButtonMask, x, y uint16) error
- func (c *ClientConn) SetEncodings(encs []Encoding) error
- func (c *ClientConn) SetPixelFormat(format *PixelFormat) error
- type ClientOption
- func WithAuth(auth ...ClientAuth) ClientOption
- func WithAuthRegistry(registry *AuthRegistry) ClientOption
- func WithConnectTimeout(timeout time.Duration) ClientOption
- func WithExclusive(exclusive bool) ClientOption
- func WithLogger(logger Logger) ClientOption
- func WithMetrics(metrics MetricsCollector) ClientOption
- func WithReadTimeout(timeout time.Duration) ClientOption
- func WithServerMessageChannel(ch chan<- ServerMessage) ClientOption
- func WithServerMessages(messages ...ServerMessage) ClientOption
- func WithTimeout(timeout time.Duration) ClientOption
- func WithWriteTimeout(timeout time.Duration) ClientOption
- type Color
- type ColorFormatConverter
- func (c *ColorFormatConverter) ColorToHSV(color Color) (h, s, v float64)
- func (c *ColorFormatConverter) ColorToRGB8(color Color) (r, g, b uint8)
- func (c *ColorFormatConverter) ColorToRGB16(color Color) (r, g, b uint16)
- func (c *ColorFormatConverter) HSVToColor(h, s, v float64) Color
- func (c *ColorFormatConverter) RGB8ToColor(r, g, b uint8) Color
- func (c *ColorFormatConverter) RGB16ToColor(r, g, b uint16) Color
- type ColorMap
- func (cm *ColorMap) Copy() *ColorMap
- func (cm *ColorMap) FromArray(colors [ColorMapSize]Color)
- func (cm *ColorMap) Get(index uint8) Color
- func (cm *ColorMap) GetRange(startIndex uint16, count uint16) ([]Color, error)
- func (cm *ColorMap) Set(index uint8, color Color)
- func (cm *ColorMap) SetRange(startIndex uint16, colors []Color) error
- func (cm *ColorMap) ToArray() [ColorMapSize]Color
- type ColorMapValidationError
- type CopyRectEncoding
- type CursorPseudoEncoding
- type DesktopSizePseudoEncoding
- type Encoding
- type ErrorCode
- type Field
- type FramebufferUpdateMessage
- type HextileEncoding
- type HextileSubrectangle
- type HextileTile
- type InputValidator
- func (iv *InputValidator) SanitizeText(text string) string
- func (iv *InputValidator) ValidateBinaryData(data []byte, expectedLength, maxLength int) error
- func (iv *InputValidator) ValidateColorMapEntries(firstColor, numColors, maxColors uint16) error
- func (iv *InputValidator) ValidateEncodingType(encodingType int32) error
- func (iv *InputValidator) ValidateFramebufferDimensions(width, height uint16) error
- func (iv *InputValidator) ValidateKeySymbol(keysym uint32) error
- func (iv *InputValidator) ValidateMessageLength(length uint32, maxLength uint32) error
- func (iv *InputValidator) ValidatePixelFormat(pf *PixelFormat) error
- func (iv *InputValidator) ValidatePointerPosition(x, y, fbWidth, fbHeight uint16) error
- func (iv *InputValidator) ValidateProtocolVersion(version string) error
- func (iv *InputValidator) ValidateRectangle(x, y, width, height, fbWidth, fbHeight uint16) error
- func (iv *InputValidator) ValidateSecurityType(securityType uint8) error
- func (iv *InputValidator) ValidateSecurityTypes(securityTypes []uint8) error
- func (iv *InputValidator) ValidateTextData(text string, maxLength int) error
- type Logger
- type MemoryProtection
- type MetricsCollector
- type NoOpLogger
- type NoOpMetrics
- type PasswordAuth
- type PixelFormat
- type PixelFormatConverter
- func (c *PixelFormatConverter) BytesPerPixel() int
- func (c *PixelFormatConverter) CreatePixel(r, g, b uint8) uint32
- func (c *PixelFormatConverter) ExtractRGB(pixel uint32) (r, g, b uint8)
- func (c *PixelFormatConverter) ReadPixel(r io.Reader) (uint32, error)
- func (c *PixelFormatConverter) WritePixel(w io.Writer, pixel uint32) error
- type PixelFormatValidationError
- type PixelReader
- type ProtectedBytes
- type PseudoEncoding
- type RREEncoding
- type RRESubrectangle
- type RawEncoding
- type Rectangle
- type SecureDESCipher
- type SecureMemory
- type SecureRandom
- type ServerCutTextMessage
- type ServerMessage
- type SetColorMapEntriesMessage
- type StandardLogger
- type TimingProtection
- type VNCError
Examples ¶
Constants ¶
const ( ColorMapSize = 256 MaxClipboardLength = 1024 * 1024 Latin1MaxCodePoint = 255 MaxRectanglesPerUpdate = 10000 MaxServerClipboardLength = 10 * 1024 * 1024 )
VNC protocol constants.
const ( HextileRaw = 1 HextileBackgroundSpecified = 2 HextileForegroundSpecified = 4 HextileAnySubrects = 8 HextileSubrectsColoured = 16 HextileTileSize = 16 MaxSubrectsPerTile = 255 )
Hextile encoding constants as defined in RFC 6143.
const ( VNCChallengeSize = 16 DESKeySize = 8 VNCMaxPasswordLength = 8 )
VNC security constants.
Variables ¶
var ( // ColorBlack represents pure black (0, 0, 0). ColorBlack = Color{R: 0, G: 0, B: 0} // ColorWhite represents pure white (65535, 65535, 65535). ColorWhite = Color{R: 65535, G: 65535, B: 65535} // ColorRed represents pure red (65535, 0, 0). ColorRed = Color{R: 65535, G: 0, B: 0} // ColorGreen represents pure green (0, 65535, 0). ColorGreen = Color{R: 0, G: 65535, B: 0} // ColorBlue represents pure blue (0, 0, 65535). ColorBlue = Color{R: 0, G: 0, B: 65535} // ColorYellow represents pure yellow (65535, 65535, 0). ColorYellow = Color{R: 65535, G: 65535, B: 0} // ColorMagenta represents pure magenta (65535, 0, 65535). ColorMagenta = Color{R: 65535, G: 0, B: 65535} // ColorCyan represents pure cyan (0, 65535, 65535). ColorCyan = Color{R: 0, G: 65535, B: 65535} )
Common color constants for convenience.
var ( // PixelFormat32BitRGBA represents high-quality 32-bit RGBA true color format. // This format provides the best color fidelity but uses the most bandwidth. PixelFormat32BitRGBA = &PixelFormat{ BPP: 32, Depth: 24, BigEndian: false, TrueColor: true, RedMax: 255, GreenMax: 255, BlueMax: 255, RedShift: 16, GreenShift: 8, BlueShift: 0, } // PixelFormat16BitRGB565 represents balanced 16-bit RGB565 true color format. // This format provides good color quality with moderate bandwidth usage. PixelFormat16BitRGB565 = &PixelFormat{ BPP: 16, Depth: 16, BigEndian: false, TrueColor: true, RedMax: 31, GreenMax: 63, BlueMax: 31, RedShift: 11, GreenShift: 5, BlueShift: 0, } // PixelFormat16BitRGB555 represents 16-bit RGB555 true color format. // This format provides balanced color with equal bits per color component. PixelFormat16BitRGB555 = &PixelFormat{ BPP: 16, Depth: 15, BigEndian: false, TrueColor: true, RedMax: 31, GreenMax: 31, BlueMax: 31, RedShift: 10, GreenShift: 5, BlueShift: 0, } // PixelFormat8BitIndexed represents bandwidth-efficient 8-bit indexed color format. // This format uses the least bandwidth but is limited to 256 simultaneous colors. PixelFormat8BitIndexed = &PixelFormat{ BPP: 8, Depth: 8, BigEndian: false, TrueColor: false, } )
Common pixel format presets for easy configuration.
Functions ¶
func ConvertPixelFormat ¶
func ConvertPixelFormat(ctx context.Context, srcData []byte, srcFormat, dstFormat *PixelFormat) ([]byte, error)
ConvertPixelFormat converts pixel data from one format to another. This is useful for format conversion during encoding/decoding operations.
func IsVNCError ¶
IsVNCError checks if an error is a VNCError and optionally matches specific error codes. If no codes are provided, returns true for any VNCError. If codes are provided, returns true only if the error matches one of the specified codes.
Types ¶
type AuthFactory ¶
type AuthFactory func() ClientAuth
AuthFactory is a function type that creates new instances of authentication methods.
type AuthRegistry ¶
type AuthRegistry struct {
// contains filtered or unexported fields
}
AuthRegistry manages available authentication methods.
func NewAuthRegistry ¶
func NewAuthRegistry() *AuthRegistry
NewAuthRegistry creates a new authentication registry with default authentication methods.
func (*AuthRegistry) CreateAuth ¶
func (r *AuthRegistry) CreateAuth(securityType uint8) (ClientAuth, error)
CreateAuth creates a new instance of the authentication method for the given security type.
func (*AuthRegistry) GetSupportedTypes ¶
func (r *AuthRegistry) GetSupportedTypes() []uint8
GetSupportedTypes returns a list of all supported security types.
func (*AuthRegistry) IsSupported ¶
func (r *AuthRegistry) IsSupported(securityType uint8) bool
IsSupported checks if a security type is supported by the registry.
func (*AuthRegistry) NegotiateAuth ¶
func (r *AuthRegistry) NegotiateAuth(ctx context.Context, serverTypes []uint8, preferredOrder []uint8) (ClientAuth, uint8, error)
NegotiateAuth performs authentication method negotiation between client and server.
func (*AuthRegistry) Register ¶
func (r *AuthRegistry) Register(securityType uint8, factory AuthFactory)
Register adds an authentication method factory to the registry.
func (*AuthRegistry) SetLogger ¶
func (r *AuthRegistry) SetLogger(logger Logger)
SetLogger sets the logger for the authentication registry.
func (*AuthRegistry) Unregister ¶
func (r *AuthRegistry) Unregister(securityType uint8) bool
Unregister removes an authentication method from the registry.
func (*AuthRegistry) ValidateAuthMethod ¶
func (r *AuthRegistry) ValidateAuthMethod(auth ClientAuth) error
ValidateAuthMethod performs validation on an authentication method instance.
type BellMessage ¶
type BellMessage byte
BellMessage represents an audible bell notification from the server (message type 2). This message indicates that the server wants the client to produce an audible alert, typically corresponding to a system bell or notification sound on the remote desktop.
As defined in RFC 6143 Section 7.6.3, this is a simple notification message with no additional data. The client should respond by producing an appropriate audible alert using the local system's notification mechanisms.
The message contains no payload data beyond the message type identifier. Applications can handle this message to provide audio feedback, visual notifications, or other appropriate user alerts.
Example usage:
switch msg := serverMsg.(type) {
case *BellMessage:
// Play system bell sound or show notification
fmt.Println("Bell notification received")
// Could trigger: system beep, notification popup, etc.
}
func (*BellMessage) Read ¶
func (*BellMessage) Read(*ClientConn, io.Reader) (ServerMessage, error)
Read processes a bell message from the server.
func (*BellMessage) Type ¶
func (*BellMessage) Type() uint8
Type returns the message type identifier for bell messages.
type ButtonMask ¶
type ButtonMask uint8
ButtonMask represents the state of pointer buttons in a VNC pointer event.
const ( ButtonLeft ButtonMask = 1 << iota ButtonMiddle ButtonRight Button4 Button5 Button6 Button7 Button8 )
Button mask constants for standard mouse buttons and scroll wheel events.
type ClientAuth ¶
type ClientAuth interface {
SecurityType() uint8
Handshake(ctx context.Context, conn net.Conn) error
String() string
}
ClientAuth defines the interface for VNC authentication methods.
type ClientAuthNone ¶
type ClientAuthNone struct {
// contains filtered or unexported fields
}
ClientAuthNone implements the "None" authentication method (security type 1).
func (*ClientAuthNone) SecurityType ¶
func (c *ClientAuthNone) SecurityType() uint8
SecurityType returns the security type identifier for None authentication.
func (*ClientAuthNone) SetLogger ¶
func (c *ClientAuthNone) SetLogger(logger Logger)
SetLogger sets the logger for the authentication method.
func (*ClientAuthNone) String ¶
func (c *ClientAuthNone) String() string
String returns a human-readable description of the authentication method.
type ClientConfig ¶
type ClientConfig struct {
// Auth specifies the authentication methods supported by the client.
Auth []ClientAuth
// Exclusive determines whether this client requests exclusive access.
Exclusive bool
// ServerMessageCh is the channel where server messages will be delivered.
ServerMessageCh chan<- ServerMessage
// ServerMessages specifies additional custom server message types.
ServerMessages []ServerMessage
// Logger specifies the logger instance to use for connection logging.
Logger Logger
// AuthRegistry specifies the authentication registry to use.
AuthRegistry *AuthRegistry
// ConnectTimeout specifies the timeout for the initial connection handshake.
ConnectTimeout time.Duration
// ReadTimeout specifies the timeout for individual read operations.
ReadTimeout time.Duration
// WriteTimeout specifies the timeout for individual write operations.
WriteTimeout time.Duration
// Metrics specifies the metrics collector to use for connection monitoring.
Metrics MetricsCollector
}
ClientConfig configures VNC client connection behavior.
type ClientConn ¶
type ClientConn struct {
// ColorMap contains the color map for indexed color modes.
ColorMap [ColorMapSize]Color
// Encs contains the list of encodings supported by this client.
Encs []Encoding
// FrameBufferWidth is the width of the remote framebuffer in pixels.
FrameBufferWidth uint16
// FrameBufferHeight is the height of the remote framebuffer in pixels.
FrameBufferHeight uint16
// DesktopName is the human-readable name of the desktop.
DesktopName string
// PixelFormat describes the format of pixel data used in this connection.
PixelFormat PixelFormat
// contains filtered or unexported fields
}
ClientConn represents an active VNC client connection. Safe for concurrent use for sending client messages.
func Client
deprecated
func Client(c net.Conn, cfg *ClientConfig) (*ClientConn, error)
Client establishes a VNC client connection with the provided configuration. Performs complete handshake and starts background message processing.
Deprecated: Use ClientWithContext for better cancellation support.
func ClientWithContext ¶
func ClientWithContext(ctx context.Context, c net.Conn, cfg *ClientConfig) (*ClientConn, error)
ClientWithContext establishes a VNC client connection with context support. Performs complete handshake including protocol negotiation, security, and initialization.
func ClientWithOptions ¶
func ClientWithOptions(ctx context.Context, c net.Conn, options ...ClientOption) (*ClientConn, error)
ClientWithOptions establishes a VNC client connection using functional options for configuration. This provides a modern, flexible way to configure client connections while maintaining backward compatibility. Options are applied in the order they are provided.
Parameters:
- ctx: Context for cancellation and timeout control
- c: An established network connection to a VNC server (typically TCP)
- options: Functional options for configuring the client behavior
Returns:
- *ClientConn: A configured VNC client connection ready for use
- error: Any error that occurred during the handshake process
Example usage:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
conn, err := net.Dial("tcp", "localhost:5900")
if err != nil {
log.Fatal(err)
}
defer conn.Close()
client, err := ClientWithOptions(ctx, conn,
WithAuth(&PasswordAuth{Password: "secret"}),
WithExclusive(true),
WithLogger(&StandardLogger{}),
WithTimeout(10*time.Second),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
Advanced configuration example:
msgCh := make(chan ServerMessage, 100)
registry := NewAuthRegistry()
registry.Register(16, func() ClientAuth { return &CustomAuth{} })
client, err := ClientWithOptions(ctx, conn,
WithAuthRegistry(registry),
WithServerMessageChannel(msgCh),
WithConnectTimeout(30*time.Second),
WithReadTimeout(5*time.Second),
WithWriteTimeout(5*time.Second),
WithMetrics(&PrometheusMetrics{}),
)
The functional options approach provides several benefits: - Type-safe configuration with compile-time validation - Extensible without breaking existing code - Self-documenting through option names - Composable and reusable option sets - Optional parameters with sensible defaults.
func (*ClientConn) Close ¶
func (c *ClientConn) Close() error
Close terminates the VNC connection and releases associated resources. This method closes the underlying network connection, cancels the connection context, and will cause the message processing goroutine to exit and close the server message channel.
It is safe to call Close multiple times; subsequent calls will have no effect. After calling Close, the ClientConn should not be used for any other operations.
Returns:
- error: Any error that occurred while closing the network connection
Example usage:
client, err := Client(conn, config)
if err != nil {
log.Fatal(err)
}
defer client.Close() // Ensure cleanup
// Use the client...
// Explicit close when done
if err := client.Close(); err != nil {
log.Printf("Error closing VNC connection: %v", err)
}
func (*ClientConn) CutText ¶
func (c *ClientConn) CutText(text string) error
CutText sends clipboard text from the client to the VNC server. This method implements the ClientCutText message as defined in RFC 6143 Section 7.5.6, allowing the client to share clipboard content with the remote desktop.
The text must contain only Latin-1 characters (Unicode code points 0-255). Characters outside this range will cause a validation error. This restriction is imposed by the VNC protocol specification for compatibility across different systems and character encodings.
Parameters:
- text: The clipboard text to send to the server (Latin-1 characters only)
Returns:
- error: ValidationError if text contains invalid characters, NetworkError for transmission issues
Example usage:
// Send simple ASCII text
err := client.CutText("Hello, World!")
if err != nil {
log.Printf("Failed to send clipboard text: %v", err)
}
// Handle clipboard synchronization
clipboardText := getLocalClipboard()
if isValidLatin1(clipboardText) {
client.CutText(clipboardText)
}
Character validation: The method validates each character to ensure it falls within the Latin-1 character set (0-255). Characters beyond this range will result in an error:
// This will fail - contains Unicode characters outside Latin-1
err := client.CutText("Hello 世界") // Contains Chinese characters
if err != nil {
// Handle validation error
}
Security considerations: Clipboard sharing can potentially expose sensitive information. Applications should consider whether clipboard synchronization is appropriate for their security requirements and may want to filter or sanitize clipboard content.
func (*ClientConn) FramebufferUpdateRequest ¶
func (c *ClientConn) FramebufferUpdateRequest(incremental bool, x, y, width, height uint16) error
FramebufferUpdateRequest requests a framebuffer update from the VNC server. This method implements the FramebufferUpdateRequest message as defined in RFC 6143 Section 7.5.3, asking the server to send pixel data for a specified rectangular region of the desktop.
The server will respond asynchronously with a FramebufferUpdateMessage containing the requested pixel data. There is no guarantee about response timing, and the server may combine multiple requests or send partial updates.
Parameters:
- incremental: If true, only send pixels that have changed since the last update. If false, send all pixels in the specified rectangle regardless of changes.
- x, y: The top-left corner coordinates of the requested rectangle (0-based)
- width, height: The dimensions of the requested rectangle in pixels
Returns:
- error: NetworkError if the request cannot be sent to the server
Example usage:
// Request full screen update (non-incremental)
err := client.FramebufferUpdateRequest(false, 0, 0,
client.FrameBufferWidth, client.FrameBufferHeight)
if err != nil {
log.Printf("Failed to request framebuffer update: %v", err)
}
// Request incremental update for a specific region
err = client.FramebufferUpdateRequest(true, 100, 100, 200, 150)
if err != nil {
log.Printf("Failed to request incremental update: %v", err)
}
Update strategies:
// Initial full screen capture
client.FramebufferUpdateRequest(false, 0, 0, width, height)
// Continuous incremental updates for live viewing
ticker := time.NewTicker(33 * time.Millisecond) // ~30 FPS
go func() {
for range ticker.C {
client.FramebufferUpdateRequest(true, 0, 0, width, height)
}
}()
Performance considerations: - Incremental updates are more bandwidth-efficient for live viewing - Non-incremental updates ensure complete accuracy but use more bandwidth - Request frequency should balance responsiveness with network/CPU usage - Large rectangles may be split by the server into multiple smaller updates.
func (*ClientConn) GetDesktopName ¶
func (c *ClientConn) GetDesktopName() string
GetDesktopName returns the desktop name in a thread-safe manner.
func (*ClientConn) GetFrameBufferSize ¶
func (c *ClientConn) GetFrameBufferSize() (width, height uint16)
GetFrameBufferSize returns the current framebuffer dimensions in a thread-safe manner.
func (*ClientConn) GetPixelFormat ¶
func (c *ClientConn) GetPixelFormat() PixelFormat
GetPixelFormat returns a copy of the current pixel format in a thread-safe manner.
func (*ClientConn) KeyEvent ¶
func (c *ClientConn) KeyEvent(keysym uint32, down bool) error
KeyEvent sends a keyboard key press or release event to the VNC server. This method implements the KeyEvent message as defined in RFC 6143 Section 7.5.4, allowing the client to send keyboard input to the remote desktop.
Keys are identified using X Window System keysym values, which provide a standardized way to represent keyboard keys across different platforms and keyboard layouts. To simulate a complete key press, you must send both a key down event (down=true) followed by a key up event (down=false).
Parameters:
- keysym: The X11 keysym value identifying the key (see X11/keysymdef.h)
- down: true for key press, false for key release
Returns:
- error: NetworkError if the event cannot be sent to the server
Example usage:
// Send the letter 'A' (complete key press and release) const XK_A = 0x0041 client.KeyEvent(XK_A, true) // Key down client.KeyEvent(XK_A, false) // Key up // Send Enter key const XK_Return = 0xff0d client.KeyEvent(XK_Return, true) client.KeyEvent(XK_Return, false) // Send Ctrl+C (hold Ctrl, press C, release C, release Ctrl) const XK_Control_L = 0xffe3 const XK_c = 0x0063 client.KeyEvent(XK_Control_L, true) // Ctrl down client.KeyEvent(XK_c, true) // C down client.KeyEvent(XK_c, false) // C up client.KeyEvent(XK_Control_L, false) // Ctrl up
Common keysym values:
// Letters (uppercase when Shift is held) XK_a = 0x0061, XK_b = 0x0062, ..., XK_z = 0x007a XK_A = 0x0041, XK_B = 0x0042, ..., XK_Z = 0x005a // Numbers XK_0 = 0x0030, XK_1 = 0x0031, ..., XK_9 = 0x0039 // Special keys XK_Return = 0xff0d // Enter XK_Escape = 0xff1b // Escape XK_BackSpace = 0xff08 // Backspace XK_Tab = 0xff09 // Tab XK_space = 0x0020 // Space // Modifier keys XK_Shift_L = 0xffe1 // Left Shift XK_Control_L = 0xffe3 // Left Ctrl XK_Alt_L = 0xffe9 // Left Alt
Key sequence helper:
func (c *ClientConn) SendKey(keysym uint32) error {
if err := c.KeyEvent(keysym, true); err != nil {
return err
}
return c.KeyEvent(keysym, false)
}
For a complete reference of keysym values, consult the X11 keysym definitions or online keysym references. The values are standardized and consistent across VNC implementations.
func (*ClientConn) PointerEvent ¶
func (c *ClientConn) PointerEvent(mask ButtonMask, x, y uint16) error
PointerEvent sends mouse movement and button state to the VNC server. This method implements the PointerEvent message as defined in RFC 6143 Section 7.5.5, allowing the client to send mouse input including movement, clicks, and scroll events to the remote desktop.
The button mask represents the current state of all mouse buttons simultaneously. When a bit is set (1), the corresponding button is pressed; when clear (0), the button is released. This allows for complex interactions like drag operations where multiple buttons may be held simultaneously.
Parameters:
- mask: Bitmask indicating which buttons are currently pressed (see ButtonMask constants)
- x, y: Mouse cursor coordinates in pixels (0-based, relative to framebuffer)
Returns:
- error: NetworkError if the event cannot be sent to the server
Example usage:
// Simple mouse movement (no buttons pressed) err := client.PointerEvent(0, 100, 200) // Left mouse button click at coordinates (150, 300) client.PointerEvent(ButtonLeft, 150, 300) // Button down client.PointerEvent(0, 150, 300) // Button up // Right mouse button click client.PointerEvent(ButtonRight, 200, 100) // Right button down client.PointerEvent(0, 200, 100) // Button up // Drag operation (left button held while moving) client.PointerEvent(ButtonLeft, 100, 100) // Start drag client.PointerEvent(ButtonLeft, 120, 120) // Drag to new position client.PointerEvent(ButtonLeft, 140, 140) // Continue dragging client.PointerEvent(0, 140, 140) // End drag (release button)
Scroll wheel events:
// Scroll up (wheel away from user) client.PointerEvent(Button4, x, y) client.PointerEvent(0, x, y) // Scroll down (wheel toward user) client.PointerEvent(Button5, x, y) client.PointerEvent(0, x, y)
Multiple buttons simultaneously:
// Left and right buttons pressed together mask := ButtonLeft | ButtonRight client.PointerEvent(mask, x, y) client.PointerEvent(0, x, y) // Release both buttons
Helper functions for common operations:
func (c *ClientConn) MouseMove(x, y uint16) error {
return c.PointerEvent(0, x, y)
}
func (c *ClientConn) LeftClick(x, y uint16) error {
if err := c.PointerEvent(ButtonLeft, x, y); err != nil {
return err
}
return c.PointerEvent(0, x, y)
}
func (c *ClientConn) ScrollUp(x, y uint16) error {
if err := c.PointerEvent(Button4, x, y); err != nil {
return err
}
return c.PointerEvent(0, x, y)
}
Coordinate system: Mouse coordinates are relative to the framebuffer origin (0,0) at the top-left corner. Valid coordinates range from (0,0) to (FrameBufferWidth-1, FrameBufferHeight-1). Coordinates outside this range may be clamped or ignored by the server.
func (*ClientConn) SetEncodings ¶
func (c *ClientConn) SetEncodings(encs []Encoding) error
SetEncodings configures which encoding types the client supports for framebuffer updates. This method implements the SetEncodings message as defined in RFC 6143 Section 7.5.2, informing the server about the client's encoding capabilities and preferences.
The server will use this information to select appropriate encodings when sending framebuffer updates, potentially choosing different encodings for different rectangles based on content characteristics and bandwidth considerations.
The encodings are specified in preference order - the server will prefer encodings that appear earlier in the slice when multiple options are suitable. The Raw encoding is always supported as a fallback and does not need to be explicitly included.
Parameters:
- encs: Slice of supported encodings in preference order (most preferred first)
Returns:
- error: NetworkError if the encoding list cannot be sent to the server
Example usage:
// Basic encoding support (Raw is always supported)
encodings := []Encoding{
&RawEncoding{},
}
err := client.SetEncodings(encodings)
// Multiple encodings in preference order
encodings := []Encoding{
&HextileEncoding{}, // Preferred for mixed content
&CopyRectEncoding{}, // Efficient for window movement
&RREEncoding{}, // Good for simple graphics
&RawEncoding{}, // Fallback for complex content
}
err := client.SetEncodings(encodings)
Encoding selection strategy:
// Optimize for bandwidth (slower connections)
encodings := []Encoding{
&ZRLEEncoding{}, // Best compression
&HextileEncoding{}, // Good compression
&RREEncoding{}, // Moderate compression
&RawEncoding{}, // No compression (fallback)
}
// Optimize for speed (fast connections)
encodings := []Encoding{
&CopyRectEncoding{}, // Fastest for window operations
&RawEncoding{}, // Fast for complex content
&HextileEncoding{}, // Moderate speed/compression balance
}
Pseudo-encodings for additional features:
encodings := []Encoding{
&HextileEncoding{},
&RawEncoding{},
&CursorPseudoEncoding{}, // Client-side cursor rendering
&DesktopSizePseudoEncoding{}, // Dynamic desktop resizing
}
Important considerations: - The provided slice should not be modified after calling this method - Raw encoding support is mandatory and always available as fallback - Pseudo-encodings provide additional features beyond pixel data - Encoding preferences affect bandwidth usage and rendering performance - Some servers may not support all encoding types
The method updates the connection's Encs field to reflect the configured encodings, which can be inspected to verify the current encoding configuration.
func (*ClientConn) SetPixelFormat ¶
func (c *ClientConn) SetPixelFormat(format *PixelFormat) error
SetPixelFormat configures the pixel format used for framebuffer updates from the server. This method implements the SetPixelFormat message as defined in RFC 6143 Section 7.5.1, allowing the client to specify how pixel color data should be encoded in subsequent framebuffer updates.
Changing the pixel format affects all future framebuffer updates and can be used to optimize for different display characteristics, color depths, or bandwidth requirements. The server will convert its internal pixel representation to match the requested format.
When the pixel format is changed to indexed color mode (TrueColor=false), the connection's color map is automatically reset, and the server may send SetColorMapEntries messages to populate the new color map.
Parameters:
- format: The desired pixel format specification
Returns:
- error: EncodingError if the format cannot be encoded, NetworkError for transmission issues
Example usage:
// 32-bit true color RGBA (high quality, more bandwidth)
format := &PixelFormat{
BPP: 32, Depth: 24, BigEndian: false, TrueColor: true,
RedMax: 255, GreenMax: 255, BlueMax: 255,
RedShift: 16, GreenShift: 8, BlueShift: 0,
}
err := client.SetPixelFormat(format)
// 16-bit true color RGB565 (balanced quality/bandwidth)
format := &PixelFormat{
BPP: 16, Depth: 16, BigEndian: false, TrueColor: true,
RedMax: 31, GreenMax: 63, BlueMax: 31,
RedShift: 11, GreenShift: 5, BlueShift: 0,
}
err := client.SetPixelFormat(format)
// 8-bit indexed color (low bandwidth, limited colors)
format := &PixelFormat{
BPP: 8, Depth: 8, BigEndian: false, TrueColor: false,
}
err := client.SetPixelFormat(format)
Bandwidth optimization:
// For slow connections - use 8-bit indexed color
lowBandwidthFormat := &PixelFormat{
BPP: 8, Depth: 8, TrueColor: false,
}
// For fast connections - use 32-bit true color
highQualityFormat := &PixelFormat{
BPP: 32, Depth: 24, TrueColor: true,
RedMax: 255, GreenMax: 255, BlueMax: 255,
RedShift: 16, GreenShift: 8, BlueShift: 0,
}
Color depth considerations: - 32-bit: Best quality, highest bandwidth usage - 16-bit: Good quality, moderate bandwidth usage - 8-bit: Limited colors (256), lowest bandwidth usage - True color: Direct RGB values, more colors available - Indexed color: Uses color map, limited to 256 simultaneous colors
Performance impact: - Higher bit depths provide better color accuracy but use more bandwidth - Indexed color modes require color map synchronization - Format changes may cause temporary visual artifacts during transition - Some servers may perform better with specific pixel formats
The method automatically resets the color map when switching to indexed color mode, as the previous color map may not be compatible with the new pixel format.
type ClientOption ¶
type ClientOption func(*ClientConfig)
ClientOption represents a functional option for configuring a VNC client connection.
func WithAuth ¶
func WithAuth(auth ...ClientAuth) ClientOption
WithAuth sets the authentication methods for the client connection. The methods are tried in the order provided during server negotiation.
func WithAuthRegistry ¶
func WithAuthRegistry(registry *AuthRegistry) ClientOption
WithAuthRegistry sets a custom authentication registry for the client. This allows registration of custom authentication methods beyond the defaults.
func WithConnectTimeout ¶
func WithConnectTimeout(timeout time.Duration) ClientOption
WithConnectTimeout sets the timeout for the initial connection handshake. This includes protocol negotiation, security handshake, and initialization.
func WithExclusive ¶
func WithExclusive(exclusive bool) ClientOption
WithExclusive sets whether the client should request exclusive access to the server. When true, other clients will be disconnected when this client connects.
func WithLogger ¶
func WithLogger(logger Logger) ClientOption
WithLogger sets the logger for the client connection. Use NoOpLogger to disable logging or provide a custom implementation.
func WithMetrics ¶
func WithMetrics(metrics MetricsCollector) ClientOption
WithMetrics sets the metrics collector for connection monitoring. Use NoOpMetrics to disable metrics collection or provide a custom implementation.
func WithReadTimeout ¶
func WithReadTimeout(timeout time.Duration) ClientOption
WithReadTimeout sets the timeout for individual read operations. This applies to reading server messages and framebuffer data.
func WithServerMessageChannel ¶
func WithServerMessageChannel(ch chan<- ServerMessage) ClientOption
WithServerMessageChannel sets the channel where server messages will be delivered. The channel should be buffered to prevent blocking the message processing loop.
func WithServerMessages ¶
func WithServerMessages(messages ...ServerMessage) ClientOption
WithServerMessages sets additional custom server message types. These will be registered alongside the standard VNC message types.
func WithTimeout ¶
func WithTimeout(timeout time.Duration) ClientOption
WithTimeout sets both read and write timeouts to the same value. This is a convenience function for setting both timeouts at once.
func WithWriteTimeout ¶
func WithWriteTimeout(timeout time.Duration) ClientOption
WithWriteTimeout sets the timeout for individual write operations. This applies to sending client messages like key events and pointer events.
type Color ¶
type Color struct {
// R is the red color component value (0-65535).
R uint16
// G is the green color component value (0-65535).
G uint16
// B is the blue color component value (0-65535).
B uint16
}
Color represents an RGB color value used in VNC color maps and pixel data.
type ColorFormatConverter ¶
type ColorFormatConverter struct{}
ColorFormatConverter provides utilities for converting between different color formats and performing color space transformations.
func NewColorFormatConverter ¶
func NewColorFormatConverter() *ColorFormatConverter
NewColorFormatConverter creates a new color format converter. Used for converting between different color formats and performing color space transformations.
func (*ColorFormatConverter) ColorToHSV ¶
func (c *ColorFormatConverter) ColorToHSV(color Color) (h, s, v float64)
ColorToHSV converts RGB Color to HSV (Hue, Saturation, Value). Returns H in degrees (0-360), S and V as percentages (0-100).
func (*ColorFormatConverter) ColorToRGB8 ¶
func (c *ColorFormatConverter) ColorToRGB8(color Color) (r, g, b uint8)
ColorToRGB8 converts a 16-bit Color to 8-bit RGB values.
func (*ColorFormatConverter) ColorToRGB16 ¶
func (c *ColorFormatConverter) ColorToRGB16(color Color) (r, g, b uint16)
ColorToRGB16 extracts 16-bit RGB values from a Color.
func (*ColorFormatConverter) HSVToColor ¶
func (c *ColorFormatConverter) HSVToColor(h, s, v float64) Color
HSVToColor converts HSV (Hue, Saturation, Value) to RGB Color. H is in degrees (0-360), S and V are percentages (0-100).
func (*ColorFormatConverter) RGB8ToColor ¶
func (c *ColorFormatConverter) RGB8ToColor(r, g, b uint8) Color
RGB8ToColor converts 8-bit RGB values to a 16-bit Color.
func (*ColorFormatConverter) RGB16ToColor ¶
func (c *ColorFormatConverter) RGB16ToColor(r, g, b uint16) Color
RGB16ToColor converts 16-bit RGB values to a Color.
type ColorMap ¶
type ColorMap struct {
// contains filtered or unexported fields
}
ColorMap represents a thread-safe color map for indexed color modes. It provides efficient access and updates with proper synchronization for concurrent operations.
func NewColorMap ¶
func NewColorMap() *ColorMap
NewColorMap creates a new color map initialized with default grayscale colors. The default color map provides a reasonable fallback for indexed color modes.
func (*ColorMap) FromArray ¶
func (cm *ColorMap) FromArray(colors [ColorMapSize]Color)
FromArray updates the color map from a fixed-size array.
func (*ColorMap) GetRange ¶
GetRange retrieves multiple consecutive color map entries starting at the specified index. This method is thread-safe and provides efficient bulk access.
func (*ColorMap) SetRange ¶
SetRange updates multiple consecutive color map entries starting at the specified index. This method is thread-safe and provides efficient bulk updates.
func (*ColorMap) ToArray ¶
func (cm *ColorMap) ToArray() [ColorMapSize]Color
ToArray returns the color map as a fixed-size array.
type ColorMapValidationError ¶
ColorMapValidationError represents a color map validation error with detailed context.
func (*ColorMapValidationError) Error ¶
func (e *ColorMapValidationError) Error() string
Error returns the formatted error message for color map validation errors.
type CopyRectEncoding ¶
type CopyRectEncoding struct {
// SrcX is the X coordinate of the source rectangle's top-left corner.
// This specifies the horizontal position within the framebuffer from
// which pixels should be copied to the destination rectangle.
SrcX uint16
// SrcY is the Y coordinate of the source rectangle's top-left corner.
// This specifies the vertical position within the framebuffer from
// which pixels should be copied to the destination rectangle.
SrcY uint16
}
CopyRectEncoding represents the CopyRect encoding as defined in RFC 6143 Section 7.7.2. This encoding is used to efficiently update screen regions by copying pixel data from another location within the same framebuffer, rather than transmitting new pixel data.
CopyRect is particularly efficient for operations like window movement, scrolling, or any scenario where screen content is moved from one location to another without modification. Instead of sending the actual pixel data, the server only needs to send the source coordinates from which to copy the pixels.
The encoding provides significant bandwidth savings when large areas of the screen are moved, as only 4 bytes of coordinate data are transmitted regardless of the rectangle size, compared to width × height × bytes-per-pixel for raw encoding.
Example usage scenarios: - Moving windows across the desktop - Scrolling content within applications - Drag and drop operations - Any operation that relocates existing screen content
Wire format: The CopyRect encoding data consists of exactly 4 bytes:
[2 bytes] - Source X coordinate (big-endian uint16) [2 bytes] - Source Y coordinate (big-endian uint16)
The source coordinates specify the top-left corner of the source rectangle from which pixels should be copied. The dimensions of the source rectangle are identical to the destination rectangle specified in the Rectangle header.
func (*CopyRectEncoding) Read ¶
func (*CopyRectEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error)
Read decodes CopyRect encoding data from the server for the specified rectangle. This method implements the Encoding interface and processes CopyRect encoding as defined in RFC 6143 Section 7.7.2. It reads the source coordinates from which pixels should be copied within the framebuffer.
The CopyRect encoding is unique among VNC encodings because it doesn't contain actual pixel data. Instead, it specifies coordinates within the existing framebuffer from which to copy pixels to the destination rectangle.
Parameters:
- c: The client connection (unused for CopyRect but required by interface)
- rect: The destination rectangle specifying where the copied pixels should be placed
- r: Reader containing the CopyRect encoding data (4 bytes: source X and Y coordinates)
Returns:
- Encoding: A new CopyRectEncoding instance containing the source coordinates
- error: EncodingError if the coordinate data cannot be read
Example usage:
// This method is typically called by the VNC client's message processing loop
enc := &CopyRectEncoding{}
decodedEnc, err := enc.Read(clientConn, rectangle, dataReader)
if err != nil {
log.Printf("Failed to decode CopyRect encoding: %v", err)
return
}
// Process the CopyRect operation
copyRectEnc := decodedEnc.(*CopyRectEncoding)
fmt.Printf("Copy from (%d,%d) to (%d,%d) size %dx%d\n",
copyRectEnc.SrcX, copyRectEnc.SrcY,
rectangle.X, rectangle.Y,
rectangle.Width, rectangle.Height)
// Perform the copy operation on the local framebuffer
copyFramebufferRegion(
copyRectEnc.SrcX, copyRectEnc.SrcY, // Source
rectangle.X, rectangle.Y, // Destination
rectangle.Width, rectangle.Height) // Dimensions
Implementation considerations:
// The copy operation should handle overlapping regions correctly:
func copyFramebufferRegion(srcX, srcY, dstX, dstY, width, height uint16) {
// For overlapping regions, copy direction matters to avoid corruption
if srcY < dstY || (srcY == dstY && srcX < dstX) {
// Copy from bottom-right to top-left to avoid overwriting source data
copyBackward(srcX, srcY, dstX, dstY, width, height)
} else {
// Copy from top-left to bottom-right (normal case)
copyForward(srcX, srcY, dstX, dstY, width, height)
}
}
Validation considerations:
// Ensure source rectangle is within framebuffer bounds:
if copyRectEnc.SrcX + rectangle.Width > framebufferWidth ||
copyRectEnc.SrcY + rectangle.Height > framebufferHeight {
// Handle out-of-bounds source rectangle
return fmt.Errorf("source rectangle extends beyond framebuffer")
}
Performance characteristics: - Extremely efficient: only 4 bytes transmitted regardless of rectangle size - Copy operation performance depends on local framebuffer implementation - No network bandwidth used for pixel data transmission - Ideal for large rectangle moves (windows, scrolling)
Error conditions: The method returns an EncodingError if: - Insufficient data is available in the reader (less than 4 bytes) - I/O errors occur while reading coordinate data - Network connection issues during data reading
Wire format details:
// Byte layout in network stream: // Offset 0-1: Source X coordinate (big-endian uint16) // Offset 2-3: Source Y coordinate (big-endian uint16) // Total size: 4 bytes // Example: Copy from (100, 200) to destination rectangle // Wire bytes: [0x00, 0x64, 0x00, 0xC8] // | 100 | 200 |
func (*CopyRectEncoding) Type ¶
func (*CopyRectEncoding) Type() int32
Type returns the encoding type identifier for CopyRect encoding.
type CursorPseudoEncoding ¶
type CursorPseudoEncoding struct {
// Width is the width of the cursor in pixels.
// A width of 0 indicates that the cursor should be hidden.
Width uint16
// Height is the height of the cursor in pixels.
// A height of 0 indicates that the cursor should be hidden.
Height uint16
// HotspotX is the horizontal offset from the cursor's left edge to the hotspot.
// This represents the active point of the cursor (e.g., the tip of an arrow).
HotspotX uint16
// HotspotY is the vertical offset from the cursor's top edge to the hotspot.
// This represents the active point of the cursor (e.g., the tip of an arrow).
HotspotY uint16
// PixelData contains the cursor image data in the current pixel format.
// The data is organized in row-major order (left-to-right, top-to-bottom).
// The length is width × height × bytes-per-pixel.
PixelData []uint8
// MaskData contains the transparency mask for the cursor.
// Each bit represents one pixel: 1 = opaque, 0 = transparent.
// The data is organized in row-major order with bits packed into bytes.
// The length is ceil(width/8) × height bytes.
MaskData []uint8
}
CursorPseudoEncoding represents the Cursor pseudo-encoding as defined in RFC 6143. Allows the server to send cursor shape and hotspot information to the client.
func (*CursorPseudoEncoding) Handle ¶
func (cursor *CursorPseudoEncoding) Handle(c *ClientConn, rect *Rectangle) error
Handle processes the cursor pseudo-encoding by updating the client's cursor state. This method implements the PseudoEncoding interface and provides a way to handle cursor updates without requiring the application to manually process the encoding data.
The method updates the client connection's cursor state and can trigger cursor visibility changes or cursor shape updates based on the encoding data.
Parameters:
- c: The client connection to update
- rect: The rectangle containing cursor position and dimensions (unused for cursor)
Returns:
- error: Always returns nil for cursor pseudo-encoding (no processing errors expected)
Example usage:
// This method is typically called automatically by the VNC client
cursorEnc := &CursorPseudoEncoding{...}
err := cursorEnc.Handle(clientConn, rectangle)
if err != nil {
log.Printf("Failed to handle cursor update: %v", err)
}
Note: This is a basic implementation that logs the cursor update. Applications should extend this to integrate with their cursor management system.
func (*CursorPseudoEncoding) IsPseudo ¶
func (*CursorPseudoEncoding) IsPseudo() bool
IsPseudo returns true indicating this is a pseudo-encoding.
func (*CursorPseudoEncoding) Read ¶
func (*CursorPseudoEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error)
Read decodes Cursor pseudo-encoding data from the server for the specified rectangle. This method implements the Encoding interface and processes cursor shape data including pixel data, transparency mask, and hotspot coordinates.
The rectangle's X and Y coordinates represent the cursor hotspot offset, while Width and Height represent the cursor dimensions. A cursor with width=0 and height=0 indicates that the cursor should be hidden.
Parameters:
- c: The client connection providing pixel format information
- rect: The rectangle containing cursor dimensions and hotspot coordinates
- r: Reader containing the cursor pixel data and mask
Returns:
- Encoding: A new CursorPseudoEncoding instance containing the cursor data
- error: EncodingError if the cursor data cannot be read or is invalid
Example usage:
// This method is typically called by the VNC client's message processing loop
enc := &CursorPseudoEncoding{}
decodedEnc, err := enc.Read(clientConn, rectangle, dataReader)
if err != nil {
log.Printf("Failed to decode cursor pseudo-encoding: %v", err)
return
}
// Process the cursor update
cursorEnc := decodedEnc.(*CursorPseudoEncoding)
if cursorEnc.Width == 0 && cursorEnc.Height == 0 {
// Hide cursor
hideCursor()
} else {
// Update cursor shape
updateCursor(cursorEnc.PixelData, cursorEnc.MaskData,
cursorEnc.Width, cursorEnc.Height,
cursorEnc.HotspotX, cursorEnc.HotspotY)
}
Cursor rendering example:
func updateCursor(pixelData, maskData []uint8, width, height, hotspotX, hotspotY uint16) {
// Create cursor bitmap from pixel data and mask
cursor := createCursorBitmap(pixelData, maskData, width, height)
// Set cursor hotspot
cursor.SetHotspot(int(hotspotX), int(hotspotY))
// Apply cursor to window/display
window.SetCursor(cursor)
}
Mask processing example:
func processCursorMask(maskData []uint8, width, height uint16) []bool {
mask := make([]bool, width*height)
bytesPerRow := (width + 7) / 8
for y := uint16(0); y < height; y++ {
for x := uint16(0); x < width; x++ {
byteIndex := y*bytesPerRow + x/8
bitIndex := 7 - (x % 8)
mask[y*width+x] = (maskData[byteIndex] & (1 << bitIndex)) != 0
}
}
return mask
}
Error conditions: The method returns an EncodingError if: - Insufficient pixel data is available (less than width × height × bytes-per-pixel) - Insufficient mask data is available (less than ceil(width/8) × height) - I/O errors occur while reading cursor data - Invalid cursor dimensions (width or height too large).
func (*CursorPseudoEncoding) Type ¶
func (*CursorPseudoEncoding) Type() int32
Type returns the encoding type identifier for Cursor pseudo-encoding.
type DesktopSizePseudoEncoding ¶
type DesktopSizePseudoEncoding struct {
// Width is the new framebuffer width in pixels.
Width uint16
// Height is the new framebuffer height in pixels.
Height uint16
}
DesktopSizePseudoEncoding represents the DesktopSize pseudo-encoding. Allows the server to notify the client when the framebuffer size changes dynamically.
func (*DesktopSizePseudoEncoding) Handle ¶
func (desktop *DesktopSizePseudoEncoding) Handle(c *ClientConn, rect *Rectangle) error
Handle processes the desktop size pseudo-encoding by updating the client's framebuffer dimensions. This method implements the PseudoEncoding interface and automatically updates the client connection's framebuffer size when a desktop resize occurs.
The method updates the client connection's FrameBufferWidth and FrameBufferHeight fields to reflect the new desktop dimensions. Applications can then respond to the size change by resizing their display windows, updating viewports, or requesting new framebuffer data.
Parameters:
- c: The client connection to update with new framebuffer dimensions
- rect: The rectangle containing position information (unused for desktop size)
Returns:
- error: Always returns nil for desktop size pseudo-encoding (no processing errors expected)
Example usage:
// This method is typically called automatically by the VNC client
desktopSizeEnc := &DesktopSizePseudoEncoding{Width: 1920, Height: 1080}
err := desktopSizeEnc.Handle(clientConn, rectangle)
if err != nil {
log.Printf("Failed to handle desktop size update: %v", err)
}
// After handling, the client connection will have updated dimensions:
fmt.Printf("New framebuffer size: %dx%d\n",
clientConn.FrameBufferWidth, clientConn.FrameBufferHeight)
Integration with application:
// Applications can monitor for desktop size changes:
func monitorDesktopSize(client *ClientConn) {
oldWidth, oldHeight := client.FrameBufferWidth, client.FrameBufferHeight
// Check periodically or in message handler
if client.FrameBufferWidth != oldWidth || client.FrameBufferHeight != oldHeight {
// Handle desktop size change
handleDesktopResize(client.FrameBufferWidth, client.FrameBufferHeight)
oldWidth, oldHeight = client.FrameBufferWidth, client.FrameBufferHeight
}
}
Note: Applications should typically request a full framebuffer update after a desktop size change to refresh the display content for the new dimensions.
func (*DesktopSizePseudoEncoding) IsPseudo ¶
func (*DesktopSizePseudoEncoding) IsPseudo() bool
IsPseudo returns true indicating this is a pseudo-encoding.
func (*DesktopSizePseudoEncoding) Read ¶
func (*DesktopSizePseudoEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error)
Read decodes DesktopSize pseudo-encoding data from the server.
func (*DesktopSizePseudoEncoding) Type ¶
func (*DesktopSizePseudoEncoding) Type() int32
Type returns the encoding type identifier for DesktopSize pseudo-encoding.
type ErrorCode ¶
type ErrorCode int
ErrorCode represents specific error categories for VNC operations.
const ( // ErrProtocol indicates a protocol-level error. ErrProtocol ErrorCode = iota // ErrAuthentication indicates an authentication failure. ErrAuthentication // ErrEncoding indicates an encoding/decoding error. ErrEncoding // ErrNetwork indicates a network-related error. ErrNetwork // ErrConfiguration indicates a configuration error. ErrConfiguration // ErrTimeout indicates a timeout error. ErrTimeout // ErrValidation indicates input validation failure. ErrValidation // ErrUnsupported indicates an unsupported feature or operation. ErrUnsupported )
func GetErrorCode ¶
GetErrorCode extracts the error code from a VNCError. Returns the error code if the error is a VNCError, otherwise returns -1.
type Field ¶
type Field struct {
Key string
Value interface{}
}
Field represents a structured logging field with a key-value pair.
type FramebufferUpdateMessage ¶
type FramebufferUpdateMessage struct {
// Rectangles contains the list of screen rectangles being updated.
Rectangles []Rectangle
}
FramebufferUpdateMessage represents a framebuffer update from the server (message type 0).
func (*FramebufferUpdateMessage) Read ¶
func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error)
Read parses a FramebufferUpdate message from the server. This method implements the ServerMessage interface and processes framebuffer update data as defined in RFC 6143 Section 7.6.1. It reads one or more rectangles of pixel data, each potentially using different encoding methods.
The method handles the complete message parsing including:
- Reading the message padding and rectangle count
- For each rectangle: position, dimensions, and encoding type
- Delegating encoding-specific decoding to the appropriate Encoding implementation
- Building a complete FramebufferUpdateMessage with all decoded rectangles
Parameters:
- c: The client connection providing encoding support and state information
- r: Reader containing the message data (excluding the message type byte)
Returns:
- ServerMessage: A new FramebufferUpdateMessage containing all decoded rectangles
- error: NetworkError for I/O issues, UnsupportedError for unknown encodings, EncodingError for decoding failures
Example usage:
// This method is typically called by the VNC client's message processing loop
msg := &FramebufferUpdateMessage{}
parsedMsg, err := msg.Read(clientConn, messageReader)
if err != nil {
log.Printf("Failed to parse framebuffer update: %v", err)
return
}
// Process the parsed message
fbUpdate := parsedMsg.(*FramebufferUpdateMessage)
for _, rect := range fbUpdate.Rectangles {
fmt.Printf("Rectangle at (%d,%d) size %dx%d using encoding %d\n",
rect.X, rect.Y, rect.Width, rect.Height, rect.Enc.Type())
// Apply rectangle to local framebuffer
switch enc := rect.Enc.(type) {
case *RawEncoding:
// Handle raw pixel data
applyRawPixels(rect, enc.Colors)
case *CopyRectEncoding:
// Handle copy rectangle operation
applyCopyRect(rect, enc)
}
}
Encoding support:
// The method uses the client's configured encodings plus mandatory Raw encoding
// Supported encodings are determined by previous SetEncodings calls:
clientConn.SetEncodings([]Encoding{
&HextileEncoding{},
&CopyRectEncoding{},
&RawEncoding{}, // Always supported as fallback
})
Message structure:
// Wire format (after message type byte): // [1 byte] - Padding (ignored) // [2 bytes] - Number of rectangles (big-endian uint16) // For each rectangle: // [2 bytes] - X position (big-endian uint16) // [2 bytes] - Y position (big-endian uint16) // [2 bytes] - Width (big-endian uint16) // [2 bytes] - Height (big-endian uint16) // [4 bytes] - Encoding type (big-endian int32) // [variable] - Encoding-specific pixel data
Error handling: The method may return various error types:
- NetworkError: I/O failures reading message data
- UnsupportedError: Unknown or unsupported encoding type encountered
- EncodingError: Failure decoding rectangle pixel data
- All errors include context about which rectangle or operation failed
Performance considerations: - Large updates with many rectangles may consume significant memory - Different encodings have varying decode performance characteristics - Rectangle processing is sequential and may benefit from parallel decoding - Memory usage scales with total pixel count across all rectangles.
func (*FramebufferUpdateMessage) Type ¶
func (*FramebufferUpdateMessage) Type() uint8
Type returns the message type identifier for framebuffer update messages.
type HextileEncoding ¶
type HextileEncoding struct {
Tiles []HextileTile
}
HextileEncoding represents the Hextile encoding as defined in RFC 6143 Section 7.7.4. Hextile divides rectangles into 16x16 pixel tiles and applies different compression techniques to each tile based on its content.
func (*HextileEncoding) Read ¶
func (*HextileEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error)
Read decodes Hextile encoding data from the server.
- error: EncodingError if the data cannot be read or is invalid
Example usage:
// This method is typically called by the VNC client's message processing loop
enc := &HextileEncoding{}
decodedEnc, err := enc.Read(clientConn, rectangle, dataReader)
if err != nil {
log.Printf("Failed to decode Hextile encoding: %v", err)
return
}
// Process the Hextile encoding
hextileEnc := decodedEnc.(*HextileEncoding)
// Render each tile to the framebuffer
tileIndex := 0
for tileY := uint16(0); tileY < rectangle.Height; tileY += 16 {
for tileX := uint16(0); tileX < rectangle.Width; tileX += 16 {
tile := hextileEnc.Tiles[tileIndex]
renderTile(rectangle.X + tileX, rectangle.Y + tileY, tile)
tileIndex++
}
}
func (*HextileEncoding) Type ¶
func (*HextileEncoding) Type() int32
Type returns the encoding type identifier for Hextile encoding.
type HextileSubrectangle ¶
type HextileSubrectangle struct {
// Color is the color of this subrectangle.
Color Color
// X is the horizontal position within the tile (0-15).
X uint8
// Y is the vertical position within the tile (0-15).
Y uint8
// Width is the width of the subrectangle (1-16).
Width uint8
// Height is the height of the subrectangle (1-16).
Height uint8
}
HextileSubrectangle represents a colored subrectangle within a Hextile tile.
type HextileTile ¶
type HextileTile struct {
Width uint16
Height uint16
Background Color
// Foreground color for this tile.
Foreground Color
// Colors contains decoded pixel data for raw tiles.
Colors []Color
// Subrectangles contains colored subrectangles for this tile.
Subrectangles []HextileSubrectangle
}
HextileTile represents a single 16x16 (or smaller) tile within a Hextile encoding.
type InputValidator ¶
type InputValidator struct{}
InputValidator validates network input data and prevents protocol vulnerabilities.
func (*InputValidator) SanitizeText ¶
func (iv *InputValidator) SanitizeText(text string) string
SanitizeText sanitizes text data by removing or replacing potentially dangerous characters.
func (*InputValidator) ValidateBinaryData ¶
func (iv *InputValidator) ValidateBinaryData(data []byte, expectedLength, maxLength int) error
ValidateBinaryData validates binary data for protocol messages.
func (*InputValidator) ValidateColorMapEntries ¶
func (iv *InputValidator) ValidateColorMapEntries(firstColor, numColors, maxColors uint16) error
ValidateColorMapEntries validates color map entry data.
func (*InputValidator) ValidateEncodingType ¶
func (iv *InputValidator) ValidateEncodingType(encodingType int32) error
ValidateEncodingType validates encoding type values.
func (*InputValidator) ValidateFramebufferDimensions ¶
func (iv *InputValidator) ValidateFramebufferDimensions(width, height uint16) error
ValidateFramebufferDimensions validates framebuffer dimensions.
func (*InputValidator) ValidateKeySymbol ¶
func (iv *InputValidator) ValidateKeySymbol(keysym uint32) error
ValidateKeySymbol validates X11 keysym values for key events.
func (*InputValidator) ValidateMessageLength ¶
func (iv *InputValidator) ValidateMessageLength(length uint32, maxLength uint32) error
ValidateMessageLength validates message length fields to prevent overflow.
func (*InputValidator) ValidatePixelFormat ¶
func (iv *InputValidator) ValidatePixelFormat(pf *PixelFormat) error
ValidatePixelFormat validates a VNC pixel format structure.
func (*InputValidator) ValidatePointerPosition ¶
func (iv *InputValidator) ValidatePointerPosition(x, y, fbWidth, fbHeight uint16) error
ValidatePointerPosition validates pointer coordinates against framebuffer bounds.
func (*InputValidator) ValidateProtocolVersion ¶
func (iv *InputValidator) ValidateProtocolVersion(version string) error
ValidateProtocolVersion validates VNC protocol version strings.
func (*InputValidator) ValidateRectangle ¶
func (iv *InputValidator) ValidateRectangle(x, y, width, height, fbWidth, fbHeight uint16) error
ValidateRectangle validates rectangle bounds against framebuffer dimensions.
func (*InputValidator) ValidateSecurityType ¶
func (iv *InputValidator) ValidateSecurityType(securityType uint8) error
ValidateSecurityType validates a VNC security type identifier.
func (*InputValidator) ValidateSecurityTypes ¶
func (iv *InputValidator) ValidateSecurityTypes(securityTypes []uint8) error
ValidateSecurityTypes validates an array of VNC security types.
func (*InputValidator) ValidateTextData ¶
func (iv *InputValidator) ValidateTextData(text string, maxLength int) error
ValidateTextData validates text data for clipboard operations.
type Logger ¶
type Logger interface {
// Debug logs debug-level messages with optional structured fields.
Debug(msg string, fields ...Field)
// Info logs info-level messages with optional structured fields.
Info(msg string, fields ...Field)
// Warn logs warning-level messages with optional structured fields.
Warn(msg string, fields ...Field)
// Error logs error-level messages with optional structured fields.
Error(msg string, fields ...Field)
// With creates a new logger instance with the provided fields pre-populated.
With(fields ...Field) Logger
}
Logger defines the interface for structured logging throughout the VNC library.
type MemoryProtection ¶
type MemoryProtection struct {
// contains filtered or unexported fields
}
MemoryProtection provides utilities for protecting sensitive data in memory.
func (*MemoryProtection) NewProtectedBytes ¶
func (mp *MemoryProtection) NewProtectedBytes(size int) *ProtectedBytes
NewProtectedBytes creates a new protected byte slice.
Parameters:
- size: The size of the protected byte slice
Returns:
- *ProtectedBytes: The protected byte slice
Security considerations: - Automatically clears data when no longer needed - Use defer Clear() to ensure cleanup - Suitable for storing sensitive cryptographic data.
type MetricsCollector ¶
type MetricsCollector interface {
Counter(name string, tags ...interface{}) interface{}
Gauge(name string, tags ...interface{}) interface{}
Histogram(name string, tags ...interface{}) interface{}
}
MetricsCollector defines the interface for collecting metrics and observability data.
type NoOpLogger ¶
type NoOpLogger struct{}
NoOpLogger is a Logger implementation that discards all log messages.
func (*NoOpLogger) Debug ¶
func (l *NoOpLogger) Debug(msg string, fields ...Field)
Debug discards debug-level log messages.
func (*NoOpLogger) Error ¶
func (l *NoOpLogger) Error(msg string, fields ...Field)
Error discards error-level log messages.
func (*NoOpLogger) Info ¶
func (l *NoOpLogger) Info(msg string, fields ...Field)
Info discards info-level log messages.
func (*NoOpLogger) Warn ¶
func (l *NoOpLogger) Warn(msg string, fields ...Field)
Warn discards warning-level log messages.
func (*NoOpLogger) With ¶
func (l *NoOpLogger) With(fields ...Field) Logger
With returns a new NoOpLogger instance (ignores fields).
type NoOpMetrics ¶
type NoOpMetrics struct{}
NoOpMetrics is a MetricsCollector implementation that discards all metrics.
func (*NoOpMetrics) Counter ¶
func (m *NoOpMetrics) Counter(name string, tags ...interface{}) interface{}
Counter returns a no-op counter metric.
func (*NoOpMetrics) Gauge ¶
func (m *NoOpMetrics) Gauge(name string, tags ...interface{}) interface{}
Gauge returns a no-op gauge metric.
func (*NoOpMetrics) Histogram ¶
func (m *NoOpMetrics) Histogram(name string, tags ...interface{}) interface{}
Histogram returns a no-op histogram metric.
type PasswordAuth ¶
type PasswordAuth struct {
Password string
// contains filtered or unexported fields
}
PasswordAuth implements VNC Authentication (security type 2).
func NewPasswordAuth ¶
func NewPasswordAuth(password string) *PasswordAuth
NewPasswordAuth creates a new PasswordAuth instance with enhanced security features.
func (*PasswordAuth) ClearPassword ¶
func (p *PasswordAuth) ClearPassword()
ClearPassword securely clears the password from memory.
func (*PasswordAuth) Handshake ¶
Handshake performs the VNC Authentication handshake with the server.
func (*PasswordAuth) SecurityType ¶
func (p *PasswordAuth) SecurityType() uint8
SecurityType returns the security type identifier for VNC Password authentication.
func (*PasswordAuth) SetLogger ¶
func (p *PasswordAuth) SetLogger(logger Logger)
SetLogger sets the logger for the authentication method.
func (*PasswordAuth) String ¶
func (p *PasswordAuth) String() string
String returns a human-readable description of the authentication method.
type PixelFormat ¶
type PixelFormat struct {
// BPP (bits-per-pixel) specifies how many bits are used to represent each pixel.
BPP uint8
// Depth specifies the number of useful bits within each pixel value.
Depth uint8
// BigEndian determines the byte order for multi-byte pixel values.
BigEndian bool
// TrueColor determines whether pixels represent direct RGB values (true)
// or indices into a color map (false).
TrueColor bool
// RedMax specifies the maximum value for the red color component.
RedMax uint16
// GreenMax specifies the maximum value for the green color component.
GreenMax uint16
// BlueMax specifies the maximum value for the blue color component.
BlueMax uint16
// RedShift specifies how many bits to right-shift a pixel value
// to position the red color component at the least significant bits.
RedShift uint8
// GreenShift specifies how many bits to right-shift a pixel value
// to position the green color component at the least significant bits.
GreenShift uint8
// BlueShift specifies how many bits to right-shift a pixel value
// to position the blue color component at the least significant bits.
BlueShift uint8
}
PixelFormat describes how pixel color data is encoded and interpreted in a VNC connection.
func (*PixelFormat) Validate ¶
func (pf *PixelFormat) Validate() error
Validate performs comprehensive validation of a pixel format according to RFC 6143. It checks all fields for consistency and validity, returning detailed error information if any validation rules are violated.
type PixelFormatConverter ¶
type PixelFormatConverter struct {
// contains filtered or unexported fields
}
PixelFormatConverter provides utilities for converting between different pixel formats and extracting color components from pixel data.
func NewPixelFormatConverter ¶
func NewPixelFormatConverter(format *PixelFormat) (*PixelFormatConverter, error)
NewPixelFormatConverter creates a new pixel format converter for the given format.
func (*PixelFormatConverter) BytesPerPixel ¶
func (c *PixelFormatConverter) BytesPerPixel() int
BytesPerPixel returns the number of bytes per pixel for this format.
func (*PixelFormatConverter) CreatePixel ¶
func (c *PixelFormatConverter) CreatePixel(r, g, b uint8) uint32
CreatePixel creates a pixel value from 8-bit RGB components according to the pixel format. The RGB values are scaled to match the pixel format's color depth.
func (*PixelFormatConverter) ExtractRGB ¶
func (c *PixelFormatConverter) ExtractRGB(pixel uint32) (r, g, b uint8)
ExtractRGB extracts RGB color components from a pixel value according to the pixel format. Returns 8-bit RGB values (0-255) regardless of the source pixel format.
func (*PixelFormatConverter) ReadPixel ¶
func (c *PixelFormatConverter) ReadPixel(r io.Reader) (uint32, error)
ReadPixel reads a single pixel from the reader according to the pixel format's byte order.
func (*PixelFormatConverter) WritePixel ¶
func (c *PixelFormatConverter) WritePixel(w io.Writer, pixel uint32) error
WritePixel writes a single pixel to the writer according to the pixel format's byte order.
type PixelFormatValidationError ¶
type PixelFormatValidationError struct {
Field string
Value interface{}
Rule string
Message string
}
PixelFormatValidationError represents a pixel format validation error with detailed context.
func (*PixelFormatValidationError) Error ¶
func (e *PixelFormatValidationError) Error() string
Error returns the formatted error message for pixel format validation errors.
type PixelReader ¶
type PixelReader struct {
// contains filtered or unexported fields
}
PixelReader provides utilities for reading pixel data from VNC streams.
func NewPixelReader ¶
func NewPixelReader(pixelFormat PixelFormat, colorMap [ColorMapSize]Color) *PixelReader
NewPixelReader creates a new pixel reader for the given pixel format and color map.
func (*PixelReader) BytesPerPixel ¶
func (pr *PixelReader) BytesPerPixel() int
BytesPerPixel returns the number of bytes per pixel for the current pixel format.
func (*PixelReader) ReadPixelColor ¶
func (pr *PixelReader) ReadPixelColor(r io.Reader) (Color, error)
ReadPixelColor reads a single pixel from the reader and converts it to a Color. This consolidates the pixel reading logic that was duplicated across encoding files.
func (*PixelReader) ReadPixelData ¶
ReadPixelData reads raw pixel data without color conversion. Used by encodings that need the raw pixel bytes (like cursor encoding).
type ProtectedBytes ¶
type ProtectedBytes struct {
// contains filtered or unexported fields
}
ProtectedBytes represents a byte slice with automatic secure clearing.
func (*ProtectedBytes) Clear ¶
func (pb *ProtectedBytes) Clear()
Clear securely clears the protected bytes from memory.
func (*ProtectedBytes) Copy ¶
func (pb *ProtectedBytes) Copy(src []byte) error
Copy copies data into the protected byte slice.
Parameters:
- src: The source data to copy
Returns:
- error: Any error that occurred during copying
func (*ProtectedBytes) Data ¶
func (pb *ProtectedBytes) Data() []byte
Data returns the protected byte slice.
func (*ProtectedBytes) IsCleared ¶
func (pb *ProtectedBytes) IsCleared() bool
IsCleared returns true if the protected bytes have been cleared.
func (*ProtectedBytes) Size ¶
func (pb *ProtectedBytes) Size() int
Size returns the size of the protected byte slice.
func (*ProtectedBytes) Zero ¶
func (pb *ProtectedBytes) Zero()
Zero fills the protected bytes with zeros.
type PseudoEncoding ¶
type PseudoEncoding interface {
Encoding
IsPseudo() bool
Handle(*ClientConn, *Rectangle) error
}
PseudoEncoding defines the interface for VNC pseudo-encodings. Pseudo-encodings provide metadata or control information rather than pixel data.
type RREEncoding ¶
type RREEncoding struct {
BackgroundColor Color
Subrectangles []RRESubrectangle
}
RREEncoding represents the RRE (Rise-and-Run-length Encoding) as defined in RFC 6143 Section 7.7.3. RRE works by defining a background color and overlaying solid-color subrectangles.
func (*RREEncoding) Read ¶
func (*RREEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error)
Read decodes RRE encoding data from the server.
return
}
// Process the RRE encoding
rreEnc := decodedEnc.(*RREEncoding)
// Fill rectangle with background color
fillRectangle(rectangle.X, rectangle.Y, rectangle.Width, rectangle.Height,
rreEnc.BackgroundColor)
// Apply each subrectangle
for _, subrect := range rreEnc.Subrectangles {
fillRectangle(rectangle.X + subrect.X, rectangle.Y + subrect.Y,
subrect.Width, subrect.Height, subrect.Color)
}
Pixel format handling:
// The method handles different pixel formats automatically:
func readPixelColor(r io.Reader, pixelFormat PixelFormat) (Color, error) {
bytesPerPixel := pixelFormat.BPP / 8
pixelBytes := make([]byte, bytesPerPixel)
if _, err := io.ReadFull(r, pixelBytes); err != nil {
return Color{}, err
}
// Convert pixel bytes to Color based on pixel format
return convertPixelToColor(pixelBytes, pixelFormat), nil
}
Validation and error handling:
// The method validates subrectangle bounds:
if subrect.X + subrect.Width > rectangle.Width ||
subrect.Y + subrect.Height > rectangle.Height {
return encodingError("invalid subrectangle bounds")
}
Performance considerations: - Decoding performance scales with the number of subrectangles - Memory usage depends on subrectangle count (typically small) - Rendering performance depends on the graphics system's rectangle fill efficiency - Best suited for images with few distinct color regions
Error conditions: The method returns an EncodingError if: - Insufficient data is available for the subrectangle count - Background color data cannot be read - Any subrectangle data is incomplete or invalid - Subrectangle bounds extend outside the parent rectangle - I/O errors occur during data reading.
func (*RREEncoding) Type ¶
func (*RREEncoding) Type() int32
Type returns the encoding type identifier for RRE encoding.
type RRESubrectangle ¶
type RRESubrectangle struct {
// Color is the solid color that fills this subrectangle.
// All pixels within the subrectangle bounds will be set to this color.
Color Color
// X is the horizontal position of the subrectangle's left edge,
// relative to the parent rectangle's top-left corner (0-based).
X uint16
// Y is the vertical position of the subrectangle's top edge,
// relative to the parent rectangle's top-left corner (0-based).
Y uint16
// Width is the width of the subrectangle in pixels.
// Must be greater than 0 for valid subrectangles.
Width uint16
// Height is the height of the subrectangle in pixels.
// Must be greater than 0 for valid subrectangles.
Height uint16
}
RRESubrectangle represents a single solid-color rectangle within an RRE encoding. Each subrectangle defines a rectangular area that should be filled with a specific color, overlaying the background color in that region.
type RawEncoding ¶
type RawEncoding struct {
// Colors contains the decoded pixel data for the rectangle.
Colors []Color
}
RawEncoding represents uncompressed pixel data as defined in RFC 6143 Section 7.7.1.
func (*RawEncoding) Read ¶
func (*RawEncoding) Read(c *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error)
Read decodes raw pixel data from the server for the specified rectangle. This method implements the Encoding interface and processes uncompressed pixel data as defined in RFC 6143 Section 7.7.1. Each pixel is transmitted in the format specified by the connection's PixelFormat without any compression or transformation.
The method reads pixel data in left-to-right, top-to-bottom order and converts each pixel from the wire format to the standard Color representation. For true color formats, it extracts RGB components using the pixel format's shift and mask values. For indexed color formats, it looks up colors in the connection's color map.
Parameters:
- c: The client connection providing pixel format and color map information
- rect: The rectangle being decoded, specifying dimensions and position
- r: Reader containing the raw pixel data from the server
Returns:
- Encoding: A new RawEncoding instance containing the decoded pixel colors
- error: EncodingError if pixel data cannot be read or decoded
Example usage:
// This method is typically called by the VNC client's message processing loop
enc := &RawEncoding{}
decodedEnc, err := enc.Read(clientConn, rectangle, dataReader)
if err != nil {
log.Printf("Failed to decode raw encoding: %v", err)
return
}
// Access the decoded pixel data
rawEnc := decodedEnc.(*RawEncoding)
for i, color := range rawEnc.Colors {
// Process each pixel color
x := uint16(i % int(rectangle.Width))
y := uint16(i / int(rectangle.Width))
// Apply color to framebuffer at (rect.X + x, rect.Y + y)
}
Pixel format handling:
// The method automatically handles different pixel formats: // - 8-bit: Single byte per pixel (indexed or true color) // - 16-bit: Two bytes per pixel (typically RGB565 true color) // - 32-bit: Four bytes per pixel (typically RGBA true color) // For true color formats, RGB components are extracted: // red = (pixel >> RedShift) & RedMax // green = (pixel >> GreenShift) & GreenMax // blue = (pixel >> BlueShift) & BlueMax // For indexed color formats, the pixel value is used as a color map index: // color = colorMap[pixelValue]
Performance characteristics: - No compression overhead (fastest decoding) - Highest bandwidth usage (largest data size) - Predictable memory usage (width × height × bytes-per-pixel) - Suitable for complex images with high color variation
Error conditions: The method returns an EncodingError if: - Insufficient pixel data is available in the reader - I/O errors occur while reading pixel data - Invalid pixel format parameters are encountered.
func (*RawEncoding) Type ¶
func (*RawEncoding) Type() int32
Type returns the encoding type identifier for Raw encoding.
type Rectangle ¶
type Rectangle struct {
// X is the horizontal position of the rectangle's left edge in pixels,
// measured from the left edge of the framebuffer (0-based coordinate system).
X uint16
// Y is the vertical position of the rectangle's top edge in pixels,
// measured from the top edge of the framebuffer (0-based coordinate system).
Y uint16
// Width is the width of the rectangle in pixels.
// Must be greater than 0 for valid rectangles.
Width uint16
// Height is the height of the rectangle in pixels.
// Must be greater than 0 for valid rectangles.
Height uint16
// Enc contains the encoding implementation and decoded pixel data for this rectangle.
// The encoding type determines how the pixel data was compressed and transmitted,
// and the encoding instance contains the actual decoded pixel information.
Enc Encoding
}
Rectangle represents a rectangular region of the framebuffer with associated pixel data. Rectangles are the fundamental unit of framebuffer updates in the VNC protocol, defining both the screen coordinates and the encoded pixel data for a specific area.
Each rectangle specifies: - The position and dimensions of the screen area being updated - The encoding method used for the pixel data - The actual encoded pixel data (contained within the Encoding)
Rectangles are processed sequentially, and some encoding types (like CopyRect) may reference pixel data from previously processed rectangles or other areas of the framebuffer.
type SecureDESCipher ¶
type SecureDESCipher struct {
// contains filtered or unexported fields
}
SecureDESCipher provides enhanced DES encryption with secure memory handling and timing attack protection for VNC authentication.
func (*SecureDESCipher) EncryptVNCChallenge ¶
func (sdc *SecureDESCipher) EncryptVNCChallenge(password string, challenge []byte) ([]byte, error)
EncryptVNCChallenge encrypts a VNC authentication challenge using DES encryption with enhanced security measures including secure memory handling and timing attack protection.
This method implements the VNC authentication encryption as specified in RFC 6143, but with additional security enhancements: - Secure memory clearing of sensitive data - Timing attack protection - Enhanced input validation - Proper error handling
Parameters:
- password: The VNC password (limited to 8 characters)
- challenge: The 16-byte challenge from the server
Returns:
- []byte: The encrypted response (16 bytes)
- error: Any error that occurred during encryption
Security enhancements: - Clears password key material from memory after use - Uses constant-time operations where possible - Validates input parameters thoroughly - Protects against timing attacks during key preparation.
type SecureMemory ¶
type SecureMemory struct{}
SecureMemory provides utilities for secure handling of sensitive data in memory.
func (*SecureMemory) ClearBytes ¶
func (sm *SecureMemory) ClearBytes(data []byte)
ClearBytes securely clears a byte slice by overwriting it with random data.
func (*SecureMemory) ClearString ¶
func (sm *SecureMemory) ClearString(s string) string
ClearString securely clears a string by converting it to a byte slice and clearing the underlying memory. Note that Go strings are immutable, so this only clears the copy, not the original string data.
Parameters:
- s: The string to clear (creates a mutable copy for clearing)
Returns:
- The cleared string (empty string)
Security considerations: - Go strings are immutable, so original string data may persist - This method clears a mutable copy to prevent accidental reuse - For maximum security, avoid storing sensitive data in strings.
func (*SecureMemory) ConstantTimeCompare ¶
func (sm *SecureMemory) ConstantTimeCompare(a, b []byte) bool
ConstantTimeCompare performs a constant-time comparison of two byte slices to prevent timing attacks. This is crucial for comparing cryptographic values like authentication tokens or encrypted data.
Parameters:
- a, b: The byte slices to compare
Returns:
- bool: true if the slices are equal, false otherwise
Security considerations: - Uses crypto/subtle.ConstantTimeCompare for timing attack protection - Always takes the same amount of time regardless of input differences - Essential for secure authentication and cryptographic operations.
type SecureRandom ¶
type SecureRandom struct{}
SecureRandom provides cryptographically secure random number generation for security-critical operations.
func (*SecureRandom) GenerateBytes ¶
func (sr *SecureRandom) GenerateBytes(length int) ([]byte, error)
GenerateBytes generates cryptographically secure random bytes.
Parameters:
- length: The number of random bytes to generate
Returns:
- []byte: The generated random bytes
- error: Any error that occurred during generation
Security considerations: - Uses crypto/rand for cryptographically secure randomness - Suitable for cryptographic keys, nonces, and challenges - Returns error if insufficient entropy is available.
func (*SecureRandom) GenerateChallenge ¶
func (sr *SecureRandom) GenerateChallenge(length int) ([]byte, error)
GenerateChallenge generates a cryptographically secure challenge for authentication.
Parameters:
- length: The length of the challenge in bytes
Returns:
- []byte: The generated challenge
- error: Any error that occurred during generation
Security considerations: - Uses cryptographically secure random generation - Suitable for authentication challenges and nonces - Each challenge should be unique and unpredictable.
type ServerCutTextMessage ¶
type ServerCutTextMessage struct {
// Text contains the clipboard text from the server.
// The text is encoded using Latin-1 character encoding, which includes
// all ASCII characters plus additional characters in the 128-255 range.
// Applications should handle character encoding conversion if needed
// for integration with local clipboard systems that use different encodings.
Text string
}
ServerCutTextMessage represents clipboard data from the server (message type 3). This message is sent when the server's clipboard (cut buffer) contents change and should be synchronized with the client's clipboard.
As defined in RFC 6143 Section 7.6.4, this message enables clipboard sharing between the client and server systems. When the server's clipboard is updated (typically by a user copying text on the remote desktop), this message communicates the new clipboard contents to the client.
The text data is transmitted as Latin-1 encoded bytes, which is compatible with ASCII and the first 256 Unicode code points. Applications should handle character encoding appropriately when integrating with local clipboard systems.
Example usage:
switch msg := serverMsg.(type) {
case *ServerCutTextMessage:
// Update local clipboard with server's clipboard content
clipboard.WriteAll(msg.Text)
fmt.Printf("Clipboard updated: %q\n", msg.Text)
}
func (*ServerCutTextMessage) Read ¶
func (*ServerCutTextMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error)
Read parses a ServerCutText message from the server. This method implements the ServerMessage interface and processes clipboard data as defined in RFC 6143 Section 7.6.4. It reads text content from the server's clipboard and makes it available for integration with the client's clipboard system.
The method handles the complete message parsing including:
- Reading message padding
- Reading the text length field
- Reading the clipboard text data
- Converting the text to a Go string
Parameters:
- c: The client connection (unused for ServerCutText messages)
- r: Reader containing the message data (excluding the message type byte)
Returns:
- ServerMessage: A new ServerCutTextMessage containing the clipboard text
- error: NetworkError for I/O issues during message parsing
Example usage:
// This method is typically called by the VNC client's message processing loop
msg := &ServerCutTextMessage{}
parsedMsg, err := msg.Read(clientConn, messageReader)
if err != nil {
log.Printf("Failed to parse server cut text: %v", err)
return
}
// Process the parsed message
cutTextMsg := parsedMsg.(*ServerCutTextMessage)
fmt.Printf("Server clipboard updated: %q\n", cutTextMsg.Text)
// Update local clipboard
updateLocalClipboard(cutTextMsg.Text)
Clipboard integration examples:
func updateLocalClipboard(text string) {
// Cross-platform clipboard integration
switch runtime.GOOS {
case "windows":
// Use Windows clipboard API
clipboard.WriteAll(text)
case "darwin":
// Use macOS pasteboard
clipboard.WriteAll(text)
case "linux":
// Use X11 clipboard
clipboard.WriteAll(text)
default:
// Log or store for manual handling
log.Printf("Clipboard text: %s", text)
}
}
Message structure:
// Wire format (after message type byte): // [3 bytes] - Padding (ignored) // [4 bytes] - Text length (big-endian uint32) // [N bytes] - Text data (Latin-1 encoded)
Character encoding:
// The text is transmitted as Latin-1 encoded bytes
// Latin-1 includes ASCII (0-127) plus extended characters (128-255)
// Go strings handle this encoding naturally for most use cases
// For applications requiring specific encoding handling:
func convertFromLatin1(text string) string {
// Convert Latin-1 to UTF-8 if needed
bytes := []byte(text)
runes := make([]rune, len(bytes))
for i, b := range bytes {
runes[i] = rune(b) // Latin-1 maps directly to Unicode
}
return string(runes)
}
Bidirectional clipboard synchronization:
// Handle server clipboard updates
func handleServerCutText(msg *ServerCutTextMessage) {
// Update local clipboard
clipboard.WriteAll(msg.Text)
// Prevent feedback loops by tracking clipboard source
lastServerClipboard = msg.Text
}
// Monitor local clipboard changes
func monitorLocalClipboard(client *ClientConn) {
for {
text, _ := clipboard.ReadAll()
if text != lastServerClipboard && text != "" {
client.CutText(text) // Send to server
}
time.Sleep(100 * time.Millisecond)
}
}
Error handling: The method may return NetworkError for:
- I/O failures reading message padding or text length
- I/O failures reading text data
- Incomplete text data (fewer bytes than specified length)
- Network connection issues during message parsing
Security considerations: - Clipboard data may contain sensitive information - Applications should consider whether automatic clipboard sync is appropriate - Large clipboard content may consume significant memory - Consider sanitizing or filtering clipboard content based on security requirements
Performance considerations: - Text length is limited by uint32 maximum (4GB theoretical limit) - Large clipboard content is rare but possible - Memory usage scales linearly with text length - Consider implementing size limits for clipboard content in security-sensitive applications.
func (*ServerCutTextMessage) Type ¶
func (*ServerCutTextMessage) Type() uint8
Type returns the message type identifier for server cut text messages.
type ServerMessage ¶
type ServerMessage interface {
Type() uint8
Read(conn *ClientConn, r io.Reader) (ServerMessage, error)
}
ServerMessage defines the interface for messages sent from a VNC server to the client.
type SetColorMapEntriesMessage ¶
type SetColorMapEntriesMessage struct {
// FirstColor is the index of the first color map entry being updated.
// Color map indices range from 0 to 255, and this value indicates
// where in the color map the new color values should be placed.
FirstColor uint16
// Colors contains the new color values to be installed in the color map.
// These colors will be placed in the color map starting at the FirstColor
// index. The length of this slice determines how many consecutive color
// map entries will be updated.
Colors []Color
}
SetColorMapEntriesMessage represents a color map update from the server (message type 1). This message is sent when the server needs to update entries in the client's color map, which is used when the pixel format uses indexed color mode rather than true color.
As defined in RFC 6143 Section 7.6.2, this message allows the server to dynamically change the color palette used for interpreting pixel values. This is particularly important for 8-bit color modes where pixel values are indices into a 256-entry color table rather than direct RGB values.
The message automatically updates the connection's ColorMap field when processed, ensuring that subsequent framebuffer updates use the correct color interpretations. Applications can also access the color change data directly for custom processing.
Example usage:
switch msg := serverMsg.(type) {
case *SetColorMapEntriesMessage:
fmt.Printf("Color map updated: %d colors starting at index %d\n",
len(msg.Colors), msg.FirstColor)
// The connection's ColorMap is automatically updated
}
func (*SetColorMapEntriesMessage) Read ¶
func (*SetColorMapEntriesMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error)
Read parses a SetColorMapEntries message from the server. This method implements the ServerMessage interface and processes color map updates as defined in RFC 6143 Section 7.6.2. It reads new color values and automatically updates the connection's color map for use with indexed color pixel formats.
The method handles the complete message parsing including:
- Reading message padding and the starting color index
- Reading the number of colors being updated
- Reading RGB values for each color entry
- Automatically updating the connection's ColorMap field
Parameters:
- c: The client connection whose color map will be updated
- r: Reader containing the message data (excluding the message type byte)
Returns:
- ServerMessage: A new SetColorMapEntriesMessage containing the color update data
- error: NetworkError for I/O issues during message parsing
Example usage:
// This method is typically called by the VNC client's message processing loop
msg := &SetColorMapEntriesMessage{}
parsedMsg, err := msg.Read(clientConn, messageReader)
if err != nil {
log.Printf("Failed to parse color map update: %v", err)
return
}
// Process the parsed message
colorUpdate := parsedMsg.(*SetColorMapEntriesMessage)
fmt.Printf("Updated %d colors starting at index %d\n",
len(colorUpdate.Colors), colorUpdate.FirstColor)
// The connection's ColorMap is automatically updated
// Access updated colors if needed:
for i, color := range colorUpdate.Colors {
index := colorUpdate.FirstColor + uint16(i)
fmt.Printf("Color[%d] = RGB(%d, %d, %d)\n",
index, color.R, color.G, color.B)
}
Color map usage:
// After this message is processed, indexed pixel values will use the new colors: // For 8-bit indexed pixel format: pixelValue := uint8(42) // Example pixel value from framebuffer update actualColor := clientConn.ColorMap[pixelValue] // Uses updated color map
Message structure:
// Wire format (after message type byte): // [1 byte] - Padding (ignored) // [2 bytes] - First color index (big-endian uint16) // [2 bytes] - Number of colors (big-endian uint16) // For each color: // [2 bytes] - Red component (big-endian uint16) // [2 bytes] - Green component (big-endian uint16) // [2 bytes] - Blue component (big-endian uint16)
Automatic color map update:
// The method automatically updates the connection's color map:
for i, color := range newColors {
clientConn.ColorMap[firstColor + i] = color
}
// This ensures that subsequent framebuffer updates with indexed pixels
// will use the correct color interpretations
Color value format: Color components are 16-bit values (0-65535) providing high precision color representation. When displaying on 8-bit systems, applications should scale appropriately (e.g., divide by 257 to convert to 8-bit values).
Error handling: The method may return NetworkError for:
- I/O failures reading message padding, indices, or color data
- Incomplete color data (fewer bytes than expected)
- Network connection issues during message parsing
Performance considerations: - Color map updates are typically small (few colors changed at once) - The automatic color map update is performed synchronously - Large color map changes (updating many colors) are rare but possible - Color map updates may trigger visual changes in subsequent framebuffer updates.
func (*SetColorMapEntriesMessage) Type ¶
func (*SetColorMapEntriesMessage) Type() uint8
Type returns the message type identifier for color map update messages.
type StandardLogger ¶
type StandardLogger struct {
// Logger is the underlying standard library logger.
Logger *log.Logger
// contains filtered or unexported fields
}
StandardLogger wraps Go's standard log package to implement the Logger interface.
func (*StandardLogger) Debug ¶
func (l *StandardLogger) Debug(msg string, fields ...Field)
Debug logs a debug-level message with structured fields.
func (*StandardLogger) Error ¶
func (l *StandardLogger) Error(msg string, fields ...Field)
Error logs an error-level message with structured fields.
func (*StandardLogger) Info ¶
func (l *StandardLogger) Info(msg string, fields ...Field)
Info logs an info-level message with structured fields.
func (*StandardLogger) Warn ¶
func (l *StandardLogger) Warn(msg string, fields ...Field)
Warn logs a warning-level message with structured fields.
func (*StandardLogger) With ¶
func (l *StandardLogger) With(fields ...Field) Logger
With creates a new StandardLogger instance with additional context fields. The returned logger will include the provided fields in all subsequent log messages.
type TimingProtection ¶
type TimingProtection struct{}
TimingProtection provides utilities for protecting against timing attacks during authentication and cryptographic operations.
func (*TimingProtection) ConstantTimeAuthentication ¶
func (tp *TimingProtection) ConstantTimeAuthentication(authFunc func() error, baseDelay time.Duration) error
ConstantTimeAuthentication performs authentication with timing attack protection. This ensures that both successful and failed authentication attempts take approximately the same amount of time.
Parameters:
- authFunc: The authentication function to execute
- baseDelay: The minimum time the operation should take
Returns:
- error: Any error from the authentication function
Security considerations: - Normalizes timing between success and failure cases - Prevents timing-based username/password enumeration - Should be used for all authentication operations.
func (*TimingProtection) ConstantTimeDelay ¶
func (tp *TimingProtection) ConstantTimeDelay(baseDelay time.Duration)
ConstantTimeDelay introduces a constant delay to normalize operation timing. This helps prevent timing attacks by ensuring operations take a consistent amount of time regardless of the input or success/failure status.
Parameters:
- baseDelay: The base delay duration to apply
Security considerations: - Helps prevent timing analysis of authentication operations - Should be used consistently across success and failure paths - Delay should be long enough to mask timing variations.
type VNCError ¶
VNCError provides structured error information with operation context, error codes, and message wrapping for comprehensive error handling.
func NewVNCError ¶
NewVNCError creates a new VNCError with the specified parameters. This is the primary constructor for structured VNC errors.