package common import ( "bytes" "encoding/binary" "io" ) // An IEncoding implements a method for encoding pixel data that is // sent by the server to the client. type IEncoding interface { // The number that uniquely identifies this encoding type. Type() int32 WriteTo(w io.Writer) (n int, err error) // Read reads the contents of the encoded pixel data from the reader. // This should return a new IEncoding implementation that contains // the proper data. Read(*PixelFormat, *Rectangle, *RfbReadHelper) (IEncoding, error) } // EncodingType represents a known VNC encoding type. type EncodingType int32 func (enct EncodingType) String() string { switch enct { case EncRaw: return "EncRaw" case EncCopyRect: return "EncCopyRect" case EncRRE: return "EncRRE" case EncCoRRE: return "EncCoRRE" case EncHextile: return "EncHextile" case EncZlib: return "EncZlib" case EncTight: return "EncTight" case EncZlibHex: return "EncZlibHex" case EncUltra1: return "EncUltra1" case EncUltra2: return "EncUltra2" case EncJPEG: return "EncJPEG" case EncJRLE: return "EncJRLE" case EncTRLE: return "EncTRLE" case EncZRLE: return "EncZRLE" case EncJPEGQualityLevelPseudo10: return "EncJPEGQualityLevelPseudo10" case EncJPEGQualityLevelPseudo9: return "EncJPEGQualityLevelPseudo9" case EncJPEGQualityLevelPseudo8: return "EncJPEGQualityLevelPseudo8" case EncJPEGQualityLevelPseudo7: return "EncJPEGQualityLevelPseudo7" case EncJPEGQualityLevelPseudo6: return "EncJPEGQualityLevelPseudo6" case EncJPEGQualityLevelPseudo5: return "EncJPEGQualityLevelPseudo5" case EncJPEGQualityLevelPseudo4: return "EncJPEGQualityLevelPseudo4" case EncJPEGQualityLevelPseudo3: return "EncJPEGQualityLevelPseudo3" case EncJPEGQualityLevelPseudo2: return "EncJPEGQualityLevelPseudo2" case EncJPEGQualityLevelPseudo1: return "EncJPEGQualityLevelPseudo1" case EncCursorPseudo: return "EncCursorPseudo" case EncDesktopSizePseudo: return "EncDesktopSizePseudo" case EncLastRectPseudo: return "EncLastRectPseudo" case EncPointerPosPseudo: return "EncPointerPosPseudo" case EncCompressionLevel10: return "EncCompressionLevel10" case EncCompressionLevel9: return "EncCompressionLevel9" case EncCompressionLevel8: return "EncCompressionLevel8" case EncCompressionLevel7: return "EncCompressionLevel7" case EncCompressionLevel6: return "EncCompressionLevel6" case EncCompressionLevel5: return "EncCompressionLevel5" case EncCompressionLevel4: return "EncCompressionLevel4" case EncCompressionLevel3: return "EncCompressionLevel3" case EncCompressionLevel2: return "EncCompressionLevel2" case EncCompressionLevel1: return "EncCompressionLevel1" case EncQEMUPointerMotionChangePseudo: return "EncQEMUPointerMotionChangePseudo" case EncQEMUExtendedKeyEventPseudo: return "EncQEMUExtendedKeyEventPseudo" case EncTightPng: return "EncTightPng" case EncExtendedDesktopSizePseudo: return "EncExtendedDesktopSizePseudo" case EncXvpPseudo: return "EncXvpPseudo" case EncFencePseudo: return "EncFencePseudo" case EncContinuousUpdatesPseudo: return "EncContinuousUpdatesPseudo" case EncClientRedirect: return "EncClientRedirect" case EncTightPNGBase64: return "EncTightPNGBase64" case EncTightDiffComp: return "EncTightDiffComp" case EncVMWDefineCursor: return "EncVMWDefineCursor" case EncVMWCursorState: return "EncVMWCursorState" case EncVMWCursorPosition: return "EncVMWCursorPosition" case EncVMWTypematicInfo: return "EncVMWTypematicInfo" case EncVMWLEDState: return "EncVMWLEDState" case EncVMWServerPush2: return "EncVMWServerPush2" case EncVMWServerCaps: return "EncVMWServerCaps" case EncVMWFrameStamp: return "EncVMWFrameStamp" case EncOffscreenCopyRect: return "EncOffscreenCopyRect" } return "" } const ( EncRaw EncodingType = 0 EncCopyRect EncodingType = 1 EncRRE EncodingType = 2 EncCoRRE EncodingType = 4 EncHextile EncodingType = 5 EncZlib EncodingType = 6 EncTight EncodingType = 7 EncZlibHex EncodingType = 8 EncUltra1 EncodingType = 9 EncUltra2 EncodingType = 10 EncJPEG EncodingType = 21 EncJRLE EncodingType = 22 EncTRLE EncodingType = 15 EncZRLE EncodingType = 16 EncJPEGQualityLevelPseudo10 EncodingType = -23 EncJPEGQualityLevelPseudo9 EncodingType = -24 EncJPEGQualityLevelPseudo8 EncodingType = -25 EncJPEGQualityLevelPseudo7 EncodingType = -26 EncJPEGQualityLevelPseudo6 EncodingType = -27 EncJPEGQualityLevelPseudo5 EncodingType = -28 EncJPEGQualityLevelPseudo4 EncodingType = -29 EncJPEGQualityLevelPseudo3 EncodingType = -30 EncJPEGQualityLevelPseudo2 EncodingType = -31 EncJPEGQualityLevelPseudo1 EncodingType = -32 EncCursorPseudo EncodingType = -239 EncDesktopSizePseudo EncodingType = -223 EncLastRectPseudo EncodingType = -224 EncPointerPosPseudo EncodingType = -232 EncCompressionLevel10 EncodingType = -247 EncCompressionLevel9 EncodingType = -248 EncCompressionLevel8 EncodingType = -249 EncCompressionLevel7 EncodingType = -250 EncCompressionLevel6 EncodingType = -251 EncCompressionLevel5 EncodingType = -252 EncCompressionLevel4 EncodingType = -253 EncCompressionLevel3 EncodingType = -254 EncCompressionLevel2 EncodingType = -255 EncCompressionLevel1 EncodingType = -256 EncQEMUPointerMotionChangePseudo EncodingType = -257 EncQEMUExtendedKeyEventPseudo EncodingType = -258 EncTightPng EncodingType = -260 EncExtendedDesktopSizePseudo EncodingType = -308 EncXvpPseudo EncodingType = -309 EncFencePseudo EncodingType = -312 EncContinuousUpdatesPseudo EncodingType = -313 EncClientRedirect EncodingType = -311 EncTightPNGBase64 EncodingType = 21 + 0x574d5600 EncTightDiffComp EncodingType = 22 + 0x574d5600 EncVMWDefineCursor EncodingType = 100 + 0x574d5600 EncVMWCursorState EncodingType = 101 + 0x574d5600 EncVMWCursorPosition EncodingType = 102 + 0x574d5600 EncVMWTypematicInfo EncodingType = 103 + 0x574d5600 EncVMWLEDState EncodingType = 104 + 0x574d5600 EncVMWServerPush2 EncodingType = 123 + 0x574d5600 EncVMWServerCaps EncodingType = 122 + 0x574d5600 EncVMWFrameStamp EncodingType = 124 + 0x574d5600 EncOffscreenCopyRect EncodingType = 126 + 0x574d5600 ) // PixelFormat describes the way a pixel is formatted for a VNC connection. // // See RFC 6143 Section 7.4 for information on each of the fields. type PixelFormat struct { BPP uint8 Depth uint8 BigEndian uint8 TrueColor uint8 RedMax uint16 GreenMax uint16 BlueMax uint16 RedShift uint8 GreenShift uint8 BlueShift uint8 } func (format *PixelFormat) WriteTo(w io.Writer) error { var buf bytes.Buffer // Byte 1 if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil { return err } // Byte 2 if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil { return err } var boolByte byte if format.BigEndian == 1 { boolByte = 1 } else { boolByte = 0 } // Byte 3 (BigEndian) if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil { return err } if format.TrueColor == 1 { boolByte = 1 } else { boolByte = 0 } // Byte 4 (TrueColor) if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil { return err } // If we have true color enabled then we have to fill in the rest of the // structure with the color values. if format.TrueColor == 1 { if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil { return err } if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil { return err } if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil { return err } if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil { return err } if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil { return err } if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil { return err } } w.Write(buf.Bytes()[0:16]) return nil } func NewPixelFormat(bpp uint8) *PixelFormat { bigEndian := 0 // rgbMax := uint16(math.Exp2(float64(bpp))) - 1 rMax := uint16(255) gMax := uint16(255) bMax := uint16(255) var ( tc = 1 rs, gs, bs uint8 depth uint8 ) switch bpp { case 8: tc = 0 depth = 8 rs, gs, bs = 0, 0, 0 case 16: depth = 16 rs, gs, bs = 0, 4, 8 case 32: depth = 24 // rs, gs, bs = 0, 8, 16 rs, gs, bs = 16, 8, 0 } return &PixelFormat{bpp, depth, uint8(bigEndian), uint8(tc), rMax, gMax, bMax, rs, gs, bs} }