mirror of
https://github.com/amitbet/vncproxy.git
synced 2025-04-27 18:55:13 +00:00
219 lines
5.2 KiB
Go
219 lines
5.2 KiB
Go
package common
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"io"
|
|
"github.com/amitbet/vncproxy/logger"
|
|
)
|
|
|
|
var TightMinToCompress = 12
|
|
|
|
const (
|
|
SegmentBytes SegmentType = iota
|
|
SegmentMessageStart
|
|
SegmentRectSeparator
|
|
SegmentFullyParsedClientMessage
|
|
SegmentFullyParsedServerMessage
|
|
SegmentServerInitMessage
|
|
SegmentConnectionClosed
|
|
SegmentMessageEnd
|
|
)
|
|
|
|
type SegmentType int
|
|
|
|
func (seg SegmentType) String() string {
|
|
switch seg {
|
|
case SegmentBytes:
|
|
return "SegmentBytes"
|
|
case SegmentMessageStart:
|
|
return "SegmentMessageStart"
|
|
case SegmentMessageEnd:
|
|
return "SegmentMessageEnd"
|
|
case SegmentRectSeparator:
|
|
return "SegmentRectSeparator"
|
|
case SegmentFullyParsedClientMessage:
|
|
return "SegmentFullyParsedClientMessage"
|
|
case SegmentFullyParsedServerMessage:
|
|
return "SegmentFullyParsedServerMessage"
|
|
case SegmentServerInitMessage:
|
|
return "SegmentServerInitMessage"
|
|
case SegmentConnectionClosed:
|
|
return "SegmentConnectionClosed"
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
type RfbSegment struct {
|
|
Bytes []byte
|
|
SegmentType SegmentType
|
|
UpcomingObjectType int
|
|
Message interface{}
|
|
}
|
|
|
|
type SegmentConsumer interface {
|
|
Consume(*RfbSegment) error
|
|
}
|
|
|
|
type RfbReadHelper struct {
|
|
io.Reader
|
|
Listeners *MultiListener
|
|
savedBytes *bytes.Buffer
|
|
}
|
|
|
|
func NewRfbReadHelper(r io.Reader) *RfbReadHelper {
|
|
return &RfbReadHelper{Reader: r, Listeners: &MultiListener{}}
|
|
}
|
|
|
|
func (r *RfbReadHelper) StartByteCollection() {
|
|
r.savedBytes = &bytes.Buffer{}
|
|
}
|
|
|
|
func (r *RfbReadHelper) EndByteCollection() []byte {
|
|
bts := r.savedBytes.Bytes()
|
|
r.savedBytes = nil
|
|
return bts
|
|
}
|
|
|
|
func (r *RfbReadHelper) ReadDiscrete(p []byte) (int, error) {
|
|
return r.Read(p)
|
|
}
|
|
|
|
func (r *RfbReadHelper) SendRectSeparator(upcomingRectType int) error {
|
|
seg := &RfbSegment{SegmentType: SegmentRectSeparator, UpcomingObjectType: upcomingRectType}
|
|
return r.Listeners.Consume(seg)
|
|
}
|
|
|
|
func (r *RfbReadHelper) SendMessageStart(upcomingMessageType ServerMessageType) error {
|
|
seg := &RfbSegment{SegmentType: SegmentMessageStart, UpcomingObjectType: int(upcomingMessageType)}
|
|
return r.Listeners.Consume(seg)
|
|
}
|
|
|
|
func (r *RfbReadHelper) SendMessageEnd(messageType ServerMessageType) error {
|
|
seg := &RfbSegment{SegmentType: SegmentMessageEnd, UpcomingObjectType: int(messageType)}
|
|
return r.Listeners.Consume(seg)
|
|
}
|
|
|
|
func (r *RfbReadHelper) PublishBytes(p []byte) error {
|
|
seg := &RfbSegment{Bytes: p, SegmentType: SegmentBytes}
|
|
return r.Listeners.Consume(seg)
|
|
}
|
|
|
|
//var prevlen int
|
|
|
|
func (r *RfbReadHelper) Read(p []byte) (n int, err error) {
|
|
readLen, err := r.Reader.Read(p)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
//if saving up our bytes, write them into the predefined buffer
|
|
if r.savedBytes != nil {
|
|
_, err := r.savedBytes.Write(p)
|
|
if err != nil {
|
|
logger.Warn("RfbReadHelper.Read: failed to collect bytes in mem buffer:", err)
|
|
}
|
|
}
|
|
/////////
|
|
// modLen := (prevlen % 10000)
|
|
// if len(p) == modLen && modLen != prevlen {
|
|
// logger.Warn("RFBReadHelper debug!! plen=", prevlen, " len=", len(p))
|
|
// }
|
|
// prevlen = len(p)
|
|
/////////
|
|
|
|
logger.Debugf("RfbReadHelper.Read: publishing bytes, bytes:%v", p[:readLen])
|
|
|
|
//write the bytes to the Listener for further processing
|
|
seg := &RfbSegment{Bytes: p[:readLen], SegmentType: SegmentBytes}
|
|
err = r.Listeners.Consume(seg)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return readLen, err
|
|
}
|
|
|
|
func (r *RfbReadHelper) ReadBytes(count int) ([]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 (r *RfbReadHelper) ReadUint8() (uint8, error) {
|
|
var myUint uint8
|
|
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return myUint, nil
|
|
}
|
|
func (r *RfbReadHelper) ReadUint16() (uint16, error) {
|
|
var myUint uint16
|
|
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return myUint, nil
|
|
}
|
|
func (r *RfbReadHelper) ReadUint32() (uint32, error) {
|
|
var myUint uint32
|
|
if err := binary.Read(r, binary.BigEndian, &myUint); err != nil {
|
|
return 0, err
|
|
}
|
|
|
|
return myUint, nil
|
|
}
|
|
func (r *RfbReadHelper) ReadCompactLen() (int, error) {
|
|
var err error
|
|
part, err := r.ReadUint8()
|
|
//byteCount := 1
|
|
len := uint32(part & 0x7F)
|
|
if (part & 0x80) != 0 {
|
|
part, err = r.ReadUint8()
|
|
//byteCount++
|
|
len |= uint32(part&0x7F) << 7
|
|
if (part & 0x80) != 0 {
|
|
part, err = r.ReadUint8()
|
|
//byteCount++
|
|
len |= uint32(part&0xFF) << 14
|
|
}
|
|
}
|
|
|
|
// for i := 0; i < byteCount; i++{
|
|
// rec.writeByte(portion[i]);
|
|
// }
|
|
|
|
return int(len), err
|
|
}
|
|
|
|
func (r *RfbReadHelper) ReadTightData(dataSize int) ([]byte, error) {
|
|
if int(dataSize) < TightMinToCompress {
|
|
return r.ReadBytes(int(dataSize))
|
|
}
|
|
zlibDataLen, err := r.ReadCompactLen()
|
|
logger.Debugf("RfbReadHelper.ReadTightData: compactlen=%d", zlibDataLen)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return r.ReadBytes(zlibDataLen)
|
|
}
|