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

4
.gitignore vendored
View File

@ -1,2 +1,2 @@
*.bin
debug
*.bin
debug

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
<entry name="!?*.aj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="false">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>

View File

@ -1,3 +1,3 @@
<component name="CopyrightManager">
<settings default="" />
<component name="CopyrightManager">
<settings default="" />
</component>

View File

@ -1,42 +1,42 @@
<component name="libraryTable">
<library name="GOPATH &lt;vncproxy&gt;">
<CLASSES>
<root url="file://$PROJECT_DIR$/../elastictrail" />
<root url="file://$PROJECT_DIR$/../gopkg.in" />
<root url="file://$PROJECT_DIR$/../vncproxy1" />
<root url="file://$PROJECT_DIR$/../GoProjExample" />
<root url="file://$PROJECT_DIR$/../srf.opb" />
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
<root url="file://$PROJECT_DIR$/../github.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
<root url="file://$PROJECT_DIR$/../golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/srf" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/version" />
<root url="file://$PROJECT_DIR$/../srf.storage" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/../elastictrail" />
<root url="file://$PROJECT_DIR$/../gopkg.in" />
<root url="file://$PROJECT_DIR$/../vncproxy1" />
<root url="file://$PROJECT_DIR$/../GoProjExample" />
<root url="file://$PROJECT_DIR$/../srf.opb" />
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
<root url="file://$PROJECT_DIR$/../github.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
<root url="file://$PROJECT_DIR$/../golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/srf" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/version" />
<root url="file://$PROJECT_DIR$/../srf.storage" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
</SOURCES>
<excluded>
<root url="file://$PROJECT_DIR$" />
</excluded>
</library>
<component name="libraryTable">
<library name="GOPATH &lt;vncproxy&gt;">
<CLASSES>
<root url="file://$PROJECT_DIR$/../elastictrail" />
<root url="file://$PROJECT_DIR$/../gopkg.in" />
<root url="file://$PROJECT_DIR$/../vncproxy1" />
<root url="file://$PROJECT_DIR$/../GoProjExample" />
<root url="file://$PROJECT_DIR$/../srf.opb" />
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
<root url="file://$PROJECT_DIR$/../github.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
<root url="file://$PROJECT_DIR$/../golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/srf" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/version" />
<root url="file://$PROJECT_DIR$/../srf.storage" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="file://$PROJECT_DIR$/../elastictrail" />
<root url="file://$PROJECT_DIR$/../gopkg.in" />
<root url="file://$PROJECT_DIR$/../vncproxy1" />
<root url="file://$PROJECT_DIR$/../GoProjExample" />
<root url="file://$PROJECT_DIR$/../srf.opb" />
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
<root url="file://$PROJECT_DIR$/../github.com" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
<root url="file://$PROJECT_DIR$/../golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/golang.org" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/srf" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/version" />
<root url="file://$PROJECT_DIR$/../srf.storage" />
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
</SOURCES>
<excluded>
<root url="file://$PROJECT_DIR$" />
</excluded>
</library>
</component>

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GOROOT" path="/usr/local/Cellar/go/1.8.3/libexec" />
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GOROOT" path="/usr/local/Cellar/go/1.8.3/libexec" />
</project>

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/vncproxy.iml" filepath="$PROJECT_DIR$/.idea/vncproxy.iml" />
</modules>
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/vncproxy.iml" filepath="$PROJECT_DIR$/.idea/vncproxy.iml" />
</modules>
</component>
</project>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="GOPATH &lt;vncproxy&gt;" level="project" />
</component>
</module>
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="GOPATH &lt;vncproxy&gt;" level="project" />
</component>
</module>

File diff suppressed because it is too large Load Diff

144
.vscode/launch.json vendored
View File

@ -1,73 +1,73 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Test",
"type": "go",
"request": "launch",
"mode": "test",
"remotePath": "",
"port": 2345,
"program": "${workspaceRoot}/reader",
"args": [
"-test.v"
],
"osx": {
"env": {
//"GOPATH": "/Users/amitbet/Dropbox/go"
}
},
"windows": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
},
"showLog": true
},
{
"name": "Launch Grouper Tests",
"type": "go",
"request": "launch",
"mode": "test",
"remotePath": "",
"port": 2345,
"program": "${workspaceRoot}/consumer",
"args": [
"-test.v"
],
"osx": {
"env": {
//"GOPATH": "${env.HOME}/Dropbox/go"
}
},
"windows": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
},
"showLog": true
},
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/",
"osx": {
"env": {
//"GOPATH": "${env.HOME}/Dropbox/go"
}
},
"windows": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
},
"args": [],
"showLog": true
}
]
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch Test",
"type": "go",
"request": "launch",
"mode": "test",
"remotePath": "",
"port": 2345,
"program": "${workspaceRoot}/reader",
"args": [
"-test.v"
],
"osx": {
"env": {
//"GOPATH": "/Users/amitbet/Dropbox/go"
}
},
"windows": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
},
"showLog": true
},
{
"name": "Launch Grouper Tests",
"type": "go",
"request": "launch",
"mode": "test",
"remotePath": "",
"port": 2345,
"program": "${workspaceRoot}/consumer",
"args": [
"-test.v"
],
"osx": {
"env": {
//"GOPATH": "${env.HOME}/Dropbox/go"
}
},
"windows": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
},
"showLog": true
},
{
"name": "Launch",
"type": "go",
"request": "launch",
"mode": "debug",
"remotePath": "",
"port": 2345,
"host": "127.0.0.1",
"program": "${workspaceRoot}/",
"osx": {
"env": {
//"GOPATH": "${env.HOME}/Dropbox/go"
}
},
"windows": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
},
"args": [],
"showLog": true
}
]
}

