proto recorder added

This commit is contained in:
Sibesh Kar 2019-07-12 10:32:25 +05:30
parent b6bd8a4330
commit 038d72a911
13 changed files with 779 additions and 1 deletions

View File

@ -2,7 +2,7 @@ vnc_rec:
go build -o ./bin/vnc_recorder ./vnc_rec/cmd/
run_rec:
./bin/vnc_recorder -recDir=./bin/recordings/ -targHost=localhost -targPort=5901 -targPass=boxware -tcpPort=5902 -vncPass=boxware
./bin/vnc_recorder -recDir=./bin/recordings/ -logLevel=debug -targHost=localhost -targPort=5901 -targPass=boxware -tcpPort=5902 -vncPass=boxware
clear:
rm -rf bin/recordings/*

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bin/vnc_reader Executable file

Binary file not shown.

Binary file not shown.

View File

@ -5,6 +5,7 @@ import (
"encoding/binary"
"io"
"os"
"github.com/amitbet/vncproxy/common"
"github.com/amitbet/vncproxy/encodings"
"github.com/amitbet/vncproxy/logger"
@ -184,6 +185,40 @@ func (fbs *FbsReader) ReadSegment() (*FbsSegment, error) {
return seg, nil
}
func (fbs *FbsReader) ReadSegmentTest() (*FbsSegment, uint32, uint32, []byte, uint32, 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)
}
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)
}
//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)
}
//timeStamp := time.Unix(timeSinceStart, 0)
seg := &FbsSegment{bytes: actualBytes, timestamp: timeSinceStart}
return seg, bytesLen, paddedSize, bytes, timeSinceStart, nil
}
type FbsSegment struct {
bytes []byte
timestamp uint32

376
proto/demo.pb.go Normal file
View File

@ -0,0 +1,376 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: demo.proto
package proto
import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
math "math"
)
// Reference imports to suppress errors if they are not otherwise used.
var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
type InitMsg struct {
RfbHeader string `protobuf:"bytes,1,opt,name=RfbHeader,json=rfbHeader,proto3" json:"RfbHeader,omitempty"`
RfbVersion string `protobuf:"bytes,2,opt,name=RfbVersion,json=rfbVersion,proto3" json:"RfbVersion,omitempty"`
FBHeight uint32 `protobuf:"varint,3,opt,name=FBHeight,json=fBHeight,proto3" json:"FBHeight,omitempty"`
FBWidth uint32 `protobuf:"varint,4,opt,name=FBWidth,json=fBWidth,proto3" json:"FBWidth,omitempty"`
SecType uint32 `protobuf:"varint,5,opt,name=SecType,json=secType,proto3" json:"SecType,omitempty"`
StartTime uint32 `protobuf:"varint,6,opt,name=StartTime,json=startTime,proto3" json:"StartTime,omitempty"`
DesktopName string `protobuf:"bytes,7,opt,name=DesktopName,json=desktopName,proto3" json:"DesktopName,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *InitMsg) Reset() { *m = InitMsg{} }
func (m *InitMsg) String() string { return proto.CompactTextString(m) }
func (*InitMsg) ProtoMessage() {}
func (*InitMsg) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{0}
}
func (m *InitMsg) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_InitMsg.Unmarshal(m, b)
}
func (m *InitMsg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_InitMsg.Marshal(b, m, deterministic)
}
func (m *InitMsg) XXX_Merge(src proto.Message) {
xxx_messageInfo_InitMsg.Merge(m, src)
}
func (m *InitMsg) XXX_Size() int {
return xxx_messageInfo_InitMsg.Size(m)
}
func (m *InitMsg) XXX_DiscardUnknown() {
xxx_messageInfo_InitMsg.DiscardUnknown(m)
}
var xxx_messageInfo_InitMsg proto.InternalMessageInfo
func (m *InitMsg) GetRfbHeader() string {
if m != nil {
return m.RfbHeader
}
return ""
}
func (m *InitMsg) GetRfbVersion() string {
if m != nil {
return m.RfbVersion
}
return ""
}
func (m *InitMsg) GetFBHeight() uint32 {
if m != nil {
return m.FBHeight
}
return 0
}
func (m *InitMsg) GetFBWidth() uint32 {
if m != nil {
return m.FBWidth
}
return 0
}
func (m *InitMsg) GetSecType() uint32 {
if m != nil {
return m.SecType
}
return 0
}
func (m *InitMsg) GetStartTime() uint32 {
if m != nil {
return m.StartTime
}
return 0
}
func (m *InitMsg) GetDesktopName() string {
if m != nil {
return m.DesktopName
}
return ""
}
type PointerEvent struct {
Mask uint32 `protobuf:"varint,1,opt,name=Mask,json=mask,proto3" json:"Mask,omitempty"`
X uint32 `protobuf:"varint,2,opt,name=X,json=x,proto3" json:"X,omitempty"`
Y uint32 `protobuf:"varint,3,opt,name=Y,json=y,proto3" json:"Y,omitempty"`
Timestamp uint32 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *PointerEvent) Reset() { *m = PointerEvent{} }
func (m *PointerEvent) String() string { return proto.CompactTextString(m) }
func (*PointerEvent) ProtoMessage() {}
func (*PointerEvent) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{1}
}
func (m *PointerEvent) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_PointerEvent.Unmarshal(m, b)
}
func (m *PointerEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_PointerEvent.Marshal(b, m, deterministic)
}
func (m *PointerEvent) XXX_Merge(src proto.Message) {
xxx_messageInfo_PointerEvent.Merge(m, src)
}
func (m *PointerEvent) XXX_Size() int {
return xxx_messageInfo_PointerEvent.Size(m)
}
func (m *PointerEvent) XXX_DiscardUnknown() {
xxx_messageInfo_PointerEvent.DiscardUnknown(m)
}
var xxx_messageInfo_PointerEvent proto.InternalMessageInfo
func (m *PointerEvent) GetMask() uint32 {
if m != nil {
return m.Mask
}
return 0
}
func (m *PointerEvent) GetX() uint32 {
if m != nil {
return m.X
}
return 0
}
func (m *PointerEvent) GetY() uint32 {
if m != nil {
return m.Y
}
return 0
}
func (m *PointerEvent) GetTimestamp() uint32 {
if m != nil {
return m.Timestamp
}
return 0
}
type KeyEvent struct {
Down uint32 `protobuf:"varint,1,opt,name=Down,json=down,proto3" json:"Down,omitempty"`
Key uint32 `protobuf:"varint,2,opt,name=Key,json=key,proto3" json:"Key,omitempty"`
Timestamp uint32 `protobuf:"varint,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *KeyEvent) Reset() { *m = KeyEvent{} }
func (m *KeyEvent) String() string { return proto.CompactTextString(m) }
func (*KeyEvent) ProtoMessage() {}
func (*KeyEvent) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{2}
}
func (m *KeyEvent) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_KeyEvent.Unmarshal(m, b)
}
func (m *KeyEvent) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_KeyEvent.Marshal(b, m, deterministic)
}
func (m *KeyEvent) XXX_Merge(src proto.Message) {
xxx_messageInfo_KeyEvent.Merge(m, src)
}
func (m *KeyEvent) XXX_Size() int {
return xxx_messageInfo_KeyEvent.Size(m)
}
func (m *KeyEvent) XXX_DiscardUnknown() {
xxx_messageInfo_KeyEvent.DiscardUnknown(m)
}
var xxx_messageInfo_KeyEvent proto.InternalMessageInfo
func (m *KeyEvent) GetDown() uint32 {
if m != nil {
return m.Down
}
return 0
}
func (m *KeyEvent) GetKey() uint32 {
if m != nil {
return m.Key
}
return 0
}
func (m *KeyEvent) GetTimestamp() uint32 {
if m != nil {
return m.Timestamp
}
return 0
}
type FbsSegment struct {
Bytes []byte `protobuf:"bytes,1,opt,name=bytes,proto3" json:"bytes,omitempty"`
Timestamp uint32 `protobuf:"varint,2,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *FbsSegment) Reset() { *m = FbsSegment{} }
func (m *FbsSegment) String() string { return proto.CompactTextString(m) }
func (*FbsSegment) ProtoMessage() {}
func (*FbsSegment) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{3}
}
func (m *FbsSegment) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FbsSegment.Unmarshal(m, b)
}
func (m *FbsSegment) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_FbsSegment.Marshal(b, m, deterministic)
}
func (m *FbsSegment) XXX_Merge(src proto.Message) {
xxx_messageInfo_FbsSegment.Merge(m, src)
}
func (m *FbsSegment) XXX_Size() int {
return xxx_messageInfo_FbsSegment.Size(m)
}
func (m *FbsSegment) XXX_DiscardUnknown() {
xxx_messageInfo_FbsSegment.DiscardUnknown(m)
}
var xxx_messageInfo_FbsSegment proto.InternalMessageInfo
func (m *FbsSegment) GetBytes() []byte {
if m != nil {
return m.Bytes
}
return nil
}
func (m *FbsSegment) GetTimestamp() uint32 {
if m != nil {
return m.Timestamp
}
return 0
}
type Demonstration struct {
Initmsg *InitMsg `protobuf:"bytes,1,opt,name=initmsg,proto3" json:"initmsg,omitempty"`
Segments []*FbsSegment `protobuf:"bytes,2,rep,name=segments,proto3" json:"segments,omitempty"`
Pointerevents []*PointerEvent `protobuf:"bytes,3,rep,name=pointerevents,proto3" json:"pointerevents,omitempty"`
Keyevents []*KeyEvent `protobuf:"bytes,4,rep,name=keyevents,proto3" json:"keyevents,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *Demonstration) Reset() { *m = Demonstration{} }
func (m *Demonstration) String() string { return proto.CompactTextString(m) }
func (*Demonstration) ProtoMessage() {}
func (*Demonstration) Descriptor() ([]byte, []int) {
return fileDescriptor_ca53982754088a9d, []int{4}
}
func (m *Demonstration) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Demonstration.Unmarshal(m, b)
}
func (m *Demonstration) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_Demonstration.Marshal(b, m, deterministic)
}
func (m *Demonstration) XXX_Merge(src proto.Message) {
xxx_messageInfo_Demonstration.Merge(m, src)
}
func (m *Demonstration) XXX_Size() int {
return xxx_messageInfo_Demonstration.Size(m)
}
func (m *Demonstration) XXX_DiscardUnknown() {
xxx_messageInfo_Demonstration.DiscardUnknown(m)
}
var xxx_messageInfo_Demonstration proto.InternalMessageInfo
func (m *Demonstration) GetInitmsg() *InitMsg {
if m != nil {
return m.Initmsg
}
return nil
}
func (m *Demonstration) GetSegments() []*FbsSegment {
if m != nil {
return m.Segments
}
return nil
}
func (m *Demonstration) GetPointerevents() []*PointerEvent {
if m != nil {
return m.Pointerevents
}
return nil
}
func (m *Demonstration) GetKeyevents() []*KeyEvent {
if m != nil {
return m.Keyevents
}
return nil
}
func init() {
proto.RegisterType((*InitMsg)(nil), "proto.InitMsg")
proto.RegisterType((*PointerEvent)(nil), "proto.PointerEvent")
proto.RegisterType((*KeyEvent)(nil), "proto.KeyEvent")
proto.RegisterType((*FbsSegment)(nil), "proto.FbsSegment")
proto.RegisterType((*Demonstration)(nil), "proto.Demonstration")
}
func init() { proto.RegisterFile("demo.proto", fileDescriptor_ca53982754088a9d) }
var fileDescriptor_ca53982754088a9d = []byte{
// 408 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x91, 0x4f, 0x8b, 0xdb, 0x30,
0x10, 0xc5, 0x51, 0x9c, 0xac, 0xe3, 0x49, 0xdc, 0x3f, 0x6a, 0x0f, 0xa2, 0x94, 0x12, 0x72, 0xca,
0x65, 0xf7, 0xb0, 0x3d, 0xf5, 0x56, 0x96, 0x34, 0x6c, 0x59, 0x76, 0x29, 0xca, 0xd2, 0x3f, 0xd0,
0x8b, 0x5d, 0x8f, 0xbd, 0xc2, 0x48, 0x32, 0x92, 0xd8, 0xad, 0xbf, 0x66, 0x2f, 0xfd, 0x3a, 0xc5,
0xb2, 0x1c, 0x37, 0x39, 0x99, 0x99, 0x37, 0xef, 0xe7, 0xa7, 0x19, 0x80, 0x02, 0xa5, 0xbe, 0x68,
0x8c, 0x76, 0x9a, 0xce, 0xfc, 0x67, 0xfd, 0x97, 0x40, 0xfc, 0x59, 0x09, 0x77, 0x6b, 0x2b, 0xfa,
0x16, 0x12, 0x5e, 0xe6, 0xd7, 0x98, 0x15, 0x68, 0x18, 0x59, 0x91, 0x4d, 0xc2, 0x13, 0x33, 0x34,
0xe8, 0x3b, 0x00, 0x5e, 0xe6, 0x5f, 0xd1, 0x58, 0xa1, 0x15, 0x9b, 0x78, 0x19, 0xcc, 0xa1, 0x43,
0xdf, 0xc0, 0x7c, 0x77, 0x75, 0x8d, 0xa2, 0x7a, 0x70, 0x2c, 0x5a, 0x91, 0x4d, 0xca, 0xe7, 0x65,
0xa8, 0x29, 0x83, 0x78, 0x77, 0xf5, 0x4d, 0x14, 0xee, 0x81, 0x4d, 0xbd, 0x14, 0x97, 0x7d, 0xd9,
0x29, 0x7b, 0xfc, 0x75, 0xdf, 0x36, 0xc8, 0x66, 0xbd, 0x62, 0xfb, 0xb2, 0x4b, 0xb3, 0x77, 0x99,
0x71, 0xf7, 0x42, 0x22, 0x3b, 0xf3, 0x5a, 0x62, 0x87, 0x06, 0x5d, 0xc1, 0x62, 0x8b, 0xb6, 0x76,
0xba, 0xb9, 0xcb, 0x24, 0xb2, 0xd8, 0xc7, 0x59, 0x14, 0x63, 0x6b, 0xfd, 0x13, 0x96, 0x5f, 0xb4,
0x50, 0x0e, 0xcd, 0xa7, 0x47, 0x54, 0x8e, 0x52, 0x98, 0xde, 0x66, 0xb6, 0xf6, 0x0f, 0x4b, 0xf9,
0x54, 0x66, 0xb6, 0xa6, 0x4b, 0x20, 0xdf, 0xfd, 0x53, 0x52, 0x4e, 0x7e, 0x77, 0xd5, 0x8f, 0x10,
0x9d, 0xb4, 0xdd, 0xff, 0x9d, 0x90, 0x68, 0x5d, 0x26, 0x9b, 0x90, 0x7a, 0x6c, 0xac, 0xef, 0x60,
0x7e, 0x83, 0xed, 0x81, 0xbc, 0xd5, 0x4f, 0x6a, 0x20, 0x17, 0xfa, 0x49, 0xd1, 0x17, 0x10, 0xdd,
0x60, 0x1b, 0xd8, 0x51, 0x8d, 0x27, 0xbc, 0xe8, 0x94, 0xf7, 0x11, 0x60, 0x97, 0xdb, 0x3d, 0x56,
0xb2, 0x23, 0xbe, 0x86, 0x59, 0xde, 0x3a, 0xb4, 0x1e, 0xb9, 0xe4, 0x7d, 0x71, 0x4c, 0x98, 0x9c,
0x12, 0xfe, 0x10, 0x48, 0xb7, 0x28, 0xb5, 0xb2, 0xce, 0x64, 0xae, 0xbb, 0xc8, 0x06, 0x62, 0xa1,
0x84, 0x93, 0xb6, 0xf2, 0x9c, 0xc5, 0xe5, 0xb3, 0xfe, 0xf6, 0x17, 0xe1, 0xe0, 0x7c, 0x90, 0xe9,
0x39, 0xcc, 0x6d, 0xff, 0x6b, 0xcb, 0x26, 0xab, 0x68, 0xb3, 0xb8, 0x7c, 0x19, 0x46, 0xc7, 0x50,
0xfc, 0x30, 0x42, 0x3f, 0x40, 0xda, 0xf4, 0xab, 0xc5, 0x47, 0xef, 0x89, 0xbc, 0xe7, 0x55, 0xf0,
0xfc, 0xbf, 0x76, 0x7e, 0x3c, 0x49, 0xcf, 0x21, 0xa9, 0xb1, 0x0d, 0xb6, 0xa9, 0xb7, 0x3d, 0x0f,
0xb6, 0x61, 0x9f, 0x7c, 0x9c, 0xc8, 0xcf, 0xbc, 0xf4, 0xfe, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff,
0xaa, 0x99, 0xea, 0x8d, 0xba, 0x02, 0x00, 0x00,
}

38
proto/demo.proto Normal file
View File

@ -0,0 +1,38 @@
syntax = "proto3";
package proto;
message InitMsg {
string RfbHeader = 1;
string RfbVersion = 2;
uint32 FBHeight = 3;
uint32 FBWidth = 4;
uint32 SecType = 5;
uint32 StartTime = 6;
string DesktopName = 7;
}
message PointerEvent {
uint32 Mask = 1;
uint32 X = 2;
uint32 Y = 3;
uint32 timestamp = 4;
}
message KeyEvent {
uint32 Down = 1;
uint32 Key = 2;
uint32 timestamp = 3;
}
message FbsSegment{
bytes bytes = 1;
uint32 timestamp = 2;
}
message Demonstration {
InitMsg initmsg = 1;
repeated FbsSegment segments = 2;
repeated PointerEvent pointerevents = 3;
repeated KeyEvent keyevents = 4;
}

53
vnc_read/main.go Normal file
View File

@ -0,0 +1,53 @@
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"os"
"github.com/golang/protobuf/proto"
pb "github.com/sibeshkar/vncproxy/proto"
)
func main() {
if len(os.Args) != 2 {
log.Fatalf("Usage: %s ADDRESS_BOOK_FILE\n", os.Args[0])
}
fname := os.Args[1]
// [START unmarshal_proto]
// Read the existing address book.
in, err := ioutil.ReadFile(fname)
if err != nil {
log.Fatalln("Error reading file:", err)
}
demonstration := &pb.Demonstration{}
if err := proto.Unmarshal(in, demonstration); err != nil {
log.Fatalln("Failed to parse demonstration file:", err)
}
listPeople(os.Stdout, demonstration)
}
func listPeople(w io.Writer, demo *pb.Demonstration) {
fmt.Printf("FBHeight: %v \n", demo.Initmsg.GetFBHeight())
fmt.Printf("FBWidth: %v \n", demo.Initmsg.GetFBWidth())
fmt.Printf("RfbHeader: %v \n", demo.Initmsg.GetRfbHeader())
fmt.Printf("RfbVersion: %v \n", demo.Initmsg.GetRfbVersion())
fmt.Printf("SecType: %v \n", demo.Initmsg.GetSecType())
fmt.Printf("StartTime: %v \n", demo.Initmsg.GetStartTime())
fmt.Printf("DesktopName: %v \n", demo.Initmsg.GetDesktopName())
// for _, p := range demo.Segments {
// writePerson(w, p)
// }
}
func writePerson(w io.Writer, p *pb.FbsSegment) {
fmt.Printf("Length: %v Timestamp: %v \n", len(p.GetBytes()), p.GetTimestamp())
}

View File

@ -130,6 +130,7 @@ func (r *ClientRecorder) HandleRfbSegment(data *common.RfbSegment) error {
logger.Warn("ClientRecorder.HandleRfbSegment: unknown message type:" + string(data.UpcomingObjectType))
}
case common.SegmentConnectionClosed:
logger.Debugf("Segment Connection closed")
r.writeToDisk()
case common.SegmentRectSeparator:
logger.Debugf("ClientRecorder.HandleRfbSegment: not writing rect")
@ -192,6 +193,8 @@ func (r *ClientRecorder) writeToDisk() error {
//write timestamp
binary.Write(r.writer, binary.BigEndian, uint32(timeSinceStart))
r.buffer.Reset()
logger.Debugf("writeToDisk() Triggered Now")
return err
}

261
vnc_rec/proto-recorder.go Normal file
View File

@ -0,0 +1,261 @@
package vnc_rec
import (
"bytes"
"fmt"
"io/ioutil"
"log"
"os"
"github.com/amitbet/vncproxy/common"
"github.com/amitbet/vncproxy/logger"
"github.com/amitbet/vncproxy/server"
"github.com/golang/protobuf/proto"
pb "github.com/sibeshkar/vncproxy/proto"
)
type ProtoRecorder struct {
//common.BytesListener
RBSFileName string
writer *os.File
demonstration *pb.Demonstration
//logger common.Logger
startTime int
buffer bytes.Buffer
serverInitMessage *common.ServerInit
sessionStartWritten bool
segmentChan chan *common.RfbSegment
maxWriteSize int
}
func NewProtoRecorder(saveFilePath string) (*ProtoRecorder, error) {
//delete file if it exists
if _, err := os.Stat(saveFilePath); err == nil {
os.Remove(saveFilePath)
}
rec := ProtoRecorder{RBSFileName: saveFilePath, startTime: getNowMillisec()}
var err error
rec.maxWriteSize = 65535
in, err := ioutil.ReadFile(saveFilePath)
if err != nil {
if os.IsNotExist(err) {
fmt.Printf("%s: File not found. Creating new file.\n", saveFilePath)
} else {
log.Fatalln("Error reading file:", err)
}
}
rec.demonstration = &pb.Demonstration{}
if err := proto.Unmarshal(in, rec.demonstration); err != nil {
log.Fatalln("Failed to parse demonstration file:", err)
}
// rec.writer, err = os.OpenFile(saveFilePath, os.O_RDWR|os.O_CREATE, 0644)
// if err != nil {
// logger.Errorf("unable to open file: %s, error: %v", saveFilePath, err)
// return nil, err
// }
//buffer the channel so we don't halt the proxying flow for slow writes when under pressure
rec.segmentChan = make(chan *common.RfbSegment, 100)
go func() {
for {
data := <-rec.segmentChan
rec.HandleRfbSegment(data)
}
}()
return &rec, nil
}
func (r *ProtoRecorder) writeStartSession(initMsg *common.ServerInit) error {
r.sessionStartWritten = true
desktopName := string(initMsg.NameText)
framebufferWidth := initMsg.FBWidth
framebufferHeight := initMsg.FBHeight
// //write rfb header information (the only part done without the [size|data|timestamp] block wrapper)
// r.writer.WriteString("FBS 001.000\n")
// r.demonstration.Initmsg.
// //push the version message into the buffer so it will be written in the first rbs block
// r.buffer.WriteString(versionMsg_3_3)
// //push sec type and fb dimensions
// binary.Write(&r.buffer, binary.BigEndian, int32(SecTypeNone))
// binary.Write(&r.buffer, binary.BigEndian, int16(framebufferWidth))
// binary.Write(&r.buffer, binary.BigEndian, int16(framebufferHeight))
// buff := bytes.Buffer{}
// //binary.Write(&buff, binary.BigEndian, initMsg.FBWidth)
// //binary.Write(&buff, binary.BigEndian, initMsg.FBHeight)
// binary.Write(&buff, binary.BigEndian, initMsg.PixelFormat)
// buff.Write([]byte{0, 0, 0}) //padding
// r.buffer.Write(buff.Bytes())
// //logger.Debugf(">>>>>>buffer for initMessage:%v ", buff.Bytes())
// //var fbsServerInitMsg = []byte{32, 24, 0, 1, 0, byte(0xFF), 0, byte(0xFF), 0, byte(0xFF), 16, 8, 0, 0, 0, 0}
// //r.buffer.Write(fbsServerInitMsg)
// binary.Write(&r.buffer, binary.BigEndian, uint32(len(desktopName)))
// r.buffer.WriteString(desktopName)
initMsgProto := &pb.InitMsg{
RfbHeader: "FBS 001.000",
RfbVersion: versionMsg_3_3,
FBHeight: uint32(framebufferHeight),
FBWidth: uint32(framebufferWidth),
SecType: uint32(SecTypeNone),
StartTime: uint32(r.startTime),
DesktopName: desktopName,
}
r.demonstration.Initmsg = initMsgProto
//binary.Write(&r.buffer, binary.BigEndian, byte(0)) // add null termination for desktop string
return nil
}
func (r *ProtoRecorder) Consume(data *common.RfbSegment) error {
//using async writes so if chan buffer overflows, proxy will not be affected
select {
case r.segmentChan <- data:
// default:
// logger.Error("error: ProtoRecorder queue is full")
}
return nil
}
func (r *ProtoRecorder) HandleRfbSegment(data *common.RfbSegment) error {
defer func() {
if r := recover(); r != nil {
logger.Error("Recovered in HandleRfbSegment: ", r)
}
}()
timeSinceStart := uint32(getNowMillisec() - r.startTime)
switch data.SegmentType {
case common.SegmentMessageStart:
if !r.sessionStartWritten {
logger.Debugf("ProtoRecorder.HandleRfbSegment: writing start session segment: %v", r.serverInitMessage)
r.writeStartSession(r.serverInitMessage)
}
switch common.ServerMessageType(data.UpcomingObjectType) {
case common.FramebufferUpdate:
logger.Debugf("ProtoRecorder.HandleRfbSegment: saving FramebufferUpdate segment")
//r.writeToDisk()
case common.SetColourMapEntries:
case common.Bell:
case common.ServerCutText:
default:
logger.Warn("ProtoRecorder.HandleRfbSegment: unknown message type:" + string(data.UpcomingObjectType))
}
case common.SegmentConnectionClosed:
r.writeToDisk()
case common.SegmentRectSeparator:
logger.Debugf("ProtoRecorder.HandleRfbSegment: writing rect")
//r.writeToDisk()
case common.SegmentBytes:
logger.Debug("ProtoRecorder.HandleRfbSegment: writing bytes, len:", len(data.Bytes))
// if r.buffer.Len()+len(data.Bytes) > r.maxWriteSize-4 {
// r.writeToDisk()
// }
segment := &pb.FbsSegment{
Bytes: data.Bytes,
Timestamp: timeSinceStart,
}
r.demonstration.Segments = append(r.demonstration.Segments, segment)
//_, err := r.buffer.Write(data.Bytes)
//return err
case common.SegmentServerInitMessage:
r.serverInitMessage = data.Message.(*common.ServerInit)
case common.SegmentFullyParsedClientMessage:
clientMsg := data.Message.(common.ClientMessage)
switch clientMsg.Type() {
case common.SetPixelFormatMsgType:
clientMsg := data.Message.(*server.MsgSetPixelFormat)
logger.Debugf("ClientRecorder.HandleRfbSegment: client message %v", *clientMsg)
r.serverInitMessage.PixelFormat = clientMsg.PF
case common.KeyEventMsgType:
clientMsg := data.Message.(*server.MsgKeyEvent)
logger.Debug("Recorder.HandleRfbSegment: writing bytes for KeyEventMsgType, len:", *clientMsg)
//clientMsg.Write(r.writer)
keyevent := &pb.KeyEvent{
Down: uint32(clientMsg.Down),
Key: uint32(clientMsg.Key),
Timestamp: timeSinceStart,
}
r.demonstration.Keyevents = append(r.demonstration.Keyevents, keyevent)
case common.PointerEventMsgType:
clientMsg := data.Message.(*server.MsgPointerEvent)
logger.Debug("Recorder.HandleRfbSegment: writing bytes for PointerEventMsgType, len:", *clientMsg)
//clientMsg.Write(r.writer)
pointerevent := &pb.PointerEvent{
Mask: uint32(clientMsg.Mask),
X: uint32(clientMsg.X),
Y: uint32(clientMsg.Y),
Timestamp: timeSinceStart,
}
r.demonstration.Pointerevents = append(r.demonstration.Pointerevents, pointerevent)
default:
//return errors.New("unknown client message type:" + string(data.UpcomingObjectType))
}
default:
//return errors.New("undefined RfbSegment type")
}
return nil
}
func (r *ProtoRecorder) writeToDisk() error {
out, err := proto.Marshal(r.demonstration)
if err != nil {
log.Fatalln("Failed to encode address book:", err)
}
if err := ioutil.WriteFile(r.RBSFileName, out, 0644); err != nil {
log.Fatalln("Failed to write address book:", err)
}
// timeSinceStart := getNowMillisec() - r.startTime
// if r.buffer.Len() == 0 {
// return nil
// }
// //write buff length
// bytesLen := r.buffer.Len()
// binary.Write(r.writer, binary.BigEndian, uint32(bytesLen))
// paddedSize := (bytesLen + 3) & 0x7FFFFFFC
// paddingSize := paddedSize - bytesLen
// //logger.Debugf("paddedSize=%d paddingSize=%d bytesLen=%d", paddedSize, paddingSize, bytesLen)
// //write buffer padded to 32bit
// _, err := r.buffer.WriteTo(r.writer)
// padding := make([]byte, paddingSize)
// //logger.Debugf("padding=%v ", padding)
// binary.Write(r.writer, binary.BigEndian, padding)
// //write timestamp
// binary.Write(r.writer, binary.BigEndian, uint32(timeSinceStart))
// r.buffer.Reset()
return err
}
// func (r *ProtoRecorder) WriteUInt8(data uint8) error {
// buf := make([]byte, 1)
// buf[0] = byte(data) // cast int8 to byte
// return r.Write(buf)
// }
func (r *ProtoRecorder) Close() {
r.writer.Close()
}

View File

@ -81,6 +81,7 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server
var rec_s *ServerRecorder
var rec_c *ClientRecorder
var rec_p *ProtoRecorder
if session.Type == SessionTypeRecordingProxy {
timeCurrent := strconv.FormatInt(time.Now().Unix(), 10)
@ -105,6 +106,16 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server
}
sconn.Listeners.AddListener(rec_c)
recProtoFile := "proto.rbs"
recProtoPath := path.Join(recFolder, recProtoFile)
rec_p, err = NewProtoRecorder(recProtoPath)
if err != nil {
logger.Errorf("Proxy.newServerConnHandler can't open ProtoRecorder save path: %s", recProtoPath)
return err
}
sconn.Listeners.AddListener(rec_p)
}
session.Status = SessionStatusInit
@ -123,6 +134,7 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server
if session.Type == SessionTypeRecordingProxy {
cconn.Listeners.AddListener(rec_s)
cconn.Listeners.AddListener(rec_c)
cconn.Listeners.AddListener(rec_p)
}
//creating cross-listeners between server and client parts to pass messages through the proxy: