Ejemplo n.º 1
0
 def test_context_add_2_listeners(self):
     ws = self.test_ws
     OTHER_WS = WebSocket(self.mock_socket, self.environ)
     ctx = self.ctx
     ctx.add_listener(ws)
     ctx.add_listener(OTHER_WS)
     eq_(len(ctx.listeners), 2)
Ejemplo n.º 2
0
    def setUp(self):
        self.mock_socket = s = mock.Mock()
        self.environ = env = dict(HTTP_ORIGIN='http://localhost', HTTP_WEBSOCKET_PROTOCOL='ws',
                                  PATH_INFO='test')

        self.test_ws = WebSocket(s, env)
        super(TestWebSocketObject, self).setUp()
Ejemplo n.º 3
0
    def setUp(self):
        self.ctx = WebSocketAwareResource()
        self.mock_socket = s = mock.Mock()
        self.environ = env = dict(HTTP_ORIGIN='http://localhost',
                                  HTTP_WEBSOCKET_PROTOCOL='ws',
                                  PATH_INFO='test')

        self.test_ws = WebSocket(s, env)
Ejemplo n.º 4
0
 def __init__(self, sock ):
     resp = httplib.HTTPResponse( sock, method='GET' )
     resp.begin()
     self.status = resp.status
     environ = { 
         'HTTP_ORIGIN': resp.getheader( 'HTTP_ORIGIN', '' ),
         'HTTP_WEBSOCKET_PROTOCOL': resp.getheader( 'HTTP_WEBSOCKET_PROTOCOL', '' ),
         'PATH_INFO': resp.getheader( 'PATH_INFO', '' ) }
     self.sock = WebSocket( sock=sock, environ=environ, version=0 )
Ejemplo n.º 5
0
    def __send_error(self, ws: WebSocket, error: Errors, info: dict = None):
        """
        Send an error to a client via the WebSocket connection.

        :param ws: WebSocket object.
        :param error: Error which has occurred.
        :param info: Additional info about the error if needed.
        :return:
        """
        # log the error being sent
        self.logger.warning("Error being sent to client: '" +
                            str(error.value) + "' | info: '" + str(info) + "'")

        # send the error to the client via the websocket
        ws.send(
            self.encoder.encode("error", {
                "error": error.value,
                "info": info
            }))
Ejemplo n.º 6
0
 def test_context_add_listeners(self):
     ws = self.test_ws
     OTHER_WS = WebSocket(self.mock_socket, self.environ)
     ctx = self.ctx
     eq_(ctx.listeners, set())
     ctx.add_listener(ws)
     eq_(ctx.listeners, set([ws]))
     ctx.add_listener(ws)
     eq_(ctx.listeners, set([ws]))
     ctx.remove_listener(OTHER_WS)
     eq_(ctx.listeners, set([ws]))
     ctx.remove_listener(ws)
     eq_(ctx.listeners, set())
Ejemplo n.º 7
0
class WebSocketResponse( object ):
    def __init__(self, sock ):
        resp = httplib.HTTPResponse( sock, method='GET' )
        resp.begin()
        self.status = resp.status
        environ = { 
            'HTTP_ORIGIN': resp.getheader( 'HTTP_ORIGIN', '' ),
            'HTTP_WEBSOCKET_PROTOCOL': resp.getheader( 'HTTP_WEBSOCKET_PROTOCOL', '' ),
            'PATH_INFO': resp.getheader( 'PATH_INFO', '' ) }
        self.sock = WebSocket( sock=sock, environ=environ, version=0 )

    def send( self, message ):
        result = self.sock.send( message )
        eventlet.sleep(0.001)
        return result

    def recv( self ):
        result = self.sock.wait()
        eventlet.sleep(0.001)
        return result

    def close( self ):
        sock.close()
        eventlet.sleep(0.01)
