mirror of
https://github.com/amitbet/vncproxy.git
synced 2025-08-10 18:11:51 +00:00
some more house cleaning, updated license & docs
This commit is contained in:
parent
fa61227d89
commit
01fd227088
27
LICENSE
27
LICENSE
@ -19,3 +19,30 @@ 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.
|
||||||
|
|
||||||
|
|
||||||
|
Based on code collected from various go-vnc implementations:
|
||||||
|
------------------------------------------------------------
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2013 Mitchell Hashimoto
|
||||||
|
Copyright (c) 2016-2017 Kate Ward
|
||||||
|
Copyright (c) 2017 Vasiliy Tolstov
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
24
README.md
24
README.md
@ -1,7 +1,23 @@
|
|||||||
# VncProxy
|
# VncProxy
|
||||||
A RFB proxy, written in go that can save and replay RBS files
|
An RFB proxy, written in go that can save and replay FBS files
|
||||||
|
* supports all modern encodings
|
||||||
|
* supports regular and sockified (noVnc) server connnections
|
||||||
|
* produces FBS files compatible with tightvnc player
|
||||||
|
* can also be used as:
|
||||||
|
* a screen recorder vnc-client
|
||||||
|
* a replay server to show fbs recordings to connecting clients
|
||||||
|
|
||||||
Still a work in progress, but the client side already includes all the required encodings
|
This is still a work in progress, and requires some error handling and general tidying up,
|
||||||
understanding the RemoteFrameBuffer protocol is important since we need to save the frameResponses with timestamps
|
but the code is already working (see server_test, proxy_test & player_test)
|
||||||
|
- tested on tight encoding with: tightvnc (client+server), noVnc(web client), chickenOfTheVnc(client), vineVnc(server), tigerVnc(client)
|
||||||
|
|
||||||
some server code will be added shortly, with the proxying logics.
|
## **Architecture**
|
||||||
|
**Proxy**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Player**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
The code is based on several implementations of go-vnc including the original one by Mitchell Hashimoto, and the very active fork which belongs to Vasiliy Tolstov.
|
35
architecture/plantUml.wsd
Normal file
35
architecture/plantUml.wsd
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
@startuml
|
||||||
|
Title Vncproxy Architecture
|
||||||
|
State VncProxy{
|
||||||
|
State ClientPart
|
||||||
|
State ServerPart
|
||||||
|
state FbsRecorder
|
||||||
|
}
|
||||||
|
State VncClient
|
||||||
|
State VncServer
|
||||||
|
|
||||||
|
VncClient -right-> ServerPart
|
||||||
|
ServerPart -left-> VncClient
|
||||||
|
VncServer -left-> ClientPart
|
||||||
|
ClientPart -right-> VncServer
|
||||||
|
ClientPart -left-> ServerPart
|
||||||
|
ServerPart -right-> ClientPart
|
||||||
|
|
||||||
|
ClientPart -down-> FbsRecorder
|
||||||
|
ServerPart -down-> FbsRecorder
|
||||||
|
@enduml
|
||||||
|
|
||||||
|
|
||||||
|
@startuml
|
||||||
|
Title Vncproxy Fbs Player
|
||||||
|
State VncProxy{
|
||||||
|
|
||||||
|
State ServerPart
|
||||||
|
state FbsPlayer
|
||||||
|
}
|
||||||
|
State VncClient
|
||||||
|
VncClient -left-> ServerPart
|
||||||
|
ServerPart -right-> VncClient
|
||||||
|
|
||||||
|
FbsPlayer -up-> ServerPart
|
||||||
|
@enduml
|
BIN
architecture/player-arch.png
Normal file
BIN
architecture/player-arch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
BIN
architecture/proxy-arch.png
Normal file
BIN
architecture/proxy-arch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
@ -1,16 +0,0 @@
|
|||||||
# VNC Library for Go
|
|
||||||
|
|
||||||
go-vnc is a VNC library for Go, initially supporting VNC clients but
|
|
||||||
with the goal of eventually implementing a VNC server.
|
|
||||||
|
|
||||||
This library implements [RFC 6143](http://tools.ietf.org/html/rfc6143).
|
|
||||||
|
|
||||||
## Usage & Installation
|
|
||||||
|
|
||||||
The library is installable via standard `go get`. The package name is `vnc`.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ go get github.com/mitchellh/go-vnc
|
|
||||||
```
|
|
||||||
|
|
||||||
Documentation is available on GoDoc: http://godoc.org/github.com/mitchellh/go-vnc
|
|
@ -68,13 +68,6 @@ type ClientConfig struct {
|
|||||||
// disconnected when a connection is established to the VNC server.
|
// disconnected when a connection is established to the VNC server.
|
||||||
Exclusive bool
|
Exclusive bool
|
||||||
|
|
||||||
// The channel that all messages received from the server will be
|
|
||||||
// sent on. If the channel blocks, then the goroutine reading data
|
|
||||||
// from the VNC server may block indefinitely. It is up to the user
|
|
||||||
// of the library to ensure that this channel is properly read.
|
|
||||||
// If this is not set, then all messages will be discarded.
|
|
||||||
ServerMessageCh chan<- common.ServerMessage
|
|
||||||
|
|
||||||
// A slice of supported messages that can be read from the server.
|
// A slice of supported messages that can be read from the server.
|
||||||
// This only needs to contain NEW server messages, and doesn't
|
// This only needs to contain NEW server messages, and doesn't
|
||||||
// need to explicitly contain the RFC-required messages.
|
// need to explicitly contain the RFC-required messages.
|
||||||
@ -523,12 +516,6 @@ func (c *ClientConn) mainLoop() {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
logger.Debugf("ClientConn.MainLoop: read & parsed ServerMessage:%d, %s", parsedMsg.Type(), parsedMsg)
|
logger.Debugf("ClientConn.MainLoop: read & parsed ServerMessage:%d, %s", parsedMsg.Type(), parsedMsg)
|
||||||
|
|
||||||
if c.config.ServerMessageCh == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
c.config.ServerMessageCh <- parsedMsg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
14
main.go
14
main.go
@ -21,16 +21,15 @@ func main() {
|
|||||||
var noauth client.ClientAuthNone
|
var noauth client.ClientAuthNone
|
||||||
authArr := []client.ClientAuth{&client.PasswordAuth{Password: "Ch_#!T@8"}, &noauth}
|
authArr := []client.ClientAuth{&client.PasswordAuth{Password: "Ch_#!T@8"}, &noauth}
|
||||||
|
|
||||||
vncSrvMessagesChan := make(chan common.ServerMessage)
|
//vncSrvMessagesChan := make(chan common.ServerMessage)
|
||||||
|
|
||||||
//rec := listeners.NewRecorder("c:/Users/betzalel/recording.rbs")
|
//rec := listeners.NewRecorder("c:/Users/betzalel/recording.rbs")
|
||||||
rec := listeners.NewRecorder("/Users/amitbet/vncRec/recording.rbs")
|
rec := listeners.NewRecorder("/Users/amitbet/vncRec/recording.rbs")
|
||||||
|
|
||||||
clientConn, err := client.NewClientConn(nc,
|
clientConn, err := client.NewClientConn(nc,
|
||||||
&client.ClientConfig{
|
&client.ClientConfig{
|
||||||
Auth: authArr,
|
Auth: authArr,
|
||||||
ServerMessageCh: vncSrvMessagesChan,
|
Exclusive: true,
|
||||||
Exclusive: true,
|
|
||||||
})
|
})
|
||||||
|
|
||||||
clientConn.Listeners.AddListener(rec)
|
clientConn.Listeners.AddListener(rec)
|
||||||
@ -91,8 +90,11 @@ func main() {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
//go func() {
|
//go func() {
|
||||||
for msg := range vncSrvMessagesChan {
|
// for msg := range vncSrvMessagesChan {
|
||||||
logger.Debugf("message type: %d, content: %v\n", msg.Type(), msg)
|
// logger.Debugf("message type: %d, content: %v\n", msg.Type(), msg)
|
||||||
|
// }
|
||||||
|
for {
|
||||||
|
time.Sleep(time.Minute)
|
||||||
}
|
}
|
||||||
//}()
|
//}()
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package player
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"log"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"vncproxy/client"
|
"vncproxy/client"
|
||||||
@ -104,20 +103,17 @@ func loadFbsFile(filename string, conn *server.ServerConn) (*FbsReader, error) {
|
|||||||
func TestServer(t *testing.T) {
|
func TestServer(t *testing.T) {
|
||||||
|
|
||||||
//chServer := make(chan common.ClientMessage)
|
//chServer := make(chan common.ClientMessage)
|
||||||
chClient := make(chan common.ServerMessage)
|
//chClient := make(chan common.ServerMessage)
|
||||||
|
|
||||||
cfg := &server.ServerConfig{
|
cfg := &server.ServerConfig{
|
||||||
//SecurityHandlers: []SecurityHandler{&ServerAuthNone{}, &ServerAuthVNC{}},
|
//SecurityHandlers: []SecurityHandler{&ServerAuthNone{}, &ServerAuthVNC{}},
|
||||||
SecurityHandlers: []server.SecurityHandler{&server.ServerAuthNone{}},
|
SecurityHandlers: []server.SecurityHandler{&server.ServerAuthNone{}},
|
||||||
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
|
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
|
||||||
PixelFormat: common.NewPixelFormat(32),
|
PixelFormat: common.NewPixelFormat(32),
|
||||||
//ClientMessageCh: chServer,
|
ClientMessages: server.DefaultClientMessages,
|
||||||
//ServerMessageCh: chClient,
|
DesktopName: []byte("workDesk"),
|
||||||
ClientMessages: server.DefaultClientMessages,
|
Height: uint16(768),
|
||||||
DesktopName: []byte("workDesk"),
|
Width: uint16(1024),
|
||||||
Height: uint16(768),
|
|
||||||
Width: uint16(1024),
|
|
||||||
//NewConnHandler: serverNewConnHandler,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.NewConnHandler = func(cfg *server.ServerConfig, conn *server.ServerConn) error {
|
cfg.NewConnHandler = func(cfg *server.ServerConfig, conn *server.ServerConn) error {
|
||||||
@ -134,15 +130,8 @@ func TestServer(t *testing.T) {
|
|||||||
go server.WsServe(url, cfg)
|
go server.WsServe(url, cfg)
|
||||||
go server.TcpServe(":5904", cfg)
|
go server.TcpServe(":5904", cfg)
|
||||||
|
|
||||||
// Process messages coming in on the ClientMessage channel.
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
msg := <-chClient
|
time.Sleep(time.Minute)
|
||||||
switch msg.Type() {
|
|
||||||
default:
|
|
||||||
log.Printf("Received message type:%v msg:%v\n", msg.Type(), msg)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,11 @@ func (vp *VncProxy) createClientConnection(targetServerUrl string) (*client.Clie
|
|||||||
var noauth client.ClientAuthNone
|
var noauth client.ClientAuthNone
|
||||||
authArr := []client.ClientAuth{&client.PasswordAuth{Password: vp.targetServersPassword}, &noauth}
|
authArr := []client.ClientAuth{&client.PasswordAuth{Password: vp.targetServersPassword}, &noauth}
|
||||||
|
|
||||||
vncSrvMessagesChan := make(chan common.ServerMessage)
|
//vncSrvMessagesChan := make(chan common.ServerMessage)
|
||||||
|
|
||||||
clientConn, err := client.NewClientConn(nc,
|
clientConn, err := client.NewClientConn(nc,
|
||||||
&client.ClientConfig{
|
&client.ClientConfig{
|
||||||
Auth: authArr,
|
Auth: authArr,
|
||||||
ServerMessageCh: vncSrvMessagesChan,
|
|
||||||
Exclusive: true,
|
Exclusive: true,
|
||||||
})
|
})
|
||||||
//clientConn.Listener = split
|
//clientConn.Listener = split
|
||||||
@ -145,7 +144,6 @@ func (vp *VncProxy) StartListening() {
|
|||||||
SecurityHandlers: secHandlers,
|
SecurityHandlers: secHandlers,
|
||||||
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
|
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
|
||||||
PixelFormat: common.NewPixelFormat(32),
|
PixelFormat: common.NewPixelFormat(32),
|
||||||
//ServerMessageCh: chClient,
|
|
||||||
ClientMessages: server.DefaultClientMessages,
|
ClientMessages: server.DefaultClientMessages,
|
||||||
DesktopName: []byte("workDesk"),
|
DesktopName: []byte("workDesk"),
|
||||||
Height: uint16(768),
|
Height: uint16(768),
|
||||||
|
@ -12,8 +12,7 @@ import (
|
|||||||
type ServerConn struct {
|
type ServerConn struct {
|
||||||
c io.ReadWriter
|
c io.ReadWriter
|
||||||
cfg *ServerConfig
|
cfg *ServerConfig
|
||||||
//br *bufio.Reader
|
|
||||||
//bw *bufio.Writer
|
|
||||||
protocol string
|
protocol string
|
||||||
m sync.Mutex
|
m sync.Mutex
|
||||||
// If the pixel format uses a color map, then this is the color
|
// If the pixel format uses a color map, then this is the color
|
||||||
@ -96,25 +95,10 @@ func (c *ServerConn) SetProtoVersion(pv string) {
|
|||||||
c.protocol = pv
|
c.protocol = pv
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (c *ServerConn) Flush() error {
|
|
||||||
// // c.m.Lock()
|
|
||||||
// // defer c.m.Unlock()
|
|
||||||
// return c.bw.Flush()
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (c *ServerConn) Close() error {
|
func (c *ServerConn) Close() error {
|
||||||
return c.c.(io.ReadWriteCloser).Close()
|
return c.c.(io.ReadWriteCloser).Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
func (c *ServerConn) Input() chan *ServerMessage {
|
|
||||||
return c.cfg.ServerMessageCh
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *ServerConn) Output() chan *ClientMessage {
|
|
||||||
return c.cfg.ClientMessageCh
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func (c *ServerConn) Read(buf []byte) (int, error) {
|
func (c *ServerConn) Read(buf []byte) (int, error) {
|
||||||
return c.c.Read(buf)
|
return c.c.Read(buf)
|
||||||
}
|
}
|
||||||
@ -157,8 +141,6 @@ func (c *ServerConn) Height() uint16 {
|
|||||||
func (c *ServerConn) Protocol() string {
|
func (c *ServerConn) Protocol() string {
|
||||||
return c.protocol
|
return c.protocol
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO send desktopsize pseudo encoding
|
|
||||||
func (c *ServerConn) SetWidth(w uint16) {
|
func (c *ServerConn) SetWidth(w uint16) {
|
||||||
c.fbWidth = w
|
c.fbWidth = w
|
||||||
}
|
}
|
||||||
@ -167,42 +149,19 @@ func (c *ServerConn) SetHeight(h uint16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *ServerConn) handle() error {
|
func (c *ServerConn) handle() error {
|
||||||
//var err error
|
|
||||||
//var wg sync.WaitGroup
|
|
||||||
|
|
||||||
//defer c.Close()
|
|
||||||
defer func() {
|
defer func() {
|
||||||
c.Listeners.Consume(&common.RfbSegment{
|
c.Listeners.Consume(&common.RfbSegment{
|
||||||
SegmentType: common.SegmentConnectionClosed,
|
SegmentType: common.SegmentConnectionClosed,
|
||||||
})
|
})
|
||||||
}()
|
}()
|
||||||
|
|
||||||
//create a map of all message types
|
//create a map of all message types
|
||||||
clientMessages := make(map[common.ClientMessageType]common.ClientMessage)
|
clientMessages := make(map[common.ClientMessageType]common.ClientMessage)
|
||||||
for _, m := range c.cfg.ClientMessages {
|
for _, m := range c.cfg.ClientMessages {
|
||||||
clientMessages[m.Type()] = m
|
clientMessages[m.Type()] = m
|
||||||
}
|
}
|
||||||
//wg.Add(2)
|
|
||||||
|
|
||||||
// server
|
|
||||||
// go func() error {
|
|
||||||
// //defer wg.Done()
|
|
||||||
// for {
|
|
||||||
// select {
|
|
||||||
// case msg := <-c.cfg.ServerMessageCh:
|
|
||||||
// logger.Debugf("%v", msg)
|
|
||||||
// // if err = msg.Write(c); err != nil {
|
|
||||||
// // return err
|
|
||||||
// // }
|
|
||||||
// case <-c.quit:
|
|
||||||
// c.Close()
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }()
|
|
||||||
|
|
||||||
// client
|
|
||||||
//go func() error {
|
|
||||||
//defer wg.Done()
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-c.quit:
|
case <-c.quit:
|
||||||
@ -238,9 +197,8 @@ func (c *ServerConn) handle() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//logger.Debugf("ServerConn.Handle got client message, type=%s", parsedMsg.Type())
|
|
||||||
logger.Debugf("ServerConn.Handle got ClientMessage: %s, %v", parsedMsg.Type(), parsedMsg)
|
logger.Debugf("ServerConn.Handle got ClientMessage: %s, %v", parsedMsg.Type(), parsedMsg)
|
||||||
//parsedMsg.Type()
|
|
||||||
seg := &common.RfbSegment{
|
seg := &common.RfbSegment{
|
||||||
SegmentType: common.SegmentFullyParsedClientMessage,
|
SegmentType: common.SegmentFullyParsedClientMessage,
|
||||||
Message: parsedMsg,
|
Message: parsedMsg,
|
||||||
@ -250,12 +208,6 @@ func (c *ServerConn) handle() error {
|
|||||||
logger.Errorf("ServerConn.Handle: listener consume err %s", err.Error())
|
logger.Errorf("ServerConn.Handle: listener consume err %s", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//c.cfg.ClientMessageCh <- parsedMsg
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//}()
|
|
||||||
|
|
||||||
//wg.Wait()
|
|
||||||
//return nil
|
|
||||||
}
|
}
|
||||||
|
@ -17,62 +17,32 @@ var DefaultClientMessages = []common.ClientMessage{
|
|||||||
&ClientCutText{},
|
&ClientCutText{},
|
||||||
}
|
}
|
||||||
|
|
||||||
//var _ ServerConn = (*ServerConn)(nil)
|
|
||||||
|
|
||||||
// ServerMessage represents a Client-to-Server RFB message type.
|
|
||||||
// type ServerMessageType uint8
|
|
||||||
|
|
||||||
// //go:generate stringer -type=ServerMessageType
|
|
||||||
|
|
||||||
// // Client-to-Server message types.
|
|
||||||
// const (
|
|
||||||
// FramebufferUpdateMsgType ServerMessageType = iota
|
|
||||||
// SetColorMapEntriesMsgType
|
|
||||||
// BellMsgType
|
|
||||||
// ServerCutTextMsgType
|
|
||||||
// )
|
|
||||||
|
|
||||||
// FramebufferUpdate holds a FramebufferUpdate wire format message.
|
// FramebufferUpdate holds a FramebufferUpdate wire format message.
|
||||||
type FramebufferUpdate struct {
|
type FramebufferUpdate struct {
|
||||||
_ [1]byte // pad
|
_ [1]byte // padding
|
||||||
NumRect uint16 // number-of-rectangles
|
NumRect uint16 // number-of-rectangles
|
||||||
Rects []*common.Rectangle // rectangles
|
Rects []*common.Rectangle // rectangles
|
||||||
}
|
}
|
||||||
|
|
||||||
// func (*FramebufferUpdate) Type() ServerMessageType {
|
|
||||||
// return FramebufferUpdateMsgType
|
|
||||||
// }
|
|
||||||
|
|
||||||
type ServerHandler func(*ServerConfig, *ServerConn) error
|
type ServerHandler func(*ServerConfig, *ServerConn) error
|
||||||
|
|
||||||
type ServerConfig struct {
|
type ServerConfig struct {
|
||||||
//VersionHandler ServerHandler
|
|
||||||
//SecurityHandler ServerHandler
|
|
||||||
SecurityHandlers []SecurityHandler
|
SecurityHandlers []SecurityHandler
|
||||||
//ClientInitHandler ServerHandler
|
Encodings []common.Encoding
|
||||||
//ServerInitHandler ServerHandler
|
PixelFormat *common.PixelFormat
|
||||||
Encodings []common.Encoding
|
ColorMap *common.ColorMap
|
||||||
PixelFormat *common.PixelFormat
|
ClientMessages []common.ClientMessage
|
||||||
ColorMap *common.ColorMap
|
DesktopName []byte
|
||||||
//ClientMessageCh chan common.ClientMessage
|
Height uint16
|
||||||
//ServerMessageCh chan common.ServerMessage
|
Width uint16
|
||||||
ClientMessages []common.ClientMessage
|
UseDummySession bool
|
||||||
DesktopName []byte
|
|
||||||
Height uint16
|
|
||||||
Width uint16
|
|
||||||
UseDummySession bool
|
|
||||||
//handler to allow for registering for messages, this can't be a channel
|
//handler to allow for registering for messages, this can't be a channel
|
||||||
//because of the websockets handler function which will kill the connection on exit if conn.handle() is run on another thread
|
//because of the websockets handler function which will kill the connection on exit if conn.handle() is run on another thread
|
||||||
NewConnHandler ServerHandler
|
NewConnHandler ServerHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
func wsHandlerFunc(ws io.ReadWriter, cfg *ServerConfig, sessionId string) {
|
func wsHandlerFunc(ws io.ReadWriter, cfg *ServerConfig, sessionId string) {
|
||||||
// header := ws.Request().Header
|
|
||||||
// url := ws.Request().URL
|
|
||||||
// //stam := header.Get("Origin")
|
|
||||||
// logger.Debugf("header: %v\nurl: %v", header, url)
|
|
||||||
// io.Copy(ws, ws)
|
|
||||||
|
|
||||||
err := attachNewServerConn(ws, cfg, sessionId)
|
err := attachNewServerConn(ws, cfg, sessionId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error attaching new connection. %v", err)
|
log.Fatalf("Error attaching new connection. %v", err)
|
||||||
@ -80,7 +50,6 @@ func wsHandlerFunc(ws io.ReadWriter, cfg *ServerConfig, sessionId string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func WsServe(url string, cfg *ServerConfig) error {
|
func WsServe(url string, cfg *ServerConfig) error {
|
||||||
//server := WsServer1{cfg}
|
|
||||||
server := WsServer{cfg}
|
server := WsServer{cfg}
|
||||||
server.Listen(url, WsHandler(wsHandlerFunc))
|
server.Listen(url, WsHandler(wsHandlerFunc))
|
||||||
return nil
|
return nil
|
||||||
@ -97,9 +66,6 @@ func TcpServe(url string, cfg *ServerConfig) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
go attachNewServerConn(c, cfg, "dummySession")
|
go attachNewServerConn(c, cfg, "dummySession")
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,6 @@ func TestServer(t *testing.T) {
|
|||||||
SecurityHandlers: []SecurityHandler{&ServerAuthVNC{"Ch_#!T@8"}},
|
SecurityHandlers: []SecurityHandler{&ServerAuthVNC{"Ch_#!T@8"}},
|
||||||
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
|
Encodings: []common.Encoding{&encodings.RawEncoding{}, &encodings.TightEncoding{}, &encodings.CopyRectEncoding{}},
|
||||||
PixelFormat: common.NewPixelFormat(32),
|
PixelFormat: common.NewPixelFormat(32),
|
||||||
//ClientMessageCh: chServer,
|
|
||||||
ServerMessageCh: chClient,
|
|
||||||
ClientMessages: DefaultClientMessages,
|
ClientMessages: DefaultClientMessages,
|
||||||
DesktopName: []byte("workDesk"),
|
DesktopName: []byte("workDesk"),
|
||||||
Height: uint16(768),
|
Height: uint16(768),
|
||||||
|
@ -1,104 +0,0 @@
|
|||||||
package server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"vncproxy/logger"
|
|
||||||
|
|
||||||
"bytes"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
)
|
|
||||||
|
|
||||||
type WsServer1 struct {
|
|
||||||
cfg *ServerConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
type WsHandler1 func(io.ReadWriter, *ServerConfig)
|
|
||||||
|
|
||||||
var upgrader = websocket.Upgrader{
|
|
||||||
ReadBufferSize: 1024,
|
|
||||||
WriteBufferSize: 1024,
|
|
||||||
CheckOrigin: func(r *http.Request) bool {
|
|
||||||
return true
|
|
||||||
}}
|
|
||||||
|
|
||||||
type WsConnection struct {
|
|
||||||
Reader WsReader
|
|
||||||
Writer WsWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewWsConnection(c *websocket.Conn) *WsConnection {
|
|
||||||
return &WsConnection{
|
|
||||||
WsReader{},
|
|
||||||
WsWriter{c},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type WsWriter struct {
|
|
||||||
conn *websocket.Conn
|
|
||||||
}
|
|
||||||
|
|
||||||
type WsReader struct {
|
|
||||||
Buff bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wr WsReader) Read(p []byte) (n int, err error) {
|
|
||||||
return wr.Buff.Read(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (wr WsWriter) Write(p []byte) (int, error) {
|
|
||||||
err := wr.conn.WriteMessage(websocket.BinaryMessage, p)
|
|
||||||
return len(p), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func handleConnection(w http.ResponseWriter, r *http.Request) {
|
|
||||||
log.Print("got connection:", r.URL)
|
|
||||||
c, err := upgrader.Upgrade(w, r, nil)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Print("upgrade:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer c.Close()
|
|
||||||
|
|
||||||
myConn := NewWsConnection(c)
|
|
||||||
|
|
||||||
for {
|
|
||||||
mt, message, err := c.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
log.Println("read:", err)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if mt == websocket.BinaryMessage {
|
|
||||||
myConn.Reader.Buff.Write(message)
|
|
||||||
}
|
|
||||||
log.Printf("recv: %s", message)
|
|
||||||
// err = c.WriteMessage(mt, message)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Println("write:", err)
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This example demonstrates a trivial echo server.
|
|
||||||
func (wsServer *WsServer1) Listen(urlStr string, handlerFunc WsHandler) {
|
|
||||||
//http.Handle("/", websocket.Handler(EchoHandler))
|
|
||||||
if urlStr == "" {
|
|
||||||
urlStr = "/"
|
|
||||||
}
|
|
||||||
url, err := url.Parse(urlStr)
|
|
||||||
if err != nil {
|
|
||||||
logger.Errorf("error while parsing url: ", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
http.HandleFunc(url.Path, handleConnection)
|
|
||||||
|
|
||||||
err = http.ListenAndServe(url.Host, nil)
|
|
||||||
if err != nil {
|
|
||||||
panic("ListenAndServe: " + err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user