90
.vscode/tasks.json vendored
View File

@ -1,46 +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
}
]
{
"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
}
]
}

42
LICENSE
View File

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2017 Amit Bezalel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
MIT License
Copyright (c) 2017 Amit Bezalel
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,7 +1,7 @@
# VncProxy
A RFB proxy, written in go that can save and replay RBS files
Still a work in progress, but the client side already includes all the required encodings
understanding the RemoteFrameBuffer protocol is important since we need to save the frameResponses with timestamps
some server code will be added shortly, with the proxying logics.
# VncProxy
A RFB proxy, written in go that can save and replay RBS files
Still a work in progress, but the client side already includes all the required encodings
understanding the RemoteFrameBuffer protocol is important since we need to save the frameResponses with timestamps
some server code will be added shortly, with the proxying logics.

View File

@ -1,14 +1,14 @@
package common
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{})
}
package common
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{})
}

View File

@ -1,9 +1,5 @@
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 {
@ -13,7 +9,7 @@ type Encoding interface {
// 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)
Read(*PixelFormat, *Rectangle, *RfbReadHelper) (Encoding, error)
}
const (

View File

@ -1,45 +1,85 @@
// 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
}
var TightMinToCompress = 12
func (r *RfbReader) Read(p []byte) (n int, err error) {
readLen, err := r.reader.Read(p)
r.savedBuff.Write(p)
return readLen, err
const (
SegmentBytes SegmentType = iota
SegmentMessageSeparator
SegmentRectSeparator
)
type SegmentType int
type RfbSegment struct {
Bytes []byte
SegmentType SegmentType
UpcomingObjectType int
}
func (r *RfbReader) SavedBuff() bytes.Buffer {
return r.savedBuff
type SegmentConsumer interface {
Consume(*RfbSegment) error
}
type RfbReadHelper struct {
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)
_, err := io.ReadFull(d.Reader, buff)
_, err := io.ReadFull(r, buff)
if err != nil {
//if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil {
return nil, err
@ -47,41 +87,41 @@ func (d *RfbReadHelper) ReadBytes(count int) ([]byte, error) {
return buff, nil
}
func (d *RfbReadHelper) ReadUint8() (uint8, error) {
func (r *RfbReadHelper) ReadUint8() (uint8, error) {
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
}
//fmt.Printf("myUint=%d", myUint)
return myUint, nil
}
func (d *RfbReadHelper) ReadUint16() (uint16, error) {
func (r *RfbReadHelper) ReadUint16() (uint16, error) {
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
}
//fmt.Printf("myUint=%d", myUint)
return myUint, nil
}
func (d *RfbReadHelper) ReadUint32() (uint32, error) {
func (r *RfbReadHelper) ReadUint32() (uint32, error) {
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
}
//fmt.Printf("myUint=%d", myUint)
return myUint, nil
}
func (d *RfbReadHelper) ReadCompactLen() (int, error) {
func (r *RfbReadHelper) ReadCompactLen() (int, error) {
var err error
part, err := d.ReadUint8()
part, err := r.ReadUint8()
//byteCount := 1
len := uint32(part & 0x7F)
if (part & 0x80) != 0 {
part, err = d.ReadUint8()
part, err = r.ReadUint8()
//byteCount++
len |= uint32(part&0x7F) << 7
if (part & 0x80) != 0 {
part, err = d.ReadUint8()
part, err = r.ReadUint8()
//byteCount++
len |= uint32(part&0xFF) << 14
}
@ -94,8 +134,6 @@ func (d *RfbReadHelper) ReadCompactLen() (int, error) {
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))

View File

@ -1,34 +1,34 @@
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
}
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
}

View File

@ -1,26 +1,20 @@
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
}
//////////
package encodings
import "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 *common.RfbReadHelper) (common.Encoding, error) {
z.copyRectSrcX, _ = r.ReadUint16()
z.copyRectSrcY, _ = r.ReadUint16()
return z, nil
}
//////////

View File

@ -1,7 +1,6 @@
package encodings
import (
"io"
"vncproxy/common"
)
@ -13,16 +12,15 @@ 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}
func (z *CoRREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
bytesPerPixel := int(pixelFmt.BPP / 8)
numOfSubrectangles, _ := conn.ReadUint32()
numOfSubrectangles, _ := r.ReadUint32()
//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)
_, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4))
_, err := r.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4))
if err != nil {
return nil, err

View File

@ -1,85 +1,80 @@
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
}
package encodings
import "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 *common.RfbReadHelper) (common.Encoding, error) {
bytesPerPixel := int(pixelFmt.BPP) / 8
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 := r.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)
r.ReadBytes(tw * th * bytesPerPixel)
//fmt.Printf("hextile reader: HextileRaw\n")
continue
}
if (subencoding & HextileBackgroundSpecified) != 0 {
r.ReadBytes(int(bytesPerPixel))
}
if (subencoding & HextileForegroundSpecified) != 0 {
r.ReadBytes(int(bytesPerPixel))
}
if (subencoding & HextileAnySubrects) == 0 {
//fmt.Printf("hextile reader: no Subrects\n")
continue
}
//fmt.Printf("hextile reader: handling Subrects\n")
nSubrects, err := r.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];
r.ReadBytes(bufsize)
}
}
// len, _ := readUint32(c.c)
// _, err := readBytes(c.c, int(len))
// if err != nil {
// return nil, err
// }
return z, nil
}

