main
Raw Download raw file
  1// Package rfb implements the RFB (Remote Framebuffer) protocol for VNC.
  2package rfb
  3
  4import (
  5	"encoding/binary"
  6	"fmt"
  7)
  8
  9// Server-to-client message types
 10const (
 11	MsgTypeFramebufferUpdate   = 0
 12	MsgTypeSetColourMapEntries = 1
 13	MsgTypeBell                = 2
 14	MsgTypeServerCutText       = 3
 15)
 16
 17// Client-to-server message types
 18const (
 19	MsgTypeSetPixelFormat           = 0
 20	MsgTypeSetEncodings             = 2
 21	MsgTypeFramebufferUpdateRequest = 3
 22	MsgTypeKeyEvent                 = 4
 23	MsgTypePointerEvent             = 5
 24	MsgTypeClientCutText            = 6
 25)
 26
 27// Common VNC key codes (X11 keysyms)
 28const (
 29	KeyBackspace = 0xff08
 30	KeyTab       = 0xff09
 31	KeyReturn    = 0xff0d
 32	KeyEscape    = 0xff1b
 33	KeyInsert    = 0xff63
 34	KeyDelete    = 0xffff
 35	KeyHome      = 0xff50
 36	KeyEnd       = 0xff57
 37	KeyPageUp    = 0xff55
 38	KeyPageDown  = 0xff56
 39	KeyLeft      = 0xff51
 40	KeyUp        = 0xff52
 41	KeyRight     = 0xff53
 42	KeyDown      = 0xff54
 43	KeyF1        = 0xffbe
 44	KeyF2        = 0xffbf
 45	KeyF3        = 0xffc0
 46	KeyF4        = 0xffc1
 47	KeyF5        = 0xffc2
 48	KeyF6        = 0xffc3
 49	KeyF7        = 0xffc4
 50	KeyF8        = 0xffc5
 51	KeyF9        = 0xffc6
 52	KeyF10       = 0xffc7
 53	KeyF11       = 0xffc8
 54	KeyF12       = 0xffc9
 55	KeyShiftL    = 0xffe1
 56	KeyShiftR    = 0xffe2
 57	KeyControlL  = 0xffe3
 58	KeyControlR  = 0xffe4
 59	KeyMetaL     = 0xffe7
 60	KeyMetaR     = 0xffe8
 61	KeyAltL      = 0xffe9
 62	KeyAltR      = 0xffea
 63	KeySuperL    = 0xffeb
 64	KeySuperR    = 0xffec
 65)
 66
 67// Standard encodings
 68const (
 69	EncodingRaw       = 0
 70	EncodingCopyRect  = 1
 71	EncodingRRE       = 2
 72	EncodingHextile   = 5
 73	EncodingZRLE      = 16
 74	EncodingTight     = 7
 75	EncodingTightPNG  = -260
 76
 77	// Pseudo-encodings
 78	EncodingCursor         = -239
 79	EncodingDesktopSize    = -223
 80	EncodingLastRect       = -224
 81	EncodingDesktopName    = -307
 82	EncodingExtendedDesktopSize = -308
 83)
 84
 85// DefaultEncodings returns the default encoding list for noVNC compatibility.
 86func DefaultEncodings() []int32 {
 87	return []int32{
 88		EncodingTight,
 89		EncodingZRLE,
 90		EncodingHextile,
 91		EncodingCopyRect,
 92		EncodingRaw,
 93		EncodingDesktopSize,
 94		EncodingLastRect,
 95		EncodingCursor,
 96	}
 97}
 98
 99// EncodeSetEncodings creates a SetEncodings message.
