mirror of
https://github.com/amitbet/vnc2video.git
synced 2025-04-28 10:33:24 +00:00
first working tight encoding reader
This commit is contained in:
parent
f6acfdfdad
commit
16f897ddfe
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
@ -0,0 +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"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
46
.vscode/tasks.json
vendored
Normal file
46
.vscode/tasks.json
vendored
Normal file
@ -0,0 +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
|
||||
}
|
||||
]
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=Button"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
// Button represents a mask of pointer presses/releases.
|
||||
type Button uint8
|
||||
|
39
client.go
39
client.go
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"sync"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -51,6 +52,15 @@ 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
|
||||
@ -183,7 +193,6 @@ type ClientConn struct {
|
||||
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.
|
||||
@ -238,11 +247,12 @@ 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()
|
||||
//defer c.Close()
|
||||
|
||||
serverMessages := make(map[ServerMessageType]ServerMessage)
|
||||
for _, m := range cfg.Messages {
|
||||
@ -272,13 +282,17 @@ func (*DefaultClientMessageHandler) Handle(c Conn) error {
|
||||
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
|
||||
@ -287,8 +301,25 @@ func (*DefaultClientMessageHandler) Handle(c Conn) error {
|
||||
}
|
||||
}
|
||||
}()
|
||||
//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))
|
||||
|
||||
wg.Wait()
|
||||
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
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=ClientMessageType"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
3
conn.go
3
conn.go
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"io"
|
||||
@ -28,4 +28,5 @@ type Conn interface {
|
||||
SetProtoVersion(string)
|
||||
SetSecurityHandler(SecurityHandler) error
|
||||
SecurityHandler() SecurityHandler
|
||||
GetEncInstance(EncodingType) Encoding
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
// DesktopSizePseudoEncoding represents a desktop size message from the server.
|
||||
type DesktopSizePseudoEncoding struct{}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
type RawEncoding struct {
|
||||
Colors []Color
|
||||
|
@ -1,8 +1,20 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"compress/zlib"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image"
|
||||
"image/color"
|
||||
"image/draw"
|
||||
"image/jpeg"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
//go:generate stringer -type=TightCompression
|
||||
@ -10,10 +22,10 @@ import (
|
||||
type TightCompression uint8
|
||||
|
||||
const (
|
||||
TightCompressionBasic TightCompression = 0
|
||||
TightCompressionFill TightCompression = 8
|
||||
TightCompressionJPEG TightCompression = 9
|
||||
TightCompressionPNG TightCompression = 10
|
||||
TightCompressionBasic = 0
|
||||
TightCompressionFill = 8
|
||||
TightCompressionJPEG = 9
|
||||
TightCompressionPNG = 10
|
||||
)
|
||||
|
||||
//go:generate stringer -type=TightFilter
|
||||
@ -21,12 +33,19 @@ const (
|
||||
type TightFilter uint8
|
||||
|
||||
const (
|
||||
TightFilterCopy TightFilter = 0
|
||||
TightFilterPalette TightFilter = 1
|
||||
TightFilterGradient TightFilter = 2
|
||||
TightFilterCopy = 0
|
||||
TightFilterPalette = 1
|
||||
TightFilterGradient = 2
|
||||
)
|
||||
|
||||
type TightEncoding struct{}
|
||||
type TightEncoding struct {
|
||||
Image image.Image
|
||||
decoders []io.Reader
|
||||
decoderBuffs []*bytes.Reader
|
||||
}
|
||||
|
||||
var instance *TightEncoding
|
||||
var TightMinToCompress int = 12
|
||||
|
||||
func (*TightEncoding) Supported(Conn) bool {
|
||||
return true
|
||||
@ -34,12 +53,539 @@ func (*TightEncoding) Supported(Conn) bool {
|
||||
|
||||
func (*TightEncoding) Type() EncodingType { return EncTight }
|
||||
|
||||
func (*TightEncoding) GetInstance() *TightEncoding {
|
||||
if instance == nil {
|
||||
instance = &TightEncoding{}
|
||||
}
|
||||
return instance
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) Write(c Conn, rect *Rectangle) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Read unmarshal color from conn
|
||||
func getTightColor(c io.Reader, pf *PixelFormat) (*color.RGBA64, error) {
|
||||
if pf.TrueColor == 0 {
|
||||
return nil, errors.New("support for non true color formats was not implemented")
|
||||
}
|
||||
order := pf.order()
|
||||
var pixel uint32
|
||||
isTightFormat := pf.TrueColor != 0 && pf.Depth == 24 && pf.BPP == 32 && pf.BlueMax <= 255 && pf.RedMax <= 255 && pf.GreenMax <= 255
|
||||
if isTightFormat {
|
||||
//tbytes := make([]byte, 3)
|
||||
tbytes, err := ReadBytes(3, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rgb := color.RGBA64{
|
||||
R: uint16(tbytes[0]), //byte(col >> pf.RedShift & int32(pf.RedMax)),
|
||||
G: uint16(tbytes[1]), //byte(col >> pf.GreenShift & int32(pf.GreenMax)),
|
||||
B: uint16(tbytes[2]), //byte(col >> pf.BlueShift & int32(pf.BlueMax)),
|
||||
A: uint16(1),
|
||||
}
|
||||
return &rgb, nil
|
||||
}
|
||||
|
||||
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.RGBA64{
|
||||
R: uint16((pixel >> pf.RedShift) & uint32(pf.RedMax)),
|
||||
G: uint16((pixel >> pf.GreenShift) & uint32(pf.GreenMax)),
|
||||
B: uint16((pixel >> pf.BlueShift) & uint32(pf.BlueMax)),
|
||||
}
|
||||
|
||||
// else {
|
||||
// *clr = clr.cm[pixel]
|
||||
// clr.cmIndex = pixel
|
||||
// }
|
||||
return &rgb, nil
|
||||
}
|
||||
|
||||
// func getTightColor(bytes []byte, pf *PixelFormat) color.RGBA {
|
||||
// col := (int32(bytes[0])&0xff)<<16 | (int32(bytes[1])&0xff)<<8 | int32(bytes[2])&0xff
|
||||
// rgb := color.RGBA{
|
||||
// R: byte(col >> pf.RedShift & int32(pf.RedMax)),
|
||||
// G: byte(col >> pf.GreenShift & int32(pf.GreenMax)),
|
||||
// B: byte(col >> pf.BlueShift & int32(pf.BlueMax)),
|
||||
// A: byte(1),
|
||||
// }
|
||||
// return rgb
|
||||
// }
|
||||
|
||||
func calcTightBytePerPixel(pf *PixelFormat) int {
|
||||
bytesPerPixel := int(pf.BPP / 8)
|
||||
|
||||
var bytesPerPixelTight int
|
||||
if 24 == pf.Depth && 32 == pf.BPP {
|
||||
bytesPerPixelTight = 3
|
||||
} else {
|
||||
bytesPerPixelTight = bytesPerPixel
|
||||
}
|
||||
return bytesPerPixelTight
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) resetDecoders(compControl uint8) {
|
||||
for i := 0; i < 4; i++ {
|
||||
if (compControl&1) != 0 && enc.decoders[i] != nil {
|
||||
enc.decoders[i] = nil //.(zlib.Resetter).Reset(nil,nil);
|
||||
}
|
||||
compControl >>= 1
|
||||
}
|
||||
}
|
||||
|
||||
var counter int = 0
|
||||
|
||||
func (enc *TightEncoding) Read(c Conn, rect *Rectangle) error {
|
||||
return nil
|
||||
|
||||
var out *os.File
|
||||
var err error
|
||||
////////////
|
||||
if counter > 40 {
|
||||
os.Exit(1)
|
||||
}
|
||||
////////////
|
||||
pixelFmt := c.PixelFormat()
|
||||
bytesPixel := calcTightBytePerPixel(&pixelFmt)
|
||||
if enc.Image == nil {
|
||||
enc.Image = image.NewRGBA(image.Rect(0, 0, int(c.Width()), int(c.Height())))
|
||||
}
|
||||
|
||||
//r.StartByteCollection()
|
||||
|
||||
//r.StartByteCollection()
|
||||
// defer func() {
|
||||
// t.bytes = r.EndByteCollection()
|
||||
// }()
|
||||
|
||||
compctl, err := ReadUint8(c)
|
||||
|
||||
/////////////////
|
||||
if out == nil {
|
||||
out, err = os.Create("./output" + strconv.Itoa(counter) + "-" + strconv.Itoa(int(compctl)) + ".jpg")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
defer func() { counter++ }()
|
||||
defer jpeg.Encode(out, enc.Image, nil)
|
||||
//////////////
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("error in handling tight encoding: %v", err)
|
||||
return err
|
||||
}
|
||||
//logger.Debugf("bytesPixel= %d, subencoding= %d", bytesPixel, compctl)
|
||||
enc.resetDecoders(compctl)
|
||||
|
||||
//move it to position (remove zlib flush commands)
|
||||
compType := compctl >> 4 & 0x0F
|
||||
|
||||
//logger.Debugf("afterSHL:%d", compType)
|
||||
switch compType {
|
||||
case TightCompressionFill:
|
||||
logger.Debugf("--TIGHT_FILL: reading fill size=%d,counter=%d", bytesPixel, counter)
|
||||
//read color
|
||||
pf := c.PixelFormat()
|
||||
rectColor, err := getTightColor(c, &pf)
|
||||
if err != nil {
|
||||
logger.Errorf("error in reading tight encoding: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
//logger.Debugf("bytesPixel= %d, compctl= %d, color= %v", bytesPixel, compctl, rectColor)
|
||||
|
||||
//imgRect := image.Rect(0, 0, int(c.Width()), int(c.Height()))
|
||||
// if enc.Image == nil {
|
||||
// enc.Image = image.NewRGBA(imgRect)
|
||||
// }
|
||||
|
||||
c1 := color.RGBAModel.Convert(rectColor).(color.RGBA)
|
||||
|
||||
dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA)
|
||||
var x, y int
|
||||
|
||||
for y = int(rect.Y); y < int(rect.Height+rect.Y); y++ {
|
||||
for x = int(rect.X); x < int(rect.Width+rect.X); x++ {
|
||||
offset := dst.PixOffset(x, y)
|
||||
dst.Pix[offset+0] = c1.R
|
||||
dst.Pix[offset+1] = c1.G
|
||||
dst.Pix[offset+2] = c1.B
|
||||
dst.Pix[offset+3] = c1.A
|
||||
|
||||
//dst.Set(int(x), int(y), c1)
|
||||
//dst.Pix[y*uint16(dst.Bounds().Max.Y)+x] = []uint8{rectColor.R, rectColor.G, rectColor.B}
|
||||
}
|
||||
}
|
||||
enc.Image = dst
|
||||
|
||||
//draw.Draw(dst, imgRect, &image.Uniform{rectColor}, image.ZP, draw.Src)
|
||||
|
||||
if bytesPixel != 3 {
|
||||
return fmt.Errorf("non tight bytesPerPixel format, should be 3 bytes")
|
||||
}
|
||||
return nil
|
||||
case TightCompressionJPEG:
|
||||
logger.Debugf("--TIGHT_JPEG,counter=%d", counter)
|
||||
if pixelFmt.BPP == 8 {
|
||||
return errors.New("Tight encoding: JPEG is not supported in 8 bpp mode")
|
||||
}
|
||||
|
||||
len, err := readTightLength(c)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//logger.Debugf("reading jpeg, size=%d\n", len)
|
||||
jpegBytes, err := ReadBytes(len, c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//TODO: check if we can read jpeg directly from stream (this is safer for now)
|
||||
buff := bytes.NewBuffer(jpegBytes)
|
||||
img, err := jpeg.Decode(buff)
|
||||
if err != nil {
|
||||
logger.Error("problem while decoding jpeg:", err)
|
||||
}
|
||||
enc.Image = img
|
||||
|
||||
return nil
|
||||
default:
|
||||
|
||||
if compType > TightCompressionJPEG {
|
||||
logger.Error("Compression control byte is incorrect!")
|
||||
}
|
||||
|
||||
enc.handleTightFilters(compctl, &pixelFmt, rect, c)
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) handleTightFilters(compCtl uint8, pixelFmt *PixelFormat, rect *Rectangle, r Conn) {
|
||||
var STREAM_ID_MASK uint8 = 0x30
|
||||
var FILTER_ID_MASK uint8 = 0x40
|
||||
|
||||
var filterid uint8
|
||||
var err error
|
||||
|
||||
decoderId := (compCtl & STREAM_ID_MASK) >> 4
|
||||
|
||||
for len(enc.decoders) < 4 {
|
||||
enc.decoders = append(enc.decoders, nil)
|
||||
enc.decoderBuffs = append(enc.decoderBuffs, nil)
|
||||
}
|
||||
|
||||
if (compCtl & FILTER_ID_MASK) > 0 {
|
||||
filterid, err = ReadUint8(r)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("error in handling tight encoding, reading filterid: %v", err)
|
||||
return
|
||||
}
|
||||
//logger.Debugf("handleTightFilters: read filter: %d", filterid)
|
||||
}
|
||||
|
||||
bytesPixel := calcTightBytePerPixel(pixelFmt)
|
||||
|
||||
//logger.Debugf("handleTightFilters: filter: %d", filterid)
|
||||
|
||||
lengthCurrentbpp := int(bytesPixel) * int(rect.Width) * int(rect.Height)
|
||||
|
||||
switch filterid {
|
||||
case TightFilterPalette: //PALETTE_FILTER
|
||||
|
||||
palette, err := enc.readTightPalette(r, bytesPixel)
|
||||
if err != nil {
|
||||
logger.Errorf("handleTightFilters: error in Reading Palette: %v", err)
|
||||
return
|
||||
}
|
||||
logger.Debugf("----PALETTE_FILTER,palette len=%d counter=%d, rect= %v", len(palette), counter, rect)
|
||||
|
||||
//logger.Debugf("got palette: %v", palette)
|
||||
var dataLength int
|
||||
if len(palette) == 2 {
|
||||
dataLength = int(rect.Height) * ((int(rect.Width) + 7) / 8)
|
||||
} else {
|
||||
dataLength = int(rect.Width * rect.Height)
|
||||
}
|
||||
tightBytes, err := enc.ReadTightData(dataLength, r, int(decoderId))
|
||||
//logger.Debugf("got tightBytes: %v", tightBytes)
|
||||
if err != nil {
|
||||
logger.Errorf("handleTightFilters: error in handling tight encoding, reading palette filter data: %v", err)
|
||||
return
|
||||
}
|
||||
//logger.Errorf("handleTightFilters: got tight data: %v", tightBytes)
|
||||
|
||||
myImg := enc.Image.(draw.Image)
|
||||
bytePos := 0
|
||||
bitPos := 0
|
||||
var palettePos int
|
||||
for i := 0; i < int(rect.Height); i++ {
|
||||
for j := 0; j < int(rect.Width); j++ {
|
||||
if len(palette) == 2 {
|
||||
currByte := tightBytes[bytePos]
|
||||
palettePos = int(currByte&byte(math.Pow(2.0, float64(bitPos)))) >> uint(bitPos)
|
||||
//logger.Debugf("palletPos=%d, bitpos=%d, bytepos=%d", palettePos, bitPos, bytePos)
|
||||
bytePos = bytePos + int((bitPos+1.0)/8.0)
|
||||
bitPos = (bitPos + 1) % 8
|
||||
//logger.Debugf("next: bitpos=%d, bytepos=%d", bitPos, bytePos)
|
||||
} else {
|
||||
palettePos = int(tightBytes[bytePos])
|
||||
bytePos++
|
||||
}
|
||||
myImg.Set(int(rect.X)+j, int(rect.Y)+i, palette[palettePos])
|
||||
//logger.Debugf("(%d,%d): pos: %d col:%d", int(rect.X)+j, int(rect.Y)+i, palettePos, palette[palettePos])
|
||||
}
|
||||
}
|
||||
//enc.Image = myImg
|
||||
case TightFilterGradient: //GRADIENT_FILTER
|
||||
logger.Debugf("----GRADIENT_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter)
|
||||
//logger.Debugf("usegrad: %d\n", filterid)
|
||||
data, err := enc.ReadTightData(lengthCurrentbpp, r, int(decoderId))
|
||||
if err != nil {
|
||||
logger.Errorf("handleTightFilters: error in handling tight encoding, Reading GRADIENT_FILTER: %v", err)
|
||||
return
|
||||
}
|
||||
enc.decodeGradData(rect, data)
|
||||
|
||||
case TightFilterCopy: //BASIC_FILTER
|
||||
//lengthCurrentbpp1 := int(pixelFmt.BPP/8) * int(rect.Width) * int(rect.Height)
|
||||
logger.Debugf("----BASIC_FILTER: bytesPixel=%d, counter=%d", bytesPixel, counter)
|
||||
|
||||
tightBytes, err := enc.ReadTightData(lengthCurrentbpp, r, int(decoderId))
|
||||
if err != nil {
|
||||
logger.Errorf("handleTightFilters: error in handling tight encoding, Reading BASIC_FILTER: %v", err)
|
||||
return
|
||||
}
|
||||
logger.Debugf("tightBytes len= %d", len(tightBytes))
|
||||
enc.drawTightBytes(tightBytes, rect)
|
||||
default:
|
||||
logger.Errorf("handleTightFilters: Bad tight filter id: %d", filterid)
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
func (enc *TightEncoding) decodeGradData(rect *Rectangle, buffer []byte) {
|
||||
|
||||
logger.Debugf("putting gradient size: %v on image: %v", rect, enc.Image.Bounds())
|
||||
|
||||
prevRow := make([]byte, rect.Width*3+3) //new byte[w * 3];
|
||||
thisRow := make([]byte, rect.Width*3+3) //new byte[w * 3];
|
||||
|
||||
bIdx := 0
|
||||
dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA)
|
||||
|
||||
for i := 0; i < int(rect.Height); i++ {
|
||||
for j := 3; j < int(rect.Width*3+3); j += 3 {
|
||||
d := int(0xff&prevRow[j]) + // "upper" pixel (from prev row)
|
||||
int(0xff&thisRow[j-3]) - // prev pixel
|
||||
int(0xff&prevRow[j-3]) // "diagonal" prev pixel
|
||||
if d < 0 {
|
||||
d = 0
|
||||
}
|
||||
if d > 255 {
|
||||
d = 255
|
||||
}
|
||||
red := int(buffer[bIdx]) + d
|
||||
thisRow[j] = byte(red & 255)
|
||||
|
||||
d = int(0xff&prevRow[j+1]) +
|
||||
int(0xff&thisRow[j+1-3]) -
|
||||
int(0xff&prevRow[j+1-3])
|
||||
if d < 0 {
|
||||
d = 0
|
||||
}
|
||||
if d > 255 {
|
||||
d = 255
|
||||
}
|
||||
green := int(buffer[bIdx+1]) + d
|
||||
thisRow[j+1] = byte(green & 255)
|
||||
|
||||
d = int(0xff&prevRow[j+2]) +
|
||||
int(0xff&thisRow[j+2-3]) -
|
||||
int(0xff&prevRow[j+2-3])
|
||||
if d < 0 {
|
||||
d = 0
|
||||
}
|
||||
if d > 255 {
|
||||
d = 255
|
||||
}
|
||||
blue := int(buffer[bIdx+2]) + d
|
||||
thisRow[j+2] = byte(blue & 255)
|
||||
|
||||
bIdx += 3
|
||||
}
|
||||
|
||||
for idx := 3; idx < (len(thisRow) - 3); idx += 3 {
|
||||
myColor := color.RGBA{R: (thisRow[idx]), G: (thisRow[idx+1]), B: (thisRow[idx+2]), A: 1}
|
||||
dst.SetRGBA(idx/3+int(rect.X)-1, int(rect.Y)+i, myColor)
|
||||
//logger.Debugf("putting pixel: idx=%d, pos=(%d,%d), col=%v", idx, idx/3+int(rect.X), int(rect.Y)+i, myColor)
|
||||
|
||||
}
|
||||
|
||||
// exchange thisRow and prevRow:
|
||||
tempRow := thisRow
|
||||
thisRow = prevRow
|
||||
prevRow = tempRow
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) decodeGradientData(rect *Rectangle, buf []byte) {
|
||||
logger.Debugf("putting gradient on image: %v", enc.Image.Bounds())
|
||||
var dx, dy, c int
|
||||
prevRow := make([]byte, rect.Width*3) //new byte[w * 3];
|
||||
thisRow := make([]byte, rect.Width*3) //new byte[w * 3];
|
||||
pix := make([]byte, 3)
|
||||
est := make([]int, 3)
|
||||
|
||||
dst := (enc.Image).(*image.RGBA) // enc.Image.(*image.RGBA)
|
||||
//offset := int(rect.Y)*dst.Bounds().Max.X + int(rect.X)
|
||||
|
||||
for dy = 0; dy < int(rect.Height); dy++ {
|
||||
//offset := dst.PixOffset(x, y)
|
||||
/* First pixel in a row */
|
||||
for c = 0; c < 3; c++ {
|
||||
pix[c] = byte(prevRow[c] + buf[dy*int(rect.Width)*3+c])
|
||||
thisRow[c] = pix[c]
|
||||
}
|
||||
//logger.Debugf("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), rect.X, rect.Y, rect.Width, rect.Height, dy)
|
||||
myColor := color.RGBA{R: (pix[0]), G: (pix[1]), B: (pix[2]), A: 1}
|
||||
dst.SetRGBA(int(rect.X), dy+int(rect.Y), myColor)
|
||||
|
||||
/* Remaining pixels of a row */
|
||||
for dx = 1; dx < int(rect.Width); dx++ {
|
||||
for c = 0; c < 3; c++ {
|
||||
est[c] = int((prevRow[dx*3+c] & 0xFF) + (pix[c] & 0xFF) - (prevRow[(dx-1)*3+c] & 0xFF))
|
||||
if est[c] > 0xFF {
|
||||
est[c] = 0xFF
|
||||
} else if est[c] < 0x00 {
|
||||
est[c] = 0x00
|
||||
}
|
||||
pix[c] = (byte)(byte(est[c]) + buf[(dy*int(rect.Width)+dx)*3+c])
|
||||
thisRow[dx*3+c] = pix[c]
|
||||
}
|
||||
//logger.Debugf("putting pixel:%d,%d,%d at offset: %d, pixArrayLen= %v, rect=x:%d,y:%d,w:%d,h:%d, Yposition=%d", pix[0], pix[1], pix[2], offset, len(dst.Pix), x, y, w, h, dy)
|
||||
myColor := color.RGBA{R: pix[0], G: (pix[1]), B: (pix[2]), A: 1}
|
||||
dst.SetRGBA(dx+int(rect.X), dy+int(rect.Y), myColor)
|
||||
|
||||
}
|
||||
|
||||
copy(prevRow, thisRow)
|
||||
}
|
||||
enc.Image = dst
|
||||
}
|
||||
|
||||
func ReadBytes(count int, r io.Reader) ([]byte, error) {
|
||||
buff := make([]byte, count)
|
||||
|
||||
lengthRead, err := io.ReadFull(r, buff)
|
||||
|
||||
//lengthRead, err := r.Read(buff)
|
||||
if lengthRead != count {
|
||||
logger.Errorf("RfbReadHelper.ReadBytes unable to read bytes: lengthRead=%d, countExpected=%d", lengthRead, count)
|
||||
return nil, errors.New("RfbReadHelper.ReadBytes unable to read bytes")
|
||||
}
|
||||
|
||||
//err := binary.Read(r, binary.BigEndian, &buff)
|
||||
|
||||
if err != nil {
|
||||
logger.Errorf("RfbReadHelper.ReadBytes error while reading bytes: ", err)
|
||||
//if err := binary.Read(d.conn, binary.BigEndian, &buff); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buff, nil
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) readTightPalette(connReader Conn, bytesPixel int) (color.Palette, error) {
|
||||
|
||||
colorCount, err := ReadUint8(connReader)
|
||||
if err != nil {
|
||||
logger.Errorf("handleTightFilters: error in handling tight encoding, reading TightFilterPalette: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paletteSize := colorCount + 1 // add one more
|
||||
//logger.Debugf("----PALETTE_FILTER: paletteSize=%d bytesPixel=%d\n", paletteSize, bytesPixel)
|
||||
//complete palette
|
||||
paletteColorBytes, err := ReadBytes(int(paletteSize)*bytesPixel, connReader)
|
||||
if err != nil {
|
||||
logger.Errorf("handleTightFilters: error in handling tight encoding, reading TightFilterPalette.paletteSize: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
var paletteColors color.Palette = make([]color.Color, 0)
|
||||
for i := 0; i < int(paletteSize)*bytesPixel; i += 3 {
|
||||
col := color.RGBA{R: paletteColorBytes[i], G: paletteColorBytes[i+1], B: paletteColorBytes[i+2], A: 1}
|
||||
paletteColors = append(paletteColors, col)
|
||||
}
|
||||
return paletteColors, nil
|
||||
}
|
||||
|
||||
func ReadUint8(r Conn) (uint8, error) {
|
||||
var myUint uint8
|
||||
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return myUint, nil
|
||||
}
|
||||
|
||||
func (enc *TightEncoding) ReadTightData(dataSize int, c Conn, decoderId int) ([]byte, error) {
|
||||
if int(dataSize) < TightMinToCompress {
|
||||
return ReadBytes(int(dataSize), c)
|
||||
}
|
||||
zlibDataLen, err := readTightLength(c)
|
||||
//logger.Debugf("RfbReadHelper.ReadTightData: compactlen=%d", zlibDataLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
zippedBytes, err := ReadBytes(zlibDataLen, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var r io.Reader
|
||||
if enc.decoders[decoderId] == nil {
|
||||
b := bytes.NewReader(zippedBytes)
|
||||
r, err = zlib.NewReader(b)
|
||||
enc.decoders[decoderId] = r
|
||||
enc.decoderBuffs[decoderId] = b
|
||||
} else {
|
||||
b := enc.decoderBuffs[decoderId]
|
||||
b.Reset(zippedBytes) //set the underlaying buffer to new content (not resetting the decoder zlib stream)
|
||||
r = enc.decoders[decoderId]
|
||||
}
|
||||
|
||||
retBytes := make([]byte, dataSize)
|
||||
count, err := io.ReadFull(r, retBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if count != dataSize {
|
||||
return nil, errors.New("ReadTightData: reading inflating zip didn't produce expected number of bytes")
|
||||
}
|
||||
return retBytes, nil
|
||||
}
|
||||
|
||||
type TightCC struct {
|
||||
@ -129,3 +675,80 @@ func readTightLength(c Conn) (int, error) {
|
||||
|
||||
return length, nil
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw byte array bitmap data (for Tight)
|
||||
*/
|
||||
func (enc *TightEncoding) drawTightBytes(bytes []byte, rect *Rectangle) {
|
||||
bytesPos := 0
|
||||
myImg := (enc.Image).(draw.Image)
|
||||
logger.Debugf("drawTightBytes: len(bytes)= %d, %v", len(bytes), rect)
|
||||
|
||||
for ly := rect.Y; ly < rect.Y+rect.Height; ly++ {
|
||||
for lx := rect.X; lx < rect.X+rect.Width; lx++ {
|
||||
color := color.RGBA{R: bytes[bytesPos], G: bytes[bytesPos+1], B: bytes[bytesPos+2], A: 1}
|
||||
//logger.Debugf("drawTightBytes: setting pixel= (%d,%d): %v", int(lx), int(ly), color)
|
||||
myImg.Set(int(lx), int(ly), color)
|
||||
|
||||
bytesPos += 3
|
||||
}
|
||||
}
|
||||
//enc.Image = myImg
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Draw paletted byte array bitmap data
|
||||
// *
|
||||
// * @param buffer bitmap data
|
||||
// * @param rect bitmap location and dimensions
|
||||
// * @param palette colour palette
|
||||
// * @param paletteSize number of colors in palette
|
||||
// */
|
||||
// func (enc *TightPngEncoding) drawBytesWithPalette( buffer []byte, rect *Rectangle, palette []int, int paletteSize) {
|
||||
// //create palette:
|
||||
// var imgPalette []color.Color = make([]int, len(palette))
|
||||
// for i:=0;len(palette);i++{
|
||||
// col := color.RGBA{
|
||||
// R:,G:,B:,A:0
|
||||
// }
|
||||
// imgPalette[i]=col
|
||||
// }
|
||||
|
||||
// //lock.lock();
|
||||
// img:=image.Paletted{
|
||||
|
||||
// }
|
||||
// // 2 colors
|
||||
// thisWidth := enc.Image.Bounds().Max.Y
|
||||
// if paletteSize == 2 {
|
||||
// var dx, dy, n int;
|
||||
// i := rect.y * thisWidth + rect.x
|
||||
// rowBytes := (rect.width + 7) / 8
|
||||
// var b byte;
|
||||
|
||||
// for dy = 0; dy < rect.height; dy++ {
|
||||
// for dx = 0; dx < rect.width / 8; dx++ {
|
||||
// b = buffer[dy * rowBytes + dx];
|
||||
// for n = 7; n >= 0; n-- {
|
||||
// color := palette[b >> n & 1]
|
||||
// enc.Image.(draw.Image).Set(0, 0, color.RGBA{R: tpx.R, G: tpx.G, B: tpx.B, A: 1})
|
||||
// //pixels[i++] = palette[b >> n & 1];
|
||||
// }
|
||||
// }
|
||||
// for n = 7; n >= 8 - rect.width % 8; n-- {
|
||||
// pixels[i++] = palette[buffer[dy * rowBytes + dx] >> n & 1];
|
||||
// }
|
||||
// i += this.width - rect.width;
|
||||
// }
|
||||
// } else {
|
||||
// // 3..255 colors (assuming bytesPixel == 4).
|
||||
// int i = 0;
|
||||
// for (int ly = rect.y; ly < rect.y + rect.height; ++ly) {
|
||||
// for (int lx = rect.x; lx < rect.x + rect.width; ++lx) {
|
||||
// int pixelsOffset = ly * this.width + lx;
|
||||
// pixels[pixelsOffset] = palette[buffer[i++] & 0xFF];
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// //lock.unlock();
|
||||
// }
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"image/draw"
|
||||
"image/png"
|
||||
"io"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
func (*TightPngEncoding) Supported(Conn) bool {
|
||||
@ -61,6 +62,7 @@ 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
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=EncodingType"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
@ -2,50 +2,72 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"image"
|
||||
"log"
|
||||
"net"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
vnc "github.com/vtolstov/go-vnc"
|
||||
vnc "vnc2webm"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
// Establish TCP connection to VNC server.
|
||||
nc, err := net.DialTimeout("tcp", os.Args[1], 5*time.Second)
|
||||
if err != nil {
|
||||
log.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])}},
|
||||
PixelFormat: vnc.PixelFormat32bit,
|
||||
ClientMessageCh: cchClient,
|
||||
ServerMessageCh: cchServer,
|
||||
ServerMessages: vnc.DefaultServerMessages,
|
||||
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
|
||||
ErrorCh: errorCh,
|
||||
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 {
|
||||
log.Fatalf("Error negotiating connection to VNC host. %v", err)
|
||||
}
|
||||
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:
|
||||
log.Printf("Received message type:%v msg:%v\n", msg.Type(), msg)
|
||||
log.Printf("Received client message type:%v msg:%v\n", msg.Type(), msg)
|
||||
case msg := <-cchServer:
|
||||
log.Printf("Received message type:%v msg:%v\n", msg.Type(), msg)
|
||||
log.Printf("Received server message type:%v msg:%v\n", msg.Type(), msg)
|
||||
myRenderer, ok := msg.(vnc.Renderer)
|
||||
|
||||
if ok {
|
||||
err = myRenderer.Render(screenImage)
|
||||
if err != nil {
|
||||
log.Printf("Received server message type:%v msg:%v\n", msg.Type(), msg)
|
||||
}
|
||||
}
|
||||
reqMsg := vnc.FramebufferUpdateRequest{Inc: 1, X: 0, Y: 0, Width: cc.Width(), Height: cc.Height()}
|
||||
reqMsg.Write(cc)
|
||||
}
|
||||
}
|
||||
cc.Wait()
|
||||
|
@ -14,8 +14,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
vnc "github.com/vtolstov/go-vnc"
|
||||
vnc "vnc2webm"
|
||||
)
|
||||
|
||||
type Auth struct {
|
||||
@ -53,9 +52,9 @@ func newConn(hostport string, password []byte) (vnc.Conn, chan vnc.ClientMessage
|
||||
PixelFormat: vnc.PixelFormat32bit,
|
||||
ClientMessageCh: cchClient,
|
||||
ServerMessageCh: cchServer,
|
||||
ServerMessages: vnc.DefaultServerMessages,
|
||||
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
|
||||
ErrorCh: errorCh,
|
||||
//ServerMessages: vnc.DefaultServerMessages,
|
||||
Encodings: []vnc.Encoding{&vnc.RawEncoding{}},
|
||||
ErrorCh: errorCh,
|
||||
}
|
||||
csrv := make(chan vnc.Conn)
|
||||
inp := make(chan vnc.ClientMessage)
|
||||
@ -78,7 +77,7 @@ func handleIO(cli vnc.Conn, inp chan vnc.ClientMessage, out chan vnc.ServerMessa
|
||||
ccfg := cli.Config().(*vnc.ClientConfig)
|
||||
defer cli.Close()
|
||||
var conns []vnc.Conn
|
||||
var prepared bool
|
||||
//var prepared bool
|
||||
|
||||
for {
|
||||
select {
|
||||
@ -247,8 +246,8 @@ func main() {
|
||||
PixelFormat: vnc.PixelFormat32bit,
|
||||
ClientMessageCh: schClient,
|
||||
ServerMessageCh: schServer,
|
||||
ClientMessages: vnc.DefaultClientMessages,
|
||||
DesktopName: []byte("vnc proxy"),
|
||||
//ClientMessages: vnc.DefaultClientMessages,
|
||||
DesktopName: []byte("vnc proxy"),
|
||||
}
|
||||
scfg.Handlers = append(scfg.Handlers, vnc.DefaultServerHandlers...)
|
||||
scfg.Handlers = append(scfg.Handlers[:len(scfg.Handlers)-1], &HijackHandler{})
|
||||
|
@ -8,8 +8,7 @@ import (
|
||||
"math"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
vnc "github.com/vtolstov/go-vnc"
|
||||
vnc "vnc2webm"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@ -24,21 +23,22 @@ func main() {
|
||||
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,
|
||||
ClientMessages: vnc.DefaultClientMessages,
|
||||
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.
|
||||
|
@ -1,8 +1,9 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
// Handler represents handler of handshake
|
||||
@ -156,6 +157,7 @@ func (*DefaultClientSecurityHandler) Handle(c Conn) error {
|
||||
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 {
|
||||
@ -256,6 +258,7 @@ type DefaultClientServerInitHandler struct{}
|
||||
|
||||
// Handle provide default server init handler
|
||||
func (*DefaultClientServerInitHandler) Handle(c Conn) error {
|
||||
logger.Debug("starting DefaultClientServerInitHandler")
|
||||
var err error
|
||||
srvInit := ServerInit{}
|
||||
|
||||
@ -276,6 +279,7 @@ func (*DefaultClientServerInitHandler) Handle(c Conn) error {
|
||||
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)
|
||||
@ -366,6 +370,7 @@ 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 {
|
||||
@ -376,6 +381,7 @@ func (*DefaultClientClientInitHandler) Handle(c Conn) error {
|
||||
if err := binary.Write(c, binary.BigEndian, shared); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Debugf("DefaultClientClientInitHandler sending: shared=%d", shared)
|
||||
return c.Flush()
|
||||
}
|
||||
|
||||
|
4
image.go
4
image.go
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
@ -172,7 +172,7 @@ func (rect *Rectangle) Read(c Conn) error {
|
||||
case EncCopyRect:
|
||||
rect.Enc = &CopyRectEncoding{}
|
||||
case EncTight:
|
||||
rect.Enc = &TightEncoding{}
|
||||
rect.Enc = c.GetEncInstance(rect.EncType)
|
||||
case EncTightPng:
|
||||
rect.Enc = &TightPngEncoding{}
|
||||
case EncRaw:
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=Key"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
156
logger/logger.go
Normal file
156
logger/logger.go
Normal file
@ -0,0 +1,156 @@
|
||||
package logger
|
||||
|
||||
import "fmt"
|
||||
|
||||
var simpleLogger = SimpleLogger{LogLevelDebug}
|
||||
|
||||
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...)
|
||||
}
|
16
messages.go
16
messages.go
@ -1,8 +1,10 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"image/draw"
|
||||
"vnc2webm/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -81,6 +83,10 @@ type ServerMessage interface {
|
||||
Supported(Conn) bool
|
||||
}
|
||||
|
||||
type Renderer interface {
|
||||
Render(draw.Image) error
|
||||
}
|
||||
|
||||
// FramebufferUpdate holds a FramebufferUpdate wire format message.
|
||||
type FramebufferUpdate struct {
|
||||
_ [1]byte // pad
|
||||
@ -93,6 +99,11 @@ func (msg *FramebufferUpdate) String() string {
|
||||
return fmt.Sprintf("rects %d rectangle[]: { %v }", msg.NumRect, msg.Rects)
|
||||
}
|
||||
|
||||
func (msg *FramebufferUpdate) Render(draw.Image) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (msg *FramebufferUpdate) Supported(c Conn) bool {
|
||||
return true
|
||||
}
|
||||
@ -115,9 +126,12 @@ func (*FramebufferUpdate) Read(c Conn) (ServerMessage, error) {
|
||||
}
|
||||
for i := uint16(0); i < msg.NumRect; i++ {
|
||||
rect := NewRectangle()
|
||||
//logger.Debugf("----------RECT %d----------:", i)
|
||||
|
||||
if err := rect.Read(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logger.Debugf("----End RECT #%d Info (%dx%d) encType:%s", i, rect.Width, rect.Height, rect.EncType)
|
||||
msg.Rects = append(msg.Rects, rect)
|
||||
}
|
||||
return &msg, nil
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Implementation of RFC 6143 §7.4 Pixel Format Data Structure.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
type SecurityType uint8
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
type ClientAuthNone struct{}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "encoding/binary"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=SecuritySubType"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=SecurityType"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
@ -15,6 +15,9 @@ var _ Conn = (*ServerConn)(nil)
|
||||
func (c *ServerConn) Config() interface{} {
|
||||
return c.cfg
|
||||
}
|
||||
func (c *ServerConn) GetEncInstance(typ EncodingType) Encoding {
|
||||
return &TightEncoding{}
|
||||
}
|
||||
|
||||
// Conn returns underlining server net.Conn
|
||||
func (c *ServerConn) Conn() net.Conn {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=TightCompression"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Code generated by "stringer -type=TightFilter"; DO NOT EDIT.
|
||||
|
||||
package vnc
|
||||
package vnc2webm
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user