Esempio n. 1
0
async def main_ws(request):
    ws = WebSocketResponse()

    session = await get_session(request)
    expires = session.get('expires', 0)
    await ws.prepare(request)
    if expires < time():
        await ws.close(code=4403)
        return ws

    user = '******'.format(
        **session['user']).strip(' ')
    logger.info('ws connection from %s', user)
    json_str = await request.app['pg'].fetchval(calls_sql)
    await ws.send_str(json_str or '[]')
    request.app['ws_propagator'].add_ws(ws)
    try:
        async for msg in ws:
            logger.info('ws message:', msg)
            if msg.tp == WSMsgType.ERROR:
                logger.warning('ws connection closed with exception %s',
                               ws.exception())
    except CancelledError:
        pass
    finally:
        request.app['ws_propagator'].remove_ws(ws)
        logger.info('websocket disconnected: %s', user)
    return ws
Esempio n. 2
0
async def websocket_handler(request):
    """
    Handle websocket connections
    """
    ws = WebSocketResponse()
    await ws.prepare(request)

    logger.info("New websocket connection")
    request.app["websockets"].add(ws)
    snapshot_processor = request.app["snapshot_processor"]

    async for msg in ws:

        if msg.type == aiohttp.WSMsgType.TEXT:
            try:
                message = msg.json()
            except (TypeError, ValueError):
                await ws.send_json({"success": False, "message": "Can't load provided JSON"})
            else:
                await snapshot_processor.process_user_message(ws, message)

        elif msg.type == aiohttp.WSMsgType.ERROR:
            logger.info('ws connection closed with exception %s' % ws.exception())

    logger.info("Websocket disconnect. Cleaning")
    await snapshot_processor.unsubscribe(ws)
    request.app["websockets"].remove(ws)

    return ws
    async def test_close_connections(self, mocker, bike_connection_manager):
        """Assert that closing the connection is handled gracefully."""

        mocked_close = mocker.patch('aiohttp.web_ws.WebSocketResponse.close')
        mocked_close.side_effect = self.conn_generator()
        r0, r1 = WebSocketResponse(), WebSocketResponse()
        bike_connection_manager._bike_connections[0] = r0
        bike_connection_manager._bike_connections[1] = r1
        await bike_connection_manager.close_connections()
        assert mocked_close.call_count == 2
        assert not bike_connection_manager._bike_connections
    async def test_add_connection_closes_previous(self, mocker,
                                                  bike_connection_manager,
                                                  random_bike):
        """Assert that adding a new socket closes the first."""

        mocked_close = mocker.patch('aiohttp.web_ws.WebSocketResponse.close')
        mocked_close.side_effect = self.conn_generator()

        r0, r1 = WebSocketResponse(), WebSocketResponse()

        await bike_connection_manager.add_connection(random_bike, r0)
        await bike_connection_manager.add_connection(random_bike, r1)

        assert mocked_close.call_count == 1
    async def test_send_command(self, mocker, bike_connection_manager,
                                random_bike):
        """Assert that you can send a connection to the bike using send_command."""
        async def assert_data(json):
            assert json["jsonrpc"] == "2.0"
            assert json["id"] == 1
            assert json["method"] == "test_command"
            assert "params" in json

        patched_send = mocker.patch(
            'aiohttp.web_ws.WebSocketResponse.send_json')
        patched_send.side_effect = assert_data
        patched_counter = mocker.patch(
            'server.service.manager.bike_connection_manager.BikeConnectionManager._next_rpc_id',
            new_callable=PropertyMock)
        patched_counter.return_value = 1

        r0 = WebSocketResponse()
        await bike_connection_manager.add_connection(random_bike, r0)

        with pytest.raises(TimeoutError):
            await bike_connection_manager._send_command(
                random_bike, "test_command", timeout=timedelta(seconds=0.01))

        assert patched_counter.call_count == 1
