Code factoring + comments
This commit is contained in:
@@ -62,9 +62,7 @@ class RFBClientQt(RFBClientObserver, QAdaptor):
|
||||
is to an RFB observer
|
||||
'''
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor
|
||||
'''
|
||||
RFBClientObserver.__init__(self)
|
||||
self._widget = QRemoteDesktop(self)
|
||||
|
||||
def getWidget(self):
|
||||
@@ -121,9 +119,7 @@ class RDPClientQt(RDPClientObserver, QAdaptor):
|
||||
Adaptor for RDP client
|
||||
'''
|
||||
def __init__(self):
|
||||
'''
|
||||
constructor
|
||||
'''
|
||||
RDPClientObserver.__init__(self)
|
||||
self._widget = QRemoteDesktop(self)
|
||||
|
||||
def getWidget(self):
|
||||
|
||||
@@ -31,7 +31,7 @@ from PyQt4 import QtGui
|
||||
from rdpy.display.qt import RDPClientQt
|
||||
from rdpy.protocol.rdp import rdp
|
||||
|
||||
class RDPClientQtFactory(rdp.ClientFactory):
|
||||
class RDPClientQtFactory(rdp.Factory):
|
||||
'''
|
||||
Factory create a RDP GUI client
|
||||
'''
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#
|
||||
|
||||
"""
|
||||
example of use rdpy as vnc client
|
||||
example of use rdpy as VNC client
|
||||
"""
|
||||
|
||||
import sys
|
||||
@@ -31,14 +31,14 @@ from PyQt4 import QtGui
|
||||
from rdpy.display.qt import RFBClientQt
|
||||
from rdpy.protocol.rfb import rfb
|
||||
|
||||
class RFBClientQtFactory(rfb.ClientFactory):
|
||||
'''
|
||||
class RFBClientQtFactory(rfb.Factory):
|
||||
"""
|
||||
Factory create a VNC GUI client
|
||||
'''
|
||||
"""
|
||||
def buildObserver(self):
|
||||
'''
|
||||
build RFB observer
|
||||
'''
|
||||
"""
|
||||
Build RFB Client observer
|
||||
"""
|
||||
#create client observer
|
||||
client = RFBClientQt()
|
||||
#create qt widget
|
||||
@@ -52,21 +52,21 @@ class RFBClientQtFactory(rfb.ClientFactory):
|
||||
pass
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
'''
|
||||
connection lost event
|
||||
"""
|
||||
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
|
||||
"""
|
||||
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()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
'''
|
||||
|
||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||
from rdpy.network.layer import LayerAutomata, Layer
|
||||
from rdpy.network.layer import LayerAutomata, Layer, LayerMode
|
||||
from rdpy.network.type import sizeof, Stream, UInt8, UInt16Be
|
||||
from rdpy.network.error import InvalidExpectedDataException, InvalidValue, InvalidSize
|
||||
from rdpy.protocol.rdp.ber import writeLength
|
||||
@@ -93,12 +93,13 @@ class MCS(LayerAutomata):
|
||||
return self._mcs._serverSettings
|
||||
|
||||
|
||||
def __init__(self, presentation):
|
||||
def __init__(self, mode, presentation):
|
||||
'''
|
||||
ctor call base class ctor
|
||||
@param mode: mode of mcs layer
|
||||
@param presentation: presentation layer
|
||||
'''
|
||||
LayerAutomata.__init__(self, presentation._mode, presentation)
|
||||
LayerAutomata.__init__(self, mode, presentation)
|
||||
self._clientSettings = gcc.ClientSettings()
|
||||
self._serverSettings = gcc.ServerSettings()
|
||||
#default user Id
|
||||
@@ -334,5 +335,18 @@ class MCS(LayerAutomata):
|
||||
max_pdu_size = ber.readInteger(s)
|
||||
ber.readInteger(s)
|
||||
return (max_channels, max_users, max_tokens, max_pdu_size)
|
||||
|
||||
|
||||
def createClient(controller):
|
||||
"""
|
||||
@param controller: RDP controller which initialized all channel layer
|
||||
@return: MCS layer in client mode
|
||||
"""
|
||||
return MCS(LayerMode.CLIENT, controller.getPDULayer())
|
||||
|
||||
def createServer(controller):
|
||||
"""
|
||||
@param controller: RDP controller which initialized all channel layer
|
||||
@return: MCS layer in server mode
|
||||
"""
|
||||
return MCS(LayerMode.SERVER, controller.getPDULayer())
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@author: citronneur
|
||||
'''
|
||||
|
||||
from rdpy.network.layer import LayerAutomata
|
||||
from rdpy.network.layer import LayerAutomata, LayerMode
|
||||
from rdpy.network.type import CompositeType, UniString, String, UInt8, UInt16Le, UInt32Le, sizeof, ArrayType,\
|
||||
FactoryType
|
||||
from rdpy.network.const import ConstAttributes, TypeAttributes
|
||||
@@ -702,10 +702,11 @@ class PDU(LayerAutomata):
|
||||
Global channel for mcs that handle session
|
||||
identification user, licensing management, and capabilities exchange
|
||||
'''
|
||||
def __init__(self, mode):
|
||||
def __init__(self, mode, controller):
|
||||
'''
|
||||
Constructor
|
||||
@param mode: LayerMode
|
||||
@param controller: controller use to inform orders
|
||||
'''
|
||||
LayerAutomata.__init__(self, mode, None)
|
||||
#logon info send from client to server
|
||||
@@ -745,14 +746,7 @@ class PDU(LayerAutomata):
|
||||
self._shareId = UInt32Le()
|
||||
|
||||
#rdp controller
|
||||
self._controller = rdp.RDPController(self)
|
||||
|
||||
def getController(self):
|
||||
'''
|
||||
Getter for RDP controller
|
||||
@return: return rdp controller
|
||||
'''
|
||||
return self._controller
|
||||
self._controller = controller
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
|
||||
@@ -6,24 +6,31 @@ import tpkt, tpdu, mcs, pdu
|
||||
from rdpy.network.layer import LayerMode
|
||||
|
||||
class RDPController(object):
|
||||
'''
|
||||
"""
|
||||
use to decode and dispatch to observer PDU messages and orders
|
||||
'''
|
||||
def __init__(self, pduLayer):
|
||||
"""
|
||||
def __init__(self, mode):
|
||||
'''
|
||||
ctor
|
||||
@param mode: mode of generate layer by controller
|
||||
@param observer: observer
|
||||
'''
|
||||
#list of observer
|
||||
self._observers = []
|
||||
self._clientObserver = []
|
||||
#transport layer
|
||||
self._pduLayer = pduLayer
|
||||
self._pduLayer = pdu.PDU(mode, self)
|
||||
|
||||
def addObserver(self, observer):
|
||||
def getPDULayer(self):
|
||||
"""
|
||||
@return: pdu layer use by controller
|
||||
"""
|
||||
return self._pduLayer
|
||||
|
||||
def addClientObserver(self, observer):
|
||||
'''
|
||||
add observer to rdp protocol
|
||||
@param observer: new observer to add
|
||||
'''
|
||||
self._observers.append(observer)
|
||||
self._clientObserver.append(observer)
|
||||
observer._controller = self
|
||||
|
||||
def recvBitmapUpdateDataPDU(self, bitmapUpdateData):
|
||||
@@ -31,12 +38,12 @@ class RDPController(object):
|
||||
call when a bitmap data is received from update pdu
|
||||
@param bitmapData: pdu.BitmapData struct
|
||||
'''
|
||||
for observer in self._observers:
|
||||
for observer in self._clientObserver:
|
||||
#for each rectangle in update PDU
|
||||
for rectangle in bitmapUpdateData.rectangles._array:
|
||||
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 Factory(protocol.Factory):
|
||||
'''
|
||||
Factory of Client RDP protocol
|
||||
'''
|
||||
@@ -45,9 +52,7 @@ class ClientFactory(protocol.Factory):
|
||||
Function call from twisted and build rdp protocol stack
|
||||
@param addr: destination address
|
||||
'''
|
||||
pduLayer = pdu.PDU(LayerMode.CLIENT)
|
||||
pduLayer.getController().addObserver(self.buildObserver())
|
||||
return tpkt.TPKT(tpdu.createClient(mcs.MCS(pduLayer)));
|
||||
return tpkt.TPKT(tpdu.createClient(mcs.createClient(self.buildObserver().getController())));
|
||||
|
||||
def buildObserver(self):
|
||||
'''
|
||||
@@ -75,7 +80,7 @@ class ServerFactory(protocol.Factory):
|
||||
'''
|
||||
pduLayer = pdu.PDU(LayerMode.SERVER)
|
||||
#pduLayer.getController().addObserver(self.buildObserver())
|
||||
return tpkt.TPKT(tpdu.createServer(mcs.MCS(pduLayer), self._privateKeyFileName, self._certificateFileName));
|
||||
return tpkt.TPKT(tpdu.createServer(mcs.createServer(pduLayer), self._privateKeyFileName, self._certificateFileName));
|
||||
|
||||
def buildObserver(self):
|
||||
'''
|
||||
@@ -88,10 +93,14 @@ class RDPClientObserver(object):
|
||||
class use to inform all rdp event handle by RDPY
|
||||
'''
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor
|
||||
'''
|
||||
self._controller = None
|
||||
self._controller = RDPController(LayerMode.CLIENT)
|
||||
self._controller.addClientObserver(self)
|
||||
|
||||
def getController(self):
|
||||
"""
|
||||
@return: RDP controller use by observer
|
||||
"""
|
||||
return self._controller
|
||||
|
||||
def onBitmapUpdate(self, destLeft, destTop, destRight, destBottom, width, height, bitsPerPixel, isCompress, data):
|
||||
'''
|
||||
|
||||
@@ -1,6 +1,31 @@
|
||||
'''
|
||||
@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 <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
"""
|
||||
Implement Remote FrameBuffer protocol use in VNC client and server
|
||||
@see: http://www.realvnc.com/docs/rfbproto.pdf
|
||||
|
||||
@todo: server side of protocol
|
||||
@todo: vnc security type
|
||||
@todo: more encoding rectangle
|
||||
"""
|
||||
|
||||
from twisted.internet import protocol
|
||||
from rdpy.network.layer import RawLayer, LayerMode
|
||||
from rdpy.network.type import UInt8, UInt16Be, UInt32Be, SInt32Be, String, CompositeType
|
||||
@@ -10,9 +35,9 @@ from rdpy.network.error import UnRegistredObject, InvalidValue
|
||||
@ConstAttributes
|
||||
@TypeAttributes(String)
|
||||
class ProtocolVersion(object):
|
||||
'''
|
||||
different ptotocol version
|
||||
'''
|
||||
"""
|
||||
Different protocol version
|
||||
"""
|
||||
UNKNOWN = ""
|
||||
RFB003003 = "RFB 003.003\n"
|
||||
RFB003007 = "RFB 003.007\n"
|
||||
@@ -21,11 +46,9 @@ class ProtocolVersion(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class SecurityType(object):
|
||||
'''
|
||||
security type supported
|
||||
(or will be supported)
|
||||
by rdpy
|
||||
'''
|
||||
"""
|
||||
Security type supported
|
||||
"""
|
||||
INVALID = 0
|
||||
NONE = 1
|
||||
VNC = 2
|
||||
@@ -33,11 +56,11 @@ class SecurityType(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt32Be)
|
||||
class Pointer(object):
|
||||
'''
|
||||
mouse event code (which button)
|
||||
actually in RFB specification only$
|
||||
"""
|
||||
Mouse event code (which button)
|
||||
actually in RFB specification only
|
||||
three buttons are supported
|
||||
'''
|
||||
"""
|
||||
BUTTON1 = 0x1
|
||||
BUTTON2 = 0x2
|
||||
BUTTON3 = 0x4
|
||||
@@ -45,17 +68,17 @@ class Pointer(object):
|
||||
@ConstAttributes
|
||||
@TypeAttributes(SInt32Be)
|
||||
class Encoding(object):
|
||||
'''
|
||||
encoding types
|
||||
'''
|
||||
"""
|
||||
Encoding types of FrameBuffer update
|
||||
"""
|
||||
RAW = 0
|
||||
|
||||
@ConstAttributes
|
||||
@TypeAttributes(UInt8)
|
||||
class ClientToServerMessages(object):
|
||||
'''
|
||||
messages types
|
||||
'''
|
||||
"""
|
||||
Client to server messages types
|
||||
"""
|
||||
PIXEL_FORMAT = 0
|
||||
ENCODING = 2
|
||||
FRAME_BUFFER_UPDATE_REQUEST = 3
|
||||
@@ -64,9 +87,9 @@ class ClientToServerMessages(object):
|
||||
CUT_TEXT = 6
|
||||
|
||||
class PixelFormat(CompositeType):
|
||||
'''
|
||||
pixel format structure
|
||||
'''
|
||||
"""
|
||||
Pixel format structure
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.BitsPerPixel = UInt8(32)
|
||||
@@ -82,10 +105,10 @@ class PixelFormat(CompositeType):
|
||||
self.padding = (UInt16Be(), UInt8())
|
||||
|
||||
class ServerInit(CompositeType):
|
||||
'''
|
||||
server init structure
|
||||
framebuffer configuration
|
||||
'''
|
||||
"""
|
||||
Server init structure
|
||||
FrameBuffer configuration
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.width = UInt16Be()
|
||||
@@ -93,9 +116,11 @@ class ServerInit(CompositeType):
|
||||
self.pixelFormat = PixelFormat()
|
||||
|
||||
class FrameBufferUpdateRequest(CompositeType):
|
||||
'''
|
||||
fb update request send from client to server
|
||||
'''
|
||||
"""
|
||||
FrameBuffer update request send from client to server
|
||||
Incremental means that server send update with a specific
|
||||
order, and client must draw orders in same order
|
||||
"""
|
||||
def __init__(self, incremental = False, x = 0, y = 0, width = 0, height = 0):
|
||||
CompositeType.__init__(self)
|
||||
self.incremental = UInt8(incremental)
|
||||
@@ -106,9 +131,9 @@ class FrameBufferUpdateRequest(CompositeType):
|
||||
|
||||
|
||||
class Rectangle(CompositeType):
|
||||
'''
|
||||
header message of update rect
|
||||
'''
|
||||
"""
|
||||
Header message of update rectangle
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.x = UInt16Be()
|
||||
@@ -118,9 +143,10 @@ class Rectangle(CompositeType):
|
||||
self.encoding = SInt32Be()
|
||||
|
||||
class KeyEvent(CompositeType):
|
||||
'''
|
||||
key event structure message
|
||||
'''
|
||||
"""
|
||||
Key event structure message
|
||||
Use to send a keyboard event
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.downFlag = UInt8(False)
|
||||
@@ -128,9 +154,10 @@ class KeyEvent(CompositeType):
|
||||
self.key = UInt32Be()
|
||||
|
||||
class PointerEvent(CompositeType):
|
||||
'''
|
||||
pointer event structure message
|
||||
'''
|
||||
"""
|
||||
Pointer event structure message
|
||||
Use to send mouse event
|
||||
"""
|
||||
def __init__(self):
|
||||
CompositeType.__init__(self)
|
||||
self.mask = UInt8()
|
||||
@@ -138,36 +165,36 @@ class PointerEvent(CompositeType):
|
||||
self.y = UInt16Be()
|
||||
|
||||
class ClientCutText(CompositeType):
|
||||
'''
|
||||
client cut text message message
|
||||
'''
|
||||
"""
|
||||
Client cut text message message
|
||||
Use to simulate copy paste (ctrl-c ctrl-v) only for text
|
||||
"""
|
||||
def __init__(self, text = ""):
|
||||
CompositeType.__init__(self)
|
||||
self.padding = (UInt16Be(), UInt8())
|
||||
self.size = UInt32Be(len(text))
|
||||
self.message = String(text)
|
||||
|
||||
class Rfb(RawLayer):
|
||||
'''
|
||||
implements rfb protocol
|
||||
'''
|
||||
|
||||
def __init__(self, mode):
|
||||
'''
|
||||
constructor
|
||||
class RFB(RawLayer):
|
||||
"""
|
||||
Implement RFB protocol
|
||||
"""
|
||||
def __init__(self, mode, controller):
|
||||
"""
|
||||
@param mode: LayerMode client or server
|
||||
'''
|
||||
@param controller: controller use to inform new orders
|
||||
"""
|
||||
RawLayer.__init__(self, mode)
|
||||
#usefull for rfb protocol
|
||||
#useful for RFB protocol
|
||||
self._callbackBody = None
|
||||
#protocol version negociated
|
||||
#protocol version negotiated
|
||||
self._version = ProtocolVersion.RFB003008
|
||||
#nb security launch by server
|
||||
#number security launch by server
|
||||
self._securityLevel = SecurityType.INVALID
|
||||
#shared framebuffer client init message
|
||||
#shared FrameBuffer client init message
|
||||
self._sharedFlag = UInt8(False)
|
||||
#server init message
|
||||
#which contain framebuffer dim and pixel format
|
||||
#which contain FrameBuffer dim and pixel format
|
||||
self._serverInit = ServerInit()
|
||||
#client pixel format
|
||||
self._pixelFormat = PixelFormat()
|
||||
@@ -178,33 +205,26 @@ class Rfb(RawLayer):
|
||||
#current rectangle header
|
||||
self._currentRect = Rectangle()
|
||||
#client or server adaptor
|
||||
self._controller = RFBController(self)
|
||||
|
||||
def getController(self):
|
||||
'''
|
||||
Getter for controller
|
||||
@return: RFBController use by rfb layer
|
||||
'''
|
||||
return self._controller
|
||||
self._controller = controller
|
||||
|
||||
def expectWithHeader(self, expectedHeaderLen, callbackBody):
|
||||
'''
|
||||
"""
|
||||
2nd level of waiting event
|
||||
read expectedHeaderLen that contain body size
|
||||
@param expectedHeaderLen: bytes read and use to compute bodylen
|
||||
@param callbackBody: next state use when value read from header
|
||||
@param expectedHeaderLen: contains the number of bytes, which body length needs to be encoded
|
||||
@param callbackBody: next state use when expected date from expectedHeaderLen
|
||||
are received
|
||||
'''
|
||||
"""
|
||||
self._callbackBody = callbackBody
|
||||
self.expect(expectedHeaderLen, self.expectedBody)
|
||||
|
||||
def expectedBody(self, data):
|
||||
'''
|
||||
read header and wait header value to call next state
|
||||
"""
|
||||
Read header and wait header value to call next state
|
||||
@param data: Stream that length are to header length (1|2|4 bytes)
|
||||
set next state to callBack body when length read from header
|
||||
are received
|
||||
'''
|
||||
"""
|
||||
bodyLen = None
|
||||
if data.len == 1:
|
||||
bodyLen = UInt8()
|
||||
@@ -219,38 +239,36 @@ class Rfb(RawLayer):
|
||||
self.expect(bodyLen.value, self._callbackBody)
|
||||
|
||||
def connect(self):
|
||||
'''
|
||||
call when transport layer connection is made
|
||||
"""
|
||||
Call when transport layer connection is made
|
||||
in Client mode -> wait protocol version
|
||||
in Server mode -> send protocol version
|
||||
'''
|
||||
"""
|
||||
if self._mode == LayerMode.CLIENT:
|
||||
self.expect(12, self.recvProtocolVersion)
|
||||
else:
|
||||
self.send(self._version)
|
||||
|
||||
def readProtocolVersion(self, data):
|
||||
'''
|
||||
read protocol version and set
|
||||
self._version var member
|
||||
"""
|
||||
Read protocol version
|
||||
@param data: Stream may contain protocol version string (ProtocolVersion)
|
||||
'''
|
||||
"""
|
||||
data.readType(self._version)
|
||||
if not self._version in [ProtocolVersion.RFB003003, ProtocolVersion.RFB003007, ProtocolVersion.RFB003008]:
|
||||
self._version = ProtocolVersion.UNKNOWN
|
||||
|
||||
def recvProtocolVersion(self, data):
|
||||
'''
|
||||
read handshake packet
|
||||
protocol version nego
|
||||
if protocol receive from client is unknow
|
||||
"""
|
||||
Read handshake packet
|
||||
If protocol receive from client is unknown
|
||||
try best version of protocol version (ProtocolVersion.RFB003008)
|
||||
@param data: Stream
|
||||
'''
|
||||
"""
|
||||
self.readProtocolVersion(data)
|
||||
if self._version == ProtocolVersion.UNKNOWN:
|
||||
print "Unknown protocol version %s send 003.008"%data.getvalue()
|
||||
#protocol version is unknow try best version we can handle
|
||||
#protocol version is unknown try best version we can handle
|
||||
self._version = ProtocolVersion.RFB003008
|
||||
#send same version of
|
||||
self.send(self._version)
|
||||
@@ -262,16 +280,19 @@ class Rfb(RawLayer):
|
||||
self.expectWithHeader(1, self.recvSecurityList)
|
||||
|
||||
def recvSecurityServer(self, data):
|
||||
'''
|
||||
security handshake for 33 rfb version
|
||||
server imposed security level
|
||||
'''
|
||||
"""
|
||||
Security handshake for 33 RFB version
|
||||
Server imposed security level
|
||||
@param data: well formed packet
|
||||
"""
|
||||
#TODO!!!
|
||||
pass
|
||||
|
||||
def recvSecurityList(self, data):
|
||||
'''
|
||||
read all security list
|
||||
'''
|
||||
"""
|
||||
Read security list packet send from server to client
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
securityList = []
|
||||
while data.dataLen() > 0:
|
||||
securityElement = UInt8()
|
||||
@@ -287,9 +308,11 @@ class Rfb(RawLayer):
|
||||
self.expect(4, self.recvSecurityResult)
|
||||
|
||||
def recvSecurityResult(self, data):
|
||||
'''
|
||||
"""
|
||||
Read security result packet
|
||||
'''
|
||||
Use by server to inform connection status of client
|
||||
@param data: Stream that contain well formed packet
|
||||
"""
|
||||
result = UInt32Be()
|
||||
data.readType(result)
|
||||
if result == UInt32Be(1):
|
||||
@@ -301,19 +324,25 @@ class Rfb(RawLayer):
|
||||
self.sendClientInit()
|
||||
|
||||
def recvSecurityFailed(self, data):
|
||||
"""
|
||||
Send by server to inform reason of why it's refused client
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
print "Security failed cause to %s"%data.getvalue()
|
||||
|
||||
def recvServerInit(self, data):
|
||||
'''
|
||||
read server init packet
|
||||
'''
|
||||
"""
|
||||
Read server init packet
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
data.readType(self._serverInit)
|
||||
self.expectWithHeader(4, self.recvServerName)
|
||||
|
||||
def recvServerName(self, data):
|
||||
'''
|
||||
read server name from server init packet
|
||||
'''
|
||||
"""
|
||||
Read server name
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
data.readType(self._serverName)
|
||||
print "Server name %s"%str(self._serverName)
|
||||
#end of handshake
|
||||
@@ -326,18 +355,21 @@ class Rfb(RawLayer):
|
||||
self.expect(1, self.recvServerOrder)
|
||||
|
||||
def recvServerOrder(self, data):
|
||||
'''
|
||||
read order receive from server
|
||||
'''
|
||||
"""
|
||||
Read order receive from server
|
||||
Main function for bitmap update from server to client
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
packet_type = UInt8()
|
||||
data.readType(packet_type)
|
||||
if packet_type == UInt8(0):
|
||||
self.expect(3, self.recvFrameBufferUpdateHeader)
|
||||
|
||||
def recvFrameBufferUpdateHeader(self, data):
|
||||
'''
|
||||
read frame buffer update packet header
|
||||
'''
|
||||
"""
|
||||
Read frame buffer update packet header
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
#padding
|
||||
nbRect = UInt16Be()
|
||||
self._nbRect = data.readType((UInt8(), nbRect))
|
||||
@@ -345,17 +377,19 @@ class Rfb(RawLayer):
|
||||
self.expect(12, self.recvRectHeader)
|
||||
|
||||
def recvRectHeader(self, data):
|
||||
'''
|
||||
read rectangle header
|
||||
'''
|
||||
"""
|
||||
Read rectangle header
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
data.readType(self._currentRect)
|
||||
if self._currentRect.encoding == Encoding.RAW:
|
||||
self.expect(self._currentRect.width.value * self._currentRect.height.value * (self._pixelFormat.BitsPerPixel.value / 8), self.recvRectBody)
|
||||
|
||||
def recvRectBody(self, data):
|
||||
'''
|
||||
read body of rect
|
||||
'''
|
||||
"""
|
||||
Read body of rectangle update
|
||||
@param data: Stream that contains well formed packet
|
||||
"""
|
||||
self._controller.recvRectangle(self._currentRect, self._pixelFormat, data.getvalue())
|
||||
|
||||
self._nbRect = self._nbRect - 1
|
||||
@@ -368,89 +402,97 @@ class Rfb(RawLayer):
|
||||
self.expect(12, self.recvRectHeader)
|
||||
|
||||
def sendClientInit(self):
|
||||
'''
|
||||
write client init packet
|
||||
'''
|
||||
"""
|
||||
Send client init packet
|
||||
"""
|
||||
self.send(self._sharedFlag)
|
||||
self.expect(20, self.recvServerInit)
|
||||
|
||||
def sendPixelFormat(self, pixelFormat):
|
||||
'''
|
||||
send pixel format structure
|
||||
'''
|
||||
"""
|
||||
Send pixel format structure
|
||||
Very important packet that inform the image struct supported by the client
|
||||
@param pixelFormat: PixelFormat struct
|
||||
"""
|
||||
self.send((ClientToServerMessages.PIXEL_FORMAT, UInt16Be(), UInt8(), pixelFormat))
|
||||
|
||||
def sendSetEncoding(self):
|
||||
'''
|
||||
send set encoding packet
|
||||
'''
|
||||
"""
|
||||
Send set encoding packet
|
||||
Actually only RAW bitmap encoding are used
|
||||
"""
|
||||
self.send((ClientToServerMessages.ENCODING, UInt8(), UInt16Be(1), Encoding.RAW))
|
||||
|
||||
def sendFramebufferUpdateRequest(self, incremental, x, y, width, height):
|
||||
'''
|
||||
request server the specified zone
|
||||
"""
|
||||
Request server the specified zone
|
||||
incremental means request only change before last update
|
||||
'''
|
||||
"""
|
||||
self.send((ClientToServerMessages.FRAME_BUFFER_UPDATE_REQUEST, FrameBufferUpdateRequest(incremental, x, y, width, height)))
|
||||
|
||||
def sendKeyEvent(self, keyEvent):
|
||||
'''
|
||||
write key event packet
|
||||
"""
|
||||
Write key event packet
|
||||
@param keyEvent: KeyEvent struct to send
|
||||
'''
|
||||
"""
|
||||
self.send((ClientToServerMessages.KEY_EVENT, keyEvent))
|
||||
|
||||
def sendPointerEvent(self, pointerEvent):
|
||||
'''
|
||||
write pointer event packet
|
||||
"""
|
||||
Write pointer event packet
|
||||
@param pointerEvent: PointerEvent struct use
|
||||
'''
|
||||
"""
|
||||
self.send((ClientToServerMessages.POINTER_EVENT, pointerEvent))
|
||||
|
||||
def sendClientCutText(self, text):
|
||||
'''
|
||||
"""
|
||||
write client cut text event packet
|
||||
'''
|
||||
"""
|
||||
self.send((ClientToServerMessages.CUT_TEXT, ClientCutText(text)))
|
||||
|
||||
class RFBController(object):
|
||||
'''
|
||||
class use to manage rfb order and dispatch throw observers
|
||||
'''
|
||||
def __init__(self, rfbLayer):
|
||||
'''
|
||||
ctor
|
||||
@param rfbLayer: network layer
|
||||
'''
|
||||
self._observers = []
|
||||
"""
|
||||
Class use to manage RFB order and dispatch throw observers
|
||||
"""
|
||||
def __init__(self, mode):
|
||||
"""
|
||||
@param mode: mode of inner RFB layer
|
||||
"""
|
||||
self._clientObservers = []
|
||||
#rfb layer to send client orders
|
||||
self._rfbLayer = rfbLayer
|
||||
self._rfbLayer = RFB(mode, self)
|
||||
|
||||
def addObserver(self, observer):
|
||||
'''
|
||||
def getRFBLayer(self):
|
||||
"""
|
||||
@return: RFB layer build by controller
|
||||
"""
|
||||
return self._rfbLayer
|
||||
|
||||
def addClientObserver(self, observer):
|
||||
"""
|
||||
Add new observer for this protocol
|
||||
@param observer: new observer
|
||||
'''
|
||||
self._observers.append(observer)
|
||||
"""
|
||||
self._clientObservers.append(observer)
|
||||
observer._controller = self
|
||||
|
||||
def recvRectangle(self, rectangle, pixelFormat, data):
|
||||
'''
|
||||
receive rectangle order
|
||||
"""
|
||||
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:
|
||||
"""
|
||||
for observer in self._clientObservers:
|
||||
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
|
||||
"""
|
||||
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
|
||||
'''
|
||||
@param key: ASCII code of key
|
||||
"""
|
||||
try:
|
||||
event = KeyEvent()
|
||||
event.downFlag.value = isDown
|
||||
@@ -461,12 +503,12 @@ class RFBController(object):
|
||||
print "Try to send an invalid key event"
|
||||
|
||||
def sendPointerEvent(self, mask, x, y):
|
||||
'''
|
||||
Send an pointer event throw RFB protocol
|
||||
"""
|
||||
Send a 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
|
||||
@@ -478,54 +520,56 @@ class RFBController(object):
|
||||
print "Try to send an invalid pointer event"
|
||||
|
||||
|
||||
class ClientFactory(protocol.Factory):
|
||||
'''
|
||||
Factory of RFB protocol
|
||||
'''
|
||||
class Factory(protocol.Factory):
|
||||
"""
|
||||
Twisted Factory of RFB protocol
|
||||
"""
|
||||
def buildProtocol(self, addr):
|
||||
'''
|
||||
function call by twisted on connection
|
||||
"""
|
||||
Function call by twisted on connection
|
||||
@param addr: address where client try to connect
|
||||
'''
|
||||
protocol = Rfb(LayerMode.CLIENT)
|
||||
protocol.getController().addObserver(self.buildObserver())
|
||||
return protocol
|
||||
"""
|
||||
return self.buildObserver().getController().getRFBLayer()
|
||||
|
||||
def buildObserver(self):
|
||||
'''
|
||||
build an RFB observer object
|
||||
'''
|
||||
"""
|
||||
Build an RFB observer object
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class RFBClientObserver(object):
|
||||
'''
|
||||
"""
|
||||
RFB client protocol observer
|
||||
'''
|
||||
"""
|
||||
def __init__(self):
|
||||
'''
|
||||
ctor
|
||||
'''
|
||||
self._controller = None
|
||||
self._controller = RFBController(LayerMode.CLIENT)
|
||||
self._controller.addClientObserver(self)
|
||||
|
||||
def getController(self):
|
||||
"""
|
||||
@return: RFB controller use by observer
|
||||
"""
|
||||
return self._controller
|
||||
|
||||
def keyEvent(self, isPressed, key):
|
||||
'''
|
||||
send a key event
|
||||
"""
|
||||
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
|
||||
"""
|
||||
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
|
||||
@@ -537,8 +581,8 @@ class RFBClientObserver(object):
|
||||
self._controller.sendPointerEvent(mask, x, y)
|
||||
|
||||
def onUpdate(self, width, height, x, y, pixelFormat, encoding, data):
|
||||
'''
|
||||
recv framebuffer update
|
||||
"""
|
||||
Receive FrameBuffer update
|
||||
@param width : width of image
|
||||
@param height : height of image
|
||||
@param x : x position
|
||||
@@ -546,5 +590,5 @@ class RFBClientObserver(object):
|
||||
@param pixelFormat : pixel format struct from rfb.types
|
||||
@param encoding : encoding struct from rfb.types
|
||||
@param data : in respect of dataFormat and pixelFormat
|
||||
'''
|
||||
"""
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user