added RfbReaderHelper which wraps the connection reader and allows to add listeners like the recorder or proxy

added fbs recorder, and tested it against vine vnc server 5.0.1 and rfbplayer 1.4 —> works! (there is still some problem with tight VNC server)
This commit is contained in:
amit bezalel 2017-06-17 11:02:06 +03:00
parent a74fe9e60c
commit 007e748c61
39 changed files with 3792 additions and 3367 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,5 @@
package common package common
import (
"io"
)
// An Encoding implements a method for encoding pixel data that is // An Encoding implements a method for encoding pixel data that is
// sent by the server to the client. // sent by the server to the client.
type Encoding interface { type Encoding interface {
@ -13,7 +9,7 @@ type Encoding interface {
// Read reads the contents of the encoded pixel data from the reader. // Read reads the contents of the encoded pixel data from the reader.
// This should return a new Encoding implementation that contains // This should return a new Encoding implementation that contains
// the proper data. // the proper data.
Read(*PixelFormat, *Rectangle, io.Reader) (Encoding, error) Read(*PixelFormat, *Rectangle, *RfbReadHelper) (Encoding, error)
} }
const ( const (

View File

@ -1,45 +1,85 @@
// Package vnc implements a VNC client.
//
// References:
// [PROTOCOL]: http://tools.ietf.org/html/rfc6143
package common package common
import ( import (
"bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"io" "io"
) )
// type DataSource struct { var TightMinToCompress = 12
// 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) { const (
readLen, err := r.reader.Read(p) SegmentBytes SegmentType = iota
r.savedBuff.Write(p) SegmentMessageSeparator
return readLen, err SegmentRectSeparator
)
type SegmentType int
type RfbSegment struct {
Bytes []byte
SegmentType SegmentType
UpcomingObjectType int
} }
func (r *RfbReader) SavedBuff() bytes.Buffer { type SegmentConsumer interface {
return r.savedBuff Consume(*RfbSegment) error
} }
type RfbReadHelper struct { type RfbReadHelper struct {
io.Reader io.Reader
Listener SegmentConsumer
} }
func (d *RfbReadHelper) ReadBytes(count int) ([]byte, error) { func (r *RfbReadHelper) ReadDiscrete(p []byte) (int, error) {
return r.Read(p)
}
func (r *RfbReadHelper) SendRectSeparator(upcomingRectType int) error {
seg := &RfbSegment{SegmentType: SegmentRectSeparator, UpcomingObjectType: upcomingRectType}
if r.Listener != nil {
return nil
}
return r.Listener.Consume(seg)
}
func (r *RfbReadHelper) SendMessageSeparator(upcomingMessageType int) error {
seg := &RfbSegment{SegmentType: SegmentMessageSeparator, UpcomingObjectType: upcomingMessageType}
if r.Listener == nil {
return nil
}
return r.Listener.Consume(seg)
}
func (r *RfbReadHelper) PublishBytes(p []byte) error {
seg := &RfbSegment{Bytes: p, SegmentType: SegmentBytes}
if r.Listener == nil {
return nil
}
return r.Listener.Consume(seg)
}
func (r *RfbReadHelper) Read(p []byte) (n int, err error) {
readLen, err := r.Reader.Read(p)
if err != nil {
return 0, err
}
//write the bytes to the Listener for further processing
seg := &RfbSegment{Bytes: p, SegmentType: SegmentBytes}
if r.Listener == nil {
return 0,nil
}
r.Listener.Consume(seg)
if err != nil {
return 0, err
}
return readLen, err
}
func (r *RfbReadHelper) ReadBytes(count int) ([]byte, error) {
buff := make([]byte, count) buff := make([]byte, count)
_, err := io.ReadFull(d.Reader, buff) _, err := io.ReadFull(r, buff)
if err != nil { if err != nil {
//if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil { //if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil {
return nil, err return nil, err
@ -47,41 +87,41 @@ func (d *RfbReadHelper) ReadBytes(count int) ([]byte, error) {
return buff, nil return buff, nil
} }
func (d *RfbReadHelper) ReadUint8() (uint8, error) { func (r *RfbReadHelper) ReadUint8() (uint8, error) {
var myUint uint8 var myUint uint8
if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil { if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
return 0, err return 0, err
} }
//fmt.Printf("myUint=%d", myUint) //fmt.Printf("myUint=%d", myUint)
return myUint, nil return myUint, nil
} }
func (d *RfbReadHelper) ReadUint16() (uint16, error) { func (r *RfbReadHelper) ReadUint16() (uint16, error) {
var myUint uint16 var myUint uint16
if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil { if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
return 0, err return 0, err
} }
//fmt.Printf("myUint=%d", myUint) //fmt.Printf("myUint=%d", myUint)
return myUint, nil return myUint, nil
} }
func (d *RfbReadHelper) ReadUint32() (uint32, error) { func (r *RfbReadHelper) ReadUint32() (uint32, error) {
var myUint uint32 var myUint uint32
if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil { if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
return 0, err return 0, err
} }
//fmt.Printf("myUint=%d", myUint) //fmt.Printf("myUint=%d", myUint)
return myUint, nil return myUint, nil
} }
func (d *RfbReadHelper) ReadCompactLen() (int, error) { func (r *RfbReadHelper) ReadCompactLen() (int, error) {
var err error var err error
part, err := d.ReadUint8() part, err := r.ReadUint8()
//byteCount := 1 //byteCount := 1
len := uint32(part & 0x7F) len := uint32(part & 0x7F)
if (part & 0x80) != 0 { if (part & 0x80) != 0 {
part, err = d.ReadUint8() part, err = r.ReadUint8()
//byteCount++ //byteCount++
len |= uint32(part&0x7F) << 7 len |= uint32(part&0x7F) << 7
if (part & 0x80) != 0 { if (part & 0x80) != 0 {
part, err = d.ReadUint8() part, err = r.ReadUint8()
//byteCount++ //byteCount++
len |= uint32(part&0xFF) << 14 len |= uint32(part&0xFF) << 14
} }
@ -94,8 +134,6 @@ func (d *RfbReadHelper) ReadCompactLen() (int, error) {
return int(len), err return int(len), err
} }
var TightMinToCompress int = 12
func (r *RfbReadHelper) ReadTightData(dataSize int) ([]byte, error) { func (r *RfbReadHelper) ReadTightData(dataSize int) ([]byte, error) {
if int(dataSize) < TightMinToCompress { if int(dataSize) < TightMinToCompress {
return r.ReadBytes(int(dataSize)) return r.ReadBytes(int(dataSize))

View File

@ -1,9 +1,6 @@
package encodings package encodings
import ( import "vncproxy/common"
"io"
"vncproxy/common"
)
type CopyRectEncoding struct { type CopyRectEncoding struct {
//Colors []Color //Colors []Color
@ -14,12 +11,9 @@ type CopyRectEncoding struct {
func (z *CopyRectEncoding) Type() int32 { func (z *CopyRectEncoding) Type() int32 {
return 1 return 1
} }
func (z *CopyRectEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (z *CopyRectEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
conn := common.RfbReadHelper{r} z.copyRectSrcX, _ = r.ReadUint16()
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} z.copyRectSrcY, _ = r.ReadUint16()
//bytesPerPixel := c.PixelFormat.BPP / 8
z.copyRectSrcX, _ = conn.ReadUint16()
z.copyRectSrcY, _ = conn.ReadUint16()
return z, nil return z, nil
} }

View File

@ -1,7 +1,6 @@
package encodings package encodings
import ( import (
"io"
"vncproxy/common" "vncproxy/common"
) )
@ -13,16 +12,15 @@ func (z *CoRREEncoding) Type() int32 {
return 4 return 4
} }
func (z *CoRREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (z *CoRREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
conn := common.RfbReadHelper{r}
bytesPerPixel := int(pixelFmt.BPP / 8) bytesPerPixel := int(pixelFmt.BPP / 8)
numOfSubrectangles, _ := conn.ReadUint32() numOfSubrectangles, _ := r.ReadUint32()
//read whole rect background color //read whole rect background color
conn.ReadBytes(bytesPerPixel) r.ReadBytes(bytesPerPixel)
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b) //read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
_, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4)) _, err := r.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1,9 +1,6 @@
package encodings package encodings
import ( import "vncproxy/common"
"io"
"vncproxy/common"
)
const ( const (
HextileRaw = 1 HextileRaw = 1
@ -20,11 +17,9 @@ type HextileEncoding struct {
func (z *HextileEncoding) Type() int32 { func (z *HextileEncoding) Type() int32 {
return 5 return 5
} }
func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
conn := common.RfbReadHelper{r}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
bytesPerPixel := int(pixelFmt.BPP) / 8 bytesPerPixel := int(pixelFmt.BPP) / 8
//buf := make([]byte, bytesPerPixel)
for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 { for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 {
th := 16 th := 16
if rect.Y+rect.Height-ty < 16 { if rect.Y+rect.Height-ty < 16 {
@ -38,7 +33,7 @@ func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectan
} }
//handle Hextile Subrect(tx, ty, tw, th): //handle Hextile Subrect(tx, ty, tw, th):
subencoding, err := conn.ReadUint8() subencoding, err := r.ReadUint8()
//fmt.Printf("hextile reader tile: (%d,%d) subenc=%d\n", ty, tx, subencoding) //fmt.Printf("hextile reader tile: (%d,%d) subenc=%d\n", ty, tx, subencoding)
if err != nil { if err != nil {
//fmt.Printf("error in hextile reader: %v\n", err) //fmt.Printf("error in hextile reader: %v\n", err)
@ -47,22 +42,22 @@ func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectan
if (subencoding & HextileRaw) != 0 { if (subencoding & HextileRaw) != 0 {
//ReadRawRect(c, rect, r) //ReadRawRect(c, rect, r)
conn.ReadBytes(tw * th * bytesPerPixel) r.ReadBytes(tw * th * bytesPerPixel)
//fmt.Printf("hextile reader: HextileRaw\n") //fmt.Printf("hextile reader: HextileRaw\n")
continue continue
} }
if (subencoding & HextileBackgroundSpecified) != 0 { if (subencoding & HextileBackgroundSpecified) != 0 {
conn.ReadBytes(int(bytesPerPixel)) r.ReadBytes(int(bytesPerPixel))
} }
if (subencoding & HextileForegroundSpecified) != 0 { if (subencoding & HextileForegroundSpecified) != 0 {
conn.ReadBytes(int(bytesPerPixel)) r.ReadBytes(int(bytesPerPixel))
} }
if (subencoding & HextileAnySubrects) == 0 { if (subencoding & HextileAnySubrects) == 0 {
//fmt.Printf("hextile reader: no Subrects\n") //fmt.Printf("hextile reader: no Subrects\n")
continue continue
} }
//fmt.Printf("hextile reader: handling Subrects\n") //fmt.Printf("hextile reader: handling Subrects\n")
nSubrects, err := conn.ReadUint8() nSubrects, err := r.ReadUint8()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -71,7 +66,7 @@ func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectan
bufsize += int(nSubrects) * int(bytesPerPixel) bufsize += int(nSubrects) * int(bytesPerPixel)
} }
//byte[] buf = new byte[bufsize]; //byte[] buf = new byte[bufsize];
conn.ReadBytes(bufsize) r.ReadBytes(bufsize)
} }
} }

View File

@ -1,7 +1,6 @@
package encodings package encodings
import ( import (
"io"
"vncproxy/common" "vncproxy/common"
) )
@ -16,9 +15,9 @@ func (*RawEncoding) Type() int32 {
return 0 return 0
} }
func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
conn := common.RfbReadHelper{r} //conn := common.RfbReadHelper{Reader:r}
bytesPerPixel := int(pixelFmt.BPP / 8) bytesPerPixel := int(pixelFmt.BPP / 8)
//pixelBytes := make([]uint8, bytesPerPixel) //pixelBytes := make([]uint8, bytesPerPixel)
@ -31,7 +30,7 @@ func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r
for y := uint16(0); y < rect.Height; y++ { for y := uint16(0); y < rect.Height; y++ {
for x := uint16(0); x < rect.Width; x++ { for x := uint16(0); x < rect.Width; x++ {
if _, err := conn.ReadBytes(bytesPerPixel); err != nil { if _, err := r.ReadBytes(bytesPerPixel); err != nil {
return nil, err return nil, err
} }

View File

@ -1,6 +1,5 @@
package encodings package encodings
import "io"
import "vncproxy/common" import "vncproxy/common"
type RREEncoding struct { type RREEncoding struct {
@ -10,16 +9,16 @@ type RREEncoding struct {
func (z *RREEncoding) Type() int32 { func (z *RREEncoding) Type() int32 {
return 2 return 2
} }
func (z *RREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (z *RREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
conn := common.RfbReadHelper{r} //conn := common.RfbReadHelper{Reader:r}
bytesPerPixel := int(pixelFmt.BPP / 8) bytesPerPixel := int(pixelFmt.BPP / 8)
numOfSubrectangles, _ := conn.ReadUint32() numOfSubrectangles, _ := r.ReadUint32()
//read whole rect background color //read whole rect background color
conn.ReadBytes(bytesPerPixel) r.ReadBytes(bytesPerPixel)
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b) //read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
_, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 8)) _, err := r.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 8))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -69,13 +69,13 @@ func calcTightBytePerPixel(pf *common.PixelFormat) int {
return bytesPerPixelTight return bytesPerPixelTight
} }
func (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, reader io.Reader) (common.Encoding, error) { func (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
bytesPixel := calcTightBytePerPixel(pixelFmt) bytesPixel := calcTightBytePerPixel(pixelFmt)
conn := common.RfbReadHelper{reader} //conn := common.RfbReadHelper{Reader:reader}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//var subencoding uint8 //var subencoding uint8
subencoding, err := conn.ReadUint8() subencoding, err := r.ReadUint8()
if err != nil { if err != nil {
fmt.Printf("error in handling tight encoding: %v\n", err) fmt.Printf("error in handling tight encoding: %v\n", err)
return nil, err return nil, err
@ -99,19 +99,19 @@ func (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangl
case TightFill: case TightFill:
fmt.Printf("reading fill size=%d\n", bytesPixel) fmt.Printf("reading fill size=%d\n", bytesPixel)
//read color //read color
conn.ReadBytes(int(bytesPixel)) r.ReadBytes(int(bytesPixel))
return t, nil return t, nil
case TightJpeg: case TightJpeg:
if pixelFmt.BPP == 8 { if pixelFmt.BPP == 8 {
return nil, errors.New("Tight encoding: JPEG is not supported in 8 bpp mode") return nil, errors.New("Tight encoding: JPEG is not supported in 8 bpp mode")
} }
len, err := conn.ReadCompactLen() len, err := r.ReadCompactLen()
if err != nil { if err != nil {
return nil, err return nil, err
} }
fmt.Printf("reading jpeg size=%d\n", len) fmt.Printf("reading jpeg size=%d\n", len)
conn.ReadBytes(len) r.ReadBytes(len)
return t, nil return t, nil
default: default:
@ -119,13 +119,13 @@ func (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangl
fmt.Println("Compression control byte is incorrect!") fmt.Println("Compression control byte is incorrect!")
} }
handleTightFilters(subencoding, pixelFmt, rect, reader) handleTightFilters(subencoding, pixelFmt, rect, r)
return t, nil return t, nil
} }
} }
func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *common.Rectangle, reader io.Reader) { func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) {
conn := common.RfbReadHelper{reader} //conn := common.RfbReadHelper{Reader:reader}
var FILTER_ID_MASK uint8 = 0x40 var FILTER_ID_MASK uint8 = 0x40
//var STREAM_ID_MASK uint8 = 0x30 //var STREAM_ID_MASK uint8 = 0x30
@ -134,7 +134,7 @@ func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *c
var err error var err error
if (subencoding & FILTER_ID_MASK) > 0 { // filter byte presence if (subencoding & FILTER_ID_MASK) > 0 { // filter byte presence
filterid, err = conn.ReadUint8() filterid, err = r.ReadUint8()
if err != nil { if err != nil {
fmt.Printf("error in handling tight encoding, reading filterid: %v\n", err) fmt.Printf("error in handling tight encoding, reading filterid: %v\n", err)
return return
@ -154,11 +154,11 @@ func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *c
switch filterid { switch filterid {
case TightFilterPalette: //PALETTE_FILTER case TightFilterPalette: //PALETTE_FILTER
colorCount, err := conn.ReadUint8() colorCount, err := r.ReadUint8()
paletteSize := colorCount + 1 // add one more paletteSize := colorCount + 1 // add one more
fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel) fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
//complete palette //complete palette
conn.ReadBytes(int(paletteSize) * bytesPixel) r.ReadBytes(int(paletteSize) * bytesPixel)
var dataLength int var dataLength int
if paletteSize == 2 { if paletteSize == 2 {
@ -166,7 +166,7 @@ func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *c
} else { } else {
dataLength = int(rect.Width * rect.Height) dataLength = int(rect.Width * rect.Height)
} }
_, err = conn.ReadTightData(dataLength) _, err = r.ReadTightData(dataLength)
if err != nil { if err != nil {
fmt.Printf("error in handling tight encoding, Reading Palette: %v\n", err) fmt.Printf("error in handling tight encoding, Reading Palette: %v\n", err)
return return
@ -175,10 +175,10 @@ func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *c
fmt.Printf("----GRADIENT_FILTER: bytesPixel=%d\n", bytesPixel) fmt.Printf("----GRADIENT_FILTER: bytesPixel=%d\n", bytesPixel)
//useGradient = true //useGradient = true
fmt.Printf("usegrad: %d\n", filterid) fmt.Printf("usegrad: %d\n", filterid)
conn.ReadTightData(lengthCurrentbpp) r.ReadTightData(lengthCurrentbpp)
case TightFilterCopy: //BASIC_FILTER case TightFilterCopy: //BASIC_FILTER
fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel) fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel)
conn.ReadTightData(lengthCurrentbpp) r.ReadTightData(lengthCurrentbpp)
default: default:
fmt.Printf("Bad tight filter id: %d\n", filterid) fmt.Printf("Bad tight filter id: %d\n", filterid)
return return

View File

@ -1,6 +1,5 @@
package encodings package encodings
import "io"
import "vncproxy/common" import "vncproxy/common"
type ZLibEncoding struct { type ZLibEncoding struct {
@ -10,12 +9,12 @@ type ZLibEncoding struct {
func (z *ZLibEncoding) Type() int32 { func (z *ZLibEncoding) Type() int32 {
return 6 return 6
} }
func (z *ZLibEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (z *ZLibEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
conn := common.RfbReadHelper{r} //conn := common.RfbReadHelper{Reader:r}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//bytesPerPixel := c.PixelFormat.BPP / 8 //bytesPerPixel := c.PixelFormat.BPP / 8
len, _ := conn.ReadUint32() len, _ := r.ReadUint32()
_, err := conn.ReadBytes(int(len)) _, err := r.ReadBytes(int(len))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -1,6 +1,5 @@
package encodings package encodings
import "io"
import "vncproxy/common" import "vncproxy/common"
type ZRLEEncoding struct { type ZRLEEncoding struct {
@ -10,12 +9,12 @@ type ZRLEEncoding struct {
func (z *ZRLEEncoding) Type() int32 { func (z *ZRLEEncoding) Type() int32 {
return 16 return 16
} }
func (z *ZRLEEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) { func (z *ZRLEEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
conn := common.RfbReadHelper{r} //conn := common.RfbReadHelper{Reader: r}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat} //conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//bytesPerPixel := c.PixelFormat.BPP / 8 //bytesPerPixel := c.PixelFormat.BPP / 8
len, _ := conn.ReadUint32() len, _ := r.ReadUint32()
_, err := conn.ReadBytes(int(len)) _, err := r.ReadBytes(int(len))
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -0,0 +1,22 @@
package listeners
import "vncproxy/common"
type MultiListener struct {
listeners []common.SegmentConsumer
}
func (m *MultiListener) AddListener(listener common.SegmentConsumer) {
m.listeners = append(m.listeners, listener)
}
func (m *MultiListener) Consume(seg *common.RfbSegment) error {
for _, li := range m.listeners {
//fmt.Println(li)
err := li.Consume(seg)
if err != nil {
return err
}
}
return nil
}

12
listeners/pass-to.go Normal file
View File

@ -0,0 +1,12 @@
package listeners
import "vncproxy/common"
import "io"
type PassListener struct {
io.Writer
}
func (*PassListener) Consume(seg *common.RfbSegment) error {
return nil
}

155
listeners/recorder.go Normal file
View File

@ -0,0 +1,155 @@
package listeners
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
"os"
"time"
"vncproxy/common"
)
type Recorder struct {
//common.BytesListener
RBSFileName string
writer *os.File
logger common.Logger
startTime int
buffer bytes.Buffer
}
func getNowMillisec() int {
return int(time.Now().UnixNano() / int64(time.Millisecond))
}
func NewRecorder(saveFilePath string, desktopName string, fbWidth uint16, fbHeight uint16) *Recorder {
//delete file if it exists
if _, err := os.Stat(saveFilePath); err == nil {
os.Remove(saveFilePath)
}
rec := Recorder{RBSFileName: saveFilePath, startTime: getNowMillisec()}
var err error
rec.writer, err = os.OpenFile(saveFilePath, os.O_RDWR|os.O_CREATE, 0755)
rec.writeStartSession(desktopName, fbWidth, fbHeight)
if err != nil {
fmt.Printf("unable to open file: %s, error: %v", saveFilePath, err)
return nil
}
return &rec
}
const (
FramebufferUpdate = 0
SetColourMapEntries = 1
Bell = 2
ServerCutText = 3
)
const versionMsg_3_3 = "RFB 003.003\n"
const versionMsg_3_7 = "RFB 003.007\n"
const versionMsg_3_8 = "RFB 003.008\n"
// Security types
const (
SecTypeInvalid = 0
SecTypeNone = 1
SecTypeVncAuth = 2
SecTypeTight = 16
)
// func (r *Recorder) writeHeader() error {
// _, err := r.writer.WriteString("FBS 001.000\n")
// return err
// // df.write("FBS 001.000\n".getBytes());
// }
func (r *Recorder) writeStartSession(desktopName string, framebufferWidth uint16, framebufferHeight uint16) error {
//write rfb header information (the only part done without the [size|data|timestamp] block wrapper)
r.buffer.WriteString("FBS 001.000\n")
r.buffer.WriteTo(r.writer)
r.buffer.Reset()
//push the version message into the buffer so it will be written in the first rbs block
r.buffer.WriteString(versionMsg_3_3)
//push sec type and fb dimensions
binary.Write(&r.buffer, binary.BigEndian, int32(SecTypeNone))
binary.Write(&r.buffer, binary.BigEndian, int16(framebufferWidth))
binary.Write(&r.buffer, binary.BigEndian, int16(framebufferHeight))
var fbsServerInitMsg = []byte{32, 24, 0, 1, 0, byte(0xFF), 0, byte(0xFF), 0, byte(0xFF), 16, 8, 0, 0, 0, 0}
r.buffer.Write(fbsServerInitMsg)
binary.Write(&r.buffer, binary.BigEndian, uint32(len(desktopName)+1))
r.buffer.WriteString(desktopName)
binary.Write(&r.buffer, binary.BigEndian, byte(0)) // add null termination for desktop string
return nil
}
func (r *Recorder) Consume(data *common.RfbSegment) error {
switch data.SegmentType {
case common.SegmentMessageSeparator:
switch data.UpcomingObjectType {
case FramebufferUpdate:
r.writeToDisk()
case SetColourMapEntries:
case Bell:
case ServerCutText:
default:
return errors.New("unknown message type:" + string(data.UpcomingObjectType))
}
case common.SegmentRectSeparator:
r.writeToDisk()
case common.SegmentBytes:
_, err := r.buffer.Write(data.Bytes)
return err
default:
return errors.New("undefined RfbSegment type")
}
return nil
}
func (r *Recorder) writeToDisk() error {
timeSinceStart := getNowMillisec() - r.startTime
if r.buffer.Len() == 0 {
return nil
}
//write buff length
bytesLen := r.buffer.Len()
binary.Write(r.writer, binary.BigEndian, uint32(bytesLen))
paddedSize := (bytesLen + 3) & 0x7FFFFFFC
paddingSize := paddedSize - bytesLen
fmt.Printf("paddedSize=%d paddingSize=%d bytesLen=%d", paddedSize, paddingSize, bytesLen)
//write buffer padded to 32bit
_, err := r.buffer.WriteTo(r.writer)
padding := make([]byte, paddingSize)
fmt.Printf("padding=%v ", padding)
binary.Write(r.writer, binary.BigEndian, padding)
//write timestamp
binary.Write(r.writer, binary.BigEndian, uint32(timeSinceStart))
r.buffer.Reset()
return err
}
// func (r *Recorder) WriteUInt8(data uint8) error {
// buf := make([]byte, 1)
// buf[0] = byte(data) // cast int8 to byte
// return r.Write(buf)
// }
func (r *Recorder) Close() {
r.writer.Close()
}

View File

@ -16,7 +16,7 @@ func main() {
nc, err := net.Dial("tcp", "localhost:5903") nc, err := net.Dial("tcp", "localhost:5903")
if err != nil { if err != nil {
fmt.Printf(";error connecting to vnc server: %s", err) fmt.Printf("error connecting to vnc server: %s", err)
} }
var noauth vnc.ClientAuthNone var noauth vnc.ClientAuthNone
authArr := []vnc.ClientAuth{&vnc.PasswordAuth{Password: "Ch_#!T@8"}, &noauth} authArr := []vnc.ClientAuth{&vnc.PasswordAuth{Password: "Ch_#!T@8"}, &noauth}

View File

@ -8,6 +8,7 @@ import (
"net" "net"
"unicode" "unicode"
"vncproxy/common" "vncproxy/common"
"vncproxy/listeners"
) )
// A ServerMessage implements a message sent from the server to the client. // A ServerMessage implements a message sent from the server to the client.
@ -18,7 +19,7 @@ type ServerMessage interface {
// Read reads the contents of the message from the reader. At the point // Read reads the contents of the message from the reader. At the point
// this is called, the message type has already been read from the reader. // this is called, the message type has already been read from the reader.
// This should return a new ServerMessage that is the appropriate type. // This should return a new ServerMessage that is the appropriate type.
Read(*ClientConn, io.Reader) (ServerMessage, error) Read(*ClientConn, *common.RfbReadHelper) (ServerMessage, error)
} }
// A ClientAuth implements a method of authenticating with a remote server. // A ClientAuth implements a method of authenticating with a remote server.
@ -442,7 +443,9 @@ FindAuth:
// proper channels for users of the client to read. // proper channels for users of the client to read.
func (c *ClientConn) mainLoop() { func (c *ClientConn) mainLoop() {
defer c.Close() defer c.Close()
rec := listeners.NewRecorder("/Users/amitbet/recording.rbs", c.DesktopName, c.FrameBufferWidth, c.FrameBufferHeight)
reader := &common.RfbReadHelper{Reader: c.conn, Listener: rec}
// Build the map of available server messages // Build the map of available server messages
typeMap := make(map[uint8]ServerMessage) typeMap := make(map[uint8]ServerMessage)
@ -474,8 +477,10 @@ func (c *ClientConn) mainLoop() {
// Unsupported message type! Bad! // Unsupported message type! Bad!
break break
} }
reader.SendMessageSeparator(int(messageType))
reader.PublishBytes([]byte{byte(messageType)})
parsedMsg, err := msg.Read(c, c.conn) parsedMsg, err := msg.Read(c, reader)
if err != nil { if err != nil {
break break
} }

View File

@ -1,38 +0,0 @@
package vnc
import (
"os"
"vncproxy/common"
)
type Recorder struct {
RBSFileName string
fileHandle *os.File
logger common.Logger
}
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)
if err != nil {
logger.Errorf("unable to open file: %s, error: %v", saveFilePath, err)
return nil
}
return &rec
}
func (r *Recorder) Write(data []byte) error {
_, err := r.fileHandle.Write(data)
return err
}
// func (r *Recorder) WriteUInt8(data uint8) error {
// buf := make([]byte, 1)
// buf[0] = byte(data) // cast int8 to byte
// return r.Write(buf)
// }
func (r *Recorder) Close() {
r.fileHandle.Close()
}

View File

@ -27,7 +27,8 @@ func (*FramebufferUpdateMessage) Type() uint8 {
return 0 return 0
} }
func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { func (fbm *FramebufferUpdateMessage) Read(c *ClientConn, r *common.RfbReadHelper) (ServerMessage, error) {
// Read off the padding // Read off the padding
var padding [1]byte var padding [1]byte
if _, err := io.ReadFull(r, padding[:]); err != nil { if _, err := io.ReadFull(r, padding[:]); err != nil {
@ -53,8 +54,9 @@ func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage
rects := make([]common.Rectangle, numRects) rects := make([]common.Rectangle, numRects)
for i := uint16(0); i < numRects; i++ { for i := uint16(0); i < numRects; i++ {
fmt.Printf("###############rect################: %d\n", i) fmt.Printf("###############rect################: %d\n", i)
var encodingType int32
var encodingType int32
r.SendRectSeparator(-1)
rect := &rects[i] rect := &rects[i]
data := []interface{}{ data := []interface{}{
&rect.X, &rect.X,
@ -108,7 +110,7 @@ func (*SetColorMapEntriesMessage) Type() uint8 {
return 1 return 1
} }
func (*SetColorMapEntriesMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) { func (*SetColorMapEntriesMessage) Read(c *ClientConn, r *common.RfbReadHelper) (ServerMessage, error) {
// Read off the padding // Read off the padding
var padding [1]byte var padding [1]byte
if _, err := io.ReadFull(r, padding[:]); err != nil { if _, err := io.ReadFull(r, padding[:]); err != nil {
@ -161,7 +163,7 @@ func (*BellMessage) Type() uint8 {
return 2 return 2
} }
func (*BellMessage) Read(*ClientConn, io.Reader) (ServerMessage, error) { func (*BellMessage) Read(*ClientConn, *common.RfbReadHelper) (ServerMessage, error) {
return new(BellMessage), nil return new(BellMessage), nil
} }
@ -180,22 +182,31 @@ func (*ServerCutTextMessage) Type() uint8 {
return 3 return 3
} }
func (*ServerCutTextMessage) Read(conn *ClientConn, r io.Reader) (ServerMessage, error) { func (*ServerCutTextMessage) Read(conn *ClientConn, r *common.RfbReadHelper) (ServerMessage, error) {
//reader := common.RfbReadHelper{Reader: r}
// Read off the padding // Read off the padding
var padding [1]byte var padding [3]byte
if _, err := io.ReadFull(r, padding[:]); err != nil { if _, err := io.ReadFull(r, padding[:]); err != nil {
return nil, err return nil, err
} }
textLength, err := r.ReadUint32()
var textLength uint32 if err != nil {
if err := binary.Read(r, binary.BigEndian, &textLength); err != nil {
return nil, err return nil, err
} }
textBytes, err := r.ReadBytes(int(textLength))
textBytes := make([]uint8, textLength) if err != nil {
if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil {
return nil, err return nil, err
} }
//var textLength uint32
// if err := binary.Read(r, binary.BigEndian, &textLength); err != nil {
// return nil, err
// }
// textBytes := make([]uint8, textLength)
// if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil {
// return nil, err
// }
return &ServerCutTextMessage{string(textBytes)}, nil return &ServerCutTextMessage{string(textBytes)}, nil
} }