main
Raw Download raw file
 1package rfb
 2
 3import (
 4	"encoding/binary"
 5	"fmt"
 6)
 7
 8// Session holds the state of an RFB session after handshake.
 9type Session struct {
10	// Width of the framebuffer in pixels.
11	Width uint16
12
13	// Height of the framebuffer in pixels.
14	Height uint16
15
16	// Name of the VNC server/desktop.
17	Name string
18
19	// PixelFormat describes the pixel format of the framebuffer.
20	PixelFormat PixelFormat
21
22	// ServerVersion is the RFB version string from the server.
23	ServerVersion string
24}
25
26// PixelFormat describes the format of pixel data.
27type PixelFormat struct {
28	BitsPerPixel  uint8
29	Depth         uint8
30	BigEndian     bool
31	TrueColour    bool
32	RedMax        uint16
33	GreenMax      uint16
34	BlueMax       uint16
35	RedShift      uint8
36	GreenShift    uint8
37	BlueShift     uint8
38}
39
40// ParseServerInit parses a ServerInit message and returns a Session.
41// ServerInit format: width(2) + height(2) + pixel_format(16) + name_len(4) + name
42func ParseServerInit(data []byte) (*Session, error) {
43	if len(data) < 24 {
44		return nil, fmt.Errorf("server init too short: %d bytes", len(data))
45	}
46
47	width := binary.BigEndian.Uint16(data[0:2])
48	height := binary.BigEndian.Uint16(data[2:4])
49
50	pf := PixelFormat{
51		BitsPerPixel: data[4],
52		Depth:        data[5],
53		BigEndian:    data[6] != 0,
54		TrueColour:   data[7] != 0,
55		RedMax:       binary.BigEndian.Uint16(data[8:10]),
56		GreenMax:     binary.BigEndian.Uint16(data[10:12]),
57		BlueMax:      binary.BigEndian.Uint16(data[12:14]),
58		RedShift:     data[14],
59		GreenShift:   data[15],
60		BlueShift:    data[16],
61		// data[17:20] is padding
62	}
63
64	nameLen := binary.BigEndian.Uint32(data[20:24])
65	if len(data) < 24+int(nameLen) {
66		return nil, fmt.Errorf("server init name incomplete: need %d, got %d", 24+nameLen, len(data))
67	}
68	name := string(data[24 : 24+nameLen])
69
70	return &Session{
71		Width:       width,
72		Height:      height,
73		Name:        name,
74		PixelFormat: pf,
75	}, nil
76}
77
78// EncodePixelFormat creates a SetPixelFormat message.
79func EncodePixelFormat(pf *PixelFormat) []byte {
80	msg := make([]byte, 20)
81	msg[0] = MsgTypeSetPixelFormat
82	// msg[1:4] padding
83	msg[4] = pf.BitsPerPixel
84	msg[5] = pf.Depth
85	if pf.BigEndian {
86		msg[6] = 1
87	}
88	if pf.TrueColour {
89		msg[7] = 1
90	}
91	binary.BigEndian.PutUint16(msg[8:10], pf.RedMax)
92	binary.BigEndian.PutUint16(msg[10:12], pf.GreenMax)
93	binary.BigEndian.PutUint16(msg[12:14], pf.BlueMax)
94	msg[14] = pf.RedShift
95	msg[15] = pf.GreenShift
96	msg[16] = pf.BlueShift
97	// msg[17:20] padding
98	return msg
99}