diff --git a/aten.go b/aten.go new file mode 100644 index 0000000..35cd942 --- /dev/null +++ b/aten.go @@ -0,0 +1,189 @@ +package vnc + +import ( + "encoding/binary" + "fmt" +) + +const ( + AteniKVMFrontGroundEventMsgType ServerMessageType = 4 + AteniKVMKeepAliveEventMsgType ServerMessageType = 22 + AteniKVMVideoGetInfoMsgType ServerMessageType = 51 + AteniKVMMouseGetInfoMsgType ServerMessageType = 55 + AteniKVMSessionMessageMsgType ServerMessageType = 57 + AteniKVMGetViewerLangMsgType ServerMessageType = 60 +) + +type AteniKVMFrontGroundEvent struct { + _ [20]byte +} + +func (msg *AteniKVMFrontGroundEvent) String() string { + return fmt.Sprintf("%s", msg.Type()) +} + +func (*AteniKVMFrontGroundEvent) Type() ServerMessageType { + return AteniKVMFrontGroundEventMsgType +} + +func (*AteniKVMFrontGroundEvent) Read(c Conn) (ServerMessage, error) { + msg := &AteniKVMFrontGroundEvent{} + var pad [20]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return nil, err + } + return msg, nil +} + +func (*AteniKVMFrontGroundEvent) Write(c Conn) error { + var pad [20]byte + if err := binary.Write(c, binary.BigEndian, pad); err != nil { + return err + } + return nil +} + +type AteniKVMKeepAliveEvent struct { + _ [1]byte +} + +func (msg *AteniKVMKeepAliveEvent) String() string { + return fmt.Sprintf("%s", msg.Type()) +} + +func (*AteniKVMKeepAliveEvent) Type() ServerMessageType { + return AteniKVMKeepAliveEventMsgType +} + +func (*AteniKVMKeepAliveEvent) Read(c Conn) (ServerMessage, error) { + msg := &AteniKVMKeepAliveEvent{} + var pad [1]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return nil, err + } + return msg, nil +} + +func (*AteniKVMKeepAliveEvent) Write(c Conn) error { + var pad [1]byte + if err := binary.Write(c, binary.BigEndian, pad); err != nil { + return err + } + return nil +} + +type AteniKVMVideoGetInfo struct { + _ [20]byte +} + +func (msg *AteniKVMVideoGetInfo) String() string { + return fmt.Sprintf("%s", msg.Type()) +} + +func (*AteniKVMVideoGetInfo) Type() ServerMessageType { + return AteniKVMVideoGetInfoMsgType +} + +func (*AteniKVMVideoGetInfo) Read(c Conn) (ServerMessage, error) { + msg := &AteniKVMVideoGetInfo{} + var pad [40]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return nil, err + } + return msg, nil +} + +func (*AteniKVMVideoGetInfo) Write(c Conn) error { + var pad [4]byte + if err := binary.Write(c, binary.BigEndian, pad); err != nil { + return err + } + return nil +} + +type AteniKVMMouseGetInfo struct { + _ [2]byte +} + +func (msg *AteniKVMMouseGetInfo) String() string { + return fmt.Sprintf("%s", msg.Type()) +} + +func (*AteniKVMMouseGetInfo) Type() ServerMessageType { + return AteniKVMMouseGetInfoMsgType +} + +func (*AteniKVMMouseGetInfo) Read(c Conn) (ServerMessage, error) { + msg := &AteniKVMFrontGroundEvent{} + var pad [2]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return nil, err + } + return msg, nil +} + +func (*AteniKVMMouseGetInfo) Write(c Conn) error { + var pad [2]byte + if err := binary.Write(c, binary.BigEndian, pad); err != nil { + return err + } + return nil +} + +type AteniKVMSessionMessage struct { + _ [264]byte +} + +func (msg *AteniKVMSessionMessage) String() string { + return fmt.Sprintf("%s", msg.Type()) +} + +func (*AteniKVMSessionMessage) Type() ServerMessageType { + return AteniKVMFrontGroundEventMsgType +} + +func (*AteniKVMSessionMessage) Read(c Conn) (ServerMessage, error) { + msg := &AteniKVMSessionMessage{} + var pad [264]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return nil, err + } + return msg, nil +} + +func (*AteniKVMSessionMessage) Write(c Conn) error { + var pad [264]byte + if err := binary.Write(c, binary.BigEndian, pad); err != nil { + return err + } + return nil +} + +type AteniKVMGetViewerLang struct { + _ [8]byte +} + +func (msg *AteniKVMGetViewerLang) String() string { + return fmt.Sprintf("%s", msg.Type()) +} + +func (*AteniKVMGetViewerLang) Type() ServerMessageType { + return AteniKVMGetViewerLangMsgType +} + +func (*AteniKVMGetViewerLang) Read(c Conn) (ServerMessage, error) { + msg := &AteniKVMGetViewerLang{} + var pad [8]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return nil, err + } + return msg, nil +} + +func (*AteniKVMGetViewerLang) Write(c Conn) error { + var pad [8]byte + if err := binary.Write(c, binary.BigEndian, pad); err != nil { + return err + } + return nil +} diff --git a/encoding_atenhermon.go b/encoding_atenhermon.go new file mode 100644 index 0000000..bb0f7e5 --- /dev/null +++ b/encoding_atenhermon.go @@ -0,0 +1,158 @@ +package vnc + +import ( + "encoding/binary" + "fmt" +) + +type AtenHermon struct { + _ [4]byte + AtenLength uint32 + AtenType uint8 + _ [1]byte + AtenSubrects uint32 + AtenRawLength uint32 + Encodings []Encoding +} + +func (*AtenHermon) Type() EncodingType { return EncAtenHermon } + +func (enc *AtenHermon) Read(c Conn, rect *Rectangle) error { + var pad4 [4]byte + + if err := binary.Read(c, binary.BigEndian, &pad4); err != nil { + return err + } + + var aten_length uint32 + if err := binary.Read(c, binary.BigEndian, &aten_length); err != nil { + return err + } + enc.AtenLength = aten_length + + if rect.Width == 64896 && rect.Height == 65056 { + if aten_length != 10 && aten_length != 0 { + return fmt.Errorf("screen is off and length is invalid") + } + aten_length = 0 + } + + if c.Width() != rect.Width && c.Height() != rect.Height { + c.SetWidth(rect.Width) + c.SetHeight(rect.Height) + } + + var aten_type uint8 + if err := binary.Read(c, binary.BigEndian, &aten_type); err != nil { + return err + } + enc.AtenType = aten_type + + var pad1 [1]byte + if err := binary.Read(c, binary.BigEndian, &pad1); err != nil { + return err + } + + var subrects uint32 + if err := binary.Read(c, binary.BigEndian, &subrects); err != nil { + return err + } + enc.AtenSubrects = subrects + + var raw_length uint32 + if err := binary.Read(c, binary.BigEndian, &raw_length); err != nil { + return err + } + enc.AtenRawLength = raw_length + + if aten_length != raw_length { + return fmt.Errorf("aten_length != raw_length, %d != %d", aten_length, raw_length) + } + + aten_length -= 10 // skip + + for aten_length > 0 { + switch aten_type { + case 0: //subrects + panic("unknown subrect") + var a uint16 + var b uint16 + var x uint8 + var y uint8 + if err := binary.Read(c, binary.BigEndian, &a); err != nil { + return err + } + if err := binary.Read(c, binary.BigEndian, &b); err != nil { + return err + } + if err := binary.Read(c, binary.BigEndian, &y); err != nil { + return err + } + if err := binary.Read(c, binary.BigEndian, &x); err != nil { + return err + } + data := make([]byte, 16*16*uint32(c.PixelFormat().BPP)) + if err := binary.Read(c, binary.BigEndian, &data); err != nil { + return err + } + + aten_length -= 6 + (16 * 16 * uint32(c.PixelFormat().BPP)) + case 1: //raw + fmt.Printf("raw reader %d %s\n", aten_length, rect) + encRaw := &RawEncoding{} + if err := encRaw.Read(c, rect); err != nil { + return err + } + enc.Encodings = append(enc.Encodings, encRaw) + aten_length = 0 + //aten_length -= uint32(rect.Area()) * uint32(c.PixelFormat().BPP) + default: + return fmt.Errorf("unknown aten hermon type %d", aten_type) + + } + } + + if aten_length < 0 { + return fmt.Errorf("aten_len dropped below zero") + } + fmt.Printf("aten hermon readed\n") + return nil +} + +func (enc *AtenHermon) Write(c Conn, rect *Rectangle) error { + var pad4 [4]byte + + if err := binary.Write(c, binary.BigEndian, pad4); err != nil { + return err + } + + if err := binary.Write(c, binary.BigEndian, enc.AtenLength); err != nil { + return err + } + + if err := binary.Write(c, binary.BigEndian, enc.AtenType); err != nil { + return err + } + + var pad1 [1]byte + if err := binary.Write(c, binary.BigEndian, pad1); err != nil { + return err + } + + if err := binary.Write(c, binary.BigEndian, enc.AtenSubrects); err != nil { + return err + } + + if err := binary.Write(c, binary.BigEndian, enc.AtenRawLength); err != nil { + return err + } + + for _, ew := range enc.Encodings { + if err := ew.Write(c, rect); err != nil { + return err + } + } + + fmt.Printf("aten hermon writed\n") + return nil +} diff --git a/encoding_raw.go b/encoding_raw.go index dd415bc..29acce2 100644 --- a/encoding_raw.go +++ b/encoding_raw.go @@ -6,33 +6,34 @@ type RawEncoding struct { func (enc *RawEncoding) Write(c Conn, rect *Rectangle) error { var err error + for _, clr := range enc.Colors { if err = clr.Write(c); err != nil { - break + return err } } + return err } // Read implements the Encoding interface. func (enc *RawEncoding) Read(c Conn, rect *Rectangle) error { - var err error pf := c.PixelFormat() cm := c.ColorMap() colors := make([]Color, rect.Area()) -Loop: + for y := uint16(0); y < rect.Height; y++ { for x := uint16(0); x < rect.Width; x++ { color := NewColor(&pf, &cm) - if err = color.Read(c); err != nil { - break Loop + if err := color.Read(c); err != nil { + return err } colors[int(y)*int(rect.Width)+int(x)] = *color } } enc.Colors = colors - return err + return nil } func (*RawEncoding) Type() EncodingType { return EncRaw } diff --git a/handlers.go b/handlers.go index f0aed68..1ed7ae2 100644 --- a/handlers.go +++ b/handlers.go @@ -246,16 +246,18 @@ func (*DefaultClientServerInitHandler) Handle(c Conn) error { return err } - nameText := make([]byte, srvInit.NameLength) - if err := binary.Read(c, binary.BigEndian, nameText); err != nil { + srvInit.NameText = make([]byte, srvInit.NameLength) + if err := binary.Read(c, binary.BigEndian, &srvInit.NameText); err != nil { return err } - - srvInit.NameText = nameText c.SetDesktopName(srvInit.NameText) c.SetWidth(srvInit.FBWidth) c.SetHeight(srvInit.FBHeight) - c.SetPixelFormat(srvInit.PixelFormat) + if c.Protocol() == "aten" { + c.SetPixelFormat(NewPixelFormatAten()) + } else { + c.SetPixelFormat(srvInit.PixelFormat) + } if c.Protocol() == "aten" { ikvm := struct { @@ -278,13 +280,13 @@ func (*DefaultClientServerInitHandler) Handle(c Conn) error { return err } - caps.ServerMessagesNum = uint16(1) + caps.ServerMessagesNum = uint16(16) var item [16]byte for i := uint16(0); i < caps.ServerMessagesNum; i++ { if err := binary.Read(c, binary.BigEndian, &item); err != nil { return err } - fmt.Printf("server message cap %s\n", item) + fmt.Printf("server message cap %v\n", item) } /* for i := uint16(0); i < caps.ClientMessagesNum; i++ { @@ -300,6 +302,10 @@ func (*DefaultClientServerInitHandler) Handle(c Conn) error { fmt.Printf("encoding cap %s\n", item) } */ + var pad [1]byte + if err := binary.Read(c, binary.BigEndian, &pad); err != nil { + return err + } } return nil } diff --git a/image.go b/image.go index dfe3637..0ad376c 100644 --- a/image.go +++ b/image.go @@ -35,6 +35,10 @@ type Rectangle struct { Enc Encoding } +func (rect *Rectangle) String() string { + return fmt.Sprintf("rect x: %d, y: %d, width: %d, height: %d, enc: %s", rect.X, rect.Y, rect.Width, rect.Height, rect.EncType) +} + func NewRectangle() *Rectangle { return &Rectangle{} } @@ -195,7 +199,6 @@ func (r *Rectangle) Write(c Conn) error { func (r *Rectangle) Read(c Conn) error { var err error - if err = binary.Read(c, binary.BigEndian, &r.X); err != nil { return err } @@ -219,13 +222,19 @@ func (r *Rectangle) Read(c Conn) error { case EncTightPng: r.Enc = &TightPngEncoding{} case EncRaw: - r.Enc = &RawEncoding{} + if c.Protocol() == "aten" { + r.Enc = &AtenHermon{} + } else { + r.Enc = &RawEncoding{} + } case EncDesktopSizePseudo: r.Enc = &DesktopSizePseudoEncoding{} case EncDesktopNamePseudo: r.Enc = &DesktopNamePseudoEncoding{} case EncXCursorPseudo: r.Enc = &XCursorPseudoEncoding{} + case EncAtenHermon: + r.Enc = &AtenHermon{} default: return fmt.Errorf("unsupported encoding %s", r.EncType) } diff --git a/pixel_format.go b/pixel_format.go index 1e926dc..3f2df20 100644 --- a/pixel_format.go +++ b/pixel_format.go @@ -13,6 +13,7 @@ var ( PixelFormat8bit PixelFormat = NewPixelFormat(8) PixelFormat16bit PixelFormat = NewPixelFormat(16) PixelFormat32bit PixelFormat = NewPixelFormat(32) + PixelFormatAten PixelFormat = NewPixelFormatAten() ) // PixelFormat describes the way a pixel is formatted for a VNC connection. @@ -74,6 +75,10 @@ func NewPixelFormat(bpp uint8) PixelFormat { return PixelFormat{bpp, depth, bigEndian, tc, rMax, gMax, bMax, rs, gs, bs, [3]byte{}} } +func NewPixelFormatAten() PixelFormat { + return PixelFormat{16, 15, 0, 1, (1 << 5) - 1, (1 << 5) - 1, (1 << 5) - 1, 10, 5, 0, [3]byte{}} +} + // Marshal implements the Marshaler interface. func (pf PixelFormat) Marshal() ([]byte, error) { // Validation checks. diff --git a/server.go b/server.go index a5e86a1..c4b9231 100644 --- a/server.go +++ b/server.go @@ -25,8 +25,8 @@ type ServerInit struct { NameText []byte } -func (srvInit *ServerInit) String() string { - return fmt.Sprintf("Width: %d, Height: %d, PixelFormat: %s, Name: %s", srvInit.FBWidth, srvInit.FBHeight, &srvInit.PixelFormat, srvInit.NameText) +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) } var _ Conn = (*ServerConn)(nil) @@ -159,8 +159,9 @@ func (*FramebufferUpdate) Read(c Conn) (ServerMessage, error) { if err := binary.Read(c, binary.BigEndian, &msg.NumRect); err != nil { return nil, err } + fmt.Printf("fb update %s\n", msg) for i := uint16(0); i < msg.NumRect; i++ { - rect := &Rectangle{} + rect := NewRectangle() if err := rect.Read(c); err != nil { return nil, err } diff --git a/servermessagetype_string.go b/servermessagetype_string.go index 51624ea..1a9ebf7 100644 --- a/servermessagetype_string.go +++ b/servermessagetype_string.go @@ -4,13 +4,39 @@ package vnc import "fmt" -const _ServerMessageType_name = "FramebufferUpdateMsgTypeSetColorMapEntriesMsgTypeBellMsgTypeServerCutTextMsgType" +const ( + _ServerMessageType_name_0 = "FramebufferUpdateMsgTypeSetColorMapEntriesMsgTypeBellMsgTypeServerCutTextMsgTypeAteniKVMFrontGroundEventMsgType" + _ServerMessageType_name_1 = "AteniKVMKeepAliveEventMsgType" + _ServerMessageType_name_2 = "AteniKVMVideoGetInfoMsgType" + _ServerMessageType_name_3 = "AteniKVMMouseGetInfoMsgType" + _ServerMessageType_name_4 = "AteniKVMSessionMessageMsgType" + _ServerMessageType_name_5 = "AteniKVMGetViewerLangMsgType" +) -var _ServerMessageType_index = [...]uint8{0, 24, 49, 60, 80} +var ( + _ServerMessageType_index_0 = [...]uint8{0, 24, 49, 60, 80, 111} + _ServerMessageType_index_1 = [...]uint8{0, 29} + _ServerMessageType_index_2 = [...]uint8{0, 27} + _ServerMessageType_index_3 = [...]uint8{0, 27} + _ServerMessageType_index_4 = [...]uint8{0, 29} + _ServerMessageType_index_5 = [...]uint8{0, 28} +) func (i ServerMessageType) String() string { - if i >= ServerMessageType(len(_ServerMessageType_index)-1) { + switch { + case 0 <= i && i <= 4: + return _ServerMessageType_name_0[_ServerMessageType_index_0[i]:_ServerMessageType_index_0[i+1]] + case i == 22: + return _ServerMessageType_name_1 + case i == 51: + return _ServerMessageType_name_2 + case i == 55: + return _ServerMessageType_name_3 + case i == 57: + return _ServerMessageType_name_4 + case i == 60: + return _ServerMessageType_name_5 + default: return fmt.Sprintf("ServerMessageType(%d)", i) } - return _ServerMessageType_name[_ServerMessageType_index[i]:_ServerMessageType_index[i+1]] }