mirror of
https://github.com/amitbet/vncproxy.git
synced 2025-06-27 06:37:10 +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
|
*.bin
|
||||||
debug
|
debug
|
||||||
|
@ -1,22 +1,22 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<resourceExtensions />
|
<resourceExtensions />
|
||||||
<wildcardResourcePatterns>
|
<wildcardResourcePatterns>
|
||||||
<entry name="!?*.java" />
|
<entry name="!?*.java" />
|
||||||
<entry name="!?*.form" />
|
<entry name="!?*.form" />
|
||||||
<entry name="!?*.class" />
|
<entry name="!?*.class" />
|
||||||
<entry name="!?*.groovy" />
|
<entry name="!?*.groovy" />
|
||||||
<entry name="!?*.scala" />
|
<entry name="!?*.scala" />
|
||||||
<entry name="!?*.flex" />
|
<entry name="!?*.flex" />
|
||||||
<entry name="!?*.kt" />
|
<entry name="!?*.kt" />
|
||||||
<entry name="!?*.clj" />
|
<entry name="!?*.clj" />
|
||||||
<entry name="!?*.aj" />
|
<entry name="!?*.aj" />
|
||||||
</wildcardResourcePatterns>
|
</wildcardResourcePatterns>
|
||||||
<annotationProcessing>
|
<annotationProcessing>
|
||||||
<profile default="true" name="Default" enabled="false">
|
<profile default="true" name="Default" enabled="false">
|
||||||
<processorPath useClasspath="true" />
|
<processorPath useClasspath="true" />
|
||||||
</profile>
|
</profile>
|
||||||
</annotationProcessing>
|
</annotationProcessing>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,3 +1,3 @@
|
|||||||
<component name="CopyrightManager">
|
<component name="CopyrightManager">
|
||||||
<settings default="" />
|
<settings default="" />
|
||||||
</component>
|
</component>
|
@ -1,42 +1,42 @@
|
|||||||
<component name="libraryTable">
|
<component name="libraryTable">
|
||||||
<library name="GOPATH <vncproxy>">
|
<library name="GOPATH <vncproxy>">
|
||||||
<CLASSES>
|
<CLASSES>
|
||||||
<root url="file://$PROJECT_DIR$/../elastictrail" />
|
<root url="file://$PROJECT_DIR$/../elastictrail" />
|
||||||
<root url="file://$PROJECT_DIR$/../gopkg.in" />
|
<root url="file://$PROJECT_DIR$/../gopkg.in" />
|
||||||
<root url="file://$PROJECT_DIR$/../vncproxy1" />
|
<root url="file://$PROJECT_DIR$/../vncproxy1" />
|
||||||
<root url="file://$PROJECT_DIR$/../GoProjExample" />
|
<root url="file://$PROJECT_DIR$/../GoProjExample" />
|
||||||
<root url="file://$PROJECT_DIR$/../srf.opb" />
|
<root url="file://$PROJECT_DIR$/../srf.opb" />
|
||||||
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
|
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
|
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
|
||||||
<root url="file://$PROJECT_DIR$/../github.com" />
|
<root url="file://$PROJECT_DIR$/../github.com" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
|
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
|
||||||
<root url="file://$PROJECT_DIR$/../golang.org" />
|
<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/golang.org" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/srf" />
|
<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://$USER_HOME$/srf/experience.center.opb/src/version" />
|
||||||
<root url="file://$PROJECT_DIR$/../srf.storage" />
|
<root url="file://$PROJECT_DIR$/../srf.storage" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
|
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
|
||||||
</CLASSES>
|
</CLASSES>
|
||||||
<JAVADOC />
|
<JAVADOC />
|
||||||
<SOURCES>
|
<SOURCES>
|
||||||
<root url="file://$PROJECT_DIR$/../elastictrail" />
|
<root url="file://$PROJECT_DIR$/../elastictrail" />
|
||||||
<root url="file://$PROJECT_DIR$/../gopkg.in" />
|
<root url="file://$PROJECT_DIR$/../gopkg.in" />
|
||||||
<root url="file://$PROJECT_DIR$/../vncproxy1" />
|
<root url="file://$PROJECT_DIR$/../vncproxy1" />
|
||||||
<root url="file://$PROJECT_DIR$/../GoProjExample" />
|
<root url="file://$PROJECT_DIR$/../GoProjExample" />
|
||||||
<root url="file://$PROJECT_DIR$/../srf.opb" />
|
<root url="file://$PROJECT_DIR$/../srf.opb" />
|
||||||
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
|
<root url="file://$PROJECT_DIR$/../sourcegraph.com" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
|
<root url="file://$USER_HOME$/srf/experience.center.opb/src/github.com" />
|
||||||
<root url="file://$PROJECT_DIR$/../github.com" />
|
<root url="file://$PROJECT_DIR$/../github.com" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
|
<root url="file://$USER_HOME$/srf/experience.center.opb/src/gopkg.in" />
|
||||||
<root url="file://$PROJECT_DIR$/../golang.org" />
|
<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/golang.org" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/srf" />
|
<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://$USER_HOME$/srf/experience.center.opb/src/version" />
|
||||||
<root url="file://$PROJECT_DIR$/../srf.storage" />
|
<root url="file://$PROJECT_DIR$/../srf.storage" />
|
||||||
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
|
<root url="file://$USER_HOME$/srf/experience.center.opb/src/sourcegraph.com" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<excluded>
|
<excluded>
|
||||||
<root url="file://$PROJECT_DIR$" />
|
<root url="file://$PROJECT_DIR$" />
|
||||||
</excluded>
|
</excluded>
|
||||||
</library>
|
</library>
|
||||||
</component>
|
</component>
|
@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="GOROOT" path="/usr/local/Cellar/go/1.8.3/libexec" />
|
<component name="GOROOT" path="/usr/local/Cellar/go/1.8.3/libexec" />
|
||||||
</project>
|
</project>
|
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="ProjectModuleManager">
|
<component name="ProjectModuleManager">
|
||||||
<modules>
|
<modules>
|
||||||
<module fileurl="file://$PROJECT_DIR$/.idea/vncproxy.iml" filepath="$PROJECT_DIR$/.idea/vncproxy.iml" />
|
<module fileurl="file://$PROJECT_DIR$/.idea/vncproxy.iml" filepath="$PROJECT_DIR$/.idea/vncproxy.iml" />
|
||||||
</modules>
|
</modules>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
@ -1,10 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<module type="WEB_MODULE" version="4">
|
<module type="WEB_MODULE" version="4">
|
||||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||||
<exclude-output />
|
<exclude-output />
|
||||||
<content url="file://$MODULE_DIR$" />
|
<content url="file://$MODULE_DIR$" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
<orderEntry type="library" name="GOPATH <vncproxy>" level="project" />
|
<orderEntry type="library" name="GOPATH <vncproxy>" level="project" />
|
||||||
</component>
|
</component>
|
||||||
</module>
|
</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",
|
"version": "0.2.0",
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "Launch Test",
|
"name": "Launch Test",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "test",
|
"mode": "test",
|
||||||
"remotePath": "",
|
"remotePath": "",
|
||||||
"port": 2345,
|
"port": 2345,
|
||||||
"program": "${workspaceRoot}/reader",
|
"program": "${workspaceRoot}/reader",
|
||||||
"args": [
|
"args": [
|
||||||
"-test.v"
|
"-test.v"
|
||||||
],
|
],
|
||||||
"osx": {
|
"osx": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "/Users/amitbet/Dropbox/go"
|
//"GOPATH": "/Users/amitbet/Dropbox/go"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"windows": {
|
"windows": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"showLog": true
|
"showLog": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Launch Grouper Tests",
|
"name": "Launch Grouper Tests",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "test",
|
"mode": "test",
|
||||||
"remotePath": "",
|
"remotePath": "",
|
||||||
"port": 2345,
|
"port": 2345,
|
||||||
"program": "${workspaceRoot}/consumer",
|
"program": "${workspaceRoot}/consumer",
|
||||||
"args": [
|
"args": [
|
||||||
"-test.v"
|
"-test.v"
|
||||||
],
|
],
|
||||||
"osx": {
|
"osx": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.HOME}/Dropbox/go"
|
//"GOPATH": "${env.HOME}/Dropbox/go"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"windows": {
|
"windows": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"showLog": true
|
"showLog": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Launch",
|
"name": "Launch",
|
||||||
"type": "go",
|
"type": "go",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"mode": "debug",
|
"mode": "debug",
|
||||||
"remotePath": "",
|
"remotePath": "",
|
||||||
"port": 2345,
|
"port": 2345,
|
||||||
"host": "127.0.0.1",
|
"host": "127.0.0.1",
|
||||||
"program": "${workspaceRoot}/",
|
"program": "${workspaceRoot}/",
|
||||||
"osx": {
|
"osx": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.HOME}/Dropbox/go"
|
//"GOPATH": "${env.HOME}/Dropbox/go"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"windows": {
|
"windows": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"args": [],
|
"args": [],
|
||||||
"showLog": true
|
"showLog": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
90
.vscode/tasks.json
vendored
90
.vscode/tasks.json
vendored
@ -1,46 +1,46 @@
|
|||||||
{
|
{
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"command": "go",
|
"command": "go",
|
||||||
"isShellCommand": true,
|
"isShellCommand": true,
|
||||||
"echoCommand": true,
|
"echoCommand": true,
|
||||||
"showOutput": "always",
|
"showOutput": "always",
|
||||||
// "showOutput": "silent",
|
// "showOutput": "silent",
|
||||||
"options": {
|
"options": {
|
||||||
// "env": {
|
// "env": {
|
||||||
// "GOPATH": "/Users/lukeh/dd/go"
|
// "GOPATH": "/Users/lukeh/dd/go"
|
||||||
// }
|
// }
|
||||||
},
|
},
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"taskName": "install",
|
"taskName": "install",
|
||||||
"args": [
|
"args": [
|
||||||
"-v",
|
"-v",
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
"osx": {
|
"osx": {
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.HOME}/Dropbox/go"
|
//"GOPATH": "${env.HOME}/Dropbox/go"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"windows": {
|
"windows": {
|
||||||
"options": {
|
"options": {
|
||||||
"env": {
|
"env": {
|
||||||
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"isBuildCommand": true,
|
"isBuildCommand": true,
|
||||||
"problemMatcher": "$go"
|
"problemMatcher": "$go"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"taskName": "test",
|
"taskName": "test",
|
||||||
"args": [
|
"args": [
|
||||||
"-v",
|
"-v",
|
||||||
"./..."
|
"./..."
|
||||||
],
|
],
|
||||||
"isTestCommand": true
|
"isTestCommand": true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
42
LICENSE
42
LICENSE
@ -1,21 +1,21 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 Amit Bezalel
|
Copyright (c) 2017 Amit Bezalel
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
in the Software without restriction, including without limitation the rights
|
in the Software without restriction, including without limitation the rights
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
The above copyright notice and this permission notice shall be included in all
|
||||||
copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
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
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
|
14
README.md
14
README.md
@ -1,7 +1,7 @@
|
|||||||
# VncProxy
|
# VncProxy
|
||||||
A RFB proxy, written in go that can save and replay RBS files
|
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
|
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
|
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.
|
some server code will be added shortly, with the proxying logics.
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
Debug(v ...interface{})
|
Debug(v ...interface{})
|
||||||
Debugf(format string, v ...interface{})
|
Debugf(format string, v ...interface{})
|
||||||
Info(v ...interface{})
|
Info(v ...interface{})
|
||||||
Infof(format string, v ...interface{})
|
Infof(format string, v ...interface{})
|
||||||
Warn(v ...interface{})
|
Warn(v ...interface{})
|
||||||
Warnf(format string, v ...interface{})
|
Warnf(format string, v ...interface{})
|
||||||
Error(v ...interface{})
|
Error(v ...interface{})
|
||||||
Errorf(format string, v ...interface{})
|
Errorf(format string, v ...interface{})
|
||||||
Fatal(v ...interface{})
|
Fatal(v ...interface{})
|
||||||
Fatalf(format string, v ...interface{})
|
Fatalf(format string, v ...interface{})
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,5 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// An Encoding implements a method for encoding pixel data that is
|
// An Encoding implements a method for encoding pixel data that is
|
||||||
// sent by the server to the client.
|
// sent by the server to the client.
|
||||||
type Encoding interface {
|
type Encoding interface {
|
||||||
@ -13,7 +9,7 @@ type Encoding interface {
|
|||||||
// Read reads the contents of the encoded pixel data from the reader.
|
// Read reads the contents of the encoded pixel data from the reader.
|
||||||
// This should return a new Encoding implementation that contains
|
// This should return a new Encoding implementation that contains
|
||||||
// the proper data.
|
// the proper data.
|
||||||
Read(*PixelFormat, *Rectangle, io.Reader) (Encoding, error)
|
Read(*PixelFormat, *Rectangle, *RfbReadHelper) (Encoding, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -1,45 +1,85 @@
|
|||||||
// Package vnc implements a VNC client.
|
|
||||||
//
|
|
||||||
// References:
|
|
||||||
// [PROTOCOL]: http://tools.ietf.org/html/rfc6143
|
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type DataSource struct {
|
var TightMinToCompress = 12
|
||||||
// conn io.Reader
|
|
||||||
// output io.Writer
|
|
||||||
// passThrough bool
|
|
||||||
// PixelFormat PixelFormat
|
|
||||||
// }Color
|
|
||||||
type RfbReader struct {
|
|
||||||
reader io.Reader
|
|
||||||
saveBytes bool
|
|
||||||
savedBuff bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RfbReader) Read(p []byte) (n int, err error) {
|
const (
|
||||||
readLen, err := r.reader.Read(p)
|
SegmentBytes SegmentType = iota
|
||||||
r.savedBuff.Write(p)
|
SegmentMessageSeparator
|
||||||
return readLen, err
|
SegmentRectSeparator
|
||||||
|
)
|
||||||
|
|
||||||
|
type SegmentType int
|
||||||
|
|
||||||
|
type RfbSegment struct {
|
||||||
|
Bytes []byte
|
||||||
|
SegmentType SegmentType
|
||||||
|
UpcomingObjectType int
|
||||||
}
|
}
|
||||||
func (r *RfbReader) SavedBuff() bytes.Buffer {
|
type SegmentConsumer interface {
|
||||||
return r.savedBuff
|
Consume(*RfbSegment) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type RfbReadHelper struct {
|
type RfbReadHelper struct {
|
||||||
io.Reader
|
io.Reader
|
||||||
|
Listener SegmentConsumer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RfbReadHelper) ReadBytes(count int) ([]byte, error) {
|
func (r *RfbReadHelper) ReadDiscrete(p []byte) (int, error) {
|
||||||
|
return r.Read(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RfbReadHelper) SendRectSeparator(upcomingRectType int) error {
|
||||||
|
seg := &RfbSegment{SegmentType: SegmentRectSeparator, UpcomingObjectType: upcomingRectType}
|
||||||
|
if r.Listener != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return r.Listener.Consume(seg)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RfbReadHelper) SendMessageSeparator(upcomingMessageType int) error {
|
||||||
|
seg := &RfbSegment{SegmentType: SegmentMessageSeparator, UpcomingObjectType: upcomingMessageType}
|
||||||
|
if r.Listener == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return r.Listener.Consume(seg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RfbReadHelper) PublishBytes(p []byte) error {
|
||||||
|
seg := &RfbSegment{Bytes: p, SegmentType: SegmentBytes}
|
||||||
|
if r.Listener == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return r.Listener.Consume(seg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RfbReadHelper) Read(p []byte) (n int, err error) {
|
||||||
|
readLen, err := r.Reader.Read(p)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
//write the bytes to the Listener for further processing
|
||||||
|
seg := &RfbSegment{Bytes: p, SegmentType: SegmentBytes}
|
||||||
|
if r.Listener == nil {
|
||||||
|
return 0,nil
|
||||||
|
}
|
||||||
|
r.Listener.Consume(seg)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return readLen, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *RfbReadHelper) ReadBytes(count int) ([]byte, error) {
|
||||||
buff := make([]byte, count)
|
buff := make([]byte, count)
|
||||||
|
|
||||||
_, err := io.ReadFull(d.Reader, buff)
|
_, err := io.ReadFull(r, buff)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil {
|
//if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -47,41 +87,41 @@ func (d *RfbReadHelper) ReadBytes(count int) ([]byte, error) {
|
|||||||
return buff, nil
|
return buff, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RfbReadHelper) ReadUint8() (uint8, error) {
|
func (r *RfbReadHelper) ReadUint8() (uint8, error) {
|
||||||
var myUint uint8
|
var myUint uint8
|
||||||
if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil {
|
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
//fmt.Printf("myUint=%d", myUint)
|
//fmt.Printf("myUint=%d", myUint)
|
||||||
return myUint, nil
|
return myUint, nil
|
||||||
}
|
}
|
||||||
func (d *RfbReadHelper) ReadUint16() (uint16, error) {
|
func (r *RfbReadHelper) ReadUint16() (uint16, error) {
|
||||||
var myUint uint16
|
var myUint uint16
|
||||||
if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil {
|
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
//fmt.Printf("myUint=%d", myUint)
|
//fmt.Printf("myUint=%d", myUint)
|
||||||
return myUint, nil
|
return myUint, nil
|
||||||
}
|
}
|
||||||
func (d *RfbReadHelper) ReadUint32() (uint32, error) {
|
func (r *RfbReadHelper) ReadUint32() (uint32, error) {
|
||||||
var myUint uint32
|
var myUint uint32
|
||||||
if err := binary.Read(d.Reader, binary.BigEndian, &myUint); err != nil {
|
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
//fmt.Printf("myUint=%d", myUint)
|
//fmt.Printf("myUint=%d", myUint)
|
||||||
return myUint, nil
|
return myUint, nil
|
||||||
}
|
}
|
||||||
func (d *RfbReadHelper) ReadCompactLen() (int, error) {
|
func (r *RfbReadHelper) ReadCompactLen() (int, error) {
|
||||||
var err error
|
var err error
|
||||||
part, err := d.ReadUint8()
|
part, err := r.ReadUint8()
|
||||||
//byteCount := 1
|
//byteCount := 1
|
||||||
len := uint32(part & 0x7F)
|
len := uint32(part & 0x7F)
|
||||||
if (part & 0x80) != 0 {
|
if (part & 0x80) != 0 {
|
||||||
part, err = d.ReadUint8()
|
part, err = r.ReadUint8()
|
||||||
//byteCount++
|
//byteCount++
|
||||||
len |= uint32(part&0x7F) << 7
|
len |= uint32(part&0x7F) << 7
|
||||||
if (part & 0x80) != 0 {
|
if (part & 0x80) != 0 {
|
||||||
part, err = d.ReadUint8()
|
part, err = r.ReadUint8()
|
||||||
//byteCount++
|
//byteCount++
|
||||||
len |= uint32(part&0xFF) << 14
|
len |= uint32(part&0xFF) << 14
|
||||||
}
|
}
|
||||||
@ -94,8 +134,6 @@ func (d *RfbReadHelper) ReadCompactLen() (int, error) {
|
|||||||
return int(len), err
|
return int(len), err
|
||||||
}
|
}
|
||||||
|
|
||||||
var TightMinToCompress int = 12
|
|
||||||
|
|
||||||
func (r *RfbReadHelper) ReadTightData(dataSize int) ([]byte, error) {
|
func (r *RfbReadHelper) ReadTightData(dataSize int) ([]byte, error) {
|
||||||
if int(dataSize) < TightMinToCompress {
|
if int(dataSize) < TightMinToCompress {
|
||||||
return r.ReadBytes(int(dataSize))
|
return r.ReadBytes(int(dataSize))
|
||||||
|
@ -1,34 +1,34 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Rectangle represents a rectangle of pixel data.
|
// Rectangle represents a rectangle of pixel data.
|
||||||
type Rectangle struct {
|
type Rectangle struct {
|
||||||
X uint16
|
X uint16
|
||||||
Y uint16
|
Y uint16
|
||||||
Width uint16
|
Width uint16
|
||||||
Height uint16
|
Height uint16
|
||||||
Enc Encoding
|
Enc Encoding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Rectangle) String() string {
|
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())
|
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.
|
// 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.
|
// See RFC 6143 Section 7.4 for information on each of the fields.
|
||||||
type PixelFormat struct {
|
type PixelFormat struct {
|
||||||
BPP uint8
|
BPP uint8
|
||||||
Depth uint8
|
Depth uint8
|
||||||
BigEndian bool
|
BigEndian bool
|
||||||
TrueColor bool
|
TrueColor bool
|
||||||
RedMax uint16
|
RedMax uint16
|
||||||
GreenMax uint16
|
GreenMax uint16
|
||||||
BlueMax uint16
|
BlueMax uint16
|
||||||
RedShift uint8
|
RedShift uint8
|
||||||
GreenShift uint8
|
GreenShift uint8
|
||||||
BlueShift uint8
|
BlueShift uint8
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,20 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import (
|
import "vncproxy/common"
|
||||||
"io"
|
|
||||||
"vncproxy/common"
|
type CopyRectEncoding struct {
|
||||||
)
|
//Colors []Color
|
||||||
|
copyRectSrcX uint16
|
||||||
type CopyRectEncoding struct {
|
copyRectSrcY uint16
|
||||||
//Colors []Color
|
}
|
||||||
copyRectSrcX uint16
|
|
||||||
copyRectSrcY uint16
|
func (z *CopyRectEncoding) Type() int32 {
|
||||||
}
|
return 1
|
||||||
|
}
|
||||||
func (z *CopyRectEncoding) Type() int32 {
|
func (z *CopyRectEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
return 1
|
z.copyRectSrcX, _ = r.ReadUint16()
|
||||||
}
|
z.copyRectSrcY, _ = r.ReadUint16()
|
||||||
func (z *CopyRectEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
return z, nil
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
//////////
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"vncproxy/common"
|
"vncproxy/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -13,16 +12,15 @@ func (z *CoRREEncoding) Type() int32 {
|
|||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
|
||||||
func (z *CoRREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
func (z *CoRREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
conn := common.RfbReadHelper{r}
|
|
||||||
bytesPerPixel := int(pixelFmt.BPP / 8)
|
bytesPerPixel := int(pixelFmt.BPP / 8)
|
||||||
numOfSubrectangles, _ := conn.ReadUint32()
|
numOfSubrectangles, _ := r.ReadUint32()
|
||||||
|
|
||||||
//read whole rect background color
|
//read whole rect background color
|
||||||
conn.ReadBytes(bytesPerPixel)
|
r.ReadBytes(bytesPerPixel)
|
||||||
|
|
||||||
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
|
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
|
||||||
_, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4))
|
_, err := r.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 4))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -1,85 +1,80 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import (
|
import "vncproxy/common"
|
||||||
"io"
|
|
||||||
"vncproxy/common"
|
const (
|
||||||
)
|
HextileRaw = 1
|
||||||
|
HextileBackgroundSpecified = 2
|
||||||
const (
|
HextileForegroundSpecified = 4
|
||||||
HextileRaw = 1
|
HextileAnySubrects = 8
|
||||||
HextileBackgroundSpecified = 2
|
HextileSubrectsColoured = 16
|
||||||
HextileForegroundSpecified = 4
|
)
|
||||||
HextileAnySubrects = 8
|
|
||||||
HextileSubrectsColoured = 16
|
type HextileEncoding struct {
|
||||||
)
|
//Colors []Color
|
||||||
|
}
|
||||||
type HextileEncoding struct {
|
|
||||||
//Colors []Color
|
func (z *HextileEncoding) Type() int32 {
|
||||||
}
|
return 5
|
||||||
|
}
|
||||||
func (z *HextileEncoding) Type() int32 {
|
func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
return 5
|
bytesPerPixel := int(pixelFmt.BPP) / 8
|
||||||
}
|
|
||||||
func (z *HextileEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 {
|
||||||
conn := common.RfbReadHelper{r}
|
th := 16
|
||||||
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
if rect.Y+rect.Height-ty < 16 {
|
||||||
bytesPerPixel := int(pixelFmt.BPP) / 8
|
th = int(rect.Y) + int(rect.Height) - int(ty)
|
||||||
//buf := make([]byte, bytesPerPixel)
|
}
|
||||||
for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 {
|
|
||||||
th := 16
|
for tx := rect.X; tx < rect.X+rect.Width; tx += 16 {
|
||||||
if rect.Y+rect.Height-ty < 16 {
|
tw := 16
|
||||||
th = int(rect.Y) + int(rect.Height) - int(ty)
|
if rect.X+rect.Width-tx < 16 {
|
||||||
}
|
tw = int(rect.X) + int(rect.Width) - int(tx)
|
||||||
|
}
|
||||||
for tx := rect.X; tx < rect.X+rect.Width; tx += 16 {
|
|
||||||
tw := 16
|
//handle Hextile Subrect(tx, ty, tw, th):
|
||||||
if rect.X+rect.Width-tx < 16 {
|
subencoding, err := r.ReadUint8()
|
||||||
tw = int(rect.X) + int(rect.Width) - int(tx)
|
//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)
|
||||||
//handle Hextile Subrect(tx, ty, tw, th):
|
return nil, err
|
||||||
subencoding, err := conn.ReadUint8()
|
}
|
||||||
//fmt.Printf("hextile reader tile: (%d,%d) subenc=%d\n", ty, tx, subencoding)
|
|
||||||
if err != nil {
|
if (subencoding & HextileRaw) != 0 {
|
||||||
//fmt.Printf("error in hextile reader: %v\n", err)
|
//ReadRawRect(c, rect, r)
|
||||||
return nil, err
|
r.ReadBytes(tw * th * bytesPerPixel)
|
||||||
}
|
//fmt.Printf("hextile reader: HextileRaw\n")
|
||||||
|
continue
|
||||||
if (subencoding & HextileRaw) != 0 {
|
}
|
||||||
//ReadRawRect(c, rect, r)
|
if (subencoding & HextileBackgroundSpecified) != 0 {
|
||||||
conn.ReadBytes(tw * th * bytesPerPixel)
|
r.ReadBytes(int(bytesPerPixel))
|
||||||
//fmt.Printf("hextile reader: HextileRaw\n")
|
}
|
||||||
continue
|
if (subencoding & HextileForegroundSpecified) != 0 {
|
||||||
}
|
r.ReadBytes(int(bytesPerPixel))
|
||||||
if (subencoding & HextileBackgroundSpecified) != 0 {
|
}
|
||||||
conn.ReadBytes(int(bytesPerPixel))
|
if (subencoding & HextileAnySubrects) == 0 {
|
||||||
}
|
//fmt.Printf("hextile reader: no Subrects\n")
|
||||||
if (subencoding & HextileForegroundSpecified) != 0 {
|
continue
|
||||||
conn.ReadBytes(int(bytesPerPixel))
|
}
|
||||||
}
|
//fmt.Printf("hextile reader: handling Subrects\n")
|
||||||
if (subencoding & HextileAnySubrects) == 0 {
|
nSubrects, err := r.ReadUint8()
|
||||||
//fmt.Printf("hextile reader: no Subrects\n")
|
if err != nil {
|
||||||
continue
|
return nil, err
|
||||||
}
|
}
|
||||||
//fmt.Printf("hextile reader: handling Subrects\n")
|
bufsize := int(nSubrects) * 2
|
||||||
nSubrects, err := conn.ReadUint8()
|
if (subencoding & HextileSubrectsColoured) != 0 {
|
||||||
if err != nil {
|
bufsize += int(nSubrects) * int(bytesPerPixel)
|
||||||
return nil, err
|
}
|
||||||
}
|
//byte[] buf = new byte[bufsize];
|
||||||
bufsize := int(nSubrects) * 2
|
r.ReadBytes(bufsize)
|
||||||
if (subencoding & HextileSubrectsColoured) != 0 {
|
}
|
||||||
bufsize += int(nSubrects) * int(bytesPerPixel)
|
}
|
||||||
}
|
|
||||||
//byte[] buf = new byte[bufsize];
|
// len, _ := readUint32(c.c)
|
||||||
conn.ReadBytes(bufsize)
|
// _, err := readBytes(c.c, int(len))
|
||||||
}
|
|
||||||
}
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
// len, _ := readUint32(c.c)
|
// }
|
||||||
// _, err := readBytes(c.c, int(len))
|
return z, nil
|
||||||
|
}
|
||||||
// if err != nil {
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
return z, nil
|
|
||||||
}
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io"
|
|
||||||
"vncproxy/common"
|
"vncproxy/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -16,9 +15,9 @@ func (*RawEncoding) Type() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
||||||
conn := common.RfbReadHelper{r}
|
//conn := common.RfbReadHelper{Reader:r}
|
||||||
bytesPerPixel := int(pixelFmt.BPP / 8)
|
bytesPerPixel := int(pixelFmt.BPP / 8)
|
||||||
//pixelBytes := make([]uint8, bytesPerPixel)
|
//pixelBytes := make([]uint8, bytesPerPixel)
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ func (*RawEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r
|
|||||||
|
|
||||||
for y := uint16(0); y < rect.Height; y++ {
|
for y := uint16(0); y < rect.Height; y++ {
|
||||||
for x := uint16(0); x < rect.Width; x++ {
|
for x := uint16(0); x < rect.Width; x++ {
|
||||||
if _, err := conn.ReadBytes(bytesPerPixel); err != nil {
|
if _, err := r.ReadBytes(bytesPerPixel); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,28 +1,27 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import "io"
|
import "vncproxy/common"
|
||||||
import "vncproxy/common"
|
|
||||||
|
type RREEncoding struct {
|
||||||
type RREEncoding struct {
|
//Colors []Color
|
||||||
//Colors []Color
|
}
|
||||||
}
|
|
||||||
|
func (z *RREEncoding) Type() int32 {
|
||||||
func (z *RREEncoding) Type() int32 {
|
return 2
|
||||||
return 2
|
}
|
||||||
}
|
func (z *RREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
func (z *RREEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
//conn := common.RfbReadHelper{Reader:r}
|
||||||
conn := common.RfbReadHelper{r}
|
bytesPerPixel := int(pixelFmt.BPP / 8)
|
||||||
bytesPerPixel := int(pixelFmt.BPP / 8)
|
numOfSubrectangles, _ := r.ReadUint32()
|
||||||
numOfSubrectangles, _ := conn.ReadUint32()
|
|
||||||
|
//read whole rect background color
|
||||||
//read whole rect background color
|
r.ReadBytes(bytesPerPixel)
|
||||||
conn.ReadBytes(bytesPerPixel)
|
|
||||||
|
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
|
||||||
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
|
_, err := r.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 8))
|
||||||
_, err := conn.ReadBytes(int(numOfSubrectangles) * (bytesPerPixel + 8))
|
|
||||||
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
return z, nil
|
||||||
return z, nil
|
}
|
||||||
}
|
|
||||||
|
@ -1,334 +1,334 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"vncproxy/common"
|
"vncproxy/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
var TightMinToCompress int = 12
|
var TightMinToCompress int = 12
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TightExplicitFilter = 0x04
|
TightExplicitFilter = 0x04
|
||||||
TightFill = 0x08
|
TightFill = 0x08
|
||||||
TightJpeg = 0x09
|
TightJpeg = 0x09
|
||||||
TightMaxSubencoding = 0x09
|
TightMaxSubencoding = 0x09
|
||||||
TightFilterCopy = 0x00
|
TightFilterCopy = 0x00
|
||||||
TightFilterPalette = 0x01
|
TightFilterPalette = 0x01
|
||||||
TightFilterGradient = 0x02
|
TightFilterGradient = 0x02
|
||||||
)
|
)
|
||||||
|
|
||||||
type TightEncoding struct {
|
type TightEncoding struct {
|
||||||
output io.Writer
|
output io.Writer
|
||||||
logger common.Logger
|
logger common.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TightEncoding) SetOutput(output io.Writer) {
|
func (t *TightEncoding) SetOutput(output io.Writer) {
|
||||||
t.output = output
|
t.output = output
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*TightEncoding) Type() int32 {
|
func (*TightEncoding) Type() int32 {
|
||||||
return 7
|
return 7
|
||||||
}
|
}
|
||||||
|
|
||||||
// func ReadAndRecBytes(conn io.Reader, rec io.Writer, count int) ([]byte, error) {
|
// func ReadAndRecBytes(conn io.Reader, rec io.Writer, count int) ([]byte, error) {
|
||||||
// buf, err := readBytes(conn, count)
|
// buf, err := readBytes(conn, count)
|
||||||
// rec.Write(buf)
|
// rec.Write(buf)
|
||||||
// return buf, err
|
// return buf, err
|
||||||
// }
|
// }
|
||||||
// func ReadAndRecUint8(conn io.Reader, rec io.Writer) (uint8, error) {
|
// func ReadAndRecUint8(conn io.Reader, rec io.Writer) (uint8, error) {
|
||||||
// myUint, err := readUint8(conn)
|
// myUint, err := readUint8(conn)
|
||||||
// buf := make([]byte, 1)
|
// buf := make([]byte, 1)
|
||||||
// buf[0] = byte(myUint) // cast int8 to byte
|
// buf[0] = byte(myUint) // cast int8 to byte
|
||||||
// rec.Write(buf)
|
// rec.Write(buf)
|
||||||
// return myUint, err
|
// return myUint, err
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// func ReadAndRecUint16(conn io.Reader, rec io.Writer) (uint16, error) {
|
// func ReadAndRecUint16(conn io.Reader, rec io.Writer) (uint16, error) {
|
||||||
// myUint, err := readUint16(conn)
|
// myUint, err := readUint16(conn)
|
||||||
// buf := make([]byte, 2)
|
// buf := make([]byte, 2)
|
||||||
// //buf[0] = byte(myUint) // cast int8 to byte
|
// //buf[0] = byte(myUint) // cast int8 to byte
|
||||||
// //var i int16 = 41
|
// //var i int16 = 41
|
||||||
// //b := make([]byte, 2)
|
// //b := make([]byte, 2)
|
||||||
// binary.LittleEndian.PutUint16(buf, uint16(myUint))
|
// binary.LittleEndian.PutUint16(buf, uint16(myUint))
|
||||||
|
|
||||||
// rec.Write(buf)
|
// rec.Write(buf)
|
||||||
// return myUint, err
|
// return myUint, err
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func calcTightBytePerPixel(pf *common.PixelFormat) int {
|
func calcTightBytePerPixel(pf *common.PixelFormat) int {
|
||||||
bytesPerPixel := int(pf.BPP / 8)
|
bytesPerPixel := int(pf.BPP / 8)
|
||||||
|
|
||||||
var bytesPerPixelTight int
|
var bytesPerPixelTight int
|
||||||
if 24 == pf.Depth && 32 == pf.BPP {
|
if 24 == pf.Depth && 32 == pf.BPP {
|
||||||
bytesPerPixelTight = 3
|
bytesPerPixelTight = 3
|
||||||
} else {
|
} else {
|
||||||
bytesPerPixelTight = bytesPerPixel
|
bytesPerPixelTight = bytesPerPixel
|
||||||
}
|
}
|
||||||
return bytesPerPixelTight
|
return bytesPerPixelTight
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, reader io.Reader) (common.Encoding, error) {
|
func (t *TightEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
bytesPixel := calcTightBytePerPixel(pixelFmt)
|
bytesPixel := calcTightBytePerPixel(pixelFmt)
|
||||||
conn := common.RfbReadHelper{reader}
|
//conn := common.RfbReadHelper{Reader:reader}
|
||||||
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
||||||
|
|
||||||
//var subencoding uint8
|
//var subencoding uint8
|
||||||
subencoding, err := conn.ReadUint8()
|
subencoding, err := r.ReadUint8()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error in handling tight encoding: %v\n", err)
|
fmt.Printf("error in handling tight encoding: %v\n", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Printf("bytesPixel= %d, subencoding= %d\n", bytesPixel, subencoding)
|
fmt.Printf("bytesPixel= %d, subencoding= %d\n", bytesPixel, subencoding)
|
||||||
// if err := binary.Read(conn.c, binary.BigEndian, &subencoding); err != nil {
|
// if err := binary.Read(conn.c, binary.BigEndian, &subencoding); err != nil {
|
||||||
// return t, err
|
// return t, err
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//move it to position (remove zlib flush commands)
|
//move it to position (remove zlib flush commands)
|
||||||
compType := subencoding >> 4 & 0x0F
|
compType := subencoding >> 4 & 0x0F
|
||||||
// for stream_id := 0; stream_id < 4; stream_id++ {
|
// for stream_id := 0; stream_id < 4; stream_id++ {
|
||||||
// // if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) {
|
// // if ((comp_ctl & 1) != 0 && tightInflaters[stream_id] != null) {
|
||||||
// // tightInflaters[stream_id] = null;
|
// // tightInflaters[stream_id] = null;
|
||||||
// // }
|
// // }
|
||||||
// subencoding >>= 1
|
// subencoding >>= 1
|
||||||
// }
|
// }
|
||||||
|
|
||||||
fmt.Printf("afterSHL:%d\n", compType)
|
fmt.Printf("afterSHL:%d\n", compType)
|
||||||
switch compType {
|
switch compType {
|
||||||
case TightFill:
|
case TightFill:
|
||||||
fmt.Printf("reading fill size=%d\n", bytesPixel)
|
fmt.Printf("reading fill size=%d\n", bytesPixel)
|
||||||
//read color
|
//read color
|
||||||
conn.ReadBytes(int(bytesPixel))
|
r.ReadBytes(int(bytesPixel))
|
||||||
return t, nil
|
return t, nil
|
||||||
case TightJpeg:
|
case TightJpeg:
|
||||||
if pixelFmt.BPP == 8 {
|
if pixelFmt.BPP == 8 {
|
||||||
return nil, errors.New("Tight encoding: JPEG is not supported in 8 bpp mode")
|
return nil, errors.New("Tight encoding: JPEG is not supported in 8 bpp mode")
|
||||||
}
|
}
|
||||||
|
|
||||||
len, err := conn.ReadCompactLen()
|
len, err := r.ReadCompactLen()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Printf("reading jpeg size=%d\n", len)
|
fmt.Printf("reading jpeg size=%d\n", len)
|
||||||
conn.ReadBytes(len)
|
r.ReadBytes(len)
|
||||||
return t, nil
|
return t, nil
|
||||||
default:
|
default:
|
||||||
|
|
||||||
if compType > TightJpeg {
|
if compType > TightJpeg {
|
||||||
fmt.Println("Compression control byte is incorrect!")
|
fmt.Println("Compression control byte is incorrect!")
|
||||||
}
|
}
|
||||||
|
|
||||||
handleTightFilters(subencoding, pixelFmt, rect, reader)
|
handleTightFilters(subencoding, pixelFmt, rect, r)
|
||||||
return t, nil
|
return t, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *common.Rectangle, reader io.Reader) {
|
func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) {
|
||||||
conn := common.RfbReadHelper{reader}
|
//conn := common.RfbReadHelper{Reader:reader}
|
||||||
var FILTER_ID_MASK uint8 = 0x40
|
var FILTER_ID_MASK uint8 = 0x40
|
||||||
//var STREAM_ID_MASK uint8 = 0x30
|
//var STREAM_ID_MASK uint8 = 0x30
|
||||||
|
|
||||||
//decoderId := (subencoding & STREAM_ID_MASK) >> 4
|
//decoderId := (subencoding & STREAM_ID_MASK) >> 4
|
||||||
var filterid uint8
|
var filterid uint8
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if (subencoding & FILTER_ID_MASK) > 0 { // filter byte presence
|
if (subencoding & FILTER_ID_MASK) > 0 { // filter byte presence
|
||||||
filterid, err = conn.ReadUint8()
|
filterid, err = r.ReadUint8()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error in handling tight encoding, reading filterid: %v\n", err)
|
fmt.Printf("error in handling tight encoding, reading filterid: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Printf("read filter: %d\n", filterid)
|
fmt.Printf("read filter: %d\n", filterid)
|
||||||
}
|
}
|
||||||
|
|
||||||
//var numColors uint8
|
//var numColors uint8
|
||||||
bytesPixel := calcTightBytePerPixel(pixelFmt)
|
bytesPixel := calcTightBytePerPixel(pixelFmt)
|
||||||
|
|
||||||
fmt.Printf("filter: %d\n", filterid)
|
fmt.Printf("filter: %d\n", filterid)
|
||||||
// if rfb.rec != null {
|
// if rfb.rec != null {
|
||||||
// rfb.rec.writeByte(filter_id)
|
// rfb.rec.writeByte(filter_id)
|
||||||
// }
|
// }
|
||||||
lengthCurrentbpp := int(bytesPixel) * int(rect.Width) * int(rect.Height)
|
lengthCurrentbpp := int(bytesPixel) * int(rect.Width) * int(rect.Height)
|
||||||
|
|
||||||
switch filterid {
|
switch filterid {
|
||||||
case TightFilterPalette: //PALETTE_FILTER
|
case TightFilterPalette: //PALETTE_FILTER
|
||||||
|
|
||||||
colorCount, err := conn.ReadUint8()
|
colorCount, err := r.ReadUint8()
|
||||||
paletteSize := colorCount + 1 // add one more
|
paletteSize := colorCount + 1 // add one more
|
||||||
fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
|
fmt.Printf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
|
||||||
//complete palette
|
//complete palette
|
||||||
conn.ReadBytes(int(paletteSize) * bytesPixel)
|
r.ReadBytes(int(paletteSize) * bytesPixel)
|
||||||
|
|
||||||
var dataLength int
|
var dataLength int
|
||||||
if paletteSize == 2 {
|
if paletteSize == 2 {
|
||||||
dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8)
|
dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8)
|
||||||
} else {
|
} else {
|
||||||
dataLength = int(rect.Width * rect.Height)
|
dataLength = int(rect.Width * rect.Height)
|
||||||
}
|
}
|
||||||
_, err = conn.ReadTightData(dataLength)
|
_, err = r.ReadTightData(dataLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("error in handling tight encoding, Reading Palette: %v\n", err)
|
fmt.Printf("error in handling tight encoding, Reading Palette: %v\n", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
case TightFilterGradient: //GRADIENT_FILTER
|
case TightFilterGradient: //GRADIENT_FILTER
|
||||||
fmt.Printf("----GRADIENT_FILTER: bytesPixel=%d\n", bytesPixel)
|
fmt.Printf("----GRADIENT_FILTER: bytesPixel=%d\n", bytesPixel)
|
||||||
//useGradient = true
|
//useGradient = true
|
||||||
fmt.Printf("usegrad: %d\n", filterid)
|
fmt.Printf("usegrad: %d\n", filterid)
|
||||||
conn.ReadTightData(lengthCurrentbpp)
|
r.ReadTightData(lengthCurrentbpp)
|
||||||
case TightFilterCopy: //BASIC_FILTER
|
case TightFilterCopy: //BASIC_FILTER
|
||||||
fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel)
|
fmt.Printf("----BASIC_FILTER: bytesPixel=%d\n", bytesPixel)
|
||||||
conn.ReadTightData(lengthCurrentbpp)
|
r.ReadTightData(lengthCurrentbpp)
|
||||||
default:
|
default:
|
||||||
fmt.Printf("Bad tight filter id: %d\n", filterid)
|
fmt.Printf("Bad tight filter id: %d\n", filterid)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
// if numColors == 0 && bytesPixel == 4 {
|
// if numColors == 0 && bytesPixel == 4 {
|
||||||
// rowSize1 *= 3
|
// rowSize1 *= 3
|
||||||
// }
|
// }
|
||||||
// rowSize := (int(rect.Width)*bitsPixel + 7) / 8
|
// rowSize := (int(rect.Width)*bitsPixel + 7) / 8
|
||||||
// dataSize := int(rect.Height) * rowSize
|
// dataSize := int(rect.Height) * rowSize
|
||||||
|
|
||||||
// dataSize1 := rect.Height * rowSize1
|
// dataSize1 := rect.Height * rowSize1
|
||||||
// fmt.Printf("datasize: %d, origDatasize: %d", dataSize, dataSize1)
|
// fmt.Printf("datasize: %d, origDatasize: %d", dataSize, dataSize1)
|
||||||
// // Read, optionally uncompress and decode data.
|
// // Read, optionally uncompress and decode data.
|
||||||
// if int(dataSize1) < TightMinToCompress {
|
// if int(dataSize1) < TightMinToCompress {
|
||||||
// // Data size is small - not compressed with zlib.
|
// // Data size is small - not compressed with zlib.
|
||||||
// if numColors != 0 {
|
// if numColors != 0 {
|
||||||
// // Indexed colors.
|
// // Indexed colors.
|
||||||
// //indexedData := make([]byte, dataSize)
|
// //indexedData := make([]byte, dataSize)
|
||||||
// readBytes(conn.c, int(dataSize1))
|
// readBytes(conn.c, int(dataSize1))
|
||||||
// //readFully(indexedData);
|
// //readFully(indexedData);
|
||||||
// // if (rfb.rec != null) {
|
// // if (rfb.rec != null) {
|
||||||
// // rfb.rec.write(indexedData);
|
// // rfb.rec.write(indexedData);
|
||||||
// // }
|
// // }
|
||||||
// // if (numColors == 2) {
|
// // if (numColors == 2) {
|
||||||
// // // Two colors.
|
// // // Two colors.
|
||||||
// // if (bytesPixel == 1) {
|
// // if (bytesPixel == 1) {
|
||||||
// // decodeMonoData(x, y, w, h, indexedData, palette8);
|
// // decodeMonoData(x, y, w, h, indexedData, palette8);
|
||||||
// // } else {
|
// // } else {
|
||||||
// // decodeMonoData(x, y, w, h, indexedData, palette24);
|
// // decodeMonoData(x, y, w, h, indexedData, palette24);
|
||||||
// // }
|
// // }
|
||||||
// // } else {
|
// // } else {
|
||||||
// // // 3..255 colors (assuming bytesPixel == 4).
|
// // // 3..255 colors (assuming bytesPixel == 4).
|
||||||
// // int i = 0;
|
// // int i = 0;
|
||||||
// // for (int dy = y; dy < y + h; dy++) {
|
// // for (int dy = y; dy < y + h; dy++) {
|
||||||
// // for (int dx = x; dx < x + w; dx++) {
|
// // for (int dx = x; dx < x + w; dx++) {
|
||||||
// // pixels24[dy * rfb.framebufferWidth + dx] = palette24[indexedData[i++] & 0xFF];
|
// // pixels24[dy * rfb.framebufferWidth + dx] = palette24[indexedData[i++] & 0xFF];
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// } else if useGradient {
|
// } else if useGradient {
|
||||||
// // "Gradient"-processed data
|
// // "Gradient"-processed data
|
||||||
// //buf := make ( []byte,w * h * 3);
|
// //buf := make ( []byte,w * h * 3);
|
||||||
// dataByteCount := int(3) * int(rect.Width) * int(rect.Height)
|
// dataByteCount := int(3) * int(rect.Width) * int(rect.Height)
|
||||||
// readBytes(conn.c, dataByteCount)
|
// readBytes(conn.c, dataByteCount)
|
||||||
// // rfb.readFully(buf);
|
// // rfb.readFully(buf);
|
||||||
// // if (rfb.rec != null) {
|
// // if (rfb.rec != null) {
|
||||||
// // rfb.rec.write(buf);
|
// // rfb.rec.write(buf);
|
||||||
// // }
|
// // }
|
||||||
// // decodeGradientData(x, y, w, h, buf);
|
// // decodeGradientData(x, y, w, h, buf);
|
||||||
// } else {
|
// } else {
|
||||||
// // Raw truecolor data.
|
// // Raw truecolor data.
|
||||||
// dataByteCount := int(bytesPixel) * int(rect.Width) * int(rect.Height)
|
// dataByteCount := int(bytesPixel) * int(rect.Width) * int(rect.Height)
|
||||||
// readBytes(conn.c, dataByteCount)
|
// readBytes(conn.c, dataByteCount)
|
||||||
|
|
||||||
// // if (bytesPixel == 1) {
|
// // if (bytesPixel == 1) {
|
||||||
// // for (int dy = y; dy < y + h; dy++) {
|
// // for (int dy = y; dy < y + h; dy++) {
|
||||||
|
|
||||||
// // rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w);
|
// // rfb.readFully(pixels8, dy * rfb.framebufferWidth + x, w);
|
||||||
// // if (rfb.rec != null) {
|
// // if (rfb.rec != null) {
|
||||||
// // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w);
|
// // rfb.rec.write(pixels8, dy * rfb.framebufferWidth + x, w);
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // } else {
|
// // } else {
|
||||||
// // byte[] buf = new byte[w * 3];
|
// // byte[] buf = new byte[w * 3];
|
||||||
// // int i, offset;
|
// // int i, offset;
|
||||||
// // for (int dy = y; dy < y + h; dy++) {
|
// // for (int dy = y; dy < y + h; dy++) {
|
||||||
// // rfb.readFully(buf);
|
// // rfb.readFully(buf);
|
||||||
// // if (rfb.rec != null) {
|
// // if (rfb.rec != null) {
|
||||||
// // rfb.rec.write(buf);
|
// // rfb.rec.write(buf);
|
||||||
// // }
|
// // }
|
||||||
// // offset = dy * rfb.framebufferWidth + x;
|
// // offset = dy * rfb.framebufferWidth + x;
|
||||||
// // for (i = 0; i < w; i++) {
|
// // 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);
|
// // pixels24[offset + i] = (buf[i * 3] & 0xFF) << 16 | (buf[i * 3 + 1] & 0xFF) << 8 | (buf[i * 3 + 2] & 0xFF);
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// }
|
// }
|
||||||
// } else {
|
// } else {
|
||||||
// // Data was compressed with zlib.
|
// // Data was compressed with zlib.
|
||||||
// zlibDataLen, err := readCompactLen(conn.c)
|
// zlibDataLen, err := readCompactLen(conn.c)
|
||||||
// fmt.Printf("compactlen=%d\n", zlibDataLen)
|
// fmt.Printf("compactlen=%d\n", zlibDataLen)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// return nil, err
|
// return nil, err
|
||||||
// }
|
// }
|
||||||
// //byte[] zlibData = new byte[zlibDataLen];
|
// //byte[] zlibData = new byte[zlibDataLen];
|
||||||
// //rfb.readFully(zlibData);
|
// //rfb.readFully(zlibData);
|
||||||
// readBytes(conn.c, zlibDataLen)
|
// readBytes(conn.c, zlibDataLen)
|
||||||
|
|
||||||
// // if (rfb.rec != null) {
|
// // if (rfb.rec != null) {
|
||||||
// // rfb.rec.write(zlibData);
|
// // rfb.rec.write(zlibData);
|
||||||
// // }
|
// // }
|
||||||
// // int stream_id = comp_ctl & 0x03;
|
// // int stream_id = comp_ctl & 0x03;
|
||||||
// // if (tightInflaters[stream_id] == null) {
|
// // if (tightInflaters[stream_id] == null) {
|
||||||
// // tightInflaters[stream_id] = new Inflater();
|
// // tightInflaters[stream_id] = new Inflater();
|
||||||
// // }
|
// // }
|
||||||
// // Inflater myInflater = tightInflaters[stream_id];
|
// // Inflater myInflater = tightInflaters[stream_id];
|
||||||
// // myInflater.setInput(zlibData);
|
// // myInflater.setInput(zlibData);
|
||||||
// // byte[] buf = new byte[dataSize];
|
// // byte[] buf = new byte[dataSize];
|
||||||
// // myInflater.inflate(buf);
|
// // myInflater.inflate(buf);
|
||||||
// // if (rfb.rec != null && !rfb.recordFromBeginning) {
|
// // if (rfb.rec != null && !rfb.recordFromBeginning) {
|
||||||
// // rfb.recordCompressedData(buf);
|
// // rfb.recordCompressedData(buf);
|
||||||
// // }
|
// // }
|
||||||
|
|
||||||
// // if (numColors != 0) {
|
// // if (numColors != 0) {
|
||||||
// // // Indexed colors.
|
// // // Indexed colors.
|
||||||
// // if (numColors == 2) {
|
// // if (numColors == 2) {
|
||||||
// // // Two colors.
|
// // // Two colors.
|
||||||
// // if (bytesPixel == 1) {
|
// // if (bytesPixel == 1) {
|
||||||
// // decodeMonoData(x, y, w, h, buf, palette8);
|
// // decodeMonoData(x, y, w, h, buf, palette8);
|
||||||
// // } else {
|
// // } else {
|
||||||
// // decodeMonoData(x, y, w, h, buf, palette24);
|
// // decodeMonoData(x, y, w, h, buf, palette24);
|
||||||
// // }
|
// // }
|
||||||
// // } else {
|
// // } else {
|
||||||
// // // More than two colors (assuming bytesPixel == 4).
|
// // // More than two colors (assuming bytesPixel == 4).
|
||||||
// // int i = 0;
|
// // int i = 0;
|
||||||
// // for (int dy = y; dy < y + h; dy++) {
|
// // for (int dy = y; dy < y + h; dy++) {
|
||||||
// // for (int dx = x; dx < x + w; dx++) {
|
// // for (int dx = x; dx < x + w; dx++) {
|
||||||
// // pixels24[dy * rfb.framebufferWidth + dx] = palette24[buf[i++] & 0xFF];
|
// // pixels24[dy * rfb.framebufferWidth + dx] = palette24[buf[i++] & 0xFF];
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // } else if (useGradient) {
|
// // } else if (useGradient) {
|
||||||
// // // Compressed "Gradient"-filtered data (assuming bytesPixel == 4).
|
// // // Compressed "Gradient"-filtered data (assuming bytesPixel == 4).
|
||||||
// // decodeGradientData(x, y, w, h, buf);
|
// // decodeGradientData(x, y, w, h, buf);
|
||||||
// // } else {
|
// // } else {
|
||||||
// // // Compressed truecolor data.
|
// // // Compressed truecolor data.
|
||||||
// // if (bytesPixel == 1) {
|
// // if (bytesPixel == 1) {
|
||||||
// // int destOffset = y * rfb.framebufferWidth + x;
|
// // int destOffset = y * rfb.framebufferWidth + x;
|
||||||
// // for (int dy = 0; dy < h; dy++) {
|
// // for (int dy = 0; dy < h; dy++) {
|
||||||
// // System.arraycopy(buf, dy * w, pixels8, destOffset, w);
|
// // System.arraycopy(buf, dy * w, pixels8, destOffset, w);
|
||||||
// // destOffset += rfb.framebufferWidth;
|
// // destOffset += rfb.framebufferWidth;
|
||||||
// // }
|
// // }
|
||||||
// // } else {
|
// // } else {
|
||||||
// // int srcOffset = 0;
|
// // int srcOffset = 0;
|
||||||
// // int destOffset, i;
|
// // int destOffset, i;
|
||||||
// // for (int dy = 0; dy < h; dy++) {
|
// // for (int dy = 0; dy < h; dy++) {
|
||||||
// // myInflater.inflate(buf);
|
// // myInflater.inflate(buf);
|
||||||
// // destOffset = (y + dy) * rfb.framebufferWidth + x;
|
// // destOffset = (y + dy) * rfb.framebufferWidth + x;
|
||||||
// // for (i = 0; i < w; i++) {
|
// // for (i = 0; i < w; i++) {
|
||||||
// // pixels24[destOffset + i] = (buf[srcOffset] & 0xFF) << 16 | (buf[srcOffset + 1] & 0xFF) << 8
|
// // pixels24[destOffset + i] = (buf[srcOffset] & 0xFF) << 16 | (buf[srcOffset + 1] & 0xFF) << 8
|
||||||
// // | (buf[srcOffset + 2] & 0xFF);
|
// // | (buf[srcOffset + 2] & 0xFF);
|
||||||
// // srcOffset += 3;
|
// // srcOffset += 3;
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// // }
|
// // }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import "io"
|
import "vncproxy/common"
|
||||||
import "vncproxy/common"
|
|
||||||
|
type ZLibEncoding struct {
|
||||||
type ZLibEncoding struct {
|
//Colors []Color
|
||||||
//Colors []Color
|
}
|
||||||
}
|
|
||||||
|
func (z *ZLibEncoding) Type() int32 {
|
||||||
func (z *ZLibEncoding) Type() int32 {
|
return 6
|
||||||
return 6
|
}
|
||||||
}
|
func (z *ZLibEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
func (z *ZLibEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
//conn := common.RfbReadHelper{Reader:r}
|
||||||
conn := common.RfbReadHelper{r}
|
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
||||||
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
//bytesPerPixel := c.PixelFormat.BPP / 8
|
||||||
//bytesPerPixel := c.PixelFormat.BPP / 8
|
len, _ := r.ReadUint32()
|
||||||
len, _ := conn.ReadUint32()
|
_, err := r.ReadBytes(int(len))
|
||||||
_, err := conn.ReadBytes(int(len))
|
|
||||||
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
return z, nil
|
||||||
return z, nil
|
}
|
||||||
}
|
|
||||||
|
@ -1,24 +1,23 @@
|
|||||||
package encodings
|
package encodings
|
||||||
|
|
||||||
import "io"
|
import "vncproxy/common"
|
||||||
import "vncproxy/common"
|
|
||||||
|
type ZRLEEncoding struct {
|
||||||
type ZRLEEncoding struct {
|
//Colors []Color
|
||||||
//Colors []Color
|
}
|
||||||
}
|
|
||||||
|
func (z *ZRLEEncoding) Type() int32 {
|
||||||
func (z *ZRLEEncoding) Type() int32 {
|
return 16
|
||||||
return 16
|
}
|
||||||
}
|
func (z *ZRLEEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.Encoding, error) {
|
||||||
func (z *ZRLEEncoding) Read(pixelFmt *common.PixelFormat, rect *common.Rectangle, r io.Reader) (common.Encoding, error) {
|
//conn := common.RfbReadHelper{Reader: r}
|
||||||
conn := common.RfbReadHelper{r}
|
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
||||||
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
|
//bytesPerPixel := c.PixelFormat.BPP / 8
|
||||||
//bytesPerPixel := c.PixelFormat.BPP / 8
|
len, _ := r.ReadUint32()
|
||||||
len, _ := conn.ReadUint32()
|
_, err := r.ReadBytes(int(len))
|
||||||
_, err := conn.ReadBytes(int(len))
|
|
||||||
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return nil, err
|
}
|
||||||
}
|
return z, nil
|
||||||
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")
|
nc, err := net.Dial("tcp", "localhost:5903")
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf(";error connecting to vnc server: %s", err)
|
fmt.Printf("error connecting to vnc server: %s", err)
|
||||||
}
|
}
|
||||||
var noauth vnc.ClientAuthNone
|
var noauth vnc.ClientAuthNone
|
||||||
authArr := []vnc.ClientAuth{&vnc.PasswordAuth{Password: "Ch_#!T@8"}, &noauth}
|
authArr := []vnc.ClientAuth{&vnc.PasswordAuth{Password: "Ch_#!T@8"}, &noauth}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
# VNC Library for Go
|
# VNC Library for Go
|
||||||
|
|
||||||
go-vnc is a VNC library for Go, initially supporting VNC clients but
|
go-vnc is a VNC library for Go, initially supporting VNC clients but
|
||||||
with the goal of eventually implementing a VNC server.
|
with the goal of eventually implementing a VNC server.
|
||||||
|
|
||||||
This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143).
|
This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143).
|
||||||
|
|
||||||
## Usage & Installation
|
## Usage & Installation
|
||||||
|
|
||||||
The library is installable via standard `go get`. The package name is `vnc`.
|
The library is installable via standard `go get`. The package name is `vnc`.
|
||||||
|
|
||||||
```
|
```
|
||||||
$ go get github.com/mitchellh/go-vnc
|
$ go get github.com/mitchellh/go-vnc
|
||||||
```
|
```
|
||||||
|
|
||||||
Documentation is available on GoDoc: http://godoc.org/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
|
package vnc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
|
||||||
"crypto/des"
|
"crypto/des"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// ClientAuthNone is the "none" authentication. See 7.2.1
|
// ClientAuthNone is the "none" authentication. See 7.2.1
|
||||||
type ClientAuthNone byte
|
type ClientAuthNone byte
|
||||||
|
|
||||||
func (*ClientAuthNone) SecurityType() uint8 {
|
func (*ClientAuthNone) SecurityType() uint8 {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*ClientAuthNone) Handshake(net.Conn) error {
|
func (*ClientAuthNone) Handshake(net.Conn) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// PasswordAuth is VNC authentication, 7.2.2
|
// PasswordAuth is VNC authentication, 7.2.2
|
||||||
type PasswordAuth struct {
|
type PasswordAuth struct {
|
||||||
Password string
|
Password string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PasswordAuth) SecurityType() uint8 {
|
func (p *PasswordAuth) SecurityType() uint8 {
|
||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PasswordAuth) Handshake(c net.Conn) error {
|
func (p *PasswordAuth) Handshake(c net.Conn) error {
|
||||||
randomValue := make([]uint8, 16)
|
randomValue := make([]uint8, 16)
|
||||||
if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil {
|
if err := binary.Read(c, binary.BigEndian, &randomValue); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
crypted, err := p.encrypt(p.Password, randomValue)
|
crypted, err := p.encrypt(p.Password, randomValue)
|
||||||
|
|
||||||
if (err != nil) {
|
if (err != nil) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(c, binary.BigEndian, &crypted); err != nil {
|
if err := binary.Write(c, binary.BigEndian, &crypted); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PasswordAuth) reverseBits(b byte) byte {
|
func (p *PasswordAuth) reverseBits(b byte) byte {
|
||||||
var reverse = [256]int{
|
var reverse = [256]int{
|
||||||
0, 128, 64, 192, 32, 160, 96, 224,
|
0, 128, 64, 192, 32, 160, 96, 224,
|
||||||
16, 144, 80, 208, 48, 176, 112, 240,
|
16, 144, 80, 208, 48, 176, 112, 240,
|
||||||
8, 136, 72, 200, 40, 168, 104, 232,
|
8, 136, 72, 200, 40, 168, 104, 232,
|
||||||
24, 152, 88, 216, 56, 184, 120, 248,
|
24, 152, 88, 216, 56, 184, 120, 248,
|
||||||
4, 132, 68, 196, 36, 164, 100, 228,
|
4, 132, 68, 196, 36, 164, 100, 228,
|
||||||
20, 148, 84, 212, 52, 180, 116, 244,
|
20, 148, 84, 212, 52, 180, 116, 244,
|
||||||
12, 140, 76, 204, 44, 172, 108, 236,
|
12, 140, 76, 204, 44, 172, 108, 236,
|
||||||
28, 156, 92, 220, 60, 188, 124, 252,
|
28, 156, 92, 220, 60, 188, 124, 252,
|
||||||
2, 130, 66, 194, 34, 162, 98, 226,
|
2, 130, 66, 194, 34, 162, 98, 226,
|
||||||
18, 146, 82, 210, 50, 178, 114, 242,
|
18, 146, 82, 210, 50, 178, 114, 242,
|
||||||
10, 138, 74, 202, 42, 170, 106, 234,
|
10, 138, 74, 202, 42, 170, 106, 234,
|
||||||
26, 154, 90, 218, 58, 186, 122, 250,
|
26, 154, 90, 218, 58, 186, 122, 250,
|
||||||
6, 134, 70, 198, 38, 166, 102, 230,
|
6, 134, 70, 198, 38, 166, 102, 230,
|
||||||
22, 150, 86, 214, 54, 182, 118, 246,
|
22, 150, 86, 214, 54, 182, 118, 246,
|
||||||
14, 142, 78, 206, 46, 174, 110, 238,
|
14, 142, 78, 206, 46, 174, 110, 238,
|
||||||
30, 158, 94, 222, 62, 190, 126, 254,
|
30, 158, 94, 222, 62, 190, 126, 254,
|
||||||
1, 129, 65, 193, 33, 161, 97, 225,
|
1, 129, 65, 193, 33, 161, 97, 225,
|
||||||
17, 145, 81, 209, 49, 177, 113, 241,
|
17, 145, 81, 209, 49, 177, 113, 241,
|
||||||
9, 137, 73, 201, 41, 169, 105, 233,
|
9, 137, 73, 201, 41, 169, 105, 233,
|
||||||
25, 153, 89, 217, 57, 185, 121, 249,
|
25, 153, 89, 217, 57, 185, 121, 249,
|
||||||
5, 133, 69, 197, 37, 165, 101, 229,
|
5, 133, 69, 197, 37, 165, 101, 229,
|
||||||
21, 149, 85, 213, 53, 181, 117, 245,
|
21, 149, 85, 213, 53, 181, 117, 245,
|
||||||
13, 141, 77, 205, 45, 173, 109, 237,
|
13, 141, 77, 205, 45, 173, 109, 237,
|
||||||
29, 157, 93, 221, 61, 189, 125, 253,
|
29, 157, 93, 221, 61, 189, 125, 253,
|
||||||
3, 131, 67, 195, 35, 163, 99, 227,
|
3, 131, 67, 195, 35, 163, 99, 227,
|
||||||
19, 147, 83, 211, 51, 179, 115, 243,
|
19, 147, 83, 211, 51, 179, 115, 243,
|
||||||
11, 139, 75, 203, 43, 171, 107, 235,
|
11, 139, 75, 203, 43, 171, 107, 235,
|
||||||
27, 155, 91, 219, 59, 187, 123, 251,
|
27, 155, 91, 219, 59, 187, 123, 251,
|
||||||
7, 135, 71, 199, 39, 167, 103, 231,
|
7, 135, 71, 199, 39, 167, 103, 231,
|
||||||
23, 151, 87, 215, 55, 183, 119, 247,
|
23, 151, 87, 215, 55, 183, 119, 247,
|
||||||
15, 143, 79, 207, 47, 175, 111, 239,
|
15, 143, 79, 207, 47, 175, 111, 239,
|
||||||
31, 159, 95, 223, 63, 191, 127, 255,
|
31, 159, 95, 223, 63, 191, 127, 255,
|
||||||
}
|
}
|
||||||
|
|
||||||
return byte(reverse[int(b)])
|
return byte(reverse[int(b)])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) {
|
func (p *PasswordAuth) encrypt(key string, bytes []byte) ([]byte, error) {
|
||||||
keyBytes := []byte{0,0,0,0,0,0,0,0}
|
keyBytes := []byte{0,0,0,0,0,0,0,0}
|
||||||
|
|
||||||
if len(key) > 8 {
|
if len(key) > 8 {
|
||||||
key = key[:8]
|
key = key[:8]
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(key); i++ {
|
for i := 0; i < len(key); i++ {
|
||||||
keyBytes[i] = p.reverseBits(key[i])
|
keyBytes[i] = p.reverseBits(key[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
block, err := des.NewCipher(keyBytes)
|
block, err := des.NewCipher(keyBytes)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result1 := make([]byte, 8)
|
result1 := make([]byte, 8)
|
||||||
block.Encrypt(result1, bytes)
|
block.Encrypt(result1, bytes)
|
||||||
result2 := make([]byte, 8)
|
result2 := make([]byte, 8)
|
||||||
block.Encrypt(result2, bytes[8:])
|
block.Encrypt(result2, bytes[8:])
|
||||||
|
|
||||||
crypted := append(result1, result2...)
|
crypted := append(result1, result2...)
|
||||||
|
|
||||||
return crypted, nil
|
return crypted, nil
|
||||||
}
|
}
|
||||||
|
@ -1,169 +1,169 @@
|
|||||||
package vnc
|
package vnc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"net"
|
"net"
|
||||||
"time"
|
"time"
|
||||||
"bytes"
|
"bytes"
|
||||||
)
|
)
|
||||||
|
|
||||||
type fakeNetConnection struct {
|
type fakeNetConnection struct {
|
||||||
DataToSend []byte
|
DataToSend []byte
|
||||||
Test *testing.T
|
Test *testing.T
|
||||||
ExpectData []byte
|
ExpectData []byte
|
||||||
Finished bool
|
Finished bool
|
||||||
Matched bool
|
Matched bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc fakeNetConnection) Read(b []byte) (n int, err error) {
|
func (fc fakeNetConnection) Read(b []byte) (n int, err error) {
|
||||||
for i := 0; i < 16; i++ {
|
for i := 0; i < 16; i++ {
|
||||||
b[i] = fc.DataToSend[i]
|
b[i] = fc.DataToSend[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
fc.Finished = false
|
fc.Finished = false
|
||||||
|
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *fakeNetConnection) Write(b []byte) (n int, err error) {
|
func (fc *fakeNetConnection) Write(b []byte) (n int, err error) {
|
||||||
fc.Matched = bytes.Equal(b, fc.ExpectData)
|
fc.Matched = bytes.Equal(b, fc.ExpectData)
|
||||||
fc.Finished = true
|
fc.Finished = true
|
||||||
|
|
||||||
return len(b), nil
|
return len(b), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (fc *fakeNetConnection) Close() error { return nil; }
|
func (fc *fakeNetConnection) Close() error { return nil; }
|
||||||
func (fc *fakeNetConnection) LocalAddr() net.Addr { return nil; }
|
func (fc *fakeNetConnection) LocalAddr() net.Addr { return nil; }
|
||||||
func (fc *fakeNetConnection) RemoteAddr() 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) SetDeadline(t time.Time) error { return nil; }
|
||||||
func (fc *fakeNetConnection) SetReadDeadline(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 (fc *fakeNetConnection) SetWriteDeadline(t time.Time) error { return nil; }
|
||||||
|
|
||||||
func TestClientAuthNone_Impl(t *testing.T) {
|
func TestClientAuthNone_Impl(t *testing.T) {
|
||||||
var raw interface{}
|
var raw interface{}
|
||||||
raw = new(ClientAuthNone)
|
raw = new(ClientAuthNone)
|
||||||
if _, ok := raw.(ClientAuth); !ok {
|
if _, ok := raw.(ClientAuth); !ok {
|
||||||
t.Fatal("ClientAuthNone doesn't implement ClientAuth")
|
t.Fatal("ClientAuthNone doesn't implement ClientAuth")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientAuthPasswordSuccess_Impl(t *testing.T) {
|
func TestClientAuthPasswordSuccess_Impl(t *testing.T) {
|
||||||
// Values ripped using WireShark
|
// Values ripped using WireShark
|
||||||
randomValue := []byte{
|
randomValue := []byte{
|
||||||
0xa4,
|
0xa4,
|
||||||
0x51,
|
0x51,
|
||||||
0x3f,
|
0x3f,
|
||||||
0xa5,
|
0xa5,
|
||||||
0x1f,
|
0x1f,
|
||||||
0x87,
|
0x87,
|
||||||
0x06,
|
0x06,
|
||||||
0x10,
|
0x10,
|
||||||
0xa4,
|
0xa4,
|
||||||
0x5f,
|
0x5f,
|
||||||
0xae,
|
0xae,
|
||||||
0xbf,
|
0xbf,
|
||||||
0x4d,
|
0x4d,
|
||||||
0xac,
|
0xac,
|
||||||
0x12,
|
0x12,
|
||||||
0x22,
|
0x22,
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedResponse := []byte{
|
expectedResponse := []byte{
|
||||||
0x71,
|
0x71,
|
||||||
0xe4,
|
0xe4,
|
||||||
0x41,
|
0x41,
|
||||||
0x30,
|
0x30,
|
||||||
0x43,
|
0x43,
|
||||||
0x65,
|
0x65,
|
||||||
0x4e,
|
0x4e,
|
||||||
0x39,
|
0x39,
|
||||||
0xda,
|
0xda,
|
||||||
0x6d,
|
0x6d,
|
||||||
0x49,
|
0x49,
|
||||||
0x93,
|
0x93,
|
||||||
0x43,
|
0x43,
|
||||||
0xf6,
|
0xf6,
|
||||||
0x5e,
|
0x5e,
|
||||||
0x29,
|
0x29,
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := PasswordAuth{Password: "Ch_#!T@8"}
|
raw := PasswordAuth{Password: "Ch_#!T@8"}
|
||||||
|
|
||||||
// Only about 12 hours into Go at the moment...
|
// Only about 12 hours into Go at the moment...
|
||||||
// if _, ok := raw.(ClientAuth); !ok {
|
// if _, ok := raw.(ClientAuth); !ok {
|
||||||
// t.Fatal("PasswordAuth doesn't implement ClientAuth")
|
// t.Fatal("PasswordAuth doesn't implement ClientAuth")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
|
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
|
||||||
err := raw.Handshake(conn)
|
err := raw.Handshake(conn)
|
||||||
|
|
||||||
if (err != nil) {
|
if (err != nil) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !conn.Matched {
|
if !conn.Matched {
|
||||||
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
|
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !conn.Finished {
|
if !conn.Finished {
|
||||||
t.Fatal("PasswordAuth didn't complete properly")
|
t.Fatal("PasswordAuth didn't complete properly")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClientAuthPasswordReject_Impl(t *testing.T) {
|
func TestClientAuthPasswordReject_Impl(t *testing.T) {
|
||||||
// Values ripped using WireShark
|
// Values ripped using WireShark
|
||||||
randomValue := []byte{
|
randomValue := []byte{
|
||||||
0xa4,
|
0xa4,
|
||||||
0x51,
|
0x51,
|
||||||
0x3f,
|
0x3f,
|
||||||
0xa5,
|
0xa5,
|
||||||
0x1f,
|
0x1f,
|
||||||
0x87,
|
0x87,
|
||||||
0x06,
|
0x06,
|
||||||
0x10,
|
0x10,
|
||||||
0xa4,
|
0xa4,
|
||||||
0x5f,
|
0x5f,
|
||||||
0xae,
|
0xae,
|
||||||
0xbf,
|
0xbf,
|
||||||
0x4d,
|
0x4d,
|
||||||
0xac,
|
0xac,
|
||||||
0x12,
|
0x12,
|
||||||
0x22,
|
0x22,
|
||||||
}
|
}
|
||||||
|
|
||||||
expectedResponse := []byte{
|
expectedResponse := []byte{
|
||||||
0x71,
|
0x71,
|
||||||
0xe4,
|
0xe4,
|
||||||
0x41,
|
0x41,
|
||||||
0x30,
|
0x30,
|
||||||
0x43,
|
0x43,
|
||||||
0x65,
|
0x65,
|
||||||
0x4e,
|
0x4e,
|
||||||
0x39,
|
0x39,
|
||||||
0xda,
|
0xda,
|
||||||
0x6d,
|
0x6d,
|
||||||
0x49,
|
0x49,
|
||||||
0x93,
|
0x93,
|
||||||
0x43,
|
0x43,
|
||||||
0xf6,
|
0xf6,
|
||||||
0x5e,
|
0x5e,
|
||||||
0x29,
|
0x29,
|
||||||
}
|
}
|
||||||
|
|
||||||
raw := PasswordAuth{Password: "Ch_#!T@"}
|
raw := PasswordAuth{Password: "Ch_#!T@"}
|
||||||
|
|
||||||
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
|
conn := &fakeNetConnection{DataToSend: randomValue, ExpectData: expectedResponse, Test: t}
|
||||||
err := raw.Handshake(conn)
|
err := raw.Handshake(conn)
|
||||||
|
|
||||||
if (err != nil) {
|
if (err != nil) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if conn.Matched {
|
if conn.Matched {
|
||||||
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
|
t.Fatal("PasswordAuth didn't pass the right response back to the wire")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !conn.Finished {
|
if !conn.Finished {
|
||||||
t.Fatal("PasswordAuth didn't complete properly")
|
t.Fatal("PasswordAuth didn't complete properly")
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,95 +1,95 @@
|
|||||||
package vnc
|
package vnc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newMockServer(t *testing.T, version string) string {
|
func newMockServer(t *testing.T, version string) string {
|
||||||
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error listening: %s", err)
|
t.Fatalf("error listening: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
defer ln.Close()
|
defer ln.Close()
|
||||||
c, err := ln.Accept()
|
c, err := ln.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error accepting conn: %s", err)
|
t.Fatalf("error accepting conn: %s", err)
|
||||||
}
|
}
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
_, err = c.Write([]byte(fmt.Sprintf("RFB %s\n", version)))
|
_, err = c.Write([]byte(fmt.Sprintf("RFB %s\n", version)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("failed writing version")
|
t.Fatal("failed writing version")
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return ln.Addr().String()
|
return ln.Addr().String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_LowMajorVersion(t *testing.T) {
|
func TestClient_LowMajorVersion(t *testing.T) {
|
||||||
nc, err := net.Dial("tcp", newMockServer(t, "002.009"))
|
nc, err := net.Dial("tcp", newMockServer(t, "002.009"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error connecting to mock server: %s", err)
|
t.Fatalf("error connecting to mock server: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = Client(nc, &ClientConfig{})
|
_, err = Client(nc, &ClientConfig{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("error expected")
|
t.Fatal("error expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err.Error() != "unsupported major version, less than 3: 2" {
|
if err.Error() != "unsupported major version, less than 3: 2" {
|
||||||
t.Fatalf("unexpected error: %s", err)
|
t.Fatalf("unexpected error: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_LowMinorVersion(t *testing.T) {
|
func TestClient_LowMinorVersion(t *testing.T) {
|
||||||
nc, err := net.Dial("tcp", newMockServer(t, "003.007"))
|
nc, err := net.Dial("tcp", newMockServer(t, "003.007"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error connecting to mock server: %s", err)
|
t.Fatalf("error connecting to mock server: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = Client(nc, &ClientConfig{})
|
_, err = Client(nc, &ClientConfig{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("error expected")
|
t.Fatal("error expected")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err.Error() != "unsupported minor version, less than 8: 7" {
|
if err.Error() != "unsupported minor version, less than 8: 7" {
|
||||||
t.Fatalf("unexpected error: %s", err)
|
t.Fatalf("unexpected error: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestParseProtocolVersion(t *testing.T) {
|
func TestParseProtocolVersion(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
proto []byte
|
proto []byte
|
||||||
major, minor uint
|
major, minor uint
|
||||||
isErr bool
|
isErr bool
|
||||||
}{
|
}{
|
||||||
// Valid ProtocolVersion messages.
|
// 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, 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, 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
|
{[]byte{82, 70, 66, 32, 48, 48, 48, 46, 48, 48, 48, 10}, 0, 0, false}, // RFB 000.0000\n
|
||||||
// Invalid messages.
|
// 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, 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{82, 70, 66, 10}, 0, 0, true}, // RFB\n -- too short
|
||||||
{[]byte{}, 0, 0, true}, // (empty) -- too short
|
{[]byte{}, 0, 0, true}, // (empty) -- too short
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
major, minor, err := parseProtocolVersion(tt.proto)
|
major, minor, err := parseProtocolVersion(tt.proto)
|
||||||
if err != nil && !tt.isErr {
|
if err != nil && !tt.isErr {
|
||||||
t.Fatalf("parseProtocolVersion(%v) unexpected error %v", tt.proto, err)
|
t.Fatalf("parseProtocolVersion(%v) unexpected error %v", tt.proto, err)
|
||||||
}
|
}
|
||||||
if err == nil && tt.isErr {
|
if err == nil && tt.isErr {
|
||||||
t.Fatalf("parseProtocolVersion(%v) expected error", tt.proto)
|
t.Fatalf("parseProtocolVersion(%v) expected error", tt.proto)
|
||||||
}
|
}
|
||||||
if major != tt.major {
|
if major != tt.major {
|
||||||
t.Errorf("parseProtocolVersion(%v) major = %v, want %v", tt.proto, major, tt.major)
|
t.Errorf("parseProtocolVersion(%v) major = %v, want %v", tt.proto, major, tt.major)
|
||||||
}
|
}
|
||||||
if major != tt.major {
|
if major != tt.major {
|
||||||
t.Errorf("parseProtocolVersion(%v) minor = %v, want %v", tt.proto, minor, tt.minor)
|
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
|
package vnc
|
||||||
|
|
||||||
// Color represents a single color in a color map.
|
// Color represents a single color in a color map.
|
||||||
type Color struct {
|
type Color struct {
|
||||||
R, G, B uint16
|
R, G, B uint16
|
||||||
}
|
}
|
||||||
|
@ -1,136 +1,136 @@
|
|||||||
package vnc
|
package vnc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"io"
|
"io"
|
||||||
"vncproxy/common"
|
"vncproxy/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readPixelFormat(r io.Reader, result *common.PixelFormat) error {
|
func readPixelFormat(r io.Reader, result *common.PixelFormat) error {
|
||||||
var rawPixelFormat [16]byte
|
var rawPixelFormat [16]byte
|
||||||
if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil {
|
if _, err := io.ReadFull(r, rawPixelFormat[:]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var pfBoolByte uint8
|
var pfBoolByte uint8
|
||||||
brPF := bytes.NewReader(rawPixelFormat[:])
|
brPF := bytes.NewReader(rawPixelFormat[:])
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.BPP); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.Depth); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pfBoolByte != 0 {
|
if pfBoolByte != 0 {
|
||||||
// Big endian is true
|
// Big endian is true
|
||||||
result.BigEndian = true
|
result.BigEndian = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &pfBoolByte); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pfBoolByte != 0 {
|
if pfBoolByte != 0 {
|
||||||
// True Color is true. So we also have to read all the color max & shifts.
|
// True Color is true. So we also have to read all the color max & shifts.
|
||||||
result.TrueColor = true
|
result.TrueColor = true
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.RedMax); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.GreenMax); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.BlueMax); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.RedShift); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.GreenShift); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil {
|
if err := binary.Read(brPF, binary.BigEndian, &result.BlueShift); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func writePixelFormat(format *common.PixelFormat) ([]byte, error) {
|
func writePixelFormat(format *common.PixelFormat) ([]byte, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
// Byte 1
|
// Byte 1
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.BPP); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte 2
|
// Byte 2
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.Depth); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var boolByte byte
|
var boolByte byte
|
||||||
if format.BigEndian {
|
if format.BigEndian {
|
||||||
boolByte = 1
|
boolByte = 1
|
||||||
} else {
|
} else {
|
||||||
boolByte = 0
|
boolByte = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte 3 (BigEndian)
|
// Byte 3 (BigEndian)
|
||||||
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if format.TrueColor {
|
if format.TrueColor {
|
||||||
boolByte = 1
|
boolByte = 1
|
||||||
} else {
|
} else {
|
||||||
boolByte = 0
|
boolByte = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// Byte 4 (TrueColor)
|
// Byte 4 (TrueColor)
|
||||||
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, boolByte); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have true color enabled then we have to fill in the rest of the
|
// If we have true color enabled then we have to fill in the rest of the
|
||||||
// structure with the color values.
|
// structure with the color values.
|
||||||
if format.TrueColor {
|
if format.TrueColor {
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.RedMax); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.GreenMax); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.BlueMax); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.RedShift); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.GreenShift); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil {
|
if err := binary.Write(&buf, binary.BigEndian, format.BlueShift); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return buf.Bytes()[0:16], nil
|
return buf.Bytes()[0:16], nil
|
||||||
}
|
}
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package vnc
|
package vnc
|
||||||
|
|
||||||
// ButtonMask represents a mask of pointer presses/releases.
|
// ButtonMask represents a mask of pointer presses/releases.
|
||||||
type ButtonMask uint8
|
type ButtonMask uint8
|
||||||
|
|
||||||
// All available button mask components.
|
// All available button mask components.
|
||||||
const (
|
const (
|
||||||
ButtonLeft ButtonMask = 1 << iota
|
ButtonLeft ButtonMask = 1 << iota
|
||||||
ButtonMiddle
|
ButtonMiddle
|
||||||
ButtonRight
|
ButtonRight
|
||||||
Button4
|
Button4
|
||||||
Button5
|
Button5
|
||||||
Button6
|
Button6
|
||||||
Button7
|
Button7
|
||||||
Button8
|
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
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) {
|
func (fbm *FramebufferUpdateMessage) Read(c *ClientConn, r *common.RfbReadHelper) (ServerMessage, error) {
|
||||||
|
|
||||||
// Read off the padding
|
// Read off the padding
|
||||||
var padding [1]byte
|
var padding [1]byte
|
||||||
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
||||||
@ -53,8 +54,9 @@ func (*FramebufferUpdateMessage) Read(c *ClientConn, r io.Reader) (ServerMessage
|
|||||||
rects := make([]common.Rectangle, numRects)
|
rects := make([]common.Rectangle, numRects)
|
||||||
for i := uint16(0); i < numRects; i++ {
|
for i := uint16(0); i < numRects; i++ {
|
||||||
fmt.Printf("###############rect################: %d\n", i)
|
fmt.Printf("###############rect################: %d\n", i)
|
||||||
var encodingType int32
|
|
||||||
|
|
||||||
|
var encodingType int32
|
||||||
|
r.SendRectSeparator(-1)
|
||||||
rect := &rects[i]
|
rect := &rects[i]
|
||||||
data := []interface{}{
|
data := []interface{}{
|
||||||
&rect.X,
|
&rect.X,
|
||||||
@ -108,7 +110,7 @@ func (*SetColorMapEntriesMessage) Type() uint8 {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*SetColorMapEntriesMessage) Read(c *ClientConn, r io.Reader) (ServerMessage, error) {
|
func (*SetColorMapEntriesMessage) Read(c *ClientConn, r *common.RfbReadHelper) (ServerMessage, error) {
|
||||||
// Read off the padding
|
// Read off the padding
|
||||||
var padding [1]byte
|
var padding [1]byte
|
||||||
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
||||||
@ -161,7 +163,7 @@ func (*BellMessage) Type() uint8 {
|
|||||||
return 2
|
return 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*BellMessage) Read(*ClientConn, io.Reader) (ServerMessage, error) {
|
func (*BellMessage) Read(*ClientConn, *common.RfbReadHelper) (ServerMessage, error) {
|
||||||
return new(BellMessage), nil
|
return new(BellMessage), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,22 +182,31 @@ func (*ServerCutTextMessage) Type() uint8 {
|
|||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*ServerCutTextMessage) Read(conn *ClientConn, r io.Reader) (ServerMessage, error) {
|
func (*ServerCutTextMessage) Read(conn *ClientConn, r *common.RfbReadHelper) (ServerMessage, error) {
|
||||||
|
//reader := common.RfbReadHelper{Reader: r}
|
||||||
|
|
||||||
// Read off the padding
|
// Read off the padding
|
||||||
var padding [1]byte
|
var padding [3]byte
|
||||||
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
if _, err := io.ReadFull(r, padding[:]); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
textLength, err := r.ReadUint32()
|
||||||
var textLength uint32
|
if err != nil {
|
||||||
if err := binary.Read(r, binary.BigEndian, &textLength); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
textBytes, err := r.ReadBytes(int(textLength))
|
||||||
textBytes := make([]uint8, textLength)
|
if err != nil {
|
||||||
if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
//var textLength uint32
|
||||||
|
// if err := binary.Read(r, binary.BigEndian, &textLength); err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// textBytes := make([]uint8, textLength)
|
||||||
|
// if err := binary.Read(r, binary.BigEndian, &textBytes); err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
return &ServerCutTextMessage{string(textBytes)}, nil
|
return &ServerCutTextMessage{string(textBytes)}, nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user