1
0
mirror of https://github.com/amitbet/vnc2video.git synced 2025-05-10 08:14:28 +00:00

name change now: vnc2video,

initial implementation for hextile, cursor
This commit is contained in:
amit bezalel 2018-01-12 04:56:55 +02:00
parent 1a112dbead
commit afc94572a3
55 changed files with 7081 additions and 6667 deletions

36
.vscode/launch.json vendored
View File

@ -1,19 +1,19 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "debug",
"args": [
"localhost:5903"
],
"program": "${workspaceRoot}/example/client"
}
]
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "debug",
"args": [
"localhost:5903"
],
"program": "${workspaceRoot}/example/client"
}
]
}

90
.vscode/tasks.json vendored
View File

@ -1,46 +1,46 @@
{
"version": "0.1.0",
"command": "go",
"isShellCommand": true,
"echoCommand": true,
"showOutput": "always",
// "showOutput": "silent",
"options": {
// "env": {
// "GOPATH": "/Users/lukeh/dd/go"
// }
},
"tasks": [
{
"taskName": "install",
"args": [
"-v",
"./..."
],
"osx": {
"options": {
"env": {
//"GOPATH": "${env.HOME}/Dropbox/go"
}
}
},
"windows": {
"options": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
}
},
"isBuildCommand": true,
"problemMatcher": "$go"
},
{
"taskName": "test",
"args": [
"-v",
"./..."
],
"isTestCommand": true
}
]
{
"version": "0.1.0",
"command": "go",
"isShellCommand": true,
"echoCommand": true,
"showOutput": "always",
// "showOutput": "silent",
"options": {
// "env": {
// "GOPATH": "/Users/lukeh/dd/go"
// }
},
"tasks": [
{
"taskName": "install",
"args": [
"-v",
"./..."
],
"osx": {
"options": {
"env": {
//"GOPATH": "${env.HOME}/Dropbox/go"
}
}
},
"windows": {
"options": {
"env": {
//"GOPATH": "${env.USERPROFILE}\\Dropbox\\go"
}
}
},
"isBuildCommand": true,
"problemMatcher": "$go"
},
{
"taskName": "test",
"args": [
"-v",
"./..."
],
"isTestCommand": true
}
]
}

47
LICENSE
View File

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

View File

@ -1,46 +1,46 @@
// Code generated by "stringer -type=Button"; DO NOT EDIT.
package vnc2webm
import "fmt"
const (
_Button_name_0 = "BtnNoneBtnLeftBtnMiddle"
_Button_name_1 = "BtnRight"
_Button_name_2 = "BtnFour"
_Button_name_3 = "BtnFive"
_Button_name_4 = "BtnSix"
_Button_name_5 = "BtnSeven"
_Button_name_6 = "BtnEight"
)
var (
_Button_index_0 = [...]uint8{0, 7, 14, 23}
_Button_index_1 = [...]uint8{0, 8}
_Button_index_2 = [...]uint8{0, 7}
_Button_index_3 = [...]uint8{0, 7}
_Button_index_4 = [...]uint8{0, 6}
_Button_index_5 = [...]uint8{0, 8}
_Button_index_6 = [...]uint8{0, 8}
)
func (i Button) String() string {
switch {
case 0 <= i && i <= 2:
return _Button_name_0[_Button_index_0[i]:_Button_index_0[i+1]]
case i == 4:
return _Button_name_1
case i == 8:
return _Button_name_2
case i == 16:
return _Button_name_3
case i == 32:
return _Button_name_4
case i == 64:
return _Button_name_5
case i == 128:
return _Button_name_6
default:
return fmt.Sprintf("Button(%d)", i)
}
}
// Code generated by "stringer -type=Button"; DO NOT EDIT.
package vnc2video
import "fmt"
const (
_Button_name_0 = "BtnNoneBtnLeftBtnMiddle"
_Button_name_1 = "BtnRight"
_Button_name_2 = "BtnFour"
_Button_name_3 = "BtnFive"
_Button_name_4 = "BtnSix"
_Button_name_5 = "BtnSeven"
_Button_name_6 = "BtnEight"
)
var (
_Button_index_0 = [...]uint8{0, 7, 14, 23}
_Button_index_1 = [...]uint8{0, 8}
_Button_index_2 = [...]uint8{0, 7}
_Button_index_3 = [...]uint8{0, 7}
_Button_index_4 = [...]uint8{0, 6}
_Button_index_5 = [...]uint8{0, 8}
_Button_index_6 = [...]uint8{0, 8}
)
func (i Button) String() string {
switch {
case 0 <= i && i <= 2:
return _Button_name_0[_Button_index_0[i]:_Button_index_0[i+1]]
case i == 4:
return _Button_name_1
case i == 8:
return _Button_name_2
case i == 16:
return _Button_name_3
case i == 32:
return _Button_name_4
case i == 64:
return _Button_name_5
case i == 128:
return _Button_name_6
default:
return fmt.Sprintf("Button(%d)", i)
}
}

View File

@ -1,24 +1,24 @@
package vnc2webm
// Button represents a mask of pointer presses/releases.
type Button uint8
//go:generate stringer -type=Button
// All available button mask components.
const (
BtnLeft Button = 1 << iota
BtnMiddle
BtnRight
BtnFour
BtnFive
BtnSix
BtnSeven
BtnEight
BtnNone Button = 0
)
// Mask returns button mask
func Mask(button Button) uint8 {
return uint8(button)
}
package vnc2video
// Button represents a mask of pointer presses/releases.
type Button uint8
//go:generate stringer -type=Button
// All available button mask components.
const (
BtnLeft Button = 1 << iota
BtnMiddle
BtnRight
BtnFour
BtnFive
BtnSix
BtnSeven
BtnEight
BtnNone Button = 0
)
// Mask returns button mask
func Mask(button Button) uint8 {
return uint8(button)
}

694
client.go
View File

@ -1,347 +1,347 @@
package vnc2webm
import (
"bufio"
"context"
"encoding/binary"
"fmt"
"net"
"sync"
"vnc2webm/logger"
)
var (
// DefaultClientHandlers represents default client handlers
DefaultClientHandlers = []Handler{
&DefaultClientVersionHandler{},
&DefaultClientSecurityHandler{},
&DefaultClientClientInitHandler{},
&DefaultClientServerInitHandler{},
&DefaultClientMessageHandler{},
}
)
// Connect handshake with remote server using underlining net.Conn
func Connect(ctx context.Context, c net.Conn, cfg *ClientConfig) (*ClientConn, error) {
conn, err := NewClientConn(c, cfg)
if err != nil {
conn.Close()
cfg.ErrorCh <- err
return nil, err
}
if len(cfg.Handlers) == 0 {
cfg.Handlers = DefaultClientHandlers
}
for _, h := range cfg.Handlers {
if err := h.Handle(conn); err != nil {
conn.Close()
cfg.ErrorCh <- err
return nil, err
}
}
return conn, nil
}
var _ Conn = (*ClientConn)(nil)
// Config returns connection config
func (c *ClientConn) Config() interface{} {
return c.cfg
}
func (c *ClientConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
// Wait waiting for connection close
func (c *ClientConn) Wait() {
<-c.quit
}
// Conn return underlining net.Conn
func (c *ClientConn) Conn() net.Conn {
return c.c
}
// SetProtoVersion sets proto version
func (c *ClientConn) SetProtoVersion(pv string) {
c.protocol = pv
}
// SetEncodings write SetEncodings message
func (c *ClientConn) SetEncodings(encs []EncodingType) error {
msg := &SetEncodings{
EncNum: uint16(len(encs)),
Encodings: encs,
}
return msg.Write(c)
}
// Flush flushes data to conn
func (c *ClientConn) Flush() error {
return c.bw.Flush()
}
// Close closing conn
func (c *ClientConn) Close() error {
if c.quit != nil {
close(c.quit)
c.quit = nil
}
if c.quitCh != nil {
close(c.quitCh)
}
return c.c.Close()
}
// Read reads data from conn
func (c *ClientConn) Read(buf []byte) (int, error) {
return c.br.Read(buf)
}
// Write data to conn must be Flushed
func (c *ClientConn) Write(buf []byte) (int, error) {
return c.bw.Write(buf)
}
// ColorMap returns color map
func (c *ClientConn) ColorMap() ColorMap {
return c.colorMap
}
// SetColorMap sets color map
func (c *ClientConn) SetColorMap(cm ColorMap) {
c.colorMap = cm
}
// DesktopName returns connection desktop name
func (c *ClientConn) DesktopName() []byte {
return c.desktopName
}
// PixelFormat returns connection pixel format
func (c *ClientConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
// SetDesktopName sets desktop name
func (c *ClientConn) SetDesktopName(name []byte) {
c.desktopName = name
}
// SetPixelFormat sets pixel format
func (c *ClientConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
// Encodings returns client encodings
func (c *ClientConn) Encodings() []Encoding {
return c.encodings
}
// Width returns width
func (c *ClientConn) Width() uint16 {
return c.fbWidth
}
// Height returns height
func (c *ClientConn) Height() uint16 {
return c.fbHeight
}
// Protocol returns protocol
func (c *ClientConn) Protocol() string {
return c.protocol
}
// SetWidth sets width of client conn
func (c *ClientConn) SetWidth(width uint16) {
c.fbWidth = width
}
// SetHeight sets height of client conn
func (c *ClientConn) SetHeight(height uint16) {
c.fbHeight = height
}
// SecurityHandler returns security handler
func (c *ClientConn) SecurityHandler() SecurityHandler {
return c.securityHandler
}
// SetSecurityHandler sets security handler
func (c *ClientConn) SetSecurityHandler(sechandler SecurityHandler) error {
c.securityHandler = sechandler
return nil
}
// The ClientConn type holds client connection information
type ClientConn struct {
c net.Conn
br *bufio.Reader
bw *bufio.Writer
cfg *ClientConfig
protocol string
// If the pixel format uses a color map, then this is the color
// map that is used. This should not be modified directly, since
// the data comes from the server.
// Definition in §5 - Representation of Pixel Data.
colorMap ColorMap
// Name associated with the desktop, sent from the server.
desktopName []byte
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings() should be used.
encodings []Encoding
securityHandler SecurityHandler
// Height of the frame buffer in pixels, sent from the server.
fbHeight uint16
// Width of the frame buffer in pixels, sent from the server.
fbWidth uint16
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
quitCh chan struct{}
quit chan struct{}
errorCh chan error
}
func (cc *ClientConn) ResetAllEncodings() {
for _, enc := range cc.encodings {
enc.Reset()
}
}
// NewClientConn creates new client conn using config
func NewClientConn(c net.Conn, cfg *ClientConfig) (*ClientConn, error) {
if len(cfg.Encodings) == 0 {
return nil, fmt.Errorf("client can't handle encodings")
}
return &ClientConn{
c: c,
cfg: cfg,
br: bufio.NewReader(c),
bw: bufio.NewWriter(c),
encodings: cfg.Encodings,
quitCh: cfg.QuitCh,
errorCh: cfg.ErrorCh,
pixelFormat: cfg.PixelFormat,
quit: make(chan struct{}),
}, nil
}
// DefaultClientMessageHandler represents default client message handler
type DefaultClientMessageHandler struct{}
// Handle handles server messages.
func (*DefaultClientMessageHandler) Handle(c Conn) error {
logger.Debug("starting DefaultClientMessageHandler")
cfg := c.Config().(*ClientConfig)
var err error
var wg sync.WaitGroup
wg.Add(2)
//defer c.Close()
serverMessages := make(map[ServerMessageType]ServerMessage)
for _, m := range cfg.Messages {
serverMessages[m.Type()] = m
}
go func() {
defer wg.Done()
for {
select {
case msg := <-cfg.ClientMessageCh:
if err = msg.Write(c); err != nil {
cfg.ErrorCh <- err
return
}
}
}
}()
go func() {
defer wg.Done()
for {
select {
default:
var messageType ServerMessageType
if err = binary.Read(c, binary.BigEndian, &messageType); err != nil {
cfg.ErrorCh <- err
return
}
logger.Debugf("got server message, msgType=%d", messageType)
msg, ok := serverMessages[messageType]
if !ok {
err = fmt.Errorf("unknown message-type: %v", messageType)
cfg.ErrorCh <- err
return
}
parsedMsg, err := msg.Read(c)
logger.Debugf("============== End Message: type=%d ==============", messageType)
if err != nil {
cfg.ErrorCh <- err
return
}
cfg.ServerMessageCh <- parsedMsg
}
}
}()
//encodings := c.Encodings()
encTypes := make(map[EncodingType]EncodingType)
for _, myEnc := range c.Encodings() {
encTypes[myEnc.Type()] = myEnc.Type()
//encTypes = append(encTypes, myEnc.Type())
}
v := make([]EncodingType, 0, len(encTypes))
for _, value := range encTypes {
v = append(v, value)
}
logger.Debugf("setting encodings: %v", v)
c.SetEncodings(v)
firstMsg := FramebufferUpdateRequest{Inc: 0, X: 0, Y: 0, Width: c.Width(), Height: c.Height()}
logger.Debugf("sending initial req message: %v", firstMsg)
firstMsg.Write(c)
//wg.Wait()
return nil
}
// A ClientConfig structure is used to configure a ClientConn. After
// one has been passed to initialize a connection, it must not be modified.
type ClientConfig struct {
Handlers []Handler
SecurityHandlers []SecurityHandler
Encodings []Encoding
PixelFormat PixelFormat
ColorMap ColorMap
ClientMessageCh chan ClientMessage
ServerMessageCh chan ServerMessage
Exclusive bool
Messages []ServerMessage
QuitCh chan struct{}
ErrorCh chan error
quit chan struct{}
}
package vnc2video
import (
"bufio"
"context"
"encoding/binary"
"fmt"
"net"
"sync"
"vnc2video/logger"
)
var (
// DefaultClientHandlers represents default client handlers
DefaultClientHandlers = []Handler{
&DefaultClientVersionHandler{},
&DefaultClientSecurityHandler{},
&DefaultClientClientInitHandler{},
&DefaultClientServerInitHandler{},
&DefaultClientMessageHandler{},
}
)
// Connect handshake with remote server using underlining net.Conn
func Connect(ctx context.Context, c net.Conn, cfg *ClientConfig) (*ClientConn, error) {
conn, err := NewClientConn(c, cfg)
if err != nil {
conn.Close()
cfg.ErrorCh <- err
return nil, err
}
if len(cfg.Handlers) == 0 {
cfg.Handlers = DefaultClientHandlers
}
for _, h := range cfg.Handlers {
if err := h.Handle(conn); err != nil {
conn.Close()
cfg.ErrorCh <- err
return nil, err
}
}
return conn, nil
}
var _ Conn = (*ClientConn)(nil)
// Config returns connection config
func (c *ClientConn) Config() interface{} {
return c.cfg
}
func (c *ClientConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
// Wait waiting for connection close
func (c *ClientConn) Wait() {
<-c.quit
}
// Conn return underlining net.Conn
func (c *ClientConn) Conn() net.Conn {
return c.c
}
// SetProtoVersion sets proto version
func (c *ClientConn) SetProtoVersion(pv string) {
c.protocol = pv
}
// SetEncodings write SetEncodings message
func (c *ClientConn) SetEncodings(encs []EncodingType) error {
msg := &SetEncodings{
EncNum: uint16(len(encs)),
Encodings: encs,
}
return msg.Write(c)
}
// Flush flushes data to conn
func (c *ClientConn) Flush() error {
return c.bw.Flush()
}
// Close closing conn
func (c *ClientConn) Close() error {
if c.quit != nil {
close(c.quit)
c.quit = nil
}
if c.quitCh != nil {
close(c.quitCh)
}
return c.c.Close()
}
// Read reads data from conn
func (c *ClientConn) Read(buf []byte) (int, error) {
return c.br.Read(buf)
}
// Write data to conn must be Flushed
func (c *ClientConn) Write(buf []byte) (int, error) {
return c.bw.Write(buf)
}
// ColorMap returns color map
func (c *ClientConn) ColorMap() ColorMap {
return c.colorMap
}
// SetColorMap sets color map
func (c *ClientConn) SetColorMap(cm ColorMap) {
c.colorMap = cm
}
// DesktopName returns connection desktop name
func (c *ClientConn) DesktopName() []byte {
return c.desktopName
}
// PixelFormat returns connection pixel format
func (c *ClientConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
// SetDesktopName sets desktop name
func (c *ClientConn) SetDesktopName(name []byte) {
c.desktopName = name
}
// SetPixelFormat sets pixel format
func (c *ClientConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
// Encodings returns client encodings
func (c *ClientConn) Encodings() []Encoding {
return c.encodings
}
// Width returns width
func (c *ClientConn) Width() uint16 {
return c.fbWidth
}
// Height returns height
func (c *ClientConn) Height() uint16 {
return c.fbHeight
}
// Protocol returns protocol
func (c *ClientConn) Protocol() string {
return c.protocol
}
// SetWidth sets width of client conn
func (c *ClientConn) SetWidth(width uint16) {
c.fbWidth = width
}
// SetHeight sets height of client conn
func (c *ClientConn) SetHeight(height uint16) {
c.fbHeight = height
}
// SecurityHandler returns security handler
func (c *ClientConn) SecurityHandler() SecurityHandler {
return c.securityHandler
}
// SetSecurityHandler sets security handler
func (c *ClientConn) SetSecurityHandler(sechandler SecurityHandler) error {
c.securityHandler = sechandler
return nil
}
// The ClientConn type holds client connection information
type ClientConn struct {
c net.Conn
br *bufio.Reader
bw *bufio.Writer
cfg *ClientConfig
protocol string
// If the pixel format uses a color map, then this is the color
// map that is used. This should not be modified directly, since
// the data comes from the server.
// Definition in §5 - Representation of Pixel Data.
colorMap ColorMap
// Name associated with the desktop, sent from the server.
desktopName []byte
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings() should be used.
encodings []Encoding
securityHandler SecurityHandler
// Height of the frame buffer in pixels, sent from the server.
fbHeight uint16
// Width of the frame buffer in pixels, sent from the server.
fbWidth uint16
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
quitCh chan struct{}
quit chan struct{}
errorCh chan error
}
func (cc *ClientConn) ResetAllEncodings() {
for _, enc := range cc.encodings {
enc.Reset()
}
}
// NewClientConn creates new client conn using config
func NewClientConn(c net.Conn, cfg *ClientConfig) (*ClientConn, error) {
if len(cfg.Encodings) == 0 {
return nil, fmt.Errorf("client can't handle encodings")
}
return &ClientConn{
c: c,
cfg: cfg,
br: bufio.NewReader(c),
bw: bufio.NewWriter(c),
encodings: cfg.Encodings,
quitCh: cfg.QuitCh,
errorCh: cfg.ErrorCh,
pixelFormat: cfg.PixelFormat,
quit: make(chan struct{}),
}, nil
}
// DefaultClientMessageHandler represents default client message handler
type DefaultClientMessageHandler struct{}
// Handle handles server messages.
func (*DefaultClientMessageHandler) Handle(c Conn) error {
logger.Debug("starting DefaultClientMessageHandler")
cfg := c.Config().(*ClientConfig)
var err error
var wg sync.WaitGroup
wg.Add(2)
//defer c.Close()
serverMessages := make(map[ServerMessageType]ServerMessage)
for _, m := range cfg.Messages {
serverMessages[m.Type()] = m
}
go func() {
defer wg.Done()
for {
select {
case msg := <-cfg.ClientMessageCh:
if err = msg.Write(c); err != nil {
cfg.ErrorCh <- err
return
}
}
}
}()
go func() {
defer wg.Done()
for {
select {
default:
var messageType ServerMessageType
if err = binary.Read(c, binary.BigEndian, &messageType); err != nil {
cfg.ErrorCh <- err
return
}
logger.Debugf("got server message, msgType=%d", messageType)
msg, ok := serverMessages[messageType]
if !ok {
err = fmt.Errorf("unknown message-type: %v", messageType)
cfg.ErrorCh <- err
return
}
parsedMsg, err := msg.Read(c)
logger.Debugf("============== End Message: type=%d ==============", messageType)
if err != nil {
cfg.ErrorCh <- err
return
}
cfg.ServerMessageCh <- parsedMsg
}
}
}()
//encodings := c.Encodings()
encTypes := make(map[EncodingType]EncodingType)
for _, myEnc := range c.Encodings() {
encTypes[myEnc.Type()] = myEnc.Type()
//encTypes = append(encTypes, myEnc.Type())
}
v := make([]EncodingType, 0, len(encTypes))
for _, value := range encTypes {
v = append(v, value)
}
logger.Debugf("setting encodings: %v", v)
c.SetEncodings(v)
firstMsg := FramebufferUpdateRequest{Inc: 0, X: 0, Y: 0, Width: c.Width(), Height: c.Height()}
logger.Debugf("sending initial req message: %v", firstMsg)
firstMsg.Write(c)
//wg.Wait()
return nil
}
// A ClientConfig structure is used to configure a ClientConn. After
// one has been passed to initialize a connection, it must not be modified.
type ClientConfig struct {
Handlers []Handler
SecurityHandlers []SecurityHandler
Encodings []Encoding
PixelFormat PixelFormat
ColorMap ColorMap
ClientMessageCh chan ClientMessage
ServerMessageCh chan ServerMessage
Exclusive bool
Messages []ServerMessage
QuitCh chan struct{}
ErrorCh chan error
quit chan struct{}
}

View File

@ -1,27 +1,27 @@
// Code generated by "stringer -type=ClientMessageType"; DO NOT EDIT.
package vnc2webm
import "fmt"
const (
_ClientMessageType_name_0 = "SetPixelFormatMsgType"
_ClientMessageType_name_1 = "SetEncodingsMsgTypeFramebufferUpdateRequestMsgTypeKeyEventMsgTypePointerEventMsgTypeClientCutTextMsgType"
)
var (
_ClientMessageType_index_0 = [...]uint8{0, 21}
_ClientMessageType_index_1 = [...]uint8{0, 19, 50, 65, 84, 104}
)
func (i ClientMessageType) String() string {
switch {
case i == 0:
return _ClientMessageType_name_0
case 2 <= i && i <= 6:
i -= 2
return _ClientMessageType_name_1[_ClientMessageType_index_1[i]:_ClientMessageType_index_1[i+1]]
default:
return fmt.Sprintf("ClientMessageType(%d)", i)
}
}
// Code generated by "stringer -type=ClientMessageType"; DO NOT EDIT.
package vnc2video
import "fmt"
const (
_ClientMessageType_name_0 = "SetPixelFormatMsgType"
_ClientMessageType_name_1 = "SetEncodingsMsgTypeFramebufferUpdateRequestMsgTypeKeyEventMsgTypePointerEventMsgTypeClientCutTextMsgType"
)
var (
_ClientMessageType_index_0 = [...]uint8{0, 21}
_ClientMessageType_index_1 = [...]uint8{0, 19, 50, 65, 84, 104}
)
func (i ClientMessageType) String() string {
switch {
case i == 0:
return _ClientMessageType_name_0
case 2 <= i && i <= 6:
i -= 2
return _ClientMessageType_name_1[_ClientMessageType_index_1[i]:_ClientMessageType_index_1[i+1]]
default:
return fmt.Sprintf("ClientMessageType(%d)", i)
}
}

64
conn.go
View File

@ -1,32 +1,32 @@
package vnc2webm
import (
"io"
"net"
)
// Conn represents vnc conection
type Conn interface {
io.ReadWriteCloser
Conn() net.Conn
Config() interface{}
Protocol() string
PixelFormat() PixelFormat
SetPixelFormat(PixelFormat) error
ColorMap() ColorMap
SetColorMap(ColorMap)
Encodings() []Encoding
SetEncodings([]EncodingType) error
Width() uint16
Height() uint16
SetWidth(uint16)
SetHeight(uint16)
DesktopName() []byte
SetDesktopName([]byte)
Flush() error
Wait()
SetProtoVersion(string)
SetSecurityHandler(SecurityHandler) error
SecurityHandler() SecurityHandler
GetEncInstance(EncodingType) Encoding
}
package vnc2video
import (
"io"
"net"
)
// Conn represents vnc conection
type Conn interface {
io.ReadWriteCloser
Conn() net.Conn
Config() interface{}
Protocol() string
PixelFormat() PixelFormat
SetPixelFormat(PixelFormat) error
ColorMap() ColorMap
SetColorMap(ColorMap)
Encodings() []Encoding
SetEncodings([]EncodingType) error
Width() uint16
Height() uint16
SetWidth(uint16)
SetHeight(uint16)
DesktopName() []byte
SetDesktopName([]byte)
Flush() error
Wait()
SetProtoVersion(string)
SetSecurityHandler(SecurityHandler) error
SecurityHandler() SecurityHandler
GetEncInstance(EncodingType) Encoding
}

View File

@ -1,91 +1,91 @@
package encoders
import (
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2webm/logger"
)
type DV8ImageEncoder struct {
cmd *exec.Cmd
binaryPath string
input io.WriteCloser
}
func (enc *DV8ImageEncoder) Init(videoFileName string) {
fileExt := ".webm"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
binary := "./ffmpeg"
cmd := exec.Command(binary,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "5",
//"-i", "pipe:0",
"-i", "-",
"-vcodec", "libvpx", //"libvpx",//"libvpx-vp9"//"libx264"
"-b:v", "1M",
"-threads", "8",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-tile-columns", "6",
//"-frame-parallel", "1",
// "-an", "-f", "webm",
"-cpu-used", "-16",
"-preset", "ultrafast",
"-deadline", "realtime",
//"-cpu-used", "-5",
"-maxrate", "2.5M",
"-bufsize", "10M",
"-g", "6",
//"-rc_lookahead", "16",
//"-profile", "0",
"-qmax", "51",
"-qmin", "11",
//"-slices", "4",
//"-vb", "2M",
videoFileName,
)
//cmd := exec.Command("/bin/echo")
//io.Copy(cmd.Stdout, os.Stdout)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
encInput, err := cmd.StdinPipe()
enc.input = encInput
if err != nil {
logger.Error("can't get ffmpeg input pipe")
}
enc.cmd = cmd
}
func (enc *DV8ImageEncoder) Run(encoderFilePath string, videoFileName string) {
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
return
}
enc.binaryPath = encoderFilePath
enc.Init(videoFileName)
logger.Infof("launching binary: %v", enc.cmd)
err := enc.cmd.Run()
if err != nil {
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
}
}
func (enc *DV8ImageEncoder) Encode(img image.Image) {
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *DV8ImageEncoder) Close() {
}
package encoders
import (
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2video/logger"
)
type DV8ImageEncoder struct {
cmd *exec.Cmd
binaryPath string
input io.WriteCloser
}
func (enc *DV8ImageEncoder) Init(videoFileName string) {
fileExt := ".webm"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
binary := "./ffmpeg"
cmd := exec.Command(binary,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "5",
//"-i", "pipe:0",
"-i", "-",
"-vcodec", "libvpx", //"libvpx",//"libvpx-vp9"//"libx264"
"-b:v", "1M",
"-threads", "8",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-tile-columns", "6",
//"-frame-parallel", "1",
// "-an", "-f", "webm",
"-cpu-used", "-16",
"-preset", "ultrafast",
"-deadline", "realtime",
//"-cpu-used", "-5",
"-maxrate", "2.5M",
"-bufsize", "10M",
"-g", "6",
//"-rc_lookahead", "16",
//"-profile", "0",
"-qmax", "51",
"-qmin", "11",
//"-slices", "4",
//"-vb", "2M",
videoFileName,
)
//cmd := exec.Command("/bin/echo")
//io.Copy(cmd.Stdout, os.Stdout)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
encInput, err := cmd.StdinPipe()
enc.input = encInput
if err != nil {
logger.Error("can't get ffmpeg input pipe")
}
enc.cmd = cmd
}
func (enc *DV8ImageEncoder) Run(encoderFilePath string, videoFileName string) {
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
return
}
enc.binaryPath = encoderFilePath
enc.Init(videoFileName)
logger.Infof("launching binary: %v", enc.cmd)
err := enc.cmd.Run()
if err != nil {
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
}
}
func (enc *DV8ImageEncoder) Encode(img image.Image) {
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *DV8ImageEncoder) Close() {
}

View File

@ -1,91 +1,91 @@
package encoders
import (
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2webm/logger"
)
type DV9ImageEncoder struct {
cmd *exec.Cmd
binaryPath string
input io.WriteCloser
}
func (enc *DV9ImageEncoder) Init(videoFileName string) {
fileExt := ".webm"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
binary := "./ffmpeg"
cmd := exec.Command(binary,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "5",
//"-i", "pipe:0",
"-i", "-",
"-vcodec", "libvpx-vp9", //"libvpx",//"libvpx-vp9"//"libx264"
"-b:v", "1M",
"-threads", "8",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-tile-columns", "6",
//"-frame-parallel", "1",
// "-an", "-f", "webm",
"-cpu-used", "-8",
"-preset", "ultrafast",
"-deadline", "realtime",
//"-cpu-used", "-5",
"-maxrate", "2.5M",
"-bufsize", "10M",
"-g", "6",
//"-rc_lookahead", "16",
//"-profile", "0",
"-qmax", "51",
"-qmin", "11",
//"-slices", "4",
//"-vb", "2M",
videoFileName,
)
//cmd := exec.Command("/bin/echo")
//io.Copy(cmd.Stdout, os.Stdout)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
encInput, err := cmd.StdinPipe()
enc.input = encInput
if err != nil {
logger.Error("can't get ffmpeg input pipe")
}
enc.cmd = cmd
}
func (enc *DV9ImageEncoder) Run(encoderFilePath string, videoFileName string) {
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
return
}
enc.binaryPath = encoderFilePath
enc.Init(videoFileName)
logger.Infof("launching binary: %v", enc.cmd)
err := enc.cmd.Run()
if err != nil {
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
}
}
func (enc *DV9ImageEncoder) Encode(img image.Image) {
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *DV9ImageEncoder) Close() {
}
package encoders
import (
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2video/logger"
)
type DV9ImageEncoder struct {
cmd *exec.Cmd
binaryPath string
input io.WriteCloser
}
func (enc *DV9ImageEncoder) Init(videoFileName string) {
fileExt := ".webm"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
binary := "./ffmpeg"
cmd := exec.Command(binary,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "5",
//"-i", "pipe:0",
"-i", "-",
"-vcodec", "libvpx-vp9", //"libvpx",//"libvpx-vp9"//"libx264"
"-b:v", "1M",
"-threads", "8",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-tile-columns", "6",
//"-frame-parallel", "1",
// "-an", "-f", "webm",
"-cpu-used", "-8",
"-preset", "ultrafast",
"-deadline", "realtime",
//"-cpu-used", "-5",
"-maxrate", "2.5M",
"-bufsize", "10M",
"-g", "6",
//"-rc_lookahead", "16",
//"-profile", "0",
"-qmax", "51",
"-qmin", "11",
//"-slices", "4",
//"-vb", "2M",
videoFileName,
)
//cmd := exec.Command("/bin/echo")
//io.Copy(cmd.Stdout, os.Stdout)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
encInput, err := cmd.StdinPipe()
enc.input = encInput
if err != nil {
logger.Error("can't get ffmpeg input pipe")
}
enc.cmd = cmd
}
func (enc *DV9ImageEncoder) Run(encoderFilePath string, videoFileName string) {
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
return
}
enc.binaryPath = encoderFilePath
enc.Init(videoFileName)
logger.Infof("launching binary: %v", enc.cmd)
err := enc.cmd.Run()
if err != nil {
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
}
}
func (enc *DV9ImageEncoder) Encode(img image.Image) {
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *DV9ImageEncoder) Close() {
}

View File

@ -1,43 +1,43 @@
package encoders
import (
"fmt"
"image"
"image/color"
"io"
)
func encodePPM(w io.Writer, img image.Image) error {
maxvalue := 255
size := img.Bounds()
// write ppm header
_, err := fmt.Fprintf(w, "P6\n%d %d\n%d\n", size.Dx(), size.Dy(), maxvalue)
if err != nil {
return err
}
// write the bitmap
colModel := color.RGBAModel
row := make([]uint8, size.Dx()*3)
for y := size.Min.Y; y < size.Max.Y; y++ {
i := 0
for x := size.Min.X; x < size.Max.X; x++ {
color := colModel.Convert(img.At(x, y)).(color.RGBA)
row[i] = color.R
row[i+1] = color.G
row[i+2] = color.B
i += 3
}
if _, err := w.Write(row); err != nil {
return err
}
}
return nil
}
type ImageEncoder interface {
Init(string)
Run()
Encode(image.Image)
Close()
}
package encoders
import (
"fmt"
"image"
"image/color"
"io"
)
func encodePPM(w io.Writer, img image.Image) error {
maxvalue := 255
size := img.Bounds()
// write ppm header
_, err := fmt.Fprintf(w, "P6\n%d %d\n%d\n", size.Dx(), size.Dy(), maxvalue)
if err != nil {
return err
}
// write the bitmap
colModel := color.RGBAModel
row := make([]uint8, size.Dx()*3)
for y := size.Min.Y; y < size.Max.Y; y++ {
i := 0
for x := size.Min.X; x < size.Max.X; x++ {
color := colModel.Convert(img.At(x, y)).(color.RGBA)
row[i] = color.R
row[i+1] = color.G
row[i+2] = color.B
i += 3
}
if _, err := w.Write(row); err != nil {
return err
}
}
return nil
}
type ImageEncoder interface {
Init(string)
Run()
Encode(image.Image)
Close()
}

View File

@ -1,56 +1,56 @@
package encoders
import (
"bytes"
"image"
"image/jpeg"
"strings"
"vnc2webm/logger"
"github.com/icza/mjpeg"
)
type MJPegImageEncoder struct {
avWriter mjpeg.AviWriter
Quality int
Framerate int32
}
func (enc *MJPegImageEncoder) Init(videoFileName string) {
fileExt := ".avi"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
if enc.Framerate <= 0 {
enc.Framerate = 5
}
avWriter, err := mjpeg.New(videoFileName, 1024, 768, enc.Framerate)
if err != nil {
logger.Error("Error during mjpeg init: ", err)
}
enc.avWriter = avWriter
}
func (enc *MJPegImageEncoder) Run() {
}
func (enc *MJPegImageEncoder) Encode(img image.Image) {
buf := &bytes.Buffer{}
jOpts := &jpeg.Options{Quality: enc.Quality}
if enc.Quality <= 0 {
jOpts = nil
}
err := jpeg.Encode(buf, img, jOpts)
if err != nil {
logger.Error("Error while creating jpeg: ", err)
}
err = enc.avWriter.AddFrame(buf.Bytes())
if err != nil {
logger.Error("Error while adding frame to mjpeg: ", err)
}
}
func (enc *MJPegImageEncoder) Close() {
err := enc.avWriter.Close()
if err != nil {
logger.Error("Error while closing mjpeg: ", err)
}
}
package encoders
import (
"bytes"
"image"
"image/jpeg"
"strings"
"vnc2video/logger"
"github.com/icza/mjpeg"
)
type MJPegImageEncoder struct {
avWriter mjpeg.AviWriter
Quality int
Framerate int32
}
func (enc *MJPegImageEncoder) Init(videoFileName string) {
fileExt := ".avi"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
if enc.Framerate <= 0 {
enc.Framerate = 5
}
avWriter, err := mjpeg.New(videoFileName, 1024, 768, enc.Framerate)
if err != nil {
logger.Error("Error during mjpeg init: ", err)
}
enc.avWriter = avWriter
}
func (enc *MJPegImageEncoder) Run() {
}
func (enc *MJPegImageEncoder) Encode(img image.Image) {
buf := &bytes.Buffer{}
jOpts := &jpeg.Options{Quality: enc.Quality}
if enc.Quality <= 0 {
jOpts = nil
}
err := jpeg.Encode(buf, img, jOpts)
if err != nil {
logger.Error("Error while creating jpeg: ", err)
}
err = enc.avWriter.AddFrame(buf.Bytes())
if err != nil {
logger.Error("Error while adding frame to mjpeg: ", err)
}
}
func (enc *MJPegImageEncoder) Close() {
err := enc.avWriter.Close()
if err != nil {
logger.Error("Error while closing mjpeg: ", err)
}
}

View File

@ -1,92 +1,92 @@
package encoders
import (
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2webm/logger"
)
type X264ImageEncoder struct {
cmd *exec.Cmd
binaryPath string
input io.WriteCloser
}
func (enc *X264ImageEncoder) Init(videoFileName string) {
fileExt := ".mp4"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
//binary := "./ffmpeg"
cmd := exec.Command(enc.binaryPath,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "4",
//"-i", "pipe:0",
"-i", "-",
"-vcodec", "libx264", //"libvpx",//"libvpx-vp9"//"libx264"
"-b:v", "1M",
"-threads", "8",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-tile-columns", "6",
//"-frame-parallel", "1",
// "-an", "-f", "webm",
"-cpu-used", "-16",
"-preset", "ultrafast",
"-deadline", "realtime",
//"-cpu-used", "-5",
"-maxrate", "2.5M",
"-bufsize", "10M",
"-g", "6",
//"-rc_lookahead", "16",
//"-profile", "0",
"-qmax", "51",
"-qmin", "11",
//"-slices", "4",
//"-vb", "2M",
videoFileName,
)
//cmd := exec.Command("/bin/echo")
//io.Copy(cmd.Stdout, os.Stdout)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
encInput, err := cmd.StdinPipe()
enc.input = encInput
if err != nil {
logger.Error("can't get ffmpeg input pipe")
}
enc.cmd = cmd
}
func (enc *X264ImageEncoder) Run(encoderFilePath string, videoFileName string) {
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
return
}
enc.binaryPath = encoderFilePath
enc.Init(videoFileName)
logger.Infof("launching binary: %v", enc.cmd)
err := enc.cmd.Run()
if err != nil {
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
}
}
func (enc *X264ImageEncoder) Encode(img image.Image) {
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *X264ImageEncoder) Close() {
}
package encoders
import (
"image"
"io"
"os"
"os/exec"
"strings"
"vnc2video/logger"
)
type X264ImageEncoder struct {
cmd *exec.Cmd
binaryPath string
input io.WriteCloser
}
func (enc *X264ImageEncoder) Init(videoFileName string) {
fileExt := ".mp4"
if !strings.HasSuffix(videoFileName, fileExt) {
videoFileName = videoFileName + fileExt
}
//binary := "./ffmpeg"
cmd := exec.Command(enc.binaryPath,
"-f", "image2pipe",
"-vcodec", "ppm",
//"-r", strconv.Itoa(framerate),
"-r", "4",
//"-i", "pipe:0",
"-i", "-",
"-vcodec", "libx264", //"libvpx",//"libvpx-vp9"//"libx264"
"-b:v", "1M",
"-threads", "8",
//"-speed", "0",
//"-lossless", "1", //for vpx
// "-tile-columns", "6",
//"-frame-parallel", "1",
// "-an", "-f", "webm",
"-cpu-used", "-16",
"-preset", "ultrafast",
"-deadline", "realtime",
//"-cpu-used", "-5",
"-maxrate", "2.5M",
"-bufsize", "10M",
"-g", "6",
//"-rc_lookahead", "16",
//"-profile", "0",
"-qmax", "51",
"-qmin", "11",
//"-slices", "4",
//"-vb", "2M",
videoFileName,
)
//cmd := exec.Command("/bin/echo")
//io.Copy(cmd.Stdout, os.Stdout)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
encInput, err := cmd.StdinPipe()
enc.input = encInput
if err != nil {
logger.Error("can't get ffmpeg input pipe")
}
enc.cmd = cmd
}
func (enc *X264ImageEncoder) Run(encoderFilePath string, videoFileName string) {
if _, err := os.Stat(encoderFilePath); os.IsNotExist(err) {
logger.Error("encoder file doesn't exist in path:", encoderFilePath)
return
}
enc.binaryPath = encoderFilePath
enc.Init(videoFileName)
logger.Infof("launching binary: %v", enc.cmd)
err := enc.cmd.Run()
if err != nil {
logger.Errorf("error while launching ffmpeg: %v\n err: %v", enc.cmd.Args, err)
}
}
func (enc *X264ImageEncoder) Encode(img image.Image) {
err := encodePPM(enc.input, img)
if err != nil {
logger.Error("error while encoding image:", err)
}
}
func (enc *X264ImageEncoder) Close() {
}

View File

@ -1,121 +1,121 @@
package vnc2webm
import (
"bytes"
"image"
"image/draw"
"sync"
)
// EncodingType represents a known VNC encoding type.
type EncodingType int32
//go:generate stringer -type=EncodingType
const (
// EncRaw raw encoding
EncRaw EncodingType = 0
// EncCopyRect copyrect encoding
EncCopyRect EncodingType = 1
EncRRE EncodingType = 2
EncCoRRE EncodingType = 4
EncHextile EncodingType = 5
EncZlib EncodingType = 6
EncTight EncodingType = 7
EncZlibHex EncodingType = 8
EncUltra1 EncodingType = 9
EncUltra2 EncodingType = 10
EncJPEG EncodingType = 21
EncJRLE EncodingType = 22
EncTRLE EncodingType = 15
EncZRLE EncodingType = 16
EncAtenAST2100 EncodingType = 0x57
EncAtenASTJPEG EncodingType = 0x58
EncAtenHermon EncodingType = 0x59
EncAtenYarkon EncodingType = 0x60
EncAtenPilot3 EncodingType = 0x61
EncJPEGQualityLevelPseudo10 EncodingType = -23
EncJPEGQualityLevelPseudo9 EncodingType = -24
EncJPEGQualityLevelPseudo8 EncodingType = -25
EncJPEGQualityLevelPseudo7 EncodingType = -26
EncJPEGQualityLevelPseudo6 EncodingType = -27
EncJPEGQualityLevelPseudo5 EncodingType = -28
EncJPEGQualityLevelPseudo4 EncodingType = -29
EncJPEGQualityLevelPseudo3 EncodingType = -30
EncJPEGQualityLevelPseudo2 EncodingType = -31
EncJPEGQualityLevelPseudo1 EncodingType = -32
EncCursorPseudo EncodingType = -239
EncXCursorPseudo EncodingType = -240
EncDesktopSizePseudo EncodingType = -223
EncLastRectPseudo EncodingType = -224
EncCompressionLevel10 EncodingType = -247
EncCompressionLevel9 EncodingType = -248
EncCompressionLevel8 EncodingType = -249
EncCompressionLevel7 EncodingType = -250
EncCompressionLevel6 EncodingType = -251
EncCompressionLevel5 EncodingType = -252
EncCompressionLevel4 EncodingType = -253
EncCompressionLevel3 EncodingType = -254
EncCompressionLevel2 EncodingType = -255
EncCompressionLevel1 EncodingType = -256
EncQEMUPointerMotionChangePseudo EncodingType = -257
EncQEMUExtendedKeyEventPseudo EncodingType = -258
EncTightPng EncodingType = -260
EncDesktopNamePseudo EncodingType = -307
EncExtendedDesktopSizePseudo EncodingType = -308
EncXvpPseudo EncodingType = -309
EncClientRedirect EncodingType = -311
EncFencePseudo EncodingType = -312
EncContinuousUpdatesPseudo EncodingType = -313
)
var bPool = sync.Pool{
New: func() interface{} {
// The Pool's New function should generally only return pointer
// types, since a pointer can be put into the return interface
// value without an allocation:
return new(bytes.Buffer)
},
}
type Renderer interface {
SetTargetImage(draw.Image)
}
// Encoding represents interface for vnc encoding
type Encoding interface {
Type() EncodingType
Read(Conn, *Rectangle) error
Write(Conn, *Rectangle) error
Supported(Conn) bool
Reset() error
}
func setBit(n uint8, pos uint8) uint8 {
n |= (1 << pos)
return n
}
func clrBit(n uint8, pos uint8) uint8 {
n = n &^ (1 << pos)
return n
}
func hasBit(n uint8, pos uint8) bool {
v := n & (1 << pos)
return (v > 0)
}
func getBit(n uint8, pos uint8) uint8 {
n = n & (1 << pos)
return n
}
func newRGBAImage(rgba []byte, rect *Rectangle) image.Image {
img := &image.RGBA{Stride: 4 * int(rect.Width)}
img.Pix = rgba
img.Rect.Max.X = int(rect.Width)
img.Rect.Max.Y = int(rect.Height)
return img
}
package vnc2video
import (
"bytes"
"image"
"image/draw"
"sync"
)
// EncodingType represents a known VNC encoding type.
type EncodingType int32
//go:generate stringer -type=EncodingType
const (
// EncRaw raw encoding
EncRaw EncodingType = 0
// EncCopyRect copyrect encoding
EncCopyRect EncodingType = 1
EncRRE EncodingType = 2
EncCoRRE EncodingType = 4
EncHextile EncodingType = 5
EncZlib EncodingType = 6
EncTight EncodingType = 7
EncZlibHex EncodingType = 8
EncUltra1 EncodingType = 9
EncUltra2 EncodingType = 10
EncJPEG EncodingType = 21
EncJRLE EncodingType = 22
EncTRLE EncodingType = 15
EncZRLE EncodingType = 16
EncAtenAST2100 EncodingType = 0x57
EncAtenASTJPEG EncodingType = 0x58
EncAtenHermon EncodingType = 0x59
EncAtenYarkon EncodingType = 0x60
EncAtenPilot3 EncodingType = 0x61
EncJPEGQualityLevelPseudo10 EncodingType = -23
EncJPEGQualityLevelPseudo9 EncodingType = -24
EncJPEGQualityLevelPseudo8 EncodingType = -25
EncJPEGQualityLevelPseudo7 EncodingType = -26
EncJPEGQualityLevelPseudo6 EncodingType = -27
EncJPEGQualityLevelPseudo5 EncodingType = -28
EncJPEGQualityLevelPseudo4 EncodingType = -29
EncJPEGQualityLevelPseudo3 EncodingType = -30
EncJPEGQualityLevelPseudo2 EncodingType = -31
EncJPEGQualityLevelPseudo1 EncodingType = -32
EncCursorPseudo EncodingType = -239
EncXCursorPseudo EncodingType = -240
EncDesktopSizePseudo EncodingType = -223
EncLastRectPseudo EncodingType = -224
EncCompressionLevel10 EncodingType = -247
EncCompressionLevel9 EncodingType = -248
EncCompressionLevel8 EncodingType = -249
EncCompressionLevel7 EncodingType = -250
EncCompressionLevel6 EncodingType = -251
EncCompressionLevel5 EncodingType = -252
EncCompressionLevel4 EncodingType = -253
EncCompressionLevel3 EncodingType = -254
EncCompressionLevel2 EncodingType = -255
EncCompressionLevel1 EncodingType = -256
EncQEMUPointerMotionChangePseudo EncodingType = -257
EncQEMUExtendedKeyEventPseudo EncodingType = -258
EncTightPng EncodingType = -260
EncDesktopNamePseudo EncodingType = -307
EncExtendedDesktopSizePseudo EncodingType = -308
EncXvpPseudo EncodingType = -309
EncClientRedirect EncodingType = -311
EncFencePseudo EncodingType = -312
EncContinuousUpdatesPseudo EncodingType = -313
)
var bPool = sync.Pool{
New: func() interface{} {
// The Pool's New function should generally only return pointer
// types, since a pointer can be put into the return interface
// value without an allocation:
return new(bytes.Buffer)
},
}
type Renderer interface {
SetTargetImage(draw.Image)
}
// Encoding represents interface for vnc encoding
type Encoding interface {
Type() EncodingType
Read(Conn, *Rectangle) error
Write(Conn, *Rectangle) error
Supported(Conn) bool
Reset() error
}
func setBit(n uint8, pos uint8) uint8 {
n |= (1 << pos)
return n
}
func clrBit(n uint8, pos uint8) uint8 {
n = n &^ (1 << pos)
return n
}
func hasBit(n uint8, pos uint8) bool {
v := n & (1 << pos)
return (v > 0)
}
func getBit(n uint8, pos uint8) uint8 {
n = n & (1 << pos)
return n
}
func newRGBAImage(rgba []byte, rect *Rectangle) image.Image {
img := &image.RGBA{Stride: 4 * int(rect.Width)}
img.Pix = rgba
img.Rect.Max.X = int(rect.Width)
img.Rect.Max.Y = int(rect.Height)
return img
}

View File

@ -1,216 +1,216 @@
package vnc2webm
import (
"encoding/binary"
"fmt"
)
const (
EncAtenHermonSubrect EncodingType = 0
EncAtenHermonRaw EncodingType = 1
)
type AtenHermon struct {
_ [4]byte
AtenLength uint32
AtenType uint8
_ [1]byte
AtenSubrects uint32
AtenRawLength uint32
Encodings []Encoding
}
type AtenHermonSubrect struct {
A uint16
B uint16
Y uint8
X uint8
Data []byte
}
func (*AtenHermon) Supported(Conn) bool {
return false
}
func (*AtenHermon) Type() EncodingType { return EncAtenHermon }
func (*AtenHermon) Reset() error {
return nil
}
func (enc *AtenHermon) Read(c Conn, rect *Rectangle) error {
var pad4 [4]byte
if err := binary.Read(c, binary.BigEndian, &pad4); err != nil {
return err
}
var aten_length uint32
if err := binary.Read(c, binary.BigEndian, &aten_length); err != nil {
return err
}
enc.AtenLength = aten_length
if rect.Width == 64896 && rect.Height == 65056 {
if aten_length != 10 && aten_length != 0 {
return fmt.Errorf("screen is off and length is invalid")
}
aten_length = 0
}
if c.Width() != rect.Width && c.Height() != rect.Height {
c.SetWidth(rect.Width)
c.SetHeight(rect.Height)
}
var aten_type uint8
if err := binary.Read(c, binary.BigEndian, &aten_type); err != nil {
return err
}
enc.AtenType = aten_type
var pad1 [1]byte
if err := binary.Read(c, binary.BigEndian, &pad1); err != nil {
return err
}
var subrects uint32
if err := binary.Read(c, binary.BigEndian, &subrects); err != nil {
return err
}
enc.AtenSubrects = subrects
var raw_length uint32
if err := binary.Read(c, binary.BigEndian, &raw_length); err != nil {
return err
}
enc.AtenRawLength = raw_length
if aten_length != raw_length {
return fmt.Errorf("aten_length != raw_length, %d != %d", aten_length, raw_length)
}
aten_length -= 10 // skip
for aten_length > 0 {
switch EncodingType(aten_type) {
case EncAtenHermonSubrect:
encSR := &AtenHermonSubrect{}
if err := encSR.Read(c, rect); err != nil {
return err
}
enc.Encodings = append(enc.Encodings, encSR)
aten_length -= 6 + (16 * 16 * uint32(c.PixelFormat().BPP/8))
case EncAtenHermonRaw:
encRaw := &RawEncoding{}
if err := encRaw.Read(c, rect); err != nil {
return err
}
enc.Encodings = append(enc.Encodings, encRaw)
aten_length -= uint32(rect.Area()) * uint32(c.PixelFormat().BPP/8)
default:
return fmt.Errorf("unknown aten hermon type %d", aten_type)
}
}
if aten_length < 0 {
return fmt.Errorf("aten_len dropped below zero")
}
return nil
}
func (enc *AtenHermon) Write(c Conn, rect *Rectangle) error {
if !enc.Supported(c) {
for _, ew := range enc.Encodings {
if err := ew.Write(c, rect); err != nil {
return err
}
}
return nil
}
var pad4 [4]byte
if err := binary.Write(c, binary.BigEndian, pad4); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenLength); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenType); err != nil {
return err
}
var pad1 [1]byte
if err := binary.Write(c, binary.BigEndian, pad1); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenSubrects); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenRawLength); err != nil {
return err
}
for _, ew := range enc.Encodings {
if err := ew.Write(c, rect); err != nil {
return err
}
}
return nil
}
func (*AtenHermonSubrect) Supported(Conn) bool {
return false
}
func (enc *AtenHermonSubrect) Type() EncodingType {
return EncAtenHermonSubrect
}
func (*AtenHermonSubrect) Reset() error {
return nil
}
func (enc *AtenHermonSubrect) Read(c Conn, rect *Rectangle) error {
if err := binary.Read(c, binary.BigEndian, &enc.A); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.B); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.Y); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.X); err != nil {
return err
}
enc.Data = make([]byte, 16*16*uint32(c.PixelFormat().BPP/8))
if err := binary.Read(c, binary.BigEndian, &enc.Data); err != nil {
return err
}
return nil
}
func (enc *AtenHermonSubrect) Write(c Conn, rect *Rectangle) error {
if !enc.Supported(c) {
return nil
}
if err := binary.Write(c, binary.BigEndian, enc.A); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.B); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Y); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.X); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Data); err != nil {
return err
}
return nil
}
package vnc2video
import (
"encoding/binary"
"fmt"
)
const (
EncAtenHermonSubrect EncodingType = 0
EncAtenHermonRaw EncodingType = 1
)
type AtenHermon struct {
_ [4]byte
AtenLength uint32
AtenType uint8
_ [1]byte
AtenSubrects uint32
AtenRawLength uint32
Encodings []Encoding
}
type AtenHermonSubrect struct {
A uint16
B uint16
Y uint8
X uint8
Data []byte
}
func (*AtenHermon) Supported(Conn) bool {
return false
}
func (*AtenHermon) Type() EncodingType { return EncAtenHermon }
func (*AtenHermon) Reset() error {
return nil
}
func (enc *AtenHermon) Read(c Conn, rect *Rectangle) error {
var pad4 [4]byte
if err := binary.Read(c, binary.BigEndian, &pad4); err != nil {
return err
}
var aten_length uint32
if err := binary.Read(c, binary.BigEndian, &aten_length); err != nil {
return err
}
enc.AtenLength = aten_length
if rect.Width == 64896 && rect.Height == 65056 {
if aten_length != 10 && aten_length != 0 {
return fmt.Errorf("screen is off and length is invalid")
}
aten_length = 0
}
if c.Width() != rect.Width && c.Height() != rect.Height {
c.SetWidth(rect.Width)
c.SetHeight(rect.Height)
}
var aten_type uint8
if err := binary.Read(c, binary.BigEndian, &aten_type); err != nil {
return err
}
enc.AtenType = aten_type
var pad1 [1]byte
if err := binary.Read(c, binary.BigEndian, &pad1); err != nil {
return err
}
var subrects uint32
if err := binary.Read(c, binary.BigEndian, &subrects); err != nil {
return err
}
enc.AtenSubrects = subrects
var raw_length uint32
if err := binary.Read(c, binary.BigEndian, &raw_length); err != nil {
return err
}
enc.AtenRawLength = raw_length
if aten_length != raw_length {
return fmt.Errorf("aten_length != raw_length, %d != %d", aten_length, raw_length)
}
aten_length -= 10 // skip
for aten_length > 0 {
switch EncodingType(aten_type) {
case EncAtenHermonSubrect:
encSR := &AtenHermonSubrect{}
if err := encSR.Read(c, rect); err != nil {
return err
}
enc.Encodings = append(enc.Encodings, encSR)
aten_length -= 6 + (16 * 16 * uint32(c.PixelFormat().BPP/8))
case EncAtenHermonRaw:
encRaw := &RawEncoding{}
if err := encRaw.Read(c, rect); err != nil {
return err
}
enc.Encodings = append(enc.Encodings, encRaw)
aten_length -= uint32(rect.Area()) * uint32(c.PixelFormat().BPP/8)
default:
return fmt.Errorf("unknown aten hermon type %d", aten_type)
}
}
if aten_length < 0 {
return fmt.Errorf("aten_len dropped below zero")
}
return nil
}
func (enc *AtenHermon) Write(c Conn, rect *Rectangle) error {
if !enc.Supported(c) {
for _, ew := range enc.Encodings {
if err := ew.Write(c, rect); err != nil {
return err
}
}
return nil
}
var pad4 [4]byte
if err := binary.Write(c, binary.BigEndian, pad4); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenLength); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenType); err != nil {
return err
}
var pad1 [1]byte
if err := binary.Write(c, binary.BigEndian, pad1); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenSubrects); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.AtenRawLength); err != nil {
return err
}
for _, ew := range enc.Encodings {
if err := ew.Write(c, rect); err != nil {
return err
}
}
return nil
}
func (*AtenHermonSubrect) Supported(Conn) bool {
return false
}
func (enc *AtenHermonSubrect) Type() EncodingType {
return EncAtenHermonSubrect
}
func (*AtenHermonSubrect) Reset() error {
return nil
}
func (enc *AtenHermonSubrect) Read(c Conn, rect *Rectangle) error {
if err := binary.Read(c, binary.BigEndian, &enc.A); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.B); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.Y); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.X); err != nil {
return err
}
enc.Data = make([]byte, 16*16*uint32(c.PixelFormat().BPP/8))
if err := binary.Read(c, binary.BigEndian, &enc.Data); err != nil {
return err
}
return nil
}
func (enc *AtenHermonSubrect) Write(c Conn, rect *Rectangle) error {
if !enc.Supported(c) {
return nil
}
if err := binary.Write(c, binary.BigEndian, enc.A); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.B); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Y); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.X); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Data); err != nil {
return err
}
return nil
}