Esempio n. 6
0
def stream(request):
    redis_pool = yield from create_redis_pool(1)
    subscriber = yield from redis_pool.start_subscribe()
    yield from subscriber.subscribe([CURRENT_COST_KEY])
    ws = WebSocketResponse()
    ws.start(request)
    continue_loop = True
    while continue_loop:
        reply = yield from subscriber.next_published()
        if ws.closed:
            logger.info('leaving web socket stream, usubscribing')
            yield from subscriber.unsubscribe()
            continue_loop = False
        else:
            ws.send_str(reply.value)

    return ws
 async def test_is_connected(self, bike_connection_manager, random_bike):
     """Assert that when the socket disappears, so does the bike connection."""
     r0 = WebSocketResponse()
     await bike_connection_manager.add_connection(random_bike, r0)
     bike_connection_manager._bike_locations[random_bike.id] = None
     bike_connection_manager._bike_battery[random_bike.id] = None
     bike_connection_manager._bike_locked[random_bike.id] = None
     assert bike_connection_manager.is_connected(random_bike)
     del r0
     assert not bike_connection_manager.is_connected(random_bike)
Esempio n. 8
0
 async def listen_for_close(self, ws: WebSocketResponse) -> None:
     async for msg in ws:
         if msg.type == aiohttp.WSMsgType.TEXT:
             if msg.data == 'close':
                 await ws.close()
                 logger.info("closed websocket")
             if msg.data == 'pong':
                 self.pong_event.set()
         elif msg.type == aiohttp.WSMsgType.ERROR:
             logger.error('ws connection closed with exception %s' %
                          ws.exception())
    async def test_add_connection_closed(self, mocker, bike_connection_manager,
                                         random_bike):
        """Assert that adding a closed connection fails."""

        mocked_close = mocker.patch('aiohttp.web_ws.WebSocketResponse.close')
        mocked_close.side_effect = self.conn_generator()
        mocked_closed = mocker.patch('aiohttp.web_ws.WebSocketResponse.closed')
        mocked_closed.return_value = True

        with pytest.raises(ConnectionError):
            await bike_connection_manager.add_connection(
                random_bike, WebSocketResponse())
Esempio n. 10
0
class WebsocketHandler:

    def __init__(self, request):
        self.request = request
        self.remote = request.remote
        self.peername = request.transport.get_extra_info('peername')
        self.pubsub = request.app['pubsub']
        self.response = WebSocketResponse()

    def __repr__(self):
        return f"<WebsocketSubscriber {self.remote}: {self.peername}>"

    async def send_metric(self, key, value):
        message = json_dumps({key: value})
        await self.response.send_str(message)

    async def send_json(self, *a, **kw):
        data = dict(*a, **kw)
        message = json_dumps(data)
        await self.response.send_str(message)

    async def loop(self):
        await self.response.prepare(self.request)
        logger.debug("ws prepared")

        async for msg in self.response:
            if msg.type == WSMsgType.TEXT:
                try:
                    data = json.loads(msg.data)
                    self._parse_command(data)
                except Exception as e:
                    await self.send_json(error=format_exception(e))
                    logger.exception('Exception in message %r', msg)
            elif msg.type == WSMsgType.ERROR:
                logger.error('ws connection closed with exception %s',
                             self.response.exception())
                break
            else:
                logger.warning("ws message: %s", msg)

        self.pubsub.unsubscribe(self)
        logger.debug("Websocket closed: %r", self)
        return self.response

    def _parse_command(self, data):
        if 'subscribe' in data and isinstance(data['subscribe'], str):
            self.pubsub.subscribe(data['subscribe'], self)
        else:
            raise ValueError("invalid command")
Esempio n. 11
0
    async def handle(self, request):
        ws = WebSocketResponse()
        await ws.prepare(request)

        handler = GrozaHandler()

        conn = GrozaServerConnection(handler,
                                     WsAiohttpServerTransportResponse(ws))

        await self._server.notify_connection_start(conn)

        try:
            await conn.handle()
        finally:
            await self._server.notify_connection_close(conn)

        return ws