View File

@ -1,7 +1,6 @@
package encodings
import (
"io"
"vncproxy/common"
)
@ -16,9 +15,9 @@ func (*RawEncoding) Type() int32 {
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 := common.RfbReadHelper{r}
//conn := common.RfbReadHelper{Reader:r}
bytesPerPixel := int(pixelFmt.BPP / 8)
//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 x := uint16(0); x < rect.Width; x++ {
if _, err := conn.ReadBytes(bytesPerPixel); err != nil {
if _, err := r.ReadBytes(bytesPerPixel); err != nil {
return nil, err
}

View File

@ -1,28 +1,27 @@
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
}
package encodings
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 *common.RfbReadHelper) (common.Encoding, error) {
//conn := common.RfbReadHelper{Reader:r}
bytesPerPixel := int(pixelFmt.BPP / 8)
numOfSubrectangles, _ := r.ReadUint32()
//read whole rect background color
r.ReadBytes(bytesPerPixel)
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
_, err := r.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 8))
if err != nil {
return nil, err
}
return z, nil
}

View File

@ -1,334 +1,334 @@
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
}
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, r *common.RfbReadHelper) (common.Encoding, error) {
bytesPixel := calcTightBytePerPixel(pixelFmt)
//conn := common.RfbReadHelper{Reader:reader}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//var subencoding uint8
subencoding, err := r.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
r.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 := r.ReadCompactLen()
if err != nil {
return nil, err
}
fmt.Printf("reading jpeg size=%d\n", len)
r.ReadBytes(len)
return t, nil
default:
if compType > TightJpeg {
fmt.Println("Compression control byte is incorrect!")
}
handleTightFilters(subencoding, pixelFmt, rect, r)
return t, nil
}
}
func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) {
//conn := common.RfbReadHelper{Reader: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 = r.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 := r.ReadUint8()
paletteSize := colorCount + 1 // add one more
fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
//complete palette
r.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 = r.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)
r.ReadTightData(lengthCurrentbpp)
case TightFilterCopy: //BASIC_FILTER
fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel)
r.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
}

View File

@ -1,24 +1,23 @@
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
}
package encodings
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 *common.RfbReadHelper) (common.Encoding, error) {
//conn := common.RfbReadHelper{Reader:r}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//bytesPerPixel := c.PixelFormat.BPP / 8
len, _ := r.ReadUint32()
_, err := r.ReadBytes(int(len))
if err != nil {
return nil, err
}
return z, nil
}

View File

@ -1,24 +1,23 @@
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
}
package encodings
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 *common.RfbReadHelper) (common.Encoding, error) {
//conn := common.RfbReadHelper{Reader: r}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//bytesPerPixel := c.PixelFormat.BPP / 8
len, _ := r.ReadUint32()
_, err := r.ReadBytes(int(len))
if err != nil {
return nil, err
}
return z, nil
}

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")
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
authArr := []vnc.ClientAuth{&vnc.PasswordAuth{Password: "Ch_#!T@8"}, &noauth}

View File