View File

@ -1,35 +1,35 @@
package vnc2webm
import "encoding/binary"
type CopyRectEncoding struct {
SX, SY uint16
}
func (*CopyRectEncoding) Supported(Conn) bool {
return true
}
func (*CopyRectEncoding) Reset() error {
return nil
}
func (*CopyRectEncoding) Type() EncodingType { return EncCopyRect }
func (enc *CopyRectEncoding) Read(c Conn, rect *Rectangle) error {
if err := binary.Read(c, binary.BigEndian, &enc.SX); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SY); err != nil {
return err
}
return nil
}
func (enc *CopyRectEncoding) Write(c Conn, rect *Rectangle) error {
if err := binary.Write(c, binary.BigEndian, enc.SX); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SY); err != nil {
return err
}
return nil
}
package vnc2video
import "encoding/binary"
type CopyRectEncoding struct {
SX, SY uint16
}
func (*CopyRectEncoding) Supported(Conn) bool {
return true
}
func (*CopyRectEncoding) Reset() error {
return nil
}
func (*CopyRectEncoding) Type() EncodingType { return EncCopyRect }
func (enc *CopyRectEncoding) Read(c Conn, rect *Rectangle) error {
if err := binary.Read(c, binary.BigEndian, &enc.SX); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SY); err != nil {
return err
}
return nil
}
func (enc *CopyRectEncoding) Write(c Conn, rect *Rectangle) error {
if err := binary.Write(c, binary.BigEndian, enc.SX); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SY); err != nil {
return err
}
return nil
}

60
encoding_corre.go Normal file
View File

@ -0,0 +1,60 @@
package vnc2video
import (
"encoding/binary"
"io"
)
type CoRREEncoding struct {
numSubRects uint32
backgroundColor []byte
subRectData []byte
}
func (z *CoRREEncoding) Type() int32 {
return 4
}
func (z *CoRREEncoding) WriteTo(w io.Writer) (n int, err error) {
binary.Write(w, binary.BigEndian, z.numSubRects)
if err != nil {
return 0, err
}
w.Write(z.backgroundColor)
if err != nil {
return 0, err
}
w.Write(z.subRectData)
if err != nil {
return 0, err
}
b := len(z.backgroundColor) + len(z.subRectData) + 4
return b, nil
}
func (z *CoRREEncoding) Read(r Conn, rect *Rectangle) error {
//func (z *CoRREEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
bytesPerPixel := int(r.PixelFormat().BPP / 8)
var numOfSubrectangles uint32
if err := binary.Read(r, binary.BigEndian, &numOfSubrectangles); err != nil {
return err
}
z.numSubRects = numOfSubrectangles
var err error
//read whole-rect background color
z.backgroundColor, err = ReadBytes(bytesPerPixel, r)
if err != nil {
return err
}
//read all individual rects (color=BPP + x=16b + y=16b + w=16b + h=16b)
z.subRectData, err = ReadBytes(int(numOfSubrectangles)*(bytesPerPixel+4), r)
if err != nil {
return err
}
return nil
}

View File

@ -1,90 +1,110 @@
package vnc2webm
import (
"encoding/binary"
"image"
"image/draw"
)
type CursorPseudoEncoding struct {
Colors []Color
BitMask []byte
Image image.Image
}
func (*CursorPseudoEncoding) Supported(Conn) bool {
return true
}
func (enc *CursorPseudoEncoding) SetTargetImage(img draw.Image) {
enc.Image = img
}
func (*CursorPseudoEncoding) Type() EncodingType { return EncCursorPseudo }
func (enc *CursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
rgba := make([]byte, int(rect.Height)*int(rect.Width)*int(c.PixelFormat().BPP/8))
if err := binary.Read(c, binary.BigEndian, &rgba); err != nil {
return err
}
bitmask := make([]byte, int((rect.Width+7)/8*rect.Height))
if err := binary.Read(c, binary.BigEndian, &bitmask); err != nil {
return err
}
/*
rectStride := 4 * rect.Width
for i := uint16(0); i < rect.Height; i++ {
for j := uint16(0); j < rect.Width; j += 8 {
for idx, k := j/8, 7; k >= 0; k-- {
if (bitmask[idx] & (1 << uint(k))) == 0 {
pIdx := j*4 + i*rectStride
rgbaBuffer[pIdx] = 0
rgbaBuffer[pIdx+1] = 0
rgbaBuffer[pIdx+2] = 0
rgbaBuffer[pIdx+3] = 0
}
}
}
}
*/
/*
int bytesPerPixel = renderer.getBytesPerPixel();
int length = rect.width * rect.height * bytesPerPixel;
if (0 == length)
return;
byte[] buffer = ByteBuffer.getInstance().getBuffer(length);
transport.readBytes(buffer, 0, length);
StringBuilder sb = new StringBuilder(" ");
for (int i=0; i<length; ++i) {
sb.append(Integer.toHexString(buffer[i]&0xff)).append(" ");
}
int scanLine = (rect.width + 7) / 8;
byte[] bitmask = new byte[scanLine * rect.height];
transport.readBytes(bitmask, 0, bitmask.length);
sb = new StringBuilder(" ");
for (byte aBitmask : bitmask) {
sb.append(Integer.toHexString(aBitmask & 0xff)).append(" ");
}
int[] cursorPixels = new int[rect.width * rect.height];
for (int y = 0; y < rect.height; ++y) {
for (int x = 0; x < rect.width; ++x) {
int offset = y * rect.width + x;
cursorPixels[offset] = isBitSet(bitmask[y * scanLine + x / 8], x % 8) ?
0xFF000000 | renderer.getPixelColor(buffer, offset * bytesPerPixel) :
0; // transparent
}
}
renderer.createCursor(cursorPixels, rect);
*/
return nil
}
func (enc *CursorPseudoEncoding) Write(c Conn, rect *Rectangle) error {
return nil
}
package vnc2video
import (
"encoding/binary"
"image/color"
"image/draw"
)
type CursorPseudoEncoding struct {
Colors []Color
BitMask []byte
Image draw.Image
}
func (*CursorPseudoEncoding) Supported(Conn) bool {
return true
}
func (enc *CursorPseudoEncoding) SetTargetImage(img draw.Image) {
enc.Image = img
}
func (*CursorPseudoEncoding) Type() EncodingType { return EncCursorPseudo }
func (enc *CursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
//rgba := make([]byte, int(rect.Height)*int(rect.Width)*int(c.PixelFormat().BPP/8))
numColors := int(rect.Height) * int(rect.Width)
colors := make([]color.Color, numColors)
var err error
pf := c.PixelFormat()
for i := 0; i < numColors; i++ {
colors[i], err = ReadColor(c, &pf)
if err != nil {
return err
}
}
// if err := binary.Read(c, binary.BigEndian, &rgba); err != nil {
// return err
// }
bitmask := make([]byte, int((rect.Width+7)/8*rect.Height))
if err := binary.Read(c, binary.BigEndian, &bitmask); err != nil {
return err
}
scanLine := (rect.Width + 7) / 8
//int[] cursorPixels = new int[rect.width * rect.height];
for y := 0; y < int(rect.Height); y++ {
for x := 0; x < int(rect.Width); x++ {
offset := y*int(rect.Width) + x
if bitmask[y*int(scanLine)+x/8]&(1<<uint(7-x%8)) > 0 {
enc.Image.Set(x, y, colors[offset])
}
}
}
/*
rectStride := 4 * rect.Width
for i := uint16(0); i < rect.Height; i++ {
for j := uint16(0); j < rect.Width; j += 8 {
for idx, k := j/8, 7; k >= 0; k-- {
if (bitmask[idx] & (1 << uint(k))) == 0 {
pIdx := j*4 + i*rectStride
rgba[pIdx] = 0
rgba[pIdx+1] = 0
rgba[pIdx+2] = 0
rgba[pIdx+3] = 0
}
}
}
}
*/
/*
int bytesPerPixel = renderer.getBytesPerPixel();
int length = rect.width * rect.height * bytesPerPixel;
if (0 == length)
return;
byte[] buffer = ByteBuffer.getInstance().getBuffer(length);
transport.readBytes(buffer, 0, length);
StringBuilder sb = new StringBuilder(" ");
for (int i=0; i<length; ++i) {
sb.append(Integer.toHexString(buffer[i]&0xff)).append(" ");
}
int scanLine = (rect.width + 7) / 8;
byte[] bitmask = new byte[scanLine * rect.height];
transport.readBytes(bitmask, 0, bitmask.length);
sb = new StringBuilder(" ");
for (byte aBitmask : bitmask) {
sb.append(Integer.toHexString(aBitmask & 0xff)).append(" ");
}
int[] cursorPixels = new int[rect.width * rect.height];
for (int y = 0; y < rect.height; ++y) {
for (int x = 0; x < rect.width; ++x) {
int offset = y * rect.width + x;
cursorPixels[offset] = isBitSet(bitmask[y * scanLine + x / 8], x % 8) ?
0xFF000000 | renderer.getPixelColor(buffer, offset * bytesPerPixel) :
0; // transparent
}
}
renderer.createCursor(cursorPixels, rect);
*/
return nil
}
func (enc *CursorPseudoEncoding) Write(c Conn, rect *Rectangle) error {
return nil
}

View File

@ -1,41 +1,41 @@
package vnc2webm
import "encoding/binary"
// DesktopNamePseudoEncoding represents a desktop size message from the server.
type DesktopNamePseudoEncoding struct {
Name []byte
}
func (*DesktopNamePseudoEncoding) Supported(Conn) bool {
return true
}
func (*DesktopNamePseudoEncoding) Reset() error {
return nil
}
func (*DesktopNamePseudoEncoding) Type() EncodingType { return EncDesktopNamePseudo }
// Read implements the Encoding interface.
func (enc *DesktopNamePseudoEncoding) Read(c Conn, rect *Rectangle) error {
var length uint32
if err := binary.Read(c, binary.BigEndian, &length); err != nil {
return err
}
name := make([]byte, length)
if err := binary.Read(c, binary.BigEndian, &name); err != nil {
return err
}
enc.Name = name
return nil
}
func (enc *DesktopNamePseudoEncoding) Write(c Conn, rect *Rectangle) error {
if err := binary.Write(c, binary.BigEndian, uint32(len(enc.Name))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Name); err != nil {
return err
}
return c.Flush()
}
package vnc2video
import "encoding/binary"
// DesktopNamePseudoEncoding represents a desktop size message from the server.
type DesktopNamePseudoEncoding struct {
Name []byte
}
func (*DesktopNamePseudoEncoding) Supported(Conn) bool {
return true
}
func (*DesktopNamePseudoEncoding) Reset() error {
return nil
}
func (*DesktopNamePseudoEncoding) Type() EncodingType { return EncDesktopNamePseudo }
// Read implements the Encoding interface.
func (enc *DesktopNamePseudoEncoding) Read(c Conn, rect *Rectangle) error {
var length uint32
if err := binary.Read(c, binary.BigEndian, &length); err != nil {
return err
}
name := make([]byte, length)
if err := binary.Read(c, binary.BigEndian, &name); err != nil {
return err
}
enc.Name = name
return nil
}
func (enc *DesktopNamePseudoEncoding) Write(c Conn, rect *Rectangle) error {
if err := binary.Write(c, binary.BigEndian, uint32(len(enc.Name))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Name); err != nil {
return err
}
return c.Flush()
}