100func EncodeSetEncodings(encodings []int32) []byte {
101	msg := make([]byte, 4+4*len(encodings))
102	msg[0] = MsgTypeSetEncodings
103	// msg[1] padding
104	binary.BigEndian.PutUint16(msg[2:4], uint16(len(encodings)))
105	for i, enc := range encodings {
106		binary.BigEndian.PutUint32(msg[4+i*4:], uint32(enc))
107	}
108	return msg
109}
110
111// EncodeFramebufferUpdateRequest creates a FramebufferUpdateRequest message.
112func EncodeFramebufferUpdateRequest(incremental bool, x, y, width, height uint16) []byte {
113	msg := make([]byte, 10)
114	msg[0] = MsgTypeFramebufferUpdateRequest
115	if incremental {
116		msg[1] = 1
117	}
118	binary.BigEndian.PutUint16(msg[2:4], x)
119	binary.BigEndian.PutUint16(msg[4:6], y)
120	binary.BigEndian.PutUint16(msg[6:8], width)
121	binary.BigEndian.PutUint16(msg[8:10], height)
122	return msg
123}
124
125// EncodeKeyEvent creates a KeyEvent message.
126func EncodeKeyEvent(down bool, key uint32) []byte {
127	msg := make([]byte, 8)
128	msg[0] = MsgTypeKeyEvent
129	if down {
130		msg[1] = 1
131	}
132	// msg[2:4] padding
133	binary.BigEndian.PutUint32(msg[4:8], key)
134	return msg
135}
136
137// EncodePointerEvent creates a PointerEvent message.
138func EncodePointerEvent(buttonMask uint8, x, y uint16) []byte {
139	msg := make([]byte, 6)
140	msg[0] = MsgTypePointerEvent
141	msg[1] = buttonMask
142	binary.BigEndian.PutUint16(msg[2:4], x)
143	binary.BigEndian.PutUint16(msg[4:6], y)
144	return msg
145}
146
147// EncodeClientCutText creates a ClientCutText message.
148func EncodeClientCutText(text string) []byte {
149	msg := make([]byte, 8+len(text))
150	msg[0] = MsgTypeClientCutText
151	// msg[1:4] padding
152	binary.BigEndian.PutUint32(msg[4:8], uint32(len(text)))
153	copy(msg[8:], text)
154	return msg
155}
156
157// ServerMessage represents a parsed server-to-client message.
158type ServerMessage struct {
159	Type uint8
160	Raw  []byte
161}
162
163// FramebufferUpdate contains parsed framebuffer update data.
164type FramebufferUpdate struct {
165	NumRects uint16
166	Raw      []byte
167}
168
169// ServerCutText contains clipboard data from the server.
170type ServerCutText struct {
171	Text string
172}
173
174// ParseServerMessage parses a raw server message.
175func ParseServerMessage(data []byte) (*ServerMessage, error) {
176	if len(data) == 0 {
177		return nil, fmt.Errorf("empty message")
178	}
179	return &ServerMessage{
180		Type: data[0],
181		Raw:  data,
182	}, nil
183}
184
185// ParseFramebufferUpdate parses a FramebufferUpdate message.
186func ParseFramebufferUpdate(data []byte) (*FramebufferUpdate, error) {
187	if len(data) < 4 {
188		return nil, fmt.Errorf("framebuffer update too short: %d", len(data))
189	}
190	return &FramebufferUpdate{
191		NumRects: binary.BigEndian.Uint16(data[2:4]),
192		Raw:      data,
193	}, nil
194}
195
196// ParseServerCutText parses a ServerCutText message.
197func ParseServerCutText(data []byte) (*ServerCutText, error) {
198	if len(data) < 8 {
199		return nil, fmt.Errorf("server cut text too short: %d", len(data))
200	}
201	textLen := binary.BigEndian.Uint32(data[4:8])
202	if len(data) < 8+int(textLen) {
203		return nil, fmt.Errorf("server cut text incomplete: need %d, got %d", 8+textLen, len(data))
204	}
205	return &ServerCutText{
206		Text: string(data[8 : 8+textLen]),
207	}, nil
208}
209
210// RuneToKeysym converts a rune to a VNC keysym.
211func RuneToKeysym(r rune) uint32 {
212	switch r {
213	case '\n':
214		return KeyReturn
215	case '\t':
216		return KeyTab
217	case '\b':
218		return KeyBackspace
219	case 0x1b:
220		return KeyEscape
221	default:
222		// For ASCII characters, the keysym equals the Unicode code point
223		return uint32(r)
224	}
225}