@ -1,16 +1,16 @@
# VNC Library for Go
go-vnc is a VNC library for Go, initially supporting VNC clients but
with the goal of eventually implementing a VNC server.
This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143).
## Usage & Installation
The library is installable via standard `go get`. The package name is `vnc`.
```
$ go get github.com/mitchellh/go-vnc
```
Documentation is available on GoDoc: http://godoc.org/github.com/mitchellh/go-vnc
# VNC Library for Go
go-vnc is a VNC library for Go, initially supporting VNC clients but
with the goal of eventually implementing a VNC server.
This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143).
## Usage & Installation
The library is installable via standard `go get`. The package name is `vnc`.
```
$ go get github.com/mitchellh/go-vnc
```
Documentation is available on GoDoc: http://godoc.org/github.com/mitchellh/go-vnc

File diff suppressed because it is too large Load Diff

View File

@ -1,114 +1,114 @@
package vnc
import (
"net"
"crypto/des"
"encoding/binary"
)
// ClientAuthNone is the "none" authentication. See 7.2.1
type ClientAuthNone byte
func (*ClientAuthNone) SecurityType() uint8 {
return 1
}
func (*ClientAuthNone) Handshake(net.Conn) error {
return nil
}
// PasswordAuth is VNC authentication, 7.2.2
type PasswordAuth struct {
Password string
}
func (p *PasswordAuth) SecurityType() uint8 {
return 2
}
func (p *PasswordAuth) Handshake(c net.Conn) error {
randomValue := make([]uint8, 16)
if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil {
return err
}
crypted, err := p.encrypt(p.Password, randomValue)
if (err != nil) {
return err
}
if err := binary.Write(c, binary.BigEndian, &crypted); err != nil {
return err
}
return nil
}
func (p *PasswordAuth) reverseBits(b byte) byte {
var reverse = [256]int{
0, 128, 64, 192, 32, 160, 96, 224,
16, 144, 80, 208, 48, 176, 112, 240,
8, 136, 72, 200, 40, 168, 104, 232,
24, 152, 88, 216, 56, 184, 120, 248,
4, 132, 68, 196, 36, 164, 100, 228,
20, 148, 84, 212, 52, 180, 116, 244,
12, 140, 76, 204, 44, 172, 108, 236,
28, 156, 92, 220, 60, 188, 124, 252,
2, 130, 66, 194, 34, 162, 98, 226,
18, 146, 82, 210, 50, 178, 114, 242,
10, 138, 74, 202, 42, 170, 106, 234,
26, 154, 90, 218, 58, 186, 122, 250,
6, 134, 70, 198, 38, 166, 102, 230,
22, 150, 86, 214, 54, 182, 118, 246,
14, 142, 78, 206, 46, 174, 110, 238,
30, 158, 94, 222, 62, 190, 126, 254,
1, 129, 65, 193, 33, 161, 97, 225,
17, 145, 81, 209, 49, 177, 113, 241,
9, 137, 73, 201, 41, 169, 105, 233,
25, 153, 89, 217, 57, 185, 121, 249,
5, 133, 69, 197, 37, 165, 101, 229,
21, 149, 85, 213, 53, 181, 117, 245,
13, 141, 77, 205, 45, 173, 109, 237,
29, 157, 93, 221, 61, 189, 125, 253,
3, 131, 67, 195, 35, 163, 99, 227,
19, 147, 83, 211, 51, 179, 115, 243,
11, 139, 75, 203, 43, 171, 107, 235,
27, 155, 91, 219, 59, 187, 123, 251,
7, 135, 71, 199, 39, 167, 103, 231,
23, 151, 87, 215, 55, 183, 119, 247,
15, 143, 79, 207, 47, 175, 111, 239,
31, 159, 95, 223, 63, 191, 127, 255,
}
return byte(reverse[int(b)])
}
func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) {
keyBytes := []byte{0,0,0,0,0,0,0,0}
if len(key) > 8 {
key = key[:8]
}
for i := 0; i < len(key); i++ {
keyBytes[i] = p.reverseBits(key[i])
}
block, err := des.NewCipher(keyBytes)
if err != nil {
return nil, err
}
result1 := make([]byte, 8)
block.Encrypt(result1, bytes)
result2 := make([]byte, 8)
block.Encrypt(result2, bytes[8:])
crypted := append(result1, result2...)
return crypted, nil
}
package vnc
import (
"net"
"crypto/des"
"encoding/binary"
)
// ClientAuthNone is the "none" authentication. See 7.2.1
type ClientAuthNone byte
func (*ClientAuthNone) SecurityType() uint8 {
return 1
}
func (*ClientAuthNone) Handshake(net.Conn) error {
return nil
}
// PasswordAuth is VNC authentication, 7.2.2
type PasswordAuth struct {
Password string
}
func (p *PasswordAuth) SecurityType() uint8 {
return 2
}
func (p *PasswordAuth) Handshake(c net.Conn) error {
randomValue := make([]uint8, 16)
if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil {
return err
}
crypted, err := p.encrypt(p.Password, randomValue)
if (err != nil) {
return err
}
if err := binary.Write(c, binary.BigEndian, &crypted); err != nil {
return err
}
return nil
}
func (p *PasswordAuth) reverseBits(b byte) byte {
var reverse = [256]int{
0, 128, 64, 192, 32, 160, 96, 224,
16, 144, 80, 208, 48, 176, 112, 240,
8, 136, 72, 200, 40, 168, 104, 232,
24, 152, 88, 216, 56, 184, 120, 248,
4, 132, 68, 196, 36, 164, 100, 228,
20, 148, 84, 212, 52, 180, 116, 244,
12, 140, 76, 204, 44, 172, 108, 236,
28, 156, 92, 220, 60, 188, 124, 252,
2, 130, 66, 194, 34, 162, 98, 226,
18, 146, 82, 210, 50, 178, 114, 242,
10, 138, 74, 202, 42, 170, 106, 234,
26, 154, 90, 218, 58, 186, 122, 250,
6, 134, 70, 198, 38, 166, 102, 230,
22, 150, 86, 214, 54, 182, 118, 246,
14, 142, 78, 206, 46, 174, 110, 238,
30, 158, 94, 222, 62, 190, 126, 254,
1, 129, 65, 193, 33, 161, 97, 225,
17, 145, 81, 209, 49, 177, 113, 241,
9, 137, 73, 201, 41, 169, 105, 233,
25, 153, 89, 217, 57, 185, 121, 249,
5, 133, 69, 197, 37, 165, 101, 229,
21, 149, 85, 213, 53, 181, 117, 245,
13, 141, 77, 205, 45, 173, 109, 237,
29, 157, 93, 221, 61, 189, 125, 253,
3, 131, 67, 195, 35, 163, 99, 227,
19, 147, 83, 211, 51, 179, 115, 243,
11, 139, 75, 203, 43, 171, 107, 235,
27, 155, 91, 219, 59, 187, 123, 251,
7, 135, 71, 199, 39, 167, 103, 231,
23, 151, 87, 215, 55, 183, 119, 247,
15, 143, 79, 207, 47, 175, 111, 239,
31, 159, 95, 223, 63, 191, 127, 255,
}
return byte(reverse[int(b)])
}
func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) {
keyBytes := []byte{0,0,0,0,0,0,0,0}
if len(key) > 8 {
key = key[:8]
}
for i := 0; i < len(key); i++ {
keyBytes[i] = p.reverseBits(key[i])
}
block, err := des.NewCipher(keyBytes)
if err != nil {
return nil, err
}
result1 := make([]byte, 8)
block.Encrypt(result1, bytes)
result2 := make([]byte, 8)
block.Encrypt(result2, bytes[8:])
crypted := append(result1, result2...)
return crypted, nil
}

