code refactoring

This commit is contained in:
speyrefitte
2014-06-20 17:11:39 +02:00
parent 3d9deca110
commit 39b1638b6a
12 changed files with 372 additions and 235 deletions

1
.gitignore vendored
View File

@@ -1,3 +1,4 @@
*.pyc
.project
.pydevproject
README.md~

View File

@@ -1,6 +1,6 @@
# RDPY
## Remote Desktop Protoc in Python
Remote Desktop Protocol in Twisted Python
## Requirements
* python2.7

View File

@@ -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.

View File

@@ -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,37 +28,39 @@ 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
@param y: y position of new image
@param pixelFormat: pixefFormat structure in rfb.message.PixelFormat
@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
if pixelFormat.BitsPerPixel.value == 32 and pixelFormat.RedShift.value == 16:
@@ -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)

View File

@@ -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

View File

@@ -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()

View 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()

View 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()

View File

@@ -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)

View File

@@ -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):

View File

@@ -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

View File

@@ -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