View File

@ -1,21 +1,21 @@
package vnc2webm
// DesktopSizePseudoEncoding represents a desktop size message from the server.
type DesktopSizePseudoEncoding struct{}
func (*DesktopSizePseudoEncoding) Supported(Conn) bool {
return true
}
func (*DesktopSizePseudoEncoding) Reset() error {
return nil
}
func (*DesktopSizePseudoEncoding) Type() EncodingType { return EncDesktopSizePseudo }
// Read implements the Encoding interface.
func (*DesktopSizePseudoEncoding) Read(c Conn, rect *Rectangle) error {
return nil
}
func (enc *DesktopSizePseudoEncoding) Write(c Conn, rect *Rectangle) error {
return nil
}
package vnc2video
// DesktopSizePseudoEncoding represents a desktop size message from the server.
type DesktopSizePseudoEncoding struct{}
func (*DesktopSizePseudoEncoding) Supported(Conn) bool {
return true
}
func (*DesktopSizePseudoEncoding) Reset() error {
return nil
}
func (*DesktopSizePseudoEncoding) Type() EncodingType { return EncDesktopSizePseudo }
// Read implements the Encoding interface.
func (*DesktopSizePseudoEncoding) Read(c Conn, rect *Rectangle) error {
return nil
}
func (enc *DesktopSizePseudoEncoding) Write(c Conn, rect *Rectangle) error {
return nil
}

168
encoding_hextile.go Normal file
View File

@ -0,0 +1,168 @@
package vnc2video
import (
"encoding/binary"
"errors"
"image"
"image/color"
"image/draw"
"io"
"vnc2video/logger"
)
const (
HextileRaw = 1
HextileBackgroundSpecified = 2
HextileForegroundSpecified = 4
HextileAnySubrects = 8
HextileSubrectsColoured = 16
)
type HextileEncoding struct {
//Colors []Color
bytes []byte
Image draw.Image
}
// Read unmarshal color from conn
func ReadColor(c io.Reader, pf *PixelFormat) (*color.RGBA, error) {
if pf.TrueColor == 0 {
return nil, errors.New("support for non true color formats was not implemented")
}
order := pf.order()
var pixel uint32
switch pf.BPP {
case 8:
var px uint8
if err := binary.Read(c, order, &px); err != nil {
return nil, err
}
pixel = uint32(px)
case 16:
var px uint16
if err := binary.Read(c, order, &px); err != nil {
return nil, err
}
pixel = uint32(px)
case 32:
var px uint32
if err := binary.Read(c, order, &px); err != nil {
return nil, err
}
pixel = uint32(px)
}
rgb := color.RGBA{
R: uint8((pixel >> pf.RedShift) & uint32(pf.RedMax)),
G: uint8((pixel >> pf.GreenShift) & uint32(pf.GreenMax)),
B: uint8((pixel >> pf.BlueShift) & uint32(pf.BlueMax)),
A: 1,
}
return &rgb, nil
}
func (z *HextileEncoding) Type() int32 {
return 5
}
func (z *HextileEncoding) WriteTo(w io.Writer) (n int, err error) {
return w.Write(z.bytes)
}
func (z *HextileEncoding) Read(r Conn, rect *Rectangle) error {
//func (z *HextileEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
//bytesPerPixel := int(r.PixelFormat().BPP) / 8
pf := r.PixelFormat()
var bgCol *color.RGBA
var fgCol *color.RGBA
var err error
var dimensions byte
var subencoding byte
//r.StartByteCollection()
// defer func() {
// z.bytes = r.EndByteCollection()
// }()
for ty := rect.Y; ty < rect.Y+rect.Height; ty += 16 {
th := 16
if rect.Y+rect.Height-ty < 16 {
th = int(rect.Y) + int(rect.Height) - int(ty)
}
for tx := rect.X; tx < rect.X+rect.Width; tx += 16 {
tw := 16
if rect.X+rect.Width-tx < 16 {
tw = int(rect.X) + int(rect.Width) - int(tx)
}
//handle Hextile Subrect(tx, ty, tw, th):
subencoding, err = ReadUint8(r)
if err != nil {
logger.Errorf("HextileEncoding.Read: error in hextile reader: %v", err)
return err
}
if (subencoding & HextileRaw) != 0 {
rawEnc := r.GetEncInstance(EncRaw)
rawEnc.Read(r, &Rectangle{0, 0, uint16(tw), uint16(th), EncRaw, rawEnc})
//ReadBytes(tw*th*bytesPerPixel, r)
continue
}
if (subencoding & HextileBackgroundSpecified) != 0 {
//ReadBytes(int(bytesPerPixel), r)
bgCol, err = ReadColor(r, &pf)
rBounds := image.Rectangle{Min: image.Point{int(tx), int(ty)}, Max: image.Point{int(tw), int(th)}}
FillRect(z.Image, &rBounds, bgCol)
}
if (subencoding & HextileForegroundSpecified) != 0 {
fgCol, err = ReadColor(r, &pf)
}
if (subencoding & HextileAnySubrects) == 0 {
//logger.Debug("hextile reader: no Subrects")
continue
}
nSubrects, err := ReadUint8(r)
if err != nil {
return err
}
//bufsize := int(nSubrects) * 2
colorSpecified := ((subencoding & HextileSubrectsColoured) != 0)
for i := 0; i < int(nSubrects); i++ {
var color *color.RGBA
if colorSpecified {
color, err = ReadColor(r, &pf)
if err != nil {
logger.Error("Hextile decoder: problem reading color from connection: ", err)
return err
}
} else {
color = fgCol
}
//int color = colorSpecified ? renderer.readPixelColor(transport) : colors[FG_COLOR_INDEX];
fgCol = color
dimensions, err = ReadUint8(r) // bits 7-4 for x, bits 3-0 for y
if err != nil {
logger.Error("Hextile decoder: problem reading dimensions from connection: ", err)
return err
}
subtileX := dimensions >> 4 & 0x0f
subtileY := dimensions & 0x0f
dimensions, err = ReadUint8(r) // bits 7-4 for w, bits 3-0 for h
if err != nil {
logger.Error("Hextile decoder: problem reading 2nd dimensions from connection: ", err)
return err
}
subtileWidth := 1 + (dimensions >> 4 & 0x0f)
subtileHeight := 1 + (dimensions & 0x0f)
subrectBounds := image.Rectangle{Min: image.Point{int(tx) + int(subtileX), int(ty) + int(subtileY)}, Max: image.Point{int(subtileWidth), int(subtileHeight)}}
FillRect(z.Image, &subrectBounds, color)
}
}
}
return nil
}

View File

@ -1,60 +1,60 @@
package vnc2webm
import "image"
import "image/draw"
import "image/color"
type RawEncoding struct {
Image image.Image
//Colors []Color
}
func (*RawEncoding) Supported(Conn) bool {
return true
}
func (*RawEncoding) Reset() error {
return nil
}
func (enc *RawEncoding) Write(c Conn, rect *Rectangle) error {
var err error
//
//for _, clr := range enc.Colors {
// if err = clr.Write(c); err != nil {
// return err
// }
//}
return err
}
func (enc *RawEncoding) SetTargetImage(img draw.Image) {
enc.Image = img
}
// Read implements the Encoding interface.
func (enc *RawEncoding) Read(c Conn, rect *Rectangle) error {
pf := c.PixelFormat()
cm := c.ColorMap()
//colors := make([]Color, rect.Area())
for y := 0; y < int(rect.Height); y++ {
for x := 0; x < int(rect.Width); x++ {
c1 := NewColor(&pf, &cm)
if err := c1.Read(c); err != nil {
return err
}
c2:=color.RGBA{R:uint8(c1.R),G:uint8(c1.G),B:uint8(c1.B),A:1}
//c3 := color.RGBAModel.Convert(c2)
enc.Image.(draw.Image).Set(int(rect.X)+x,int(rect.Y)+y,c2)
//colors[int(y)*int(rect.Width)+int(x)] = *color
}
}
//enc.Colors = colors
return nil
}
func (*RawEncoding) Type() EncodingType { return EncRaw }
package vnc2video
import "image"
import "image/draw"
import "image/color"
type RawEncoding struct {
Image image.Image
//Colors []Color
}
func (*RawEncoding) Supported(Conn) bool {
return true
}
func (*RawEncoding) Reset() error {
return nil
}
func (enc *RawEncoding) Write(c Conn, rect *Rectangle) error {
var err error
//
//for _, clr := range enc.Colors {
// if err = clr.Write(c); err != nil {
// return err
// }
//}
return err
}
func (enc *RawEncoding) SetTargetImage(img draw.Image) {
enc.Image = img
}
// Read implements the Encoding interface.
func (enc *RawEncoding) Read(c Conn, rect *Rectangle) error {
pf := c.PixelFormat()
cm := c.ColorMap()
//colors := make([]Color, rect.Area())
for y := 0; y < int(rect.Height); y++ {
for x := 0; x < int(rect.Width); x++ {
c1 := NewColor(&pf, &cm)
if err := c1.Read(c); err != nil {
return err
}
c2:=color.RGBA{R:uint8(c1.R),G:uint8(c1.G),B:uint8(c1.B),A:1}
//c3 := color.RGBAModel.Convert(c2)
enc.Image.(draw.Image).Set(int(rect.X)+x,int(rect.Y)+y,c2)
//colors[int(y)*int(rect.Width)+int(x)] = *color
}
}
//enc.Colors = colors
return nil
}
func (*RawEncoding) Type() EncodingType { return EncRaw }

64
encoding_rre.go Normal file
View File

@ -0,0 +1,64 @@
package vnc2video
import (
"encoding/binary"
"io"
//"image/draw"
)
type RREEncoding struct {
//Colors []Color
numSubRects uint32
backgroundColor []byte
subRectData []byte
}
func (z *RREEncoding) WriteTo(w io.Writer) (n int, err error) {
binary.Write(w, binary.BigEndian, z.numSubRects)
if err != nil {
return 0, err
}
w.Write(z.backgroundColor)
if err != nil {
return 0, err
}
w.Write(z.subRectData)
if err != nil {
return 0, err
}
b := len(z.backgroundColor) + len(z.subRectData) + 4
return b, nil
}
func (z *RREEncoding) Type() int32 {
return 2
}
func (z *RREEncoding) Read(r Conn, rect *Rectangle) error {
//func (z *RREEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
bytesPerPixel := int(r.PixelFormat().BPP / 8)
var numOfSubrectangles uint32
if err := binary.Read(r, binary.BigEndian, &numOfSubrectangles); err != nil {
return err
}
var err error
z.numSubRects = numOfSubrectangles
//read whole-rect background color
z.backgroundColor, err = ReadBytes(bytesPerPixel, r)
if err != nil {
return err
}
//read all individual rects (color=bytesPerPixel + x=16b + y=16b + w=16b + h=16b)
z.subRectData, err = ReadBytes(int(numOfSubrectangles)*(bytesPerPixel+8), r) // x+y+w+h=8 bytes
if err != nil {
return err
}
return nil
}

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +1,95 @@
package vnc2webm
import (
"bytes"
"encoding/binary"
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"io"
"vnc2webm/logger"
)
func (*TightPngEncoding) Supported(Conn) bool {
return true
}
func (*TightPngEncoding) Reset() error {
return nil
}
func (enc *TightPngEncoding) Write(c Conn, rect *Rectangle) error {
if err := writeTightCC(c, enc.TightCC); err != nil {
return err
}
cmp := enc.TightCC.Compression
switch cmp {
case TightCompressionPNG:
buf := bPool.Get().(*bytes.Buffer)
buf.Reset()
defer bPool.Put(buf)
pngEnc := &png.Encoder{CompressionLevel: png.BestSpeed}
//pngEnc := &png.Encoder{CompressionLevel: png.NoCompression}
if err := pngEnc.Encode(buf, enc.Image); err != nil {
return err
}
if err := writeTightLength(c, buf.Len()); err != nil {
return err
}
if _, err := buf.WriteTo(c); err != nil {
return err
}
case TightCompressionFill:
var tpx TightPixel
r, g, b, _ := enc.Image.At(0, 0).RGBA()
tpx.R = uint8(r)
tpx.G = uint8(g)
tpx.B = uint8(b)
if err := binary.Write(c, binary.BigEndian, tpx); err != nil {
return err
}
default:
return fmt.Errorf("unknown tight compression %d", cmp)
}
return nil
}
type TightPngEncoding struct {
TightCC *TightCC
Image image.Image
}
func (*TightPngEncoding) Type() EncodingType { return EncTightPng }
func (enc *TightPngEncoding) Read(c Conn, rect *Rectangle) error {
tcc, err := readTightCC(c)
logger.Debug("starting to read a tight rect: %v", rect)
if err != nil {
return err
}
enc.TightCC = tcc
cmp := enc.TightCC.Compression
switch cmp {
case TightCompressionPNG:
l, err := readTightLength(c)
if err != nil {
return err
}
enc.Image, err = png.Decode(io.LimitReader(c, int64(l)))
if err != nil {
return err
}
case TightCompressionFill:
var tpx TightPixel
if err := binary.Read(c, binary.BigEndian, &tpx); err != nil {
return err
}
enc.Image = image.NewRGBA(image.Rect(0, 0, 1, 1))
enc.Image.(draw.Image).Set(0, 0, color.RGBA{R: tpx.R, G: tpx.G, B: tpx.B, A: 1})
default:
return fmt.Errorf("unknown compression %d", cmp)
}
return nil
}
package vnc2video
import (
"bytes"
"encoding/binary"
"fmt"
"image"
"image/color"
"image/draw"
"image/png"
"io"
"vnc2video/logger"
)
func (*TightPngEncoding) Supported(Conn) bool {
return true
}
func (*TightPngEncoding) Reset() error {
return nil
}
func (enc *TightPngEncoding) Write(c Conn, rect *Rectangle) error {
if err := writeTightCC(c, enc.TightCC); err != nil {
return err
}
cmp := enc.TightCC.Compression
switch cmp {
case TightCompressionPNG:
buf := bPool.Get().(*bytes.Buffer)
buf.Reset()
defer bPool.Put(buf)
pngEnc := &png.Encoder{CompressionLevel: png.BestSpeed}
//pngEnc := &png.Encoder{CompressionLevel: png.NoCompression}
if err := pngEnc.Encode(buf, enc.Image); err != nil {
return err
}
if err := writeTightLength(c, buf.Len()); err != nil {
return err
}
if _, err := buf.WriteTo(c); err != nil {
return err
}
case TightCompressionFill:
var tpx TightPixel
r, g, b, _ := enc.Image.At(0, 0).RGBA()
tpx.R = uint8(r)
tpx.G = uint8(g)
tpx.B = uint8(b)
if err := binary.Write(c, binary.BigEndian, tpx); err != nil {
return err
}
default:
return fmt.Errorf("unknown tight compression %d", cmp)
}
return nil
}
type TightPngEncoding struct {
TightCC *TightCC
Image image.Image
}
func (*TightPngEncoding) Type() EncodingType { return EncTightPng }
func (enc *TightPngEncoding) Read(c Conn, rect *Rectangle) error {
tcc, err := readTightCC(c)
logger.Debug("starting to read a tight rect: %v", rect)
if err != nil {
return err
}
enc.TightCC = tcc
cmp := enc.TightCC.Compression
switch cmp {
case TightCompressionPNG:
l, err := readTightLength(c)
if err != nil {
return err
}
enc.Image, err = png.Decode(io.LimitReader(c, int64(l)))
if err != nil {
return err
}
case TightCompressionFill:
var tpx TightPixel
if err := binary.Read(c, binary.BigEndian, &tpx); err != nil {
return err
}
enc.Image = image.NewRGBA(image.Rect(0, 0, 1, 1))
enc.Image.(draw.Image).Set(0, 0, color.RGBA{R: tpx.R, G: tpx.G, B: tpx.B, A: 1})
default:
return fmt.Errorf("unknown compression %d", cmp)
}
return nil
}

19
encoding_util.go Normal file
View File

@ -0,0 +1,19 @@
package vnc2video
import (
"image"
"image/color"
"image/draw"
)
func FillRect(img draw.Image, rect *image.Rectangle, c color.Color) {
for x := 0; x < rect.Max.X; x++ {
for y := 0; y < rect.Max.Y; y++ {
img.Set(x, y, c)
}
}
}
func DrawLine(img draw.Image, rect *image.Rectangle, c color.Color) {
}

View File

@ -1,92 +1,92 @@
package vnc2webm
import (
"encoding/binary"
"math"
)
type XCursorPseudoEncoding struct {
PrimaryR uint8
PrimaryG uint8
PrimaryB uint8
SecondaryR uint8
SecondaryG uint8
SecondaryB uint8
Bitmap []byte
Bitmask []byte
}
func (*XCursorPseudoEncoding) Supported(Conn) bool {
return true
}
func (*XCursorPseudoEncoding) Reset() error {
return nil
}
func (*XCursorPseudoEncoding) Type() EncodingType { return EncXCursorPseudo }
// Read implements the Encoding interface.
func (enc *XCursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
if err := binary.Read(c, binary.BigEndian, &enc.PrimaryR); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.PrimaryG); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.PrimaryB); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SecondaryR); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SecondaryG); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SecondaryB); err != nil {
return err
}
bitmapsize := int(math.Floor((float64(rect.Width)+7)/8) * float64(rect.Height))
bitmasksize := int(math.Floor((float64(rect.Width)+7)/8) * float64(rect.Height))
enc.Bitmap = make([]byte, bitmapsize)
enc.Bitmask = make([]byte, bitmasksize)
if err := binary.Read(c, binary.BigEndian, &enc.Bitmap); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.Bitmask); err != nil {
return err
}
return nil
}
func (enc *XCursorPseudoEncoding) Write(c Conn, rect *Rectangle) error {
if err := binary.Write(c, binary.BigEndian, enc.PrimaryR); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.PrimaryG); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.PrimaryB); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SecondaryR); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SecondaryG); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SecondaryB); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Bitmap); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Bitmask); err != nil {
return err
}
return nil
}
package vnc2video
import (
"encoding/binary"
"math"
)
type XCursorPseudoEncoding struct {
PrimaryR uint8
PrimaryG uint8
PrimaryB uint8
SecondaryR uint8
SecondaryG uint8
SecondaryB uint8
Bitmap []byte
Bitmask []byte
}
func (*XCursorPseudoEncoding) Supported(Conn) bool {
return true
}
func (*XCursorPseudoEncoding) Reset() error {
return nil
}
func (*XCursorPseudoEncoding) Type() EncodingType { return EncXCursorPseudo }
// Read implements the Encoding interface.
func (enc *XCursorPseudoEncoding) Read(c Conn, rect *Rectangle) error {
if err := binary.Read(c, binary.BigEndian, &enc.PrimaryR); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.PrimaryG); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.PrimaryB); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SecondaryR); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SecondaryG); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.SecondaryB); err != nil {
return err
}
bitmapsize := int(math.Floor((float64(rect.Width)+7)/8) * float64(rect.Height))
bitmasksize := int(math.Floor((float64(rect.Width)+7)/8) * float64(rect.Height))
enc.Bitmap = make([]byte, bitmapsize)
enc.Bitmask = make([]byte, bitmasksize)
if err := binary.Read(c, binary.BigEndian, &enc.Bitmap); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &enc.Bitmask); err != nil {
return err
}
return nil
}
func (enc *XCursorPseudoEncoding) Write(c Conn, rect *Rectangle) error {
if err := binary.Write(c, binary.BigEndian, enc.PrimaryR); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.PrimaryG); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.PrimaryB); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SecondaryR); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SecondaryG); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.SecondaryB); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Bitmap); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, enc.Bitmask); err != nil {
return err
}
return nil
}

38
encoding_zlib.go Normal file
View File

@ -0,0 +1,38 @@
package vnc2video
import (
"bytes"
"encoding/binary"
"io"
)
type ZLibEncoding struct {
bytes []byte
}
func (z *ZLibEncoding) Type() int32 {
return 6
}
func (z *ZLibEncoding) WriteTo(w io.Writer) (n int, err error) {
return w.Write(z.bytes)
}
func (z *ZLibEncoding) Read(r Conn, rect *Rectangle) error {
//func (z *ZLibEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
//conn := RfbReadHelper{Reader:r}
//conn := &DataSource{conn: conn.c, PixelFormat: conn.PixelFormat}
//bytesPerPixel := c.PixelFormat.BPP / 8
bytes := &bytes.Buffer{}
len, err := ReadUint32(r)
if err != nil {
return err
}
binary.Write(bytes, binary.BigEndian, len)
_, err = ReadBytes(int(len), r)
if err != nil {
return err
}
//StoreBytes(bytes, bts)
z.bytes = bytes.Bytes()
return nil
}

37
encoding_zrle.go Normal file
View File

@ -0,0 +1,37 @@
package vnc2video
import (
"bytes"
"encoding/binary"
"io"
)
type ZRLEEncoding struct {
bytes []byte
}
func (z *ZRLEEncoding) Type() int32 {
return 16
}
func (z *ZRLEEncoding) WriteTo(w io.Writer) (n int, err error) {
return w.Write(z.bytes)
}
func (z *ZRLEEncoding) Read(r Conn, rect *Rectangle) error {
//func (z *ZRLEEncoding) Read(pixelFmt *PixelFormat, rect *Rectangle, r io.Reader) (Encoding, error) {
bytes := &bytes.Buffer{}
len, err := ReadUint32(r)
if err != nil {
return err
}
binary.Write(bytes, binary.BigEndian, len)
_, err = ReadBytes(int(len), r)
if err != nil {
return err
}
//StoreBytes(bytes, bts)
z.bytes = bytes.Bytes()
return nil
}

View File

@ -1,69 +1,69 @@
// Code generated by "stringer -type=EncodingType"; DO NOT EDIT.
package vnc2webm
import "fmt"
const _EncodingType_name = "EncContinuousUpdatesPseudoEncFencePseudoEncClientRedirectEncXvpPseudoEncExtendedDesktopSizePseudoEncDesktopNamePseudoEncTightPngEncQEMUExtendedKeyEventPseudoEncQEMUPointerMotionChangePseudoEncCompressionLevel1EncCompressionLevel2EncCompressionLevel3EncCompressionLevel4EncCompressionLevel5EncCompressionLevel6EncCompressionLevel7EncCompressionLevel8EncCompressionLevel9EncCompressionLevel10EncXCursorPseudoEncCursorPseudoEncLastRectPseudoEncDesktopSizePseudoEncJPEGQualityLevelPseudo1EncJPEGQualityLevelPseudo2EncJPEGQualityLevelPseudo3EncJPEGQualityLevelPseudo4EncJPEGQualityLevelPseudo5EncJPEGQualityLevelPseudo6EncJPEGQualityLevelPseudo7EncJPEGQualityLevelPseudo8EncJPEGQualityLevelPseudo9EncJPEGQualityLevelPseudo10EncRawEncCopyRectEncRREEncCoRREEncHextileEncZlibEncTightEncZlibHexEncUltra1EncUltra2EncTRLEEncZRLEEncJPEGEncJRLEEncAtenAST2100EncAtenASTJPEGEncAtenHermonEncAtenYarkonEncAtenPilot3"
var _EncodingType_map = map[EncodingType]string{
-313: _EncodingType_name[0:26],
-312: _EncodingType_name[26:40],
-311: _EncodingType_name[40:57],
-309: _EncodingType_name[57:69],
-308: _EncodingType_name[69:97],
-307: _EncodingType_name[97:117],
-260: _EncodingType_name[117:128],
-258: _EncodingType_name[128:157],
-257: _EncodingType_name[157:189],
-256: _EncodingType_name[189:209],
-255: _EncodingType_name[209:229],
-254: _EncodingType_name[229:249],
-253: _EncodingType_name[249:269],
-252: _EncodingType_name[269:289],
-251: _EncodingType_name[289:309],
-250: _EncodingType_name[309:329],
-249: _EncodingType_name[329:349],
-248: _EncodingType_name[349:369],
-247: _EncodingType_name[369:390],
-240: _EncodingType_name[390:406],
-239: _EncodingType_name[406:421],
-224: _EncodingType_name[421:438],
-223: _EncodingType_name[438:458],
-32: _EncodingType_name[458:484],
-31: _EncodingType_name[484:510],
-30: _EncodingType_name[510:536],
-29: _EncodingType_name[536:562],
-28: _EncodingType_name[562:588],
-27: _EncodingType_name[588:614],
-26: _EncodingType_name[614:640],
-25: _EncodingType_name[640:666],
-24: _EncodingType_name[666:692],
-23: _EncodingType_name[692:719],
0: _EncodingType_name[719:725],
1: _EncodingType_name[725:736],
2: _EncodingType_name[736:742],
4: _EncodingType_name[742:750],
5: _EncodingType_name[750:760],
6: _EncodingType_name[760:767],
7: _EncodingType_name[767:775],
8: _EncodingType_name[775:785],
9: _EncodingType_name[785:794],
10: _EncodingType_name[794:803],
15: _EncodingType_name[803:810],
16: _EncodingType_name[810:817],
21: _EncodingType_name[817:824],
22: _EncodingType_name[824:831],
87: _EncodingType_name[831:845],
88: _EncodingType_name[845:859],
89: _EncodingType_name[859:872],
96: _EncodingType_name[872:885],
97: _EncodingType_name[885:898],
}
func (i EncodingType) String() string {
if str, ok := _EncodingType_map[i]; ok {
return str
}
return fmt.Sprintf("EncodingType(%d)", i)
}
// Code generated by "stringer -type=EncodingType"; DO NOT EDIT.
package vnc2video
import "fmt"
const _EncodingType_name = "EncContinuousUpdatesPseudoEncFencePseudoEncClientRedirectEncXvpPseudoEncExtendedDesktopSizePseudoEncDesktopNamePseudoEncTightPngEncQEMUExtendedKeyEventPseudoEncQEMUPointerMotionChangePseudoEncCompressionLevel1EncCompressionLevel2EncCompressionLevel3EncCompressionLevel4EncCompressionLevel5EncCompressionLevel6EncCompressionLevel7EncCompressionLevel8EncCompressionLevel9EncCompressionLevel10EncXCursorPseudoEncCursorPseudoEncLastRectPseudoEncDesktopSizePseudoEncJPEGQualityLevelPseudo1EncJPEGQualityLevelPseudo2EncJPEGQualityLevelPseudo3EncJPEGQualityLevelPseudo4EncJPEGQualityLevelPseudo5EncJPEGQualityLevelPseudo6EncJPEGQualityLevelPseudo7EncJPEGQualityLevelPseudo8EncJPEGQualityLevelPseudo9EncJPEGQualityLevelPseudo10EncRawEncCopyRectEncRREEncCoRREEncHextileEncZlibEncTightEncZlibHexEncUltra1EncUltra2EncTRLEEncZRLEEncJPEGEncJRLEEncAtenAST2100EncAtenASTJPEGEncAtenHermonEncAtenYarkonEncAtenPilot3"
var _EncodingType_map = map[EncodingType]string{
-313: _EncodingType_name[0:26],
-312: _EncodingType_name[26:40],
-311: _EncodingType_name[40:57],
-309: _EncodingType_name[57:69],
-308: _EncodingType_name[69:97],
-307: _EncodingType_name[97:117],
-260: _EncodingType_name[117:128],
-258: _EncodingType_name[128:157],
-257: _EncodingType_name[157:189],
-256: _EncodingType_name[189:209],
-255: _EncodingType_name[209:229],
-254: _EncodingType_name[229:249],
-253: _EncodingType_name[249:269],
-252: _EncodingType_name[269:289],
-251: _EncodingType_name[289:309],
-250: _EncodingType_name[309:329],
-249: _EncodingType_name[329:349],
-248: _EncodingType_name[349:369],
-247: _EncodingType_name[369:390],
-240: _EncodingType_name[390:406],
-239: _EncodingType_name[406:421],
-224: _EncodingType_name[421:438],
-223: _EncodingType_name[438:458],
-32: _EncodingType_name[458:484],
-31: _EncodingType_name[484:510],
-30: _EncodingType_name[510:536],
-29: _EncodingType_name[536:562],
-28: _EncodingType_name[562:588],
-27: _EncodingType_name[588:614],
-26: _EncodingType_name[614:640],
-25: _EncodingType_name[640:666],
-24: _EncodingType_name[666:692],
-23: _EncodingType_name[692:719],
0: _EncodingType_name[719:725],
1: _EncodingType_name[725:736],
2: _EncodingType_name[736:742],
4: _EncodingType_name[742:750],
5: _EncodingType_name[750:760],
6: _EncodingType_name[760:767],
7: _EncodingType_name[767:775],
8: _EncodingType_name[775:785],
9: _EncodingType_name[785:794],
10: _EncodingType_name[794:803],
15: _EncodingType_name[803:810],
16: _EncodingType_name[810:817],
21: _EncodingType_name[817:824],
22: _EncodingType_name[824:831],
87: _EncodingType_name[831:845],
88: _EncodingType_name[845:859],
89: _EncodingType_name[859:872],
96: _EncodingType_name[872:885],
97: _EncodingType_name[885:898],
}
func (i EncodingType) String() string {
if str, ok := _EncodingType_map[i]; ok {
return str
}
return fmt.Sprintf("EncodingType(%d)", i)
}

View File

@ -1,102 +1,102 @@
package main
import (
"context"
"image"
"net"
"os"
"time"
vnc "vnc2webm"
"vnc2webm/encoders"
"vnc2webm/logger"
)
func main() {
// Establish TCP connection to VNC server.
nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second)
if err != nil {
logger.Fatalf("Error connecting to VNC host. %v", err)
}
logger.Debugf("starting up the client, connecting to: %s", os.Args[1])
// Negotiate connection with the server.
cchServer := make(chan vnc.ServerMessage)
cchClient := make(chan vnc.ClientMessage)
errorCh := make(chan error)
ccfg := &vnc.ClientConfig{
SecurityHandlers: []vnc.SecurityHandler{
//&vnc.ClientAuthATEN{Username: []byte(os.Args[2]), Password: []byte(os.Args[3])}
&vnc.ClientAuthVNC{Password: []byte("12345")},
&vnc.ClientAuthNone{},
},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: cchClient,
ServerMessageCh: cchServer,
Messages: vnc.DefaultServerMessages,
Encodings: []vnc.Encoding{&vnc.RawEncoding{}, &vnc.TightEncoding{}},
ErrorCh: errorCh,
}
cc, err := vnc.Connect(context.Background(), nc, ccfg)
if err != nil {
logger.Fatalf("Error negotiating connection to VNC host. %v", err)
}
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
//vcodec := &encoders.MJPegImageEncoder{Quality: 60, Framerate: 6}
vcodec := &encoders.X264ImageEncoder{}
//vcodec := &encoders.DV8ImageEncoder{}
//vcodec := &encoders.DV9ImageEncoder{}
//counter := 0
//vcodec.Init("./output" + strconv.Itoa(counter))
go vcodec.Run("./ffmpeg", "./output.mp4")
screenImage := image.NewRGBA(image.Rect(0, 0, int(cc.Width()), int(cc.Height())))
for _, enc := range ccfg.Encodings {
myRenderer, ok := enc.(vnc.Renderer)
if ok {
myRenderer.SetTargetImage(screenImage)
}
}
// var out *os.File
logger.Debugf("connected to: %s", os.Args[1])
defer cc.Close()
cc.SetEncodings([]vnc.EncodingType{vnc.EncTight})
//rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height()))
//screenImage := image.NewRGBA64(rect)
// Process messages coming in on the ServerMessage channel.
for {
select {
case err := <-errorCh:
panic(err)
case msg := <-cchClient:
logger.Debugf("Received client message type:%v msg:%v\n", msg.Type(), msg)
case msg := <-cchServer:
logger.Debugf("Received server message type:%v msg:%v\n", msg.Type(), msg)
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
if msg.Type() == vnc.FramebufferUpdateMsgType {
//counter++
//jpeg.Encode(out, screenImage, nil)
vcodec.Encode(screenImage)
reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()}
//cc.ResetAllEncodings()
reqMsg.Write(cc)
}
}
}
//cc.Wait()
}
package main
import (
"context"
"image"
"net"
"os"
"time"
vnc "vnc2video"
"vnc2video/encoders"
"vnc2video/logger"
)
func main() {
// Establish TCP connection to VNC server.
nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second)
if err != nil {
logger.Fatalf("Error connecting to VNC host. %v", err)
}
logger.Debugf("starting up the client, connecting to: %s", os.Args[1])
// Negotiate connection with the server.
cchServer := make(chan vnc.ServerMessage)
cchClient := make(chan vnc.ClientMessage)
errorCh := make(chan error)
ccfg := &vnc.ClientConfig{
SecurityHandlers: []vnc.SecurityHandler{
//&vnc.ClientAuthATEN{Username: []byte(os.Args[2]), Password: []byte(os.Args[3])}
&vnc.ClientAuthVNC{Password: []byte("12345")},
&vnc.ClientAuthNone{},
},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: cchClient,
ServerMessageCh: cchServer,
Messages: vnc.DefaultServerMessages,
Encodings: []vnc.Encoding{&vnc.RawEncoding{}, &vnc.TightEncoding{}},
ErrorCh: errorCh,
}
cc, err := vnc.Connect(context.Background(), nc, ccfg)
if err != nil {
logger.Fatalf("Error negotiating connection to VNC host. %v", err)
}
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
//vcodec := &encoders.MJPegImageEncoder{Quality: 60, Framerate: 6}
vcodec := &encoders.X264ImageEncoder{}
//vcodec := &encoders.DV8ImageEncoder{}
//vcodec := &encoders.DV9ImageEncoder{}
//counter := 0
//vcodec.Init("./output" + strconv.Itoa(counter))
go vcodec.Run("./ffmpeg", "./output.mp4")
screenImage := image.NewRGBA(image.Rect(0, 0, int(cc.Width()), int(cc.Height())))
for _, enc := range ccfg.Encodings {
myRenderer, ok := enc.(vnc.Renderer)
if ok {
myRenderer.SetTargetImage(screenImage)
}
}
// var out *os.File
logger.Debugf("connected to: %s", os.Args[1])
defer cc.Close()
cc.SetEncodings([]vnc.EncodingType{vnc.EncTight})
//rect := image.Rect(0, 0, int(cc.Width()), int(cc.Height()))
//screenImage := image.NewRGBA64(rect)
// Process messages coming in on the ServerMessage channel.
for {
select {
case err := <-errorCh:
panic(err)
case msg := <-cchClient:
logger.Debugf("Received client message type:%v msg:%v\n", msg.Type(), msg)
case msg := <-cchServer:
logger.Debugf("Received server message type:%v msg:%v\n", msg.Type(), msg)
// out, err := os.Create("./output" + strconv.Itoa(counter) + ".jpg")
// if err != nil {
// fmt.Println(err)
// os.Exit(1)
// }
if msg.Type() == vnc.FramebufferUpdateMsgType {
//counter++
//jpeg.Encode(out, screenImage, nil)
vcodec.Encode(screenImage)
reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()}
//cc.ResetAllEncodings()
reqMsg.Write(cc)
}
}
}
//cc.Wait()
}

