/
rfb.go
173 lines (155 loc) · 4.04 KB
/
rfb.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package rfb
import (
"encoding/binary"
"fmt"
"io"
)
type PixelFormat struct {
BitsPerPixel uint8
BitDepth uint8
BigEndian bool
TrueColor bool
RedMax uint16
GreenMax uint16
BlueMax uint16
RedShift uint8
GreenShift uint8
BlueShift uint8
}
type FramebufferUpdateRequest struct {
Incremental bool
X uint16
Y uint16
Width uint16
Height uint16
}
type KeyEvent struct {
Pressed bool
KeySym uint32
}
type PointerEvent struct {
ButtonMask uint8
X uint16
Y uint16
}
type FramebufferUpdate struct {
Rectangles []*FramebufferUpdateRect
}
type FramebufferUpdateRect struct {
X uint16
Y uint16
Width uint16
Height uint16
EncodingType uint32 // Unsigned per spec, but often interpreted signed
PixelData []byte
}
const (
PixelFormatEncodingLength = 16
FramebufferUpdateRequestEncodingLength = 9
KeyEventEncodingLength = 7
PointerEventEncodingLength = 5
)
// buf must contain at least PixelFormatEncodingLength bytes.
func (pf *PixelFormat) Read(buf []byte, bo binary.ByteOrder) {
pf.BitsPerPixel = buf[0]
pf.BitDepth = buf[1]
pf.BigEndian = buf[2] != 0
pf.TrueColor = buf[3] != 0
pf.RedMax = bo.Uint16(buf[4:])
pf.GreenMax = bo.Uint16(buf[6:])
pf.BlueMax = bo.Uint16(buf[8:])
pf.RedShift = buf[10]
pf.GreenShift = buf[11]
pf.BlueShift = buf[12]
}
// buf must contain at least PixelFormatEncodingLength bytes.
func (pf *PixelFormat) Write(buf []byte, bo binary.ByteOrder) {
buf[0] = pf.BitsPerPixel
buf[1] = pf.BitDepth
if pf.BigEndian {
buf[2] = 1
} else {
buf[2] = 0
}
if pf.TrueColor {
buf[3] = 1
} else {
buf[3] = 0
}
bo.PutUint16(buf[4:], pf.RedMax)
bo.PutUint16(buf[6:], pf.GreenMax)
bo.PutUint16(buf[8:], pf.BlueMax)
buf[10] = pf.RedShift
buf[11] = pf.GreenShift
buf[12] = pf.BlueShift
}
// buf must contain at least FramebufferUpdateRequestEncodingLength bytes.
func (r *FramebufferUpdateRequest) Read(buf []byte, bo binary.ByteOrder) {
r.Incremental = buf[0] != 0
r.X = bo.Uint16(buf[1:])
r.Y = bo.Uint16(buf[3:])
r.Width = bo.Uint16(buf[5:])
r.Height = bo.Uint16(buf[7:])
}
// buf must contain at least FramebufferUpdateRequestEncodingLength bytes.
func (r *FramebufferUpdateRequest) Write(buf []byte, bo binary.ByteOrder) {
if r.Incremental {
buf[0] = 1
} else {
buf[0] = 0
}
bo.PutUint16(buf[1:], r.X)
bo.PutUint16(buf[3:], r.Y)
bo.PutUint16(buf[5:], r.Width)
bo.PutUint16(buf[7:], r.Height)
}
// buf must contain at least KeyEventEncodingLength bytes.
func (e *KeyEvent) Read(buf []byte, bo binary.ByteOrder) {
e.Pressed = buf[0] != 0
e.KeySym = bo.Uint32(buf[3:])
}
// buf must contain at least PointerEventEncodingLength bytes.
func (e *PointerEvent) Read(buf []byte, bo binary.ByteOrder) {
e.ButtonMask = buf[0]
e.X = bo.Uint16(buf[1:])
e.Y = bo.Uint16(buf[3:])
}
func (rect *FramebufferUpdateRect) Read(r io.Reader, bo binary.ByteOrder, pixelFormat PixelFormat) error {
var buf [12]byte
if _, err := io.ReadFull(r, buf[:]); err != nil {
return err
}
rect.X = bo.Uint16(buf[0:])
rect.Y = bo.Uint16(buf[2:])
rect.Width = bo.Uint16(buf[4:])
rect.Height = bo.Uint16(buf[6:])
rect.EncodingType = bo.Uint32(buf[8:])
if rect.EncodingType != 0 {
return fmt.Errorf("only raw encoding is supported, but it is %d", rect.EncodingType)
}
rect.PixelData = make([]byte, int(pixelFormat.BitsPerPixel/8)*int(rect.Width)*int(rect.Height))
if _, err := io.ReadFull(r, rect.PixelData); err != nil {
return err
}
return nil
}
func (u *FramebufferUpdate) Write(w io.Writer, bo binary.ByteOrder) error {
if err := binary.Write(w, bo, uint16(len(u.Rectangles))); err != nil {
return err
}
for _, rect := range u.Rectangles {
var buf [12]byte
bo.PutUint16(buf[0:], rect.X)
bo.PutUint16(buf[2:], rect.Y)
bo.PutUint16(buf[4:], rect.Width)
bo.PutUint16(buf[6:], rect.Height)
bo.PutUint32(buf[8:], uint32(rect.EncodingType))
if _, err := w.Write(buf[:]); err != nil {
return err
}
if _, err := w.Write(rect.PixelData); err != nil {
return err
}
}
return nil
}