View File

@ -1,169 +1,169 @@
package vnc
import (
"testing"
"net"
"time"
"bytes"
)
type fakeNetConnection struct {
DataToSend []byte
Test *testing.T
ExpectData []byte
Finished bool
Matched bool
}
func (fc fakeNetConnection) Read(b []byte) (n int, err error) {
for i := 0; i < 16; i++ {
b[i] = fc.DataToSend[i]
}
fc.Finished = false
return len(b), nil
}
func (fc *fakeNetConnection) Write(b []byte) (n int, err error) {
fc.Matched = bytes.Equal(b, fc.ExpectData)
fc.Finished = true
return len(b), nil
}
func (fc *fakeNetConnection) Close() error { return nil; }
func (fc *fakeNetConnection) LocalAddr() net.Addr { return nil; }
func (fc *fakeNetConnection) RemoteAddr() net.Addr { return nil; }
func (fc *fakeNetConnection) SetDeadline(t time.Time) error { return nil; }
func (fc *fakeNetConnection) SetReadDeadline(t time.Time) error { return nil; }
func (fc *fakeNetConnection) SetWriteDeadline(t time.Time) error { return nil; }
func TestClientAuthNone_Impl(t *testing.T) {
var raw interface{}
raw = new(ClientAuthNone)
if _, ok := raw.(ClientAuth); !ok {
t.Fatal("ClientAuthNone doesn't implement ClientAuth")
}
}
func TestClientAuthPasswordSuccess_Impl(t *testing.T) {
// Values ripped using WireShark
randomValue := []byte{
0xa4,
0x51,
0x3f,
0xa5,
0x1f,
0x87,
0x06,
0x10,
0xa4,
0x5f,
0xae,
0xbf,
0x4d,
0xac,
0x12,
0x22,
}
expectedResponse := []byte{
0x71,
0xe4,
0x41,
0x30,
0x43,
0x65,
0x4e,
0x39,
0xda,
0x6d,
0x49,
0x93,
0x43,
0xf6,
0x5e,
0x29,
}
raw := PasswordAuth{Password: "Ch_#!T@8"}
// Only about 12 hours into Go at the moment...
// if _, ok := raw.(ClientAuth); !ok {
// t.Fatal("PasswordAuth doesn't implement ClientAuth")
// }
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
err := raw.Handshake(conn)
if (err != nil) {
t.Fatal(err)
}
if !conn.Matched {
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
}
if !conn.Finished {
t.Fatal("PasswordAuth didn't complete properly")
}
}
func TestClientAuthPasswordReject_Impl(t *testing.T) {
// Values ripped using WireShark
randomValue := []byte{
0xa4,
0x51,
0x3f,
0xa5,
0x1f,
0x87,
0x06,
0x10,
0xa4,
0x5f,
0xae,
0xbf,
0x4d,
0xac,
0x12,
0x22,
}
expectedResponse := []byte{
0x71,
0xe4,
0x41,
0x30,
0x43,
0x65,
0x4e,
0x39,
0xda,
0x6d,
0x49,
0x93,
0x43,
0xf6,
0x5e,
0x29,
}
raw := PasswordAuth{Password: "Ch_#!T@"}
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
err := raw.Handshake(conn)
if (err != nil) {
t.Fatal(err)
}
if conn.Matched {
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
}
if !conn.Finished {
t.Fatal("PasswordAuth didn't complete properly")
}
package vnc
import (
"testing"
"net"
"time"
"bytes"
)
type fakeNetConnection struct {
DataToSend []byte
Test *testing.T
ExpectData []byte
Finished bool
Matched bool
}
func (fc fakeNetConnection) Read(b []byte) (n int, err error) {
for i := 0; i < 16; i++ {
b[i] = fc.DataToSend[i]
}
fc.Finished = false
return len(b), nil
}
func (fc *fakeNetConnection) Write(b []byte) (n int, err error) {
fc.Matched = bytes.Equal(b, fc.ExpectData)
fc.Finished = true
return len(b), nil
}
func (fc *fakeNetConnection) Close() error { return nil; }
func (fc *fakeNetConnection) LocalAddr() net.Addr { return nil; }
func (fc *fakeNetConnection) RemoteAddr() net.Addr { return nil; }
func (fc *fakeNetConnection) SetDeadline(t time.Time) error { return nil; }
func (fc *fakeNetConnection) SetReadDeadline(t time.Time) error { return nil; }
func (fc *fakeNetConnection) SetWriteDeadline(t time.Time) error { return nil; }
func TestClientAuthNone_Impl(t *testing.T) {
var raw interface{}
raw = new(ClientAuthNone)
if _, ok := raw.(ClientAuth); !ok {
t.Fatal("ClientAuthNone doesn't implement ClientAuth")
}
}
func TestClientAuthPasswordSuccess_Impl(t *testing.T) {
// Values ripped using WireShark
randomValue := []byte{
0xa4,
0x51,
0x3f,
0xa5,
0x1f,
0x87,
0x06,
0x10,
0xa4,
0x5f,
0xae,
0xbf,
0x4d,
0xac,
0x12,
0x22,
}
expectedResponse := []byte{
0x71,
0xe4,
0x41,
0x30,
0x43,
0x65,
0x4e,
0x39,
0xda,
0x6d,
0x49,
0x93,
0x43,
0xf6,
0x5e,
0x29,
}
raw := PasswordAuth{Password: "Ch_#!T@8"}
// Only about 12 hours into Go at the moment...
// if _, ok := raw.(ClientAuth); !ok {
// t.Fatal("PasswordAuth doesn't implement ClientAuth")
// }
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
err := raw.Handshake(conn)
if (err != nil) {
t.Fatal(err)
}
if !conn.Matched {
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
}
if !conn.Finished {
t.Fatal("PasswordAuth didn't complete properly")
}
}
func TestClientAuthPasswordReject_Impl(t *testing.T) {
// Values ripped using WireShark
randomValue := []byte{
0xa4,
0x51,
0x3f,
0xa5,
0x1f,
0x87,
0x06,
0x10,
0xa4,
0x5f,
0xae,
0xbf,
0x4d,
0xac,
0x12,
0x22,
}
expectedResponse := []byte{
0x71,
0xe4,
0x41,
0x30,
0x43,
0x65,
0x4e,
0x39,
0xda,
0x6d,
0x49,
0x93,
0x43,
0xf6,
0x5e,
0x29,
}
raw := PasswordAuth{Password: "Ch_#!T@"}
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
err := raw.Handshake(conn)
if (err != nil) {
t.Fatal(err)
}
if conn.Matched {
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
}
if !conn.Finished {
t.Fatal("PasswordAuth didn't complete properly")
}
}

View File

@ -1,95 +1,95 @@
package vnc
import (
"fmt"
"net"
"testing"
)
func newMockServer(t *testing.T, version string) string {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("error listening: %s", err)
}
go func() {
defer ln.Close()
c, err := ln.Accept()
if err != nil {
t.Fatalf("error accepting conn: %s", err)
}
defer c.Close()
_, err = c.Write([]byte(fmt.Sprintf("RFB %s\n", version)))
if err != nil {
t.Fatal("failed writing version")
}
}()
return ln.Addr().String()
}
func TestClient_LowMajorVersion(t *testing.T) {
nc, err := net.Dial("tcp", newMockServer(t, "002.009"))
if err != nil {
t.Fatalf("error connecting to mock server: %s", err)
}
_, err = Client(nc, &ClientConfig{})
if err == nil {
t.Fatal("error expected")
}
if err.Error() != "unsupported major version, less than 3: 2" {
t.Fatalf("unexpected error: %s", err)
}
}
func TestClient_LowMinorVersion(t *testing.T) {
nc, err := net.Dial("tcp", newMockServer(t, "003.007"))
if err != nil {
t.Fatalf("error connecting to mock server: %s", err)
}
_, err = Client(nc, &ClientConfig{})
if err == nil {
t.Fatal("error expected")
}
if err.Error() != "unsupported minor version, less than 8: 7" {
t.Fatalf("unexpected error: %s", err)
}
}
func TestParseProtocolVersion(t *testing.T) {
tests := []struct {
proto []byte
major, minor uint
isErr bool
}{
// Valid ProtocolVersion messages.
{[]byte{82, 70, 66, 32, 48, 48, 51, 46, 48, 48, 56, 10}, 3, 8, false}, // RFB 003.008\n
{[]byte{82, 70, 66, 32, 48, 48, 51, 46, 56, 56, 57, 10}, 3, 889, false}, // RFB 003.889\n -- OS X 10.10.3
{[]byte{82, 70, 66, 32, 48, 48, 48, 46, 48, 48, 48, 10}, 0, 0, false}, // RFB 000.0000\n
// Invalid messages.
{[]byte{82, 70, 66, 32, 51, 46, 56, 10}, 0, 0, true}, // RFB 3.8\n -- too short; not zero padded
{[]byte{82, 70, 66, 10}, 0, 0, true}, // RFB\n -- too short
{[]byte{}, 0, 0, true}, // (empty) -- too short
}
for _, tt := range tests {
major, minor, err := parseProtocolVersion(tt.proto)
if err != nil && !tt.isErr {
t.Fatalf("parseProtocolVersion(%v) unexpected error %v", tt.proto, err)
}
if err == nil && tt.isErr {
t.Fatalf("parseProtocolVersion(%v) expected error", tt.proto)
}
if major != tt.major {
t.Errorf("parseProtocolVersion(%v) major = %v, want %v", tt.proto, major, tt.major)
}
if major != tt.major {
t.Errorf("parseProtocolVersion(%v) minor = %v, want %v", tt.proto, minor, tt.minor)
}
}
}
package vnc
import (
"fmt"
"net"
"testing"
)
func newMockServer(t *testing.T, version string) string {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatalf("error listening: %s", err)
}
go func() {
defer ln.Close()
c, err := ln.Accept()
if err != nil {
t.Fatalf("error accepting conn: %s", err)
}
defer c.Close()
_, err = c.Write([]byte(fmt.Sprintf("RFB %s\n", version)))
if err != nil {
t.Fatal("failed writing version")
}
}()
return ln.Addr().String()
}
func TestClient_LowMajorVersion(t *testing.T) {
nc, err := net.Dial("tcp", newMockServer(t, "002.009"))
if err != nil {
t.Fatalf("error connecting to mock server: %s", err)
}
_, err = Client(nc, &ClientConfig{})
if err == nil {
t.Fatal("error expected")
}
if err.Error() != "unsupported major version, less than 3: 2" {
t.Fatalf("unexpected error: %s", err)
}
}
func TestClient_LowMinorVersion(t *testing.T) {
nc, err := net.Dial("tcp", newMockServer(t, "003.007"))
if err != nil {
t.Fatalf("error connecting to mock server: %s", err)
}
_, err = Client(nc, &ClientConfig{})
if err == nil {
t.Fatal("error expected")
}
if err.Error() != "unsupported minor version, less than 8: 7" {
t.Fatalf("unexpected error: %s", err)
}
}
func TestParseProtocolVersion(t *testing.T) {
tests := []struct {
proto []byte
major, minor uint
isErr bool
}{
// Valid ProtocolVersion messages.
{[]byte{82, 70, 66, 32, 48, 48, 51, 46, 48, 48, 56, 10}, 3, 8, false}, // RFB 003.008\n
{[]byte{82, 70, 66, 32, 48, 48, 51, 46, 56, 56, 57, 10}, 3, 889, false}, // RFB 003.889\n -- OS X 10.10.3
{[]byte{82, 70, 66, 32, 48, 48, 48, 46, 48, 48, 48, 10}, 0, 0, false}, // RFB 000.0000\n
// Invalid messages.
{[]byte{82, 70, 66, 32, 51, 46, 56, 10}, 0, 0, true}, // RFB 3.8\n -- too short; not zero padded
{[]byte{82, 70, 66, 10}, 0, 0, true}, // RFB\n -- too short
{[]byte{}, 0, 0, true}, // (empty) -- too short
}
for _, tt := range tests {
major, minor, err := parseProtocolVersion(tt.proto)
if err != nil && !tt.isErr {
t.Fatalf("parseProtocolVersion(%v) unexpected error %v", tt.proto, err)
}
if err == nil && tt.isErr {
t.Fatalf("parseProtocolVersion(%v) expected error", tt.proto)
}
if major != tt.major {
t.Errorf("parseProtocolVersion(%v) major = %v, want %v", tt.proto, major, tt.major)
}
if major != tt.major {
t.Errorf("parseProtocolVersion(%v) minor = %v, want %v", tt.proto, minor, tt.minor)
}
}
}

