diff --git a/rdpy/display/rle.py b/rdpy/display/rle.py
index e9295b8..a321513 100644
--- a/rdpy/display/rle.py
+++ b/rdpy/display/rle.py
@@ -45,7 +45,9 @@ def decode(src, width, height, colorType):
insertMix = False
fom_mask = 0
mask = 0
- dst = Stream("\x00" * (width * height * sizeof(colorType())))
+ line = 0
+ typeSize = sizeof(colorType())
+ dst = Stream("\x00" * (width * height * typeSize))
while src.dataLen() > 0:
#compute orders
@@ -107,7 +109,10 @@ def decode(src, width, height, colorType):
raise InvalidExpectedDataException("In RLE decompression height must be greater than 0")
x = 0
height -= 1
- #prevline = line
+ prevline = line
+ line = width * height * typeSize
+
+
return dst
\ No newline at end of file
diff --git a/rdpy/network/error.py b/rdpy/network/error.py
index 69eacea..46b0080 100644
--- a/rdpy/network/error.py
+++ b/rdpy/network/error.py
@@ -21,6 +21,16 @@
All exceptions error use in RDPY
"""
+class CallPureVirtualFuntion(Exception):
+ """
+ Raise when a virtual function is called and not implemented
+ """
+ def __init__(self, message = ""):
+ """
+ @param message: message show when exception is raised
+ """
+ Exception.__init__(self, message)
+
class InvalidValue(Exception):
"""
Raise when invalid value type occurred
diff --git a/rdpy/network/layer.py b/rdpy/network/layer.py
index 5c2d514..dc011dd 100644
--- a/rdpy/network/layer.py
+++ b/rdpy/network/layer.py
@@ -23,88 +23,94 @@ Join RDPY design with twisted design
RDPY use Layer Protocol design (like twisted)
"""
+from rdpy.network.error import CallPureVirtualFuntion
+
class LayerMode(object):
NONE = 0
SERVER = 1
CLIENT = 2
-
+
+
+class StreamListener(object):
+ """
+ Interface use to inform that we can handle receive stream
+ """
+ def recv(self, s):
+ """
+ Signal that data is available for this layer
+ call by transport layer
+ default is to pass data to presentation layer
+ @param s: raw Stream receive from transport layer
+ """
+ raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "recv", "StreamListener"))
+
+class StreamSender(object):
+ """
+ Interface use to show stream sender capability
+ """
+ def send(self, data):
+ '''
+ Send Stream on layer
+ @param data: Type or tuple element handle by transport layer
+ '''
+ raise CallPureVirtualFuntion("%s:%s defined by interface %s"%(self.__class__, "send", "StreamSender"))
+
class Layer(object):
- '''
- Network abstraction for protocol
- Try as possible to divide user protocol in layer
- default implementation is a transparent layer
- '''
- def __init__(self, mode = LayerMode.NONE, presentation = None):
- '''
- Constructor
- @param presentation: Layer which handled connect and recv messages
- '''
+ """
+ A simple double linked list with presentation and transport layer
+ and a subset of event (connect and close)
+ """
+ def __init__(self, mode, presentation = None):
+ """
+ @param mode: LayerMode use
+ @param presentation: presentation layer
+ """
#presentation layer higher layer in model
self._presentation = presentation
#transport layer under layer in model
self._transport = None
- #register layer mode
+ #network layer mode
self._mode = mode
#auto set transport layer of own presentation layer
if not self._presentation is None:
self._presentation._transport = self
def connect(self):
- '''
- call when transport layer is connected
+ """
+ Call when transport layer is connected
default is send connect event to presentation layer
- '''
+ """
if not self._presentation is None:
self._presentation.connect()
- def recv(self, s):
- '''
- signal that data is available for this layer
- call by transport layer
- default is to pass data to presentation layer
- @param s: raw Stream receive from transport layer
- '''
- if not self._presentation is None:
- self._presentation.recv(s)
-
- def send(self, data):
- '''
- classical use by presentation layer
- write data for this layer
- default pass data to transport layer
- @param data: Type or tuple element handle by transport layer
- '''
- if not self._transport is None:
- self._transport.send(data)
-
def close(self):
- '''
- close layer and send close signal
- to transport layer
- '''
+ """
+ Close layer event
+ default is sent to transport layer
+ """
if not self._transport is None:
self._transport.close()
-class LayerAutomata(Layer):
- '''
- layer with automata state
- we can set next recv function used
- '''
+class LayerAutomata(Layer, StreamListener):
+ """
+ Layer with automata state
+ we can set next recv function used for Stream packet
+ """
def __init__(self, mode, presentation = None):
- '''
- Constructor
+ """
+ @param mode: LayerMode use
@param presentation: presentation Layer
- '''
+ """
#call parent constructor
Layer.__init__(self, mode, presentation)
def setNextState(self, callback = None):
- '''
- set recv function to next callback or
+ """
+ Set receive function to next callback or
current self.recv function if it's None
@param callback: a callable object that can
receive Layer, Stream parameters
- '''
+ """
if callback is None:
callback = self.__class__.recv
@@ -115,16 +121,17 @@ from twisted.internet import protocol
#first that handle stream
from type import Stream
-class RawLayer(protocol.Protocol, LayerAutomata):
- '''
+class RawLayer(protocol.Protocol, LayerAutomata, StreamSender):
+ """
Inherit from protocol twisted class
allow this protocol to wait until expected size of packet
and use Layer automata to call next automata state
- '''
+ """
def __init__(self, mode, presentation = None):
- '''
- Constructor
- '''
+ """
+ @param mode: LayerMode use
+ @param presentation: presentation layer in layer list
+ """
#call parent automata
LayerAutomata.__init__(self, mode, presentation)
#data buffer received from twisted network layer
@@ -133,11 +140,11 @@ class RawLayer(protocol.Protocol, LayerAutomata):
self._expectedLen = 0
def dataReceived(self, data):
- '''
- inherit from protocol class
+ """
+ Inherit from protocol class
main event of received data
@param data: string data receive from twisted
- '''
+ """
#add in buffer
self._buffer += data
#while buffer have expected size call local callback
@@ -150,29 +157,29 @@ class RawLayer(protocol.Protocol, LayerAutomata):
self.recv(expectedData)
def connectionMade(self):
- '''
+ """
inherit from twisted protocol
- '''
+ """
#join two scheme
self.connect()
def expect(self, expectedLen, callback = None):
- '''
- configure layer to change next state with callback only
+ """
+ Configure layer to change next state with callback only
when expectLen bytes is received from transport layer
- @param expectedLen: in bytes len use to call nextstate
- @param callback: callback call when expectedlen bytes is received
- '''
+ @param expectedLen: in bytes length use to call next state
+ @param callback: callback call when expected length bytes is received
+ """
self._expectedLen = expectedLen
#default callback is recv from LayerAutomata
self.setNextState(callback)
def send(self, message):
- '''
- send stream on tcp layer
+ """
+ Send Stream on TCP layer
format message into raw stream understood by transport layer
@param message: (tuple | Type)
- '''
+ """
s = Stream()
s.writeType(message)
self.transport.write(s.getvalue())
\ No newline at end of file
diff --git a/rdpy/protocol/rdp/ber.py b/rdpy/protocol/rdp/ber.py
index 1300cec..5e6eabc 100644
--- a/rdpy/protocol/rdp/ber.py
+++ b/rdpy/protocol/rdp/ber.py
@@ -1,6 +1,27 @@
-'''
-@author: sylvain
-'''
+#
+# Copyright (c) 2014 Sylvain Peyrefitte
+#
+# This file is part of rdpy.
+#
+# rdpy is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+"""
+Basic Encoding Rules use in RDP.
+ASN.1 standard
+"""
+
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, String
from rdpy.network.const import ConstAttributes, TypeAttributes
from rdpy.network.error import InvalidExpectedDataException, InvalidSize
@@ -35,24 +56,24 @@ class Tag(object):
BER_TAG_SEQUENCE_OF = 0x10
def berPC(pc):
- '''
- return BER_CONSTRUCT if true
+ """
+ Return BER_CONSTRUCT if true
BER_PRIMITIVE if false
@param pc: boolean
@return: BerPc value
- '''
+ """
if pc:
return BerPc.BER_CONSTRUCT
else:
return BerPc.BER_PRIMITIVE
def readLength(s):
- '''
- read length of ber structure
+ """
+ Read length of BER structure
length be on 1 2 or 3 bytes
@param s: stream
- @return: int or python long
- '''
+ @return: int or Python long
+ """
size = None
length = UInt8()
s.readType(length)
@@ -64,50 +85,50 @@ def readLength(s):
elif byte == 2:
size = UInt16Be()
else:
- raise InvalidExpectedDataException("ber length may be 1 or 2")
+ raise InvalidExpectedDataException("BER length may be 1 or 2")
s.readType(size)
else:
size = length
return size.value
def writeLength(size):
- '''
- return strcture length as expected in Ber specification
+ """
+ Return structure length as expected in BER specification
@param size: int or python long
@return: UInt8 or (UInt8(0x82), UInt16Be)
- '''
+ """
if size > 0x7f:
return (UInt8(0x82), UInt16Be(size))
else:
return UInt8(size)
def readUniversalTag(s, tag, pc):
- '''
- read tag of ber packet
+ """
+ Read tag of BER packet
@param tag: Tag class attributes
@param pc: boolean
@return: true if tag is correctly read
- '''
+ """
byte = UInt8()
s.readType(byte)
return byte == ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag))
def writeUniversalTag(tag, pc):
- '''
- return universal tag byte
+ """
+ Return universal tag byte
@param tag: tag class attributes
@param pc: boolean
@return: UInt8
- '''
+ """
return ((Class.BER_CLASS_UNIV | berPC(pc)) | (Tag.BER_TAG_MASK & tag))
def readApplicationTag(s, tag):
- '''
- read application tag
+ """
+ Read application tag
@param s: stream
@param tag: tag class attributes
@return: length of application packet
- '''
+ """
byte = UInt8()
s.readType(byte)
if tag > UInt8(30):
@@ -123,22 +144,22 @@ def readApplicationTag(s, tag):
return readLength(s)
def writeApplicationTag(tag, size):
- '''
- return struct that represent ber application tag
+ """
+ Return structure that represent BER application tag
@param tag: UINt8
@param size: size to rest of packet
- '''
+ """
if tag > UInt8(30):
return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | Tag.BER_TAG_MASK), tag, writeLength(size))
else:
return (((Class.BER_CLASS_APPL | BerPc.BER_CONSTRUCT) | (Tag.BER_TAG_MASK & tag)), writeLength(size))
def readBoolean(s):
- '''
- return boolean
+ """
+ Return boolean
@param s: stream
@return: boolean
- '''
+ """
if not readUniversalTag(s, Tag.BER_TAG_BOOLEAN, False):
raise InvalidExpectedDataException("bad boolean tag")
size = readLength(s)
@@ -149,24 +170,24 @@ def readBoolean(s):
return bool(b.value)
def writeBoolean(b):
- '''
- return structure that represent boolean in ber specification
+ """
+ Return structure that represent boolean in BER specification
@param b: boolean
- @return: ber boolean structure
- '''
+ @return: BER boolean structure
+ """
boolean = UInt8(0)
if b:
boolean = UInt8(0xff)
return (writeUniversalTag(Tag.BER_TAG_BOOLEAN, False), writeLength(1), boolean)
def readInteger(s):
- '''
- read integer structure from stream
+ """
+ Read integer structure from stream
@param s: stream
@return: int or long python
- '''
+ """
if not readUniversalTag(s, Tag.BER_TAG_INTEGER, False):
- raise InvalidExpectedDataException("bad integer tag")
+ raise InvalidExpectedDataException("Bad integer tag")
size = readLength(s)
@@ -189,14 +210,14 @@ def readInteger(s):
s.readType(integer)
return integer.value
else:
- raise InvalidExpectedDataException("wrong integer size")
+ raise InvalidExpectedDataException("Wrong integer size")
def writeInteger(value):
- '''
- write integer value
+ """
+ Write integer value
@param param: int or python long
- @return ber interger structure
- '''
+ @return: BER integer structure
+ """
if value <= 0xff:
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(1), UInt8(value))
elif value <= 0xffff:
@@ -205,30 +226,30 @@ def writeInteger(value):
return (writeUniversalTag(Tag.BER_TAG_INTEGER, False), writeLength(4), UInt32Be(value))
def readOctetString(s):
- '''
- read ber string structure
+ """
+ Read BER string structure
@param s: stream
@return: String
- '''
+ """
if not readUniversalTag(s, Tag.BER_TAG_OCTET_STRING, False):
- raise InvalidExpectedDataException("unexpected ber tag")
+ raise InvalidExpectedDataException("Unexpected BER tag")
size = readLength(s)
return String(s.read(size.value))
def writeOctetstring(value):
- '''
- write string in ber representation
+ """
+ Write string in ber representation
@param value: string
@return: string ber structure
- '''
+ """
return (writeUniversalTag(Tag.BER_TAG_OCTET_STRING, False), writeLength(len(value)), String(value))
def readEnumerated(s):
- '''
- read enumerated structure
+ """
+ Read enumerated structure
@param s: Stream
@return: int or long
- '''
+ """
if not readUniversalTag(s, Tag.BER_TAG_ENUMERATED, False):
raise InvalidExpectedDataException("invalid ber tag")
if readLength(s) != 1:
diff --git a/rdpy/protocol/rdp/mcs.py b/rdpy/protocol/rdp/mcs.py
index b0f2a46..37d1afe 100644
--- a/rdpy/protocol/rdp/mcs.py
+++ b/rdpy/protocol/rdp/mcs.py
@@ -1,9 +1,32 @@
-'''
-@author: citronneur
-'''
+#
+# Copyright (c) 2014 Sylvain Peyrefitte
+#
+# This file is part of rdpy.
+#
+# rdpy is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+#
+
+"""
+Implement Multi Channel Service
+
+Each channel have a particular role.
+The main channel is the graphical channel.
+It exist channel for file system order, audio channel, clipboard etc...
+"""
from rdpy.network.const import ConstAttributes, TypeAttributes
-from rdpy.network.layer import LayerAutomata, Layer, LayerMode
+from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
from rdpy.protocol.rdp.ber import writeLength
@@ -13,18 +36,18 @@ import ber, gcc, per
@ConstAttributes
@TypeAttributes(UInt8)
class Message(object):
- '''
- message type
- '''
+ """
+ Message type
+ """
MCS_TYPE_CONNECT_INITIAL = 0x65
MCS_TYPE_CONNECT_RESPONSE = 0x66
@ConstAttributes
@TypeAttributes(UInt8)
class DomainMCSPDU:
- '''
- domain mcs pdu header
- '''
+ """
+ Domain MCS PDU header
+ """
ERECT_DOMAIN_REQUEST = 1
DISCONNECT_PROVIDER_ULTIMATUM = 8
ATTACH_USER_REQUEST = 10
@@ -37,27 +60,28 @@ class DomainMCSPDU:
@ConstAttributes
@TypeAttributes(UInt16Be)
class Channel:
+ """
+ Channel id of main channels use in RDP
+ """
MCS_GLOBAL_CHANNEL = 1003
MCS_USERCHANNEL_BASE = 1001
class MCS(LayerAutomata):
- '''
+ """
Multi Channel Service layer
the main layer of RDP protocol
is why he can do everything and more!
- '''
-
- class MCSProxySender(Layer):
- '''
- Proxy use to set as trnsport layer for upper channel
+ """
+ class MCSProxySender(StreamSender):
+ """
+ Proxy use to set as transport layer for upper channel
use to abstract channel id for presentation layer
- '''
+ """
def __init__(self, mcs, channelId):
- '''
- ctor
- @param mcs: mcs layer use as proxy
+ """
+ @param mcs: MCS layer use as proxy
@param channelId: channel id for presentation layer
- '''
+ """
self._mcs = mcs
self._channelId = channelId
@@ -94,11 +118,10 @@ class MCS(LayerAutomata):
def __init__(self, mode, presentation):
- '''
- ctor call base class ctor
- @param mode: mode of mcs layer
+ """
+ @param mode: mode of MCS layer
@param presentation: presentation layer
- '''
+ """
LayerAutomata.__init__(self, mode, presentation)
self._clientSettings = gcc.ClientSettings()
self._serverSettings = gcc.ServerSettings()
@@ -110,17 +133,17 @@ class MCS(LayerAutomata):
self._channelIdsRequest = {}
def connect(self):
- '''
- connection send for client mode
+ """
+ Connection send for client mode
a write connect initial packet
- '''
+ """
self._clientSettings.core.serverSelectedProtocol = self._transport._selectedProtocol
self.sendConnectInitial()
def connectNextChannel(self):
- '''
- send sendChannelJoinRequest message on next unconnect channel
- '''
+ """
+ Send sendChannelJoinRequest message on next unconnect channel
+ """
for (channelId, layer) in self._channelIds.iteritems():
#for each unconnect channel send a request
if not self._channelIdsRequest.has_key(channelId):
@@ -138,9 +161,9 @@ class MCS(LayerAutomata):
layer.connect()
def sendConnectInitial(self):
- '''
- send connect initial packet
- '''
+ """
+ Send connect initial packet
+ """
ccReq = gcc.writeConferenceCreateRequest(self._clientSettings)
ccReqStream = Stream()
ccReqStream.writeType(ccReq)
@@ -155,28 +178,28 @@ class MCS(LayerAutomata):
self.setNextState(self.recvConnectResponse)
def sendErectDomainRequest(self):
- '''
- send a formated erect domain request for RDP connection
- '''
+ """
+ Send a formated erect domain request for RDP connection
+ """
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.ERECT_DOMAIN_REQUEST), per.writeInteger(0), per.writeInteger(0)))
def sendAttachUserRequest(self):
- '''
- send a formated attach user request for RDP connection
- '''
+ """
+ Send a formated attach user request for RDP connection
+ """
self._transport.send(self.writeMCSPDUHeader(DomainMCSPDU.ATTACH_USER_REQUEST))
def sendChannelJoinRequest(self, channelId):
- '''
- send a formated Channel join request from client to server
- '''
+ """
+ Send a formated Channel join request from client to server
+ """
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.CHANNEL_JOIN_REQUEST), self._userId, channelId))
def recvConnectResponse(self, data):
- '''
- receive mcs connect response from server
+ """
+ receive MCS connect response from server
@param data: Stream
- '''
+ """
ber.readApplicationTag(data, Message.MCS_TYPE_CONNECT_RESPONSE)
ber.readEnumerated(data)
ber.readInteger(data)
@@ -196,10 +219,10 @@ class MCS(LayerAutomata):
self.setNextState(self.recvAttachUserConfirm)
def recvAttachUserConfirm(self, data):
- '''
- receive an attach user confirm
+ """
+ Receive an attach user confirm
@param data: Stream
- '''
+ """
opcode = UInt8()
confirm = UInt8()
data.readType((opcode, confirm))
@@ -217,10 +240,10 @@ class MCS(LayerAutomata):
self.connectNextChannel()
def recvChannelJoinConfirm(self, data):
- '''
- receive a channel join confirm from server
+ """
+ Receive a channel join confirm from server
@param data: Stream
- '''
+ """
opcode = UInt8()
confirm = UInt8()
data.readType((opcode, confirm))
@@ -239,10 +262,10 @@ class MCS(LayerAutomata):
self.connectNextChannel()
def recvData(self, data):
- '''
- main receive method
+ """
+ Main receive method
@param data: Stream
- '''
+ """
opcode = UInt8()
data.readType(opcode)
@@ -278,51 +301,52 @@ class MCS(LayerAutomata):
self._channelIds[channelId].recv(data)
def send(self, channelId, data):
- '''
- specific send function for channelId
+ """
+ Specific send function for channelId
+ @param channelId: Channel use to send
@param data: message to send
- '''
+ """
self._transport.send((self.writeMCSPDUHeader(DomainMCSPDU.SEND_DATA_REQUEST), self._userId, channelId, UInt8(0x70), UInt16Be(sizeof(data)) | UInt16Be(0x8000), data))
def writeDomainParams(self, maxChannels, maxUsers, maxTokens, maxPduSize):
- '''
- write a special domain param structure
+ """
+ Write a special domain parameter structure
use in connection sequence
- @param maxChannels: number of mcs channel use
- @param maxUsers: number of mcs user used (1)
+ @param maxChannels: number of MCS channel use
+ @param maxUsers: number of MCS user used (1)
@param maxTokens: unknown
@param maxPduSize: unknown
- @return: domain param structure
- '''
+ @return: domain parameter structure
+ """
domainParam = (ber.writeInteger(maxChannels), ber.writeInteger(maxUsers), ber.writeInteger(maxTokens),
ber.writeInteger(1), ber.writeInteger(0), ber.writeInteger(1),
ber.writeInteger(maxPduSize), ber.writeInteger(2))
return (ber.writeUniversalTag(ber.Tag.BER_TAG_SEQUENCE, True), writeLength(sizeof(domainParam)), domainParam)
def writeMCSPDUHeader(self, mcsPdu, options = 0):
- '''
- write mcs pdu header
- @param mcsPdu: pdu code
+ """
+ Write MCS PDU header
+ @param mcsPdu: PDU code
@param options: option contains in header
@return: UInt8
- '''
+ """
return (mcsPdu << 2) | options
def readMCSPDUHeader(self, opcode, mcsPdu):
- '''
- read mcsPdu header and return options parameter
+ """
+ Read mcsPdu header and return options parameter
@param opcode: UInt8 opcode
@param mcsPdu: mcsPdu will be checked
@return: true if opcode is correct
- '''
+ """
return (opcode >> 2) == mcsPdu
def readDomainParams(self, s):
- '''
- read domain params structure
+ """
+ Read domain parameters structure
@return: (max_channels, max_users, max_tokens, max_pdu_size)
- '''
+ """
if not ber.readUniversalTag(s, ber.Tag.BER_TAG_SEQUENCE, True):
raise InvalidValue("bad BER tags")
ber.readLength(s)#length
diff --git a/rdpy/protocol/rdp/pdu.py b/rdpy/protocol/rdp/pdu.py
index f5a0a8a..60323df 100644
--- a/rdpy/protocol/rdp/pdu.py
+++ b/rdpy/protocol/rdp/pdu.py
@@ -2,16 +2,12 @@
@author: citronneur
'''
-from rdpy.network.layer import LayerAutomata, LayerMode
-from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType,\
- FactoryType
+from rdpy.network.layer import LayerAutomata
+from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType, FactoryType
from rdpy.network.const import ConstAttributes, TypeAttributes
from rdpy.network.error import InvalidExpectedDataException, ErrorReportedFromPeer
-import gcc
-import lic
-import caps
-import rdp
+import gcc, lic, caps
@ConstAttributes
@TypeAttributes(UInt16Le)
diff --git a/rdpy/protocol/rdp/rdp.py b/rdpy/protocol/rdp/rdp.py
index 7d21a2e..4735a26 100644
--- a/rdpy/protocol/rdp/rdp.py
+++ b/rdpy/protocol/rdp/rdp.py
@@ -2,8 +2,8 @@
@author: sylvain
'''
from twisted.internet import protocol
-import tpkt, tpdu, mcs, pdu
from rdpy.network.layer import LayerMode
+import tpkt, tpdu, mcs, pdu
class RDPController(object):
"""
diff --git a/rdpy/protocol/rdp/tpdu.py b/rdpy/protocol/rdp/tpdu.py
index f124fcd..31a3658 100644
--- a/rdpy/protocol/rdp/tpdu.py
+++ b/rdpy/protocol/rdp/tpdu.py
@@ -24,7 +24,7 @@ This layer have main goal to negociate ssl transport
RDP basic security is not supported by RDPY (because is not a true security layer...)
"""
-from rdpy.network.layer import LayerAutomata, LayerMode
+from rdpy.network.layer import LayerAutomata, LayerMode, StreamSender
from rdpy.network.type import UInt8, UInt16Le, UInt16Be, UInt32Le, CompositeType, sizeof
from rdpy.network.error import InvalidExpectedDataException
from rdpy.network.const import ConstAttributes, TypeAttributes
@@ -116,7 +116,7 @@ class Negotiation(CompositeType):
self.selectedProtocol = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_RSP)
self.failureCode = UInt32Le(conditional = lambda: self.code == NegociationType.TYPE_RDP_NEG_FAILURE)
-class TPDU(LayerAutomata):
+class TPDU(LayerAutomata, StreamSender):
"""
TPDU layer management
there is an connection automata
@@ -223,7 +223,7 @@ class TPDU(LayerAutomata):
"""
header = TPDUDataHeader()
data.readType(header)
- LayerAutomata.recv(self, data)
+ self._presentation.recv(data)
def sendConnectionRequest(self):
"""