Esempio n. 12
0
async def news_websocket_handler(request):
    ws = WebSocketResponse()
    await ws.prepare(request)
    profile_id = 0
    async for ws_msg in ws:
        if ws_msg.type == aiohttp.WSMsgType.TEXT:
            profile_id = await check_has_profile(ws_msg.data, request['conn'])
        break

    queue = request.app['queue']
    async for msg in queue.receive():
        if msg['profile']['id'] in await followed_profiles(request['conn'], profile_id):
            name = f'{msg["profile"]["first_name"]} {msg["profile"]["last_name"]}'
            await ws.send_str(f'''
                <p>
                    <a href="/profiles/post/{msg["id"]}">{msg["text"][:50]}...</a> by
                    <a href="{msg["profile"]["id"]}">{name}</a></p>''')
    return ws
    async def test_resolve_command(self, mocker, bike_connection_manager,
                                   random_bike):
        """Assert that an opened request can be resolved."""
        async def noop(json):
            pass

        patched_send = mocker.patch(
            'aiohttp.web_ws.WebSocketResponse.send_json')
        patched_send.side_effect = noop

        r0 = WebSocketResponse()
        rpc = RPC(1, r0, "command")
        bike_connection_manager._pending_commands[random_bike.id][1] = rpc

        rpc_request = rpc()
        rpc_resolver = bike_connection_manager.resolve_command(
            random_bike, 1, "returned_data")

        returned_data, _ = await gather(rpc_request, rpc_resolver)
        assert returned_data == "returned_data"
Esempio n. 14
0
async def websocket_handler(request):
    resp = WebSocketResponse()
    await resp.prepare(request)

    async with AsyncTail(filepath=request.app['filepath']) as atail:
        async for line in atail:
            resp.send_str(json.dumps({'action': 'sent', 'text': line}))

    resp.send_str(json.dumps({
        'action': 'close',
    }))

    await resp.close()

    return resp
Esempio n. 15
0
 def __init__(self, request):
     self.request = request
     self.remote = request.remote
     self.peername = request.transport.get_extra_info('peername')
     self.pubsub = request.app['pubsub']
     self.response = WebSocketResponse()
Esempio n. 16
0
async def unload_sock(request: Request):
    """
    WebSocket view to detect when Messenger closes the WebView.

    There is a dual mechanism:

        - If "unload" is received over the socket, then close instantly
        - If no heartbeat is received for some time, them close

    The URL must include signed information about the user, like what
    the `sign_webview` parameter of UrlButton would provide.
    """

    tk = request.query.get(settings.WEBVIEW_TOKEN_KEY)

    if not tk:
        return json_response(
            {
                'error': True,
                'message': 'Missing "{}"'.format(settings.WEBVIEW_TOKEN_KEY),
            },
            status=400)

    try:
        tk = jwt.decode(tk, settings.WEBVIEW_SECRET_KEY)
    except jwt.InvalidTokenError:
        return json_response(
            {
                'error': True,
                'message': 'Provided token is invalid'
            },
            status=400)

    try:
        user_id = tk['fb_psid']
        assert isinstance(user_id, Text)
        page_id = tk['fb_pid']
        assert isinstance(page_id, Text)
        slug = tk['slug']
        assert isinstance(slug, Text) or slug is None
    except (KeyError, AssertionError):
        return json_response(
            {
                'error': True,
                'message': 'Provided payload is invalid'
            },
            status=400)

    event = {
        'sender': {
            'id': user_id,
        },
        'recipient': {
            'id': page_id,
        },
        'url_base': str(request.url),
        'close_webview': {
            'slug': slug,
        },
    }

    ws = WebSocketResponse(timeout=settings.WEBVIEW_HEARTBEAT_TIMEOUT,
                           receive_timeout=settings.WEBVIEW_HEARTBEAT_TIMEOUT)
    await ws.prepare(request)

    inhibit = False

    try:
        # noinspection PyTypeChecker
        async for msg in ws:
            # For some reason, the timeout does not work without a print
            # Yeah, what the f**k right?
            # TODO make it work properly
            print('hack print')
            if msg.type == WSMsgType.TEXT:
                if msg.data == 'unload':
                    break
                if msg.data == 'inhibit':
                    inhibit = True
            elif msg.type == WSMsgType.ERROR:
                break
    except asyncio.TimeoutError:
        pass

    if not inhibit:
        fb = await manager.get_platform('facebook')
        msg = FacebookMessage(event, fb, False)
        await fb.handle_event(msg)

    return ws
 async def test_add_connection(self, bike_connection_manager, random_bike):
     """Assert that the list of connected bikes is maintained."""
     r0 = WebSocketResponse()
     await bike_connection_manager.add_connection(random_bike, r0)
     assert len(list(
         bike_connection_manager._bike_connections.values())) == 1