View File

@ -1,6 +1,6 @@
package vnc
// Color represents a single color in a color map.
type Color struct {
R, G, B uint16
}
package vnc
// Color represents a single color in a color map.
type Color struct {
R, G, B uint16
}

View File

@ -1,136 +1,136 @@
package vnc
import (
"bytes"
"encoding/binary"
"io"
"vncproxy/common"
)
func readPixelFormat(r io.Reader, result *common.PixelFormat) error {
var rawPixelFormat [16]byte
if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil {
return err
}
var pfBoolByte uint8
brPF := bytes.NewReader(rawPixelFormat[:])
if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
return err
}
if pfBoolByte != 0 {
// Big endian is true
result.BigEndian = true
}
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
return err
}
if pfBoolByte != 0 {
// True Color is true. So we also have to read all the color max & shifts.
result.TrueColor = true
if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil {
return err
}
}
return nil
}
func writePixelFormat(format *common.PixelFormat) ([]byte, error) {
var buf bytes.Buffer
// Byte 1
if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil {
return nil, err
}
// Byte 2
if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil {
return nil, err
}
var boolByte byte
if format.BigEndian {
boolByte = 1
} else {
boolByte = 0
}
// Byte 3 (BigEndian)
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
return nil, err
}
if format.TrueColor {
boolByte = 1
} else {
boolByte = 0
}
// Byte 4 (TrueColor)
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
return nil, err
}
// If we have true color enabled then we have to fill in the rest of the
// structure with the color values.
if format.TrueColor {
if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil {
return nil, err
}
}
return buf.Bytes()[0:16], nil
}
package vnc
import (
"bytes"
"encoding/binary"
"io"
"vncproxy/common"
)
func readPixelFormat(r io.Reader, result *common.PixelFormat) error {
var rawPixelFormat [16]byte
if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil {
return err
}
var pfBoolByte uint8
brPF := bytes.NewReader(rawPixelFormat[:])
if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
return err
}
if pfBoolByte != 0 {
// Big endian is true
result.BigEndian = true
}
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
return err
}
if pfBoolByte != 0 {
// True Color is true. So we also have to read all the color max & shifts.
result.TrueColor = true
if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil {
return err
}
if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil {
return err
}
}
return nil
}
func writePixelFormat(format *common.PixelFormat) ([]byte, error) {
var buf bytes.Buffer
// Byte 1
if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil {
return nil, err
}
// Byte 2
if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil {
return nil, err
}
var boolByte byte
if format.BigEndian {
boolByte = 1
} else {
boolByte = 0
}
// Byte 3 (BigEndian)
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
return nil, err
}
if format.TrueColor {
boolByte = 1
} else {
boolByte = 0
}
// Byte 4 (TrueColor)
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
return nil, err
}
// If we have true color enabled then we have to fill in the rest of the
// structure with the color values.
if format.TrueColor {
if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil {
return nil, err
}
if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil {
return nil, err
}
}
return buf.Bytes()[0:16], nil
}

View File

@ -1,16 +1,16 @@
package vnc
// ButtonMask represents a mask of pointer presses/releases.
type ButtonMask uint8
// All available button mask components.
const (
ButtonLeft ButtonMask = 1 << iota
ButtonMiddle
ButtonRight
Button4
Button5
Button6
Button7
Button8
)
package vnc
// ButtonMask represents a mask of pointer presses/releases.
type ButtonMask uint8
// All available button mask components.
const (
ButtonLeft ButtonMask = 1 << iota
ButtonMiddle
ButtonRight
Button4
Button5
Button6
Button7
Button8
)

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