Skip to content

Commit

Permalink
fix: Buffer replays until connection is established. Fixes #169
Browse files Browse the repository at this point in the history
  • Loading branch information
alxbl committed Apr 8, 2020
1 parent c133371 commit 1ffaf5f
Showing 1 changed file with 22 additions and 9 deletions.
31 changes: 22 additions & 9 deletions pyrdp/recording/recorder.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#
# This file is part of the PyRDP project.
# Copyright (C) 2018 GoSecure Inc.
# Copyright (C) 2018-2020 GoSecure Inc.
# Licensed under the GPLv3 or later.
#

Expand All @@ -10,16 +10,17 @@
from pyrdp.enum import ParserMode, PlayerPDUType
from pyrdp.layer import LayerChainItem, PlayerLayer
from pyrdp.logging import log
from pyrdp.parser import BasicFastPathParser, ClientConnectionParser, ClientInfoParser, ClipboardParser, Parser, \
SlowPathParser
from pyrdp.parser import BasicFastPathParser, ClientConnectionParser, \
ClientInfoParser, ClipboardParser, Parser, SlowPathParser
from pyrdp.pdu import PDU


class Recorder:
"""
Class that manages recording of RDP events using the provided
transport layers. Those transport layers are the ones that will
receive binary data and handle them as they wish. They perform the actual recording.
receive binary data and handle them as they wish. They perform the
actual recording.
"""

def __init__(self, transports: List[LayerChainItem]):
Expand Down Expand Up @@ -56,7 +57,6 @@ def setParser(self, messageType: PlayerPDUType, parser: Parser):
"""
self.parsers[messageType] = parser


def record(self, pdu: Optional[PDU], messageType: PlayerPDUType):
"""
Encapsulate the pdu properly, then record the data
Expand Down Expand Up @@ -86,17 +86,30 @@ class FileLayer(LayerChainItem):
Layer that saves RDP events to a file for later replay.
"""

FLUSH_THRESHOLD = 18

def __init__(self, fileName: Union[str, Path]):
super().__init__()
self.file_descriptor = open(str(fileName), "wb")

# Buffer data until we have enough bytes for a meaningful replay.
self.pending = b''

self.filename = fileName
self.fd = None

def sendBytes(self, data: bytes):
"""
Save data to the file.
:param data: data to write.
"""

if not self.file_descriptor.closed:
self.file_descriptor.write(data)
if not self.fd:
self.pending += data
if len(self.pending) > FileLayer.FLUSH_THRESHOLD:
self.fd = open(str(self.filename), "wb")
self.fd.write(self.pending)
self.pending = b''
elif not self.fd.closed:
self.fd.write(data)
else:
log.error("Recording file handle closed, cannot write message: %(message)s", {"message": data})
log.error("Recording file handle closed, cannot write message: %(message)s", {"message": data})

0 comments on commit 1ffaf5f

Please sign in to comment.