mirror of
https://github.com/amitbet/vncproxy.git
synced 2025-10-26 22:49:55 +00:00
Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1596f0daee | ||
|
|
7cecffecf2 | ||
|
|
f57b698430 | ||
|
|
e03c85f7ab | ||
|
|
931b08376b | ||
|
|
2ccc4009f4 | ||
|
|
6e1a343b5f | ||
|
|
446bc0e537 | ||
|
|
a870f3cbb9 | ||
|
|
f19a75749b | ||
|
|
02dde77daa | ||
|
|
b46f708726 | ||
|
|
f298567976 | ||
|
|
8543af35a4 | ||
|
|
f05c96d449 | ||
|
|
37e11cd72e | ||
|
|
47fefaacb6 | ||
|
|
7852f11ceb | ||
|
|
e06ad806db | ||
|
|
9fff2b46aa | ||
|
|
aff3a20d4a | ||
|
|
6f8d591789 | ||
|
|
c75e9ccc9c | ||
|
|
b448d0235a | ||
|
|
57fdfe914d | ||
|
|
538037aa8f |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -2,3 +2,8 @@
|
|||||||
*.debug
|
*.debug
|
||||||
*.test
|
*.test
|
||||||
debug
|
debug
|
||||||
|
/dist
|
||||||
|
vncproxy
|
||||||
|
prox
|
||||||
|
cmd
|
||||||
|
aa
|
||||||
43
README.md
43
README.md
@@ -1,30 +1,35 @@
|
|||||||
# VncProxy
|
# VncProxy
|
||||||
An RFB proxy, written in go that can save and replay FBS files
|
An RFB proxy, written in go that can save and replay FBS files
|
||||||
* supports all modern encodings & most useful pseudo-encodings
|
* Supports all modern encodings & most useful pseudo-encodings
|
||||||
* supports multiple VNC client connections & multi servers (chosen by sessionId)
|
* Supports multiple VNC client connections & multi servers (chosen by sessionId)
|
||||||
* supports being a "websockify" proxy (for web clients like NoVnc)
|
* Supports being a "websockify" proxy (for web clients like NoVnc)
|
||||||
* produces FBS files compatible with tightvnc player (while using tight's default 3Byte color format)
|
* Produces FBS files compatible with tightvnc player (while using tight's default 3Byte color format)
|
||||||
* can also be used as:
|
* Can also be used as:
|
||||||
* a screen recorder vnc-client
|
* A screen recorder vnc-client
|
||||||
* a replay server to show fbs recordings to connecting clients
|
* A replay server to show fbs recordings to connecting clients
|
||||||
|
|
||||||
**This is still a work in progress, and requires some error handling and general tidying up,
|
- Tested on tight encoding with:
|
||||||
but the code is already working (see main, proxy_test & player_test)**
|
|
||||||
- tested on tight encoding with:
|
|
||||||
- Tightvnc (client + java client + server)
|
- Tightvnc (client + java client + server)
|
||||||
- FBS player (tightVnc Java player)
|
- FBS player (tightVnc Java player)
|
||||||
- NoVnc(web client)
|
- NoVnc(web client) => use -wsPort to open a websocket
|
||||||
- ChickenOfTheVnc(client)
|
- ChickenOfTheVnc(client)
|
||||||
- VineVnc(server)
|
- VineVnc(server)
|
||||||
- TigerVnc(client)
|
- TigerVnc(client)
|
||||||
|
|
||||||
## Usage
|
|
||||||
**Some very usable cmdline executables are Coming Soon...**
|
|
||||||
|
|
||||||
Code samples can be found by looking at:
|
### Executables (see releases)
|
||||||
* main.go (fbs recording vnc client)
|
* proxy - the actual recording proxy, supports listening to tcp & ws ports and recording traffic to fbs files
|
||||||
* Connects, records to FBS file
|
* recorder - connects to a vnc server as a client and records the screen
|
||||||
* Programmed to quit after 10 seconds
|
* player - a toy player that will replay a given fbs file to all incoming connections
|
||||||
|
|
||||||
|
## Usage:
|
||||||
|
recorder -recDir=./recording.rbs -targHost=192.168.0.100 -targPort=5903 -targPass=@@@@@
|
||||||
|
player -fbsFile=./myrec.fbs -tcpPort=5905
|
||||||
|
proxy -recDir=./recordings/ -targHost=192.168.0.100 -targPort=5903 -targPass=@@@@@ -tcpPort=5903 -wsPort=5905 -vncPass=@!@!@!
|
||||||
|
|
||||||
|
### Code usage examples
|
||||||
|
* player/main.go (fbs recording vnc client)
|
||||||
|
* Connects as client, records to FBS file
|
||||||
* proxy/proxy_test.go (vnc proxy with recording)
|
* proxy/proxy_test.go (vnc proxy with recording)
|
||||||
* Listens to both Tcp and WS ports
|
* Listens to both Tcp and WS ports
|
||||||
* Proxies connections to a hard-coded localhost vnc server
|
* Proxies connections to a hard-coded localhost vnc server
|
||||||
@@ -56,4 +61,4 @@ The Recorder uses channels and runs in parallel to avoid hampering the communica
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
The code is based on several implementations of go-vnc including the original one by *Mitchell Hashimoto*, and the recentely active fork which belongs to *Vasiliy Tolstov*.
|
The code is based on several implementations of go-vnc including the original one by *Mitchell Hashimoto*, and the recentely active fork by *Vasiliy Tolstov*.
|
||||||
|
|||||||
52
build.sh
52
build.sh
@@ -1,4 +1,48 @@
|
|||||||
export GOOS="darwin"
|
#!/bin/bash
|
||||||
go build -o ./dist/recorder ./recorder/cmd
|
sum="sha1sum"
|
||||||
go build -o ./dist/player ./player/cmd
|
|
||||||
go build -o ./dist/proxy ./proxy/cmd
|
# VERSION=`date -u +%Y%m%d`
|
||||||
|
VERSION="v1.02"
|
||||||
|
LDFLAGS="-X main.VERSION=$VERSION -s -w"
|
||||||
|
GCFLAGS=""
|
||||||
|
|
||||||
|
if ! hash sha1sum 2>/dev/null; then
|
||||||
|
if ! hash shasum 2>/dev/null; then
|
||||||
|
echo "I can't see 'sha1sum' or 'shasum'"
|
||||||
|
echo "Please install one of them!"
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
sum="shasum"
|
||||||
|
fi
|
||||||
|
|
||||||
|
UPX=false
|
||||||
|
if hash upx 2>/dev/null; then
|
||||||
|
UPX=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
OSES=( linux darwin windows )
|
||||||
|
ARCHS=(amd64 386 )
|
||||||
|
for os in ${OSES[@]}; do
|
||||||
|
for arch in ${ARCHS[@]}; do
|
||||||
|
suffix=""
|
||||||
|
if [ "$os" == "windows" ]
|
||||||
|
then
|
||||||
|
suffix=".exe"
|
||||||
|
fi
|
||||||
|
|
||||||
|
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./dist/${os}_${arch}/recorder${suffix} ./recorder/cmd
|
||||||
|
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./dist/${os}_${arch}/player${suffix} ./player/cmd
|
||||||
|
env CGO_ENABLED=0 GOOS=$os GOARCH=$arch go build -ldflags "$LDFLAGS" -gcflags "$GCFLAGS" -o ./dist/${os}_${arch}/proxy${suffix} ./proxy/cmd
|
||||||
|
|
||||||
|
if $UPX; then upx -9 client_${os}_${arch}${suffix} server_${os}_${arch}${suffix};fi
|
||||||
|
# tar -zcf ./dist/vncproxy-${os}-${arch}-$VERSION.tar.gz ./dist/${os}_${arch}/proxy${suffix} ./dist/${os}_${arch}/player${suffix} ./dist/${os}_${arch}/recorder${suffix}
|
||||||
|
cd dist/${os}_${arch}/
|
||||||
|
zip -D -q -r ../vncproxy-${os}-${arch}-$VERSION.zip proxy${suffix} player${suffix} recorder${suffix}
|
||||||
|
cd ../..
|
||||||
|
$sum ./dist/vncproxy-${os}-${arch}-$VERSION.zip
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|||||||
@@ -116,9 +116,9 @@ func (c *ClientConn) Read(bytes []byte) (n int, err error) {
|
|||||||
return c.conn.Read(bytes)
|
return c.conn.Read(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClientConn) CurrentColorMap() *common.ColorMap {
|
// func (c *ClientConn) CurrentColorMap() *common.ColorMap {
|
||||||
return &c.ColorMap
|
// return &c.ColorMap
|
||||||
}
|
// }
|
||||||
|
|
||||||
// CutText tells the server that the client has new text in its cut buffer.
|
// CutText tells the server that the client has new text in its cut buffer.
|
||||||
// The text string MUST only contain Latin-1 characters. This encoding
|
// The text string MUST only contain Latin-1 characters. This encoding
|
||||||
@@ -506,7 +506,7 @@ func (c *ClientConn) mainLoop() {
|
|||||||
// Unsupported message type! Bad!
|
// Unsupported message type! Bad!
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
logger.Infof("ClientConn.MainLoop: got ServerMessage:%s", common.ServerMessageType(messageType))
|
logger.Debugf("ClientConn.MainLoop: got ServerMessage:%s", common.ServerMessageType(messageType))
|
||||||
reader.SendMessageStart(common.ServerMessageType(messageType))
|
reader.SendMessageStart(common.ServerMessageType(messageType))
|
||||||
reader.PublishBytes([]byte{byte(messageType)})
|
reader.PublishBytes([]byte{byte(messageType)})
|
||||||
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func (fbm *MsgFramebufferUpdate) Read(c common.IClientConn, r *common.RfbReadHel
|
|||||||
// We must always support the raw encoding
|
// We must always support the raw encoding
|
||||||
rawEnc := new(encodings.RawEncoding)
|
rawEnc := new(encodings.RawEncoding)
|
||||||
encMap[rawEnc.Type()] = rawEnc
|
encMap[rawEnc.Type()] = rawEnc
|
||||||
logger.Infof("MsgFramebufferUpdate.Read: numrects= %d", numRects)
|
logger.Debugf("MsgFramebufferUpdate.Read: numrects= %d", numRects)
|
||||||
|
|
||||||
rects := make([]common.Rectangle, numRects)
|
rects := make([]common.Rectangle, numRects)
|
||||||
for i := uint16(0); i < numRects; i++ {
|
for i := uint16(0); i < numRects; i++ {
|
||||||
@@ -90,7 +90,7 @@ func (fbm *MsgFramebufferUpdate) Read(c common.IClientConn, r *common.RfbReadHel
|
|||||||
|
|
||||||
encType := common.EncodingType(encodingTypeInt)
|
encType := common.EncodingType(encodingTypeInt)
|
||||||
|
|
||||||
logger.Infof("MsgFramebufferUpdate.Read: rect# %d, rect hdr data: enctype=%s, data: %s", i, encType, string(jBytes))
|
logger.Debugf("MsgFramebufferUpdate.Read: rect# %d, rect hdr data: enctype=%s, data: %s", i, encType, string(jBytes))
|
||||||
enc, supported := encMap[encodingTypeInt]
|
enc, supported := encMap[encodingTypeInt]
|
||||||
if supported {
|
if supported {
|
||||||
var err error
|
var err error
|
||||||
@@ -175,9 +175,9 @@ func (m *MsgSetColorMapEntries) Read(c common.IClientConn, r *common.RfbReadHelp
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmap := c.CurrentColorMap()
|
// cmap := c.CurrentColorMap()
|
||||||
// Update the connection's color map
|
// // Update the connection's color map
|
||||||
cmap[result.FirstColor+i] = *color
|
// cmap[result.FirstColor+i] = *color
|
||||||
}
|
}
|
||||||
r.SendMessageEnd(common.ServerMessageType(m.Type()))
|
r.SendMessageEnd(common.ServerMessageType(m.Type()))
|
||||||
return &result, nil
|
return &result, nil
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ const (
|
|||||||
KeyEventMsgType
|
KeyEventMsgType
|
||||||
PointerEventMsgType
|
PointerEventMsgType
|
||||||
ClientCutTextMsgType
|
ClientCutTextMsgType
|
||||||
ClientFenceMsgType = 248
|
ClientFenceMsgType = 248
|
||||||
|
QEMUExtendedKeyEventMsgType = 255
|
||||||
)
|
)
|
||||||
|
|
||||||
// Color represents a single color in a color map.
|
// Color represents a single color in a color map.
|
||||||
@@ -47,6 +48,8 @@ func (cmt ClientMessageType) String() string {
|
|||||||
return "FramebufferUpdateRequest"
|
return "FramebufferUpdateRequest"
|
||||||
case KeyEventMsgType:
|
case KeyEventMsgType:
|
||||||
return "KeyEvent"
|
return "KeyEvent"
|
||||||
|
case QEMUExtendedKeyEventMsgType:
|
||||||
|
return "QEMUExtendedKeyEvent"
|
||||||
case PointerEventMsgType:
|
case PointerEventMsgType:
|
||||||
return "PointerEvent"
|
return "PointerEvent"
|
||||||
case ClientCutTextMsgType:
|
case ClientCutTextMsgType:
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ type IServerConn interface {
|
|||||||
|
|
||||||
type IClientConn interface {
|
type IClientConn interface {
|
||||||
CurrentPixelFormat() *PixelFormat
|
CurrentPixelFormat() *PixelFormat
|
||||||
CurrentColorMap() *ColorMap
|
//CurrentColorMap() *ColorMap
|
||||||
Encodings() []IEncoding
|
Encodings() []IEncoding
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,6 +73,8 @@ func (enct EncodingType) String() string {
|
|||||||
return "EncJPEGQualityLevelPseudo1"
|
return "EncJPEGQualityLevelPseudo1"
|
||||||
case EncCursorPseudo:
|
case EncCursorPseudo:
|
||||||
return "EncCursorPseudo"
|
return "EncCursorPseudo"
|
||||||
|
case EncLedStatePseudo:
|
||||||
|
return "EncLedStatePseudo"
|
||||||
case EncDesktopSizePseudo:
|
case EncDesktopSizePseudo:
|
||||||
return "EncDesktopSizePseudo"
|
return "EncDesktopSizePseudo"
|
||||||
case EncLastRectPseudo:
|
case EncLastRectPseudo:
|
||||||
@@ -183,6 +185,7 @@ const (
|
|||||||
EncQEMUPointerMotionChangePseudo EncodingType = -257
|
EncQEMUPointerMotionChangePseudo EncodingType = -257
|
||||||
EncQEMUExtendedKeyEventPseudo EncodingType = -258
|
EncQEMUExtendedKeyEventPseudo EncodingType = -258
|
||||||
EncTightPng EncodingType = -260
|
EncTightPng EncodingType = -260
|
||||||
|
EncLedStatePseudo EncodingType = -261
|
||||||
EncExtendedDesktopSizePseudo EncodingType = -308
|
EncExtendedDesktopSizePseudo EncodingType = -308
|
||||||
EncXvpPseudo EncodingType = -309
|
EncXvpPseudo EncodingType = -309
|
||||||
EncFencePseudo EncodingType = -312
|
EncFencePseudo EncodingType = -312
|
||||||
|
|||||||
31
encodings/enc-led-state.go
Normal file
31
encodings/enc-led-state.go
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
package encodings
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"vncproxy/common"
|
||||||
|
"vncproxy/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type EncLedStatePseudo struct {
|
||||||
|
LedState uint8
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pe *EncLedStatePseudo) Type() int32 {
|
||||||
|
return int32(common.EncLedStatePseudo)
|
||||||
|
}
|
||||||
|
func (pe *EncLedStatePseudo) WriteTo(w io.Writer) (n int, err error) {
|
||||||
|
w.Write([]byte{pe.LedState})
|
||||||
|
return 1, nil
|
||||||
|
}
|
||||||
|
func (pe *EncLedStatePseudo) Read(pf *common.PixelFormat, rect *common.Rectangle, r *common.RfbReadHelper) (common.IEncoding, error) {
|
||||||
|
if rect.Width*rect.Height == 0 {
|
||||||
|
return pe, nil
|
||||||
|
}
|
||||||
|
u8, err := r.ReadUint8()
|
||||||
|
pe.LedState = u8
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("error while reading led state: ", err)
|
||||||
|
return pe, err
|
||||||
|
}
|
||||||
|
return pe, nil
|
||||||
|
}
|
||||||
@@ -142,7 +142,7 @@ func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *c
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
paletteSize := colorCount + 1 // add one more
|
paletteSize := int(colorCount) + 1 // add one more
|
||||||
logger.Debugf("handleTightFilters: ----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
|
logger.Debugf("handleTightFilters: ----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
|
||||||
//complete palette
|
//complete palette
|
||||||
_, err = r.ReadBytes(int(paletteSize) * bytesPixel)
|
_, err = r.ReadBytes(int(paletteSize) * bytesPixel)
|
||||||
@@ -155,7 +155,7 @@ func handleTightFilters(subencoding uint8, pixelFmt *common.PixelFormat, rect *c
|
|||||||
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) * int(rect.Height)
|
||||||
}
|
}
|
||||||
_, err = r.ReadTightData(dataLength)
|
_, err = r.ReadTightData(dataLength)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -4,6 +4,30 @@ import "fmt"
|
|||||||
|
|
||||||
var simpleLogger = SimpleLogger{LogLevelInfo}
|
var simpleLogger = SimpleLogger{LogLevelInfo}
|
||||||
|
|
||||||
|
func SetLogLevel(logLevel string) {
|
||||||
|
level := GetLogLevel(logLevel)
|
||||||
|
fmt.Println("Log level set to: ", logLevel)
|
||||||
|
simpleLogger = SimpleLogger{level}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLogLevel(logLevel string) LogLevel {
|
||||||
|
switch logLevel {
|
||||||
|
case "trace":
|
||||||
|
return LogLevelTrace
|
||||||
|
case "debug":
|
||||||
|
return LogLevelDebug
|
||||||
|
case "info":
|
||||||
|
return LogLevelInfo
|
||||||
|
case "warn":
|
||||||
|
return LogLevelWarn
|
||||||
|
case "error":
|
||||||
|
return LogLevelError
|
||||||
|
case "fatal":
|
||||||
|
return LogLevelFatal
|
||||||
|
}
|
||||||
|
return LogLevelInfo
|
||||||
|
}
|
||||||
|
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
Debug(v ...interface{})
|
Debug(v ...interface{})
|
||||||
Debugf(format string, v ...interface{})
|
Debugf(format string, v ...interface{})
|
||||||
@@ -127,6 +151,13 @@ func Debugf(format string, v ...interface{}) {
|
|||||||
simpleLogger.Debugf(format, v...)
|
simpleLogger.Debugf(format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Trace(v ...interface{}) {
|
||||||
|
simpleLogger.Trace(v...)
|
||||||
|
}
|
||||||
|
func Tracef(format string, v ...interface{}) {
|
||||||
|
simpleLogger.Tracef(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
func Info(v ...interface{}) {
|
func Info(v ...interface{}) {
|
||||||
simpleLogger.Info(v...)
|
simpleLogger.Info(v...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,10 @@ func main() {
|
|||||||
wsPort := flag.String("wsPort", "", "websocket port for player to listen to client connections")
|
wsPort := flag.String("wsPort", "", "websocket port for player to listen to client connections")
|
||||||
tcpPort := flag.String("tcpPort", "", "tcp port for player to listen to client connections")
|
tcpPort := flag.String("tcpPort", "", "tcp port for player to listen to client connections")
|
||||||
fbsFile := flag.String("fbsFile", "", "fbs file to serve to all connecting clients")
|
fbsFile := flag.String("fbsFile", "", "fbs file to serve to all connecting clients")
|
||||||
|
logLevel := flag.String("logLevel", "info", "change logging level")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
logger.SetLogLevel(*logLevel)
|
||||||
|
|
||||||
fmt.Println("**************************************************************************")
|
fmt.Println("**************************************************************************")
|
||||||
fmt.Println("*** This is a toy server that replays a single FBS file to all clients ***")
|
fmt.Println("*** This is a toy server that replays a single FBS file to all clients ***")
|
||||||
@@ -80,7 +82,7 @@ func main() {
|
|||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
url := "http://localhost:" + *wsPort + "/"
|
url := "http://0.0.0.0:" + *wsPort + "/"
|
||||||
|
|
||||||
if *tcpPort != "" && *wsPort != "" {
|
if *tcpPort != "" && *wsPort != "" {
|
||||||
logger.Infof("running two listeners: tcp port: %s, ws url: %s", *tcpPort, url)
|
logger.Infof("running two listeners: tcp port: %s, ws url: %s", *tcpPort, url)
|
||||||
|
|||||||
@@ -3,17 +3,25 @@ package player
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
||||||
|
"io"
|
||||||
"time"
|
"time"
|
||||||
"vncproxy/client"
|
"vncproxy/client"
|
||||||
"vncproxy/common"
|
"vncproxy/common"
|
||||||
|
|
||||||
"vncproxy/logger"
|
"vncproxy/logger"
|
||||||
"vncproxy/server"
|
"vncproxy/server"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type VncStreamFileReader interface {
|
||||||
|
io.Reader
|
||||||
|
CurrentTimestamp() int
|
||||||
|
ReadStartSession() (*common.ServerInit, error)
|
||||||
|
CurrentPixelFormat() *common.PixelFormat
|
||||||
|
Encodings() []common.IEncoding
|
||||||
|
}
|
||||||
|
|
||||||
type FBSPlayListener struct {
|
type FBSPlayListener struct {
|
||||||
Conn *server.ServerConn
|
Conn *server.ServerConn
|
||||||
Fbs *FbsReader
|
Fbs VncStreamFileReader
|
||||||
serverMessageMap map[uint8]common.ServerMessage
|
serverMessageMap map[uint8]common.ServerMessage
|
||||||
firstSegDone bool
|
firstSegDone bool
|
||||||
startTime int
|
startTime int
|
||||||
@@ -88,7 +96,7 @@ func (h *FBSPlayListener) sendFbsMessage() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
timeSinceStart := int(time.Now().UnixNano()/int64(time.Millisecond)) - h.startTime
|
timeSinceStart := int(time.Now().UnixNano()/int64(time.Millisecond)) - h.startTime
|
||||||
timeToSleep := fbs.currentTimestamp - timeSinceStart
|
timeToSleep := fbs.CurrentTimestamp() - timeSinceStart
|
||||||
if timeToSleep > 0 {
|
if timeToSleep > 0 {
|
||||||
time.Sleep(time.Duration(timeToSleep) * time.Millisecond)
|
time.Sleep(time.Duration(timeToSleep) * time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,10 @@ type FbsReader struct {
|
|||||||
encodings []common.IEncoding
|
encodings []common.IEncoding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (fbs *FbsReader) CurrentTimestamp() int {
|
||||||
|
return fbs.currentTimestamp
|
||||||
|
}
|
||||||
|
|
||||||
func (fbs *FbsReader) Read(p []byte) (n int, err error) {
|
func (fbs *FbsReader) Read(p []byte) (n int, err error) {
|
||||||
if fbs.buffer.Len() < len(p) {
|
if fbs.buffer.Len() < len(p) {
|
||||||
seg, err := fbs.ReadSegment()
|
seg, err := fbs.ReadSegment()
|
||||||
@@ -33,8 +37,9 @@ func (fbs *FbsReader) Read(p []byte) (n int, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (fbs *FbsReader) CurrentPixelFormat() *common.PixelFormat { return fbs.pixelFormat }
|
func (fbs *FbsReader) CurrentPixelFormat() *common.PixelFormat { return fbs.pixelFormat }
|
||||||
func (fbs *FbsReader) CurrentColorMap() *common.ColorMap { return &common.ColorMap{} }
|
|
||||||
func (fbs *FbsReader) Encodings() []common.IEncoding { return fbs.encodings }
|
//func (fbs *FbsReader) CurrentColorMap() *common.ColorMap { return &common.ColorMap{} }
|
||||||
|
func (fbs *FbsReader) Encodings() []common.IEncoding { return fbs.encodings }
|
||||||
|
|
||||||
func NewFbsReader(fbsFile string) (*FbsReader, error) {
|
func NewFbsReader(fbsFile string) (*FbsReader, error) {
|
||||||
|
|
||||||
@@ -53,6 +58,7 @@ func NewFbsReader(fbsFile string) (*FbsReader, error) {
|
|||||||
&encodings.TightEncoding{},
|
&encodings.TightEncoding{},
|
||||||
&encodings.TightPngEncoding{},
|
&encodings.TightPngEncoding{},
|
||||||
&encodings.EncCursorPseudo{},
|
&encodings.EncCursorPseudo{},
|
||||||
|
&encodings.EncLedStatePseudo{},
|
||||||
&encodings.RawEncoding{},
|
&encodings.RawEncoding{},
|
||||||
&encodings.RREEncoding{},
|
&encodings.RREEncoding{},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ func TestServer(t *testing.T) {
|
|||||||
&encodings.RawEncoding{},
|
&encodings.RawEncoding{},
|
||||||
&encodings.TightEncoding{},
|
&encodings.TightEncoding{},
|
||||||
&encodings.EncCursorPseudo{},
|
&encodings.EncCursorPseudo{},
|
||||||
|
&encodings.EncLedStatePseudo{},
|
||||||
//encodings.TightPngEncoding{},
|
//encodings.TightPngEncoding{},
|
||||||
&encodings.RREEncoding{},
|
&encodings.RREEncoding{},
|
||||||
&encodings.ZLibEncoding{},
|
&encodings.ZLibEncoding{},
|
||||||
|
|||||||
@@ -12,9 +12,12 @@ func main() {
|
|||||||
var vncPass = flag.String("vncPass", "", "password on incoming vnc connections to the proxy, defaults to no password")
|
var vncPass = flag.String("vncPass", "", "password on incoming vnc connections to the proxy, defaults to no password")
|
||||||
var recordDir = flag.String("recDir", "", "path to save FBS recordings WILL NOT RECORD if not defined.")
|
var recordDir = flag.String("recDir", "", "path to save FBS recordings WILL NOT RECORD if not defined.")
|
||||||
var targetVncPort = flag.String("targPort", "", "target vnc server port")
|
var targetVncPort = flag.String("targPort", "", "target vnc server port")
|
||||||
|
var targetVncHost = flag.String("targHost", "", "target vnc server host")
|
||||||
var targetVncPass = flag.String("targPass", "", "target vnc password")
|
var targetVncPass = flag.String("targPass", "", "target vnc password")
|
||||||
|
var logLevel = flag.String("logLevel", "info", "change logging level")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
logger.SetLogLevel(*logLevel)
|
||||||
|
|
||||||
if *tcpPort == "" && *wsPort == "" {
|
if *tcpPort == "" && *wsPort == "" {
|
||||||
logger.Error("no listening port defined")
|
logger.Error("no listening port defined")
|
||||||
@@ -35,13 +38,18 @@ func main() {
|
|||||||
logger.Warn("FBS recording is turned off")
|
logger.Warn("FBS recording is turned off")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tcpUrl := ""
|
||||||
|
if *tcpPort != "" {
|
||||||
|
tcpUrl = ":" + string(*tcpPort)
|
||||||
|
}
|
||||||
|
|
||||||
proxy := &proxy.VncProxy{
|
proxy := &proxy.VncProxy{
|
||||||
WsListeningUrl: "http://localhost:" + string(*wsPort) + "/", // empty = not listening on ws
|
WsListeningUrl: "http://0.0.0.0:" + string(*wsPort) + "/", // empty = not listening on ws
|
||||||
RecordingDir: *recordDir, //"/Users/amitbet/vncRec", // empty = no recording
|
RecordingDir: *recordDir, //"/Users/amitbet/vncRec", // empty = no recording
|
||||||
TcpListeningUrl: ":" + string(*tcpPort),
|
TcpListeningUrl: tcpUrl,
|
||||||
ProxyVncPassword: *vncPass, //empty = no auth
|
ProxyVncPassword: *vncPass, //empty = no auth
|
||||||
SingleSession: &proxy.VncSession{
|
SingleSession: &proxy.VncSession{
|
||||||
TargetHostname: "localhost",
|
TargetHostname: *targetVncHost,
|
||||||
TargetPort: *targetVncPort,
|
TargetPort: *targetVncPort,
|
||||||
TargetPassword: *targetVncPass, //"vncPass",
|
TargetPassword: *targetVncPass, //"vncPass",
|
||||||
ID: "dummySession",
|
ID: "dummySession",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ type ClientUpdater struct {
|
|||||||
|
|
||||||
// Consume recieves vnc-server-bound messages (Client messages) and updates the server part of the proxy
|
// Consume recieves vnc-server-bound messages (Client messages) and updates the server part of the proxy
|
||||||
func (cc *ClientUpdater) Consume(seg *common.RfbSegment) error {
|
func (cc *ClientUpdater) Consume(seg *common.RfbSegment) error {
|
||||||
//logger.Debugf("ClientUpdater.Consume (vnc-server-bound): got segment type=%s bytes: %v", seg.SegmentType, seg.Bytes)
|
logger.Tracef("ClientUpdater.Consume (vnc-server-bound): got segment type=%s bytes: %v", seg.SegmentType, seg.Bytes)
|
||||||
switch seg.SegmentType {
|
switch seg.SegmentType {
|
||||||
|
|
||||||
case common.SegmentFullyParsedClientMessage:
|
case common.SegmentFullyParsedClientMessage:
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func (vp *VncProxy) getProxySession(sessionId string) (*VncSession, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server.ServerConn) error {
|
func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server.ServerConn) error {
|
||||||
|
var err error
|
||||||
session, err := vp.getProxySession(sconn.SessionId)
|
session, err := vp.getProxySession(sconn.SessionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Proxy.newServerConnHandler can't get session: %d", sconn.SessionId)
|
logger.Errorf("Proxy.newServerConnHandler can't get session: %d", sconn.SessionId)
|
||||||
@@ -70,10 +70,11 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server
|
|||||||
}
|
}
|
||||||
|
|
||||||
var rec *listeners.Recorder
|
var rec *listeners.Recorder
|
||||||
|
|
||||||
if session.Type == SessionTypeRecordingProxy {
|
if session.Type == SessionTypeRecordingProxy {
|
||||||
recFile := "recording" + strconv.FormatInt(time.Now().Unix(), 10) + ".rbs"
|
recFile := "recording" + strconv.FormatInt(time.Now().Unix(), 10) + ".rbs"
|
||||||
recPath := path.Join(vp.RecordingDir, recFile)
|
recPath := path.Join(vp.RecordingDir, recFile)
|
||||||
rec, err := listeners.NewRecorder(recPath)
|
rec, err = listeners.NewRecorder(recPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("Proxy.newServerConnHandler can't open recorder save path: %s", recPath)
|
logger.Errorf("Proxy.newServerConnHandler can't open recorder save path: %s", recPath)
|
||||||
return err
|
return err
|
||||||
@@ -117,6 +118,7 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server
|
|||||||
&encodings.RawEncoding{},
|
&encodings.RawEncoding{},
|
||||||
&encodings.TightEncoding{},
|
&encodings.TightEncoding{},
|
||||||
&encodings.EncCursorPseudo{},
|
&encodings.EncCursorPseudo{},
|
||||||
|
&encodings.EncLedStatePseudo{},
|
||||||
&encodings.TightPngEncoding{},
|
&encodings.TightPngEncoding{},
|
||||||
&encodings.RREEncoding{},
|
&encodings.RREEncoding{},
|
||||||
&encodings.ZLibEncoding{},
|
&encodings.ZLibEncoding{},
|
||||||
@@ -173,7 +175,7 @@ func (vp *VncProxy) StartListening() {
|
|||||||
logger.Infof("running two listeners: tcp port: %s, ws url: %s", vp.TcpListeningUrl, vp.WsListeningUrl)
|
logger.Infof("running two listeners: tcp port: %s, ws url: %s", vp.TcpListeningUrl, vp.WsListeningUrl)
|
||||||
|
|
||||||
go server.WsServe(vp.WsListeningUrl, cfg)
|
go server.WsServe(vp.WsListeningUrl, cfg)
|
||||||
server.TcpServe(":"+vp.TcpListeningUrl, cfg)
|
server.TcpServe(vp.TcpListeningUrl, cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if vp.WsListeningUrl != "" {
|
if vp.WsListeningUrl != "" {
|
||||||
|
|||||||
@@ -6,15 +6,15 @@ func TestProxy(t *testing.T) {
|
|||||||
//create default session if required
|
//create default session if required
|
||||||
|
|
||||||
proxy := &VncProxy{
|
proxy := &VncProxy{
|
||||||
WsListeningUrl: "http://localhost:7777/", // empty = not listening on ws
|
WsListeningUrl: "http://0.0.0.0:7778/", // empty = not listening on ws
|
||||||
RecordingDir: "/Users/amitbet/vncRec", // empty = no recording
|
RecordingDir: "d:\\", // empty = no recording
|
||||||
TcpListeningUrl: ":5904",
|
TcpListeningUrl: ":5904",
|
||||||
//recordingDir: "C:\\vncRec", // empty = no recording
|
//RecordingDir: "C:\\vncRec", // empty = no recording
|
||||||
ProxyVncPassword: "1234", //empty = no auth
|
ProxyVncPassword: "1234", //empty = no auth
|
||||||
SingleSession: &VncSession{
|
SingleSession: &VncSession{
|
||||||
TargetHostname: "localhost",
|
TargetHostname: "192.168.1.101",
|
||||||
TargetPort: "5903",
|
TargetPort: "5901",
|
||||||
TargetPassword: "Ch_#!T@8",
|
TargetPassword: "123456",
|
||||||
ID: "dummySession",
|
ID: "dummySession",
|
||||||
Status: SessionStatusInit,
|
Status: SessionStatusInit,
|
||||||
Type: SessionTypeRecordingProxy,
|
Type: SessionTypeRecordingProxy,
|
||||||
|
|||||||
@@ -16,11 +16,20 @@ func main() {
|
|||||||
// var tcpPort = flag.String("tcpPort", "", "tcp port")
|
// var tcpPort = flag.String("tcpPort", "", "tcp port")
|
||||||
// var wsPort = flag.String("wsPort", "", "websocket port")
|
// var wsPort = flag.String("wsPort", "", "websocket port")
|
||||||
// var vncPass = flag.String("vncPass", "", "password on incoming vnc connections to the proxy, defaults to no password")
|
// var vncPass = flag.String("vncPass", "", "password on incoming vnc connections to the proxy, defaults to no password")
|
||||||
var recordDir = flag.String("recDir", "", "path to save FBS recordings WILL NOT RECORD IF EMPTY.")
|
var recordDir = flag.String("recFile", "", "FBS file to create, recordings WILL NOT RECORD IF EMPTY.")
|
||||||
var targetVncPort = flag.String("targPort", "", "target vnc server port")
|
var targetVncPort = flag.String("targPort", "", "target vnc server port")
|
||||||
var targetVncPass = flag.String("targPass", "", "target vnc password")
|
var targetVncPass = flag.String("targPass", "", "target vnc password")
|
||||||
|
var targetVncHost = flag.String("targHost", "localhost", "target vnc hostname")
|
||||||
|
var logLevel = flag.String("logLevel", "info", "change logging level")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
logger.SetLogLevel(*logLevel)
|
||||||
|
|
||||||
|
if *targetVncHost == "" {
|
||||||
|
logger.Error("no target vnc server host defined")
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if *targetVncPort == "" {
|
if *targetVncPort == "" {
|
||||||
logger.Error("no target vnc server port defined")
|
logger.Error("no target vnc server port defined")
|
||||||
@@ -33,10 +42,12 @@ func main() {
|
|||||||
}
|
}
|
||||||
if *recordDir == "" {
|
if *recordDir == "" {
|
||||||
logger.Warn("FBS recording is turned off")
|
logger.Warn("FBS recording is turned off")
|
||||||
|
} else {
|
||||||
|
logger.Infof("Recording rfb stream into file: '%s'", *recordDir)
|
||||||
}
|
}
|
||||||
|
|
||||||
//nc, err := net.Dial("tcp", "192.168.1.101:5903")
|
//nc, err := net.Dial("tcp", "192.168.1.101:5903")
|
||||||
nc, err := net.Dial("tcp", "localhost:"+*targetVncPort)
|
nc, err := net.Dial("tcp", *targetVncHost+":"+*targetVncPort)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("error connecting to vnc server: %s", err)
|
logger.Errorf("error connecting to vnc server: %s", err)
|
||||||
@@ -74,9 +85,9 @@ func main() {
|
|||||||
encs := []common.IEncoding{
|
encs := []common.IEncoding{
|
||||||
&encodings.TightEncoding{},
|
&encodings.TightEncoding{},
|
||||||
//&encodings.TightPngEncoding{},
|
//&encodings.TightPngEncoding{},
|
||||||
//rre := encodings.RREEncoding{},
|
//&encodings.RREEncoding{},
|
||||||
//zlib := encodings.ZLibEncoding{},
|
//&encodings.ZLibEncoding{},
|
||||||
//zrle := encodings.ZRLEEncoding{},
|
//&encodings.ZRLEEncoding{},
|
||||||
//&encodings.CopyRectEncoding{},
|
//&encodings.CopyRectEncoding{},
|
||||||
//coRRE := encodings.CoRREEncoding{},
|
//coRRE := encodings.CoRREEncoding{},
|
||||||
//hextile := encodings.HextileEncoding{},
|
//hextile := encodings.HextileEncoding{},
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ func NewRecorder(saveFilePath string) (*Recorder, error) {
|
|||||||
|
|
||||||
rec.maxWriteSize = 65535
|
rec.maxWriteSize = 65535
|
||||||
|
|
||||||
rec.writer, err = os.OpenFile(saveFilePath, os.O_RDWR|os.O_CREATE, 0755)
|
rec.writer, err = os.OpenFile(saveFilePath, os.O_RDWR|os.O_CREATE, 0644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Errorf("unable to open file: %s, error: %v", saveFilePath, err)
|
logger.Errorf("unable to open file: %s, error: %v", saveFilePath, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -165,6 +165,36 @@ func (msg *MsgKeyEvent) Write(c io.Writer) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MsgKeyEvent holds the wire format message.
|
||||||
|
type MsgQEMUExtKeyEvent struct {
|
||||||
|
SubmessageType uint8 // submessage type
|
||||||
|
DownFlag uint16 // down-flag
|
||||||
|
KeySym Key // key symbol
|
||||||
|
KeyCode uint32 // scan code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*MsgQEMUExtKeyEvent) Type() common.ClientMessageType {
|
||||||
|
return common.QEMUExtendedKeyEventMsgType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*MsgQEMUExtKeyEvent) Read(c io.Reader) (common.ClientMessage, error) {
|
||||||
|
msg := MsgKeyEvent{}
|
||||||
|
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *MsgQEMUExtKeyEvent) Write(c io.Writer) error {
|
||||||
|
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := binary.Write(c, binary.BigEndian, msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// PointerEventMessage holds the wire format message.
|
// PointerEventMessage holds the wire format message.
|
||||||
type MsgPointerEvent struct {
|
type MsgPointerEvent struct {
|
||||||
Mask uint8 // button-mask
|
Mask uint8 // button-mask
|
||||||
@@ -280,3 +310,34 @@ func (msg *MsgClientCutText) Write(c io.Writer) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MsgClientQemuExtendedKey holds the wire format message, for qemu keys
|
||||||
|
type MsgClientQemuExtendedKey struct {
|
||||||
|
SubType uint8 // sub type
|
||||||
|
IsDown uint16 // button down indicator
|
||||||
|
KeySym uint32 // key symbol
|
||||||
|
KeyCode uint32 // key code
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*MsgClientQemuExtendedKey) Type() common.ClientMessageType {
|
||||||
|
return common.QEMUExtendedKeyEventMsgType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*MsgClientQemuExtendedKey) Read(c io.Reader) (common.ClientMessage, error) {
|
||||||
|
msg := MsgClientQemuExtendedKey{}
|
||||||
|
|
||||||
|
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &msg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (msg *MsgClientQemuExtendedKey) Write(c io.Writer) error {
|
||||||
|
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := binary.Write(c, binary.BigEndian, msg); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func ServerSecurityHandler(cfg *ServerConfig, c *ServerConn) error {
|
|||||||
|
|
||||||
sType, ok := secTypes[secType]
|
sType, ok := secTypes[secType]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("server type %d not implemented")
|
return fmt.Errorf("server type %d not implemented", secType)
|
||||||
}
|
}
|
||||||
|
|
||||||
var authCode uint32
|
var authCode uint32
|
||||||
@@ -135,7 +135,7 @@ func ServerServerInitHandler(cfg *ServerConfig, c *ServerConn) error {
|
|||||||
NameLength: uint32(len(cfg.DesktopName)),
|
NameLength: uint32(len(cfg.DesktopName)),
|
||||||
NameText: []byte(cfg.DesktopName),
|
NameText: []byte(cfg.DesktopName),
|
||||||
}
|
}
|
||||||
logger.Infof("Server.ServerServerInitHandler initMessage: %v", srvInit)
|
logger.Debugf("Server.ServerServerInitHandler initMessage: %v", srvInit)
|
||||||
if err := binary.Write(c, binary.BigEndian, srvInit.FBWidth); err != nil {
|
if err := binary.Write(c, binary.BigEndian, srvInit.FBWidth); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,16 +168,17 @@ func (c *ServerConn) handle() error {
|
|||||||
default:
|
default:
|
||||||
var messageType common.ClientMessageType
|
var messageType common.ClientMessageType
|
||||||
if err := binary.Read(c, binary.BigEndian, &messageType); err != nil {
|
if err := binary.Read(c, binary.BigEndian, &messageType); err != nil {
|
||||||
logger.Errorf("IServerConn.handle error: %v", err)
|
logger.Errorf("ServerConn.handle error: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
logger.Debugf("ServerConn.handle: got messagetype, %d", messageType)
|
||||||
msg, ok := clientMessages[messageType]
|
msg, ok := clientMessages[messageType]
|
||||||
|
logger.Debugf("ServerConn.handle: found message type, %v", ok)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("IServerConn.Handle: unsupported message-type: %v", messageType)
|
logger.Errorf("ServerConn.handle: unsupported message-type: %v", messageType)
|
||||||
}
|
}
|
||||||
|
|
||||||
parsedMsg, err := msg.Read(c)
|
parsedMsg, err := msg.Read(c)
|
||||||
|
logger.Debugf("ServerConn.handle: got parsed messagetype, %v", parsedMsg)
|
||||||
//update connection for pixel format / color map changes
|
//update connection for pixel format / color map changes
|
||||||
switch parsedMsg.Type() {
|
switch parsedMsg.Type() {
|
||||||
case common.SetPixelFormatMsgType:
|
case common.SetPixelFormatMsgType:
|
||||||
@@ -196,7 +197,7 @@ func (c *ServerConn) handle() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Infof("IServerConn.Handle got ClientMessage: %s, %v", parsedMsg.Type(), parsedMsg)
|
logger.Debugf("IServerConn.Handle got ClientMessage: %s, %v", parsedMsg.Type(), parsedMsg)
|
||||||
//TODO: treat set encodings by allowing only supported encoding in proxy configurations
|
//TODO: treat set encodings by allowing only supported encoding in proxy configurations
|
||||||
//// if parsedMsg.Type() == common.SetEncodingsMsgType{
|
//// if parsedMsg.Type() == common.SetEncodingsMsgType{
|
||||||
//// c.cfg.Encodings
|
//// c.cfg.Encodings
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ var DefaultClientMessages = []common.ClientMessage{
|
|||||||
&MsgKeyEvent{},
|
&MsgKeyEvent{},
|
||||||
&MsgPointerEvent{},
|
&MsgPointerEvent{},
|
||||||
&MsgClientCutText{},
|
&MsgClientCutText{},
|
||||||
|
&MsgClientQemuExtendedKey{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// FramebufferUpdate holds a FramebufferUpdate wire format message.
|
// FramebufferUpdate holds a FramebufferUpdate wire format message.
|
||||||
|
|||||||
9
todo.md
9
todo.md
@@ -6,4 +6,11 @@
|
|||||||
* code stuff:
|
* code stuff:
|
||||||
* move encodings to be on the framebufferupdate message object
|
* move encodings to be on the framebufferupdate message object
|
||||||
* clear all messages read functions from updating stuff, move modification logic to another listener
|
* clear all messages read functions from updating stuff, move modification logic to another listener
|
||||||
* message read function should accept only an io.Reader, move read helper logic (readuint8) to an actual helper class
|
* message read function should accept only an io.Reader, move read helper logic (readuint8) to an actual helper class
|
||||||
|
* new recording format:
|
||||||
|
* rfb extension
|
||||||
|
* save FBResponse messages with additional fields
|
||||||
|
* timestamp
|
||||||
|
* is incremental
|
||||||
|
* size (bytes)
|
||||||
|
* have a header which contains an index of messages, holding timestamps & file positions for seeking
|
||||||
|
|||||||
Reference in New Issue
Block a user