View File

@ -1,61 +1,61 @@
package main
import (
"image"
"os"
vnc "vnc2webm"
"vnc2webm/encoders"
"vnc2webm/logger"
"path/filepath"
)
func main() {
if len(os.Args) <= 1 {
logger.Errorf("please provide a fbs file name")
return
}
if _, err := os.Stat(os.Args[1]); os.IsNotExist(err) {
logger.Errorf("File doesn't exist", err)
return
}
encs := []vnc.Encoding{
&vnc.RawEncoding{},
&vnc.TightEncoding{},
}
fbs, err := vnc.NewFbsConn(
os.Args[1],
encs,
)
if err != nil {
logger.Error("failed to open fbs reader:", err)
//return nil, err
}
//launch video encoding process:
vcodec := &encoders.X264ImageEncoder{}
//vcodec := &encoders.DV8ImageEncoder{}
//vcodec := &encoders.DV9ImageEncoder{}
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
logger.Debugf("current dir: %s", dir)
go vcodec.Run("./ffmpeg", "./output.mp4")
screenImage := image.NewRGBA(image.Rect(0, 0, int(fbs.Width()), int(fbs.Height())))
for _, enc := range encs {
myRenderer, ok := enc.(vnc.Renderer)
if ok {
myRenderer.SetTargetImage(screenImage)
}
}
msgReader := vnc.NewFBSPlayHelper(fbs)
//loop over all messages, feed images to video codec:
for {
msgReader.ReadFbsMessage()
vcodec.Encode(screenImage)
}
}
package main
import (
"image"
"os"
vnc "vnc2video"
"vnc2video/encoders"
"vnc2video/logger"
"path/filepath"
)
func main() {
if len(os.Args) <= 1 {
logger.Errorf("please provide a fbs file name")
return
}
if _, err := os.Stat(os.Args[1]); os.IsNotExist(err) {
logger.Errorf("File doesn't exist", err)
return
}
encs := []vnc.Encoding{
&vnc.RawEncoding{},
&vnc.TightEncoding{},
}
fbs, err := vnc.NewFbsConn(
os.Args[1],
encs,
)
if err != nil {
logger.Error("failed to open fbs reader:", err)
//return nil, err
}
//launch video encoding process:
vcodec := &encoders.X264ImageEncoder{}
//vcodec := &encoders.DV8ImageEncoder{}
//vcodec := &encoders.DV9ImageEncoder{}
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
logger.Debugf("current dir: %s", dir)
go vcodec.Run("./ffmpeg", "./output.mp4")
screenImage := image.NewRGBA(image.Rect(0, 0, int(fbs.Width()), int(fbs.Height())))
for _, enc := range encs {
myRenderer, ok := enc.(vnc.Renderer)
if ok {
myRenderer.SetTargetImage(screenImage)
}
}
msgReader := vnc.NewFBSPlayHelper(fbs)
//loop over all messages, feed images to video codec:
for {
msgReader.ReadFbsMessage()
vcodec.Encode(screenImage)
}
}

View File

@ -1,255 +1,255 @@
package main
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"io"
"net"
"net/http"
_ "net/http/pprof"
"net/url"
"strings"
"sync"
"time"
vnc "vnc2webm"
"vnc2webm/logger"
)
type Auth struct {
Username []byte
Password []byte
}
type Proxy struct {
cc vnc.Conn
conns chan vnc.Conn
inp chan vnc.ClientMessage
out chan vnc.ServerMessage
}
var (
cliconns = make(map[string]*Proxy)
srvconns = make(map[vnc.Conn]string)
m sync.Mutex
)
func newConn(hostport string, password []byte) (vnc.Conn, chan vnc.ClientMessage, chan vnc.ServerMessage, chan vnc.Conn, error) {
fmt.Printf("new conn to %s with %s\n", hostport, password)
if cc, ok := cliconns[hostport]; ok {
return cc.cc, cc.inp, cc.out, cc.conns, nil
}
c, err := net.DialTimeout("tcp", hostport, 10*time.Second)
if err != nil {
return nil, nil, nil, nil, err
}
cchServer := make(chan vnc.ServerMessage)
cchClient := make(chan vnc.ClientMessage)
errorCh := make(chan error)
ccfg := &vnc.ClientConfig{
SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthVNC{Password: password}},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: cchClient,
ServerMessageCh: cchServer,
//ServerMessages: vnc.DefaultServerMessages,
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
ErrorCh: errorCh,
}
csrv := make(chan vnc.Conn)
inp := make(chan vnc.ClientMessage)
out := make(chan vnc.ServerMessage)
fmt.Printf("connect to vnc\n")
cc, err := vnc.Connect(context.Background(), c, ccfg)
if err != nil {
return nil, nil, nil, nil, err
}
fmt.Printf("connected to vnc %#+v\n", cc)
ds := &vnc.DefaultClientMessageHandler{}
go ds.Handle(cc)
go handleIO(cc, inp, out, csrv)
return cc, inp, out, csrv, nil
}
func handleIO(cli vnc.Conn, inp chan vnc.ClientMessage, out chan vnc.ServerMessage, csrv chan vnc.Conn) {
fmt.Printf("handle io\n")
ccfg := cli.Config().(*vnc.ClientConfig)
defer cli.Close()
var conns []vnc.Conn
//var prepared bool
for {
select {
case err := <-ccfg.ErrorCh:
for _, srv := range conns {
srv.Close()
}
fmt.Printf("err %v\n", err)
return
case msg := <-ccfg.ServerMessageCh:
for _, srv := range conns {
scfg := srv.Config().(*vnc.ServerConfig)
scfg.ServerMessageCh <- msg
}
case msg := <-inp:
// messages from real clients
fmt.Printf("3 %#+v\n", msg)
switch msg.Type() {
case vnc.SetPixelFormatMsgType:
case vnc.SetEncodingsMsgType:
var encTypes []vnc.EncodingType
encs := []vnc.Encoding{
// &vnc.TightPngEncoding{},
&vnc.CopyRectEncoding{},
&vnc.RawEncoding{},
}
for _, senc := range encs {
for _, cenc := range msg.(*vnc.SetEncodings).Encodings {
if cenc == senc.Type() {
encTypes = append(encTypes, senc.Type())
}
}
}
ccfg.ClientMessageCh <- &vnc.SetEncodings{Encodings: encTypes}
default:
ccfg.ClientMessageCh <- msg
}
case msg := <-out:
fmt.Printf("4 %#+v\n", msg)
case srv := <-csrv:
conns = append(conns, srv)
}
}
}
type HijackHandler struct{}
func (*HijackHandler) Handle(c vnc.Conn) error {
m.Lock()
defer m.Unlock()
hostport, ok := srvconns[c]
if !ok {
return fmt.Errorf("client connect in server pool not found")
}
proxy, ok := cliconns[hostport]
if !ok {
return fmt.Errorf("client connect to qemu not found")
}
cfg := c.Config().(*vnc.ServerConfig)
cfg.ClientMessageCh = proxy.inp
cfg.ServerMessageCh = proxy.out
proxy.conns <- c
ds := &vnc.DefaultServerMessageHandler{}
go ds.Handle(c)
return nil
}
type AuthVNCHTTP struct {
c *http.Client
vnc.ServerAuthVNC
}
func (auth *AuthVNCHTTP) Auth(c vnc.Conn) error {
auth.ServerAuthVNC.Challenge = []byte("clodo.ruclodo.ru")
if err := auth.ServerAuthVNC.WriteChallenge(c); err != nil {
return err
}
if err := auth.ServerAuthVNC.ReadChallenge(c); err != nil {
return err
}
buf := new(bytes.Buffer)
enc := base64.NewEncoder(base64.StdEncoding, buf)
enc.Write(auth.ServerAuthVNC.Crypted)
enc.Close()
v := url.Values{}
v.Set("hash", buf.String())
buf.Reset()
src, _, _ := net.SplitHostPort(c.Conn().RemoteAddr().String())
v.Set("ip", src)
res, err := auth.c.PostForm("https://api.ix.clodo.ru/system/vnc", v)
if err != nil {
return err
}
if res.StatusCode != 200 || res.Body == nil {
if res.Body != nil {
io.Copy(buf, res.Body)
}
fmt.Printf("failed to get auth data: code %d body %s\n", res.StatusCode, buf.String())
defer buf.Reset()
return fmt.Errorf("failed to get auth data: code %d body %s", res.StatusCode, buf.String())
}
_, err = io.Copy(buf, res.Body)
if err != nil {
return fmt.Errorf("failed to get auth data: %s", err.Error())
}
logger.Infof("http auth: %s\n", buf.Bytes())
res.Body.Close()
data := strings.Split(buf.String(), " ")
if len(data) < 2 {
return fmt.Errorf("failed to get auth data data invalid")
}
buf.Reset()
hostport := string(data[0])
password := []byte(data[1])
m.Lock()
defer m.Unlock()
cc, inp, out, conns, err := newConn(hostport, password)
if err != nil {
return err
}
cliconns[hostport] = &Proxy{cc, conns, inp, out}
srvconns[c] = hostport
c.SetWidth(cc.Width())
c.SetHeight(cc.Height())
return nil
}
func (*AuthVNCHTTP) Type() vnc.SecurityType {
return vnc.SecTypeVNC
}
func (*AuthVNCHTTP) SubType() vnc.SecuritySubType {
return vnc.SecSubTypeUnknown
}
func main() {
go func() {
logger.Info(http.ListenAndServe(":6060", nil))
}()
ln, err := net.Listen("tcp", ":6900")
if err != nil {
logger.Fatalf("Error listen. %v", err)
}
schClient := make(chan vnc.ClientMessage)
schServer := make(chan vnc.ServerMessage)
scfg := &vnc.ServerConfig{
SecurityHandlers: []vnc.SecurityHandler{
&AuthVNCHTTP{c: &http.Client{}},
},
Encodings: []vnc.Encoding{
// &vnc.TightPngEncoding{},
&vnc.CopyRectEncoding{},
&vnc.RawEncoding{},
},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: schClient,
ServerMessageCh: schServer,
//ClientMessages: vnc.DefaultClientMessages,
DesktopName: []byte("vnc proxy"),
}
scfg.Handlers = append(scfg.Handlers, vnc.DefaultServerHandlers...)
scfg.Handlers = append(scfg.Handlers[:len(scfg.Handlers)-1], &HijackHandler{})
vnc.Serve(context.Background(), ln, scfg)
}
package main
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"io"
"net"
"net/http"
_ "net/http/pprof"
"net/url"
"strings"
"sync"
"time"
vnc "vnc2video"
"vnc2video/logger"
)
type Auth struct {
Username []byte
Password []byte
}
type Proxy struct {
cc vnc.Conn
conns chan vnc.Conn
inp chan vnc.ClientMessage
out chan vnc.ServerMessage
}
var (
cliconns = make(map[string]*Proxy)
srvconns = make(map[vnc.Conn]string)
m sync.Mutex
)
func newConn(hostport string, password []byte) (vnc.Conn, chan vnc.ClientMessage, chan vnc.ServerMessage, chan vnc.Conn, error) {
fmt.Printf("new conn to %s with %s\n", hostport, password)
if cc, ok := cliconns[hostport]; ok {
return cc.cc, cc.inp, cc.out, cc.conns, nil
}
c, err := net.DialTimeout("tcp", hostport, 10*time.Second)
if err != nil {
return nil, nil, nil, nil, err
}
cchServer := make(chan vnc.ServerMessage)
cchClient := make(chan vnc.ClientMessage)
errorCh := make(chan error)
ccfg := &vnc.ClientConfig{
SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthVNC{Password: password}},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: cchClient,
ServerMessageCh: cchServer,
//ServerMessages: vnc.DefaultServerMessages,
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
ErrorCh: errorCh,
}
csrv := make(chan vnc.Conn)
inp := make(chan vnc.ClientMessage)
out := make(chan vnc.ServerMessage)
fmt.Printf("connect to vnc\n")
cc, err := vnc.Connect(context.Background(), c, ccfg)
if err != nil {
return nil, nil, nil, nil, err
}
fmt.Printf("connected to vnc %#+v\n", cc)
ds := &vnc.DefaultClientMessageHandler{}
go ds.Handle(cc)
go handleIO(cc, inp, out, csrv)
return cc, inp, out, csrv, nil
}
func handleIO(cli vnc.Conn, inp chan vnc.ClientMessage, out chan vnc.ServerMessage, csrv chan vnc.Conn) {
fmt.Printf("handle io\n")
ccfg := cli.Config().(*vnc.ClientConfig)
defer cli.Close()
var conns []vnc.Conn
//var prepared bool
for {
select {
case err := <-ccfg.ErrorCh:
for _, srv := range conns {
srv.Close()
}
fmt.Printf("err %v\n", err)
return
case msg := <-ccfg.ServerMessageCh:
for _, srv := range conns {
scfg := srv.Config().(*vnc.ServerConfig)
scfg.ServerMessageCh <- msg
}
case msg := <-inp:
// messages from real clients
fmt.Printf("3 %#+v\n", msg)
switch msg.Type() {
case vnc.SetPixelFormatMsgType:
case vnc.SetEncodingsMsgType:
var encTypes []vnc.EncodingType
encs := []vnc.Encoding{
// &vnc.TightPngEncoding{},
&vnc.CopyRectEncoding{},
&vnc.RawEncoding{},
}
for _, senc := range encs {
for _, cenc := range msg.(*vnc.SetEncodings).Encodings {
if cenc == senc.Type() {
encTypes = append(encTypes, senc.Type())
}
}
}
ccfg.ClientMessageCh <- &vnc.SetEncodings{Encodings: encTypes}
default:
ccfg.ClientMessageCh <- msg
}
case msg := <-out:
fmt.Printf("4 %#+v\n", msg)
case srv := <-csrv:
conns = append(conns, srv)
}
}
}
type HijackHandler struct{}
func (*HijackHandler) Handle(c vnc.Conn) error {
m.Lock()
defer m.Unlock()
hostport, ok := srvconns[c]
if !ok {
return fmt.Errorf("client connect in server pool not found")
}
proxy, ok := cliconns[hostport]
if !ok {
return fmt.Errorf("client connect to qemu not found")
}
cfg := c.Config().(*vnc.ServerConfig)
cfg.ClientMessageCh = proxy.inp
cfg.ServerMessageCh = proxy.out
proxy.conns <- c
ds := &vnc.DefaultServerMessageHandler{}
go ds.Handle(c)
return nil
}
type AuthVNCHTTP struct {
c *http.Client
vnc.ServerAuthVNC
}
func (auth *AuthVNCHTTP) Auth(c vnc.Conn) error {
auth.ServerAuthVNC.Challenge = []byte("clodo.ruclodo.ru")
if err := auth.ServerAuthVNC.WriteChallenge(c); err != nil {
return err
}
if err := auth.ServerAuthVNC.ReadChallenge(c); err != nil {
return err
}
buf := new(bytes.Buffer)
enc := base64.NewEncoder(base64.StdEncoding, buf)
enc.Write(auth.ServerAuthVNC.Crypted)
enc.Close()
v := url.Values{}
v.Set("hash", buf.String())
buf.Reset()
src, _, _ := net.SplitHostPort(c.Conn().RemoteAddr().String())
v.Set("ip", src)
res, err := auth.c.PostForm("https://api.ix.clodo.ru/system/vnc", v)
if err != nil {
return err
}
if res.StatusCode != 200 || res.Body == nil {
if res.Body != nil {
io.Copy(buf, res.Body)
}
fmt.Printf("failed to get auth data: code %d body %s\n", res.StatusCode, buf.String())
defer buf.Reset()
return fmt.Errorf("failed to get auth data: code %d body %s", res.StatusCode, buf.String())
}
_, err = io.Copy(buf, res.Body)
if err != nil {
return fmt.Errorf("failed to get auth data: %s", err.Error())
}
logger.Infof("http auth: %s\n", buf.Bytes())
res.Body.Close()
data := strings.Split(buf.String(), " ")
if len(data) < 2 {
return fmt.Errorf("failed to get auth data data invalid")
}
buf.Reset()
hostport := string(data[0])
password := []byte(data[1])
m.Lock()
defer m.Unlock()
cc, inp, out, conns, err := newConn(hostport, password)
if err != nil {
return err
}
cliconns[hostport] = &Proxy{cc, conns, inp, out}
srvconns[c] = hostport
c.SetWidth(cc.Width())
c.SetHeight(cc.Height())
return nil
}
func (*AuthVNCHTTP) Type() vnc.SecurityType {
return vnc.SecTypeVNC
}
func (*AuthVNCHTTP) SubType() vnc.SecuritySubType {
return vnc.SecSubTypeUnknown
}
func main() {
go func() {
logger.Info(http.ListenAndServe(":6060", nil))
}()
ln, err := net.Listen("tcp", ":6900")
if err != nil {
logger.Fatalf("Error listen. %v", err)
}
schClient := make(chan vnc.ClientMessage)
schServer := make(chan vnc.ServerMessage)
scfg := &vnc.ServerConfig{
SecurityHandlers: []vnc.SecurityHandler{
&AuthVNCHTTP{c: &http.Client{}},
},
Encodings: []vnc.Encoding{
// &vnc.TightPngEncoding{},
&vnc.CopyRectEncoding{},
&vnc.RawEncoding{},
},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: schClient,
ServerMessageCh: schServer,
//ClientMessages: vnc.DefaultClientMessages,
DesktopName: []byte("vnc proxy"),
}
scfg.Handlers = append(scfg.Handlers, vnc.DefaultServerHandlers...)
scfg.Handlers = append(scfg.Handlers[:len(scfg.Handlers)-1], &HijackHandler{})
vnc.Serve(context.Background(), ln, scfg)
}

View File

@ -1,93 +1,93 @@
package main
import (
"context"
"fmt"
"image"
"math"
"net"
"time"
vnc "vnc2webm"
"vnc2webm/logger"
)
func main() {
ln, err := net.Listen("tcp", ":5900")
if err != nil {
logger.Fatalf("Error listen. %v", err)
}
chServer := make(chan vnc.ClientMessage)
chClient := make(chan vnc.ServerMessage)
im := image.NewRGBA(image.Rect(0, 0, width, height))
tick := time.NewTicker(time.Second / 2)
defer tick.Stop()
cfg := &vnc.ServerConfig{
Width: 800,
Height: 600,
//VersionHandler: vnc.ServerVersionHandler,
//SecurityHandler: vnc.ServerSecurityHandler,
SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthNone{}},
//ClientInitHandler: vnc.ServerClientInitHandler,
//ServerInitHandler: vnc.ServerServerInitHandler,
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: chServer,
ServerMessageCh: chClient,
Messages: vnc.DefaultClientMessages,
}
cfg.Handlers = vnc.DefaultServerHandlers
go vnc.Serve(context.Background(), ln, cfg)
// Process messages coming in on the ClientMessage channel.
for {
select {
case <-tick.C:
drawImage(im, 0)
fmt.Printf("tick\n")
case msg := <-chClient:
switch msg.Type() {
default:
logger.Debugf("11 Received message type:%v msg:%v\n", msg.Type(), msg)
}
case msg := <-chServer:
switch msg.Type() {
default:
logger.Debugf("22 Received message type:%v msg:%v\n", msg.Type(), msg)
}
}
}
}
const (
width = 800
height = 600
)
func drawImage(im *image.RGBA, anim int) {
pos := 0
const border = 50
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
var r, g, b uint8
switch {
case x < border*2.5 && x < int((1.1+math.Sin(float64(y+anim*2)/40))*border):
r = 255
case x > width-border*2.5 && x > width-int((1.1+math.Sin(math.Pi+float64(y+anim*2)/40))*border):
g = 255
case y < border*2.5 && y < int((1.1+math.Sin(float64(x+anim*2)/40))*border):
r, g = 255, 255
case y > height-border*2.5 && y > height-int((1.1+math.Sin(math.Pi+float64(x+anim*2)/40))*border):
b = 255
default:
r, g, b = uint8(x+anim), uint8(y+anim), uint8(x+y+anim*3)
}
im.Pix[pos] = r
im.Pix[pos+1] = g
im.Pix[pos+2] = b
pos += 4 // skipping alpha
}
}
}
package main
import (
"context"
"fmt"
"image"
"math"
"net"
"time"
vnc "vnc2video"
"vnc2video/logger"
)
func main() {
ln, err := net.Listen("tcp", ":5900")
if err != nil {
logger.Fatalf("Error listen. %v", err)
}
chServer := make(chan vnc.ClientMessage)
chClient := make(chan vnc.ServerMessage)
im := image.NewRGBA(image.Rect(0, 0, width, height))
tick := time.NewTicker(time.Second / 2)
defer tick.Stop()
cfg := &vnc.ServerConfig{
Width: 800,
Height: 600,
//VersionHandler: vnc.ServerVersionHandler,
//SecurityHandler: vnc.ServerSecurityHandler,
SecurityHandlers: []vnc.SecurityHandler{&vnc.ClientAuthNone{}},
//ClientInitHandler: vnc.ServerClientInitHandler,
//ServerInitHandler: vnc.ServerServerInitHandler,
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
PixelFormat: vnc.PixelFormat32bit,
ClientMessageCh: chServer,
ServerMessageCh: chClient,
Messages: vnc.DefaultClientMessages,
}
cfg.Handlers = vnc.DefaultServerHandlers
go vnc.Serve(context.Background(), ln, cfg)
// Process messages coming in on the ClientMessage channel.
for {
select {
case <-tick.C:
drawImage(im, 0)
fmt.Printf("tick\n")
case msg := <-chClient:
switch msg.Type() {
default:
logger.Debugf("11 Received message type:%v msg:%v\n", msg.Type(), msg)
}
case msg := <-chServer:
switch msg.Type() {
default:
logger.Debugf("22 Received message type:%v msg:%v\n", msg.Type(), msg)
}
}
}
}
const (
width = 800
height = 600
)
func drawImage(im *image.RGBA, anim int) {
pos := 0
const border = 50
for y := 0; y < height; y++ {
for x := 0; x < width; x++ {
var r, g, b uint8
switch {
case x < border*2.5 && x < int((1.1+math.Sin(float64(y+anim*2)/40))*border):
r = 255
case x > width-border*2.5 && x > width-int((1.1+math.Sin(math.Pi+float64(y+anim*2)/40))*border):
g = 255
case y < border*2.5 && y < int((1.1+math.Sin(float64(x+anim*2)/40))*border):
r, g = 255, 255
case y > height-border*2.5 && y > height-int((1.1+math.Sin(math.Pi+float64(x+anim*2)/40))*border):
b = 255
default:
r, g, b = uint8(x+anim), uint8(y+anim), uint8(x+y+anim*3)
}
im.Pix[pos] = r
im.Pix[pos+1] = g
im.Pix[pos+2] = b
pos += 4 // skipping alpha
}
}
}

View File

