go-rfb/messages.go

523 lines
12 KiB
Go
Raw Normal View History

package vnc
import (
"encoding/binary"
"fmt"
)
var DefaultClientMessages = []ClientMessage{
&SetPixelFormat{},
&SetEncodings{},
&FramebufferUpdateRequest{},
&KeyEvent{},
&PointerEvent{},
&ClientCutText{},
}
type ServerInit struct {
FBWidth, FBHeight uint16
PixelFormat PixelFormat
NameLength uint32
NameText []byte
}
func (srvInit ServerInit) String() string {
return fmt.Sprintf("Width: %d, Height: %d, PixelFormat: %s, NameLength: %d, MameText: %s", srvInit.FBWidth, srvInit.FBHeight, srvInit.PixelFormat, srvInit.NameLength, srvInit.NameText)
}
// ServerMessage represents a Client-to-Server RFB message type.
type ServerMessageType uint8
//go:generate stringer -type=ServerMessageType
// Client-to-Server message types.
const (
FramebufferUpdateMsgType ServerMessageType = iota
SetColorMapEntriesMsgType
BellMsgType
ServerCutTextMsgType
)
// FramebufferUpdate holds a FramebufferUpdate wire format message.
type FramebufferUpdate struct {
_ [1]byte // pad
NumRect uint16 // number-of-rectangles
Rects []*Rectangle // rectangles
}
func (msg *FramebufferUpdate) String() string {
return fmt.Sprintf("rects %d rectangle[]: { %v }", msg.NumRect, msg.Rects)
}
func (*FramebufferUpdate) Type() ServerMessageType {
return FramebufferUpdateMsgType
}
func (*FramebufferUpdate) Read(c Conn) (ServerMessage, error) {
msg := FramebufferUpdate{}
var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
if err := binary.Read(c, binary.BigEndian, &msg.NumRect); err != nil {
return nil, err
}
for i := uint16(0); i < msg.NumRect; i++ {
rect := NewRectangle()
if err := rect.Read(c); err != nil {
return nil, err
}
msg.Rects = append(msg.Rects, rect)
}
return &msg, nil
}
func (msg *FramebufferUpdate) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
var pad [1]byte
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg.NumRect); err != nil {
return err
}
for _, rect := range msg.Rects {
if err := rect.Write(c); err != nil {
return err
}
}
return c.Flush()
}
type ServerCutText struct {
_ [1]byte
Length uint32
Text []byte
}
func (msg *ServerCutText) String() string {
return fmt.Sprintf("lenght: %d text: %s", msg.Length, msg.Text)
}
func (*ServerCutText) Type() ServerMessageType {
return ServerCutTextMsgType
}
func (*ServerCutText) Read(c Conn) (ServerMessage, error) {
msg := ServerCutText{}
var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
if err := binary.Read(c, binary.BigEndian, &msg.Length); err != nil {
return nil, err
}
msg.Text = make([]byte, msg.Length)
if err := binary.Read(c, binary.BigEndian, &msg.Text); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *ServerCutText) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
var pad [1]byte
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
if msg.Length < uint32(len(msg.Text)) {
msg.Length = uint32(len(msg.Text))
}
if err := binary.Write(c, binary.BigEndian, msg.Length); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg.Text); err != nil {
return err
}
return c.Flush()
}
type Bell struct{}
func (*Bell) String() string {
return fmt.Sprintf("bell")
}
func (*Bell) Type() ServerMessageType {
return BellMsgType
}
func (*Bell) Read(c Conn) (ServerMessage, error) {
return &Bell{}, nil
}
func (msg *Bell) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
return c.Flush()
}
type SetColorMapEntries struct {
_ [1]byte
FirstColor uint16
ColorsNum uint16
Colors []Color
}
func (msg *SetColorMapEntries) String() string {
return fmt.Sprintf("first color: %d, numcolors: %d, colors[]: { %v }", msg.FirstColor, msg.ColorsNum, msg.Colors)
}
func (*SetColorMapEntries) Type() ServerMessageType {
return SetColorMapEntriesMsgType
}
func (*SetColorMapEntries) Read(c Conn) (ServerMessage, error) {
msg := SetColorMapEntries{}
var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
if err := binary.Read(c, binary.BigEndian, &msg.FirstColor); err != nil {
return nil, err
}
if err := binary.Read(c, binary.BigEndian, &msg.ColorsNum); err != nil {
return nil, err
}
msg.Colors = make([]Color, msg.ColorsNum)
colorMap := c.ColorMap()
for i := uint16(0); i < msg.ColorsNum; i++ {
color := &msg.Colors[i]
if err := binary.Read(c, binary.BigEndian, &color); err != nil {
return nil, err
}
colorMap[msg.FirstColor+i] = *color
}
c.SetColorMap(colorMap)
return &msg, nil
}
func (msg *SetColorMapEntries) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
var pad [1]byte
if err := binary.Write(c, binary.BigEndian, &pad); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg.FirstColor); err != nil {
return err
}
if msg.ColorsNum < uint16(len(msg.Colors)) {
msg.ColorsNum = uint16(len(msg.Colors))
}
if err := binary.Write(c, binary.BigEndian, msg.ColorsNum); err != nil {
return err
}
for i := 0; i < len(msg.Colors); i++ {
color := msg.Colors[i]
if err := binary.Write(c, binary.BigEndian, color); err != nil {
return err
}
}
return c.Flush()
}
var DefaultServerMessages = []ServerMessage{
&FramebufferUpdate{},
&SetColorMapEntries{},
&Bell{},
&ServerCutText{},
}
// ClientMessage represents a Client-to-Server RFB message type.
type ClientMessageType uint8
//go:generate stringer -type=ClientMessageType
// Client-to-Server message types.
const (
SetPixelFormatMsgType ClientMessageType = iota
_
SetEncodingsMsgType
FramebufferUpdateRequestMsgType
KeyEventMsgType
PointerEventMsgType
ClientCutTextMsgType
)
// SetPixelFormat holds the wire format message.
type SetPixelFormat struct {
_ [3]byte // padding
PF PixelFormat // pixel-format
}
func (msg *SetPixelFormat) String() string {
return fmt.Sprintf("%s", msg.PF)
}
func (*SetPixelFormat) Type() ClientMessageType {
return SetPixelFormatMsgType
}
func (msg *SetPixelFormat) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg); err != nil {
return err
}
pf := c.PixelFormat()
// Invalidate the color map.
if pf.TrueColor != 1 {
c.SetColorMap(ColorMap{})
}
return c.Flush()
}
func (*SetPixelFormat) Read(c Conn) (ClientMessage, error) {
msg := SetPixelFormat{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
// SetEncodings holds the wire format message, sans encoding-type field.
type SetEncodings struct {
_ [1]byte // padding
EncNum uint16 // number-of-encodings
Encodings []EncodingType
}
func (msg *SetEncodings) String() string {
return fmt.Sprintf("encnum: %d, encodings[]: { %v }", msg.EncNum, msg.Encodings)
}
func (*SetEncodings) Type() ClientMessageType {
return SetEncodingsMsgType
}
func (*SetEncodings) Read(c Conn) (ClientMessage, error) {
msg := SetEncodings{}
var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
if err := binary.Read(c, binary.BigEndian, &msg.EncNum); err != nil {
return nil, err
}
var enc EncodingType
for i := uint16(0); i < msg.EncNum; i++ {
if err := binary.Read(c, binary.BigEndian, &enc); err != nil {
return nil, err
}
msg.Encodings = append(msg.Encodings, enc)
}
c.SetEncodings(msg.Encodings)
return &msg, nil
}
func (msg *SetEncodings) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
var pad [1]byte
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
if uint16(len(msg.Encodings)) > msg.EncNum {
msg.EncNum = uint16(len(msg.Encodings))
}
if err := binary.Write(c, binary.BigEndian, msg.EncNum); err != nil {
return err
}
for _, enc := range msg.Encodings {
if err := binary.Write(c, binary.BigEndian, enc); err != nil {
return err
}
}
return c.Flush()
}
// FramebufferUpdateRequest holds the wire format message.
type FramebufferUpdateRequest struct {
Inc uint8 // incremental
X, Y uint16 // x-, y-position
Width, Height uint16 // width, height
}
func (msg *FramebufferUpdateRequest) String() string {
return fmt.Sprintf("incremental: %d, x: %d, y: %d, width: %d, height: %d", msg.Inc, msg.X, msg.Y, msg.Width, msg.Height)
}
func (*FramebufferUpdateRequest) Type() ClientMessageType {
return FramebufferUpdateRequestMsgType
}
func (*FramebufferUpdateRequest) Read(c Conn) (ClientMessage, error) {
msg := FramebufferUpdateRequest{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *FramebufferUpdateRequest) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg); err != nil {
return err
}
return c.Flush()
}
// KeyEvent holds the wire format message.
type KeyEvent struct {
Down uint8 // down-flag
_ [2]byte // padding
Key Key // key
}
func (msg *KeyEvent) String() string {
return fmt.Sprintf("down: %d, key: %v", msg.Down, msg.Key)
}
func (*KeyEvent) Type() ClientMessageType {
return KeyEventMsgType
}
func (*KeyEvent) Read(c Conn) (ClientMessage, error) {
msg := KeyEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *KeyEvent) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg); err != nil {
return err
}
return c.Flush()
}
// PointerEventMessage holds the wire format message.
type PointerEvent struct {
Mask uint8 // button-mask
X, Y uint16 // x-, y-position
}
func (msg *PointerEvent) String() string {
return fmt.Sprintf("mask %d, x: %d, y: %d", msg.Mask, msg.X, msg.Y)
}
func (*PointerEvent) Type() ClientMessageType {
return PointerEventMsgType
}
func (*PointerEvent) Read(c Conn) (ClientMessage, error) {
msg := PointerEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *PointerEvent) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg); err != nil {
return err
}
return c.Flush()
}
// ClientCutText holds the wire format message, sans the text field.
type ClientCutText struct {
_ [3]byte // padding
Length uint32 // length
Text []byte
}
func (msg *ClientCutText) String() string {
return fmt.Sprintf("length: %d, text: %s", msg.Length, msg.Text)
}
func (*ClientCutText) Type() ClientMessageType {
return ClientCutTextMsgType
}
func (*ClientCutText) Read(c Conn) (ClientMessage, error) {
msg := ClientCutText{}
var pad [3]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
if err := binary.Read(c, binary.BigEndian, &msg.Length); err != nil {
return nil, err
}
msg.Text = make([]byte, msg.Length)
if err := binary.Read(c, binary.BigEndian, &msg.Text); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *ClientCutText) Write(c Conn) error {
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
var pad [3]byte
if err := binary.Write(c, binary.BigEndian, &pad); err != nil {
return err
}
if uint32(len(msg.Text)) > msg.Length {
msg.Length = uint32(len(msg.Text))
}
if err := binary.Write(c, binary.BigEndian, msg.Length); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, msg.Text); err != nil {
return err
}
return c.Flush()
}