code refactoring
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
*.pyc
|
||||
.project
|
||||
.pydevproject
|
||||
README.md~
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# RDPY
|
||||
|
||||
## Remote Desktop Protoc in Python
|
||||
Remote Desktop Protocol in Twisted Python
|
||||
|
||||
## Requirements
|
||||
* python2.7
|
||||
|
||||
13
README.md~
13
README.md~
@@ -1,13 +0,0 @@
|
||||
# RDPY
|
||||
|
||||
## Remote Desktop Protoc in Python
|
||||
|
||||
## Requirements
|
||||
* python2.7
|
||||
* python-twisted
|
||||
|
||||
## Requirements for examples
|
||||
* python-qt4
|
||||
* python-qt4reactor
|
||||
|
||||
this project is still in progress.
|
||||
@@ -2,22 +2,15 @@
|
||||
@author: sylvain
|
||||
'''
|
||||
from PyQt4 import QtGui, QtCore
|
||||
from rdpy.protocol.rfb.rfb import RfbObserver
|
||||
from rdpy.protocol.rdp.rdp import RDPObserver
|
||||
from rdpy.protocol.rfb.rfb import RFBClientObserver
|
||||
from rdpy.protocol.rdp.rdp import RDPClientObserver
|
||||
from rdpy.network.error import UnRegistredObject
|
||||
|
||||
class QAdaptor(object):
|
||||
'''
|
||||
adaptor model with link beetween protocol
|
||||
adaptor model with link between protocol
|
||||
and qt widget
|
||||
'''
|
||||
def __init__(self, qRemoteDesktop):
|
||||
'''
|
||||
constructor
|
||||
must set qRemoteDesktop attribute
|
||||
'''
|
||||
#qwidget use for render
|
||||
self._qRemoteDesktop = qRemoteDesktop
|
||||
self._qRemoteDesktop._adaptor = self
|
||||
|
||||
def sendMouseEvent(self, e):
|
||||
'''
|
||||
@@ -35,30 +28,32 @@ class QAdaptor(object):
|
||||
'''
|
||||
pass
|
||||
|
||||
class RfbAdaptor(RfbObserver, QAdaptor):
|
||||
def getWidget(self):
|
||||
'''
|
||||
@return: widget use for render
|
||||
'''
|
||||
pass
|
||||
|
||||
class RFBClientQt(RFBClientObserver, QAdaptor):
|
||||
'''
|
||||
QAdaptor for specific RFB protocol stack
|
||||
is to an RFB observer
|
||||
'''
|
||||
def __init__(self, qRemoteDesktop):
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor
|
||||
@param qRemoteDesktop: widget use for render
|
||||
'''
|
||||
QAdaptor.__init__(self, qRemoteDesktop)
|
||||
self._rfb = None
|
||||
self._widget = QRemoteDesktop(self)
|
||||
|
||||
def setProtocol(self, rfb):
|
||||
def getWidget(self):
|
||||
'''
|
||||
inherit from RfbObserver
|
||||
init protocol settings
|
||||
@return: widget use for render
|
||||
'''
|
||||
#set RFB observer to
|
||||
self._rfb = rfb
|
||||
return self._widget
|
||||
|
||||
def notifyFramebufferUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
def onUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
'''
|
||||
implement RfbAdaptor interface
|
||||
implement RFBClientObserver interface
|
||||
@param width: width of new image
|
||||
@param height: height of new image
|
||||
@param x: x position of new image
|
||||
@@ -75,44 +70,47 @@ class RfbAdaptor(RfbObserver, QAdaptor):
|
||||
return
|
||||
|
||||
image = QtGui.QImage(data, width, height, imageFormat)
|
||||
self._qRemoteDesktop.notifyImage(x, y, image)
|
||||
self._widget.notifyImage(x, y, image)
|
||||
|
||||
def sendMouseEvent(self, e):
|
||||
'''
|
||||
convert qt mouse event to rfb mouse event
|
||||
send mouse event to rfb protocol stack
|
||||
convert qt mouse event to RFB mouse event
|
||||
@param e: qMouseEvent
|
||||
'''
|
||||
button = e.button()
|
||||
mask = 0
|
||||
buttonNumber = 0
|
||||
if button == QtCore.Qt.LeftButton:
|
||||
mask = 1
|
||||
buttonNumber = 1
|
||||
elif button == QtCore.Qt.MidButton:
|
||||
mask = 1 << 1
|
||||
buttonNumber = 2
|
||||
elif button == QtCore.Qt.RightButton:
|
||||
mask = 1 << 2
|
||||
self._rfb.sendPointerEvent(mask, e.pos().x(), e.pos().y())
|
||||
buttonNumber = 3
|
||||
self.mouseEvent(buttonNumber, e.pos().x(), e.pos().y())
|
||||
|
||||
def sendKeyEvent(self, e):
|
||||
'''
|
||||
convert qt key press event to rfb press event
|
||||
send key event to protocol stack
|
||||
convert Qt key press event to RFB press event
|
||||
@param e: qKeyEvent
|
||||
'''
|
||||
self._rfb.sendKeyEvent(True, e.nativeVirtualKey())
|
||||
self.keyEvent(True, e.nativeVirtualKey())
|
||||
|
||||
class RDPAdaptor(RDPObserver, QAdaptor):
|
||||
class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
'''
|
||||
Adaptor for RDP client
|
||||
'''
|
||||
def __init__(self, qRemoteDesktop):
|
||||
def __init__(self):
|
||||
'''
|
||||
constructor
|
||||
@param qRemoteDesktop: widget use for render
|
||||
'''
|
||||
QAdaptor.__init__(self, qRemoteDesktop)
|
||||
self._widget = QRemoteDesktop(self)
|
||||
|
||||
def notifyBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
||||
def getWidget(self):
|
||||
'''
|
||||
@return: widget use for render
|
||||
'''
|
||||
return self._widget
|
||||
|
||||
def onBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
||||
'''
|
||||
notify bitmap update
|
||||
@param destLeft: xmin position
|
||||
@@ -141,19 +139,20 @@ class RDPAdaptor(RDPObserver, QAdaptor):
|
||||
return
|
||||
|
||||
image = QtGui.QImage(data, width, height, imageFormat)
|
||||
self._qRemoteDesktop.notifyImage(destLeft, destTop, image)
|
||||
self._widget.notifyImage(destLeft, destTop, image)
|
||||
|
||||
|
||||
class QRemoteDesktop(QtGui.QWidget):
|
||||
'''
|
||||
qt display widget
|
||||
'''
|
||||
def __init__(self):
|
||||
def __init__(self, adaptor):
|
||||
'''
|
||||
constructor
|
||||
'''
|
||||
super(QRemoteDesktop, self).__init__()
|
||||
#set by adaptor
|
||||
self._adaptor = None
|
||||
#adaptor use to send
|
||||
self._adaptor = adaptor
|
||||
#refresh stack of image
|
||||
#because we can update image only in paint
|
||||
#event function. When protocol receive image
|
||||
@@ -208,7 +207,8 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@param event: qMouseEvent
|
||||
'''
|
||||
if self._adaptor is None:
|
||||
print "No adaptor to send mouse press event"
|
||||
raise UnRegistredObject("No adaptor to send mouse press event")
|
||||
|
||||
self._adaptor.sendMouseEvent(event)
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
@@ -217,5 +217,7 @@ class QRemoteDesktop(QtGui.QWidget):
|
||||
@param event: qKeyEvent
|
||||
'''
|
||||
if self._adaptor is None:
|
||||
print "No adaptor to send key press event"
|
||||
raise UnRegistredObject("No adaptor to send key press event")
|
||||
|
||||
self._adaptor.sendKeyEvent(event)
|
||||
|
||||
@@ -3,4 +3,23 @@
|
||||
@file: implement run length encoding algorithm use in RDP protocol to compress bit
|
||||
@see: http://msdn.microsoft.com/en-us/library/dd240593.aspx
|
||||
'''
|
||||
from rdpy.network.type import UInt8
|
||||
|
||||
def extractCodeId(data):
|
||||
'''
|
||||
Read first unsigned char
|
||||
'''
|
||||
res = UInt8()
|
||||
data.readType(res)
|
||||
return res
|
||||
|
||||
def decode(dst, src, rowDelta):
|
||||
|
||||
insertFgPel = False
|
||||
firstLine = True
|
||||
|
||||
while src.dataLen() > 0:
|
||||
if firstLine:
|
||||
firstLine = False
|
||||
insertFgPel = False
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
'''
|
||||
@author: citronneur
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
# Change path so we find rdpy
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../..'))
|
||||
|
||||
from PyQt4 import QtGui
|
||||
from rdpy.display.qt import RDPAdaptor, RfbAdaptor, QRemoteDesktop
|
||||
from rdpy.protocol.rdp import rdp
|
||||
from rdpy.protocol.rfb import rfb
|
||||
|
||||
class RDPClientQtFactory(rdp.ClientFactory):
|
||||
'''
|
||||
Factory create a RDP GUI client
|
||||
'''
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor that init qt context and protocol needed
|
||||
'''
|
||||
#create qt widget
|
||||
self._w = QRemoteDesktop()
|
||||
self._w.resize(1024, 800)
|
||||
self._w.setWindowTitle('rdpyclient-rdp')
|
||||
self._w.show()
|
||||
#build protocol
|
||||
rdp.ClientFactory.__init__(self, RDPAdaptor(self._w))
|
||||
|
||||
def startedConnecting(self, connector):
|
||||
pass
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
'''
|
||||
connection lost event
|
||||
@param connector: twisted connector use for rdp connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Lost connection : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
'''
|
||||
connection failed event
|
||||
@param connector: twisted connector use for rdp connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Connection failed : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
class RFBClientQtFactory(rfb.ClientFactory):
|
||||
'''
|
||||
Factory create a VNC GUI client
|
||||
'''
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor that init qt context and protocol needed
|
||||
'''
|
||||
#create qt widget
|
||||
self._w = QRemoteDesktop()
|
||||
self._w.resize(1024, 800)
|
||||
self._w.setWindowTitle('rdpyclient-vnc')
|
||||
self._w.show()
|
||||
|
||||
rfb.ClientFactory.__init__(self, RfbAdaptor(self._w))
|
||||
|
||||
def startedConnecting(self, connector):
|
||||
pass
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
'''
|
||||
connection lost event
|
||||
@param connector: twisted connector use for vnc connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Lost connection : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
'''
|
||||
connection failed event
|
||||
@param connector: twisted connector use for vnc connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Connection failed : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
#create application
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
|
||||
#add qt4 reactor
|
||||
import qt4reactor
|
||||
qt4reactor.install()
|
||||
|
||||
if sys.argv[3] == 'rdp':
|
||||
factory = RDPClientQtFactory()
|
||||
else:
|
||||
factory = RFBClientQtFactory()
|
||||
|
||||
from twisted.internet import reactor
|
||||
reactor.connectTCP(sys.argv[1], int(sys.argv[2]), factory)
|
||||
reactor.runReturn()
|
||||
app.exec_()
|
||||
reactor.stop()
|
||||
65
rdpy/examples/rdpclient.py
Normal file
65
rdpy/examples/rdpclient.py
Normal file
@@ -0,0 +1,65 @@
|
||||
'''
|
||||
@author: citronneur
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
# Change path so we find rdpy
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../..'))
|
||||
|
||||
from PyQt4 import QtGui
|
||||
from rdpy.display.qt import RDPClientQt
|
||||
from rdpy.protocol.rdp import rdp
|
||||
|
||||
class RDPClientQtFactory(rdp.ClientFactory):
|
||||
'''
|
||||
Factory create a RDP GUI client
|
||||
'''
|
||||
def buildObserver(self):
|
||||
'''
|
||||
build RFB observer
|
||||
'''
|
||||
#create client observer
|
||||
client = RDPClientQt()
|
||||
#create qt widget
|
||||
self._w = client.getWidget()
|
||||
self._w.resize(1024, 800)
|
||||
self._w.setWindowTitle('rdpyclient-vnc')
|
||||
self._w.show()
|
||||
return client
|
||||
|
||||
def startedConnecting(self, connector):
|
||||
pass
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
'''
|
||||
connection lost event
|
||||
@param connector: twisted connector use for rdp connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Lost connection : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
'''
|
||||
connection failed event
|
||||
@param connector: twisted connector use for rdp connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Connection failed : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
#create application
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
|
||||
#add qt4 reactor
|
||||
import qt4reactor
|
||||
qt4reactor.install()
|
||||
|
||||
from twisted.internet import reactor
|
||||
reactor.connectTCP(sys.argv[1], int(sys.argv[2]), RDPClientQtFactory())
|
||||
reactor.runReturn()
|
||||
app.exec_()
|
||||
reactor.stop()
|
||||
65
rdpy/examples/vncclient.py
Normal file
65
rdpy/examples/vncclient.py
Normal file
@@ -0,0 +1,65 @@
|
||||
'''
|
||||
@author: citronneur
|
||||
'''
|
||||
import sys
|
||||
import os
|
||||
# Change path so we find rdpy
|
||||
sys.path.insert(1, os.path.join(sys.path[0], '../..'))
|
||||
|
||||
from PyQt4 import QtGui
|
||||
from rdpy.display.qt import RFBClientQt
|
||||
from rdpy.protocol.rfb import rfb
|
||||
|
||||
class RFBClientQtFactory(rfb.ClientFactory):
|
||||
'''
|
||||
Factory create a VNC GUI client
|
||||
'''
|
||||
def buildObserver(self):
|
||||
'''
|
||||
build RFB observer
|
||||
'''
|
||||
#create client observer
|
||||
client = RFBClientQt()
|
||||
#create qt widget
|
||||
self._w = client.getWidget()
|
||||
self._w.resize(1024, 800)
|
||||
self._w.setWindowTitle('rdpyclient-vnc')
|
||||
self._w.show()
|
||||
return client
|
||||
|
||||
def startedConnecting(self, connector):
|
||||
pass
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
'''
|
||||
connection lost event
|
||||
@param connector: twisted connector use for vnc connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Lost connection : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
'''
|
||||
connection failed event
|
||||
@param connector: twisted connector use for vnc connection (use reconnect to restart connection)
|
||||
@param reason: str use to advertise reason of lost connection
|
||||
'''
|
||||
QtGui.QMessageBox.warning(self._w, "Warning", "Connection failed : %s"%reason)
|
||||
reactor.stop()
|
||||
app.exit()
|
||||
|
||||
if __name__ == '__main__':
|
||||
#create application
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
|
||||
#add qt4 reactor
|
||||
import qt4reactor
|
||||
qt4reactor.install()
|
||||
|
||||
from twisted.internet import reactor
|
||||
reactor.connectTCP(sys.argv[1], int(sys.argv[2]), RFBClientQtFactory())
|
||||
reactor.runReturn()
|
||||
app.exec_()
|
||||
reactor.stop()
|
||||
@@ -67,3 +67,25 @@ class ErrorReportedFromPeer(Exception):
|
||||
@param message: message show when exception is raised
|
||||
'''
|
||||
Exception.__init__(self, message)
|
||||
|
||||
class DisconnectLayer(Exception):
|
||||
'''
|
||||
raise when try to send on unconnect layer
|
||||
'''
|
||||
def __init__(self, message = ""):
|
||||
'''
|
||||
constructor with message
|
||||
@param message: message show when exception is raised
|
||||
'''
|
||||
Exception.__init__(self, message)
|
||||
|
||||
class UnRegistredObject(Exception):
|
||||
'''
|
||||
raise when an object is not registred in other objet
|
||||
'''
|
||||
def __init__(self, message = ""):
|
||||
'''
|
||||
constructor with message
|
||||
@param message: message show when exception is raised
|
||||
'''
|
||||
Exception.__init__(self, message)
|
||||
|
||||
@@ -11,6 +11,7 @@ from rdpy.network.error import InvalidExpectedDataException, ErrorReportedFromPe
|
||||
import gcc
|
||||
import lic
|
||||
import caps
|
||||
import rdp
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt16Le)
|
||||
@@ -701,9 +702,10 @@ class PDU(LayerAutomata):
|
||||
Global channel for mcs that handle session
|
||||
identification user, licensing management, and capabilities exchange
|
||||
'''
|
||||
def __init__(self, mode, ordersManager):
|
||||
def __init__(self, mode):
|
||||
'''
|
||||
Constructor
|
||||
@param mode: LayerMode
|
||||
'''
|
||||
LayerAutomata.__init__(self, mode, None)
|
||||
#logon info send from client to server
|
||||
@@ -742,8 +744,15 @@ class PDU(LayerAutomata):
|
||||
#share id between client and server
|
||||
self._shareId = UInt32Le()
|
||||
|
||||
#rdp observer
|
||||
self._ordersManager = ordersManager
|
||||
#rdp controller
|
||||
self._controller = rdp.RDPController(self)
|
||||
|
||||
def getController(self):
|
||||
'''
|
||||
Getter for RDP controller
|
||||
@return: return rdp controller
|
||||
'''
|
||||
return self._controller
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
@@ -871,7 +880,7 @@ class PDU(LayerAutomata):
|
||||
'''
|
||||
dataPDU = self.readDataPDU(data)
|
||||
if dataPDU.shareDataHeader.pduType2 == PDUType2.PDUTYPE2_UPDATE and dataPDU.pduData._value.updateType == UpdateType.UPDATETYPE_BITMAP:
|
||||
self._ordersManager.recvBitmapUpdateDataPDU(dataPDU.pduData._value.updateData._value)
|
||||
self._controller.recvBitmapUpdateDataPDU(dataPDU.pduData._value.updateData._value)
|
||||
|
||||
|
||||
def sendConfirmActivePDU(self):
|
||||
|
||||
@@ -5,16 +5,18 @@ from twisted.internet import protocol
|
||||
import tpkt, tpdu, mcs, pdu
|
||||
from rdpy.network.layer import LayerMode
|
||||
|
||||
class RDPOrdersManager(object):
|
||||
class RDPController(object):
|
||||
'''
|
||||
use to decode and dispatch to observer PDU messages and orders
|
||||
'''
|
||||
def __init__(self):
|
||||
def __init__(self, pduLayer):
|
||||
'''
|
||||
ctor
|
||||
'''
|
||||
#list of observer
|
||||
self._observers = []
|
||||
#transport layer
|
||||
self._pduLayer = pduLayer
|
||||
|
||||
def addObserver(self, observer):
|
||||
'''
|
||||
@@ -22,6 +24,7 @@ class RDPOrdersManager(object):
|
||||
@param observer: new observer to add
|
||||
'''
|
||||
self._observers.append(observer)
|
||||
observer._controller = self
|
||||
|
||||
def recvBitmapUpdateDataPDU(self, bitmapUpdateData):
|
||||
'''
|
||||
@@ -31,32 +34,39 @@ class RDPOrdersManager(object):
|
||||
for observer in self._observers:
|
||||
#for each rectangle in update PDU
|
||||
for rectangle in bitmapUpdateData.rectangles._array:
|
||||
observer.notifyBitmapUpdate(rectangle.destLeft.value, rectangle.destTop.value, rectangle.destRight.value, rectangle.destBottom.value, rectangle.width.value, rectangle.height.value, rectangle.bitsPerPixel.value, (rectangle.flags & pdu.BitmapFlag.BITMAP_COMPRESSION).value, rectangle.bitmapDataStream.value)
|
||||
observer.onBitmapUpdate(rectangle.destLeft.value, rectangle.destTop.value, rectangle.destRight.value, rectangle.destBottom.value, rectangle.width.value, rectangle.height.value, rectangle.bitsPerPixel.value, (rectangle.flags & pdu.BitmapFlag.BITMAP_COMPRESSION).value, rectangle.bitmapDataStream.value)
|
||||
|
||||
class ClientFactory(protocol.Factory):
|
||||
'''
|
||||
Factory of Client RDP protocol
|
||||
'''
|
||||
def __init__(self, observer):
|
||||
'''
|
||||
ctor
|
||||
@param observer: observer use by rdp protocol to handle events must implement RDPObserver
|
||||
'''
|
||||
self._observer = observer
|
||||
|
||||
def buildProtocol(self, addr):
|
||||
'''
|
||||
Function call from twisted and build rdp protocol stack
|
||||
@param addr: destination address
|
||||
'''
|
||||
rdpOrdersManager = RDPOrdersManager()
|
||||
rdpOrdersManager.addObserver(self._observer)
|
||||
return tpkt.TPKT(tpdu.TPDU(mcs.MCS(pdu.PDU(LayerMode.CLIENT, rdpOrdersManager))));
|
||||
pduLayer = pdu.PDU(LayerMode.CLIENT)
|
||||
pduLayer.getController().addObserver(self.buildObserver())
|
||||
return tpkt.TPKT(tpdu.TPDU(mcs.MCS(pduLayer)));
|
||||
|
||||
class RDPObserver(object):
|
||||
def buildObserver(self):
|
||||
'''
|
||||
build observer use for connection
|
||||
'''
|
||||
pass
|
||||
|
||||
|
||||
class RDPClientObserver(object):
|
||||
'''
|
||||
class use to inform all rdp event handle by RDPY
|
||||
'''
|
||||
def notifyBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor
|
||||
'''
|
||||
self._controller = None
|
||||
|
||||
def onBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
||||
'''
|
||||
notify bitmap update
|
||||
@param destLeft: xmin position
|
||||
|
||||
@@ -5,6 +5,7 @@ from twisted.internet import protocol
|
||||
from rdpy.network.layer import RawLayer, LayerMode
|
||||
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.network.error import UnRegistredObject, InvalidValue
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(String)
|
||||
@@ -80,7 +81,6 @@ class PixelFormat(CompositeType):
|
||||
self.BlueShift = UInt8(0)
|
||||
self.padding = (UInt16Be(), UInt8())
|
||||
|
||||
|
||||
class ServerInit(CompositeType):
|
||||
'''
|
||||
server init structure
|
||||
@@ -121,21 +121,21 @@ class KeyEvent(CompositeType):
|
||||
'''
|
||||
key event structure message
|
||||
'''
|
||||
def __init__(self, downFlag = False, key = 0):
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.downFlag = UInt8(downFlag)
|
||||
self.downFlag = UInt8(False)
|
||||
self.padding = UInt16Be()
|
||||
self.key = UInt32Be(key)
|
||||
self.key = UInt32Be()
|
||||
|
||||
class PointerEvent(CompositeType):
|
||||
'''
|
||||
pointer event structure message
|
||||
'''
|
||||
def __init__(self, mask = 0, x = 0, y = 0):
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.mask = UInt8(mask)
|
||||
self.x = UInt16Be(x)
|
||||
self.y = UInt16Be(y)
|
||||
self.mask = UInt8()
|
||||
self.x = UInt16Be()
|
||||
self.y = UInt16Be()
|
||||
|
||||
class ClientCutText(CompositeType):
|
||||
'''
|
||||
@@ -152,9 +152,10 @@ class Rfb(RawLayer):
|
||||
implements rfb protocol
|
||||
'''
|
||||
|
||||
def __init__(self, mode, ordersManager):
|
||||
def __init__(self, mode):
|
||||
'''
|
||||
constructor
|
||||
@param mode: LayerMode client or server
|
||||
'''
|
||||
RawLayer.__init__(self, mode)
|
||||
#usefull for rfb protocol
|
||||
@@ -177,14 +178,14 @@ class Rfb(RawLayer):
|
||||
#current rectangle header
|
||||
self._currentRect = Rectangle()
|
||||
#client or server adaptor
|
||||
self._ordersManager = ordersManager
|
||||
self._controller = RFBController(self)
|
||||
|
||||
def addObserver(self, observer):
|
||||
def getController(self):
|
||||
'''
|
||||
add observer for input/ouput events
|
||||
@param observer: RfbObserver interface implementation
|
||||
Getter for controller
|
||||
@return: RFBController use by rfb layer
|
||||
'''
|
||||
self._observer.append(observer)
|
||||
return self._controller
|
||||
|
||||
def expectWithHeader(self, expectedHeaderLen, callbackBody):
|
||||
'''
|
||||
@@ -355,7 +356,7 @@ class Rfb(RawLayer):
|
||||
'''
|
||||
read body of rect
|
||||
'''
|
||||
self._ordersManager.recvRectangle(self._currentRect, self._pixelFormat, data.getvalue())
|
||||
self._controller.recvRectangle(self._currentRect, self._pixelFormat, data.getvalue())
|
||||
|
||||
self._nbRect = self._nbRect - 1
|
||||
#if there is another rect to read
|
||||
@@ -392,17 +393,19 @@ class Rfb(RawLayer):
|
||||
'''
|
||||
self.send((ClientToServerMessages.FRAME_BUFFER_UPDATE_REQUEST, FrameBufferUpdateRequest(incremental, x, y, width, height)))
|
||||
|
||||
def sendKeyEvent(self, downFlag, key):
|
||||
def sendKeyEvent(self, keyEvent):
|
||||
'''
|
||||
write key event packet
|
||||
@param keyEvent: KeyEvent struct to send
|
||||
'''
|
||||
self.send((ClientToServerMessages.KEY_EVENT, KeyEvent(downFlag, key)))
|
||||
self.send((ClientToServerMessages.KEY_EVENT, keyEvent))
|
||||
|
||||
def sendPointerEvent(self, mask, x, y):
|
||||
def sendPointerEvent(self, pointerEvent):
|
||||
'''
|
||||
write pointer event packet
|
||||
@param pointerEvent: PointerEvent struct use
|
||||
'''
|
||||
self.send((ClientToServerMessages.POINTER_EVENT, PointerEvent(mask, x, y)))
|
||||
self.send((ClientToServerMessages.POINTER_EVENT, pointerEvent))
|
||||
|
||||
def sendClientCutText(self, text):
|
||||
'''
|
||||
@@ -410,15 +413,18 @@ class Rfb(RawLayer):
|
||||
'''
|
||||
self.send((ClientToServerMessages.CUT_TEXT, ClientCutText(text)))
|
||||
|
||||
class RFBOrderManager(object):
|
||||
class RFBController(object):
|
||||
'''
|
||||
class use to manage rfb order and dispatch throw observers
|
||||
'''
|
||||
def __init__(self):
|
||||
def __init__(self, rfbLayer):
|
||||
'''
|
||||
ctor
|
||||
@param rfbLayer: network layer
|
||||
'''
|
||||
self._observers = []
|
||||
#rfb layer to send client orders
|
||||
self._rfbLayer = rfbLayer
|
||||
|
||||
def addObserver(self, observer):
|
||||
'''
|
||||
@@ -426,44 +432,111 @@ class RFBOrderManager(object):
|
||||
@param observer: new observer
|
||||
'''
|
||||
self._observers.append(observer)
|
||||
observer._controller = self
|
||||
|
||||
def recvRectangle(self, rectangle, pixelFormat, data):
|
||||
'''
|
||||
receive rectangle order
|
||||
Main update order type
|
||||
@param rectangle: Rectangle type header of packet
|
||||
@param pixelFormat: pixelFormat struct of current session
|
||||
@param data: image data
|
||||
'''
|
||||
for observer in self._observers:
|
||||
observer.notifyFramebufferUpdate(rectangle.width.value, rectangle.height.value, rectangle.x.value, rectangle.y.value, self._pixelFormat, rectangle.encoding, data)
|
||||
observer.onUpdate(rectangle.width.value, rectangle.height.value, rectangle.x.value, rectangle.y.value, pixelFormat, rectangle.encoding, data)
|
||||
|
||||
def sendKeyEvent(self, isDown, key):
|
||||
'''
|
||||
send a key event throw RFB protocol
|
||||
@param isDown: boolean notify if key is pressed or not (True if key is pressed)
|
||||
@param key: ascii code of key
|
||||
'''
|
||||
try:
|
||||
event = KeyEvent()
|
||||
event.downFlag.value = isDown
|
||||
event.key.value = key
|
||||
|
||||
self._rfbLayer.sendKeyEvent(event)
|
||||
except InvalidValue:
|
||||
print "Try to send an invalid key event"
|
||||
|
||||
def sendPointerEvent(self, mask, x, y):
|
||||
'''
|
||||
Send an pointer event throw RFB protocol
|
||||
@param mask: mask of button if button 1 and 3 are pressed then mask is 00000101
|
||||
@param x: x coordinate of mouse pointer
|
||||
@param y: y pointer of mouse pointer
|
||||
'''
|
||||
try:
|
||||
event = PointerEvent()
|
||||
event.mask.value = mask
|
||||
event.x.value = x
|
||||
event.y.value = y
|
||||
|
||||
self._rfbLayer.sendPointerEvent(event)
|
||||
except InvalidValue:
|
||||
print "Try to send an invalid pointer event"
|
||||
|
||||
|
||||
class ClientFactory(protocol.Factory):
|
||||
'''
|
||||
Factory of RFB protocol
|
||||
'''
|
||||
def __init__(self, observer):
|
||||
'''
|
||||
save mode and adapter
|
||||
@param adapter: graphic client adapter
|
||||
'''
|
||||
self._observer = observer
|
||||
|
||||
def buildProtocol(self, addr):
|
||||
'''
|
||||
function call by twisted on connection
|
||||
@param addr: adress where client try to connect
|
||||
@param addr: address where client try to connect
|
||||
'''
|
||||
orderManager = RFBOrderManager()
|
||||
orderManager.addObserver(self._observer)
|
||||
protocol = Rfb(LayerMode.CLIENT, orderManager)
|
||||
self._observer.setProtocol(protocol)
|
||||
protocol = Rfb(LayerMode.CLIENT)
|
||||
protocol.getController().addObserver(self.buildObserver())
|
||||
return protocol
|
||||
|
||||
class RfbObserver(object):
|
||||
def buildObserver(self):
|
||||
'''
|
||||
Rfb protocol obserser
|
||||
build an RFB observer object
|
||||
'''
|
||||
def notifyFramebufferUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
pass
|
||||
|
||||
|
||||
class RFBClientObserver(object):
|
||||
'''
|
||||
RFB client protocol observer
|
||||
'''
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor
|
||||
'''
|
||||
self._controller = None
|
||||
|
||||
def keyEvent(self, isPressed, key):
|
||||
'''
|
||||
send a key event
|
||||
@param isPressed: state of key
|
||||
@param key: ascii code of key
|
||||
'''
|
||||
if self._controller is None:
|
||||
raise UnRegistredObject("RFBClientObserver need to be registred to a RFBController object")
|
||||
|
||||
self._controller.sendKeyEvent(isPressed, key)
|
||||
|
||||
def mouseEvent(self, button, x, y):
|
||||
'''
|
||||
send a mouse event to RFB Layer
|
||||
@param button: button number which is pressed (0,1,2,3,4,5,6,7,8)
|
||||
@param x: x coordinate of mouse pointer
|
||||
@param y: y coordinate of mouse pointer
|
||||
'''
|
||||
if self._controller is None:
|
||||
raise UnRegistredObject("RFBClientObserver need to be registred to a RFBController object")
|
||||
mask = 0
|
||||
if button == 1:
|
||||
mask = 1
|
||||
elif button > 1:
|
||||
mask = 1 << button - 1
|
||||
|
||||
self._controller.sendPointerEvent(mask, x, y)
|
||||
|
||||
def onUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
'''
|
||||
recv framebuffer update
|
||||
@param width : width of image
|
||||
@@ -475,10 +548,3 @@ class RfbObserver(object):
|
||||
@param data : in respect of dataFormat and pixelFormat
|
||||
'''
|
||||
pass
|
||||
|
||||
def setProtocol(self, rfbLayer):
|
||||
'''
|
||||
call when observer is added to an rfb layer
|
||||
@param: rfbLayer layer inform the observer
|
||||
'''
|
||||
pass
|
||||
Reference in New Issue
Block a user