Ejemplo n.º 1
0
    def websocket(self):
        """ Websocket main server """
        set_thread_name('WebsocketServer')

        async def register_websocket(websocket, path):
            address = websocket.remote_address if websocket.remote_address \
                else '<unknown client>'

            self.logger.info('New websocket connection from {} on path {}'.format(address, path))
            self.active_websockets.add(websocket)

            try:
                await websocket.recv()
            except ConnectionClosed:
                self.logger.info('Websocket client {} closed connection'.format(address))
                self.active_websockets.remove(websocket)
                if address in self._websocket_locks:
                    del self._websocket_locks[address]

        websocket_args = {}
        if self.ssl_context:
            websocket_args['ssl'] = self.ssl_context

        self._websocket_loop = get_or_create_event_loop()
        self._websocket_loop.run_until_complete(
            websocket_serve(register_websocket, self.bind_address, self.websocket_port,
                             **websocket_args))
        self._websocket_loop.run_forever()
Ejemplo n.º 2
0
    def notify_web_clients(self, event):
        """ Notify all the connected web clients (over websocket) of a new event """
        import websockets

        async def send_event(ws):
            try:
                self._acquire_websocket_lock(ws)
                await ws.send(str(event))
            except Exception as e:
                self.logger.warning(
                    'Error on websocket send_event: {}'.format(e))
            finally:
                self._release_websocket_lock(ws)

        loop = get_or_create_event_loop()
        wss = self.active_websockets.copy()

        for _ws in wss:
            try:
                loop.run_until_complete(send_event(_ws))
            except websockets.exceptions.ConnectionClosed:
                self.logger.warning(
                    'Websocket client {} connection lost'.format(
                        _ws.remote_address))
                self.active_websockets.remove(_ws)
                if _ws.remote_address in self._websocket_locks:
                    del self._websocket_locks[_ws.remote_address]
Ejemplo n.º 3
0
    def run(self):
        super().run()
        self.register_service(port=self.port, name='ws')

        # noinspection PyUnusedLocal
        async def serve_client(websocket, path):
            self.active_websockets.add(websocket)
            self.logger.debug('New websocket connection from {}'.format(
                websocket.remote_address[0]))

            try:
                while True:
                    if self.client_timeout:
                        msg = await asyncio.wait_for(
                            websocket.recv(), timeout=self.client_timeout)
                    else:
                        msg = await websocket.recv()

                    msg = Message.build(msg)
                    self.logger.info('Received message from {}: {}'.format(
                        websocket.remote_address[0], msg))

                    self.on_message(msg)

                    if isinstance(msg, Request):
                        response = self.get_message_response(msg) or Response()
                        self.logger.info(
                            'Processing response on the websocket backend: {}'.
                            format(response))

                        await websocket.send(str(response))

            except websockets.exceptions.ConnectionClosed as e:
                self.active_websockets.remove(websocket)
                self.logger.debug(
                    'Websocket client {} closed connection'.format(
                        websocket.remote_address[0]))
            except asyncio.TimeoutError as e:
                self.active_websockets.remove(websocket)
                self.logger.debug(
                    'Websocket connection to {} timed out'.format(
                        websocket.remote_address[0]))
            except Exception as e:
                self.logger.exception(e)

        self.logger.info(
            'Initialized websocket backend on port {}, bind address: {}'.
            format(self.port, self.bind_address))

        websocket_args = {}
        if self.ssl_context:
            websocket_args['ssl'] = self.ssl_context

        loop = get_or_create_event_loop()
        server = websockets.serve(serve_client, self.bind_address, self.port,
                                  **websocket_args)

        loop.run_until_complete(server)
        loop.run_forever()
Ejemplo n.º 4
0
    def send(self,
             url,
             msg,
             ssl_cert=None,
             ssl_key=None,
             ssl_cafile=None,
             ssl_capath=None,
             *args,
             **kwargs):
        """
        Sends a message to a websocket.

        :param url: Websocket URL, e.g. ws://localhost:8765 or wss://localhost:8765
        :type topic: str

        :param msg: Message to be sent. It can be a list, a dict, or a Message object

        :param ssl_cert: Path to the SSL certificate to be used, if the SSL connection requires client authentication as well (default: None)
        :type ssl_cert: str

        :param ssl_key: Path to the SSL key to be used, if the SSL connection requires client authentication as well (default: None)
        :type ssl_key: str

        :param ssl_cafile: Path to the certificate authority file if required by the SSL configuration (default: None)
        :type ssl_cafile: str

        :param ssl_capath: Path to the certificate authority directory if required by the SSL configuration (default: None)
        :type ssl_capath: str
        """
        async def send():
            websocket_args = {}
            if ssl_cert:
                websocket_args['ssl'] = get_ssl_client_context(
                    ssl_cert=ssl_cert,
                    ssl_key=ssl_key,
                    ssl_cafile=ssl_cafile,
                    ssl_capath=ssl_capath)

            async with websockets.connect(url, **websocket_args) as websocket:
                try:
                    await websocket.send(str(msg))
                except websockets.exceptions.ConnectionClosed:
                    self.logger.warning('Error on websocket {}: {}'.format(
                        url, e))

        try:
            msg = json.dumps(msg)
        except:
            pass

        try:
            msg = Message.build(json.loads(msg))
        except:
            pass

        loop = get_or_create_event_loop()
        loop.run_until_complete(send())
Ejemplo n.º 5
0
    def notify_web_clients(self, event):
        """ Notify all the connected web clients (over websocket) of a new event """
        async def send_event(websocket):
            try:
                await websocket.send(str(event))
            except Exception as e:
                self.logger.warning(
                    'Error on websocket send_event: {}'.format(e))

        loop = get_or_create_event_loop()
        active_websockets = self.active_websockets.copy()

        for websocket in active_websockets:
            try:
                loop.run_until_complete(send_event(websocket))
            except websockets.exceptions.ConnectionClosed:
                self.logger.info('Client connection lost')
                self.active_websockets.remove(websocket)