Beispiel #1
0
async def open_connection(host: str, port: int,
                          streamch: SendCh[net.JSONStream]) -> None:
    """ open connection with server.

    1. open connection
    2. send on channel
    3. wait for 'log in' message from server
    4. close channel
    """

    raw = await trio.open_tcp_stream(host, port)
    stream = net.JSONStream(raw)

    log.info(f"connection open {stream}")

    await streamch.send(stream)

    async def wait_for_login(stream: net.JSONStream) -> None:
        """ reads until the server says to log in """
        resp = await stream.read()
        if resp != {"type": "log in"}:
            log.error(f"invalid resp {resp}")
            await wait_for_login(stream)

    log.debug(f"waiting for 'log in' request {stream}")

    await wait_for_login(stream)

    log.debug(f"closing streamch {stream}")
    await streamch.aclose()
Beispiel #2
0
    async def spawn(
        connch: SendCh[trio.abc.Stream],
        playerch: RecvCh[Player],
        quitch: SendCh[Player],
    ) -> None:

        left, right = new_half_stream_pair()

        await connch.send(right)
        assert await left.read() == {"type": "log in"}
        await left.write({"type": "log in", "username": "******"})
        assert await left.read() == {
            "type": "log in update",
            "state": "accepted"
        }

        # the initiator should spit the player out
        player = await playerch.receive()

        assert player.username == "first"
        assert player.stream == net.JSONStream(right)

        # player quits from the lobby or a sub, or anything that isn't the
        # initiator
        await quitch.send(player)

        left, right = new_half_stream_pair()

        await connch.send(right)
        assert await left.read() == {"type": "log in"}
        # notice how we use the same username. It shouldn't block, because
        # the other quitted
        await left.write({"type": "log in", "username": "******"})
        assert await left.read() == {
            "type": "log in update",
            "state": "accepted"
        }

        player = await playerch.receive()

        assert player.username == "first"
        assert player.stream == net.JSONStream(right)

        await conn_sendch.aclose()
        await quit_sendch.aclose()
Beispiel #3
0
    async def get_players(playerch: RecvCh[Player]) -> None:
        order = ["quick", "average", "slow", "late", "average2", "closing"]

        i = 0
        async for player in playerch:
            assert player.username == order[i]
            assert player.stream == net.JSONStream(
                conns[order[i]][1]), f"{order[i]!r} stream differs"
            i += 1
Beispiel #4
0
async def initiate_conn(
    rawstream: trio.abc.Stream,
    playerch: SendCh[Player],
    usernameslk: Lockable[List[str]],
) -> None:

    log.debug("initiating stream")

    stream = net.JSONStream(rawstream)

    with trio.move_on_after(120) as cancel_scope:

        username = None

        try:

            log.debug("asking for log in infos")

            await stream.write({"type": "log in"})

            log.debug("getting valid username")

            username = await get_username(stream, usernameslk)
            if username is None:
                return log.info("connection dropped")

            player = Player(stream, username)

            log.debug(f"{username!r} accepted")

            await stream.write({"type": "log in update", "state": "accepted"})

        except net.ConnectionClosed as e:
            log.warning("connection dropped", exc_info=e)

            # remove username from the list of usernames
            if username is not None:
                async with usernameslk as usernames:
                    try:
                        usernames.remove(username)
                    except ValueError:
                        pass
            return

        log.info("conn initialized %s", player)

    if cancel_scope.cancelled_caught:
        return log.warning("initiating conn: dropping after timeout %s",
                           stream)

    # copy the username, because once it's sent on the channel, I shouldn't
    # access player
    username = player.username
    await playerch.send(player)
    log.info("player '%s' sent", username)
Beispiel #5
0
async def test_read_chuncky_connection(objects):
    """ Make sure that JSON stream works when texts doesn't come in nicely """
    with trio.move_on_after(1) as cancel_scope:
        a, stream_controlled = trio.testing.memory_stream_pair()
        stream_tested = net.JSONStream(a)
        string = '\n'.join(json.dumps(obj) for obj in objects) + '\n'

        async with trio.open_nursery() as n:
            n.start_soon(_send_string_by_chunks, stream_controlled, string)
            n.start_soon(_assert_reading, stream_tested, objects)
    assert cancel_scope.cancelled_caught is False
Beispiel #6
0
async def test_read_multiple_object_per_message(objects):
    """ Make sure that JSON stream can read multiple objects in one read (one
    message) """

    with trio.move_on_after(1) as cancel_scope:
        a, stream_controlled = trio.testing.memory_stream_pair()
        stream_tested = net.JSONStream(a)
        string = '\n'.join(json.dumps(obj) for obj in objects) + '\n'
        async with trio.open_nursery() as n:
            n.start_soon(_assert_reading, stream_tested, objects)
            n.start_soon(stream_controlled.send_all,
                         bytes(string, encoding='utf-8'))

    assert cancel_scope.cancelled_caught is False
Beispiel #7
0
    async def accept_players(self, stream):
        """ Accepts players and puts them into self.players once
        they are ready for the game loop """
        log.info("New connection")

        player = Player(net.JSONStream(stream))

        try:
            log.debug("Waiting for player name")
            await player.get_username()
        except net.ConnectionClosed:
            log.info(f"{player} connection closed")
        except Exception as e:
            log.exception("Initiater crashed")
        else:
            await self.initiate_player(player)
Beispiel #8
0
def new_stream_player(username: str) -> Tuple[Player, Player]:
    left, right = trio.testing.memory_stream_pair()
    return (
        Player(net.JSONStream(left), username),
        Player(net.JSONStream(right), username),
    )
Beispiel #9
0
def new_half_stream_pair() -> Tuple[net.JSONStream, trio.abc.Stream]:
    left, right = trio.testing.memory_stream_pair()
    client = net.JSONStream(left)
    return client, right
Beispiel #10
0
 async def connect_to_server(self):
     log.debug("Connecting to server...")
     self.pdata.stream = net.JSONStream(await trio.open_tcp_stream(
         "localhost", PORT))
     self.state = STATE_WAITING_INPUT
     log.info(f"Connected to server ({self.state})")
Beispiel #11
0
def new_stream_pair() -> Tuple[net.JSONStream, net.JSONStream]:
    left, right = trio.testing.memory_stream_pair()
    return net.JSONStream(left), net.JSONStream(right)