@ -1,201 +1,201 @@
package vnc2webm
import (
"encoding/binary"
"net"
"vnc2webm/logger"
"io"
"time"
)
// Conn represents vnc conection
type FbsConn struct {
FbsReader
protocol string
//c net.IServerConn
//config *ClientConfig
colorMap ColorMap
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings should be used.
encodings []Encoding
// Height of the frame buffer in pixels, sent from the server.
fbHeight uint16
// Width of the frame buffer in pixels, sent from the server.
fbWidth uint16
desktopName string
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
}
// func (c *FbsConn) Close() error {
// return c.fbs.Close()
// }
// // Read reads data from conn
// func (c *FbsConn) Read(buf []byte) (int, error) {
// return c.fbs.Read(buf)
// }
//dummy, no writing to this conn...
func (c *FbsConn) Write(buf []byte) (int, error) {
return len(buf), nil
}
func (c *FbsConn) Conn() net.Conn {
return nil
}
func (c *FbsConn) Config() interface{} {
return nil
}
func (c *FbsConn) Protocol() string {
return "RFB 003.008"
}
func (c *FbsConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
func (c *FbsConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
func (c *FbsConn) ColorMap() ColorMap { return c.colorMap }
func (c *FbsConn) SetColorMap(cm ColorMap) { c.colorMap = cm }
func (c *FbsConn) Encodings() []Encoding { return c.encodings }
func (c *FbsConn) SetEncodings([]EncodingType) error { return nil }
func (c *FbsConn) Width() uint16 { return c.fbWidth }
func (c *FbsConn) Height() uint16 { return c.fbHeight }
func (c *FbsConn) SetWidth(w uint16) { c.fbWidth = w }
func (c *FbsConn) SetHeight(h uint16) { c.fbHeight = h }
func (c *FbsConn) DesktopName() []byte { return []byte(c.desktopName) }
func (c *FbsConn) SetDesktopName(d []byte) { c.desktopName = string(d) }
func (c *FbsConn) Flush() error { return nil }
func (c *FbsConn) Wait() {}
func (c *FbsConn) SetProtoVersion(string) {}
func (c *FbsConn) SetSecurityHandler(SecurityHandler) error { return nil }
func (c *FbsConn) SecurityHandler() SecurityHandler { return nil }
func (c *FbsConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
type VncStreamFileReader interface {
io.Reader
CurrentTimestamp() int
ReadStartSession() (*ServerInit, error)
CurrentPixelFormat() *PixelFormat
Encodings() []Encoding
}
type FBSPlayHelper struct {
Conn *FbsConn
//Fbs VncStreamFileReader
serverMessageMap map[uint8]ServerMessage
firstSegDone bool
startTime int
}
func NewFbsConn(filename string, encs []Encoding) (*FbsConn, error) {
fbs, err := NewFbsReader(filename)
if err != nil {
logger.Error("failed to open fbs reader:", err)
return nil, err
}
//NewFbsReader("/Users/amitbet/vncRec/recording.rbs")
initMsg, err := fbs.ReadStartSession()
if err != nil {
logger.Error("failed to open read fbs start session:", err)
return nil, err
}
fbsConn := &FbsConn{FbsReader: *fbs}
fbsConn.encodings = encs
fbsConn.SetPixelFormat(initMsg.PixelFormat)
fbsConn.SetHeight(initMsg.FBHeight)
fbsConn.SetWidth(initMsg.FBWidth)
fbsConn.SetDesktopName([]byte(initMsg.NameText))
return fbsConn, nil
}
func NewFBSPlayHelper(r *FbsConn) *FBSPlayHelper {
h := &FBSPlayHelper{Conn: r}
h.startTime = int(time.Now().UnixNano() / int64(time.Millisecond))
h.serverMessageMap = make(map[uint8]ServerMessage)
h.serverMessageMap[0] = &FramebufferUpdate{}
h.serverMessageMap[1] = &SetColorMapEntries{}
h.serverMessageMap[2] = &Bell{}
h.serverMessageMap[3] = &ServerCutText{}
return h
}
// func (handler *FBSPlayHelper) Consume(seg *RfbSegment) error {
// switch seg.SegmentType {
// case SegmentFullyParsedClientMessage:
// clientMsg := seg.Message.(ClientMessage)
// logger.Debugf("ClientUpdater.Consume:(vnc-server-bound) got ClientMessage type=%s", clientMsg.Type())
// switch clientMsg.Type() {
// case FramebufferUpdateRequestMsgType:
// if !handler.firstSegDone {
// handler.firstSegDone = true
// handler.startTime = int(time.Now().UnixNano() / int64(time.Millisecond))
// }
// handler.sendFbsMessage()
// }
// // server.MsgFramebufferUpdateRequest:
// }
// return nil
// }
func (h *FBSPlayHelper) ReadFbsMessage() ServerMessage {
var messageType uint8
//messages := make(map[uint8]ServerMessage)
fbs := h.Conn
//conn := h.Conn
err := binary.Read(fbs, binary.BigEndian, &messageType)
if err != nil {
logger.Error("TestServer.NewConnHandler: Error in reading FBS: ", err)
return nil
}
//IClientConn{}
//binary.Write(h.Conn, binary.BigEndian, messageType)
msg := h.serverMessageMap[messageType]
if msg == nil {
logger.Error("TestServer.NewConnHandler: Error unknown message type: ", messageType)
return nil
}
//read the actual message data
//err = binary.Read(fbs, binary.BigEndian, &msg)
parsedMsg, err := msg.Read(fbs)
if err != nil {
logger.Error("TestServer.NewConnHandler: Error in reading FBS message: ", err)
return nil
}
timeSinceStart := int(time.Now().UnixNano()/int64(time.Millisecond)) - h.startTime
timeToSleep := fbs.CurrentTimestamp() - timeSinceStart
if timeToSleep > 0 {
time.Sleep(time.Duration(timeToSleep) * time.Millisecond)
}
return parsedMsg
}
package vnc2video
import (
"encoding/binary"
"net"
"vnc2video/logger"
"io"
"time"
)
// Conn represents vnc conection
type FbsConn struct {
FbsReader
protocol string
//c net.IServerConn
//config *ClientConfig
colorMap ColorMap
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings should be used.
encodings []Encoding
// Height of the frame buffer in pixels, sent from the server.
fbHeight uint16
// Width of the frame buffer in pixels, sent from the server.
fbWidth uint16
desktopName string
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
}
// func (c *FbsConn) Close() error {
// return c.fbs.Close()
// }
// // Read reads data from conn
// func (c *FbsConn) Read(buf []byte) (int, error) {
// return c.fbs.Read(buf)
// }
//dummy, no writing to this conn...
func (c *FbsConn) Write(buf []byte) (int, error) {
return len(buf), nil
}
func (c *FbsConn) Conn() net.Conn {
return nil
}
func (c *FbsConn) Config() interface{} {
return nil
}
func (c *FbsConn) Protocol() string {
return "RFB 003.008"
}
func (c *FbsConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
func (c *FbsConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
func (c *FbsConn) ColorMap() ColorMap { return c.colorMap }
func (c *FbsConn) SetColorMap(cm ColorMap) { c.colorMap = cm }
func (c *FbsConn) Encodings() []Encoding { return c.encodings }
func (c *FbsConn) SetEncodings([]EncodingType) error { return nil }
func (c *FbsConn) Width() uint16 { return c.fbWidth }
func (c *FbsConn) Height() uint16 { return c.fbHeight }
func (c *FbsConn) SetWidth(w uint16) { c.fbWidth = w }
func (c *FbsConn) SetHeight(h uint16) { c.fbHeight = h }
func (c *FbsConn) DesktopName() []byte { return []byte(c.desktopName) }
func (c *FbsConn) SetDesktopName(d []byte) { c.desktopName = string(d) }
func (c *FbsConn) Flush() error { return nil }
func (c *FbsConn) Wait() {}
func (c *FbsConn) SetProtoVersion(string) {}
func (c *FbsConn) SetSecurityHandler(SecurityHandler) error { return nil }
func (c *FbsConn) SecurityHandler() SecurityHandler { return nil }
func (c *FbsConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
type VncStreamFileReader interface {
io.Reader
CurrentTimestamp() int
ReadStartSession() (*ServerInit, error)
CurrentPixelFormat() *PixelFormat
Encodings() []Encoding
}
type FBSPlayHelper struct {
Conn *FbsConn
//Fbs VncStreamFileReader
serverMessageMap map[uint8]ServerMessage
firstSegDone bool
startTime int
}
func NewFbsConn(filename string, encs []Encoding) (*FbsConn, error) {
fbs, err := NewFbsReader(filename)
if err != nil {
logger.Error("failed to open fbs reader:", err)
return nil, err
}
//NewFbsReader("/Users/amitbet/vncRec/recording.rbs")
initMsg, err := fbs.ReadStartSession()
if err != nil {
logger.Error("failed to open read fbs start session:", err)
return nil, err
}
fbsConn := &FbsConn{FbsReader: *fbs}
fbsConn.encodings = encs
fbsConn.SetPixelFormat(initMsg.PixelFormat)
fbsConn.SetHeight(initMsg.FBHeight)
fbsConn.SetWidth(initMsg.FBWidth)
fbsConn.SetDesktopName([]byte(initMsg.NameText))
return fbsConn, nil
}
func NewFBSPlayHelper(r *FbsConn) *FBSPlayHelper {
h := &FBSPlayHelper{Conn: r}
h.startTime = int(time.Now().UnixNano() / int64(time.Millisecond))
h.serverMessageMap = make(map[uint8]ServerMessage)
h.serverMessageMap[0] = &FramebufferUpdate{}
h.serverMessageMap[1] = &SetColorMapEntries{}
h.serverMessageMap[2] = &Bell{}
h.serverMessageMap[3] = &ServerCutText{}
return h
}
// func (handler *FBSPlayHelper) Consume(seg *RfbSegment) error {
// switch seg.SegmentType {
// case SegmentFullyParsedClientMessage:
// clientMsg := seg.Message.(ClientMessage)
// logger.Debugf("ClientUpdater.Consume:(vnc-server-bound) got ClientMessage type=%s", clientMsg.Type())
// switch clientMsg.Type() {
// case FramebufferUpdateRequestMsgType:
// if !handler.firstSegDone {
// handler.firstSegDone = true
// handler.startTime = int(time.Now().UnixNano() / int64(time.Millisecond))
// }
// handler.sendFbsMessage()
// }
// // server.MsgFramebufferUpdateRequest:
// }
// return nil
// }
func (h *FBSPlayHelper) ReadFbsMessage() ServerMessage {
var messageType uint8
//messages := make(map[uint8]ServerMessage)
fbs := h.Conn
//conn := h.Conn
err := binary.Read(fbs, binary.BigEndian, &messageType)
if err != nil {
logger.Error("TestServer.NewConnHandler: Error in reading FBS: ", err)
return nil
}
//IClientConn{}
//binary.Write(h.Conn, binary.BigEndian, messageType)
msg := h.serverMessageMap[messageType]
if msg == nil {
logger.Error("TestServer.NewConnHandler: Error unknown message type: ", messageType)
return nil
}
//read the actual message data
//err = binary.Read(fbs, binary.BigEndian, &msg)
parsedMsg, err := msg.Read(fbs)
if err != nil {
logger.Error("TestServer.NewConnHandler: Error in reading FBS message: ", err)
return nil
}
timeSinceStart := int(time.Now().UnixNano()/int64(time.Millisecond)) - h.startTime
timeToSleep := fbs.CurrentTimestamp() - timeSinceStart
if timeToSleep > 0 {
time.Sleep(time.Duration(timeToSleep) * time.Millisecond)
}
return parsedMsg
}

View File

@ -1,190 +1,190 @@
package vnc2webm
import (
"bytes"
"encoding/binary"
"io"
"os"
//"vncproxy/common"
//"vncproxy/encodings"
"vnc2webm/logger"
//"vncproxy/encodings"
//"vncproxy/encodings"
)
type FbsReader struct {
reader io.ReadCloser
buffer bytes.Buffer
currentTimestamp int
//pixelFormat *PixelFormat
//encodings []IEncoding
}
func (fbs *FbsReader) Close() error {
return fbs.reader.Close()
}
func (fbs *FbsReader) CurrentTimestamp() int {
return fbs.currentTimestamp
}
func (fbs *FbsReader) Read(p []byte) (n int, err error) {
if fbs.buffer.Len() < len(p) {
seg, err := fbs.ReadSegment()
if err != nil {
logger.Error("FBSReader.Read: error reading FBSsegment: ", err)
return 0, err
}
fbs.buffer.Write(seg.bytes)
fbs.currentTimestamp = int(seg.timestamp)
}
return fbs.buffer.Read(p)
}
//func (fbs *FbsReader) CurrentPixelFormat() *PixelFormat { return fbs.pixelFormat }
//func (fbs *FbsReader) CurrentColorMap() *common.ColorMap { return &common.ColorMap{} }
//func (fbs *FbsReader) Encodings() []IEncoding { return fbs.encodings }
func NewFbsReader(fbsFile string) (*FbsReader, error) {
reader, err := os.OpenFile(fbsFile, os.O_RDONLY, 0644)
if err != nil {
logger.Error("NewFbsReader: can't open fbs file: ", fbsFile)
return nil, err
}
return &FbsReader{reader: reader}, //encodings: []IEncoding{
// //&encodings.CopyRectEncoding{},
// //&encodings.ZLibEncoding{},
// //&encodings.ZRLEEncoding{},
// //&encodings.CoRREEncoding{},
// //&encodings.HextileEncoding{},
// &TightEncoding{},
// //&TightPngEncoding{},
// //&EncCursorPseudo{},
// &RawEncoding{},
// //&encodings.RREEncoding{},
//},
nil
}
func (fbs *FbsReader) ReadStartSession() (*ServerInit, error) {
initMsg := ServerInit{}
reader := fbs.reader
var framebufferWidth uint16
var framebufferHeight uint16
var SecTypeNone uint32
//read rfb header information (the only part done without the [size|data|timestamp] block wrapper)
//.("FBS 001.000\n")
bytes := make([]byte, 12)
_, err := reader.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init message - FBS file Version:", err)
return nil, err
}
//read the version message into the buffer, it is written in the first fbs block
//RFB 003.008\n
bytes = make([]byte, 12)
_, err = fbs.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - RFB Version: ", err)
return nil, err
}
//push sec type and fb dimensions
binary.Read(fbs, binary.BigEndian, &SecTypeNone)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - SecType: ", err)
}
//read frame buffer width, height
binary.Read(fbs, binary.BigEndian, &framebufferWidth)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - FBWidth: ", err)
return nil, err
}
initMsg.FBWidth = framebufferWidth
binary.Read(fbs, binary.BigEndian, &framebufferHeight)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - FBHeight: ", err)
return nil, err
}
initMsg.FBHeight = framebufferHeight
//read pixel format
pixelFormat := &PixelFormat{}
binary.Read(fbs, binary.BigEndian, pixelFormat)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - Pixelformat: ", err)
return nil, err
}
initMsg.PixelFormat = *pixelFormat
//read desktop name
var desknameLen uint32
binary.Read(fbs, binary.BigEndian, &desknameLen)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - deskname Len: ", err)
return nil, err
}
initMsg.NameLength = desknameLen
bytes = make([]byte, desknameLen)
fbs.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - desktopName: ", err)
return nil, err
}
initMsg.NameText = bytes
return &initMsg, nil
}
func (fbs *FbsReader) ReadSegment() (*FbsSegment, error) {
reader := fbs.reader
var bytesLen uint32
//read length
err := binary.Read(reader, binary.BigEndian, &bytesLen)
if err != nil {
logger.Error("FbsReader.ReadStartSession: read len, error reading rbs file: ", err)
return nil, err
}
paddedSize := (bytesLen + 3) & 0x7FFFFFFC
//read bytes
bytes := make([]byte, paddedSize)
_, err = reader.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadSegment: read bytes, error reading rbs file: ", err)
return nil, err
}
//remove padding
actualBytes := bytes[:bytesLen]
//read timestamp
var timeSinceStart uint32
binary.Read(reader, binary.BigEndian, &timeSinceStart)
if err != nil {
logger.Error("FbsReader.ReadSegment: read timestamp, error reading rbs file: ", err)
return nil, err
}
//timeStamp := time.Unix(timeSinceStart, 0)
seg := &FbsSegment{bytes: actualBytes, timestamp: timeSinceStart}
return seg, nil
}
type FbsSegment struct {
bytes []byte
timestamp uint32
}
package vnc2video
import (
"bytes"
"encoding/binary"
"io"
"os"
//"vncproxy/common"
//"vncproxy/encodings"
"vnc2video/logger"
//"vncproxy/encodings"
//"vncproxy/encodings"
)
type FbsReader struct {
reader io.ReadCloser
buffer bytes.Buffer
currentTimestamp int
//pixelFormat *PixelFormat
//encodings []IEncoding
}
func (fbs *FbsReader) Close() error {
return fbs.reader.Close()
}
func (fbs *FbsReader) CurrentTimestamp() int {
return fbs.currentTimestamp
}
func (fbs *FbsReader) Read(p []byte) (n int, err error) {
if fbs.buffer.Len() < len(p) {
seg, err := fbs.ReadSegment()
if err != nil {
logger.Error("FBSReader.Read: error reading FBSsegment: ", err)
return 0, err
}
fbs.buffer.Write(seg.bytes)
fbs.currentTimestamp = int(seg.timestamp)
}
return fbs.buffer.Read(p)
}
//func (fbs *FbsReader) CurrentPixelFormat() *PixelFormat { return fbs.pixelFormat }
//func (fbs *FbsReader) CurrentColorMap() *common.ColorMap { return &common.ColorMap{} }
//func (fbs *FbsReader) Encodings() []IEncoding { return fbs.encodings }
func NewFbsReader(fbsFile string) (*FbsReader, error) {
reader, err := os.OpenFile(fbsFile, os.O_RDONLY, 0644)
if err != nil {
logger.Error("NewFbsReader: can't open fbs file: ", fbsFile)
return nil, err
}
return &FbsReader{reader: reader}, //encodings: []IEncoding{
// //&encodings.CopyRectEncoding{},
// //&encodings.ZLibEncoding{},
// //&encodings.ZRLEEncoding{},
// //&encodings.CoRREEncoding{},
// //&encodings.HextileEncoding{},
// &TightEncoding{},
// //&TightPngEncoding{},
// //&EncCursorPseudo{},
// &RawEncoding{},
// //&encodings.RREEncoding{},
//},
nil
}
func (fbs *FbsReader) ReadStartSession() (*ServerInit, error) {
initMsg := ServerInit{}
reader := fbs.reader
var framebufferWidth uint16
var framebufferHeight uint16
var SecTypeNone uint32
//read rfb header information (the only part done without the [size|data|timestamp] block wrapper)
//.("FBS 001.000\n")
bytes := make([]byte, 12)
_, err := reader.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init message - FBS file Version:", err)
return nil, err
}
//read the version message into the buffer, it is written in the first fbs block
//RFB 003.008\n
bytes = make([]byte, 12)
_, err = fbs.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - RFB Version: ", err)
return nil, err
}
//push sec type and fb dimensions
binary.Read(fbs, binary.BigEndian, &SecTypeNone)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - SecType: ", err)
}
//read frame buffer width, height
binary.Read(fbs, binary.BigEndian, &framebufferWidth)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - FBWidth: ", err)
return nil, err
}
initMsg.FBWidth = framebufferWidth
binary.Read(fbs, binary.BigEndian, &framebufferHeight)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - FBHeight: ", err)
return nil, err
}
initMsg.FBHeight = framebufferHeight
//read pixel format
pixelFormat := &PixelFormat{}
binary.Read(fbs, binary.BigEndian, pixelFormat)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - Pixelformat: ", err)
return nil, err
}
initMsg.PixelFormat = *pixelFormat
//read desktop name
var desknameLen uint32
binary.Read(fbs, binary.BigEndian, &desknameLen)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - deskname Len: ", err)
return nil, err
}
initMsg.NameLength = desknameLen
bytes = make([]byte, desknameLen)
fbs.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadStartSession: error reading rbs init - desktopName: ", err)
return nil, err
}
initMsg.NameText = bytes
return &initMsg, nil
}
func (fbs *FbsReader) ReadSegment() (*FbsSegment, error) {
reader := fbs.reader
var bytesLen uint32
//read length
err := binary.Read(reader, binary.BigEndian, &bytesLen)
if err != nil {
logger.Error("FbsReader.ReadStartSession: read len, error reading rbs file: ", err)
return nil, err
}
paddedSize := (bytesLen + 3) & 0x7FFFFFFC
//read bytes
bytes := make([]byte, paddedSize)
_, err = reader.Read(bytes)
if err != nil {
logger.Error("FbsReader.ReadSegment: read bytes, error reading rbs file: ", err)
return nil, err
}
//remove padding
actualBytes := bytes[:bytesLen]
//read timestamp
var timeSinceStart uint32
binary.Read(reader, binary.BigEndian, &timeSinceStart)
if err != nil {
logger.Error("FbsReader.ReadSegment: read timestamp, error reading rbs file: ", err)
return nil, err
}
//timeStamp := time.Unix(timeSinceStart, 0)
seg := &FbsSegment{bytes: actualBytes, timestamp: timeSinceStart}
return seg, nil
}
type FbsSegment struct {
bytes []byte
timestamp uint32
}

View File

@ -1,408 +1,408 @@
package vnc2webm
import (
"encoding/binary"
"fmt"
"vnc2webm/logger"
)
// Handler represents handler of handshake
type Handler interface {
Handle(Conn) error
}
// ProtoVersionLength protocol version length
const ProtoVersionLength = 12
const (
// ProtoVersionUnknown unknown version
ProtoVersionUnknown = ""
// ProtoVersion33 sets if proto 003.003
ProtoVersion33 = "RFB 003.003\n"
// ProtoVersion38 sets if proto 003.008
ProtoVersion38 = "RFB 003.008\n"
// ProtoVersion37 sets if proto 003.007
ProtoVersion37 = "RFB 003.007\n"
)
// ParseProtoVersion parse protocol version
func ParseProtoVersion(pv []byte) (uint, uint, error) {
var major, minor uint
if len(pv) < ProtoVersionLength {
return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), ProtoVersionLength)
}
l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor)
if l != 2 {
return 0, 0, fmt.Errorf("error parsing protocol version")
}
if err != nil {
return 0, 0, err
}
return major, minor, nil
}
// DefaultClientVersionHandler represents default handler
type DefaultClientVersionHandler struct{}
// Handle provide version handler for client side
func (*DefaultClientVersionHandler) Handle(c Conn) error {
var version [ProtoVersionLength]byte
if err := binary.Read(c, binary.BigEndian, &version); err != nil {
return err
}
major, minor, err := ParseProtoVersion(version[:])
if err != nil {
return err
}
pv := ProtoVersionUnknown
if major == 3 {
if minor >= 8 {
pv = ProtoVersion38
} else if minor >= 3 {
pv = ProtoVersion38
}
}
if pv == ProtoVersionUnknown {
return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
}
c.SetProtoVersion(string(version[:]))
if err := binary.Write(c, binary.BigEndian, []byte(pv)); err != nil {
return err
}
return c.Flush()
}
// DefaultServerVersionHandler represents default server handler
type DefaultServerVersionHandler struct{}
// Handle provide server version handler
func (*DefaultServerVersionHandler) Handle(c Conn) error {
var version [ProtoVersionLength]byte
if err := binary.Write(c, binary.BigEndian, []byte(ProtoVersion38)); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &version); err != nil {
return err
}
major, minor, err := ParseProtoVersion(version[:])
if err != nil {
return err
}
pv := ProtoVersionUnknown
if major == 3 {
if minor >= 8 {
pv = ProtoVersion38
} else if minor >= 3 {
pv = ProtoVersion33
}
}
if pv == ProtoVersionUnknown {
return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
}
c.SetProtoVersion(pv)
return nil
}
// DefaultClientSecurityHandler used for client security handler
type DefaultClientSecurityHandler struct{}
// Handle provide client side security handler
func (*DefaultClientSecurityHandler) Handle(c Conn) error {
cfg := c.Config().(*ClientConfig)
var numSecurityTypes uint8
if err := binary.Read(c, binary.BigEndian, &numSecurityTypes); err != nil {
return err
}
secTypes := make([]SecurityType, numSecurityTypes)
if err := binary.Read(c, binary.BigEndian, &secTypes); err != nil {
return err
}
var secType SecurityHandler
for _, st := range cfg.SecurityHandlers {
for _, sc := range secTypes {
if st.Type() == sc {
secType = st
}
}
}
if err := binary.Write(c, binary.BigEndian, cfg.SecurityHandlers[0].Type()); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
err := secType.Auth(c)
if err != nil {
return err
}
var authCode uint32
if err := binary.Read(c, binary.BigEndian, &authCode); err != nil {
return err
}
logger.Debugf("authenticating, secType: %d, auth code(0=success): %d", secType.Type(), authCode)
if authCode == 1 {
var reasonLength uint32
if err := binary.Read(c, binary.BigEndian, &reasonLength); err != nil {
return err
}
reasonText := make([]byte, reasonLength)
if err := binary.Read(c, binary.BigEndian, &reasonText); err != nil {
return err
}
return fmt.Errorf("%s", reasonText)
}
c.SetSecurityHandler(secType)
return nil
}
// DefaultServerSecurityHandler used for server security handler
type DefaultServerSecurityHandler struct{}
// Handle provide server side security handler
func (*DefaultServerSecurityHandler) Handle(c Conn) error {
cfg := c.Config().(*ServerConfig)
var secType SecurityType
if c.Protocol() == ProtoVersion37 || c.Protocol() == ProtoVersion38 {
if err := binary.Write(c, binary.BigEndian, uint8(len(cfg.SecurityHandlers))); err != nil {
return err
}
for _, sectype := range cfg.SecurityHandlers {
if err := binary.Write(c, binary.BigEndian, sectype.Type()); err != nil {
return err
}
}
} else {
st := uint32(0)
for _, sectype := range cfg.SecurityHandlers {
if uint32(sectype.Type()) > st {
st = uint32(sectype.Type())
secType = sectype.Type()
}
}
if err := binary.Write(c, binary.BigEndian, st); err != nil {
return err
}
}
if err := c.Flush(); err != nil {
return err
}
if c.Protocol() == ProtoVersion38 {
if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
return err
}
}
secTypes := make(map[SecurityType]SecurityHandler)
for _, sType := range cfg.SecurityHandlers {
secTypes[sType.Type()] = sType
}
sType, ok := secTypes[secType]
if !ok {
return fmt.Errorf("security type %d not implemented", secType)
}
var authCode uint32
authErr := sType.Auth(c)
if authErr != nil {
authCode = uint32(1)
}
if err := binary.Write(c, binary.BigEndian, authCode); err != nil {
return err
}
if authErr == nil {
if err := c.Flush(); err != nil {
return err
}
c.SetSecurityHandler(sType)
return nil
}
if c.Protocol() == ProtoVersion38 {
if err := binary.Write(c, binary.BigEndian, uint32(len(authErr.Error()))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, []byte(authErr.Error())); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
}
return authErr
}
// DefaultClientServerInitHandler default client server init handler
type DefaultClientServerInitHandler struct{}
// Handle provide default server init handler
func (*DefaultClientServerInitHandler) Handle(c Conn) error {
logger.Debug("starting DefaultClientServerInitHandler")
var err error
srvInit := ServerInit{}
if err = binary.Read(c, binary.BigEndian, &srvInit.FBWidth); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.FBHeight); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.PixelFormat); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.NameLength); err != nil {
return err
}
srvInit.NameText = make([]byte, srvInit.NameLength)
if err = binary.Read(c, binary.BigEndian, &srvInit.NameText); err != nil {
return err
}
logger.Debugf("DefaultClientServerInitHandler got serverInit: %v", srvInit)
c.SetDesktopName(srvInit.NameText)
if c.Protocol() == "aten1" {
c.SetWidth(800)
c.SetHeight(600)
c.SetPixelFormat(NewPixelFormatAten())
} else {
c.SetWidth(srvInit.FBWidth)
c.SetHeight(srvInit.FBHeight)
//telling the server to use 32bit pixels (with 24 dept, tight standard format)
pixelMsg:=SetPixelFormat{PF: PixelFormat32bit}
pixelMsg.Write(c)
c.SetPixelFormat(PixelFormat32bit)
//c.SetPixelFormat(srvInit.PixelFormat)
}
if c.Protocol() == "aten1" {
ikvm := struct {
_ [8]byte
IKVMVideoEnable uint8
IKVMKMEnable uint8
IKVMKickEnable uint8
VUSBEnable uint8
}{}
if err = binary.Read(c, binary.BigEndian, &ikvm); err != nil {
return err
}
}
/*
caps := struct {
ServerMessagesNum uint16
ClientMessagesNum uint16
EncodingsNum uint16
_ [2]byte
}{}
if err := binary.Read(c, binary.BigEndian, &caps); err != nil {
return err
}
caps.ServerMessagesNum = uint16(1)
var item [16]byte
for i := uint16(0); i < caps.ServerMessagesNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("server message cap %s\n", item)
}
for i := uint16(0); i < caps.ClientMessagesNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("client message cap %s\n", item)
}
for i := uint16(0); i < caps.EncodingsNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("encoding cap %s\n", item)
}
// var pad [1]byte
// if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
// return err
// }
}*/
return nil
}
// DefaultServerServerInitHandler default server server init handler
type DefaultServerServerInitHandler struct{}
// Handle provide default server server init handler
func (*DefaultServerServerInitHandler) Handle(c Conn) error {
if err := binary.Write(c, binary.BigEndian, c.Width()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, c.Height()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, c.PixelFormat()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, uint32(len(c.DesktopName()))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, []byte(c.DesktopName())); err != nil {
return err
}
return c.Flush()
}
// DefaultClientClientInitHandler default client client init handler
type DefaultClientClientInitHandler struct{}
// Handle provide default client client init handler
func (*DefaultClientClientInitHandler) Handle(c Conn) error {
logger.Debug("starting DefaultClientClientInitHandler")
cfg := c.Config().(*ClientConfig)
var shared uint8
if cfg.Exclusive {
shared = 0
} else {
shared = 1
}
if err := binary.Write(c, binary.BigEndian, shared); err != nil {
return err
}
logger.Debugf("DefaultClientClientInitHandler sending: shared=%d", shared)
return c.Flush()
}
// DefaultServerClientInitHandler default server client init handler
type DefaultServerClientInitHandler struct{}
// Handle provide default server client init handler
func (*DefaultServerClientInitHandler) Handle(c Conn) error {
var shared uint8
if err := binary.Read(c, binary.BigEndian, &shared); err != nil {
return err
}
/* TODO
if shared != 1 {
c.SetShared(false)
}
*/
return nil
}
package vnc2video
import (
"encoding/binary"
"fmt"
"vnc2video/logger"
)
// Handler represents handler of handshake
type Handler interface {
Handle(Conn) error
}
// ProtoVersionLength protocol version length
const ProtoVersionLength = 12
const (
// ProtoVersionUnknown unknown version
ProtoVersionUnknown = ""
// ProtoVersion33 sets if proto 003.003
ProtoVersion33 = "RFB 003.003\n"
// ProtoVersion38 sets if proto 003.008
ProtoVersion38 = "RFB 003.008\n"
// ProtoVersion37 sets if proto 003.007
ProtoVersion37 = "RFB 003.007\n"
)
// ParseProtoVersion parse protocol version
func ParseProtoVersion(pv []byte) (uint, uint, error) {
var major, minor uint
if len(pv) < ProtoVersionLength {
return 0, 0, fmt.Errorf("ProtocolVersion message too short (%v < %v)", len(pv), ProtoVersionLength)
}
l, err := fmt.Sscanf(string(pv), "RFB %d.%d\n", &major, &minor)
if l != 2 {
return 0, 0, fmt.Errorf("error parsing protocol version")
}
if err != nil {
return 0, 0, err
}
return major, minor, nil
}
// DefaultClientVersionHandler represents default handler
type DefaultClientVersionHandler struct{}
// Handle provide version handler for client side
func (*DefaultClientVersionHandler) Handle(c Conn) error {
var version [ProtoVersionLength]byte
if err := binary.Read(c, binary.BigEndian, &version); err != nil {
return err
}
major, minor, err := ParseProtoVersion(version[:])
if err != nil {
return err
}
pv := ProtoVersionUnknown
if major == 3 {
if minor >= 8 {
pv = ProtoVersion38
} else if minor >= 3 {
pv = ProtoVersion38
}
}
if pv == ProtoVersionUnknown {
return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
}
c.SetProtoVersion(string(version[:]))
if err := binary.Write(c, binary.BigEndian, []byte(pv)); err != nil {
return err
}
return c.Flush()
}
// DefaultServerVersionHandler represents default server handler
type DefaultServerVersionHandler struct{}
// Handle provide server version handler
func (*DefaultServerVersionHandler) Handle(c Conn) error {
var version [ProtoVersionLength]byte
if err := binary.Write(c, binary.BigEndian, []byte(ProtoVersion38)); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &version); err != nil {
return err
}
major, minor, err := ParseProtoVersion(version[:])
if err != nil {
return err
}
pv := ProtoVersionUnknown
if major == 3 {
if minor >= 8 {
pv = ProtoVersion38
} else if minor >= 3 {
pv = ProtoVersion33
}
}
if pv == ProtoVersionUnknown {
return fmt.Errorf("ProtocolVersion handshake failed; unsupported version '%v'", string(version[:]))
}
c.SetProtoVersion(pv)
return nil
}
// DefaultClientSecurityHandler used for client security handler
type DefaultClientSecurityHandler struct{}
// Handle provide client side security handler
func (*DefaultClientSecurityHandler) Handle(c Conn) error {
cfg := c.Config().(*ClientConfig)
var numSecurityTypes uint8
if err := binary.Read(c, binary.BigEndian, &numSecurityTypes); err != nil {
return err
}
secTypes := make([]SecurityType, numSecurityTypes)
if err := binary.Read(c, binary.BigEndian, &secTypes); err != nil {
return err
}
var secType SecurityHandler
for _, st := range cfg.SecurityHandlers {
for _, sc := range secTypes {
if st.Type() == sc {
secType = st
}
}
}
if err := binary.Write(c, binary.BigEndian, cfg.SecurityHandlers[0].Type()); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
err := secType.Auth(c)
if err != nil {
return err
}
var authCode uint32
if err := binary.Read(c, binary.BigEndian, &authCode); err != nil {
return err
}
logger.Debugf("authenticating, secType: %d, auth code(0=success): %d", secType.Type(), authCode)
if authCode == 1 {
var reasonLength uint32
if err := binary.Read(c, binary.BigEndian, &reasonLength); err != nil {
return err
}
reasonText := make([]byte, reasonLength)
if err := binary.Read(c, binary.BigEndian, &reasonText); err != nil {
return err
}
return fmt.Errorf("%s", reasonText)
}
c.SetSecurityHandler(secType)
return nil
}
// DefaultServerSecurityHandler used for server security handler
type DefaultServerSecurityHandler struct{}
// Handle provide server side security handler
func (*DefaultServerSecurityHandler) Handle(c Conn) error {
cfg := c.Config().(*ServerConfig)
var secType SecurityType
if c.Protocol() == ProtoVersion37 || c.Protocol() == ProtoVersion38 {
if err := binary.Write(c, binary.BigEndian, uint8(len(cfg.SecurityHandlers))); err != nil {
return err
}
for _, sectype := range cfg.SecurityHandlers {
if err := binary.Write(c, binary.BigEndian, sectype.Type()); err != nil {
return err
}
}
} else {
st := uint32(0)
for _, sectype := range cfg.SecurityHandlers {
if uint32(sectype.Type()) > st {
st = uint32(sectype.Type())
secType = sectype.Type()
}
}
if err := binary.Write(c, binary.BigEndian, st); err != nil {
return err
}
}
if err := c.Flush(); err != nil {
return err
}
if c.Protocol() == ProtoVersion38 {
if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
return err
}
}
secTypes := make(map[SecurityType]SecurityHandler)
for _, sType := range cfg.SecurityHandlers {
secTypes[sType.Type()] = sType
}
sType, ok := secTypes[secType]
if !ok {
return fmt.Errorf("security type %d not implemented", secType)
}
var authCode uint32
authErr := sType.Auth(c)
if authErr != nil {
authCode = uint32(1)
}
if err := binary.Write(c, binary.BigEndian, authCode); err != nil {
return err
}
if authErr == nil {
if err := c.Flush(); err != nil {
return err
}
c.SetSecurityHandler(sType)
return nil
}
if c.Protocol() == ProtoVersion38 {
if err := binary.Write(c, binary.BigEndian, uint32(len(authErr.Error()))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, []byte(authErr.Error())); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
}
return authErr
}
// DefaultClientServerInitHandler default client server init handler
type DefaultClientServerInitHandler struct{}
// Handle provide default server init handler
func (*DefaultClientServerInitHandler) Handle(c Conn) error {
logger.Debug("starting DefaultClientServerInitHandler")
var err error
srvInit := ServerInit{}
if err = binary.Read(c, binary.BigEndian, &srvInit.FBWidth); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.FBHeight); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.PixelFormat); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &srvInit.NameLength); err != nil {
return err
}
srvInit.NameText = make([]byte, srvInit.NameLength)
if err = binary.Read(c, binary.BigEndian, &srvInit.NameText); err != nil {
return err
}
logger.Debugf("DefaultClientServerInitHandler got serverInit: %v", srvInit)
c.SetDesktopName(srvInit.NameText)
if c.Protocol() == "aten1" {
c.SetWidth(800)
c.SetHeight(600)
c.SetPixelFormat(NewPixelFormatAten())
} else {
c.SetWidth(srvInit.FBWidth)
c.SetHeight(srvInit.FBHeight)
//telling the server to use 32bit pixels (with 24 dept, tight standard format)
pixelMsg:=SetPixelFormat{PF: PixelFormat32bit}
pixelMsg.Write(c)
c.SetPixelFormat(PixelFormat32bit)
//c.SetPixelFormat(srvInit.PixelFormat)
}
if c.Protocol() == "aten1" {
ikvm := struct {
_ [8]byte
IKVMVideoEnable uint8
IKVMKMEnable uint8
IKVMKickEnable uint8
VUSBEnable uint8
}{}
if err = binary.Read(c, binary.BigEndian, &ikvm); err != nil {
return err
}
}
/*
caps := struct {
ServerMessagesNum uint16
ClientMessagesNum uint16
EncodingsNum uint16
_ [2]byte
}{}
if err := binary.Read(c, binary.BigEndian, &caps); err != nil {
return err
}
caps.ServerMessagesNum = uint16(1)
var item [16]byte
for i := uint16(0); i < caps.ServerMessagesNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("server message cap %s\n", item)
}
for i := uint16(0); i < caps.ClientMessagesNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("client message cap %s\n", item)
}
for i := uint16(0); i < caps.EncodingsNum; i++ {
if err := binary.Read(c, binary.BigEndian, &item); err != nil {
return err
}
fmt.Printf("encoding cap %s\n", item)
}
// var pad [1]byte
// if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
// return err
// }
}*/
return nil
}
// DefaultServerServerInitHandler default server server init handler
type DefaultServerServerInitHandler struct{}
// Handle provide default server server init handler
func (*DefaultServerServerInitHandler) Handle(c Conn) error {
if err := binary.Write(c, binary.BigEndian, c.Width()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, c.Height()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, c.PixelFormat()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, uint32(len(c.DesktopName()))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, []byte(c.DesktopName())); err != nil {
return err
}
return c.Flush()
}
// DefaultClientClientInitHandler default client client init handler
type DefaultClientClientInitHandler struct{}
// Handle provide default client client init handler
func (*DefaultClientClientInitHandler) Handle(c Conn) error {
logger.Debug("starting DefaultClientClientInitHandler")
cfg := c.Config().(*ClientConfig)
var shared uint8
if cfg.Exclusive {
shared = 0
} else {
shared = 1
}
if err := binary.Write(c, binary.BigEndian, shared); err != nil {
return err
}
logger.Debugf("DefaultClientClientInitHandler sending: shared=%d", shared)
return c.Flush()
}
// DefaultServerClientInitHandler default server client init handler
type DefaultServerClientInitHandler struct{}
// Handle provide default server client init handler
func (*DefaultServerClientInitHandler) Handle(c Conn) error {
var shared uint8
if err := binary.Read(c, binary.BigEndian, &shared); err != nil {
return err
}
/* TODO
if shared != 1 {
c.SetShared(false)
}
*/
return nil
}

404
image.go
View File

