forked from mitchellh/go-vnc
-
Notifications
You must be signed in to change notification settings - Fork 16
/
encodings.go
154 lines (125 loc) · 4.35 KB
/
encodings.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
/*
Implementation of RFC 6143 §7.7 Encodings.
https://tools.ietf.org/html/rfc6143#section-7.7
*/
package vnc
import (
"bytes"
"fmt"
"github.com/kward/go-vnc/encodings"
)
//=============================================================================
// Encodings
// An Encoding implements a method for encoding pixel data that is
// sent by the server to the client.
type Encoding interface {
fmt.Stringer
Marshaler
// Read the contents of the encoded pixel data from the reader.
// This should return a new Encoding implementation that contains
// the proper data.
Read(*ClientConn, *Rectangle) (Encoding, error)
// The number that uniquely identifies this encoding type.
Type() encodings.Encoding
}
// Encodings describes a slice of Encoding.
type Encodings []Encoding
// Verify that interfaces are honored.
var _ Marshaler = (*Encodings)(nil)
// Marshal implements the Marshaler interface.
func (e Encodings) Marshal() ([]byte, error) {
buf := NewBuffer(nil)
for _, enc := range e {
if err := buf.Write(enc.Type()); err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}
//-----------------------------------------------------------------------------
// Raw Encoding
//
// Raw encoding is the simplest encoding type, which is raw pixel data.
//
// See RFC 6143 §7.7.1.
// https://tools.ietf.org/html/rfc6143#section-7.7.1
// RawEncoding holds raw encoded rectangle data.
type RawEncoding struct {
Colors []Color
}
// Verify that interfaces are honored.
var _ Encoding = (*RawEncoding)(nil)
// Marshal implements the Encoding interface.
func (e *RawEncoding) Marshal() ([]byte, error) {
buf := NewBuffer(nil)
for _, c := range e.Colors {
bytes, err := c.Marshal()
if err != nil {
return nil, err
}
if err := buf.Write(bytes); err != nil {
return nil, err
}
}
return buf.Bytes(), nil
}
// Read implements the Encoding interface.
func (*RawEncoding) Read(c *ClientConn, rect *Rectangle) (Encoding, error) {
var buf bytes.Buffer
bytesPerPixel := int(c.pixelFormat.BPP / 8)
n := rect.Area() * bytesPerPixel
if err := c.receiveN(&buf, n); err != nil {
return nil, fmt.Errorf("unable to read rectangle with raw encoding: %s", err)
}
colors := make([]Color, rect.Area())
for y := uint16(0); y < rect.Height; y++ {
for x := uint16(0); x < rect.Width; x++ {
color := NewColor(&c.pixelFormat, &c.colorMap)
if err := color.Unmarshal(buf.Next(bytesPerPixel)); err != nil {
return nil, err
}
colors[int(y)*int(rect.Width)+int(x)] = *color
}
}
return &RawEncoding{colors}, nil
}
// String implements the fmt.Stringer interface.
func (*RawEncoding) String() string { return "RawEncoding" }
// Type implements the Encoding interface.
func (*RawEncoding) Type() encodings.Encoding { return encodings.Raw }
//=============================================================================
// Pseudo-Encodings
//
// Rectangles with a "pseudo-encoding" allow a server to send data to the
// client. The interpretation of the data depends on the pseudo-encoding.
//
// See RFC 6143 §7.8.
// https://tools.ietf.org/html/rfc6143#section-7.8
//-----------------------------------------------------------------------------
// DesktopSize Pseudo-Encoding
//
// When a client requests DesktopSize pseudo-encoding, it is indicating to the
// server that it can handle changes to the framebuffer size. If this encoding
// received, the client must resize its framebuffer, and drop all existing
// information stored in the framebuffer.
//
// See RFC 6143 §7.8.2.
// https://tools.ietf.org/html/rfc6143#section-7.8.2
// DesktopSizePseudoEncoding represents a desktop size message from the server.
type DesktopSizePseudoEncoding struct{}
// Verify that interfaces are honored.
var _ Encoding = (*DesktopSizePseudoEncoding)(nil)
// Marshal implements the Marshaler interface.
func (e *DesktopSizePseudoEncoding) Marshal() ([]byte, error) {
return []byte{}, nil
}
// Read implements the Encoding interface.
func (*DesktopSizePseudoEncoding) Read(c *ClientConn, rect *Rectangle) (Encoding, error) {
c.fbWidth = rect.Width
c.fbHeight = rect.Height
return &DesktopSizePseudoEncoding{}, nil
}
// String implements the fmt.Stringer interface.
func (e *DesktopSizePseudoEncoding) String() string { return "DesktopSizePseudoEncoding" }
// Type implements the Encoding interface.
func (*DesktopSizePseudoEncoding) Type() encodings.Encoding { return encodings.DesktopSizePseudo }