Example #1
0
File: comm.py Project: LCROBOT/rce
class RCERobotProtocol(WebSocketClientProtocol):
    """ WebSocket client protocol which is used to communicate with the Robot
        Manager.
    """
    def __init__(self, connection):
        """ Initialize the protocol.
            
            @param connection:      Connection instance which provides callback
                                    functions.
            @type  connection:      pyrce.connection._Connection
        """
        self._connection = connection
        self._assembler = MessageAssembler(self, 60)
        self._registered = False
    
    def onOpen(self):
        """ This method is called by twisted as soon as the websocket
            connection has been successfully established.
        """
        self._assembler.start()
        self._connection.registerConnection(self)
        self._registered = True
    
    def onMessage(self, msg, binary):
        """ This method is called by twisted when a new message has been
            received.
        """
        self._assembler.processMessage(msg, binary)
    
    def processCompleteMessage(self, msg):
        """ Callback for MessageAssembler which will be called as soon as a
            message has been completed and is ready for processing.
        """
        self._connection.receivedMessage(msg)
    
    def onClose(self, *a):
        """ This method is called by twisted when the connection has been
            closed.
        """
        if self._registered:
            self._connection.unregisterConnection(self)
            self._assembler.stop()
            self._registered = False
    
    def failHandshake(self, reason):
        """ This method is called by twisted when the connection could not be
            initialized.
        """
        print(reason)
        WebSocketClientProtocol.failHandshake(self, reason)
Example #2
0
class RobotWebSocketProtocol(WebSocketServerProtocol):
    """ Protocol which is used for the connections from the robots to the
        robot manager.
    """
    def __init__(self, manager):
        """ Initialize the Protocol.
        """
        self._manager = manager
        self._userID = None
        self._robotID = None
        self._msgHandler = {}
        self._assembler = MessageAssembler(self, definition.MSG_QUEUE_TIMEOUT)
    
    def onConnect(self, req):
        """ Method is called by the Autobahn engine when a request to establish
            a connection has been received.
            
            @param req:     Connection Request object.
            @type  req:     autobahn.websocket.ConnectionRequest
            
            @raise:         autobahn.websocket.HttpException
        """
        params = req.params
        
        try:
            userID = params['userID']
            robotID = params['robotID']
            key = params['key']
        except KeyError as e:
            raise HttpException(httpstatus.HTTP_STATUS_CODE_BAD_REQUEST[0],
                                'Request is missing parameter: {0}'.format(e))
        
        for name, param in [('userID', userID),
                            ('robotID', robotID),
                            ('key', key)]:
            if len(param) != 1:
                raise HttpException(httpstatus.HTTP_STATUS_CODE_BAD_REQUEST[0],
                                    "Parameter '{0}' has to be unique in "
                                    'request.'.format(name))
        
        userID = userID[0]
        robotID = robotID[0]
        key = key[0]
        
        try:
            self._manager.robotConnected(userID, robotID, key, self)
        except AuthenticationError as e:
            raise HttpException(httpstatus.HTTP_STATUS_CODE_FORBIDDEN[0],
                                str(e))
        except Exception as e:
            import traceback
            raise HttpException(
                httpstatus.HTTP_STATUS_CODE_INTERNAL_SERVER_ERROR[0],
                traceback.format_exc()
            )
            
        self._robotID = robotID
        self._userID = userID
        
        # TODO: List should probably not be hard coded here,
        #       but given as an argument...
        for handler in [ CreateContainerHandler(self._manager, userID),
                         DestroyContainerHandler(self._manager, userID),
                         ConfigureContainerHandler(self._manager, userID),
                         ConnectInterfacesHandler(self._manager, userID),
                         DataMessageHandler(self._manager, userID) ]:
            verifyObject(IClientMsgHandler, handler)
            self._msgHandler[handler.TYPE] = handler
        
        self._assembler.start()
        return None
    
    def processCompleteMessage(self, msg):
        """ Process complete messages by calling the appropriate handler for
            the manager. (Called by client.protocol.BinaryAssembler)
        """
        try:
            msgType = msg['type']
            data = msg['data']
        except KeyError as e:
            raise InvalidRequest('Message is missing key: {0}'.format(e))
        
        try:
            self._msgHandler[msgType].handle(data)
        except KeyError as e:
            raise InvalidRequest('This message type is not supported.')
    
    def onMessage(self, msg, binary):
        """ Method is called by the Autobahn engine when a message has been
            received from the client.
        """
        log.msg('WebSocket: Received new message from client. '
                '(binary={0})'.format(binary))
        
        resp = None
        
        try:
            self._assembler.processMessage(msg, binary)
        except InvalidRequest as e:
            #resp = 'Invalid Request: {0}'.format(e)
            import traceback
            resp = traceback.format_exc()
            msgType = types.ERROR
        except AuthenticationError as e:
            #resp =  'Authentication Error: {0}'.format(e)
            import traceback
            resp = traceback.format_exc()
            msgType = types.ERROR
        except Exception as e:   # TODO: Refine Error handling
            #import sys, traceback
            #WebSocketServerProtocol.sendMessage(self, '\n'.join(
            #    traceback.format_exception_only(type(e), e)))
            
            # Full debug message
            import traceback
            resp = traceback.format_exc()
            msgType = types.ERROR
        
        if resp:
            self.sendMessage({'data' : resp, 'type' : msgType})
    
    def sendMessage(self, msg):
        """ This method is called by the User instance to send a message to the
            robot.
            
            @param msg:     Message which should be sent
        """
        uriBinary, msgURI = recursiveBinarySearch(msg)
        
        WebSocketServerProtocol.sendMessage(self, json.dumps(msgURI))
        
        for binData in uriBinary:
            WebSocketServerProtocol.sendMessage(self,
                binData[0] + binData[1].getvalue(), binary=True)
    
    def onClose(self, wasClean, code, reason):
        """ Method is called by the Autobahn engine when the connection has
            been lost.
        """
        if self._userID and self._robotID:
            self._manager.robotClosed(self._userID, self._robotID)
        
        self._assembler.stop()
        self._assembler = None