From 16f897ddfe2c89f96d4e913a910ff51a9121fe06 Mon Sep 17 00:00:00 2001 From: amit bezalel Date: Sat, 30 Dec 2017 02:00:28 +0200 Subject: [PATCH] first working tight encoding reader --- .vscode/launch.json | 19 ++ .vscode/tasks.json | 46 +++ button_string.go | 2 +- buttons.go | 2 +- client.go | 39 ++- clientmessagetype_string.go | 2 +- conn.go | 3 +- encoding.go | 2 +- encoding_atenhermon.go | 2 +- encoding_copyrect.go | 2 +- encoding_cursor.go | 2 +- encoding_desktopname.go | 2 +- encoding_desktopsize.go | 2 +- encoding_raw.go | 2 +- encoding_tight.go | 643 +++++++++++++++++++++++++++++++++++- encoding_tightpng.go | 4 +- encoding_xcursor.go | 2 +- encodingtype_string.go | 2 +- example/client/main.go | 46 ++- example/proxy/main.go | 15 +- example/server/main.go | 30 +- handlers.go | 8 +- image.go | 4 +- key_string.go | 2 +- keys.go | 2 +- logger/logger.go | 156 +++++++++ messages.go | 16 +- messages_aten.go | 2 +- pixel_format.go | 2 +- security.go | 2 +- security_aten.go | 2 +- security_none.go | 2 +- security_tight.go | 2 +- security_vencryptplain.go | 2 +- security_vnc.go | 2 +- securitysubtype_string.go | 2 +- securitytype_string.go | 2 +- server.go | 5 +- tightcompression_string.go | 2 +- tightfilter_string.go | 2 +- 40 files changed, 1004 insertions(+), 82 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json create mode 100644 logger/logger.go diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..59c9844 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Launch Package", + "type": "go", + "request": "launch", + "mode": "debug", + "args": [ + "localhost:5903" + ], + "program": "${workspaceRoot}/example/client" + } + + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..b725b84 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,46 @@ +{ + "version": "0.1.0", + "command": "go", + "isShellCommand": true, + "echoCommand": true, + "showOutput": "always", + // "showOutput": "silent", + "options": { + // "env": { + // "GOPATH": "/Users/lukeh/dd/go" + // } + }, + "tasks": [ + { + "taskName": "install", + "args": [ + "-v", + "./..." + ], + "osx": { + "options": { + "env": { + //"GOPATH": "${env.HOME}/Dropbox/go" + } + } + }, + "windows": { + "options": { + "env": { + //"GOPATH": "${env.USERPROFILE}\\Dropbox\\go" + } + } + }, + "isBuildCommand": true, + "problemMatcher": "$go" + }, + { + "taskName": "test", + "args": [ + "-v", + "./..." + ], + "isTestCommand": true + } + ] +} \ No newline at end of file diff --git a/button_string.go b/button_string.go index d08d228..19fb0f7 100644 --- a/button_string.go +++ b/button_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=Button"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/buttons.go b/buttons.go index e10121d..005a445 100644 --- a/buttons.go +++ b/buttons.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm // Button represents a mask of pointer presses/releases. type Button uint8 diff --git a/client.go b/client.go index 5a5aa02..13baae4 100644 --- a/client.go +++ b/client.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bufio" @@ -7,6 +7,7 @@ import ( "fmt" "net" "sync" + "vnc2webm/logger" ) var ( @@ -51,6 +52,15 @@ func (c *ClientConn) Config() interface{} { return c.cfg } +func (c *ClientConn) GetEncInstance(typ EncodingType) Encoding { + for _, enc := range c.encodings { + if enc.Type() == typ { + return enc + } + } + return nil +} + // Wait waiting for connection close func (c *ClientConn) Wait() { <-c.quit @@ -183,7 +193,6 @@ type ClientConn struct { bw *bufio.Writer cfg *ClientConfig protocol string - // If the pixel format uses a color map, then this is the color // map that is used. This should not be modified directly, since // the data comes from the server. @@ -238,11 +247,12 @@ type DefaultClientMessageHandler struct{} // Handle handles server messages. func (*DefaultClientMessageHandler) Handle(c Conn) error { + logger.Debug("starting DefaultClientMessageHandler") cfg := c.Config().(*ClientConfig) var err error var wg sync.WaitGroup wg.Add(2) - defer c.Close() + //defer c.Close() serverMessages := make(map[ServerMessageType]ServerMessage) for _, m := range cfg.Messages { @@ -272,13 +282,17 @@ func (*DefaultClientMessageHandler) Handle(c Conn) error { cfg.ErrorCh <- err return } + logger.Debugf("got server message, msgType=%d", messageType) msg, ok := serverMessages[messageType] if !ok { err = fmt.Errorf("unknown message-type: %v", messageType) cfg.ErrorCh <- err return } + parsedMsg, err := msg.Read(c) + logger.Debugf("============== End Message: type=%d ==============", messageType) + if err != nil { cfg.ErrorCh <- err return @@ -287,8 +301,25 @@ func (*DefaultClientMessageHandler) Handle(c Conn) error { } } }() + //encodings := c.Encodings() + encTypes := make(map[EncodingType]EncodingType) + for _, myEnc := range c.Encodings() { + encTypes[myEnc.Type()] = myEnc.Type() + //encTypes = append(encTypes, myEnc.Type()) + } + v := make([]EncodingType, 0, len(encTypes)) - wg.Wait() + for _, value := range encTypes { + v = append(v, value) + } + logger.Debugf("setting encodings: %v", v) + c.SetEncodings(v) + + firstMsg := FramebufferUpdateRequest{Inc: 0, X: 0, Y: 0, Width: c.Width(), Height: c.Height()} + logger.Debugf("sending initial req message: %v", firstMsg) + firstMsg.Write(c) + + //wg.Wait() return nil } diff --git a/clientmessagetype_string.go b/clientmessagetype_string.go index 4951ffd..27fab0e 100644 --- a/clientmessagetype_string.go +++ b/clientmessagetype_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=ClientMessageType"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/conn.go b/conn.go index 7427cbf..371484f 100644 --- a/conn.go +++ b/conn.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "io" @@ -28,4 +28,5 @@ type Conn interface { SetProtoVersion(string) SetSecurityHandler(SecurityHandler) error SecurityHandler() SecurityHandler + GetEncInstance(EncodingType) Encoding } diff --git a/encoding.go b/encoding.go index 55d7b29..7d5a4a4 100644 --- a/encoding.go +++ b/encoding.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bytes" diff --git a/encoding_atenhermon.go b/encoding_atenhermon.go index b7b440e..0dd3587 100644 --- a/encoding_atenhermon.go +++ b/encoding_atenhermon.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "encoding/binary" diff --git a/encoding_copyrect.go b/encoding_copyrect.go index 9dd510f..e9e3692 100644 --- a/encoding_copyrect.go +++ b/encoding_copyrect.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import "encoding/binary" diff --git a/encoding_cursor.go b/encoding_cursor.go index c09c24a..ad1968b 100644 --- a/encoding_cursor.go +++ b/encoding_cursor.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import "encoding/binary" diff --git a/encoding_desktopname.go b/encoding_desktopname.go index 20be716..0da522d 100644 --- a/encoding_desktopname.go +++ b/encoding_desktopname.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import "encoding/binary" diff --git a/encoding_desktopsize.go b/encoding_desktopsize.go index f2db3c2..195f073 100644 --- a/encoding_desktopsize.go +++ b/encoding_desktopsize.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm // DesktopSizePseudoEncoding represents a desktop size message from the server. type DesktopSizePseudoEncoding struct{} diff --git a/encoding_raw.go b/encoding_raw.go index ab7d6c6..f63319d 100644 --- a/encoding_raw.go +++ b/encoding_raw.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm type RawEncoding struct { Colors []Color diff --git a/encoding_tight.go b/encoding_tight.go index 9b199ce..d3e4ea4 100644 --- a/encoding_tight.go +++ b/encoding_tight.go @@ -1,8 +1,20 @@ -package vnc +package vnc2webm import ( + "bytes" + "compress/zlib" "encoding/binary" + "errors" "fmt" + "image" + "image/color" + "image/draw" + "image/jpeg" + "io" + "math" + "os" + "strconv" + "vnc2webm/logger" ) //go:generate stringer -type=TightCompression @@ -10,10 +22,10 @@ import ( type TightCompression uint8 const ( - TightCompressionBasic TightCompression = 0 - TightCompressionFill TightCompression = 8 - TightCompressionJPEG TightCompression = 9 - TightCompressionPNG TightCompression = 10 + TightCompressionBasic = 0 + TightCompressionFill = 8 + TightCompressionJPEG = 9 + TightCompressionPNG = 10 ) //go:generate stringer -type=TightFilter @@ -21,12 +33,19 @@ const ( type TightFilter uint8 const ( - TightFilterCopy TightFilter = 0 - TightFilterPalette TightFilter = 1 - TightFilterGradient TightFilter = 2 + TightFilterCopy = 0 + TightFilterPalette = 1 + TightFilterGradient = 2 ) -type TightEncoding struct{} +type TightEncoding struct { + Image image.Image + decoders []io.Reader + decoderBuffs []*bytes.Reader +} + +var instance *TightEncoding +var TightMinToCompress int = 12 func (*TightEncoding) Supported(Conn) bool { return true @@ -34,12 +53,539 @@ func (*TightEncoding) Supported(Conn) bool { func (*TightEncoding) Type() EncodingType { return EncTight } +func (*TightEncoding) GetInstance() *TightEncoding { + if instance == nil { + instance = &TightEncoding{} + } + return instance +} + func (enc *TightEncoding) Write(c Conn, rect *Rectangle) error { return nil } +// Read unmarshal color from conn +func getTightColor(c io.Reader, pf *PixelFormat) (*color.RGBA64, error) { + if pf.TrueColor == 0 { + return nil, errors.New("support for non true color formats was not implemented") + } + order := pf.order() + var pixel uint32 + isTightFormat := pf.TrueColor != 0 && pf.Depth == 24 && pf.BPP == 32 && pf.BlueMax <= 255 && pf.RedMax <= 255 && pf.GreenMax <= 255 + if isTightFormat { + //tbytes := make([]byte, 3) + tbytes, err := ReadBytes(3, c) + if err != nil { + return nil, err + } + rgb := color.RGBA64{ + R: uint16(tbytes[0]), //byte(col >> pf.RedShift & int32(pf.RedMax)), + G: uint16(tbytes[1]), //byte(col >> pf.GreenShift & int32(pf.GreenMax)), + B: uint16(tbytes[2]), //byte(col >> pf.BlueShift & int32(pf.BlueMax)), + A: uint16(1), + } + return &rgb, nil + } + + switch pf.BPP { + case 8: + var px uint8 + if err := binary.Read(c, order, &px); err != nil { + return nil, err + } + pixel = uint32(px) + case 16: + var px uint16 + if err := binary.Read(c, order, &px); err != nil { + return nil, err + } + pixel = uint32(px) + case 32: + var px uint32 + if err := binary.Read(c, order, &px); err != nil { + return nil, err + } + pixel = uint32(px) + } + + rgb := color.RGBA64{ + R: uint16((pixel >> pf.RedShift) & uint32(pf.RedMax)), + G: uint16((pixel >> pf.GreenShift) & uint32(pf.GreenMax)), + B: uint16((pixel >> pf.BlueShift) & uint32(pf.BlueMax)), + } + + // else { + // *clr = clr.cm[pixel] + // clr.cmIndex = pixel + // } + return &rgb, nil +} + +// func getTightColor(bytes []byte, pf *PixelFormat) color.RGBA { +// col := (int32(bytes[0])&0xff)<<16 | (int32(bytes[1])&0xff)<<8 | int32(bytes[2])&0xff +// rgb := color.RGBA{ +// R: byte(col >> pf.RedShift & int32(pf.RedMax)), +// G: byte(col >> pf.GreenShift & int32(pf.GreenMax)), +// B: byte(col >> pf.BlueShift & int32(pf.BlueMax)), +// A: byte(1), +// } +// return rgb +// } + +func calcTightBytePerPixel(pf *PixelFormat) int { + bytesPerPixel := int(pf.BPP / 8) + + var bytesPerPixelTight int + if 24 == pf.Depth && 32 == pf.BPP { + bytesPerPixelTight = 3 + } else { + bytesPerPixelTight = bytesPerPixel + } + return bytesPerPixelTight +} + +func (enc *TightEncoding) resetDecoders(compControl uint8) { + for i := 0; i < 4; i++ { + if (compControl&1) != 0 && enc.decoders[i] != nil { + enc.decoders[i] = nil //.(zlib.Resetter).Reset(nil,nil); + } + compControl >>= 1 + } +} + +var counter int = 0 + func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error { - return nil + + var out *os.File + var err error + //////////// + if counter > 40 { + os.Exit(1) + } + //////////// + pixelFmt := c.PixelFormat() + bytesPixel := calcTightBytePerPixel(&pixelFmt) + if enc.Image == nil { + enc.Image = image.NewRGBA(image.Rect(0, 0, int(c.Width()), int(c.Height()))) + } + + //r.StartByteCollection() + + //r.StartByteCollection() + // defer func() { + // t.bytes = r.EndByteCollection() + // }() + + compctl, err := ReadUint8(c) + + ///////////////// + if out == nil { + out, err = os.Create("./output" + strconv.Itoa(counter) + "-" + strconv.Itoa(int(compctl)) + ".jpg") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + } + defer func() { counter++ }() + defer jpeg.Encode(out, enc.Image, nil) + ////////////// + + if err != nil { + logger.Errorf("error in handling tight encoding: %v", err) + return err + } + //logger.Debugf("bytesPixel= %d, subencoding= %d", bytesPixel, compctl) + enc.resetDecoders(compctl) + + //move it to position (remove zlib flush commands) + compType := compctl >> 4 & 0x0F + + //logger.Debugf("afterSHL:%d", compType) + switch compType { + case TightCompressionFill: + logger.Debugf("--TIGHT_FILL: reading fill size=%d,counter=%d", bytesPixel, counter) + //read color + pf := c.PixelFormat() + rectColor, err := getTightColor(c, &pf) + if err != nil { + logger.Errorf("error in reading tight encoding: %v", err) + return err + } + + //logger.Debugf("bytesPixel= %d, compctl= %d, color= %v", bytesPixel, compctl, rectColor) + + //imgRect := image.Rect(0, 0, int(c.Width()), int(c.Height())) + // if enc.Image == nil { + // enc.Image = image.NewRGBA(imgRect) + // } + + c1 := color.RGBAModel.Convert(rectColor).(color.RGBA) + + dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA) + var x, y int + + for y = int(rect.Y); y < int(rect.Height+rect.Y); y++ { + for x = int(rect.X); x < int(rect.Width+rect.X); x++ { + offset := dst.PixOffset(x, y) + dst.Pix[offset+0] = c1.R + dst.Pix[offset+1] = c1.G + dst.Pix[offset+2] = c1.B + dst.Pix[offset+3] = c1.A + + //dst.Set(int(x), int(y), c1) + //dst.Pix[y*uint16(dst.Bounds().Max.Y)+x] = []uint8{rectColor.R, rectColor.G, rectColor.B} + } + } + enc.Image = dst + + //draw.Draw(dst, imgRect, &image.Uniform{rectColor}, image.ZP, draw.Src) + + if bytesPixel != 3 { + return fmt.Errorf("non tight bytesPerPixel format, should be 3 bytes") + } + return nil + case TightCompressionJPEG: + logger.Debugf("--TIGHT_JPEG,counter=%d", counter) + if pixelFmt.BPP == 8 { + return errors.New("Tight encoding: JPEG is not supported in 8 bpp mode") + } + + len, err := readTightLength(c) + + if err != nil { + return err + } + //logger.Debugf("reading jpeg, size=%d\n", len) + jpegBytes, err := ReadBytes(len, c) + if err != nil { + return err + } + //TODO: check if we can read jpeg directly from stream (this is safer for now) + buff := bytes.NewBuffer(jpegBytes) + img, err := jpeg.Decode(buff) + if err != nil { + logger.Error("problem while decoding jpeg:", err) + } + enc.Image = img + + return nil + default: + + if compType > TightCompressionJPEG { + logger.Error("Compression control byte is incorrect!") + } + + enc.handleTightFilters(compctl, &pixelFmt, rect, c) + + return nil + } +} + +func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelFormat, rect *Rectangle, r Conn) { + var STREAM_ID_MASK uint8 = 0x30 + var FILTER_ID_MASK uint8 = 0x40 + + var filterid uint8 + var err error + + decoderId := (compCtl & STREAM_ID_MASK) >> 4 + + for len(enc.decoders) < 4 { + enc.decoders = append(enc.decoders, nil) + enc.decoderBuffs = append(enc.decoderBuffs, nil) + } + + if (compCtl & FILTER_ID_MASK) > 0 { + filterid, err = ReadUint8(r) + + if err != nil { + logger.Errorf("error in handling tight encoding, reading filterid: %v", err) + return + } + //logger.Debugf("handleTightFilters: read filter: %d", filterid) + } + + bytesPixel := calcTightBytePerPixel(pixelFmt) + + //logger.Debugf("handleTightFilters: filter: %d", filterid) + + lengthCurrentbpp := int(bytesPixel) * int(rect.Width) * int(rect.Height) + + switch filterid { + case TightFilterPalette: //PALETTE_FILTER + + palette, err := enc.readTightPalette(r, bytesPixel) + if err != nil { + logger.Errorf("handleTightFilters: error in Reading Palette: %v", err) + return + } + logger.Debugf("----PALETTE_FILTER,palette len=%d counter=%d, rect= %v", len(palette), counter, rect) + + //logger.Debugf("got palette: %v", palette) + var dataLength int + if len(palette) == 2 { + dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8) + } else { + dataLength = int(rect.Width * rect.Height) + } + tightBytes, err := enc.ReadTightData(dataLength, r, int(decoderId)) + //logger.Debugf("got tightBytes: %v", tightBytes) + if err != nil { + logger.Errorf("handleTightFilters: error in handling tight encoding, reading palette filter data: %v", err) + return + } + //logger.Errorf("handleTightFilters: got tight data: %v", tightBytes) + + myImg := enc.Image.(draw.Image) + bytePos := 0 + bitPos := 0 + var palettePos int + for i := 0; i < int(rect.Height); i++ { + for j := 0; j < int(rect.Width); j++ { + if len(palette) == 2 { + currByte := tightBytes[bytePos] + palettePos = int(currByte&byte(math.Pow(2.0, float64(bitPos)))) >> uint(bitPos) + //logger.Debugf("palletPos=%d, bitpos=%d, bytepos=%d", palettePos, bitPos, bytePos) + bytePos = bytePos + int((bitPos+1.0)/8.0) + bitPos = (bitPos + 1) % 8 + //logger.Debugf("next: bitpos=%d, bytepos=%d", bitPos, bytePos) + } else { + palettePos = int(tightBytes[bytePos]) + bytePos++ + } + myImg.Set(int(rect.X)+j, int(rect.Y)+i, palette[palettePos]) + //logger.Debugf("(%d,%d): pos: %d col:%d", int(rect.X)+j, int(rect.Y)+i, palettePos, palette[palettePos]) + } + } + //enc.Image = myImg + case TightFilterGradient: //GRADIENT_FILTER + logger.Debugf("----GRADIENT_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter) + //logger.Debugf("usegrad: %d\n", filterid) + data, err := enc.ReadTightData(lengthCurrentbpp, r, int(decoderId)) + if err != nil { + logger.Errorf("handleTightFilters: error in handling tight encoding, Reading GRADIENT_FILTER: %v", err) + return + } + enc.decodeGradData(rect, data) + + case TightFilterCopy: //BASIC_FILTER + //lengthCurrentbpp1 := int(pixelFmt.BPP/8) * int(rect.Width) * int(rect.Height) + logger.Debugf("----BASIC_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter) + + tightBytes, err := enc.ReadTightData(lengthCurrentbpp, r, int(decoderId)) + if err != nil { + logger.Errorf("handleTightFilters: error in handling tight encoding, Reading BASIC_FILTER: %v", err) + return + } + logger.Debugf("tightBytes len= %d", len(tightBytes)) + enc.drawTightBytes(tightBytes, rect) + default: + logger.Errorf("handleTightFilters: Bad tight filter id: %d", filterid) + return + } + + return +} +func (enc *TightEncoding) decodeGradData(rect *Rectangle, buffer []byte) { + + logger.Debugf("putting gradient size: %v on image: %v", rect, enc.Image.Bounds()) + + prevRow := make([]byte, rect.Width*3+3) //new byte[w * 3]; + thisRow := make([]byte, rect.Width*3+3) //new byte[w * 3]; + + bIdx := 0 + dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA) + + for i := 0; i < int(rect.Height); i++ { + for j := 3; j < int(rect.Width*3+3); j += 3 { + d := int(0xff&prevRow[j]) + // "upper" pixel (from prev row) + int(0xff&thisRow[j-3]) - // prev pixel + int(0xff&prevRow[j-3]) // "diagonal" prev pixel + if d < 0 { + d = 0 + } + if d > 255 { + d = 255 + } + red := int(buffer[bIdx]) + d + thisRow[j] = byte(red & 255) + + d = int(0xff&prevRow[j+1]) + + int(0xff&thisRow[j+1-3]) - + int(0xff&prevRow[j+1-3]) + if d < 0 { + d = 0 + } + if d > 255 { + d = 255 + } + green := int(buffer[bIdx+1]) + d + thisRow[j+1] = byte(green & 255) + + d = int(0xff&prevRow[j+2]) + + int(0xff&thisRow[j+2-3]) - + int(0xff&prevRow[j+2-3]) + if d < 0 { + d = 0 + } + if d > 255 { + d = 255 + } + blue := int(buffer[bIdx+2]) + d + thisRow[j+2] = byte(blue & 255) + + bIdx += 3 + } + + for idx := 3; idx < (len(thisRow) - 3); idx += 3 { + myColor := color.RGBA{R: (thisRow[idx]), G: (thisRow[idx+1]), B: (thisRow[idx+2]), A: 1} + dst.SetRGBA(idx/3+int(rect.X)-1, int(rect.Y)+i, myColor) + //logger.Debugf("putting pixel: idx=%d, pos=(%d,%d), col=%v", idx, idx/3+int(rect.X), int(rect.Y)+i, myColor) + + } + + // exchange thisRow and prevRow: + tempRow := thisRow + thisRow = prevRow + prevRow = tempRow + } +} + +func (enc *TightEncoding) decodeGradientData(rect *Rectangle, buf []byte) { + logger.Debugf("putting gradient on image: %v", enc.Image.Bounds()) + var dx, dy, c int + prevRow := make([]byte, rect.Width*3) //new byte[w * 3]; + thisRow := make([]byte, rect.Width*3) //new byte[w * 3]; + pix := make([]byte, 3) + est := make([]int, 3) + + dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA) + //offset := int(rect.Y)*dst.Bounds().Max.X + int(rect.X) + + for dy = 0; dy < int(rect.Height); dy++ { + //offset := dst.PixOffset(x, y) + /* First pixel in a row */ + for c = 0; c < 3; c++ { + pix[c] = byte(prevRow[c] + buf[dy*int(rect.Width)*3+c]) + thisRow[c] = pix[c] + } + //logger.Debugf("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), rect.X, rect.Y, rect.Width, rect.Height, dy) + myColor := color.RGBA{R: (pix[0]), G: (pix[1]), B: (pix[2]), A: 1} + dst.SetRGBA(int(rect.X), dy+int(rect.Y), myColor) + + /* Remaining pixels of a row */ + for dx = 1; dx < int(rect.Width); dx++ { + for c = 0; c < 3; c++ { + est[c] = int((prevRow[dx*3+c] & 0xFF) + (pix[c] & 0xFF) - (prevRow[(dx-1)*3+c] & 0xFF)) + if est[c] > 0xFF { + est[c] = 0xFF + } else if est[c] < 0x00 { + est[c] = 0x00 + } + pix[c] = (byte)(byte(est[c]) + buf[(dy*int(rect.Width)+dx)*3+c]) + thisRow[dx*3+c] = pix[c] + } + //logger.Debugf("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), x, y, w, h, dy) + myColor := color.RGBA{R: pix[0], G: (pix[1]), B: (pix[2]), A: 1} + dst.SetRGBA(dx+int(rect.X), dy+int(rect.Y), myColor) + + } + + copy(prevRow, thisRow) + } + enc.Image = dst +} + +func ReadBytes(count int, r io.Reader) ([]byte, error) { + buff := make([]byte, count) + + lengthRead, err := io.ReadFull(r, buff) + + //lengthRead, err := r.Read(buff) + if lengthRead != count { + logger.Errorf("RfbReadHelper.ReadBytes unable to read bytes: lengthRead=%d, countExpected=%d", lengthRead, count) + return nil, errors.New("RfbReadHelper.ReadBytes unable to read bytes") + } + + //err := binary.Read(r, binary.BigEndian, &buff) + + if err != nil { + logger.Errorf("RfbReadHelper.ReadBytes error while reading bytes: ", err) + //if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil { + return nil, err + } + + return buff, nil +} + +func (enc *TightEncoding) readTightPalette(connReader Conn, bytesPixel int) (color.Palette, error) { + + colorCount, err := ReadUint8(connReader) + if err != nil { + logger.Errorf("handleTightFilters: error in handling tight encoding, reading TightFilterPalette: %v", err) + return nil, err + } + + paletteSize := colorCount + 1 // add one more + //logger.Debugf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel) + //complete palette + paletteColorBytes, err := ReadBytes(int(paletteSize)*bytesPixel, connReader) + if err != nil { + logger.Errorf("handleTightFilters: error in handling tight encoding, reading TightFilterPalette.paletteSize: %v", err) + return nil, err + } + var paletteColors color.Palette = make([]color.Color, 0) + for i := 0; i < int(paletteSize)*bytesPixel; i += 3 { + col := color.RGBA{R: paletteColorBytes[i], G: paletteColorBytes[i+1], B: paletteColorBytes[i+2], A: 1} + paletteColors = append(paletteColors, col) + } + return paletteColors, nil +} + +func ReadUint8(r Conn) (uint8, error) { + var myUint uint8 + if err := binary.Read(r, binary.BigEndian, &myUint); err != nil { + return 0, err + } + + return myUint, nil +} + +func (enc *TightEncoding) ReadTightData(dataSize int, c Conn, decoderId int) ([]byte, error) { + if int(dataSize) < TightMinToCompress { + return ReadBytes(int(dataSize), c) + } + zlibDataLen, err := readTightLength(c) + //logger.Debugf("RfbReadHelper.ReadTightData: compactlen=%d", zlibDataLen) + if err != nil { + return nil, err + } + zippedBytes, err := ReadBytes(zlibDataLen, c) + if err != nil { + return nil, err + } + var r io.Reader + if enc.decoders[decoderId] == nil { + b := bytes.NewReader(zippedBytes) + r, err = zlib.NewReader(b) + enc.decoders[decoderId] = r + enc.decoderBuffs[decoderId] = b + } else { + b := enc.decoderBuffs[decoderId] + b.Reset(zippedBytes) //set the underlaying buffer to new content (not resetting the decoder zlib stream) + r = enc.decoders[decoderId] + } + + retBytes := make([]byte, dataSize) + count, err := io.ReadFull(r, retBytes) + if err != nil { + return nil, err + } + if count != dataSize { + return nil, errors.New("ReadTightData: reading inflating zip didn't produce expected number of bytes") + } + return retBytes, nil } type TightCC struct { @@ -129,3 +675,80 @@ func readTightLength(c Conn) (int, error) { return length, nil } + +/** + * Draw byte array bitmap data (for Tight) + */ +func (enc *TightEncoding) drawTightBytes(bytes []byte, rect *Rectangle) { + bytesPos := 0 + myImg := (enc.Image).(draw.Image) + logger.Debugf("drawTightBytes: len(bytes)= %d, %v", len(bytes), rect) + + for ly := rect.Y; ly < rect.Y+rect.Height; ly++ { + for lx := rect.X; lx < rect.X+rect.Width; lx++ { + color := color.RGBA{R: bytes[bytesPos], G: bytes[bytesPos+1], B: bytes[bytesPos+2], A: 1} + //logger.Debugf("drawTightBytes: setting pixel= (%d,%d): %v", int(lx), int(ly), color) + myImg.Set(int(lx), int(ly), color) + + bytesPos += 3 + } + } + //enc.Image = myImg +} + +// /** +// * Draw paletted byte array bitmap data +// * +// * @param buffer bitmap data +// * @param rect bitmap location and dimensions +// * @param palette colour palette +// * @param paletteSize number of colors in palette +// */ +// func (enc *TightPngEncoding) drawBytesWithPalette( buffer []byte, rect *Rectangle, palette []int, int paletteSize) { +// //create palette: +// var imgPalette []color.Color = make([]int, len(palette)) +// for i:=0;len(palette);i++{ +// col := color.RGBA{ +// R:,G:,B:,A:0 +// } +// imgPalette[i]=col +// } + +// //lock.lock(); +// img:=image.Paletted{ + +// } +// // 2 colors +// thisWidth := enc.Image.Bounds().Max.Y +// if paletteSize == 2 { +// var dx, dy, n int; +// i := rect.y * thisWidth + rect.x +// rowBytes := (rect.width + 7) / 8 +// var b byte; + +// for dy = 0; dy < rect.height; dy++ { +// for dx = 0; dx < rect.width / 8; dx++ { +// b = buffer[dy * rowBytes + dx]; +// for n = 7; n >= 0; n-- { +// color := palette[b >> n & 1] +// enc.Image.(draw.Image).Set(0, 0, color.RGBA{R: tpx.R, G: tpx.G, B: tpx.B, A: 1}) +// //pixels[i++] = palette[b >> n & 1]; +// } +// } +// for n = 7; n >= 8 - rect.width % 8; n-- { +// pixels[i++] = palette[buffer[dy * rowBytes + dx] >> n & 1]; +// } +// i += this.width - rect.width; +// } +// } else { +// // 3..255 colors (assuming bytesPixel == 4). +// int i = 0; +// for (int ly = rect.y; ly < rect.y + rect.height; ++ly) { +// for (int lx = rect.x; lx < rect.x + rect.width; ++lx) { +// int pixelsOffset = ly * this.width + lx; +// pixels[pixelsOffset] = palette[buffer[i++] & 0xFF]; +// } +// } +// } +// //lock.unlock(); +// } diff --git a/encoding_tightpng.go b/encoding_tightpng.go index a3c3185..3b47a69 100644 --- a/encoding_tightpng.go +++ b/encoding_tightpng.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bytes" @@ -9,6 +9,7 @@ import ( "image/draw" "image/png" "io" + "vnc2webm/logger" ) func (*TightPngEncoding) Supported(Conn) bool { @@ -61,6 +62,7 @@ func (*TightPngEncoding) Type() EncodingType { return EncTightPng } func (enc *TightPngEncoding) Read(c Conn, rect *Rectangle) error { tcc, err := readTightCC(c) + logger.Debug("starting to read a tight rect: %v", rect) if err != nil { return err } diff --git a/encoding_xcursor.go b/encoding_xcursor.go index 310450e..72748be 100644 --- a/encoding_xcursor.go +++ b/encoding_xcursor.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "encoding/binary" diff --git a/encodingtype_string.go b/encodingtype_string.go index b21a196..5fea279 100644 --- a/encodingtype_string.go +++ b/encodingtype_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=EncodingType"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/example/client/main.go b/example/client/main.go index cca2dbb..a70705a 100644 --- a/example/client/main.go +++ b/example/client/main.go @@ -2,50 +2,72 @@ package main import ( "context" + "image" "log" "net" "os" "time" - - vnc "github.com/vtolstov/go-vnc" + vnc "vnc2webm" + "vnc2webm/logger" ) func main() { + // Establish TCP connection to VNC server. nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second) if err != nil { log.Fatalf("Error connecting to VNC host. %v", err) } + logger.Debugf("starting up the client, connecting to: %s", os.Args[1]) // Negotiate connection with the server. cchServer := make(chan vnc.ServerMessage) cchClient := make(chan vnc.ClientMessage) errorCh := make(chan error) ccfg := &vnc.ClientConfig{ - SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthATEN{Username: []byte(os.Args[2]), Password: []byte(os.Args[3])}}, - PixelFormat: vnc.PixelFormat32bit, - ClientMessageCh: cchClient, - ServerMessageCh: cchServer, - ServerMessages: vnc.DefaultServerMessages, - Encodings: []vnc.Encoding{&vnc.RawEncoding{}}, - ErrorCh: errorCh, + SecurityHandlers: []vnc.SecurityHandler{ + //&vnc.ClientAuthATEN{Username: []byte(os.Args[2]), Password: []byte(os.Args[3])} + &vnc.ClientAuthVNC{Password: []byte("12345")}, + &vnc.ClientAuthNone{}, + }, + PixelFormat: vnc.PixelFormat32bit, + ClientMessageCh: cchClient, + ServerMessageCh: cchServer, + Messages: vnc.DefaultServerMessages, + Encodings: []vnc.Encoding{&vnc.RawEncoding{}, &vnc.TightEncoding{}}, + ErrorCh: errorCh, } cc, err := vnc.Connect(context.Background(), nc, ccfg) - if err != nil { log.Fatalf("Error negotiating connection to VNC host. %v", err) } + logger.Debugf("connected to: %s", os.Args[1]) + defer cc.Close() + + cc.SetEncodings([]vnc.EncodingType{vnc.EncTight}) + rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height())) + screenImage := image.NewRGBA64(rect) // Process messages coming in on the ServerMessage channel. for { select { case err := <-errorCh: panic(err) case msg := <-cchClient: - log.Printf("Received message type:%v msg:%v\n", msg.Type(), msg) + log.Printf("Received client message type:%v msg:%v\n", msg.Type(), msg) case msg := <-cchServer: - log.Printf("Received message type:%v msg:%v\n", msg.Type(), msg) + log.Printf("Received server message type:%v msg:%v\n", msg.Type(), msg) + myRenderer, ok := msg.(vnc.Renderer) + + if ok { + err = myRenderer.Render(screenImage) + if err != nil { + log.Printf("Received server message type:%v msg:%v\n", msg.Type(), msg) + } + } + reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()} + reqMsg.Write(cc) } } cc.Wait() diff --git a/example/proxy/main.go b/example/proxy/main.go index ea0f173..2d4d5ba 100644 --- a/example/proxy/main.go +++ b/example/proxy/main.go @@ -14,8 +14,7 @@ import ( "strings" "sync" "time" - - vnc "github.com/vtolstov/go-vnc" + vnc "vnc2webm" ) type Auth struct { @@ -53,9 +52,9 @@ func newConn(hostport string, password []byte) (vnc.Conn, chan vnc.ClientMessage PixelFormat: vnc.PixelFormat32bit, ClientMessageCh: cchClient, ServerMessageCh: cchServer, - ServerMessages: vnc.DefaultServerMessages, - Encodings: []vnc.Encoding{&vnc.RawEncoding{}}, - ErrorCh: errorCh, + //ServerMessages: vnc.DefaultServerMessages, + Encodings: []vnc.Encoding{&vnc.RawEncoding{}}, + ErrorCh: errorCh, } csrv := make(chan vnc.Conn) inp := make(chan vnc.ClientMessage) @@ -78,7 +77,7 @@ func handleIO(cli vnc.Conn, inp chan vnc.ClientMessage, out chan vnc.ServerMessa ccfg := cli.Config().(*vnc.ClientConfig) defer cli.Close() var conns []vnc.Conn - var prepared bool + //var prepared bool for { select { @@ -247,8 +246,8 @@ func main() { PixelFormat: vnc.PixelFormat32bit, ClientMessageCh: schClient, ServerMessageCh: schServer, - ClientMessages: vnc.DefaultClientMessages, - DesktopName: []byte("vnc proxy"), + //ClientMessages: vnc.DefaultClientMessages, + DesktopName: []byte("vnc proxy"), } scfg.Handlers = append(scfg.Handlers, vnc.DefaultServerHandlers...) scfg.Handlers = append(scfg.Handlers[:len(scfg.Handlers)-1], &HijackHandler{}) diff --git a/example/server/main.go b/example/server/main.go index 899f46e..301a75b 100644 --- a/example/server/main.go +++ b/example/server/main.go @@ -8,8 +8,7 @@ import ( "math" "net" "time" - - vnc "github.com/vtolstov/go-vnc" + vnc "vnc2webm" ) func main() { @@ -24,21 +23,22 @@ func main() { im := image.NewRGBA(image.Rect(0, 0, width, height)) tick := time.NewTicker(time.Second / 2) defer tick.Stop() - + cfg := &vnc.ServerConfig{ - Width: 800, - Height: 600, - VersionHandler: vnc.ServerVersionHandler, - SecurityHandler: vnc.ServerSecurityHandler, - SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthNone{}}, - ClientInitHandler: vnc.ServerClientInitHandler, - ServerInitHandler: vnc.ServerServerInitHandler, - Encodings: []vnc.Encoding{&vnc.RawEncoding{}}, - PixelFormat: vnc.PixelFormat32bit, - ClientMessageCh: chServer, - ServerMessageCh: chClient, - ClientMessages: vnc.DefaultClientMessages, + Width: 800, + Height: 600, + //VersionHandler: vnc.ServerVersionHandler, + //SecurityHandler: vnc.ServerSecurityHandler, + SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthNone{}}, + //ClientInitHandler: vnc.ServerClientInitHandler, + //ServerInitHandler: vnc.ServerServerInitHandler, + Encodings: []vnc.Encoding{&vnc.RawEncoding{}}, + PixelFormat: vnc.PixelFormat32bit, + ClientMessageCh: chServer, + ServerMessageCh: chClient, + Messages: vnc.DefaultClientMessages, } + cfg.Handlers = vnc.DefaultServerHandlers go vnc.Serve(context.Background(), ln, cfg) // Process messages coming in on the ClientMessage channel. diff --git a/handlers.go b/handlers.go index 8941262..082e920 100644 --- a/handlers.go +++ b/handlers.go @@ -1,8 +1,9 @@ -package vnc +package vnc2webm import ( "encoding/binary" "fmt" + "vnc2webm/logger" ) // Handler represents handler of handshake @@ -156,6 +157,7 @@ func (*DefaultClientSecurityHandler) Handle(c Conn) error { return err } + logger.Debugf("authenticating, secType: %d, auth code(0=success): %d", secType.Type(), authCode) if authCode == 1 { var reasonLength uint32 if err := binary.Read(c, binary.BigEndian, &reasonLength); err != nil { @@ -256,6 +258,7 @@ type DefaultClientServerInitHandler struct{} // Handle provide default server init handler func (*DefaultClientServerInitHandler) Handle(c Conn) error { + logger.Debug("starting DefaultClientServerInitHandler") var err error srvInit := ServerInit{} @@ -276,6 +279,7 @@ func (*DefaultClientServerInitHandler) Handle(c Conn) error { if err = binary.Read(c, binary.BigEndian, &srvInit.NameText); err != nil { return err } + logger.Debugf("DefaultClientServerInitHandler got serverInit: %v", srvInit) c.SetDesktopName(srvInit.NameText) if c.Protocol() == "aten1" { c.SetWidth(800) @@ -366,6 +370,7 @@ type DefaultClientClientInitHandler struct{} // Handle provide default client client init handler func (*DefaultClientClientInitHandler) Handle(c Conn) error { + logger.Debug("starting DefaultClientClientInitHandler") cfg := c.Config().(*ClientConfig) var shared uint8 if cfg.Exclusive { @@ -376,6 +381,7 @@ func (*DefaultClientClientInitHandler) Handle(c Conn) error { if err := binary.Write(c, binary.BigEndian, shared); err != nil { return err } + logger.Debugf("DefaultClientClientInitHandler sending: shared=%d", shared) return c.Flush() } diff --git a/image.go b/image.go index 1e345f4..7bc45dd 100644 --- a/image.go +++ b/image.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "encoding/binary" @@ -172,7 +172,7 @@ func (rect *Rectangle) Read(c Conn) error { case EncCopyRect: rect.Enc = &CopyRectEncoding{} case EncTight: - rect.Enc = &TightEncoding{} + rect.Enc = c.GetEncInstance(rect.EncType) case EncTightPng: rect.Enc = &TightPngEncoding{} case EncRaw: diff --git a/key_string.go b/key_string.go index c96b5b3..efaf8a2 100644 --- a/key_string.go +++ b/key_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=Key"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/keys.go b/keys.go index 0e0485d..ba548e1 100644 --- a/keys.go +++ b/keys.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import "fmt" diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..0e76d26 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,156 @@ +package logger + +import "fmt" + +var simpleLogger = SimpleLogger{LogLevelDebug} + +type Logger interface { + Debug(v ...interface{}) + Debugf(format string, v ...interface{}) + Info(v ...interface{}) + Infof(format string, v ...interface{}) + Warn(v ...interface{}) + Warnf(format string, v ...interface{}) + Error(v ...interface{}) + Errorf(format string, v ...interface{}) + Fatal(v ...interface{}) + Fatalf(format string, v ...interface{}) +} +type LogLevel int + +const ( + LogLevelTrace LogLevel = iota + LogLevelDebug + LogLevelInfo + LogLevelWarn + LogLevelError + LogLevelFatal +) + +type SimpleLogger struct { + level LogLevel +} + +func (sl *SimpleLogger) Trace(v ...interface{}) { + if sl.level <= LogLevelTrace { + arr := []interface{}{"[Trace]"} + for _, item := range v { + arr = append(arr, item) + } + + fmt.Println(arr...) + } +} +func (sl *SimpleLogger) Tracef(format string, v ...interface{}) { + if sl.level <= LogLevelTrace { + fmt.Printf("[Trace] "+format+"\n", v...) + } +} + +func (sl *SimpleLogger) Debug(v ...interface{}) { + if sl.level <= LogLevelDebug { + arr := []interface{}{"[Debug]"} + for _, item := range v { + arr = append(arr, item) + } + + fmt.Println(arr...) + } +} +func (sl *SimpleLogger) Debugf(format string, v ...interface{}) { + if sl.level <= LogLevelDebug { + fmt.Printf("[Debug] "+format+"\n", v...) + } +} +func (sl *SimpleLogger) Info(v ...interface{}) { + if sl.level <= LogLevelInfo { + arr := []interface{}{"[Info ]"} + for _, item := range v { + arr = append(arr, item) + } + fmt.Println(arr...) + } +} +func (sl *SimpleLogger) Infof(format string, v ...interface{}) { + if sl.level <= LogLevelInfo { + fmt.Printf("[Info ] "+format+"\n", v...) + } +} +func (sl *SimpleLogger) Warn(v ...interface{}) { + if sl.level <= LogLevelWarn { + arr := []interface{}{"[Warn ]"} + for _, item := range v { + arr = append(arr, item) + } + fmt.Println(arr...) + } +} +func (sl *SimpleLogger) Warnf(format string, v ...interface{}) { + if sl.level <= LogLevelWarn { + fmt.Printf("[Warn ] "+format+"\n", v...) + } +} +func (sl *SimpleLogger) Error(v ...interface{}) { + if sl.level <= LogLevelError { + arr := []interface{}{"[Error]"} + for _, item := range v { + arr = append(arr, item) + } + fmt.Println(arr...) + } +} +func (sl *SimpleLogger) Errorf(format string, v ...interface{}) { + if sl.level <= LogLevelError { + fmt.Printf("[Error] "+format+"\n", v...) + } +} +func (sl *SimpleLogger) Fatal(v ...interface{}) { + if sl.level <= LogLevelFatal { + arr := []interface{}{"[Fatal]"} + for _, item := range v { + arr = append(arr, item) + } + fmt.Println(arr...) + + } +} +func (sl *SimpleLogger) Fatalf(format string, v ...interface{}) { + if sl.level <= LogLevelFatal { + fmt.Printf("[Fatal] "+format+"\n", v) + } +} + +func Debug(v ...interface{}) { + simpleLogger.Debug(v...) +} +func Debugf(format string, v ...interface{}) { + simpleLogger.Debugf(format, v...) +} + +func Info(v ...interface{}) { + simpleLogger.Info(v...) +} +func Infof(format string, v ...interface{}) { + simpleLogger.Infof(format, v...) +} + +func Warn(v ...interface{}) { + simpleLogger.Warn(v...) +} +func Warnf(format string, v ...interface{}) { + simpleLogger.Warnf(format, v...) +} + +func Error(v ...interface{}) { + simpleLogger.Error(v...) +} +func Errorf(format string, v ...interface{}) { + simpleLogger.Errorf(format, v...) +} + +func Fatal(v ...interface{}) { + simpleLogger.Fatal(v...) +} +func Fatalf(format string, v ...interface{}) { + simpleLogger.Fatalf(format, v...) +} diff --git a/messages.go b/messages.go index 28ba9ae..2311459 100644 --- a/messages.go +++ b/messages.go @@ -1,8 +1,10 @@ -package vnc +package vnc2webm import ( "encoding/binary" "fmt" + "image/draw" + "vnc2webm/logger" ) var ( @@ -81,6 +83,10 @@ type ServerMessage interface { Supported(Conn) bool } +type Renderer interface { + Render(draw.Image) error +} + // FramebufferUpdate holds a FramebufferUpdate wire format message. type FramebufferUpdate struct { _ [1]byte // pad @@ -93,6 +99,11 @@ func (msg *FramebufferUpdate) String() string { return fmt.Sprintf("rects %d rectangle[]: { %v }", msg.NumRect, msg.Rects) } +func (msg *FramebufferUpdate) Render(draw.Image) error { + + return nil +} + func (msg *FramebufferUpdate) Supported(c Conn) bool { return true } @@ -115,9 +126,12 @@ func (*FramebufferUpdate) Read(c Conn) (ServerMessage, error) { } for i := uint16(0); i < msg.NumRect; i++ { rect := NewRectangle() + //logger.Debugf("----------RECT %d----------:", i) + if err := rect.Read(c); err != nil { return nil, err } + logger.Debugf("----End RECT #%d Info (%dx%d) encType:%s", i, rect.Width, rect.Height, rect.EncType) msg.Rects = append(msg.Rects, rect) } return &msg, nil diff --git a/messages_aten.go b/messages_aten.go index d8bb800..e05535a 100644 --- a/messages_aten.go +++ b/messages_aten.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "encoding/binary" diff --git a/pixel_format.go b/pixel_format.go index 5816e01..81ea23f 100644 --- a/pixel_format.go +++ b/pixel_format.go @@ -1,6 +1,6 @@ // Implementation of RFC 6143 ยง7.4 Pixel Format Data Structure. -package vnc +package vnc2webm import ( "bytes" diff --git a/security.go b/security.go index 0b846d4..35904bc 100644 --- a/security.go +++ b/security.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm type SecurityType uint8 diff --git a/security_aten.go b/security_aten.go index 341c8fa..b894505 100644 --- a/security_aten.go +++ b/security_aten.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bytes" diff --git a/security_none.go b/security_none.go index f65424a..a342706 100644 --- a/security_none.go +++ b/security_none.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm type ClientAuthNone struct{} diff --git a/security_tight.go b/security_tight.go index 327b5cf..b312d96 100644 --- a/security_tight.go +++ b/security_tight.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import "encoding/binary" diff --git a/security_vencryptplain.go b/security_vencryptplain.go index c641671..70fea66 100644 --- a/security_vencryptplain.go +++ b/security_vencryptplain.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bytes" diff --git a/security_vnc.go b/security_vnc.go index 61cce45..58a147e 100644 --- a/security_vnc.go +++ b/security_vnc.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bytes" diff --git a/securitysubtype_string.go b/securitysubtype_string.go index 2c9c35b..7b90af3 100644 --- a/securitysubtype_string.go +++ b/securitysubtype_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=SecuritySubType"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/securitytype_string.go b/securitytype_string.go index 48795b3..7a2a365 100644 --- a/securitytype_string.go +++ b/securitytype_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=SecurityType"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/server.go b/server.go index c01c15f..b0dada4 100644 --- a/server.go +++ b/server.go @@ -1,4 +1,4 @@ -package vnc +package vnc2webm import ( "bufio" @@ -15,6 +15,9 @@ var _ Conn = (*ServerConn)(nil) func (c *ServerConn) Config() interface{} { return c.cfg } +func (c *ServerConn) GetEncInstance(typ EncodingType) Encoding { + return &TightEncoding{} +} // Conn returns underlining server net.Conn func (c *ServerConn) Conn() net.Conn { diff --git a/tightcompression_string.go b/tightcompression_string.go index b0a1457..473ffa8 100644 --- a/tightcompression_string.go +++ b/tightcompression_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=TightCompression"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt" diff --git a/tightfilter_string.go b/tightfilter_string.go index c87ebea..c61947d 100644 --- a/tightfilter_string.go +++ b/tightfilter_string.go @@ -1,6 +1,6 @@ // Code generated by "stringer -type=TightFilter"; DO NOT EDIT. -package vnc +package vnc2webm import "fmt"