diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 52c4091..18f8f14 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,29 +2,12 @@ - - - - - - - - - - - - - - + - - - - @@ -57,21 +40,36 @@ - - + + - - - + + + + + - - + + - - + + + + + + + + + + + + + + + @@ -80,85 +78,79 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -170,36 +162,36 @@ - vnc-server - problem writing to port - listener consume - WriteTo.Consume - writeToDisk - Recorder.Consume - rect hdr data - sending segment to server - s - segment - rsegment - rfsegment - rfbsegment - SendMessageSeparator - got ClientMessage - done! + pseudo + pseudoen + pseudoenc + pseudoenco + pseudoencod + pseudoencoding + [Debug] ###############rect################: 0 + [Debug] ###############rect################: + [Debug] ###############rect################: + [Debug] ###############rect################ + [Debug] ###############rect############### + Debug] ###############rect############### + #############rect############### + type=SegmentFullyParsedClientMessage + sending segment type sending segment - servermessage - got ServerMessage - Recorder.HandleRfbSegment - paddedSize - rect hdr - encodingType - read & parsed ServerMessage - pr - prox. - prox - proxy - proxy.go - vncpass + SegmentFullyParsedClientMessage + WriteTo.Consume + rect hdr data + upc + got ClientMessage + got segment type + read & parsed + FramebufferUpdateRequestMsgType + d & parsed ServerMessage + connect + Connect + Error: + got ClientMessage type + ServerConn.Handle got ClientMessage C:\Users\betzalel\Dropbox\go\src\vncproxy @@ -232,19 +224,19 @@ @@ -452,7 +444,7 @@ - + @@ -467,7 +459,7 @@ - + - + - + - + - + - + - + - + - + - + - + - @@ -1009,7 +1001,7 @@ - + @@ -1025,7 +1017,7 @@ - + @@ -1114,13 +1106,13 @@ file://$PROJECT_DIR$/tee-listeners/recorder.go - 147 + 146 file://$PROJECT_DIR$/tee-listeners/recorder.go - 153 + 152 @@ -1180,7 +1172,7 @@ file://$PROJECT_DIR$/tee-listeners/write-to.go - 26 + 27 @@ -1234,14 +1226,6 @@ - - - - - - - - @@ -1289,23 +1273,7 @@ - - - - - - - - - - - - - - - - - + @@ -1331,10 +1299,7 @@ - - - - + @@ -1350,7 +1315,7 @@ - + @@ -1405,14 +1370,6 @@ - - - - - - - - @@ -1421,46 +1378,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1493,33 +1410,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1528,44 +1418,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1654,32 +1506,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1690,12 +1516,135 @@ - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/client-conn.go b/client/client-conn.go index 0d0c8d8..1e4389b 100644 --- a/client/client-conn.go +++ b/client/client-conn.go @@ -493,18 +493,20 @@ func (c *ClientConn) mainLoop() { } } - defer func(){ + defer func() { logger.Warn("ClientConn.MainLoop: exiting!") }() for { var messageType uint8 if err := binary.Read(c.conn, binary.BigEndian, &messageType); err != nil { + logger.Errorf("ClientConn.MainLoop: error reading messagetype, %s", err) break } msg, ok := typeMap[messageType] if !ok { + logger.Errorf("ClientConn.MainLoop: bad message type, %d", messageType) // Unsupported message type! Bad! break } @@ -514,9 +516,10 @@ func (c *ClientConn) mainLoop() { parsedMsg, err := msg.Read(c, reader) if err != nil { + logger.Errorf("ClientConn.MainLoop: error parsing message, %s", err) break } - logger.Debugf("ClientConn.MainLoop: read & parsed ServerMessage:%s, %v", parsedMsg.Type(), parsedMsg) + logger.Debugf("ClientConn.MainLoop: read & parsed ServerMessage:%d, %s", parsedMsg.Type(), parsedMsg) if c.config.ServerMessageCh == nil { continue diff --git a/client/server-messages.go b/client/server-messages.go index 36cc722..935e60b 100644 --- a/client/server-messages.go +++ b/client/server-messages.go @@ -5,10 +5,10 @@ import ( "encoding/json" "fmt" "io" + "strings" "vncproxy/common" "vncproxy/encodings" "vncproxy/logger" - "strings" ) // FramebufferUpdateMessage consists of a sequence of rectangles of @@ -90,6 +90,7 @@ func (fbm *FramebufferUpdateMessage) Read(c common.IClientConn, r *common.RfbRea if strings.Contains(encType.String(), "Pseudo") { rect.Enc = &encodings.PseudoEncoding{encodingTypeInt} } else { + logger.Errorf("unsupported encoding type: %d, %s", encodingTypeInt, encType) return nil, fmt.Errorf("unsupported encoding type: %d, %s", encodingTypeInt, encType) } @@ -100,10 +101,6 @@ func (fbm *FramebufferUpdateMessage) Read(c common.IClientConn, r *common.RfbRea return &FramebufferUpdateMessage{rects}, nil } - - - - // SetColorMapEntriesMessage is sent by the server to set values into // the color map. This message will automatically update the color map // for the associated connection, but contains the color change data diff --git a/common/client-message.go b/common/client-message.go index 8d643ad..0ebe8c7 100644 --- a/common/client-message.go +++ b/common/client-message.go @@ -61,17 +61,17 @@ type ClientMessage interface { func (cmt ClientMessageType) String() string { switch cmt { case SetPixelFormatMsgType: - return "SetPixelFormatMsgType" + return "SetPixelFormat" case SetEncodingsMsgType: - return "SetEncodingsMsgType" + return "SetEncodings" case FramebufferUpdateRequestMsgType: - return "FramebufferUpdateRequestMsgType" + return "FramebufferUpdateRequest" case KeyEventMsgType: - return "KeyEventMsgType" + return "KeyEvent" case PointerEventMsgType: - return "PointerEventMsgType" + return "PointerEvent" case ClientCutTextMsgType: - return "ClientCutTextMsgType" + return "ClientCutText" } return "" } diff --git a/encodings/enc-pseudo.go b/encodings/enc-pseudo.go index 565077a..32430b5 100644 --- a/encodings/enc-pseudo.go +++ b/encodings/enc-pseudo.go @@ -6,10 +6,10 @@ type PseudoEncoding struct { Typ int32 } -func (pe *PseudoEncoding ) Type() int32{ +func (pe *PseudoEncoding) Type() int32 { return pe.Typ } -func (pe *PseudoEncoding) Read(*common.PixelFormat, *common.Rectangle, *common.RfbReadHelper) (common.Encoding, error){ +func (pe *PseudoEncoding) Read(*common.PixelFormat, *common.Rectangle, *common.RfbReadHelper) (common.Encoding, error) { return pe, nil } diff --git a/main.go b/main.go index ad04430..abea0ae 100644 --- a/main.go +++ b/main.go @@ -23,7 +23,8 @@ func main() { vncSrvMessagesChan := make(chan common.ServerMessage) - rec := listeners.NewRecorder("c:/Users/betzalel/recording.rbs") + //rec := listeners.NewRecorder("c:/Users/betzalel/recording.rbs") + rec := listeners.NewRecorder("/Users/amitbet/vncRec/recording.rbs") clientConn, err := client.NewClientConn(nc, &client.ClientConfig{ @@ -42,20 +43,22 @@ func main() { // if err != nil { // logger.Errorf("error requesting fb update: %s", err) // } + encs := []common.Encoding{ + &encodings.TightEncoding{}, + //&encodings.TightPngEncoding{}, + //rre := encodings.RREEncoding{}, + //zlib := encodings.ZLibEncoding{}, + //zrle := encodings.ZRLEEncoding{}, + //&encodings.CopyRectEncoding{}, + //coRRE := encodings.CoRREEncoding{}, + //hextile := encodings.HextileEncoding{}, + } - tight := encodings.TightEncoding{} - tightPng := encodings.TightPngEncoding{} - //rre := encodings.RREEncoding{} - //zlib := encodings.ZLibEncoding{} - //zrle := encodings.ZRLEEncoding{} - cpyRect := encodings.CopyRectEncoding{} - //coRRE := encodings.CoRREEncoding{} - //hextile := encodings.HextileEncoding{} // file, _ := os.OpenFile("stam.bin", os.O_CREATE|os.O_RDWR, 0755) // defer file.Close() //tight.SetOutput(file) - clientConn.SetEncodings([]common.Encoding{&cpyRect, &tightPng, &tight}) + clientConn.SetEncodings(encs) go func() { for { diff --git a/proxy/message-listeners.go b/proxy/message-listeners.go new file mode 100644 index 0000000..8c7610a --- /dev/null +++ b/proxy/message-listeners.go @@ -0,0 +1,71 @@ +package proxy + +import ( + "vncproxy/client" + "vncproxy/common" + "vncproxy/logger" + "vncproxy/server" +) + +type ClientUpdater struct { + conn *client.ClientConn +} + +// Consume recieves vnc-server-bound messages (Client messages) and updates the server part of the proxy +func (cc *ClientUpdater) Consume(seg *common.RfbSegment) error { + //logger.Debugf("ClientUpdater.Consume (vnc-server-bound): got segment type=%s bytes: %v", seg.SegmentType, seg.Bytes) + switch seg.SegmentType { + + case common.SegmentFullyParsedClientMessage: + clientMsg := seg.Message.(common.ClientMessage) + logger.Debugf("ClientUpdater.Consume:(vnc-server-bound) got ClientMessage type=%s", clientMsg.Type()) + switch clientMsg.Type() { + + case common.SetPixelFormatMsgType: + // update pixel format + logger.Debugf("ClientUpdater.Consume: updating pixel format") + pixFmtMsg := clientMsg.(*server.SetPixelFormat) + cc.conn.PixelFormat = pixFmtMsg.PF + } + + err := clientMsg.Write(cc.conn) + if err != nil { + logger.Errorf("ClientUpdater.Consume (vnc-server-bound, SegmentFullyParsedClientMessage): problem writing to port: %s", err) + } + return err + } + return nil +} + +type ServerUpdater struct { + conn *server.ServerConn + Name string +} + +// Consume receives vnc-client-bound messages (Server messages) and updates the server part of the proxy +func (p *ServerUpdater) Consume(seg *common.RfbSegment) error { + + logger.Debugf("ServerUpdater.Consume ("+p.Name+"): got segment type=%s bytes: %v", seg.SegmentType, seg.Bytes) + switch seg.SegmentType { + case common.SegmentMessageSeparator: + case common.SegmentRectSeparator: + case common.SegmentBytes: + // _, err := p.Writer.Write(seg.Bytes) + // if (err != nil) { + // logger.Errorf("WriteTo.Consume ("+p.Name+" SegmentBytes): problem writing to port: %s", err) + // } + // return err + case common.SegmentFullyParsedClientMessage: + + // clientMsg := seg.Message.(common.ClientMessage) + // logger.Debugf("WriteTo.Consume ("+p.Name+"): got ClientMessage type=%s", clientMsg.Type()) + // err := clientMsg.Write(p.Writer) + // if err != nil { + // logger.Errorf("WriteTo.Consume ("+p.Name+" SegmentFullyParsedClientMessage): problem writing to port: %s", err) + // } + // return err + default: + //return errors.New("WriteTo.Consume: undefined RfbSegment type") + } + return nil +} diff --git a/proxy/proxy.go b/proxy/proxy.go index 0a562ba..9e21f27 100644 --- a/proxy/proxy.go +++ b/proxy/proxy.go @@ -101,8 +101,9 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server // gets the messages from the server part (from vnc-client), // and write through the client to the actual vnc-server - clientMsgRepeater := &listeners.WriteTo{cconn, "vnc-server-bound"} - sconn.Listeners.AddListener(clientMsgRepeater) + //clientMsgRepeater := &listeners.WriteTo{cconn, "vnc-server-bound"} + clientUpdater := &ClientUpdater{cconn} + sconn.Listeners.AddListener(clientUpdater) err = cconn.Connect() if err != nil { @@ -121,7 +122,8 @@ func (vp *VncProxy) newServerConnHandler(cfg *server.ServerConfig, sconn *server //encodings.CoRREEncoding{}, //encodings.HextileEncoding{}, } - err = cconn.SetEncodings(encs) + cconn.Encs = encs + //err = cconn.SetEncodings(encs) if err != nil { logger.Errorf("Proxy.newServerConnHandler error connecting to client: %s", err) return err diff --git a/proxy/proxy_test.go b/proxy/proxy_test.go index 6963149..12202f2 100644 --- a/proxy/proxy_test.go +++ b/proxy/proxy_test.go @@ -7,8 +7,8 @@ func TestProxy(t *testing.T) { proxy := &VncProxy{ wsListeningUrl: "http://localhost:7777/", // empty = not listening on ws - recordingDir: "c:\\vncRec", // empty = no recording - targetServersPassword: "Ch_#!T@8", //empty = no auth + recordingDir: "/Users/amitbet/vncRec", // empty = no recording + targetServersPassword: "Ch_#!T@8", //empty = no auth SingleSession: &VncSession{ TargetHostname: "localhost", TargetPort: "5903", diff --git a/server/server-conn.go b/server/server-conn.go index 376897b..721dca7 100644 --- a/server/server-conn.go +++ b/server/server-conn.go @@ -206,7 +206,7 @@ func (c *ServerConn) handle() error { default: var messageType common.ClientMessageType if err := binary.Read(c, binary.BigEndian, &messageType); err != nil { - logger.Errorf("Error: %v", err) + logger.Errorf("ServerConn.handle error: %v", err) return err } msg, ok := clientMessages[messageType] @@ -216,11 +216,27 @@ func (c *ServerConn) handle() error { parsedMsg, err := msg.Read(c) + //update connection for pixel format / color map changes + switch parsedMsg.Type() { + case common.SetPixelFormatMsgType: + // update pixel format + logger.Debugf("ClientUpdater.Consume: updating pixel format") + pixFmtMsg := parsedMsg.(*SetPixelFormat) + c.SetPixelFormat(&pixFmtMsg.PF) + if pixFmtMsg.PF.TrueColor != 0 { + c.SetColorMap(&common.ColorMap{}) + } + } + //////// + if err != nil { logger.Errorf("srv err %s", err.Error()) return err } + //logger.Debugf("ServerConn.Handle got client message, type=%s", parsedMsg.Type()) + logger.Debugf("ServerConn.Handle got ClientMessage: %s, %v", parsedMsg.Type(), parsedMsg) + //parsedMsg.Type() seg := &common.RfbSegment{ SegmentType: common.SegmentFullyParsedClientMessage, Message: parsedMsg, @@ -231,7 +247,6 @@ func (c *ServerConn) handle() error { return err } - logger.Debugf("ServerConn.Handle got ClientMessage: %s, %v", parsedMsg.Type(), parsedMsg) //c.cfg.ClientMessageCh <- parsedMsg } } diff --git a/tee-listeners/recorder.go b/tee-listeners/recorder.go index 018006f..40d1834 100644 --- a/tee-listeners/recorder.go +++ b/tee-listeners/recorder.go @@ -3,7 +3,6 @@ package listeners import ( "bytes" "encoding/binary" - "errors" "os" "time" "vncproxy/common" @@ -73,7 +72,7 @@ const ( // } func (r *Recorder) writeStartSession(initMsg *common.ServerInit) error { - + r.sessionStartWritten = true desktopName := string(initMsg.NameText) framebufferWidth := initMsg.FBWidth framebufferHeight := initMsg.FBHeight @@ -91,13 +90,21 @@ func (r *Recorder) writeStartSession(initMsg *common.ServerInit) error { binary.Write(&r.buffer, binary.BigEndian, int16(framebufferWidth)) binary.Write(&r.buffer, binary.BigEndian, int16(framebufferHeight)) - 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) + 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()) - binary.Write(&r.buffer, binary.BigEndian, uint32(len(desktopName)+1)) + //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) - binary.Write(&r.buffer, binary.BigEndian, byte(0)) // add null termination for desktop string + //binary.Write(&r.buffer, binary.BigEndian, byte(0)) // add null termination for desktop string return nil } @@ -123,23 +130,23 @@ func (r *Recorder) HandleRfbSegment(data *common.RfbSegment) error { switch data.SegmentType { case common.SegmentMessageSeparator: if !r.sessionStartWritten { - logger.Debugf("Recorder.HandleRfbSegment: writing start session segment: %v",r.serverInitMessage) + logger.Debugf("Recorder.HandleRfbSegment: writing start session segment: %v", r.serverInitMessage) r.writeStartSession(r.serverInitMessage) } switch common.ServerMessageType(data.UpcomingObjectType) { case common.FramebufferUpdate: logger.Debugf("Recorder.HandleRfbSegment: saving FramebufferUpdate segment") - r.writeToDisk() + //r.writeToDisk() case common.SetColourMapEntries: case common.Bell: case common.ServerCutText: default: - return errors.New("unknown message type:" + string(data.UpcomingObjectType)) + logger.Warn("Recorder.HandleRfbSegment: unknown message type:" + string(data.UpcomingObjectType)) } case common.SegmentRectSeparator: - logger.Debugf("Recorder.HandleRfbSegment: writing start rect start") + logger.Debugf("Recorder.HandleRfbSegment: writing rect") r.writeToDisk() case common.SegmentBytes: _, err := r.buffer.Write(data.Bytes) diff --git a/tee-listeners/write-to.go b/tee-listeners/write-to.go index 20c3227..f2d8423 100644 --- a/tee-listeners/write-to.go +++ b/tee-listeners/write-to.go @@ -13,7 +13,7 @@ type WriteTo struct { func (p *WriteTo) Consume(seg *common.RfbSegment) error { - logger.Debugf("WriteTo.Consume ("+p.Name+"): sending segment type=%s", seg.SegmentType) + logger.Debugf("WriteTo.Consume ("+p.Name+"): got segment type=%s bytes: %v", seg.SegmentType, seg.Bytes) switch seg.SegmentType { case common.SegmentMessageSeparator: case common.SegmentRectSeparator: @@ -24,7 +24,9 @@ func (p *WriteTo) Consume(seg *common.RfbSegment) error { } return err case common.SegmentFullyParsedClientMessage: + clientMsg := seg.Message.(common.ClientMessage) + logger.Debugf("WriteTo.Consume ("+p.Name+"): got ClientMessage type=%s", clientMsg.Type()) err := clientMsg.Write(p.Writer) if (err != nil) { logger.Errorf("WriteTo.Consume ("+p.Name+" SegmentFullyParsedClientMessage): problem writing to port: %s", err) @@ -36,6 +38,8 @@ func (p *WriteTo) Consume(seg *common.RfbSegment) error { return nil } + + // type SendToClientMessageChan struct { // Channel chan *common.ClientMessage // } diff --git a/todo.md b/todo.md index cf74195..ae8bc79 100644 --- a/todo.md +++ b/todo.md @@ -3,7 +3,6 @@ * test proxy flow * create replay flow * set correct status for each flow -* have splitter logic on the connection objects * move encodings to be on the framebufferupdate message object * clear all messages read functions from updating stuff, move modification logic to another listener * message read function should accept only an io.Reader, move read helper logic (readuint8) to an actual helper class \ No newline at end of file