@ -1,202 +1,202 @@
package vnc2webm
import (
"encoding/binary"
"fmt"
"image"
)
//var _ draw.Drawer = (*ServerConn)(nil)
//var _ draw.Image = (*ServerConn)(nil)
// Color represents a single color in a color map.
type Color struct {
pf *PixelFormat
cm *ColorMap
cmIndex uint32 // Only valid if pf.TrueColor is false.
R, G, B uint16
}
// ColorMap represent color map
type ColorMap [256]Color
// NewColor returns a new Color object
func NewColor(pf *PixelFormat, cm *ColorMap) *Color {
return &Color{
pf: pf,
cm: cm,
}
}
// Rectangle represents a rectangle of pixel data
type Rectangle struct {
X, Y uint16
Width, Height uint16
EncType EncodingType
Enc Encoding
}
// String return string representation
func (rect *Rectangle) String() string {
return fmt.Sprintf("rect x: %d, y: %d, width: %d, height: %d, enc: %s", rect.X, rect.Y, rect.Width, rect.Height, rect.EncType)
}
// NewRectangle returns new rectangle
func NewRectangle() *Rectangle {
return &Rectangle{}
}
// Write marshal color to conn
func (clr *Color) Write(c Conn) error {
var err error
pf := c.PixelFormat()
order := pf.order()
pixel := clr.cmIndex
if clr.pf.TrueColor != 0 {
pixel = uint32(clr.R) << pf.RedShift
pixel |= uint32(clr.G) << pf.GreenShift
pixel |= uint32(clr.B) << pf.BlueShift
}
switch pf.BPP {
case 8:
err = binary.Write(c, order, byte(pixel))
case 16:
err = binary.Write(c, order, uint16(pixel))
case 32:
err = binary.Write(c, order, uint32(pixel))
}
return err
}
// Read unmarshal color from conn
func (clr *Color) Read(c Conn) error {
order := clr.pf.order()
var pixel uint32
switch clr.pf.BPP {
case 8:
var px uint8
if err := binary.Read(c, order, &px); err != nil {
return err
}
pixel = uint32(px)
case 16:
var px uint16
if err := binary.Read(c, order, &px); err != nil {
return err
}
pixel = uint32(px)
case 32:
var px uint32
if err := binary.Read(c, order, &px); err != nil {
return err
}
pixel = uint32(px)
}
if clr.pf.TrueColor != 0 {
clr.R = uint16((pixel >> clr.pf.RedShift) & uint32(clr.pf.RedMax))
clr.G = uint16((pixel >> clr.pf.GreenShift) & uint32(clr.pf.GreenMax))
clr.B = uint16((pixel >> clr.pf.BlueShift) & uint32(clr.pf.BlueMax))
} else {
*clr = clr.cm[pixel]
clr.cmIndex = pixel
}
return nil
}
func colorsToImage(x, y, width, height uint16, colors []Color) *image.RGBA64 {
rect := image.Rect(int(x), int(y), int(x+width), int(y+height))
rgba := image.NewRGBA64(rect)
a := uint16(1)
for i, color := range colors {
rgba.Pix[4*i+0] = uint8(color.R >> 8)
rgba.Pix[4*i+1] = uint8(color.R)
rgba.Pix[4*i+2] = uint8(color.G >> 8)
rgba.Pix[4*i+3] = uint8(color.G)
rgba.Pix[4*i+4] = uint8(color.B >> 8)
rgba.Pix[4*i+5] = uint8(color.B)
rgba.Pix[4*i+6] = uint8(a >> 8)
rgba.Pix[4*i+7] = uint8(a)
}
return rgba
}
// Write marshal rectangle to conn
func (rect *Rectangle) Write(c Conn) error {
var err error
if err = binary.Write(c, binary.BigEndian, rect.X); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.Y); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.Width); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.Height); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.EncType); err != nil {
return err
}
return rect.Enc.Write(c, rect)
}
// Read unmarshal rectangle from conn
func (rect *Rectangle) Read(c Conn) error {
var err error
if err = binary.Read(c, binary.BigEndian, &rect.X); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.Y); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.Width); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.Height); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.EncType); err != nil {
return err
}
switch rect.EncType {
// case EncCopyRect:
// rect.Enc = &CopyRectEncoding{}
// case EncTight:
// rect.Enc = c.GetEncInstance(rect.EncType)
// case EncTightPng:
// rect.Enc = &TightPngEncoding{}
// case EncRaw:
// if strings.HasPrefix(c.Protocol(), "aten") {
// rect.Enc = &AtenHermon{}
// } else {
// rect.Enc = &RawEncoding{}
// }
case EncDesktopSizePseudo:
rect.Enc = &DesktopSizePseudoEncoding{}
case EncDesktopNamePseudo:
rect.Enc = &DesktopNamePseudoEncoding{}
// case EncXCursorPseudo:
// rect.Enc = &XCursorPseudoEncoding{}
// case EncAtenHermon:
// rect.Enc = &AtenHermon{}
default:
rect.Enc = c.GetEncInstance(rect.EncType)
if rect.Enc == nil {
return fmt.Errorf("unsupported encoding %s", rect.EncType)
}
}
return rect.Enc.Read(c, rect)
}
// Area returns the total area in pixels of the Rectangle
func (rect *Rectangle) Area() int { return int(rect.Width) * int(rect.Height) }
package vnc2video
import (
"encoding/binary"
"fmt"
"image"
)
//var _ draw.Drawer = (*ServerConn)(nil)
//var _ draw.Image = (*ServerConn)(nil)
// Color represents a single color in a color map.
type Color struct {
pf *PixelFormat
cm *ColorMap
cmIndex uint32 // Only valid if pf.TrueColor is false.
R, G, B uint16
}
// ColorMap represent color map
type ColorMap [256]Color
// NewColor returns a new Color object
func NewColor(pf *PixelFormat, cm *ColorMap) *Color {
return &Color{
pf: pf,
cm: cm,
}
}
// Rectangle represents a rectangle of pixel data
type Rectangle struct {
X, Y uint16
Width, Height uint16
EncType EncodingType
Enc Encoding
}
// String return string representation
func (rect *Rectangle) String() string {
return fmt.Sprintf("rect x: %d, y: %d, width: %d, height: %d, enc: %s", rect.X, rect.Y, rect.Width, rect.Height, rect.EncType)
}
// NewRectangle returns new rectangle
func NewRectangle() *Rectangle {
return &Rectangle{}
}
// Write marshal color to conn
func (clr *Color) Write(c Conn) error {
var err error
pf := c.PixelFormat()
order := pf.order()
pixel := clr.cmIndex
if clr.pf.TrueColor != 0 {
pixel = uint32(clr.R) << pf.RedShift
pixel |= uint32(clr.G) << pf.GreenShift
pixel |= uint32(clr.B) << pf.BlueShift
}
switch pf.BPP {
case 8:
err = binary.Write(c, order, byte(pixel))
case 16:
err = binary.Write(c, order, uint16(pixel))
case 32:
err = binary.Write(c, order, uint32(pixel))
}
return err
}
// Read unmarshal color from conn
func (clr *Color) Read(c Conn) error {
order := clr.pf.order()
var pixel uint32
switch clr.pf.BPP {
case 8:
var px uint8
if err := binary.Read(c, order, &px); err != nil {
return err
}
pixel = uint32(px)
case 16:
var px uint16
if err := binary.Read(c, order, &px); err != nil {
return err
}
pixel = uint32(px)
case 32:
var px uint32
if err := binary.Read(c, order, &px); err != nil {
return err
}
pixel = uint32(px)
}
if clr.pf.TrueColor != 0 {
clr.R = uint16((pixel >> clr.pf.RedShift) & uint32(clr.pf.RedMax))
clr.G = uint16((pixel >> clr.pf.GreenShift) & uint32(clr.pf.GreenMax))
clr.B = uint16((pixel >> clr.pf.BlueShift) & uint32(clr.pf.BlueMax))
} else {
*clr = clr.cm[pixel]
clr.cmIndex = pixel
}
return nil
}
func colorsToImage(x, y, width, height uint16, colors []Color) *image.RGBA64 {
rect := image.Rect(int(x), int(y), int(x+width), int(y+height))
rgba := image.NewRGBA64(rect)
a := uint16(1)
for i, color := range colors {
rgba.Pix[4*i+0] = uint8(color.R >> 8)
rgba.Pix[4*i+1] = uint8(color.R)
rgba.Pix[4*i+2] = uint8(color.G >> 8)
rgba.Pix[4*i+3] = uint8(color.G)
rgba.Pix[4*i+4] = uint8(color.B >> 8)
rgba.Pix[4*i+5] = uint8(color.B)
rgba.Pix[4*i+6] = uint8(a >> 8)
rgba.Pix[4*i+7] = uint8(a)
}
return rgba
}
// Write marshal rectangle to conn
func (rect *Rectangle) Write(c Conn) error {
var err error
if err = binary.Write(c, binary.BigEndian, rect.X); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.Y); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.Width); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.Height); err != nil {
return err
}
if err = binary.Write(c, binary.BigEndian, rect.EncType); err != nil {
return err
}
return rect.Enc.Write(c, rect)
}
// Read unmarshal rectangle from conn
func (rect *Rectangle) Read(c Conn) error {
var err error
if err = binary.Read(c, binary.BigEndian, &rect.X); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.Y); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.Width); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.Height); err != nil {
return err
}
if err = binary.Read(c, binary.BigEndian, &rect.EncType); err != nil {
return err
}
switch rect.EncType {
// case EncCopyRect:
// rect.Enc = &CopyRectEncoding{}
// case EncTight:
// rect.Enc = c.GetEncInstance(rect.EncType)
// case EncTightPng:
// rect.Enc = &TightPngEncoding{}
// case EncRaw:
// if strings.HasPrefix(c.Protocol(), "aten") {
// rect.Enc = &AtenHermon{}
// } else {
// rect.Enc = &RawEncoding{}
// }
case EncDesktopSizePseudo:
rect.Enc = &DesktopSizePseudoEncoding{}
case EncDesktopNamePseudo:
rect.Enc = &DesktopNamePseudoEncoding{}
// case EncXCursorPseudo:
// rect.Enc = &XCursorPseudoEncoding{}
// case EncAtenHermon:
// rect.Enc = &AtenHermon{}
default:
rect.Enc = c.GetEncInstance(rect.EncType)
if rect.Enc == nil {
return fmt.Errorf("unsupported encoding %s", rect.EncType)
}
}
return rect.Enc.Read(c, rect)
}
// Area returns the total area in pixels of the Rectangle
func (rect *Rectangle) Area() int { return int(rect.Width) * int(rect.Height) }

View File

@ -1,197 +1,197 @@
// Code generated by "stringer -type=Key"; DO NOT EDIT.
package vnc2webm
import "fmt"
const _Key_name = "SpaceExclaimQuoteDblNumberSignDollarPercentAmpersandApostropheParenLeftParenRightAsteriskPlusCommaMinusPeriodSlashDigit0Digit1Digit2Digit3Digit4Digit5Digit6Digit7Digit8Digit9ColonSemicolonLessEqualGreaterQuestionAtABCDEFGHIJKLMNOPQRSTUVWXYZBracketLeftBackslashBracketRightAsciiCircumUnderscoreGraveSmallASmallBSmallCSmallDSmallESmallFSmallGSmallHSmallISmallJSmallKSmallLSmallMSmallNSmallOSmallPSmallQSmallRSmallSSmallTSmallUSmallVSmallWSmallXSmallYSmallZBraceLeftBarBraceRightAsciiTildeBackSpaceTabLinefeedClearReturnPauseScrollLockSysReqEscapeHomeLeftUpRightDownPageUpPageDownEndBeginSelectModeSwitchNumLockKeypadSpaceKeypadTabKeypadEnterKeypadF1KeypadF2KeypadF3KeypadF4KeypadHomeKeypadLeftKeypadUpKeypadRightKeypadDownKeypadPriorKeypadPageUpKeypadNextKeypadPageDownKeypadEndKeypadBeginKeypadInsertKeypadDeleteKeypadMultiplyKeypadAddKeypadSeparatorKeypadSubtractKeypadDecimalKeypadDivideKeypad0Keypad1Keypad2Keypad3Keypad4Keypad5Keypad6Keypad7Keypad8Keypad9KeypadEqualF1F2F3F4F5F6F7F8F9F10F11F12ShiftLeftShiftRightControlLeftControlRightCapsLockShiftLockMetaLeftMetaRightAltLeftAltRightSuperLeftSuperRightHyperLeftHyperRightDelete"
var _Key_map = map[Key]string{
32: _Key_name[0:5],
33: _Key_name[5:12],
34: _Key_name[12:20],
35: _Key_name[20:30],
36: _Key_name[30:36],
37: _Key_name[36:43],
38: _Key_name[43:52],
39: _Key_name[52:62],
40: _Key_name[62:71],
41: _Key_name[71:81],
42: _Key_name[81:89],
43: _Key_name[89:93],
44: _Key_name[93:98],
45: _Key_name[98:103],
46: _Key_name[103:109],
47: _Key_name[109:114],
48: _Key_name[114:120],
49: _Key_name[120:126],
50: _Key_name[126:132],
51: _Key_name[132:138],
52: _Key_name[138:144],
53: _Key_name[144:150],
54: _Key_name[150:156],
55: _Key_name[156:162],
56: _Key_name[162:168],
57: _Key_name[168:174],
58: _Key_name[174:179],
59: _Key_name[179:188],
60: _Key_name[188:192],
61: _Key_name[192:197],
62: _Key_name[197:204],
63: _Key_name[204:212],
64: _Key_name[212:214],
65: _Key_name[214:215],
66: _Key_name[215:216],
67: _Key_name[216:217],
68: _Key_name[217:218],
69: _Key_name[218:219],
70: _Key_name[219:220],
71: _Key_name[220:221],
72: _Key_name[221:222],
73: _Key_name[222:223],
74: _Key_name[223:224],
75: _Key_name[224:225],
76: _Key_name[225:226],
77: _Key_name[226:227],
78: _Key_name[227:228],
79: _Key_name[228:229],
80: _Key_name[229:230],
81: _Key_name[230:231],
82: _Key_name[231:232],
83: _Key_name[232:233],
84: _Key_name[233:234],
85: _Key_name[234:235],
86: _Key_name[235:236],
87: _Key_name[236:237],
88: _Key_name[237:238],
89: _Key_name[238:239],
90: _Key_name[239:240],
91: _Key_name[240:251],
92: _Key_name[251:260],
93: _Key_name[260:272],
94: _Key_name[272:283],
95: _Key_name[283:293],
96: _Key_name[293:298],
97: _Key_name[298:304],
98: _Key_name[304:310],
99: _Key_name[310:316],
100: _Key_name[316:322],
101: _Key_name[322:328],
102: _Key_name[328:334],
103: _Key_name[334:340],
104: _Key_name[340:346],
105: _Key_name[346:352],
106: _Key_name[352:358],
107: _Key_name[358:364],
108: _Key_name[364:370],
109: _Key_name[370:376],
110: _Key_name[376:382],
111: _Key_name[382:388],
112: _Key_name[388:394],
113: _Key_name[394:400],
114: _Key_name[400:406],
115: _Key_name[406:412],
116: _Key_name[412:418],
117: _Key_name[418:424],
118: _Key_name[424:430],
119: _Key_name[430:436],
120: _Key_name[436:442],
121: _Key_name[442:448],
122: _Key_name[448:454],
123: _Key_name[454:463],
124: _Key_name[463:466],
125: _Key_name[466:476],
126: _Key_name[476:486],
65288: _Key_name[486:495],
65289: _Key_name[495:498],
65290: _Key_name[498:506],
65291: _Key_name[506:511],
65293: _Key_name[511:517],
65299: _Key_name[517:522],
65300: _Key_name[522:532],
65301: _Key_name[532:538],
65307: _Key_name[538:544],
65360: _Key_name[544:548],
65361: _Key_name[548:552],
65362: _Key_name[552:554],
65363: _Key_name[554:559],
65364: _Key_name[559:563],
65365: _Key_name[563:569],
65366: _Key_name[569:577],
65367: _Key_name[577:580],
65368: _Key_name[580:585],
65376: _Key_name[585:591],
65406: _Key_name[591:601],
65407: _Key_name[601:608],
65408: _Key_name[608:619],
65417: _Key_name[619:628],
65421: _Key_name[628:639],
65425: _Key_name[639:647],
65426: _Key_name[647:655],
65427: _Key_name[655:663],
65428: _Key_name[663:671],
65429: _Key_name[671:681],
65430: _Key_name[681:691],
65431: _Key_name[691:699],
65432: _Key_name[699:710],
65433: _Key_name[710:720],
65434: _Key_name[720:731],
65435: _Key_name[731:743],
65436: _Key_name[743:753],
65437: _Key_name[753:767],
65438: _Key_name[767:776],
65439: _Key_name[776:787],
65440: _Key_name[787:799],
65441: _Key_name[799:811],
65442: _Key_name[811:825],
65443: _Key_name[825:834],
65444: _Key_name[834:849],
65445: _Key_name[849:863],
65446: _Key_name[863:876],
65447: _Key_name[876:888],
65448: _Key_name[888:895],
65449: _Key_name[895:902],
65450: _Key_name[902:909],
65451: _Key_name[909:916],
65452: _Key_name[916:923],
65453: _Key_name[923:930],
65454: _Key_name[930:937],
65455: _Key_name[937:944],
65456: _Key_name[944:951],
65457: _Key_name[951:958],
65469: _Key_name[958:969],
65470: _Key_name[969:971],
65471: _Key_name[971:973],
65472: _Key_name[973:975],
65473: _Key_name[975:977],
65474: _Key_name[977:979],
65475: _Key_name[979:981],
65476: _Key_name[981:983],
65477: _Key_name[983:985],
65478: _Key_name[985:987],
65479: _Key_name[987:990],
65480: _Key_name[990:993],
65481: _Key_name[993:996],
65505: _Key_name[996:1005],
65506: _Key_name[1005:1015],
65507: _Key_name[1015:1026],
65508: _Key_name[1026:1038],
65509: _Key_name[1038:1046],
65510: _Key_name[1046:1055],
65511: _Key_name[1055:1063],
65512: _Key_name[1063:1072],
65513: _Key_name[1072:1079],
65514: _Key_name[1079:1087],
65515: _Key_name[1087:1096],
65516: _Key_name[1096:1106],
65517: _Key_name[1106:1115],
65518: _Key_name[1115:1125],
65535: _Key_name[1125:1131],
}
func (i Key) String() string {
if str, ok := _Key_map[i]; ok {
return str
}
return fmt.Sprintf("Key(%d)", i)
}
// Code generated by "stringer -type=Key"; DO NOT EDIT.
package vnc2video
import "fmt"
const _Key_name = "SpaceExclaimQuoteDblNumberSignDollarPercentAmpersandApostropheParenLeftParenRightAsteriskPlusCommaMinusPeriodSlashDigit0Digit1Digit2Digit3Digit4Digit5Digit6Digit7Digit8Digit9ColonSemicolonLessEqualGreaterQuestionAtABCDEFGHIJKLMNOPQRSTUVWXYZBracketLeftBackslashBracketRightAsciiCircumUnderscoreGraveSmallASmallBSmallCSmallDSmallESmallFSmallGSmallHSmallISmallJSmallKSmallLSmallMSmallNSmallOSmallPSmallQSmallRSmallSSmallTSmallUSmallVSmallWSmallXSmallYSmallZBraceLeftBarBraceRightAsciiTildeBackSpaceTabLinefeedClearReturnPauseScrollLockSysReqEscapeHomeLeftUpRightDownPageUpPageDownEndBeginSelectModeSwitchNumLockKeypadSpaceKeypadTabKeypadEnterKeypadF1KeypadF2KeypadF3KeypadF4KeypadHomeKeypadLeftKeypadUpKeypadRightKeypadDownKeypadPriorKeypadPageUpKeypadNextKeypadPageDownKeypadEndKeypadBeginKeypadInsertKeypadDeleteKeypadMultiplyKeypadAddKeypadSeparatorKeypadSubtractKeypadDecimalKeypadDivideKeypad0Keypad1Keypad2Keypad3Keypad4Keypad5Keypad6Keypad7Keypad8Keypad9KeypadEqualF1F2F3F4F5F6F7F8F9F10F11F12ShiftLeftShiftRightControlLeftControlRightCapsLockShiftLockMetaLeftMetaRightAltLeftAltRightSuperLeftSuperRightHyperLeftHyperRightDelete"
var _Key_map = map[Key]string{
32: _Key_name[0:5],
33: _Key_name[5:12],
34: _Key_name[12:20],
35: _Key_name[20:30],
36: _Key_name[30:36],
37: _Key_name[36:43],
38: _Key_name[43:52],
39: _Key_name[52:62],
40: _Key_name[62:71],
41: _Key_name[71:81],
42: _Key_name[81:89],
43: _Key_name[89:93],
44: _Key_name[93:98],
45: _Key_name[98:103],
46: _Key_name[103:109],
47: _Key_name[109:114],
48: _Key_name[114:120],
49: _Key_name[120:126],
50: _Key_name[126:132],
51: _Key_name[132:138],
52: _Key_name[138:144],
53: _Key_name[144:150],
54: _Key_name[150:156],
55: _Key_name[156:162],
56: _Key_name[162:168],
57: _Key_name[168:174],
58: _Key_name[174:179],
59: _Key_name[179:188],
60: _Key_name[188:192],
61: _Key_name[192:197],
62: _Key_name[197:204],
63: _Key_name[204:212],
64: _Key_name[212:214],
65: _Key_name[214:215],
66: _Key_name[215:216],
67: _Key_name[216:217],
68: _Key_name[217:218],
69: _Key_name[218:219],
70: _Key_name[219:220],
71: _Key_name[220:221],
72: _Key_name[221:222],
73: _Key_name[222:223],
74: _Key_name[223:224],
75: _Key_name[224:225],
76: _Key_name[225:226],
77: _Key_name[226:227],
78: _Key_name[227:228],
79: _Key_name[228:229],
80: _Key_name[229:230],
81: _Key_name[230:231],
82: _Key_name[231:232],
83: _Key_name[232:233],
84: _Key_name[233:234],
85: _Key_name[234:235],
86: _Key_name[235:236],
87: _Key_name[236:237],
88: _Key_name[237:238],
89: _Key_name[238:239],
90: _Key_name[239:240],
91: _Key_name[240:251],
92: _Key_name[251:260],
93: _Key_name[260:272],
94: _Key_name[272:283],
95: _Key_name[283:293],
96: _Key_name[293:298],
97: _Key_name[298:304],
98: _Key_name[304:310],
99: _Key_name[310:316],
100: _Key_name[316:322],
101: _Key_name[322:328],
102: _Key_name[328:334],
103: _Key_name[334:340],
104: _Key_name[340:346],
105: _Key_name[346:352],
106: _Key_name[352:358],
107: _Key_name[358:364],
108: _Key_name[364:370],
109: _Key_name[370:376],
110: _Key_name[376:382],
111: _Key_name[382:388],
112: _Key_name[388:394],
113: _Key_name[394:400],
114: _Key_name[400:406],
115: _Key_name[406:412],
116: _Key_name[412:418],
117: _Key_name[418:424],
118: _Key_name[424:430],
119: _Key_name[430:436],
120: _Key_name[436:442],
121: _Key_name[442:448],
122: _Key_name[448:454],
123: _Key_name[454:463],
124: _Key_name[463:466],
125: _Key_name[466:476],
126: _Key_name[476:486],
65288: _Key_name[486:495],
65289: _Key_name[495:498],
65290: _Key_name[498:506],
65291: _Key_name[506:511],
65293: _Key_name[511:517],
65299: _Key_name[517:522],
65300: _Key_name[522:532],
65301: _Key_name[532:538],
65307: _Key_name[538:544],
65360: _Key_name[544:548],
65361: _Key_name[548:552],
65362: _Key_name[552:554],
65363: _Key_name[554:559],
65364: _Key_name[559:563],
65365: _Key_name[563:569],
65366: _Key_name[569:577],
65367: _Key_name[577:580],
65368: _Key_name[580:585],
65376: _Key_name[585:591],
65406: _Key_name[591:601],
65407: _Key_name[601:608],
65408: _Key_name[608:619],
65417: _Key_name[619:628],
65421: _Key_name[628:639],
65425: _Key_name[639:647],
65426: _Key_name[647:655],
65427: _Key_name[655:663],
65428: _Key_name[663:671],
65429: _Key_name[671:681],
65430: _Key_name[681:691],
65431: _Key_name[691:699],
65432: _Key_name[699:710],
65433: _Key_name[710:720],
65434: _Key_name[720:731],
65435: _Key_name[731:743],
65436: _Key_name[743:753],
65437: _Key_name[753:767],
65438: _Key_name[767:776],
65439: _Key_name[776:787],
65440: _Key_name[787:799],
65441: _Key_name[799:811],
65442: _Key_name[811:825],
65443: _Key_name[825:834],
65444: _Key_name[834:849],
65445: _Key_name[849:863],
65446: _Key_name[863:876],
65447: _Key_name[876:888],
65448: _Key_name[888:895],
65449: _Key_name[895:902],
65450: _Key_name[902:909],
65451: _Key_name[909:916],
65452: _Key_name[916:923],
65453: _Key_name[923:930],
65454: _Key_name[930:937],
65455: _Key_name[937:944],
65456: _Key_name[944:951],
65457: _Key_name[951:958],
65469: _Key_name[958:969],
65470: _Key_name[969:971],
65471: _Key_name[971:973],
65472: _Key_name[973:975],
65473: _Key_name[975:977],
65474: _Key_name[977:979],
65475: _Key_name[979:981],
65476: _Key_name[981:983],
65477: _Key_name[983:985],
65478: _Key_name[985:987],
65479: _Key_name[987:990],
65480: _Key_name[990:993],
65481: _Key_name[993:996],
65505: _Key_name[996:1005],
65506: _Key_name[1005:1015],
65507: _Key_name[1015:1026],
65508: _Key_name[1026:1038],
65509: _Key_name[1038:1046],
65510: _Key_name[1046:1055],
65511: _Key_name[1055:1063],
65512: _Key_name[1063:1072],
65513: _Key_name[1072:1079],
65514: _Key_name[1079:1087],
65515: _Key_name[1087:1096],
65516: _Key_name[1096:1106],
65517: _Key_name[1106:1115],
65518: _Key_name[1115:1125],
65535: _Key_name[1125:1131],
}
func (i Key) String() string {
if str, ok := _Key_map[i]; ok {
return str
}
return fmt.Sprintf("Key(%d)", i)
}

508
keys.go
View File

@ -1,254 +1,254 @@
package vnc2webm
import "fmt"
// Key represents a VNC key press.
type Key uint32
//go:generate stringer -type=Key
// Keys is a slice of Key values.
type Keys []Key
var keymap = map[rune]Key{
'-': Minus,
'0': Digit0,
'1': Digit1,
'2': Digit2,
'3': Digit3,
'4': Digit4,
'5': Digit5,
'6': Digit6,
'7': Digit7,
'8': Digit8,
'9': Digit9,
}
// IntToKeys returns Keys that represent the key presses required to type an int.
func IntToKeys(v int) Keys {
k := Keys{}
for _, c := range fmt.Sprintf("%d", v) {
k = append(k, keymap[c])
}
return k
}
// Latin 1 (byte 3 = 0)
// ISO/IEC 8859-1 = Unicode U+0020..U+00FF
const (
Space Key = iota + 0x0020
Exclaim // exclamation mark
QuoteDbl
NumberSign
Dollar
Percent
Ampersand
Apostrophe
ParenLeft
ParenRight
Asterisk
Plus
Comma
Minus
Period
Slash
Digit0
Digit1
Digit2
Digit3
Digit4
Digit5
Digit6
Digit7
Digit8
Digit9
Colon
Semicolon
Less
Equal
Greater
Question
At
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
BracketLeft
Backslash
BracketRight
AsciiCircum
Underscore
Grave
SmallA
SmallB
SmallC
SmallD
SmallE
SmallF
SmallG
SmallH
SmallI
SmallJ
SmallK
SmallL
SmallM
SmallN
SmallO
SmallP
SmallQ
SmallR
SmallS
SmallT
SmallU
SmallV
SmallW
SmallX
SmallY
SmallZ
BraceLeft
Bar
BraceRight
AsciiTilde
)
const (
BackSpace Key = iota + 0xff08
Tab
Linefeed
Clear
_
Return
)
const (
Pause Key = iota + 0xff13
ScrollLock
SysReq
Escape Key = 0xff1b
Delete Key = 0xffff
)
const ( // Cursor control & motion.
Home Key = iota + 0xff50
Left
Up
Right
Down
PageUp
PageDown
End
Begin
)
const ( // Misc functions.
Select Key = 0xff60
Print
Execute
Insert
Undo
Redo
Menu
Find
Cancel
Help
Break
ModeSwitch Key = 0xff7e
NumLock Key = 0xff7f
)
const ( // Keypad functions.
KeypadSpace Key = 0xff80
KeypadTab Key = 0xff89
KeypadEnter Key = 0xff8d
)
const ( // Keypad functions cont.
KeypadF1 Key = iota + 0xff91
KeypadF2
KeypadF3
KeypadF4
KeypadHome
KeypadLeft
KeypadUp
KeypadRight
KeypadDown
KeypadPrior
KeypadPageUp
KeypadNext
KeypadPageDown
KeypadEnd
KeypadBegin
KeypadInsert
KeypadDelete
KeypadMultiply
KeypadAdd
KeypadSeparator
KeypadSubtract
KeypadDecimal
KeypadDivide
Keypad0
Keypad1
Keypad2
Keypad3
Keypad4
Keypad5
Keypad6
Keypad7
Keypad8
Keypad9
KeypadEqual Key = 0xffbd
)
const (
F1 Key = iota + 0xffbe
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
)
const (
ShiftLeft Key = iota + 0xffe1
ShiftRight
ControlLeft
ControlRight
CapsLock
ShiftLock
MetaLeft
MetaRight
AltLeft
AltRight
SuperLeft
SuperRight
HyperLeft
HyperRight
)
package vnc2video
import "fmt"
// Key represents a VNC key press.
type Key uint32
//go:generate stringer -type=Key
// Keys is a slice of Key values.
type Keys []Key
var keymap = map[rune]Key{
'-': Minus,
'0': Digit0,
'1': Digit1,
'2': Digit2,
'3': Digit3,
'4': Digit4,
'5': Digit5,
'6': Digit6,
'7': Digit7,
'8': Digit8,
'9': Digit9,
}
// IntToKeys returns Keys that represent the key presses required to type an int.
func IntToKeys(v int) Keys {
k := Keys{}
for _, c := range fmt.Sprintf("%d", v) {
k = append(k, keymap[c])
}
return k
}
// Latin 1 (byte 3 = 0)
// ISO/IEC 8859-1 = Unicode U+0020..U+00FF
const (
Space Key = iota + 0x0020
Exclaim // exclamation mark
QuoteDbl
NumberSign
Dollar
Percent
Ampersand
Apostrophe
ParenLeft
ParenRight
Asterisk
Plus
Comma
Minus
Period
Slash
Digit0
Digit1
Digit2
Digit3
Digit4
Digit5
Digit6
Digit7
Digit8
Digit9
Colon
Semicolon
Less
Equal
Greater
Question
At
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X
Y
Z
BracketLeft
Backslash
BracketRight
AsciiCircum
Underscore
Grave
SmallA
SmallB
SmallC
SmallD
SmallE
SmallF
SmallG
SmallH
SmallI
SmallJ
SmallK
SmallL
SmallM
SmallN
SmallO
SmallP
SmallQ
SmallR
SmallS
SmallT
SmallU
SmallV
SmallW
SmallX
SmallY
SmallZ
BraceLeft
Bar
BraceRight
AsciiTilde
)
const (
BackSpace Key = iota + 0xff08
Tab
Linefeed
Clear
_
Return
)
const (
Pause Key = iota + 0xff13
ScrollLock
SysReq
Escape Key = 0xff1b
Delete Key = 0xffff
)
const ( // Cursor control & motion.
Home Key = iota + 0xff50
Left
Up
Right
Down
PageUp
PageDown
End
Begin
)
const ( // Misc functions.
Select Key = 0xff60
Print
Execute
Insert
Undo
Redo
Menu
Find
Cancel
Help
Break
ModeSwitch Key = 0xff7e
NumLock Key = 0xff7f
)
const ( // Keypad functions.
KeypadSpace Key = 0xff80
KeypadTab Key = 0xff89
KeypadEnter Key = 0xff8d
)
const ( // Keypad functions cont.
KeypadF1 Key = iota + 0xff91
KeypadF2
KeypadF3
KeypadF4
KeypadHome
KeypadLeft
KeypadUp
KeypadRight
KeypadDown
KeypadPrior
KeypadPageUp
KeypadNext
KeypadPageDown
KeypadEnd
KeypadBegin
KeypadInsert
KeypadDelete
KeypadMultiply
KeypadAdd
KeypadSeparator
KeypadSubtract
KeypadDecimal
KeypadDivide
Keypad0
Keypad1
Keypad2
Keypad3
Keypad4
Keypad5
Keypad6
Keypad7
Keypad8
Keypad9
KeypadEqual Key = 0xffbd
)
const (
F1 Key = iota + 0xffbe
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
)
const (
ShiftLeft Key = iota + 0xffe1
ShiftRight
ControlLeft
ControlRight
CapsLock
ShiftLock
MetaLeft
MetaRight
AltLeft
AltRight
SuperLeft
SuperRight
HyperLeft
HyperRight
)

View File

@ -1,156 +1,156 @@
package logger
import "fmt"
var simpleLogger = SimpleLogger{LogLevelInfo}
type Logger interface {
Debug(v ...interface{})
Debugf(format string, v ...interface{})
Info(v ...interface{})
Infof(format string, v ...interface{})
Warn(v ...interface{})
Warnf(format string, v ...interface{})
Error(v ...interface{})
Errorf(format string, v ...interface{})
Fatal(v ...interface{})
Fatalf(format string, v ...interface{})
}
type LogLevel int
const (
LogLevelTrace LogLevel = iota
LogLevelDebug
LogLevelInfo
LogLevelWarn
LogLevelError
LogLevelFatal
)
type SimpleLogger struct {
level LogLevel
}
func (sl *SimpleLogger) Trace(v ...interface{}) {
if sl.level <= LogLevelTrace {
arr := []interface{}{"[Trace]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Tracef(format string, v ...interface{}) {
if sl.level <= LogLevelTrace {
fmt.Printf("[Trace] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Debug(v ...interface{}) {
if sl.level <= LogLevelDebug {
arr := []interface{}{"[Debug]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Debugf(format string, v ...interface{}) {
if sl.level <= LogLevelDebug {
fmt.Printf("[Debug] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Info(v ...interface{}) {
if sl.level <= LogLevelInfo {
arr := []interface{}{"[Info ]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Infof(format string, v ...interface{}) {
if sl.level <= LogLevelInfo {
fmt.Printf("[Info ] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Warn(v ...interface{}) {
if sl.level <= LogLevelWarn {
arr := []interface{}{"[Warn ]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Warnf(format string, v ...interface{}) {
if sl.level <= LogLevelWarn {
fmt.Printf("[Warn ] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Error(v ...interface{}) {
if sl.level <= LogLevelError {
arr := []interface{}{"[Error]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Errorf(format string, v ...interface{}) {
if sl.level <= LogLevelError {
fmt.Printf("[Error] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Fatal(v ...interface{}) {
if sl.level <= LogLevelFatal {
arr := []interface{}{"[Fatal]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Fatalf(format string, v ...interface{}) {
if sl.level <= LogLevelFatal {
fmt.Printf("[Fatal] "+format+"\n", v)
}
}
func Debug(v ...interface{}) {
simpleLogger.Debug(v...)
}
func Debugf(format string, v ...interface{}) {
simpleLogger.Debugf(format, v...)
}
func Info(v ...interface{}) {
simpleLogger.Info(v...)
}
func Infof(format string, v ...interface{}) {
simpleLogger.Infof(format, v...)
}
func Warn(v ...interface{}) {
simpleLogger.Warn(v...)
}
func Warnf(format string, v ...interface{}) {
simpleLogger.Warnf(format, v...)
}
func Error(v ...interface{}) {
simpleLogger.Error(v...)
}
func Errorf(format string, v ...interface{}) {
simpleLogger.Errorf(format, v...)
}
func Fatal(v ...interface{}) {
simpleLogger.Fatal(v...)
}
func Fatalf(format string, v ...interface{}) {
simpleLogger.Fatalf(format, v...)
}
package logger
import "fmt"
var simpleLogger = SimpleLogger{LogLevelInfo}
type Logger interface {
Debug(v ...interface{})
Debugf(format string, v ...interface{})
Info(v ...interface{})
Infof(format string, v ...interface{})
Warn(v ...interface{})
Warnf(format string, v ...interface{})
Error(v ...interface{})
Errorf(format string, v ...interface{})
Fatal(v ...interface{})
Fatalf(format string, v ...interface{})
}
type LogLevel int
const (
LogLevelTrace LogLevel = iota
LogLevelDebug
LogLevelInfo
LogLevelWarn
LogLevelError
LogLevelFatal
)
type SimpleLogger struct {
level LogLevel
}
func (sl *SimpleLogger) Trace(v ...interface{}) {
if sl.level <= LogLevelTrace {
arr := []interface{}{"[Trace]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Tracef(format string, v ...interface{}) {
if sl.level <= LogLevelTrace {
fmt.Printf("[Trace] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Debug(v ...interface{}) {
if sl.level <= LogLevelDebug {
arr := []interface{}{"[Debug]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Debugf(format string, v ...interface{}) {
if sl.level <= LogLevelDebug {
fmt.Printf("[Debug] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Info(v ...interface{}) {
if sl.level <= LogLevelInfo {
arr := []interface{}{"[Info ]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Infof(format string, v ...interface{}) {
if sl.level <= LogLevelInfo {
fmt.Printf("[Info ] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Warn(v ...interface{}) {
if sl.level <= LogLevelWarn {
arr := []interface{}{"[Warn ]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Warnf(format string, v ...interface{}) {
if sl.level <= LogLevelWarn {
fmt.Printf("[Warn ] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Error(v ...interface{}) {
if sl.level <= LogLevelError {
arr := []interface{}{"[Error]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Errorf(format string, v ...interface{}) {
if sl.level <= LogLevelError {
fmt.Printf("[Error] "+format+"\n", v...)
}
}
func (sl *SimpleLogger) Fatal(v ...interface{}) {
if sl.level <= LogLevelFatal {
arr := []interface{}{"[Fatal]"}
for _, item := range v {
arr = append(arr, item)
}
fmt.Println(arr...)
}
}
func (sl *SimpleLogger) Fatalf(format string, v ...interface{}) {
if sl.level <= LogLevelFatal {
fmt.Printf("[Fatal] "+format+"\n", v)
}
}
func Debug(v ...interface{}) {
simpleLogger.Debug(v...)
}
func Debugf(format string, v ...interface{}) {
simpleLogger.Debugf(format, v...)
}
func Info(v ...interface{}) {
simpleLogger.Info(v...)
}
func Infof(format string, v ...interface{}) {
simpleLogger.Infof(format, v...)
}
func Warn(v ...interface{}) {
simpleLogger.Warn(v...)
}
func Warnf(format string, v ...interface{}) {
simpleLogger.Warnf(format, v...)
}
func Error(v ...interface{}) {
simpleLogger.Error(v...)
}
func Errorf(format string, v ...interface{}) {
simpleLogger.Errorf(format, v...)
}
func Fatal(v ...interface{}) {
simpleLogger.Fatal(v...)
}
func Fatalf(format string, v ...interface{}) {
simpleLogger.Fatalf(format, v...)
}

File diff suppressed because it is too large Load Diff

View File

@ -1,370 +1,370 @@
package vnc2webm
import (
"encoding/binary"
"fmt"
)
// Aten IKVM server message types
const (
AteniKVMFrontGroundEventMsgType ServerMessageType = 4
AteniKVMKeepAliveEventMsgType ServerMessageType = 22
AteniKVMVideoGetInfoMsgType ServerMessageType = 51
AteniKVMMouseGetInfoMsgType ServerMessageType = 55
AteniKVMSessionMessageMsgType ServerMessageType = 57
AteniKVMGetViewerLangMsgType ServerMessageType = 60
)
// Aten IKVM client message types
const (
AteniKVMKeyEventMsgType ClientMessageType = 4
AteniKVMPointerEventMsgType ClientMessageType = 5
)
// AteniKVMKeyEvent holds the wire format message
type AteniKVMKeyEvent struct {
_ [1]byte // padding
Down uint8 // down-flag
_ [2]byte // padding
Key Key // key
_ [9]byte // padding
}
// AteniKVMPointerEvent holds the wire format message
type AteniKVMPointerEvent struct {
_ [1]byte // padding
Mask uint8 // mask
X uint16 // x
Y uint16 // y
_ [11]byte // padding
}
func (msg *AteniKVMPointerEvent) Supported(c Conn) bool {
return false
}
func (msg *AteniKVMPointerEvent) String() string {
return fmt.Sprintf("mask: %d, x:%d, y:%d", msg.Mask, msg.X, msg.Y)
}
func (msg *AteniKVMPointerEvent) Type() ClientMessageType {
return AteniKVMPointerEventMsgType
}
func (*AteniKVMPointerEvent) Read(c Conn) (ClientMessage, error) {
msg := AteniKVMPointerEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *AteniKVMPointerEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
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 c.Flush()
}
func (msg *AteniKVMKeyEvent) Supported(c Conn) bool {
return false
}
func (msg *AteniKVMKeyEvent) String() string {
return fmt.Sprintf("down:%d, key:%s", msg.Down, msg.Key)
}
func (msg *AteniKVMKeyEvent) Type() ClientMessageType {
return AteniKVMKeyEventMsgType
}
func (*AteniKVMKeyEvent) Read(c Conn) (ClientMessage, error) {
msg := AteniKVMKeyEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *AteniKVMKeyEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
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 c.Flush()
}
// AteniKVMFrontGroundEvent unknown aten ikvm message
type AteniKVMFrontGroundEvent struct {
_ [20]byte
}
func (msg *AteniKVMFrontGroundEvent) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMFrontGroundEvent) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMFrontGroundEvent) Type() ServerMessageType {
return AteniKVMFrontGroundEventMsgType
}
// Read unmarshal message from conn
func (*AteniKVMFrontGroundEvent) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMFrontGroundEvent{}
var pad [20]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMFrontGroundEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [20]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMKeepAliveEvent unknown aten ikvm message
type AteniKVMKeepAliveEvent struct {
_ [1]byte
}
func (msg *AteniKVMKeepAliveEvent) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMKeepAliveEvent) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMKeepAliveEvent) Type() ServerMessageType {
return AteniKVMKeepAliveEventMsgType
}
// Read unmarshal message from conn
func (*AteniKVMKeepAliveEvent) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMKeepAliveEvent{}
var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMKeepAliveEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [1]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMVideoGetInfo unknown aten ikvm message
type AteniKVMVideoGetInfo struct {
_ [20]byte
}
func (msg *AteniKVMVideoGetInfo) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMVideoGetInfo) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMVideoGetInfo) Type() ServerMessageType {
return AteniKVMVideoGetInfoMsgType
}
// Read unmarshal message from conn
func (*AteniKVMVideoGetInfo) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMVideoGetInfo{}
var pad [40]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMVideoGetInfo) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [4]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMMouseGetInfo unknown aten ikvm message
type AteniKVMMouseGetInfo struct {
_ [2]byte
}
func (msg *AteniKVMMouseGetInfo) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMMouseGetInfo) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMMouseGetInfo) Type() ServerMessageType {
return AteniKVMMouseGetInfoMsgType
}
// Read unmarshal message from conn
func (*AteniKVMMouseGetInfo) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMFrontGroundEvent{}
var pad [2]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMMouseGetInfo) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [2]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMSessionMessage unknown aten ikvm message
type AteniKVMSessionMessage struct {
_ [264]byte
}
func (msg *AteniKVMSessionMessage) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMSessionMessage) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMSessionMessage) Type() ServerMessageType {
return AteniKVMSessionMessageMsgType
}
// Read unmarshal message from conn
func (*AteniKVMSessionMessage) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMSessionMessage{}
var pad [264]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMSessionMessage) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [264]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return nil
}
// AteniKVMGetViewerLang unknown aten ikvm message
type AteniKVMGetViewerLang struct {
_ [8]byte
}
func (msg *AteniKVMGetViewerLang) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMGetViewerLang) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMGetViewerLang) Type() ServerMessageType {
return AteniKVMGetViewerLangMsgType
}
// Read unmarshal message from conn
func (*AteniKVMGetViewerLang) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMGetViewerLang{}
var pad [8]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMGetViewerLang) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [8]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
package vnc2video
import (
"encoding/binary"
"fmt"
)
// Aten IKVM server message types
const (
AteniKVMFrontGroundEventMsgType ServerMessageType = 4
AteniKVMKeepAliveEventMsgType ServerMessageType = 22
AteniKVMVideoGetInfoMsgType ServerMessageType = 51
AteniKVMMouseGetInfoMsgType ServerMessageType = 55
AteniKVMSessionMessageMsgType ServerMessageType = 57
AteniKVMGetViewerLangMsgType ServerMessageType = 60
)
// Aten IKVM client message types
const (
AteniKVMKeyEventMsgType ClientMessageType = 4
AteniKVMPointerEventMsgType ClientMessageType = 5
)
// AteniKVMKeyEvent holds the wire format message
type AteniKVMKeyEvent struct {
_ [1]byte // padding
Down uint8 // down-flag
_ [2]byte // padding
Key Key // key
_ [9]byte // padding
}
// AteniKVMPointerEvent holds the wire format message
type AteniKVMPointerEvent struct {
_ [1]byte // padding
Mask uint8 // mask
X uint16 // x
Y uint16 // y
_ [11]byte // padding
}
func (msg *AteniKVMPointerEvent) Supported(c Conn) bool {
return false
}
func (msg *AteniKVMPointerEvent) String() string {
return fmt.Sprintf("mask: %d, x:%d, y:%d", msg.Mask, msg.X, msg.Y)
}
func (msg *AteniKVMPointerEvent) Type() ClientMessageType {
return AteniKVMPointerEventMsgType
}
func (*AteniKVMPointerEvent) Read(c Conn) (ClientMessage, error) {
msg := AteniKVMPointerEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *AteniKVMPointerEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
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 c.Flush()
}
func (msg *AteniKVMKeyEvent) Supported(c Conn) bool {
return false
}
func (msg *AteniKVMKeyEvent) String() string {
return fmt.Sprintf("down:%d, key:%s", msg.Down, msg.Key)
}
func (msg *AteniKVMKeyEvent) Type() ClientMessageType {
return AteniKVMKeyEventMsgType
}
func (*AteniKVMKeyEvent) Read(c Conn) (ClientMessage, error) {
msg := AteniKVMKeyEvent{}
if err := binary.Read(c, binary.BigEndian, &msg); err != nil {
return nil, err
}
return &msg, nil
}
func (msg *AteniKVMKeyEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
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 c.Flush()
}
// AteniKVMFrontGroundEvent unknown aten ikvm message
type AteniKVMFrontGroundEvent struct {
_ [20]byte
}
func (msg *AteniKVMFrontGroundEvent) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMFrontGroundEvent) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMFrontGroundEvent) Type() ServerMessageType {
return AteniKVMFrontGroundEventMsgType
}
// Read unmarshal message from conn
func (*AteniKVMFrontGroundEvent) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMFrontGroundEvent{}
var pad [20]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMFrontGroundEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [20]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMKeepAliveEvent unknown aten ikvm message
type AteniKVMKeepAliveEvent struct {
_ [1]byte
}
func (msg *AteniKVMKeepAliveEvent) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMKeepAliveEvent) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMKeepAliveEvent) Type() ServerMessageType {
return AteniKVMKeepAliveEventMsgType
}
// Read unmarshal message from conn
func (*AteniKVMKeepAliveEvent) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMKeepAliveEvent{}
var pad [1]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMKeepAliveEvent) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [1]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMVideoGetInfo unknown aten ikvm message
type AteniKVMVideoGetInfo struct {
_ [20]byte
}
func (msg *AteniKVMVideoGetInfo) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMVideoGetInfo) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMVideoGetInfo) Type() ServerMessageType {
return AteniKVMVideoGetInfoMsgType
}
// Read unmarshal message from conn
func (*AteniKVMVideoGetInfo) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMVideoGetInfo{}
var pad [40]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMVideoGetInfo) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [4]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMMouseGetInfo unknown aten ikvm message
type AteniKVMMouseGetInfo struct {
_ [2]byte
}
func (msg *AteniKVMMouseGetInfo) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMMouseGetInfo) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMMouseGetInfo) Type() ServerMessageType {
return AteniKVMMouseGetInfoMsgType
}
// Read unmarshal message from conn
func (*AteniKVMMouseGetInfo) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMFrontGroundEvent{}
var pad [2]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMMouseGetInfo) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [2]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}
// AteniKVMSessionMessage unknown aten ikvm message
type AteniKVMSessionMessage struct {
_ [264]byte
}
func (msg *AteniKVMSessionMessage) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMSessionMessage) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMSessionMessage) Type() ServerMessageType {
return AteniKVMSessionMessageMsgType
}
// Read unmarshal message from conn
func (*AteniKVMSessionMessage) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMSessionMessage{}
var pad [264]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMSessionMessage) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [264]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return nil
}
// AteniKVMGetViewerLang unknown aten ikvm message
type AteniKVMGetViewerLang struct {
_ [8]byte
}
func (msg *AteniKVMGetViewerLang) Supported(c Conn) bool {
return false
}
// String return string representation
func (msg *AteniKVMGetViewerLang) String() string {
return fmt.Sprintf("%s", msg.Type())
}
// Type return ServerMessageType
func (*AteniKVMGetViewerLang) Type() ServerMessageType {
return AteniKVMGetViewerLangMsgType
}
// Read unmarshal message from conn
func (*AteniKVMGetViewerLang) Read(c Conn) (ServerMessage, error) {
msg := &AteniKVMGetViewerLang{}
var pad [8]byte
if err := binary.Read(c, binary.BigEndian, &pad); err != nil {
return nil, err
}
return msg, nil
}
// Write marshal message to conn
func (msg *AteniKVMGetViewerLang) Write(c Conn) error {
if !msg.Supported(c) {
return nil
}
var pad [8]byte
if err := binary.Write(c, binary.BigEndian, msg.Type()); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, pad); err != nil {
return err
}
return c.Flush()
}

View File

@ -1,136 +1,136 @@
// Implementation of RFC 6143 §7.4 Pixel Format Data Structure.
package vnc2webm
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
var (
// PixelFormat8bit returns 8 bit pixel format
PixelFormat8bit = NewPixelFormat(8)
// PixelFormat16bit returns 16 bit pixel format
PixelFormat16bit = NewPixelFormat(16)
// PixelFormat32bit returns 32 bit pixel format
PixelFormat32bit = NewPixelFormat(32)
// PixelFormatAten returns pixel format used in Aten IKVM
PixelFormatAten = NewPixelFormatAten()
)
// PixelFormat describes the way a pixel is formatted for a VNC connection
type PixelFormat struct {
BPP uint8 // bits-per-pixel
Depth uint8 // depth
BigEndian uint8 // big-endian-flag
TrueColor uint8 // true-color-flag
RedMax, GreenMax, BlueMax uint16 // red-, green-, blue-max (2^BPP-1)
RedShift, GreenShift, BlueShift uint8 // red-, green-, blue-shift
_ [3]byte // padding
}
const pixelFormatLen = 16
// NewPixelFormat returns a populated PixelFormat structure
func NewPixelFormat(bpp uint8) PixelFormat {
bigEndian := uint8(0)
// rgbMax := uint16(math.Exp2(float64(bpp))) - 1
rMax := uint16(255)
gMax := uint16(255)
bMax := uint16(255)
var (
tc = uint8(1)
rs, gs, bs uint8
depth uint8
)
switch bpp {
case 8:
tc = 0
depth = 8
rs, gs, bs = 0, 0, 0
case 16:
depth = 16
rs, gs, bs = 0, 4, 8
case 32:
depth = 24
// rs, gs, bs = 0, 8, 16
rs, gs, bs = 16, 8, 0
}
return PixelFormat{bpp, depth, bigEndian, tc, rMax, gMax, bMax, rs, gs, bs, [3]byte{}}
}
// NewPixelFormatAten returns Aten IKVM pixel format
func NewPixelFormatAten() PixelFormat {
return PixelFormat{16, 15, 0, 1, (1 << 5) - 1, (1 << 5) - 1, (1 << 5) - 1, 10, 5, 0, [3]byte{}}
}
// Marshal implements the Marshaler interface
func (pf PixelFormat) Marshal() ([]byte, error) {
// Validation checks.
switch pf.BPP {
case 8, 16, 32:
default:
return nil, fmt.Errorf("Invalid BPP value %v; must be 8, 16, or 32", pf.BPP)
}
if pf.Depth < pf.BPP {
return nil, fmt.Errorf("Invalid Depth value %v; cannot be < BPP", pf.Depth)
}
switch pf.Depth {
case 8, 16, 32:
default:
return nil, fmt.Errorf("Invalid Depth value %v; must be 8, 16, or 32", pf.Depth)
}
// Create the slice of bytes
buf := bPool.Get().(*bytes.Buffer)
buf.Reset()
defer bPool.Put(buf)
if err := binary.Write(buf, binary.BigEndian, &pf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Read reads from an io.Reader, and populates the PixelFormat
func (pf PixelFormat) Read(r io.Reader) error {
buf := make([]byte, pixelFormatLen)
if _, err := io.ReadAtLeast(r, buf, pixelFormatLen); err != nil {
return err
}
return pf.Unmarshal(buf)
}
// Unmarshal implements the Unmarshaler interface
func (pf PixelFormat) Unmarshal(data []byte) error {
buf := bPool.Get().(*bytes.Buffer)
buf.Reset()
defer bPool.Put(buf)
if _, err := buf.Write(data); err != nil {
return err
}
if err := binary.Read(buf, binary.BigEndian, &pf); err != nil {
return err
}
return nil
}
// String implements the fmt.Stringer interface
func (pf PixelFormat) String() string {
return fmt.Sprintf("{ bpp: %d depth: %d big-endian: %d true-color: %d red-max: %d green-max: %d blue-max: %d red-shift: %d green-shift: %d blue-shift: %d }",
pf.BPP, pf.Depth, pf.BigEndian, pf.TrueColor, pf.RedMax, pf.GreenMax, pf.BlueMax, pf.RedShift, pf.GreenShift, pf.BlueShift)
}
func (pf PixelFormat) order() binary.ByteOrder {
if pf.BigEndian == 1 {
return binary.BigEndian
}
return binary.LittleEndian
}
// Implementation of RFC 6143 §7.4 Pixel Format Data Structure.
package vnc2video
import (
"bytes"
"encoding/binary"
"fmt"
"io"
)
var (
// PixelFormat8bit returns 8 bit pixel format
PixelFormat8bit = NewPixelFormat(8)
// PixelFormat16bit returns 16 bit pixel format
PixelFormat16bit = NewPixelFormat(16)
// PixelFormat32bit returns 32 bit pixel format
PixelFormat32bit = NewPixelFormat(32)
// PixelFormatAten returns pixel format used in Aten IKVM
PixelFormatAten = NewPixelFormatAten()
)
// PixelFormat describes the way a pixel is formatted for a VNC connection
type PixelFormat struct {
BPP uint8 // bits-per-pixel
Depth uint8 // depth
BigEndian uint8 // big-endian-flag
TrueColor uint8 // true-color-flag
RedMax, GreenMax, BlueMax uint16 // red-, green-, blue-max (2^BPP-1)
RedShift, GreenShift, BlueShift uint8 // red-, green-, blue-shift
_ [3]byte // padding
}
const pixelFormatLen = 16
// NewPixelFormat returns a populated PixelFormat structure
func NewPixelFormat(bpp uint8) PixelFormat {
bigEndian := uint8(0)
// rgbMax := uint16(math.Exp2(float64(bpp))) - 1
rMax := uint16(255)
gMax := uint16(255)
bMax := uint16(255)
var (
tc = uint8(1)
rs, gs, bs uint8
depth uint8
)
switch bpp {
case 8:
tc = 0
depth = 8
rs, gs, bs = 0, 0, 0
case 16:
depth = 16
rs, gs, bs = 0, 4, 8
case 32:
depth = 24
// rs, gs, bs = 0, 8, 16
rs, gs, bs = 16, 8, 0
}
return PixelFormat{bpp, depth, bigEndian, tc, rMax, gMax, bMax, rs, gs, bs, [3]byte{}}
}
// NewPixelFormatAten returns Aten IKVM pixel format
func NewPixelFormatAten() PixelFormat {
return PixelFormat{16, 15, 0, 1, (1 << 5) - 1, (1 << 5) - 1, (1 << 5) - 1, 10, 5, 0, [3]byte{}}
}
// Marshal implements the Marshaler interface
func (pf PixelFormat) Marshal() ([]byte, error) {
// Validation checks.
switch pf.BPP {
case 8, 16, 32:
default:
return nil, fmt.Errorf("Invalid BPP value %v; must be 8, 16, or 32", pf.BPP)
}
if pf.Depth < pf.BPP {
return nil, fmt.Errorf("Invalid Depth value %v; cannot be < BPP", pf.Depth)
}
switch pf.Depth {
case 8, 16, 32:
default:
return nil, fmt.Errorf("Invalid Depth value %v; must be 8, 16, or 32", pf.Depth)
}
// Create the slice of bytes
buf := bPool.Get().(*bytes.Buffer)
buf.Reset()
defer bPool.Put(buf)
if err := binary.Write(buf, binary.BigEndian, &pf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// Read reads from an io.Reader, and populates the PixelFormat
func (pf PixelFormat) Read(r io.Reader) error {
buf := make([]byte, pixelFormatLen)
if _, err := io.ReadAtLeast(r, buf, pixelFormatLen); err != nil {
return err
}
return pf.Unmarshal(buf)
}
// Unmarshal implements the Unmarshaler interface
func (pf PixelFormat) Unmarshal(data []byte) error {
buf := bPool.Get().(*bytes.Buffer)
buf.Reset()
defer bPool.Put(buf)
if _, err := buf.Write(data); err != nil {
return err
}
if err := binary.Read(buf, binary.BigEndian, &pf); err != nil {
return err
}
return nil
}
// String implements the fmt.Stringer interface
func (pf PixelFormat) String() string {
return fmt.Sprintf("{ bpp: %d depth: %d big-endian: %d true-color: %d red-max: %d green-max: %d blue-max: %d red-shift: %d green-shift: %d blue-shift: %d }",
pf.BPP, pf.Depth, pf.BigEndian, pf.TrueColor, pf.RedMax, pf.GreenMax, pf.BlueMax, pf.RedShift, pf.GreenShift, pf.BlueShift)
}
func (pf PixelFormat) order() binary.ByteOrder {
if pf.BigEndian == 1 {
return binary.BigEndian
}
return binary.LittleEndian
}

View File

@ -1,50 +1,50 @@
package vnc2webm
type SecurityType uint8
//go:generate stringer -type=SecurityType
const (
SecTypeUnknown SecurityType = SecurityType(0)
SecTypeNone SecurityType = SecurityType(1)
SecTypeVNC SecurityType = SecurityType(2)
SecTypeTight SecurityType = SecurityType(16)
SecTypeATEN SecurityType = SecurityType(16)
SecTypeVeNCrypt SecurityType = SecurityType(19)
)
type SecuritySubType uint32
//go:generate stringer -type=SecuritySubType
const (
SecSubTypeUnknown SecuritySubType = SecuritySubType(0)
)
const (
SecSubTypeVeNCrypt01Unknown SecuritySubType = SecuritySubType(0)
SecSubTypeVeNCrypt01Plain SecuritySubType = SecuritySubType(19)
SecSubTypeVeNCrypt01TLSNone SecuritySubType = SecuritySubType(20)
SecSubTypeVeNCrypt01TLSVNC SecuritySubType = SecuritySubType(21)
SecSubTypeVeNCrypt01TLSPlain SecuritySubType = SecuritySubType(22)
SecSubTypeVeNCrypt01X509None SecuritySubType = SecuritySubType(23)
SecSubTypeVeNCrypt01X509VNC SecuritySubType = SecuritySubType(24)
SecSubTypeVeNCrypt01X509Plain SecuritySubType = SecuritySubType(25)
)
const (
SecSubTypeVeNCrypt02Unknown SecuritySubType = SecuritySubType(0)
SecSubTypeVeNCrypt02Plain SecuritySubType = SecuritySubType(256)
SecSubTypeVeNCrypt02TLSNone SecuritySubType = SecuritySubType(257)
SecSubTypeVeNCrypt02TLSVNC SecuritySubType = SecuritySubType(258)
SecSubTypeVeNCrypt02TLSPlain SecuritySubType = SecuritySubType(259)
SecSubTypeVeNCrypt02X509None SecuritySubType = SecuritySubType(260)
SecSubTypeVeNCrypt02X509VNC SecuritySubType = SecuritySubType(261)
SecSubTypeVeNCrypt02X509Plain SecuritySubType = SecuritySubType(262)
)
type SecurityHandler interface {
Type() SecurityType
SubType() SecuritySubType
Auth(Conn) error
}
package vnc2video
type SecurityType uint8
//go:generate stringer -type=SecurityType
const (
SecTypeUnknown SecurityType = SecurityType(0)
SecTypeNone SecurityType = SecurityType(1)
SecTypeVNC SecurityType = SecurityType(2)
SecTypeTight SecurityType = SecurityType(16)
SecTypeATEN SecurityType = SecurityType(16)
SecTypeVeNCrypt SecurityType = SecurityType(19)
)
type SecuritySubType uint32
//go:generate stringer -type=SecuritySubType
const (
SecSubTypeUnknown SecuritySubType = SecuritySubType(0)
)
const (
SecSubTypeVeNCrypt01Unknown SecuritySubType = SecuritySubType(0)
SecSubTypeVeNCrypt01Plain SecuritySubType = SecuritySubType(19)
SecSubTypeVeNCrypt01TLSNone SecuritySubType = SecuritySubType(20)
SecSubTypeVeNCrypt01TLSVNC SecuritySubType = SecuritySubType(21)
SecSubTypeVeNCrypt01TLSPlain SecuritySubType = SecuritySubType(22)
SecSubTypeVeNCrypt01X509None SecuritySubType = SecuritySubType(23)
SecSubTypeVeNCrypt01X509VNC SecuritySubType = SecuritySubType(24)
SecSubTypeVeNCrypt01X509Plain SecuritySubType = SecuritySubType(25)
)
const (
SecSubTypeVeNCrypt02Unknown SecuritySubType = SecuritySubType(0)
SecSubTypeVeNCrypt02Plain SecuritySubType = SecuritySubType(256)
SecSubTypeVeNCrypt02TLSNone SecuritySubType = SecuritySubType(257)
SecSubTypeVeNCrypt02TLSVNC SecuritySubType = SecuritySubType(258)
SecSubTypeVeNCrypt02TLSPlain SecuritySubType = SecuritySubType(259)
SecSubTypeVeNCrypt02X509None SecuritySubType = SecuritySubType(260)
SecSubTypeVeNCrypt02X509VNC SecuritySubType = SecuritySubType(261)
SecSubTypeVeNCrypt02X509Plain SecuritySubType = SecuritySubType(262)
)
type SecurityHandler interface {
Type() SecurityType
SubType() SecuritySubType
Auth(Conn) error
}

View File

@ -1,107 +1,107 @@
package vnc2webm
import (
"bytes"
"encoding/binary"
"fmt"
)
type ClientAuthATEN struct {
Username []byte
Password []byte
}
func (*ClientAuthATEN) Type() SecurityType {
return SecTypeATEN
}
func (*ClientAuthATEN) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func charCodeAt(s string, n int) rune {
for i, r := range s {
if i == n {
return r
}
}
return 0
}
func (auth *ClientAuthATEN) Auth(c Conn) error {
var definedAuthLen = 24
if len(auth.Username) > definedAuthLen || len(auth.Password) > definedAuthLen {
return fmt.Errorf("username/password is too long, allowed 0-23")
}
nt, err := readTightTunnels(c)
if err != nil {
return err
}
/*
fmt.Printf("tunnels %d\n", nt)
for i := uint32(0); i < nt; i++ {
code, vendor, signature, err := readTightCaps(c)
if err != nil {
return err
}
fmt.Printf("code %d vendor %s signature %s\n", code, vendor, signature)
}
*/
if ((nt&0xffff0ff0)>>0 == 0xaff90fb0) || (nt <= 0 || nt > 0x1000000) {
c.SetProtoVersion("aten1")
var skip [20]byte
binary.Read(c, binary.BigEndian, &skip)
//fmt.Printf("skip %v\n", skip)
}
username := make([]byte, definedAuthLen)
password := make([]byte, definedAuthLen)
copy(username, auth.Username)
copy(password, auth.Password)
challenge := bytes.Join([][]byte{username, password}, []byte(""))
if err := binary.Write(c, binary.BigEndian, challenge); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
/*
sendUsername := make([]byte, definedAuthLen)
for i := 0; i < definedAuthLen; i++ {
if i < len(auth.Username) {
sendUsername[i] = byte(charCodeAt(string(auth.Username), i))
} else {
sendUsername[i] = 0
}
}
sendPassword := make([]byte, definedAuthLen)
for i := 0; i < definedAuthLen; i++ {
if i < len(auth.Password) {
sendPassword[i] = byte(charCodeAt(string(auth.Password), i))
} else {
sendPassword[i] = 0
}
}
if err := binary.Write(c, binary.BigEndian, sendUsername); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, sendPassword); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
*/
//var pp [10]byte
//binary.Read(c, binary.BigEndian, &pp)
//fmt.Printf("ddd %v\n", pp)
return nil
}
package vnc2video
import (
"bytes"
"encoding/binary"
"fmt"
)
type ClientAuthATEN struct {
Username []byte
Password []byte
}
func (*ClientAuthATEN) Type() SecurityType {
return SecTypeATEN
}
func (*ClientAuthATEN) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func charCodeAt(s string, n int) rune {
for i, r := range s {
if i == n {
return r
}
}
return 0
}
func (auth *ClientAuthATEN) Auth(c Conn) error {
var definedAuthLen = 24
if len(auth.Username) > definedAuthLen || len(auth.Password) > definedAuthLen {
return fmt.Errorf("username/password is too long, allowed 0-23")
}
nt, err := readTightTunnels(c)
if err != nil {
return err
}
/*
fmt.Printf("tunnels %d\n", nt)
for i := uint32(0); i < nt; i++ {
code, vendor, signature, err := readTightCaps(c)
if err != nil {
return err
}
fmt.Printf("code %d vendor %s signature %s\n", code, vendor, signature)
}
*/
if ((nt&0xffff0ff0)>>0 == 0xaff90fb0) || (nt <= 0 || nt > 0x1000000) {
c.SetProtoVersion("aten1")
var skip [20]byte
binary.Read(c, binary.BigEndian, &skip)
//fmt.Printf("skip %v\n", skip)
}
username := make([]byte, definedAuthLen)
password := make([]byte, definedAuthLen)
copy(username, auth.Username)
copy(password, auth.Password)
challenge := bytes.Join([][]byte{username, password}, []byte(""))
if err := binary.Write(c, binary.BigEndian, challenge); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
/*
sendUsername := make([]byte, definedAuthLen)
for i := 0; i < definedAuthLen; i++ {
if i < len(auth.Username) {
sendUsername[i] = byte(charCodeAt(string(auth.Username), i))
} else {
sendUsername[i] = 0
}
}
sendPassword := make([]byte, definedAuthLen)
for i := 0; i < definedAuthLen; i++ {
if i < len(auth.Password) {
sendPassword[i] = byte(charCodeAt(string(auth.Password), i))
} else {
sendPassword[i] = 0
}
}
if err := binary.Write(c, binary.BigEndian, sendUsername); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, sendPassword); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
*/
//var pp [10]byte
//binary.Read(c, binary.BigEndian, &pp)
//fmt.Printf("ddd %v\n", pp)
return nil
}

View File

@ -1,30 +1,30 @@
package vnc2webm
type ClientAuthNone struct{}
func (*ClientAuthNone) Type() SecurityType {
return SecTypeNone
}
func (*ClientAuthNone) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (*ClientAuthNone) Auth(conn Conn) error {
return nil
}
// ServerAuthNone is the "none" authentication. See 7.2.1.
type ServerAuthNone struct{}
func (*ServerAuthNone) Type() SecurityType {
return SecTypeNone
}
func (*ServerAuthNone) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (*ServerAuthNone) Auth(c Conn) error {
return nil
}
package vnc2video
type ClientAuthNone struct{}
func (*ClientAuthNone) Type() SecurityType {
return SecTypeNone
}
func (*ClientAuthNone) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (*ClientAuthNone) Auth(conn Conn) error {
return nil
}
// ServerAuthNone is the "none" authentication. See 7.2.1.
type ServerAuthNone struct{}
func (*ServerAuthNone) Type() SecurityType {
return SecTypeNone
}
func (*ServerAuthNone) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (*ServerAuthNone) Auth(c Conn) error {
return nil
}

View File

@ -1,27 +1,27 @@
package vnc2webm
import "encoding/binary"
func readTightTunnels(c Conn) (uint32, error) {
var n uint32
if err := binary.Read(c, binary.BigEndian, &n); err != nil {
return 0, err
}
return n, nil
}
func readTightCaps(c Conn) (int32, []byte, []byte, error) {
var code int32
var vendor [4]byte
var signature [8]byte
if err := binary.Read(c, binary.BigEndian, &code); err != nil {
return 0, nil, nil, err
}
if err := binary.Read(c, binary.BigEndian, &vendor); err != nil {
return 0, nil, nil, err
}
if err := binary.Read(c, binary.BigEndian, &signature); err != nil {
return 0, nil, nil, err
}
return code, vendor[:], signature[:], nil
}
package vnc2video
import "encoding/binary"
func readTightTunnels(c Conn) (uint32, error) {
var n uint32
if err := binary.Read(c, binary.BigEndian, &n); err != nil {
return 0, err
}
return n, nil
}
func readTightCaps(c Conn) (int32, []byte, []byte, error) {
var code int32
var vendor [4]byte
var signature [8]byte
if err := binary.Read(c, binary.BigEndian, &code); err != nil {
return 0, nil, nil, err
}
if err := binary.Read(c, binary.BigEndian, &vendor); err != nil {
return 0, nil, nil, err
}
if err := binary.Read(c, binary.BigEndian, &signature); err != nil {
return 0, nil, nil, err
}
return code, vendor[:], signature[:], nil
}

View File

@ -1,109 +1,109 @@
package vnc2webm
import (
"bytes"
"encoding/binary"
"fmt"
)
func (*ClientAuthVeNCrypt02Plain) Type() SecurityType {
return SecTypeVeNCrypt
}
func (*ClientAuthVeNCrypt02Plain) SubType() SecuritySubType {
return SecSubTypeVeNCrypt02Plain
}
// ClientAuthVeNCryptPlain see https://www.berrange.com/~dan/vencrypt.txt
type ClientAuthVeNCrypt02Plain struct {
Username []byte
Password []byte
}
func (auth *ClientAuthVeNCrypt02Plain) Auth(c Conn) error {
if err := binary.Write(c, binary.BigEndian, []uint8{0, 2}); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
var (
major, minor uint8
)
if err := binary.Read(c, binary.BigEndian, &major); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &minor); err != nil {
return err
}
res := uint8(1)
if major == 0 && minor == 2 {
res = uint8(0)
}
if err := binary.Write(c, binary.BigEndian, res); err != nil {
return err
}
c.Flush()
if err := binary.Write(c, binary.BigEndian, uint8(1)); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, auth.SubType()); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
var secType SecuritySubType
if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
return err
}
if secType != auth.SubType() {
binary.Write(c, binary.BigEndian, uint8(1))
c.Flush()
return fmt.Errorf("invalid sectype")
}
if len(auth.Password) == 0 || len(auth.Username) == 0 {
return fmt.Errorf("Security Handshake failed; no username and/or password provided for VeNCryptAuth.")
}
/*
if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Username))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Password))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, auth.Username); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, auth.Password); err != nil {
return err
}
*/
var (
uLength, pLength uint32
)
if err := binary.Read(c, binary.BigEndian, &uLength); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &pLength); err != nil {
return err
}
username := make([]byte, uLength)
password := make([]byte, pLength)
if err := binary.Read(c, binary.BigEndian, &username); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &password); err != nil {
return err
}
if !bytes.Equal(auth.Username, username) || !bytes.Equal(auth.Password, password) {
return fmt.Errorf("invalid username/password")
}
return nil
}
package vnc2video
import (
"bytes"
"encoding/binary"
"fmt"
)
func (*ClientAuthVeNCrypt02Plain) Type() SecurityType {
return SecTypeVeNCrypt
}
func (*ClientAuthVeNCrypt02Plain) SubType() SecuritySubType {
return SecSubTypeVeNCrypt02Plain
}
// ClientAuthVeNCryptPlain see https://www.berrange.com/~dan/vencrypt.txt
type ClientAuthVeNCrypt02Plain struct {
Username []byte
Password []byte
}
func (auth *ClientAuthVeNCrypt02Plain) Auth(c Conn) error {
if err := binary.Write(c, binary.BigEndian, []uint8{0, 2}); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
var (
major, minor uint8
)
if err := binary.Read(c, binary.BigEndian, &major); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &minor); err != nil {
return err
}
res := uint8(1)
if major == 0 && minor == 2 {
res = uint8(0)
}
if err := binary.Write(c, binary.BigEndian, res); err != nil {
return err
}
c.Flush()
if err := binary.Write(c, binary.BigEndian, uint8(1)); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, auth.SubType()); err != nil {
return err
}
if err := c.Flush(); err != nil {
return err
}
var secType SecuritySubType
if err := binary.Read(c, binary.BigEndian, &secType); err != nil {
return err
}
if secType != auth.SubType() {
binary.Write(c, binary.BigEndian, uint8(1))
c.Flush()
return fmt.Errorf("invalid sectype")
}
if len(auth.Password) == 0 || len(auth.Username) == 0 {
return fmt.Errorf("Security Handshake failed; no username and/or password provided for VeNCryptAuth.")
}
/*
if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Username))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, uint32(len(auth.Password))); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, auth.Username); err != nil {
return err
}
if err := binary.Write(c, binary.BigEndian, auth.Password); err != nil {
return err
}
*/
var (
uLength, pLength uint32
)
if err := binary.Read(c, binary.BigEndian, &uLength); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &pLength); err != nil {
return err
}
username := make([]byte, uLength)
password := make([]byte, pLength)
if err := binary.Read(c, binary.BigEndian, &username); err != nil {
return err
}
if err := binary.Read(c, binary.BigEndian, &password); err != nil {
return err
}
if !bytes.Equal(auth.Username, username) || !bytes.Equal(auth.Password, password) {
return fmt.Errorf("invalid username/password")
}
return nil
}

View File

@ -1,120 +1,120 @@
package vnc2webm
import (
"bytes"
"crypto/des"
"encoding/binary"
"fmt"
)
// ServerAuthVNC is the standard password authentication. See 7.2.2.
type ServerAuthVNC struct {
Challenge []byte
Password []byte
Crypted []byte
}
func (*ServerAuthVNC) Type() SecurityType {
return SecTypeVNC
}
func (*ServerAuthVNC) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (auth *ServerAuthVNC) WriteChallenge(c Conn) error {
if err := binary.Write(c, binary.BigEndian, auth.Challenge); err != nil {
return err
}
return c.Flush()
}
func (auth *ServerAuthVNC) ReadChallenge(c Conn) error {
var crypted [16]byte
if err := binary.Read(c, binary.BigEndian, &crypted); err != nil {
return err
}
auth.Crypted = crypted[:]
return nil
}
func (auth *ServerAuthVNC) Auth(c Conn) error {
if err := auth.WriteChallenge(c); err != nil {
return err
}
if err := auth.ReadChallenge(c); err != nil {
return err
}
encrypted, err := AuthVNCEncode(auth.Password, auth.Challenge)
if err != nil {
return err
}
if !bytes.Equal(encrypted, auth.Crypted) {
return fmt.Errorf("password invalid")
}
return nil
}
// ClientAuthVNC is the standard password authentication. See 7.2.2.
type ClientAuthVNC struct {
Challenge []byte
Password []byte
}
func (*ClientAuthVNC) Type() SecurityType {
return SecTypeVNC
}
func (*ClientAuthVNC) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (auth *ClientAuthVNC) Auth(c Conn) error {
if len(auth.Password) == 0 {
return fmt.Errorf("Security Handshake failed; no password provided for VNCAuth.")
}
var challenge [16]byte
if err := binary.Read(c, binary.BigEndian, &challenge); err != nil {
return err
}
encrypted, err := AuthVNCEncode(auth.Password, challenge[:])
if err != nil {
return err
}
// Send the encrypted challenge back to server
if err := binary.Write(c, binary.BigEndian, encrypted); err != nil {
return err
}
return c.Flush()
}
func AuthVNCEncode(password []byte, challenge []byte) ([]byte, error) {
if len(challenge) != 16 {
return nil, fmt.Errorf("challenge size not 16 byte long")
}
// Copy password string to 8 byte 0-padded slice
key := make([]byte, 8)
copy(key, password)
// Each byte of the password needs to be reversed. This is a
// non RFC-documented behaviour of VNC clients and servers
for i := range key {
key[i] = (key[i]&0x55)<<1 | (key[i]&0xAA)>>1 // Swap adjacent bits
key[i] = (key[i]&0x33)<<2 | (key[i]&0xCC)>>2 // Swap adjacent pairs
key[i] = (key[i]&0x0F)<<4 | (key[i]&0xF0)>>4 // Swap the 2 halves
}
// Encrypt challenge with key.
cipher, err := des.NewCipher(key)
if err != nil {
return nil, err
}
for i := 0; i < len(challenge); i += cipher.BlockSize() {
cipher.Encrypt(challenge[i:i+cipher.BlockSize()], challenge[i:i+cipher.BlockSize()])
}
return challenge, nil
}
package vnc2video
import (
"bytes"
"crypto/des"
"encoding/binary"
"fmt"
)
// ServerAuthVNC is the standard password authentication. See 7.2.2.
type ServerAuthVNC struct {
Challenge []byte
Password []byte
Crypted []byte
}
func (*ServerAuthVNC) Type() SecurityType {
return SecTypeVNC
}
func (*ServerAuthVNC) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (auth *ServerAuthVNC) WriteChallenge(c Conn) error {
if err := binary.Write(c, binary.BigEndian, auth.Challenge); err != nil {
return err
}
return c.Flush()
}
func (auth *ServerAuthVNC) ReadChallenge(c Conn) error {
var crypted [16]byte
if err := binary.Read(c, binary.BigEndian, &crypted); err != nil {
return err
}
auth.Crypted = crypted[:]
return nil
}
func (auth *ServerAuthVNC) Auth(c Conn) error {
if err := auth.WriteChallenge(c); err != nil {
return err
}
if err := auth.ReadChallenge(c); err != nil {
return err
}
encrypted, err := AuthVNCEncode(auth.Password, auth.Challenge)
if err != nil {
return err
}
if !bytes.Equal(encrypted, auth.Crypted) {
return fmt.Errorf("password invalid")
}
return nil
}
// ClientAuthVNC is the standard password authentication. See 7.2.2.
type ClientAuthVNC struct {
Challenge []byte
Password []byte
}
func (*ClientAuthVNC) Type() SecurityType {
return SecTypeVNC
}
func (*ClientAuthVNC) SubType() SecuritySubType {
return SecSubTypeUnknown
}
func (auth *ClientAuthVNC) Auth(c Conn) error {
if len(auth.Password) == 0 {
return fmt.Errorf("Security Handshake failed; no password provided for VNCAuth.")
}
var challenge [16]byte
if err := binary.Read(c, binary.BigEndian, &challenge); err != nil {
return err
}
encrypted, err := AuthVNCEncode(auth.Password, challenge[:])
if err != nil {
return err
}
// Send the encrypted challenge back to server
if err := binary.Write(c, binary.BigEndian, encrypted); err != nil {
return err
}
return c.Flush()
}
func AuthVNCEncode(password []byte, challenge []byte) ([]byte, error) {
if len(challenge) != 16 {
return nil, fmt.Errorf("challenge size not 16 byte long")
}
// Copy password string to 8 byte 0-padded slice
key := make([]byte, 8)
copy(key, password)
// Each byte of the password needs to be reversed. This is a
// non RFC-documented behaviour of VNC clients and servers
for i := range key {
key[i] = (key[i]&0x55)<<1 | (key[i]&0xAA)>>1 // Swap adjacent bits
key[i] = (key[i]&0x33)<<2 | (key[i]&0xCC)>>2 // Swap adjacent pairs
key[i] = (key[i]&0x0F)<<4 | (key[i]&0xF0)>>4 // Swap the 2 halves
}
// Encrypt challenge with key.
cipher, err := des.NewCipher(key)
if err != nil {
return nil, err
}
for i := 0; i < len(challenge); i += cipher.BlockSize() {
cipher.Encrypt(challenge[i:i+cipher.BlockSize()], challenge[i:i+cipher.BlockSize()])
}
return challenge, nil
}

View File

@ -1,32 +1,32 @@
// Code generated by "stringer -type=SecuritySubType"; DO NOT EDIT.
package vnc2webm
import "fmt"
const (
_SecuritySubType_name_0 = "SecSubTypeUnknown"
_SecuritySubType_name_1 = "SecSubTypeVeNCrypt01PlainSecSubTypeVeNCrypt01TLSNoneSecSubTypeVeNCrypt01TLSVNCSecSubTypeVeNCrypt01TLSPlainSecSubTypeVeNCrypt01X509NoneSecSubTypeVeNCrypt01X509VNCSecSubTypeVeNCrypt01X509Plain"
_SecuritySubType_name_2 = "SecSubTypeVeNCrypt02PlainSecSubTypeVeNCrypt02TLSNoneSecSubTypeVeNCrypt02TLSVNCSecSubTypeVeNCrypt02TLSPlainSecSubTypeVeNCrypt02X509NoneSecSubTypeVeNCrypt02X509VNCSecSubTypeVeNCrypt02X509Plain"
)
var (
_SecuritySubType_index_0 = [...]uint8{0, 17}
_SecuritySubType_index_1 = [...]uint8{0, 25, 52, 78, 106, 134, 161, 190}
_SecuritySubType_index_2 = [...]uint8{0, 25, 52, 78, 106, 134, 161, 190}
)
func (i SecuritySubType) String() string {
switch {
case i == 0:
return _SecuritySubType_name_0
case 19 <= i && i <= 25:
i -= 19
return _SecuritySubType_name_1[_SecuritySubType_index_1[i]:_SecuritySubType_index_1[i+1]]
case 256 <= i && i <= 262:
i -= 256
return _SecuritySubType_name_2[_SecuritySubType_index_2[i]:_SecuritySubType_index_2[i+1]]
default:
return fmt.Sprintf("SecuritySubType(%d)", i)
}
}
// Code generated by "stringer -type=SecuritySubType"; DO NOT EDIT.
package vnc2video
import "fmt"
const (
_SecuritySubType_name_0 = "SecSubTypeUnknown"
_SecuritySubType_name_1 = "SecSubTypeVeNCrypt01PlainSecSubTypeVeNCrypt01TLSNoneSecSubTypeVeNCrypt01TLSVNCSecSubTypeVeNCrypt01TLSPlainSecSubTypeVeNCrypt01X509NoneSecSubTypeVeNCrypt01X509VNCSecSubTypeVeNCrypt01X509Plain"
_SecuritySubType_name_2 = "SecSubTypeVeNCrypt02PlainSecSubTypeVeNCrypt02TLSNoneSecSubTypeVeNCrypt02TLSVNCSecSubTypeVeNCrypt02TLSPlainSecSubTypeVeNCrypt02X509NoneSecSubTypeVeNCrypt02X509VNCSecSubTypeVeNCrypt02X509Plain"
)
var (
_SecuritySubType_index_0 = [...]uint8{0, 17}
_SecuritySubType_index_1 = [...]uint8{0, 25, 52, 78, 106, 134, 161, 190}
_SecuritySubType_index_2 = [...]uint8{0, 25, 52, 78, 106, 134, 161, 190}
)
func (i SecuritySubType) String() string {
switch {
case i == 0:
return _SecuritySubType_name_0
case 19 <= i && i <= 25:
i -= 19
return _SecuritySubType_name_1[_SecuritySubType_index_1[i]:_SecuritySubType_index_1[i+1]]
case 256 <= i && i <= 262:
i -= 256
return _SecuritySubType_name_2[_SecuritySubType_index_2[i]:_SecuritySubType_index_2[i+1]]
default:
return fmt.Sprintf("SecuritySubType(%d)", i)
}
}

View File

@ -1,30 +1,30 @@
// Code generated by "stringer -type=SecurityType"; DO NOT EDIT.
package vnc2webm
import "fmt"
const (
_SecurityType_name_0 = "SecTypeUnknownSecTypeNoneSecTypeVNC"
_SecurityType_name_1 = "SecTypeTight"
_SecurityType_name_2 = "SecTypeVeNCrypt"
)
var (
_SecurityType_index_0 = [...]uint8{0, 14, 25, 35}
_SecurityType_index_1 = [...]uint8{0, 12}
_SecurityType_index_2 = [...]uint8{0, 15}
)
func (i SecurityType) String() string {
switch {
case 0 <= i && i <= 2:
return _SecurityType_name_0[_SecurityType_index_0[i]:_SecurityType_index_0[i+1]]
case i == 16:
return _SecurityType_name_1
case i == 19:
return _SecurityType_name_2
default:
return fmt.Sprintf("SecurityType(%d)", i)
}
}
// Code generated by "stringer -type=SecurityType"; DO NOT EDIT.
package vnc2video
import "fmt"
const (
_SecurityType_name_0 = "SecTypeUnknownSecTypeNoneSecTypeVNC"
_SecurityType_name_1 = "SecTypeTight"
_SecurityType_name_2 = "SecTypeVeNCrypt"
)
var (
_SecurityType_index_0 = [...]uint8{0, 14, 25, 35}
_SecurityType_index_1 = [...]uint8{0, 12}
_SecurityType_index_2 = [...]uint8{0, 15}
)
func (i SecurityType) String() string {
switch {
case 0 <= i && i <= 2:
return _SecurityType_name_0[_SecurityType_index_0[i]:_SecurityType_index_0[i+1]]
case i == 16:
return _SecurityType_name_1
case i == 19:
return _SecurityType_name_2
default:
return fmt.Sprintf("SecurityType(%d)", i)
}
}

684
server.go
View File

@ -1,342 +1,342 @@
package vnc2webm
import (
"bufio"
"context"
"encoding/binary"
"fmt"
"net"
"sync"
)
var _ Conn = (*ServerConn)(nil)
// Config returns config for server conn
func (c *ServerConn) Config() interface{} {
return c.cfg
}
func (c *ServerConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
// Conn returns underlining server net.Conn
func (c *ServerConn) Conn() net.Conn {
return c.c
}
// Wait waits connection to close
func (c *ServerConn) Wait() {
<-c.quit
}
// SetEncodings ??? sets server connection encodings
func (c *ServerConn) SetEncodings(encs []EncodingType) error {
encodings := make(map[EncodingType]Encoding)
for _, enc := range c.cfg.Encodings {
encodings[enc.Type()] = enc
}
for _, encType := range encs {
if enc, ok := encodings[encType]; ok {
c.encodings = append(c.encodings, enc)
}
}
return nil
}
// SetProtoVersion ??? sets proto version
func (c *ServerConn) SetProtoVersion(pv string) {
c.protocol = pv
}
// Flush buffered data to server conn
func (c *ServerConn) Flush() error {
return c.bw.Flush()
}
// Close closing server conn
func (c *ServerConn) Close() error {
if c.quit != nil {
close(c.quit)
c.quit = nil
}
return c.c.Close()
}
// Read reads data from net.Conn
func (c *ServerConn) Read(buf []byte) (int, error) {
return c.br.Read(buf)
}
// Write writes data to net.Conn, must be Flashed
func (c *ServerConn) Write(buf []byte) (int, error) {
return c.bw.Write(buf)
}
// ColorMap returns server connection color map
func (c *ServerConn) ColorMap() ColorMap {
return c.colorMap
}
// SetColorMap sets connection color map
func (c *ServerConn) SetColorMap(cm ColorMap) {
c.colorMap = cm
}
// DesktopName returns connection desktop name
func (c *ServerConn) DesktopName() []byte {
return c.desktopName
}
// PixelFormat return connection pixel format
func (c *ServerConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
// SetDesktopName sets connection desktop name
func (c *ServerConn) SetDesktopName(name []byte) {
c.desktopName = name
}
// SetPixelFormat sets pixel format for server conn
func (c *ServerConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
// Encodings returns connection encodings
func (c *ServerConn) Encodings() []Encoding {
return c.encodings
}
// Width returns framebuffer width
func (c *ServerConn) Width() uint16 {
return c.fbWidth
}
// Height returns framebuffer height
func (c *ServerConn) Height() uint16 {
return c.fbHeight
}
// Protocol returns protocol
func (c *ServerConn) Protocol() string {
return c.protocol
}
// SecurityHandler returns security handler
func (c *ServerConn) SecurityHandler() SecurityHandler {
return c.securityHandler
}
// SetSecurityHandler sets security handler
func (c *ServerConn) SetSecurityHandler(sechandler SecurityHandler) error {
c.securityHandler = sechandler
return nil
}
// SetWidth sets framebuffer width
func (c *ServerConn) SetWidth(w uint16) {
// TODO send desktopsize pseudo encoding
c.fbWidth = w
}
// SetHeight sets framebuffer height
func (c *ServerConn) SetHeight(h uint16) {
// TODO send desktopsize pseudo encoding
c.fbHeight = h
}
// ServerConn underlining server conn
type ServerConn struct {
c net.Conn
cfg *ServerConfig
br *bufio.Reader
bw *bufio.Writer
protocol string
// If the pixel format uses a color map, then this is the color
// map that is used. This should not be modified directly, since
// the data comes from the server.
// Definition in §5 - Representation of Pixel Data.
colorMap ColorMap
// Name associated with the desktop, sent from the server.
desktopName []byte
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings() should be used.
encodings []Encoding
securityHandler SecurityHandler
// Height of the frame buffer in pixels, sent to the client.
fbHeight uint16
// Width of the frame buffer in pixels, sent to the client.
fbWidth uint16
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
quit chan struct{}
}
var (
// DefaultServerHandlers uses default handlers for hanshake
DefaultServerHandlers = []Handler{
&DefaultServerVersionHandler{},
&DefaultServerSecurityHandler{},
&DefaultServerClientInitHandler{},
&DefaultServerServerInitHandler{},
&DefaultServerMessageHandler{},
}
)
// ServerConfig config struct
type ServerConfig struct {
Handlers []Handler
SecurityHandlers []SecurityHandler
Encodings []Encoding
PixelFormat PixelFormat
ColorMap ColorMap
ClientMessageCh chan ClientMessage
ServerMessageCh chan ServerMessage
Messages []ClientMessage
DesktopName []byte
Height uint16
Width uint16
ErrorCh chan error
}
// NewServerConn returns new Server connection fron net.Conn
func NewServerConn(c net.Conn, cfg *ServerConfig) (*ServerConn, error) {
return &ServerConn{
c: c,
br: bufio.NewReader(c),
bw: bufio.NewWriter(c),
cfg: cfg,
desktopName: cfg.DesktopName,
encodings: cfg.Encodings,
pixelFormat: cfg.PixelFormat,
fbWidth: cfg.Width,
fbHeight: cfg.Height,
quit: make(chan struct{}),
}, nil
}
// Serve serves requests from net.Listener using ServerConfig
func Serve(ctx context.Context, ln net.Listener, cfg *ServerConfig) error {
for {
c, err := ln.Accept()
if err != nil {
continue
}
conn, err := NewServerConn(c, cfg)
if err != nil {
cfg.ErrorCh <- err
continue
}
if len(cfg.Handlers) == 0 {
cfg.Handlers = DefaultServerHandlers
}
handlerLoop:
for _, h := range cfg.Handlers {
if err := h.Handle(conn); err != nil {
if cfg.ErrorCh != nil {
cfg.ErrorCh <- err
}
conn.Close()
break handlerLoop
}
}
}
}
// DefaultServerMessageHandler default package handler
type DefaultServerMessageHandler struct{}
// Handle handles messages from clients
func (*DefaultServerMessageHandler) Handle(c Conn) error {
cfg := c.Config().(*ServerConfig)
var err error
var wg sync.WaitGroup
defer c.Close()
clientMessages := make(map[ClientMessageType]ClientMessage)
for _, m := range cfg.Messages {
clientMessages[m.Type()] = m
}
wg.Add(2)
quit := make(chan struct{})
// server
go func() {
defer wg.Done()
for {
select {
case <-quit:
return
case msg := <-cfg.ServerMessageCh:
if err = msg.Write(c); err != nil {
cfg.ErrorCh <- err
if quit != nil {
close(quit)
quit = nil
}
return
}
}
}
}()
// client
go func() {
defer wg.Done()
for {
select {
case <-quit:
return
default:
var messageType ClientMessageType
if err := binary.Read(c, binary.BigEndian, &messageType); err != nil {
cfg.ErrorCh <- err
if quit != nil {
close(quit)
quit = nil
}
return
}
msg, ok := clientMessages[messageType]
if !ok {
cfg.ErrorCh <- fmt.Errorf("unsupported message-type: %v", messageType)
close(quit)
return
}
parsedMsg, err := msg.Read(c)
if err != nil {
cfg.ErrorCh <- err
if quit != nil {
close(quit)
quit = nil
}
return
}
cfg.ClientMessageCh <- parsedMsg
}
}
}()
wg.Wait()
return nil
}
package vnc2video
import (
"bufio"
"context"
"encoding/binary"
"fmt"
"net"
"sync"
)
var _ Conn = (*ServerConn)(nil)
// Config returns config for server conn
func (c *ServerConn) Config() interface{} {
return c.cfg
}
func (c *ServerConn) GetEncInstance(typ EncodingType) Encoding {
for _, enc := range c.encodings {
if enc.Type() == typ {
return enc
}
}
return nil
}
// Conn returns underlining server net.Conn
func (c *ServerConn) Conn() net.Conn {
return c.c
}
// Wait waits connection to close
func (c *ServerConn) Wait() {
<-c.quit
}
// SetEncodings ??? sets server connection encodings
func (c *ServerConn) SetEncodings(encs []EncodingType) error {
encodings := make(map[EncodingType]Encoding)
for _, enc := range c.cfg.Encodings {
encodings[enc.Type()] = enc
}
for _, encType := range encs {
if enc, ok := encodings[encType]; ok {
c.encodings = append(c.encodings, enc)
}
}
return nil
}
// SetProtoVersion ??? sets proto version
func (c *ServerConn) SetProtoVersion(pv string) {
c.protocol = pv
}
// Flush buffered data to server conn
func (c *ServerConn) Flush() error {
return c.bw.Flush()
}
// Close closing server conn
func (c *ServerConn) Close() error {
if c.quit != nil {
close(c.quit)
c.quit = nil
}
return c.c.Close()
}
// Read reads data from net.Conn
func (c *ServerConn) Read(buf []byte) (int, error) {
return c.br.Read(buf)
}
// Write writes data to net.Conn, must be Flashed
func (c *ServerConn) Write(buf []byte) (int, error) {
return c.bw.Write(buf)
}
// ColorMap returns server connection color map
func (c *ServerConn) ColorMap() ColorMap {
return c.colorMap
}
// SetColorMap sets connection color map
func (c *ServerConn) SetColorMap(cm ColorMap) {
c.colorMap = cm
}
// DesktopName returns connection desktop name
func (c *ServerConn) DesktopName() []byte {
return c.desktopName
}
// PixelFormat return connection pixel format
func (c *ServerConn) PixelFormat() PixelFormat {
return c.pixelFormat
}
// SetDesktopName sets connection desktop name
func (c *ServerConn) SetDesktopName(name []byte) {
c.desktopName = name
}
// SetPixelFormat sets pixel format for server conn
func (c *ServerConn) SetPixelFormat(pf PixelFormat) error {
c.pixelFormat = pf
return nil
}
// Encodings returns connection encodings
func (c *ServerConn) Encodings() []Encoding {
return c.encodings
}
// Width returns framebuffer width
func (c *ServerConn) Width() uint16 {
return c.fbWidth
}
// Height returns framebuffer height
func (c *ServerConn) Height() uint16 {
return c.fbHeight
}
// Protocol returns protocol
func (c *ServerConn) Protocol() string {
return c.protocol
}
// SecurityHandler returns security handler
func (c *ServerConn) SecurityHandler() SecurityHandler {
return c.securityHandler
}
// SetSecurityHandler sets security handler
func (c *ServerConn) SetSecurityHandler(sechandler SecurityHandler) error {
c.securityHandler = sechandler
return nil
}
// SetWidth sets framebuffer width
func (c *ServerConn) SetWidth(w uint16) {
// TODO send desktopsize pseudo encoding
c.fbWidth = w
}
// SetHeight sets framebuffer height
func (c *ServerConn) SetHeight(h uint16) {
// TODO send desktopsize pseudo encoding
c.fbHeight = h
}
// ServerConn underlining server conn
type ServerConn struct {
c net.Conn
cfg *ServerConfig
br *bufio.Reader
bw *bufio.Writer
protocol string
// If the pixel format uses a color map, then this is the color
// map that is used. This should not be modified directly, since
// the data comes from the server.
// Definition in §5 - Representation of Pixel Data.
colorMap ColorMap
// Name associated with the desktop, sent from the server.
desktopName []byte
// Encodings supported by the client. This should not be modified
// directly. Instead, SetEncodings() should be used.
encodings []Encoding
securityHandler SecurityHandler
// Height of the frame buffer in pixels, sent to the client.
fbHeight uint16
// Width of the frame buffer in pixels, sent to the client.
fbWidth uint16
// The pixel format associated with the connection. This shouldn't
// be modified. If you wish to set a new pixel format, use the
// SetPixelFormat method.
pixelFormat PixelFormat
quit chan struct{}
}
var (
// DefaultServerHandlers uses default handlers for hanshake
DefaultServerHandlers = []Handler{
&DefaultServerVersionHandler{},
&DefaultServerSecurityHandler{},
&DefaultServerClientInitHandler{},
&DefaultServerServerInitHandler{},
&DefaultServerMessageHandler{},
}
)
// ServerConfig config struct
type ServerConfig struct {
Handlers []Handler
SecurityHandlers []SecurityHandler
Encodings []Encoding
PixelFormat PixelFormat
ColorMap ColorMap
ClientMessageCh chan ClientMessage
ServerMessageCh chan ServerMessage
Messages []ClientMessage
DesktopName []byte
Height uint16
Width uint16
ErrorCh chan error
}
// NewServerConn returns new Server connection fron net.Conn
func NewServerConn(c net.Conn, cfg *ServerConfig) (*ServerConn, error) {
return &ServerConn{
c: c,
br: bufio.NewReader(c),
bw: bufio.NewWriter(c),
cfg: cfg,
desktopName: cfg.DesktopName,
encodings: cfg.Encodings,
pixelFormat: cfg.PixelFormat,
fbWidth: cfg.Width,
fbHeight: cfg.Height,
quit: make(chan struct{}),
}, nil
}
// Serve serves requests from net.Listener using ServerConfig
func Serve(ctx context.Context, ln net.Listener, cfg *ServerConfig) error {
for {
c, err := ln.Accept()
if err != nil {
continue
}
conn, err := NewServerConn(c, cfg)
if err != nil {
cfg.ErrorCh <- err
continue
}
if len(cfg.Handlers) == 0 {
cfg.Handlers = DefaultServerHandlers
}
handlerLoop:
for _, h := range cfg.Handlers {
if err := h.Handle(conn); err != nil {
if cfg.ErrorCh != nil {
cfg.ErrorCh <- err
}
conn.Close()
break handlerLoop
}
}
}
}
// DefaultServerMessageHandler default package handler
type DefaultServerMessageHandler struct{}
// Handle handles messages from clients
func (*DefaultServerMessageHandler) Handle(c Conn) error {
cfg := c.Config().(*ServerConfig)
var err error
var wg sync.WaitGroup
defer c.Close()
clientMessages := make(map[ClientMessageType]ClientMessage)
for _, m := range cfg.Messages {
clientMessages[m.Type()] = m
}
wg.Add(2)
quit := make(chan struct{})
// server
go func() {
defer wg.Done()
for {
select {
case <-quit:
return
case msg := <-cfg.ServerMessageCh:
if err = msg.Write(c); err != nil {
cfg.ErrorCh <- err
if quit != nil {
close(quit)
quit = nil
}
return
}
}
}
}()
// client
go func() {
defer wg.Done()
for {
select {
case <-quit:
return
default:
var messageType ClientMessageType
if err := binary.Read(c, binary.BigEndian, &messageType); err != nil {
cfg.ErrorCh <- err
if quit != nil {
close(quit)
quit = nil
}
return
}
msg, ok := clientMessages[messageType]
if !ok {
cfg.ErrorCh <- fmt.Errorf("unsupported message-type: %v", messageType)
close(quit)
return
}
parsedMsg, err := msg.Read(c)
if err != nil {
cfg.ErrorCh <- err
if quit != nil {
close(quit)
quit = nil
}
return
}
cfg.ClientMessageCh <- parsedMsg
}
}
}()
wg.Wait()
return nil
}

View File

@ -1,27 +1,27 @@
// Code generated by "stringer -type=TightCompression"; DO NOT EDIT.
package vnc2webm
import "fmt"
const (
_TightCompression_name_0 = "TightCompressionBasic"
_TightCompression_name_1 = "TightCompressionFillTightCompressionJPEGTightCompressionPNG"
)
var (
_TightCompression_index_0 = [...]uint8{0, 21}
_TightCompression_index_1 = [...]uint8{0, 20, 40, 59}
)
func (i TightCompression) String() string {
switch {
case i == 0:
return _TightCompression_name_0
case 8 <= i && i <= 10:
i -= 8
return _TightCompression_name_1[_TightCompression_index_1[i]:_TightCompression_index_1[i+1]]
default:
return fmt.Sprintf("TightCompression(%d)", i)
}
}
// Code generated by "stringer -type=TightCompression"; DO NOT EDIT.
package vnc2video
import "fmt"
const (
_TightCompression_name_0 = "TightCompressionBasic"
_TightCompression_name_1 = "TightCompressionFillTightCompressionJPEGTightCompressionPNG"
)
var (
_TightCompression_index_0 = [...]uint8{0, 21}
_TightCompression_index_1 = [...]uint8{0, 20, 40, 59}
)
func (i TightCompression) String() string {
switch {
case i == 0:
return _TightCompression_name_0
case 8 <= i && i <= 10:
i -= 8
return _TightCompression_name_1[_TightCompression_index_1[i]:_TightCompression_index_1[i+1]]
default:
return fmt.Sprintf("TightCompression(%d)", i)
}
}

View File

@ -1,16 +1,16 @@
// Code generated by "stringer -type=TightFilter"; DO NOT EDIT.
package vnc2webm
import "fmt"
const _TightFilter_name = "TightFilterCopyTightFilterPaletteTightFilterGradient"
var _TightFilter_index = [...]uint8{0, 15, 33, 52}
func (i TightFilter) String() string {
if i >= TightFilter(len(_TightFilter_index)-1) {
return fmt.Sprintf("TightFilter(%d)", i)
}
return _TightFilter_name[_TightFilter_index[i]:_TightFilter_index[i+1]]
}
// Code generated by "stringer -type=TightFilter"; DO NOT EDIT.
package vnc2video
import "fmt"
const _TightFilter_name = "TightFilterCopyTightFilterPaletteTightFilterGradient"
var _TightFilter_index = [...]uint8{0, 15, 33, 52}
func (i TightFilter) String() string {
if i >= TightFilter(len(_TightFilter_index)-1) {
return fmt.Sprintf("TightFilter(%d)", i)
}
return _TightFilter_name[_TightFilter_index[i]:_TightFilter_index[i+1]]
}