mirror of
https://github.com/amitbet/vncproxy.git
synced 2025-04-27 10:50:47 +00:00
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:
parent
a74fe9e60c
commit
007e748c61
4
.gitignore
vendored
4
.gitignore
vendored
@ -1,2 +1,2 @@
|
||||
*.bin
|
||||
debug
|
||||
*.bin
|
||||
debug
|
||||
|
@ -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>
|
@ -1,3 +1,3 @@
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
<component name="CopyrightManager">
|
||||
<settings default="" />
|
||||
</component>
|
@ -1,42 +1,42 @@
|
||||
<component name="libraryTable">
|
||||
<library name="GOPATH <vncproxy>">
|
||||
<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 <vncproxy>">
|
||||
<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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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 <vncproxy>" 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 <vncproxy>" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
3053
.idea/workspace.xml
3053
.idea/workspace.xml
File diff suppressed because it is too large
Load Diff
144
.vscode/launch.json
vendored
144
.vscode/launch.json
vendored
@ -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
90
.vscode/tasks.json
vendored
@ -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
42
LICENSE
@ -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.
|
||||
|
14
README.md
14
README.md
@ -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.
|
||||
|
@ -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{})
|
||||
}
|
||||
|
@ -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 (
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
//////////
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
22
listeners/multiListener.go
Normal file
22
listeners/multiListener.go
Normal 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
12
listeners/pass-to.go
Normal 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
155
listeners/recorder.go
Normal 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()
|
||||
}
|
2
main.go
2
main.go
@ -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}
|
||||
|
@ -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
|
||||
|
1011
vnc/client-conn.go
1011
vnc/client-conn.go
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
12
vnc/color.go
12
vnc/color.go
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
)
|
||||
|
@ -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()
|
||||
}
|
@ -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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user