code refactoring
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
.project
|
.project
|
||||||
.pydevproject
|
.pydevproject
|
||||||
|
README.md~
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# RDPY
|
# RDPY
|
||||||
|
|
||||||
## Remote Desktop Protoc in Python
|
Remote Desktop Protocol in Twisted Python
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
* python2.7
|
* 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
|
@author: sylvain
|
||||||
'''
|
'''
|
||||||
from PyQt4 import QtGui, QtCore
|
from PyQt4 import QtGui, QtCore
|
||||||
from rdpy.protocol.rfb.rfb import RfbObserver
|
from rdpy.protocol.rfb.rfb import RFBClientObserver
|
||||||
from rdpy.protocol.rdp.rdp import RDPObserver
|
from rdpy.protocol.rdp.rdp import RDPClientObserver
|
||||||
|
from rdpy.network.error import UnRegistredObject
|
||||||
|
|
||||||
class QAdaptor(object):
|
class QAdaptor(object):
|
||||||
'''
|
'''
|
||||||
adaptor model with link beetween protocol
|
adaptor model with link between protocol
|
||||||
and qt widget
|
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):
|
def sendMouseEvent(self, e):
|
||||||
'''
|
'''
|
||||||
@@ -34,38 +27,40 @@ class QAdaptor(object):
|
|||||||
@param e: qEvent
|
@param e: qEvent
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def getWidget(self):
|
||||||
|
'''
|
||||||
|
@return: widget use for render
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
class RfbAdaptor(RfbObserver, QAdaptor):
|
class RFBClientQt(RFBClientObserver, QAdaptor):
|
||||||
'''
|
'''
|
||||||
QAdaptor for specific RFB protocol stack
|
QAdaptor for specific RFB protocol stack
|
||||||
is to an RFB observer
|
is to an RFB observer
|
||||||
'''
|
'''
|
||||||
def __init__(self, qRemoteDesktop):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
ctor
|
ctor
|
||||||
@param qRemoteDesktop: widget use for render
|
|
||||||
'''
|
'''
|
||||||
QAdaptor.__init__(self, qRemoteDesktop)
|
self._widget = QRemoteDesktop(self)
|
||||||
self._rfb = None
|
|
||||||
|
|
||||||
def setProtocol(self, rfb):
|
def getWidget(self):
|
||||||
'''
|
'''
|
||||||
inherit from RfbObserver
|
@return: widget use for render
|
||||||
init protocol settings
|
|
||||||
'''
|
'''
|
||||||
#set RFB observer to
|
return self._widget
|
||||||
self._rfb = rfb
|
|
||||||
|
|
||||||
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 width: width of new image
|
||||||
@param height: height of new image
|
@param height: height of new image
|
||||||
@param x: x position of new image
|
@param x: x position of new image
|
||||||
@param y: y position of new image
|
@param y: y position of new image
|
||||||
@param pixelFormat: pixefFormat structure in rfb.message.PixelFormat
|
@param pixelFormat: pixefFormat structure in rfb.message.PixelFormat
|
||||||
@param encoding: encoding type rfb.message.Encoding
|
@param encoding: encoding type rfb.message.Encoding
|
||||||
@param data: image data in accordance with pixelformat and encoding
|
@param data: image data in accordance with pixel format and encoding
|
||||||
'''
|
'''
|
||||||
imageFormat = None
|
imageFormat = None
|
||||||
if pixelFormat.BitsPerPixel.value == 32 and pixelFormat.RedShift.value == 16:
|
if pixelFormat.BitsPerPixel.value == 32 and pixelFormat.RedShift.value == 16:
|
||||||
@@ -75,44 +70,47 @@ class RfbAdaptor(RfbObserver, QAdaptor):
|
|||||||
return
|
return
|
||||||
|
|
||||||
image = QtGui.QImage(data, width, height, imageFormat)
|
image = QtGui.QImage(data, width, height, imageFormat)
|
||||||
self._qRemoteDesktop.notifyImage(x, y, image)
|
self._widget.notifyImage(x, y, image)
|
||||||
|
|
||||||
def sendMouseEvent(self, e):
|
def sendMouseEvent(self, e):
|
||||||
'''
|
'''
|
||||||
convert qt mouse event to rfb mouse event
|
convert qt mouse event to RFB mouse event
|
||||||
send mouse event to rfb protocol stack
|
|
||||||
@param e: qMouseEvent
|
@param e: qMouseEvent
|
||||||
'''
|
'''
|
||||||
button = e.button()
|
button = e.button()
|
||||||
mask = 0
|
buttonNumber = 0
|
||||||
if button == QtCore.Qt.LeftButton:
|
if button == QtCore.Qt.LeftButton:
|
||||||
mask = 1
|
buttonNumber = 1
|
||||||
elif button == QtCore.Qt.MidButton:
|
elif button == QtCore.Qt.MidButton:
|
||||||
mask = 1 << 1
|
buttonNumber = 2
|
||||||
elif button == QtCore.Qt.RightButton:
|
elif button == QtCore.Qt.RightButton:
|
||||||
mask = 1 << 2
|
buttonNumber = 3
|
||||||
self._rfb.sendPointerEvent(mask, e.pos().x(), e.pos().y())
|
self.mouseEvent(buttonNumber, e.pos().x(), e.pos().y())
|
||||||
|
|
||||||
def sendKeyEvent(self, e):
|
def sendKeyEvent(self, e):
|
||||||
'''
|
'''
|
||||||
convert qt key press event to rfb press event
|
convert Qt key press event to RFB press event
|
||||||
send key event to protocol stack
|
|
||||||
@param e: qKeyEvent
|
@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
|
Adaptor for RDP client
|
||||||
'''
|
'''
|
||||||
def __init__(self, qRemoteDesktop):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
constructor
|
constructor
|
||||||
@param qRemoteDesktop: widget use for render
|
|
||||||
'''
|
'''
|
||||||
QAdaptor.__init__(self, qRemoteDesktop)
|
self._widget = QRemoteDesktop(self)
|
||||||
|
|
||||||
|
def getWidget(self):
|
||||||
|
'''
|
||||||
|
@return: widget use for render
|
||||||
|
'''
|
||||||
|
return self._widget
|
||||||
|
|
||||||
def notifyBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
def onBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
||||||
'''
|
'''
|
||||||
notify bitmap update
|
notify bitmap update
|
||||||
@param destLeft: xmin position
|
@param destLeft: xmin position
|
||||||
@@ -141,19 +139,20 @@ class RDPAdaptor(RDPObserver, QAdaptor):
|
|||||||
return
|
return
|
||||||
|
|
||||||
image = QtGui.QImage(data, width, height, imageFormat)
|
image = QtGui.QImage(data, width, height, imageFormat)
|
||||||
self._qRemoteDesktop.notifyImage(destLeft, destTop, image)
|
self._widget.notifyImage(destLeft, destTop, image)
|
||||||
|
|
||||||
|
|
||||||
class QRemoteDesktop(QtGui.QWidget):
|
class QRemoteDesktop(QtGui.QWidget):
|
||||||
'''
|
'''
|
||||||
qt display widget
|
qt display widget
|
||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self, adaptor):
|
||||||
'''
|
'''
|
||||||
constructor
|
constructor
|
||||||
'''
|
'''
|
||||||
super(QRemoteDesktop, self).__init__()
|
super(QRemoteDesktop, self).__init__()
|
||||||
#set by adaptor
|
#adaptor use to send
|
||||||
self._adaptor = None
|
self._adaptor = adaptor
|
||||||
#refresh stack of image
|
#refresh stack of image
|
||||||
#because we can update image only in paint
|
#because we can update image only in paint
|
||||||
#event function. When protocol receive image
|
#event function. When protocol receive image
|
||||||
@@ -208,7 +207,8 @@ class QRemoteDesktop(QtGui.QWidget):
|
|||||||
@param event: qMouseEvent
|
@param event: qMouseEvent
|
||||||
'''
|
'''
|
||||||
if self._adaptor is None:
|
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)
|
self._adaptor.sendMouseEvent(event)
|
||||||
|
|
||||||
def keyPressEvent(self, event):
|
def keyPressEvent(self, event):
|
||||||
@@ -217,5 +217,7 @@ class QRemoteDesktop(QtGui.QWidget):
|
|||||||
@param event: qKeyEvent
|
@param event: qKeyEvent
|
||||||
'''
|
'''
|
||||||
if self._adaptor is None:
|
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)
|
|
||||||
|
self._adaptor.sendKeyEvent(event)
|
||||||
|
|
||||||
@@ -3,4 +3,23 @@
|
|||||||
@file: implement run length encoding algorithm use in RDP protocol to compress bit
|
@file: implement run length encoding algorithm use in RDP protocol to compress bit
|
||||||
@see: http://msdn.microsoft.com/en-us/library/dd240593.aspx
|
@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()
|
||||||
@@ -66,4 +66,26 @@ class ErrorReportedFromPeer(Exception):
|
|||||||
constructor with message
|
constructor with message
|
||||||
@param message: message show when exception is raised
|
@param message: message show when exception is raised
|
||||||
'''
|
'''
|
||||||
Exception.__init__(self, message)
|
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 gcc
|
||||||
import lic
|
import lic
|
||||||
import caps
|
import caps
|
||||||
|
import rdp
|
||||||
|
|
||||||
@ConstAttributes
|
@ConstAttributes
|
||||||
@TypeAttributes(UInt16Le)
|
@TypeAttributes(UInt16Le)
|
||||||
@@ -701,9 +702,10 @@ class PDU(LayerAutomata):
|
|||||||
Global channel for mcs that handle session
|
Global channel for mcs that handle session
|
||||||
identification user, licensing management, and capabilities exchange
|
identification user, licensing management, and capabilities exchange
|
||||||
'''
|
'''
|
||||||
def __init__(self, mode, ordersManager):
|
def __init__(self, mode):
|
||||||
'''
|
'''
|
||||||
Constructor
|
Constructor
|
||||||
|
@param mode: LayerMode
|
||||||
'''
|
'''
|
||||||
LayerAutomata.__init__(self, mode, None)
|
LayerAutomata.__init__(self, mode, None)
|
||||||
#logon info send from client to server
|
#logon info send from client to server
|
||||||
@@ -742,8 +744,15 @@ class PDU(LayerAutomata):
|
|||||||
#share id between client and server
|
#share id between client and server
|
||||||
self._shareId = UInt32Le()
|
self._shareId = UInt32Le()
|
||||||
|
|
||||||
#rdp observer
|
#rdp controller
|
||||||
self._ordersManager = ordersManager
|
self._controller = rdp.RDPController(self)
|
||||||
|
|
||||||
|
def getController(self):
|
||||||
|
'''
|
||||||
|
Getter for RDP controller
|
||||||
|
@return: return rdp controller
|
||||||
|
'''
|
||||||
|
return self._controller
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
'''
|
'''
|
||||||
@@ -871,7 +880,7 @@ class PDU(LayerAutomata):
|
|||||||
'''
|
'''
|
||||||
dataPDU = self.readDataPDU(data)
|
dataPDU = self.readDataPDU(data)
|
||||||
if dataPDU.shareDataHeader.pduType2 == PDUType2.PDUTYPE2_UPDATE and dataPDU.pduData._value.updateType == UpdateType.UPDATETYPE_BITMAP:
|
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):
|
def sendConfirmActivePDU(self):
|
||||||
|
|||||||
@@ -5,16 +5,18 @@ from twisted.internet import protocol
|
|||||||
import tpkt, tpdu, mcs, pdu
|
import tpkt, tpdu, mcs, pdu
|
||||||
from rdpy.network.layer import LayerMode
|
from rdpy.network.layer import LayerMode
|
||||||
|
|
||||||
class RDPOrdersManager(object):
|
class RDPController(object):
|
||||||
'''
|
'''
|
||||||
use to decode and dispatch to observer PDU messages and orders
|
use to decode and dispatch to observer PDU messages and orders
|
||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self, pduLayer):
|
||||||
'''
|
'''
|
||||||
ctor
|
ctor
|
||||||
'''
|
'''
|
||||||
#list of observer
|
#list of observer
|
||||||
self._observers = []
|
self._observers = []
|
||||||
|
#transport layer
|
||||||
|
self._pduLayer = pduLayer
|
||||||
|
|
||||||
def addObserver(self, observer):
|
def addObserver(self, observer):
|
||||||
'''
|
'''
|
||||||
@@ -22,6 +24,7 @@ class RDPOrdersManager(object):
|
|||||||
@param observer: new observer to add
|
@param observer: new observer to add
|
||||||
'''
|
'''
|
||||||
self._observers.append(observer)
|
self._observers.append(observer)
|
||||||
|
observer._controller = self
|
||||||
|
|
||||||
def recvBitmapUpdateDataPDU(self, bitmapUpdateData):
|
def recvBitmapUpdateDataPDU(self, bitmapUpdateData):
|
||||||
'''
|
'''
|
||||||
@@ -31,32 +34,39 @@ class RDPOrdersManager(object):
|
|||||||
for observer in self._observers:
|
for observer in self._observers:
|
||||||
#for each rectangle in update PDU
|
#for each rectangle in update PDU
|
||||||
for rectangle in bitmapUpdateData.rectangles._array:
|
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):
|
class ClientFactory(protocol.Factory):
|
||||||
'''
|
'''
|
||||||
Factory of Client RDP protocol
|
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):
|
def buildProtocol(self, addr):
|
||||||
'''
|
'''
|
||||||
Function call from twisted and build rdp protocol stack
|
Function call from twisted and build rdp protocol stack
|
||||||
|
@param addr: destination address
|
||||||
'''
|
'''
|
||||||
rdpOrdersManager = RDPOrdersManager()
|
pduLayer = pdu.PDU(LayerMode.CLIENT)
|
||||||
rdpOrdersManager.addObserver(self._observer)
|
pduLayer.getController().addObserver(self.buildObserver())
|
||||||
return tpkt.TPKT(tpdu.TPDU(mcs.MCS(pdu.PDU(LayerMode.CLIENT, rdpOrdersManager))));
|
return tpkt.TPKT(tpdu.TPDU(mcs.MCS(pduLayer)));
|
||||||
|
|
||||||
|
def buildObserver(self):
|
||||||
|
'''
|
||||||
|
build observer use for connection
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
class RDPObserver(object):
|
|
||||||
|
class RDPClientObserver(object):
|
||||||
'''
|
'''
|
||||||
class use to inform all rdp event handle by RDPY
|
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
|
notify bitmap update
|
||||||
@param destLeft: xmin position
|
@param destLeft: xmin position
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from twisted.internet import protocol
|
|||||||
from rdpy.network.layer import RawLayer, LayerMode
|
from rdpy.network.layer import RawLayer, LayerMode
|
||||||
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
||||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||||
|
from rdpy.network.error import UnRegistredObject, InvalidValue
|
||||||
|
|
||||||
@ConstAttributes
|
@ConstAttributes
|
||||||
@TypeAttributes(String)
|
@TypeAttributes(String)
|
||||||
@@ -79,7 +80,6 @@ class PixelFormat(CompositeType):
|
|||||||
self.GreenShift = UInt8(8)
|
self.GreenShift = UInt8(8)
|
||||||
self.BlueShift = UInt8(0)
|
self.BlueShift = UInt8(0)
|
||||||
self.padding = (UInt16Be(), UInt8())
|
self.padding = (UInt16Be(), UInt8())
|
||||||
|
|
||||||
|
|
||||||
class ServerInit(CompositeType):
|
class ServerInit(CompositeType):
|
||||||
'''
|
'''
|
||||||
@@ -121,21 +121,21 @@ class KeyEvent(CompositeType):
|
|||||||
'''
|
'''
|
||||||
key event structure message
|
key event structure message
|
||||||
'''
|
'''
|
||||||
def __init__(self, downFlag = False, key = 0):
|
def __init__(self):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
self.downFlag = UInt8(downFlag)
|
self.downFlag = UInt8(False)
|
||||||
self.padding = UInt16Be()
|
self.padding = UInt16Be()
|
||||||
self.key = UInt32Be(key)
|
self.key = UInt32Be()
|
||||||
|
|
||||||
class PointerEvent(CompositeType):
|
class PointerEvent(CompositeType):
|
||||||
'''
|
'''
|
||||||
pointer event structure message
|
pointer event structure message
|
||||||
'''
|
'''
|
||||||
def __init__(self, mask = 0, x = 0, y = 0):
|
def __init__(self):
|
||||||
CompositeType.__init__(self)
|
CompositeType.__init__(self)
|
||||||
self.mask = UInt8(mask)
|
self.mask = UInt8()
|
||||||
self.x = UInt16Be(x)
|
self.x = UInt16Be()
|
||||||
self.y = UInt16Be(y)
|
self.y = UInt16Be()
|
||||||
|
|
||||||
class ClientCutText(CompositeType):
|
class ClientCutText(CompositeType):
|
||||||
'''
|
'''
|
||||||
@@ -152,9 +152,10 @@ class Rfb(RawLayer):
|
|||||||
implements rfb protocol
|
implements rfb protocol
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, mode, ordersManager):
|
def __init__(self, mode):
|
||||||
'''
|
'''
|
||||||
constructor
|
constructor
|
||||||
|
@param mode: LayerMode client or server
|
||||||
'''
|
'''
|
||||||
RawLayer.__init__(self, mode)
|
RawLayer.__init__(self, mode)
|
||||||
#usefull for rfb protocol
|
#usefull for rfb protocol
|
||||||
@@ -177,14 +178,14 @@ class Rfb(RawLayer):
|
|||||||
#current rectangle header
|
#current rectangle header
|
||||||
self._currentRect = Rectangle()
|
self._currentRect = Rectangle()
|
||||||
#client or server adaptor
|
#client or server adaptor
|
||||||
self._ordersManager = ordersManager
|
self._controller = RFBController(self)
|
||||||
|
|
||||||
def addObserver(self, observer):
|
def getController(self):
|
||||||
'''
|
'''
|
||||||
add observer for input/ouput events
|
Getter for controller
|
||||||
@param observer: RfbObserver interface implementation
|
@return: RFBController use by rfb layer
|
||||||
'''
|
'''
|
||||||
self._observer.append(observer)
|
return self._controller
|
||||||
|
|
||||||
def expectWithHeader(self, expectedHeaderLen, callbackBody):
|
def expectWithHeader(self, expectedHeaderLen, callbackBody):
|
||||||
'''
|
'''
|
||||||
@@ -355,7 +356,7 @@ class Rfb(RawLayer):
|
|||||||
'''
|
'''
|
||||||
read body of rect
|
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
|
self._nbRect = self._nbRect - 1
|
||||||
#if there is another rect to read
|
#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)))
|
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
|
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
|
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):
|
def sendClientCutText(self, text):
|
||||||
'''
|
'''
|
||||||
@@ -410,15 +413,18 @@ class Rfb(RawLayer):
|
|||||||
'''
|
'''
|
||||||
self.send((ClientToServerMessages.CUT_TEXT, ClientCutText(text)))
|
self.send((ClientToServerMessages.CUT_TEXT, ClientCutText(text)))
|
||||||
|
|
||||||
class RFBOrderManager(object):
|
class RFBController(object):
|
||||||
'''
|
'''
|
||||||
class use to manage rfb order and dispatch throw observers
|
class use to manage rfb order and dispatch throw observers
|
||||||
'''
|
'''
|
||||||
def __init__(self):
|
def __init__(self, rfbLayer):
|
||||||
'''
|
'''
|
||||||
ctor
|
ctor
|
||||||
|
@param rfbLayer: network layer
|
||||||
'''
|
'''
|
||||||
self._observers = []
|
self._observers = []
|
||||||
|
#rfb layer to send client orders
|
||||||
|
self._rfbLayer = rfbLayer
|
||||||
|
|
||||||
def addObserver(self, observer):
|
def addObserver(self, observer):
|
||||||
'''
|
'''
|
||||||
@@ -426,44 +432,111 @@ class RFBOrderManager(object):
|
|||||||
@param observer: new observer
|
@param observer: new observer
|
||||||
'''
|
'''
|
||||||
self._observers.append(observer)
|
self._observers.append(observer)
|
||||||
|
observer._controller = self
|
||||||
|
|
||||||
def recvRectangle(self, rectangle, pixelFormat, data):
|
def recvRectangle(self, rectangle, pixelFormat, data):
|
||||||
'''
|
'''
|
||||||
receive rectangle order
|
receive rectangle order
|
||||||
|
Main update order type
|
||||||
@param rectangle: Rectangle type header of packet
|
@param rectangle: Rectangle type header of packet
|
||||||
@param pixelFormat: pixelFormat struct of current session
|
@param pixelFormat: pixelFormat struct of current session
|
||||||
@param data: image data
|
@param data: image data
|
||||||
'''
|
'''
|
||||||
for observer in self._observers:
|
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):
|
class ClientFactory(protocol.Factory):
|
||||||
'''
|
'''
|
||||||
Factory of RFB protocol
|
Factory of RFB protocol
|
||||||
'''
|
'''
|
||||||
def __init__(self, observer):
|
|
||||||
'''
|
|
||||||
save mode and adapter
|
|
||||||
@param adapter: graphic client adapter
|
|
||||||
'''
|
|
||||||
self._observer = observer
|
|
||||||
|
|
||||||
def buildProtocol(self, addr):
|
def buildProtocol(self, addr):
|
||||||
'''
|
'''
|
||||||
function call by twisted on connection
|
function call by twisted on connection
|
||||||
@param addr: adress where client try to connect
|
@param addr: address where client try to connect
|
||||||
'''
|
'''
|
||||||
orderManager = RFBOrderManager()
|
protocol = Rfb(LayerMode.CLIENT)
|
||||||
orderManager.addObserver(self._observer)
|
protocol.getController().addObserver(self.buildObserver())
|
||||||
protocol = Rfb(LayerMode.CLIENT, orderManager)
|
|
||||||
self._observer.setProtocol(protocol)
|
|
||||||
return protocol
|
return protocol
|
||||||
|
|
||||||
|
def buildObserver(self):
|
||||||
|
'''
|
||||||
|
build an RFB observer object
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class RfbObserver(object):
|
class RFBClientObserver(object):
|
||||||
'''
|
'''
|
||||||
Rfb protocol obserser
|
RFB client protocol observer
|
||||||
'''
|
'''
|
||||||
def notifyFramebufferUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
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
|
recv framebuffer update
|
||||||
@param width : width of image
|
@param width : width of image
|
||||||
@@ -475,10 +548,3 @@ class RfbObserver(object):
|
|||||||
@param data : in respect of dataFormat and pixelFormat
|
@param data : in respect of dataFormat and pixelFormat
|
||||||
'''
|
'''
|
||||||
pass
|
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