Ejemplo n.º 8
0
    def socket(self, ws: WebSocket):
        # parse out client information from url
        args = parse(environ=ws.environ)

        # get headers
        headers = dict(ws.environ["headers_raw"])
        """
        for key, value in headers.items():
            print(key + ": ", value)
        """

        # if id is omitted
        if "IoT-IO-Id" not in headers.keys():
            # send error message to client
            self.__send_error(ws, Errors.CLIENT_NO_ID)

            raise ClientNoId()

        # if type is omitted
        if "IoT-IO-Type" not in headers.keys():
            # send error message to client
            self.__send_error(ws, Errors.CLIENT_NO_TYPE)

            raise ClientNoType()

        # if protocol version is omitted
        if "IoT-IO-ProtocolVersion" not in headers.keys():
            # send error message to client
            self.__send_error(ws, Errors.CLIENT_NO_PROTOCOL_VERSION)

            raise ClientNoProtocolVersion()

        # if data is omitted populate with default value
        if "IoT-IO-Data" not in headers.keys():
            headers["IoT-IO-Data"] = "{}"

        # if endpoints are omitted populate with default value
        if "IoT-IO-Endpoints" not in headers.keys():
            headers["IoT-IO-Endpoints"] = "[]"

        # deserialize headers
        try:
            headers["IoT-IO-Data"] = json.loads(headers["IoT-IO-Data"])
        except json.JSONDecodeError:
            # send error message to client
            self.__send_error(ws, Errors.CLIENT_INVALID_DATA)

            raise ClientInvalidData()

        try:
            headers["IoT-IO-Endpoints"] = json.loads(
                headers["IoT-IO-Endpoints"])
        except json.JSONDecodeError:
            # send error message to client
            self.__send_error(ws, Errors.CLIENT_INVALID_ENDPOINTS, {
                "endpointId": "",
                "endpointProblem": "invalid_json"
            })

            raise ClientInvalidEndpoints()

        # check if the client's protocol version matches that of the server
        if headers["IoT-IO-ProtocolVersion"] != __protocol_version__:
            # send error message to client
            self.__send_error(ws, Errors.CLIENT_INCOMPATIBLE_PROTOCOL_VERSION)

            raise ClientIncompatibleProtocolVersion()

        # check if the client has a valid type
        if self.__types.get(headers["IoT-IO-Type"], None) is None:
            # log and exit if the client has an invalid type
            self.logger.warning(
                "Client with ID '" + args["id"] +
                "' claimed a device type of '" + args["type"] +
                "' but no such device type was defined. Refusing connection.")

            # send error message to client
            self.__send_error(ws, Errors.CLIENT_INVALID_TYPE)

            # abort connection
            raise ClientInvalidType()

        # remove a client with the same id if it exists (getting rid of ghost clients)
        self.remove(headers["IoT-IO-Id"])

        # create a new client
        client = IoTClient(ws,
                           headers["IoT-IO-Id"],
                           headers["IoT-IO-Type"],
                           headers["IoT-IO-Data"],
                           self,
                           logging_level=self.client_logging_level,
                           encoder=self.encoder)

        # parse endpoints
        endpoint_id, response = client.parse_endpoints(
            headers["IoT-IO-Endpoints"])

        if response != EndpointParseResponse.VALID:
            self.__send_error(ws, Errors.CLIENT_INVALID_ENDPOINTS, {
                "endpointId": endpoint_id,
                "endpointProblem": response.value
            })

            raise ClientInvalidEndpoints()

        self.add(client)

        # client loop
        try:
            data = ""

            while data is not None:
                # wait for message from the websocket
                data = ws.wait()

                # if the message is None check if the connection is closed
                if data is None:
                    break

                # decode received message
                event, message = self.encoder.decode(data)

                # call the callback associated with the event
                event, response = self.__handle_event_message(
                    event, message, client)

                # check if there is a response to send to the client
                if response is not None:
                    try:
                        client.emit(event, response)
                    except ConnectionEnded:
                        return
        except BrokenPipeError:
            pass
        finally:
            self.remove(client)