diff --git a/.idea/libraries/GOPATH__vncproxy_.xml b/.idea/libraries/GOPATH__vncproxy_.xml index 60c50f4..d56667c 100644 --- a/.idea/libraries/GOPATH__vncproxy_.xml +++ b/.idea/libraries/GOPATH__vncproxy_.xml @@ -3,23 +3,37 @@ - + - - + + + + + + + + + - + - - + + + + + + + + + diff --git a/.idea/misc.xml b/.idea/misc.xml index aeb2b94..009d106 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,4 +1,4 @@ - + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml index 6564d52..94a25f7 100644 --- a/.idea/vcs.xml +++ b/.idea/vcs.xml @@ -1,6 +1,6 @@ - + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml index b708980..93de0cb 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -1,7 +1,39 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -18,63 +50,46 @@ + + - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - + + - - - - - + + + - - + + - - + + @@ -90,11 +105,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + @@ -103,18 +160,8 @@ - - - - - - - - - - - - + + @@ -122,6 +169,19 @@ + + + Read + .Read + .read + server + uint8 + TightMinToCompress + + + + - + @@ -163,13 +228,120 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -232,51 +404,24 @@ - - - - - - - - - - - - - - - - - - - - + + + + - @@ -534,7 +679,7 @@ - + @@ -735,9 +880,9 @@ - - - + + + @@ -784,11 +929,16 @@ + + + + + - @@ -800,38 +950,38 @@ - - + - - + - + - + + - + + @@ -855,53 +1005,45 @@ file://$PROJECT_DIR$/main.go 11 - file://$PROJECT_DIR$/vnc/enc-tight.go 76 - file://$PROJECT_DIR$/vnc/enc-tight.go 98 - file://$PROJECT_DIR$/vnc/enc-tight.go 103 - file://$PROJECT_DIR$/vnc/enc-tight.go - 155 - + 156 file://$PROJECT_DIR$/vnc/enc-tight.go - 172 - + 173 file://$PROJECT_DIR$/vnc/enc-tight.go - 177 - + 178 file://$PROJECT_DIR$/vnc/server_messages.go 78 - - @@ -910,16 +1052,54 @@ - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -933,7 +1113,7 @@ - + @@ -946,16 +1126,7 @@ - - - - - - - - - - + @@ -969,7 +1140,7 @@ - + @@ -982,16 +1153,7 @@ - - - - - - - - - - + @@ -1013,21 +1175,12 @@ - - - - - - - - - - - + + @@ -1036,16 +1189,7 @@ - - - - - - - - - - + @@ -1067,31 +1211,13 @@ - - - - - - - - - - - - - - - - - - - - - + + + @@ -1113,21 +1239,12 @@ - - - - - - - - - - - + + @@ -1136,42 +1253,92 @@ - + + - - - - - + + + + + + + + + + + + + - - + + - + + + + + + + + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1188,42 +1355,38 @@ - + - - + + - + - - - - - + + + + + + + + + + + - - + + - - - - - - - - - - diff --git a/vnc/Logger.go b/common/Logger.go similarity index 95% rename from vnc/Logger.go rename to common/Logger.go index 389ee0b..069f906 100644 --- a/vnc/Logger.go +++ b/common/Logger.go @@ -1,4 +1,4 @@ -package vnc +package common type Logger interface { Debug(v ...interface{}) diff --git a/common/encoding.go b/common/encoding.go new file mode 100644 index 0000000..baab23c --- /dev/null +++ b/common/encoding.go @@ -0,0 +1,28 @@ +package common + +import ( + "io" +) + +// An Encoding implements a method for encoding pixel data that is +// sent by the server to the client. +type Encoding interface { + // The number that uniquely identifies this encoding type. + Type() int32 + + // Read reads the contents of the encoded pixel data from the reader. + // This should return a new Encoding implementation that contains + // the proper data. + Read(*PixelFormat, *Rectangle, io.Reader) (Encoding, error) +} + +const ( + EncodingRaw = 0 + EncodingCopyRect = 1 + EncodingRRE = 2 + EncodingCoRRE = 4 + EncodingHextile = 5 + EncodingZlib = 6 + EncodingTight = 7 + EncodingZRLE = 16 +) diff --git a/common/readers.go b/common/readers.go new file mode 100644 index 0000000..0f2212d --- /dev/null +++ b/common/readers.go @@ -0,0 +1,111 @@ +// Package vnc implements a VNC client. +// +// References: +// [PROTOCOL]: http://tools.ietf.org/html/rfc6143 +package common + +import ( + "bytes" + "encoding/binary" + "fmt" + "io" +) + +// type DataSource struct { +// conn io.Reader +// output io.Writer +// passThrough bool +// PixelFormat PixelFormat +// }Color +type RfbReader struct { + reader io.Reader + saveBytes bool + savedBuff bytes.Buffer +} + +func (r *RfbReader) Read(p []byte) (n int, err error) { + readLen, err := r.reader.Read(p) + r.savedBuff.Write(p) + return readLen, err +} +func (r *RfbReader) SavedBuff() bytes.Buffer { + return r.savedBuff +} + +type RfbReadHelper struct { + io.Reader +} + +func (d *RfbReadHelper) ReadBytes(count int) ([]byte, error) { + buff := make([]byte, count) + + _, err := io.ReadFull(d.Reader, buff) + if err != nil { + //if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil { + return nil, err + } + return buff, nil +} + +func (d *RfbReadHelper) ReadUint8() (uint8, error) { + var myUint uint8 + if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil { + return 0, err + } + //fmt.Printf("myUint=%d", myUint) + return myUint, nil +} +func (d *RfbReadHelper) ReadUint16() (uint16, error) { + var myUint uint16 + if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil { + return 0, err + } + //fmt.Printf("myUint=%d", myUint) + return myUint, nil +} +func (d *RfbReadHelper) ReadUint32() (uint32, error) { + var myUint uint32 + if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil { + return 0, err + } + //fmt.Printf("myUint=%d", myUint) + return myUint, nil +} +func (d *RfbReadHelper) ReadCompactLen() (int, error) { + var err error + part, err := d.ReadUint8() + //byteCount := 1 + len := uint32(part & 0x7F) + if (part & 0x80) != 0 { + part, err = d.ReadUint8() + //byteCount++ + len |= uint32(part&0x7F) << 7 + if (part & 0x80) != 0 { + part, err = d.ReadUint8() + //byteCount++ + len |= uint32(part&0xFF) << 14 + } + } + + // for i := 0; i < byteCount; i++{ + // rec.writeByte(portion[i]); + // } + + return int(len), err +} + +var TightMinToCompress int = 12 + +func (r *RfbReadHelper) ReadTightData(dataSize int) ([]byte, error) { + if int(dataSize) < TightMinToCompress { + return r.ReadBytes(int(dataSize)) + } + zlibDataLen, err := r.ReadCompactLen() + fmt.Printf("compactlen=%d\n", zlibDataLen) + if err != nil { + return nil, err + } + //byte[] zlibData = new byte[zlibDataLen]; + //rfb.readFully(zlibData); + return r.ReadBytes(zlibDataLen) +} diff --git a/vnc/rectangle.go b/common/rectangle.go similarity index 73% rename from vnc/rectangle.go rename to common/rectangle.go index 3211635..8125823 100644 --- a/vnc/rectangle.go +++ b/common/rectangle.go @@ -1,26 +1,34 @@ -package vnc - -// Rectangle represents a rectangle of pixel data. -type Rectangle struct { - X uint16 - Y uint16 - Width uint16 - Height uint16 - Enc Encoding -} - -// 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 bool - TrueColor bool - RedMax uint16 - GreenMax uint16 - BlueMax uint16 - RedShift uint8 - GreenShift uint8 - BlueShift uint8 -} +package common + +import ( + "fmt" +) + +// Rectangle represents a rectangle of pixel data. +type Rectangle struct { + X uint16 + Y uint16 + Width uint16 + Height uint16 + Enc Encoding +} + +func (r *Rectangle) String() string { + return fmt.Sprintf("(%d,%d) (width: %d, height: %d), Enc= %d", r.X, r.Y, r.Width, r.Height, r.Enc.Type()) +} + +// 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 bool + TrueColor bool + RedMax uint16 + GreenMax uint16 + BlueMax uint16 + RedShift uint8 + GreenShift uint8 + BlueShift uint8 +} diff --git a/encodings/enc-copy-rect.go b/encodings/enc-copy-rect.go new file mode 100644 index 0000000..4cef62f --- /dev/null +++ b/encodings/enc-copy-rect.go @@ -0,0 +1,26 @@ +package encodings + +import ( + "io" + "vncproxy/common" +) + +type CopyRectEncoding struct { + //Colors []Color + copyRectSrcX uint16 + copyRectSrcY uint16 +} + +func (z *CopyRectEncoding) Type() int32 { + return 1 +} +func (z *CopyRectEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { + conn := common.RfbReadHelper{r} + //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} + //bytesPerPixel := c.PixelFormat.BPP / 8 + z.copyRectSrcX, _ = conn.ReadUint16() + z.copyRectSrcY, _ = conn.ReadUint16() + return z, nil +} + +////////// diff --git a/encodings/enc-corre.go b/encodings/enc-corre.go new file mode 100644 index 0000000..6731691 --- /dev/null +++ b/encodings/enc-corre.go @@ -0,0 +1,48 @@ +package encodings + +import ( + "io" + "vncproxy/common" +) + +type CoRREEncoding struct { + //Colors []Color +} + +func (z *CoRREEncoding) Type() int32 { + return 4 +} + +func (z *CoRREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { + conn := common.RfbReadHelper{r} + bytesPerPixel := int(pixelFmt.BPP / 8) + numOfSubrectangles, _ := conn.ReadUint32() + + //read whole rect background color + conn.ReadBytes(bytesPerPixel) + + //read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b) + _, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4)) + + if err != nil { + return nil, err + } + return z, nil + + //int nSubrects = rfb.readU32(); + + //byte[] bg_buf = new byte[bytesPerPixel]; + //rfb.readFully(bytesPerPixel); + //Color pixel; + // if (bytesPixel == 1) { + // pixel = colors[bg_buf[0] & 0xFF]; + // } else { + // pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF); + // } + // memGraphics.setColor(pixel); + // memGraphics.fillRect(x, y, w, h); + + // byte[] buf = new byte[nSubrects * (bytesPixel + 4)]; + // rfb.readFully(buf); + +} diff --git a/vnc/enc-hextile.go b/encodings/enc-hextile.go similarity index 77% rename from vnc/enc-hextile.go rename to encodings/enc-hextile.go index b545126..9bb8d6c 100644 --- a/vnc/enc-hextile.go +++ b/encodings/enc-hextile.go @@ -1,81 +1,85 @@ -package vnc - -import "io" - -const ( - HextileRaw = 1 - HextileBackgroundSpecified = 2 - HextileForegroundSpecified = 4 - HextileAnySubrects = 8 - HextileSubrectsColoured = 16 -) - -type HextileEncoding struct { - Colors []Color -} - -func (z *HextileEncoding) Type() int32 { - return 5 -} -func (z *HextileEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { - //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} - bytesPerPixel := int(conn.PixelFormat.BPP) / 8 - //buf := make([]byte, bytesPerPixel) - for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 { - th := 16 - if rect.Y+rect.Height-ty < 16 { - th = int(rect.Y) + int(rect.Height) - int(ty) - } - - for tx := rect.X; tx < rect.X+rect.Width; tx += 16 { - tw := 16 - if rect.X+rect.Width-tx < 16 { - tw = int(rect.X) + int(rect.Width) - int(tx) - } - - //handle Hextile Subrect(tx, ty, tw, th): - subencoding, err := conn.readUint8() - //fmt.Printf("hextile reader tile: (%d,%d) subenc=%d\n", ty, tx, subencoding) - if err != nil { - //fmt.Printf("error in hextile reader: %v\n", err) - return nil, err - } - - if (subencoding & HextileRaw) != 0 { - //ReadRawRect(c, rect, r) - conn.readBytes(tw * th * bytesPerPixel) - //fmt.Printf("hextile reader: HextileRaw\n") - continue - } - if (subencoding & HextileBackgroundSpecified) != 0 { - conn.readBytes(int(bytesPerPixel)) - } - if (subencoding & HextileForegroundSpecified) != 0 { - conn.readBytes(int(bytesPerPixel)) - } - if (subencoding & HextileAnySubrects) == 0 { - //fmt.Printf("hextile reader: no Subrects\n") - continue - } - //fmt.Printf("hextile reader: handling Subrects\n") - nSubrects, err := conn.readUint8() - if err != nil { - return nil, err - } - bufsize := int(nSubrects) * 2 - if (subencoding & HextileSubrectsColoured) != 0 { - bufsize += int(nSubrects) * int(bytesPerPixel) - } - //byte[] buf = new byte[bufsize]; - conn.readBytes(bufsize) - } - } - - // len, _ := readUint32(c.c) - // _, err := readBytes(c.c, int(len)) - - // if err != nil { - // return nil, err - // } - return z, nil -} +package encodings + +import ( + "io" + "vncproxy/common" +) + +const ( + HextileRaw = 1 + HextileBackgroundSpecified = 2 + HextileForegroundSpecified = 4 + HextileAnySubrects = 8 + HextileSubrectsColoured = 16 +) + +type HextileEncoding struct { + //Colors []Color +} + +func (z *HextileEncoding) Type() int32 { + return 5 +} +func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { + conn := common.RfbReadHelper{r} + //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} + bytesPerPixel := int(pixelFmt.BPP) / 8 + //buf := make([]byte, bytesPerPixel) + for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 { + th := 16 + if rect.Y+rect.Height-ty < 16 { + th = int(rect.Y) + int(rect.Height) - int(ty) + } + + for tx := rect.X; tx < rect.X+rect.Width; tx += 16 { + tw := 16 + if rect.X+rect.Width-tx < 16 { + tw = int(rect.X) + int(rect.Width) - int(tx) + } + + //handle Hextile Subrect(tx, ty, tw, th): + subencoding, err := conn.ReadUint8() + //fmt.Printf("hextile reader tile: (%d,%d) subenc=%d\n", ty, tx, subencoding) + if err != nil { + //fmt.Printf("error in hextile reader: %v\n", err) + return nil, err + } + + if (subencoding & HextileRaw) != 0 { + //ReadRawRect(c, rect, r) + conn.ReadBytes(tw * th * bytesPerPixel) + //fmt.Printf("hextile reader: HextileRaw\n") + continue + } + if (subencoding & HextileBackgroundSpecified) != 0 { + conn.ReadBytes(int(bytesPerPixel)) + } + if (subencoding & HextileForegroundSpecified) != 0 { + conn.ReadBytes(int(bytesPerPixel)) + } + if (subencoding & HextileAnySubrects) == 0 { + //fmt.Printf("hextile reader: no Subrects\n") + continue + } + //fmt.Printf("hextile reader: handling Subrects\n") + nSubrects, err := conn.ReadUint8() + if err != nil { + return nil, err + } + bufsize := int(nSubrects) * 2 + if (subencoding & HextileSubrectsColoured) != 0 { + bufsize += int(nSubrects) * int(bytesPerPixel) + } + //byte[] buf = new byte[bufsize]; + conn.ReadBytes(bufsize) + } + } + + // len, _ := readUint32(c.c) + // _, err := readBytes(c.c, int(len)) + + // if err != nil { + // return nil, err + // } + return z, nil +} diff --git a/vnc/enc-raw.go b/encodings/enc-raw.go similarity index 75% rename from vnc/enc-raw.go rename to encodings/enc-raw.go index dc67e8a..e810c28 100644 --- a/vnc/enc-raw.go +++ b/encodings/enc-raw.go @@ -1,24 +1,25 @@ -package vnc +package encodings -import "io" +import ( + "io" + "vncproxy/common" +) // RawEncoding is raw pixel data sent by the server. // // See RFC 6143 Section 7.7.1 type RawEncoding struct { - Colors []Color + //Colors []Color } func (*RawEncoding) Type() int32 { return 0 } - - -func (*RawEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { +func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} - - bytesPerPixel := int(conn.PixelFormat.BPP / 8) + conn := common.RfbReadHelper{r} + bytesPerPixel := int(pixelFmt.BPP / 8) //pixelBytes := make([]uint8, bytesPerPixel) // var byteOrder binary.ByteOrder = binary.LittleEndian @@ -26,11 +27,11 @@ func (*RawEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encodi // byteOrder = binary.BigEndian // } - colors := make([]Color, int(rect.Height)*int(rect.Width)) + //colors := make([]vnc.Color, int(rect.Height)*int(rect.Width)) for y := uint16(0); y < rect.Height; y++ { for x := uint16(0); x < rect.Width; x++ { - if _, err := conn.readBytes(bytesPerPixel); err != nil { + if _, err := conn.ReadBytes(bytesPerPixel); err != nil { return nil, err } @@ -54,5 +55,5 @@ func (*RawEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encodi } } - return &RawEncoding{colors}, nil + return &RawEncoding{}, nil } diff --git a/encodings/enc-rre.go b/encodings/enc-rre.go new file mode 100644 index 0000000..7c501d5 --- /dev/null +++ b/encodings/enc-rre.go @@ -0,0 +1,28 @@ +package encodings + +import "io" +import "vncproxy/common" + +type RREEncoding struct { + //Colors []Color +} + +func (z *RREEncoding) Type() int32 { + return 2 +} +func (z *RREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { + conn := common.RfbReadHelper{r} + bytesPerPixel := int(pixelFmt.BPP / 8) + numOfSubrectangles, _ := conn.ReadUint32() + + //read whole rect background color + conn.ReadBytes(bytesPerPixel) + + //read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b) + _, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 8)) + + if err != nil { + return nil, err + } + return z, nil +} diff --git a/vnc/enc-tight.go b/encodings/enc-tight.go similarity index 85% rename from vnc/enc-tight.go rename to encodings/enc-tight.go index d9346b1..4d43bdf 100644 --- a/vnc/enc-tight.go +++ b/encodings/enc-tight.go @@ -1,346 +1,334 @@ -package vnc - -import ( - "errors" - "fmt" - "io" -) - -var TightMinToCompress int = 12 - -const ( - TightExplicitFilter = 0x04 - TightFill = 0x08 - TightJpeg = 0x09 - TightMaxSubencoding = 0x09 - TightFilterCopy = 0x00 - TightFilterPalette = 0x01 - TightFilterGradient = 0x02 -) - -type TightEncoding struct { - output io.Writer - logger Logger -} - -func (t *TightEncoding) SetOutput(output io.Writer) { - t.output = output -} - -func (*TightEncoding) Type() int32 { - return 7 -} - -// func ReadAndRecBytes(conn io.Reader, rec io.Writer, count int) ([]byte, error) { -// buf, err := readBytes(conn, count) -// rec.Write(buf) -// return buf, err -// } -// func ReadAndRecUint8(conn io.Reader, rec io.Writer) (uint8, error) { -// myUint, err := readUint8(conn) -// buf := make([]byte, 1) -// buf[0] = byte(myUint) // cast int8 to byte -// rec.Write(buf) -// return myUint, err -// } - -// func ReadAndRecUint16(conn io.Reader, rec io.Writer) (uint16, error) { -// myUint, err := readUint16(conn) -// buf := make([]byte, 2) -// //buf[0] = byte(myUint) // cast int8 to byte -// //var i int16 = 41 -// //b := make([]byte, 2) -// binary.LittleEndian.PutUint16(buf, uint16(myUint)) - -// rec.Write(buf) -// return myUint, err -// } - -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 (t *TightEncoding) Read(conn *ClientConn, rect *Rectangle, reader io.Reader) (Encoding, error) { - bytesPixel := calcTightBytePerPixel(conn.PixelFormat) - - //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} - - //var subencoding uint8 - subencoding, err := conn.readUint8() - if err != nil { - fmt.Printf("error in handling tight encoding: %v\n", err) - return nil, err - } - fmt.Printf("bytesPixel= %d, subencoding= %d\n", bytesPixel, subencoding) - // if err := binary.Read(conn.c, binary.BigEndian, &subencoding); err != nil { - // return t, err - // } - - //move it to position (remove zlib flush commands) - compType := subencoding >> 4 & 0x0F - // for stream_id := 0; stream_id < 4; stream_id++ { - // // if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) { - // // tightInflaters[stream_id] = null; - // // } - // subencoding >>= 1 - // } - - fmt.Printf("afterSHL:%d\n", compType) - switch compType { - case TightFill: - fmt.Printf("reading fill size=%d\n", bytesPixel) - //read color - conn.readBytes(int(bytesPixel)) - return t, nil - case TightJpeg: - if conn.PixelFormat.BPP == 8 { - return nil, errors.New("Tight encoding: JPEG is not supported in 8 bpp mode") - } - - len, err := conn.readCompactLen() - if err != nil { - return nil, err - } - fmt.Printf("reading jpeg size=%d\n", len) - conn.readBytes(len) - return t, nil - default: - - if compType > TightJpeg { - fmt.Println("Compression control byte is incorrect!") - } - - handleTightFilters(subencoding, conn, rect, reader) - return t, nil - } -} - -func handleTightFilters(subencoding uint8, conn *ClientConn, rect *Rectangle, reader io.Reader) { - var FILTER_ID_MASK uint8 = 0x40 - //var STREAM_ID_MASK uint8 = 0x30 - - //decoderId := (subencoding & STREAM_ID_MASK) >> 4 - var filterid uint8 - var err error - - if (subencoding & FILTER_ID_MASK) > 0 { // filter byte presence - filterid, err = conn.readUint8() - if err != nil { - fmt.Printf("error in handling tight encoding, reading filterid: %v\n", err) - return - } - fmt.Printf("read filter: %d\n", filterid) - } - - //var numColors uint8 - bytesPixel := calcTightBytePerPixel(conn.PixelFormat) - - fmt.Printf("filter: %d\n", filterid) - // if rfb.rec != null { - // rfb.rec.writeByte(filter_id) - // } - lengthCurrentbpp := int(bytesPixel) * int(rect.Width) * int(rect.Height) - - switch filterid { - case TightFilterPalette: //PALETTE_FILTER - - colorCount, err := conn.readUint8() - paletteSize := colorCount + 1 // add one more - fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel) - //complete palette - conn.readBytes(int(paletteSize) * bytesPixel) - - var dataLength int - if paletteSize == 2 { - dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8) - } else { - dataLength = int(rect.Width * rect.Height) - } - _, err = readTightData(conn, dataLength) - if err != nil { - fmt.Printf("error in handling tight encoding, Reading Palette: %v\n", err) - return - } - case TightFilterGradient: //GRADIENT_FILTER - fmt.Printf("----GRADIENT_FILTER: bytesPixel=%d\n", bytesPixel) - //useGradient = true - fmt.Printf("usegrad: %d\n", filterid) - readTightData(conn, lengthCurrentbpp) - case TightFilterCopy: //BASIC_FILTER - fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel) - readTightData(conn, lengthCurrentbpp) - default: - fmt.Printf("Bad tight filter id: %d\n", filterid) - return - } - - //////////// - - // if numColors == 0 && bytesPixel == 4 { - // rowSize1 *= 3 - // } - // rowSize := (int(rect.Width)*bitsPixel + 7) / 8 - // dataSize := int(rect.Height) * rowSize - - // dataSize1 := rect.Height * rowSize1 - // fmt.Printf("datasize: %d, origDatasize: %d", dataSize, dataSize1) - // // Read, optionally uncompress and decode data. - // if int(dataSize1) < TightMinToCompress { - // // Data size is small - not compressed with zlib. - // if numColors != 0 { - // // Indexed colors. - // //indexedData := make([]byte, dataSize) - // readBytes(conn.c, int(dataSize1)) - // //readFully(indexedData); - // // if (rfb.rec != null) { - // // rfb.rec.write(indexedData); - // // } - // // if (numColors == 2) { - // // // Two colors. - // // if (bytesPixel == 1) { - // // decodeMonoData(x, y, w, h, indexedData, palette8); - // // } else { - // // decodeMonoData(x, y, w, h, indexedData, palette24); - // // } - // // } else { - // // // 3..255 colors (assuming bytesPixel == 4). - // // int i = 0; - // // for (int dy = y; dy < y + h; dy++) { - // // for (int dx = x; dx < x + w; dx++) { - // // pixels24[dy * rfb.framebufferWidth + dx] = palette24[indexedData[i++] & 0xFF]; - // // } - // // } - // // } - // } else if useGradient { - // // "Gradient"-processed data - // //buf := make ( []byte,w * h * 3); - // dataByteCount := int(3) * int(rect.Width) * int(rect.Height) - // readBytes(conn.c, dataByteCount) - // // rfb.readFully(buf); - // // if (rfb.rec != null) { - // // rfb.rec.write(buf); - // // } - // // decodeGradientData(x, y, w, h, buf); - // } else { - // // Raw truecolor data. - // dataByteCount := int(bytesPixel) * int(rect.Width) * int(rect.Height) - // readBytes(conn.c, dataByteCount) - - // // if (bytesPixel == 1) { - // // for (int dy = y; dy < y + h; dy++) { - - // // rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w); - // // if (rfb.rec != null) { - // // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); - // // } - // // } - // // } else { - // // byte[] buf = new byte[w * 3]; - // // int i, offset; - // // for (int dy = y; dy < y + h; dy++) { - // // rfb.readFully(buf); - // // if (rfb.rec != null) { - // // rfb.rec.write(buf); - // // } - // // offset = dy * rfb.framebufferWidth + x; - // // for (i = 0; i < w; i++) { - // // pixels24[offset + i] = (buf[i * 3] & 0xFF) << 16 | (buf[i * 3 + 1] & 0xFF) << 8 | (buf[i * 3 + 2] & 0xFF); - // // } - // // } - // // } - // } - // } else { - // // Data was compressed with zlib. - // zlibDataLen, err := readCompactLen(conn.c) - // fmt.Printf("compactlen=%d\n", zlibDataLen) - // if err != nil { - // return nil, err - // } - // //byte[] zlibData = new byte[zlibDataLen]; - // //rfb.readFully(zlibData); - // readBytes(conn.c, zlibDataLen) - - // // if (rfb.rec != null) { - // // rfb.rec.write(zlibData); - // // } - // // int stream_id = comp_ctl & 0x03; - // // if (tightInflaters[stream_id] == null) { - // // tightInflaters[stream_id] = new Inflater(); - // // } - // // Inflater myInflater = tightInflaters[stream_id]; - // // myInflater.setInput(zlibData); - // // byte[] buf = new byte[dataSize]; - // // myInflater.inflate(buf); - // // if (rfb.rec != null && !rfb.recordFromBeginning) { - // // rfb.recordCompressedData(buf); - // // } - - // // if (numColors != 0) { - // // // Indexed colors. - // // if (numColors == 2) { - // // // Two colors. - // // if (bytesPixel == 1) { - // // decodeMonoData(x, y, w, h, buf, palette8); - // // } else { - // // decodeMonoData(x, y, w, h, buf, palette24); - // // } - // // } else { - // // // More than two colors (assuming bytesPixel == 4). - // // int i = 0; - // // for (int dy = y; dy < y + h; dy++) { - // // for (int dx = x; dx < x + w; dx++) { - // // pixels24[dy * rfb.framebufferWidth + dx] = palette24[buf[i++] & 0xFF]; - // // } - // // } - // // } - // // } else if (useGradient) { - // // // Compressed "Gradient"-filtered data (assuming bytesPixel == 4). - // // decodeGradientData(x, y, w, h, buf); - // // } else { - // // // Compressed truecolor data. - // // if (bytesPixel == 1) { - // // int destOffset = y * rfb.framebufferWidth + x; - // // for (int dy = 0; dy < h; dy++) { - // // System.arraycopy(buf, dy * w, pixels8, destOffset, w); - // // destOffset += rfb.framebufferWidth; - // // } - // // } else { - // // int srcOffset = 0; - // // int destOffset, i; - // // for (int dy = 0; dy < h; dy++) { - // // myInflater.inflate(buf); - // // destOffset = (y + dy) * rfb.framebufferWidth + x; - // // for (i = 0; i < w; i++) { - // // pixels24[destOffset + i] = (buf[srcOffset] & 0xFF) << 16 | (buf[srcOffset + 1] & 0xFF) << 8 - // // | (buf[srcOffset + 2] & 0xFF); - // // srcOffset += 3; - // // } - // // } - // // } - // // } - // } - - return -} - -func readTightData(conn *ClientConn, dataSize int) ([]byte, error) { - if int(dataSize) < TightMinToCompress { - return conn.readBytes(int(dataSize)) - } - zlibDataLen, err := conn.readCompactLen() - fmt.Printf("compactlen=%d\n", zlibDataLen) - if err != nil { - return nil, err - } - //byte[] zlibData = new byte[zlibDataLen]; - //rfb.readFully(zlibData); - return conn.readBytes(zlibDataLen) -} +package encodings + +import ( + "errors" + "fmt" + "io" + "vncproxy/common" +) + +var TightMinToCompress int = 12 + +const ( + TightExplicitFilter = 0x04 + TightFill = 0x08 + TightJpeg = 0x09 + TightMaxSubencoding = 0x09 + TightFilterCopy = 0x00 + TightFilterPalette = 0x01 + TightFilterGradient = 0x02 +) + +type TightEncoding struct { + output io.Writer + logger common.Logger +} + +func (t *TightEncoding) SetOutput(output io.Writer) { + t.output = output +} + +func (*TightEncoding) Type() int32 { + return 7 +} + +// func ReadAndRecBytes(conn io.Reader, rec io.Writer, count int) ([]byte, error) { +// buf, err := readBytes(conn, count) +// rec.Write(buf) +// return buf, err +// } +// func ReadAndRecUint8(conn io.Reader, rec io.Writer) (uint8, error) { +// myUint, err := readUint8(conn) +// buf := make([]byte, 1) +// buf[0] = byte(myUint) // cast int8 to byte +// rec.Write(buf) +// return myUint, err +// } + +// func ReadAndRecUint16(conn io.Reader, rec io.Writer) (uint16, error) { +// myUint, err := readUint16(conn) +// buf := make([]byte, 2) +// //buf[0] = byte(myUint) // cast int8 to byte +// //var i int16 = 41 +// //b := make([]byte, 2) +// binary.LittleEndian.PutUint16(buf, uint16(myUint)) + +// rec.Write(buf) +// return myUint, err +// } + +func calcTightBytePerPixel(pf *common.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 (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, reader io.Reader) (common.Encoding, error) { + bytesPixel := calcTightBytePerPixel(pixelFmt) + conn := common.RfbReadHelper{reader} + //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} + + //var subencoding uint8 + subencoding, err := conn.ReadUint8() + if err != nil { + fmt.Printf("error in handling tight encoding: %v\n", err) + return nil, err + } + fmt.Printf("bytesPixel= %d, subencoding= %d\n", bytesPixel, subencoding) + // if err := binary.Read(conn.c, binary.BigEndian, &subencoding); err != nil { + // return t, err + // } + + //move it to position (remove zlib flush commands) + compType := subencoding >> 4 & 0x0F + // for stream_id := 0; stream_id < 4; stream_id++ { + // // if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) { + // // tightInflaters[stream_id] = null; + // // } + // subencoding >>= 1 + // } + + fmt.Printf("afterSHL:%d\n", compType) + switch compType { + case TightFill: + fmt.Printf("reading fill size=%d\n", bytesPixel) + //read color + conn.ReadBytes(int(bytesPixel)) + return t, nil + case TightJpeg: + if pixelFmt.BPP == 8 { + return nil, errors.New("Tight encoding: JPEG is not supported in 8 bpp mode") + } + + len, err := conn.ReadCompactLen() + if err != nil { + return nil, err + } + fmt.Printf("reading jpeg size=%d\n", len) + conn.ReadBytes(len) + return t, nil + default: + + if compType > TightJpeg { + fmt.Println("Compression control byte is incorrect!") + } + + handleTightFilters(subencoding, pixelFmt, rect, reader) + return t, nil + } +} + +func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *common.Rectangle, reader io.Reader) { + conn := common.RfbReadHelper{reader} + var FILTER_ID_MASK uint8 = 0x40 + //var STREAM_ID_MASK uint8 = 0x30 + + //decoderId := (subencoding & STREAM_ID_MASK) >> 4 + var filterid uint8 + var err error + + if (subencoding & FILTER_ID_MASK) > 0 { // filter byte presence + filterid, err = conn.ReadUint8() + if err != nil { + fmt.Printf("error in handling tight encoding, reading filterid: %v\n", err) + return + } + fmt.Printf("read filter: %d\n", filterid) + } + + //var numColors uint8 + bytesPixel := calcTightBytePerPixel(pixelFmt) + + fmt.Printf("filter: %d\n", filterid) + // if rfb.rec != null { + // rfb.rec.writeByte(filter_id) + // } + lengthCurrentbpp := int(bytesPixel) * int(rect.Width) * int(rect.Height) + + switch filterid { + case TightFilterPalette: //PALETTE_FILTER + + colorCount, err := conn.ReadUint8() + paletteSize := colorCount + 1 // add one more + fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel) + //complete palette + conn.ReadBytes(int(paletteSize) * bytesPixel) + + var dataLength int + if paletteSize == 2 { + dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8) + } else { + dataLength = int(rect.Width * rect.Height) + } + _, err = conn.ReadTightData(dataLength) + if err != nil { + fmt.Printf("error in handling tight encoding, Reading Palette: %v\n", err) + return + } + case TightFilterGradient: //GRADIENT_FILTER + fmt.Printf("----GRADIENT_FILTER: bytesPixel=%d\n", bytesPixel) + //useGradient = true + fmt.Printf("usegrad: %d\n", filterid) + conn.ReadTightData(lengthCurrentbpp) + case TightFilterCopy: //BASIC_FILTER + fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel) + conn.ReadTightData(lengthCurrentbpp) + default: + fmt.Printf("Bad tight filter id: %d\n", filterid) + return + } + + //////////// + + // if numColors == 0 && bytesPixel == 4 { + // rowSize1 *= 3 + // } + // rowSize := (int(rect.Width)*bitsPixel + 7) / 8 + // dataSize := int(rect.Height) * rowSize + + // dataSize1 := rect.Height * rowSize1 + // fmt.Printf("datasize: %d, origDatasize: %d", dataSize, dataSize1) + // // Read, optionally uncompress and decode data. + // if int(dataSize1) < TightMinToCompress { + // // Data size is small - not compressed with zlib. + // if numColors != 0 { + // // Indexed colors. + // //indexedData := make([]byte, dataSize) + // readBytes(conn.c, int(dataSize1)) + // //readFully(indexedData); + // // if (rfb.rec != null) { + // // rfb.rec.write(indexedData); + // // } + // // if (numColors == 2) { + // // // Two colors. + // // if (bytesPixel == 1) { + // // decodeMonoData(x, y, w, h, indexedData, palette8); + // // } else { + // // decodeMonoData(x, y, w, h, indexedData, palette24); + // // } + // // } else { + // // // 3..255 colors (assuming bytesPixel == 4). + // // int i = 0; + // // for (int dy = y; dy < y + h; dy++) { + // // for (int dx = x; dx < x + w; dx++) { + // // pixels24[dy * rfb.framebufferWidth + dx] = palette24[indexedData[i++] & 0xFF]; + // // } + // // } + // // } + // } else if useGradient { + // // "Gradient"-processed data + // //buf := make ( []byte,w * h * 3); + // dataByteCount := int(3) * int(rect.Width) * int(rect.Height) + // readBytes(conn.c, dataByteCount) + // // rfb.readFully(buf); + // // if (rfb.rec != null) { + // // rfb.rec.write(buf); + // // } + // // decodeGradientData(x, y, w, h, buf); + // } else { + // // Raw truecolor data. + // dataByteCount := int(bytesPixel) * int(rect.Width) * int(rect.Height) + // readBytes(conn.c, dataByteCount) + + // // if (bytesPixel == 1) { + // // for (int dy = y; dy < y + h; dy++) { + + // // rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w); + // // if (rfb.rec != null) { + // // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w); + // // } + // // } + // // } else { + // // byte[] buf = new byte[w * 3]; + // // int i, offset; + // // for (int dy = y; dy < y + h; dy++) { + // // rfb.readFully(buf); + // // if (rfb.rec != null) { + // // rfb.rec.write(buf); + // // } + // // offset = dy * rfb.framebufferWidth + x; + // // for (i = 0; i < w; i++) { + // // pixels24[offset + i] = (buf[i * 3] & 0xFF) << 16 | (buf[i * 3 + 1] & 0xFF) << 8 | (buf[i * 3 + 2] & 0xFF); + // // } + // // } + // // } + // } + // } else { + // // Data was compressed with zlib. + // zlibDataLen, err := readCompactLen(conn.c) + // fmt.Printf("compactlen=%d\n", zlibDataLen) + // if err != nil { + // return nil, err + // } + // //byte[] zlibData = new byte[zlibDataLen]; + // //rfb.readFully(zlibData); + // readBytes(conn.c, zlibDataLen) + + // // if (rfb.rec != null) { + // // rfb.rec.write(zlibData); + // // } + // // int stream_id = comp_ctl & 0x03; + // // if (tightInflaters[stream_id] == null) { + // // tightInflaters[stream_id] = new Inflater(); + // // } + // // Inflater myInflater = tightInflaters[stream_id]; + // // myInflater.setInput(zlibData); + // // byte[] buf = new byte[dataSize]; + // // myInflater.inflate(buf); + // // if (rfb.rec != null && !rfb.recordFromBeginning) { + // // rfb.recordCompressedData(buf); + // // } + + // // if (numColors != 0) { + // // // Indexed colors. + // // if (numColors == 2) { + // // // Two colors. + // // if (bytesPixel == 1) { + // // decodeMonoData(x, y, w, h, buf, palette8); + // // } else { + // // decodeMonoData(x, y, w, h, buf, palette24); + // // } + // // } else { + // // // More than two colors (assuming bytesPixel == 4). + // // int i = 0; + // // for (int dy = y; dy < y + h; dy++) { + // // for (int dx = x; dx < x + w; dx++) { + // // pixels24[dy * rfb.framebufferWidth + dx] = palette24[buf[i++] & 0xFF]; + // // } + // // } + // // } + // // } else if (useGradient) { + // // // Compressed "Gradient"-filtered data (assuming bytesPixel == 4). + // // decodeGradientData(x, y, w, h, buf); + // // } else { + // // // Compressed truecolor data. + // // if (bytesPixel == 1) { + // // int destOffset = y * rfb.framebufferWidth + x; + // // for (int dy = 0; dy < h; dy++) { + // // System.arraycopy(buf, dy * w, pixels8, destOffset, w); + // // destOffset += rfb.framebufferWidth; + // // } + // // } else { + // // int srcOffset = 0; + // // int destOffset, i; + // // for (int dy = 0; dy < h; dy++) { + // // myInflater.inflate(buf); + // // destOffset = (y + dy) * rfb.framebufferWidth + x; + // // for (i = 0; i < w; i++) { + // // pixels24[destOffset + i] = (buf[srcOffset] & 0xFF) << 16 | (buf[srcOffset + 1] & 0xFF) << 8 + // // | (buf[srcOffset + 2] & 0xFF); + // // srcOffset += 3; + // // } + // // } + // // } + // // } + // } + + return +} diff --git a/encodings/enc-zlib.go b/encodings/enc-zlib.go new file mode 100644 index 0000000..3da39d1 --- /dev/null +++ b/encodings/enc-zlib.go @@ -0,0 +1,24 @@ +package encodings + +import "io" +import "vncproxy/common" + +type ZLibEncoding struct { + //Colors []Color +} + +func (z *ZLibEncoding) Type() int32 { + return 6 +} +func (z *ZLibEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { + conn := common.RfbReadHelper{r} + //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} + //bytesPerPixel := c.PixelFormat.BPP / 8 + len, _ := conn.ReadUint32() + _, err := conn.ReadBytes(int(len)) + + if err != nil { + return nil, err + } + return z, nil +} diff --git a/encodings/enc-zrle.go b/encodings/enc-zrle.go new file mode 100644 index 0000000..5059b7e --- /dev/null +++ b/encodings/enc-zrle.go @@ -0,0 +1,24 @@ +package encodings + +import "io" +import "vncproxy/common" + +type ZRLEEncoding struct { + //Colors []Color +} + +func (z *ZRLEEncoding) Type() int32 { + return 16 +} +func (z *ZRLEEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { + conn := common.RfbReadHelper{r} + //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} + //bytesPerPixel := c.PixelFormat.BPP / 8 + len, _ := conn.ReadUint32() + _, err := conn.ReadBytes(int(len)) + + if err != nil { + return nil, err + } + return z, nil +} diff --git a/main.go b/main.go index 2340df1..c151fe9 100644 --- a/main.go +++ b/main.go @@ -5,11 +5,13 @@ import ( "net" "os" "time" + "vncproxy/common" + "vncproxy/encodings" "vncproxy/vnc" ) func main() { - fmt.Println("") + //fmt.Println("") //nc, err := net.Dial("tcp", "192.168.1.101:5903") nc, err := net.Dial("tcp", "localhost:5903") @@ -29,17 +31,18 @@ func main() { // fmt.Printf("error requesting fb update: %s\n", err) // } - tight := vnc.TightEncoding{} - //rre := vnc.RREEncoding{} - //zlib := vnc.ZLibEncoding{} - //zrle := vnc.ZRLEEncoding{} - cpyRect := vnc.CopyRectEncoding{} - //hextile := vnc.HextileEncoding{} + tight := encodings.TightEncoding{} + //rre := encodings.RREEncoding{} + //zlib := encodings.ZLibEncoding{} + //zrle := encodings.ZRLEEncoding{} + cpyRect := encodings.CopyRectEncoding{} + //coRRE := encodings.CoRREEncoding{} + //hextile := encodings.HextileEncoding{} file, _ := os.OpenFile("stam.bin", os.O_CREATE|os.O_RDWR, 0755) defer file.Close() tight.SetOutput(file) - clientConn.SetEncodings([]vnc.Encoding{&cpyRect, &tight}) + clientConn.SetEncodings([]common.Encoding{&cpyRect, &tight}) go func() { for { diff --git a/vnc/client-conn.go b/vnc/client-conn.go index 6fc55a8..5710e0d 100644 --- a/vnc/client-conn.go +++ b/vnc/client-conn.go @@ -7,6 +7,7 @@ import ( "io" "net" "unicode" + "vncproxy/common" ) // A ServerMessage implements a message sent from the server to the client. @@ -32,9 +33,7 @@ type ClientAuth interface { } type ClientConn struct { - conn net.Conn - output io.Writer - passThrough bool + conn net.Conn //c net.Conn config *ClientConfig @@ -46,7 +45,7 @@ type ClientConn struct { // Encodings supported by the client. This should not be modified // directly. Instead, SetEncodings should be used. - Encs []Encoding + Encs []common.Encoding // Width of the frame buffer in pixels, sent from the server. FrameBufferWidth uint16 @@ -60,7 +59,7 @@ type ClientConn struct { // The pixel format associated with the connection. This shouldn't // be modified. If you wish to set a new pixel format, use the // SetPixelFormat method. - PixelFormat PixelFormat + PixelFormat common.PixelFormat } // A ClientConfig structure is used to configure a ClientConn. After @@ -246,7 +245,7 @@ func (c *ClientConn) PointerEvent(mask ButtonMask, x, y uint16) error { // given should not be modified. // // See RFC 6143 Section 7.5.2 -func (c *ClientConn) SetEncodings(encs []Encoding) error { +func (c *ClientConn) SetEncodings(encs []common.Encoding) error { data := make([]interface{}, 3+len(encs)) data[0] = uint8(2) data[1] = uint8(0) @@ -277,7 +276,7 @@ func (c *ClientConn) SetEncodings(encs []Encoding) error { // in FramebufferUpdate messages from the server. // // See RFC 6143 Section 7.5.1 -func (c *ClientConn) SetPixelFormat(format *PixelFormat) error { +func (c *ClientConn) SetPixelFormat(format *common.PixelFormat) error { var keyEvent [20]byte keyEvent[0] = 0 diff --git a/vnc/client.go b/vnc/client.go deleted file mode 100644 index e46d86c..0000000 --- a/vnc/client.go +++ /dev/null @@ -1,75 +0,0 @@ -// Package vnc implements a VNC client. -// -// References: -// [PROTOCOL]: http://tools.ietf.org/html/rfc6143 -package vnc - -import ( - "encoding/binary" - "io" -) - -// type DataSource struct { -// conn io.Reader -// output io.Writer -// passThrough bool -// PixelFormat PixelFormat -// }Color - -func (d *ClientConn) readBytes(count int) ([]byte, error) { - buff := make([]byte, count) - - _, err := io.ReadFull(d.conn, buff) - if err != nil { - //if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil { - return nil, err - } - return buff, nil -} - -func (d *ClientConn) readUint8() (uint8, error) { - var myUint uint8 - if err := binary.Read(d.conn, binary.BigEndian, &myUint); err != nil { - return 0, err - } - //fmt.Printf("myUint=%d", myUint) - return myUint, nil -} -func (d *ClientConn) readUint16() (uint16, error) { - var myUint uint16 - if err := binary.Read(d.conn, binary.BigEndian, &myUint); err != nil { - return 0, err - } - //fmt.Printf("myUint=%d", myUint) - return myUint, nil -} -func (d *ClientConn) readUint32() (uint32, error) { - var myUint uint32 - if err := binary.Read(d.conn, binary.BigEndian, &myUint); err != nil { - return 0, err - } - //fmt.Printf("myUint=%d", myUint) - return myUint, nil -} -func (d *ClientConn) readCompactLen() (int, error) { - var err error - part, err := d.readUint8() - //byteCount := 1 - len := uint32(part & 0x7F) - if (part & 0x80) != 0 { - part, err = d.readUint8() - //byteCount++ - len |= uint32(part&0x7F) << 7 - if (part & 0x80) != 0 { - part, err = d.readUint8() - //byteCount++ - len |= uint32(part&0xFF) << 14 - } - } - - // for i := 0; i < byteCount; i++{ - // rec.writeByte(portion[i]); - // } - - return int(len), err -} diff --git a/vnc/enc-rre.go b/vnc/enc-rre.go deleted file mode 100644 index 2b58811..0000000 --- a/vnc/enc-rre.go +++ /dev/null @@ -1,69 +0,0 @@ -package vnc - -import "io" - -type RREEncoding struct { - Colors []Color -} - -func (z *RREEncoding) Type() int32 { - return 2 -} -func (z *RREEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { - - bytesPerPixel := int(conn.PixelFormat.BPP / 8) - numOfSubrectangles, _ := conn.readUint32() - - //read whole rect background color - conn.readBytes(bytesPerPixel) - - //read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b) - _, err := conn.readBytes(int(numOfSubrectangles) * (bytesPerPixel + 8)) - - if err != nil { - return nil, err - } - return z, nil -} - -type CoRREEncoding struct { - Colors []Color -} - -func (z *CoRREEncoding) Type() int32 { - return 4 -} - -func (z *CoRREEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { - - bytesPerPixel := int(conn.PixelFormat.BPP / 8) - numOfSubrectangles, _ := conn.readUint32() - - //read whole rect background color - conn.readBytes(bytesPerPixel) - - //read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b) - _, err := conn.readBytes(int(numOfSubrectangles) * (bytesPerPixel + 4)) - - if err != nil { - return nil, err - } - return z, nil - - //int nSubrects = rfb.readU32(); - - //byte[] bg_buf = new byte[bytesPerPixel]; - //rfb.readFully(bytesPerPixel); - //Color pixel; - // if (bytesPixel == 1) { - // pixel = colors[bg_buf[0] & 0xFF]; - // } else { - // pixel = new Color(bg_buf[2] & 0xFF, bg_buf[1] & 0xFF, bg_buf[0] & 0xFF); - // } - // memGraphics.setColor(pixel); - // memGraphics.fillRect(x, y, w, h); - - // byte[] buf = new byte[nSubrects * (bytesPixel + 4)]; - // rfb.readFully(buf); - -} diff --git a/vnc/enc-zlib.go b/vnc/enc-zlib.go deleted file mode 100644 index f28b023..0000000 --- a/vnc/enc-zlib.go +++ /dev/null @@ -1,22 +0,0 @@ -package vnc - -import "io" - -type ZLibEncoding struct { - Colors []Color -} - -func (z *ZLibEncoding) Type() int32 { - return 6 -} -func (z *ZLibEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { - //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} - //bytesPerPixel := c.PixelFormat.BPP / 8 - len, _ := conn.readUint32() - _, err := conn.readBytes(int(len)) - - if err != nil { - return nil, err - } - return z, nil -} diff --git a/vnc/enc-zrle.go b/vnc/enc-zrle.go deleted file mode 100644 index 7731a8a..0000000 --- a/vnc/enc-zrle.go +++ /dev/null @@ -1,22 +0,0 @@ -package vnc - -import "io" - -type ZRLEEncoding struct { - Colors []Color -} - -func (z *ZRLEEncoding) Type() int32 { - return 16 -} -func (z *ZRLEEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { - //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} - //bytesPerPixel := c.PixelFormat.BPP / 8 - len, _ := conn.readUint32() - _, err := conn.readBytes(int(len)) - - if err != nil { - return nil, err - } - return z, nil -} diff --git a/vnc/encoding.go b/vnc/encoding.go deleted file mode 100644 index 9c7b09e..0000000 --- a/vnc/encoding.go +++ /dev/null @@ -1,45 +0,0 @@ -package vnc - -import "io" - -// An Encoding implements a method for encoding pixel data that is -// sent by the server to the client. -type Encoding interface { - // The number that uniquely identifies this encoding type. - Type() int32 - - // Read reads 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, io.Reader) (Encoding, error) -} - -const ( - EncodingRaw = 0 - EncodingCopyRect = 1 - EncodingRRE = 2 - EncodingCoRRE = 4 - EncodingHextile = 5 - EncodingZlib = 6 - EncodingTight = 7 - EncodingZRLE = 16 -) - -type CopyRectEncoding struct { - Colors []Color - copyRectSrcX uint16 - copyRectSrcY uint16 -} - -func (z *CopyRectEncoding) Type() int32 { - return 1 -} -func (z *CopyRectEncoding) Read(conn *ClientConn, rect *Rectangle, r io.Reader) (Encoding, error) { - //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} - //bytesPerPixel := c.PixelFormat.BPP / 8 - z.copyRectSrcX, _ = conn.readUint16() - z.copyRectSrcY, _ = conn.readUint16() - return z, nil -} - -////////// diff --git a/vnc/pixel_format.go b/vnc/pixel_format.go index c951298..e25af24 100644 --- a/vnc/pixel_format.go +++ b/vnc/pixel_format.go @@ -4,9 +4,10 @@ import ( "bytes" "encoding/binary" "io" + "vncproxy/common" ) -func readPixelFormat(r io.Reader, result *PixelFormat) error { +func readPixelFormat(r io.Reader, result *common.PixelFormat) error { var rawPixelFormat [16]byte if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil { return err @@ -67,7 +68,7 @@ func readPixelFormat(r io.Reader, result *PixelFormat) error { return nil } -func writePixelFormat(format *PixelFormat) ([]byte, error) { +func writePixelFormat(format *common.PixelFormat) ([]byte, error) { var buf bytes.Buffer // Byte 1 diff --git a/vnc/recorder.go b/vnc/recorder.go index a9aad24..83b900d 100644 --- a/vnc/recorder.go +++ b/vnc/recorder.go @@ -2,15 +2,16 @@ package vnc import ( "os" + "vncproxy/common" ) type Recorder struct { RBSFileName string fileHandle *os.File - logger Logger + logger common.Logger } -func NewRecorder(saveFilePath string, logger Logger) *Recorder { +func NewRecorder(saveFilePath string, logger common.Logger) *Recorder { rec := Recorder{RBSFileName: saveFilePath} var err error rec.fileHandle, err = os.OpenFile(saveFilePath, os.O_RDWR|os.O_CREATE, 0755) diff --git a/vnc/server_messages.go b/vnc/server_messages.go index 8f6de43..fb1ad2e 100644 --- a/vnc/server_messages.go +++ b/vnc/server_messages.go @@ -5,18 +5,14 @@ import ( "encoding/json" "fmt" "io" + "vncproxy/common" + "vncproxy/encodings" ) - // FramebufferUpdateMessage consists of a sequence of rectangles of // pixel data that the client should put into its framebuffer. type FramebufferUpdateMessage struct { - Rectangles []Rectangle -} - - -func (r *Rectangle) String() string { - return fmt.Sprintf("(%d,%d) (width: %d, height: %d), Enc= %d", r.X, r.Y, r.Width, r.Height, r.Enc.Type()) + Rectangles []common.Rectangle } func (m *FramebufferUpdateMessage) String() string { @@ -44,17 +40,17 @@ func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage } // Build the map of encodings supported - encMap := make(map[int32]Encoding) + encMap := make(map[int32]common.Encoding) for _, enc := range c.Encs { encMap[enc.Type()] = enc } // We must always support the raw encoding - rawEnc := new(RawEncoding) + rawEnc := new(encodings.RawEncoding) encMap[rawEnc.Type()] = rawEnc fmt.Printf("numrects= %d\n", numRects) - rects := make([]Rectangle, numRects) + rects := make([]common.Rectangle, numRects) for i := uint16(0); i < numRects; i++ { fmt.Printf("###############rect################: %d\n", i) var encodingType int32 @@ -84,7 +80,7 @@ func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage } var err error - rect.Enc, err = enc.Read(c, rect, r) + rect.Enc, err = enc.Read(&c.PixelFormat, rect, r) if err != nil { return nil, err } @@ -184,7 +180,7 @@ func (*ServerCutTextMessage) Type() uint8 { return 3 } -func (*ServerCutTextMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { +func (*ServerCutTextMessage) Read(conn *ClientConn, r io.Reader) (ServerMessage, error) { // Read off the padding var padding [1]byte if _, err := io.ReadFull(r, padding[:]); err != nil {