예제 #1
0
async def request_async_impl(conn,
                             encoding,
                             a2s_proto,
                             challenge=0,
                             retries=0,
                             ping=None):
    send_time = time.monotonic()
    resp_data = await conn.request(a2s_proto.serialize_request(challenge))
    recv_time = time.monotonic()
    # Only set ping on first packet received
    if retries == 0:
        ping = recv_time - send_time

    reader = ByteReader(io.BytesIO(resp_data), endian="<", encoding=encoding)

    response_type = reader.read_uint8()
    if response_type == A2S_CHALLENGE_RESPONSE:
        if retries >= DEFAULT_RETRIES:
            raise BrokenMessageError(
                "Server keeps sending challenge responses")
        challenge = reader.read_uint32()
        return await request_async_impl(conn, encoding, a2s_proto, challenge,
                                        retries + 1, ping)

    if not a2s_proto.validate_response_type(response_type):
        raise BrokenMessageError("Invalid response type: " +
                                 hex(response_type))

    return a2s_proto.deserialize_response(reader, response_type, ping)
예제 #2
0
def players_impl(address, timeout, encoding, challenge=0, retries=0):
    resp_data = request(address, b"\x55" + challenge.to_bytes(4, "little"),
                        timeout)
    reader = ByteReader(io.BytesIO(resp_data), endian="<", encoding=encoding)

    response_type = reader.read_uint8()
    if response_type == A2S_CHALLENGE_RESPONSE:
        if retries >= DEFAULT_RETRIES:
            raise BrokenMessageError(
                "Server keeps sending challenge responses")
        challenge = reader.read_uint32()
        return players_impl(address, timeout, encoding, challenge, retries + 1)

    if response_type != A2S_PLAYER_RESPONSE:
        raise BrokenMessageError("Invalid response type: " +
                                 str(response_type))

    player_count = reader.read_uint8()
    resp = [
        Player(index=reader.read_uint8(),
               name=reader.read_cstring(),
               score=reader.read_int32(),
               duration=reader.read_float())
        for player_num in range(player_count)
    ]

    return resp
예제 #3
0
def players_request(conn, encoding, challenge=0, retries=0):
    resp_data = conn.request(b"\x55" + challenge.to_bytes(4, "little"))
    reader = ByteReader(io.BytesIO(resp_data), endian="<", encoding=encoding)

    response_type = reader.read_uint8()
    if response_type == A2S_CHALLENGE_RESPONSE:
        if retries >= DEFAULT_RETRIES:
            raise BrokenMessageError(
                "Server keeps sending challenge responses")
        challenge = reader.read_uint32()
        return players_request(conn, encoding, challenge, retries + 1)

    if response_type != A2S_PLAYER_RESPONSE:
        raise BrokenMessageError("Invalid response type: " +
                                 str(response_type))

    return reader
예제 #4
0
async def rules_request_async(conn, encoding, challenge=0, retries=0):
    resp_data = await conn.request(b"\x56" + challenge.to_bytes(4, "little"))
    reader = ByteReader(io.BytesIO(resp_data), endian="<", encoding=encoding)

    if reader.peek(4) == b"\xFF\xFF\xFF\xFF":
        reader.read(4)

    response_type = reader.read_uint8()
    if response_type == A2S_CHALLENGE_RESPONSE:
        if retries >= DEFAULT_RETRIES:
            raise BrokenMessageError(
                "Server keeps sending challenge responses")
        challenge = reader.read_uint32()
        return await rules_request_async(conn, encoding, challenge,
                                         retries + 1)

    if response_type != A2S_RULES_RESPONSE:
        raise BrokenMessageError("Invalid response type: " +
                                 str(response_type))

    return reader
예제 #5
0
def info_response(resp_data, ping, encoding):
    reader = ByteReader(io.BytesIO(resp_data), endian="<", encoding=encoding)

    response_type = reader.read_uint8()
    if response_type == A2S_INFO_RESPONSE:
        resp = parse_source(reader)
    elif response_type == A2S_INFO_RESPONSE_LEGACY:
        resp = parse_goldsrc(reader)
    else:
        raise BrokenMessageError("Invalid response type: " +
                                 str(response_type))

    resp.ping = ping
    return resp
예제 #6
0
def info(address, timeout=DEFAULT_TIMEOUT, encoding=DEFAULT_ENCODING):
    send_time = time.monotonic()
    resp_data = request(address, b"\x54Source Engine Query\0", timeout)
    recv_time = time.monotonic()
    reader = ByteReader(
        io.BytesIO(resp_data), endian="<", encoding=encoding)

    response_type = reader.read_uint8()
    if response_type == A2S_INFO_RESPONSE:
        resp = parse_source(reader)
    elif response_type == A2S_INFO_RESPONSE_LEGACY:
        resp = parse_goldsrc(reader)
    else:
        raise BrokenMessageError(
            "Invalid response type: " + str(response_type))

    resp.ping = recv_time - send_time
    return resp
예제 #7
0
 def recv(self):
     packet = self._socket.recv(65535)
     header = packet[:4]
     data = packet[4:]
     if header == HEADER_SIMPLE:
         logger.debug("Received single packet: %r", data)
         return data
     elif header == HEADER_MULTI:
         fragments = [decode_fragment(data)]
         while len(fragments) < fragments[0].fragment_count:
             packet = self._socket.recv(4096)
             fragments.append(decode_fragment(packet[4:]))
         fragments.sort(key=lambda f: f.fragment_id)
         reassembled = b"".join(fragment.payload for fragment in fragments)
         logger.debug("Received %s part packet with content: %r",
                      len(fragments), reassembled)
         return reassembled
     else:
         raise BrokenMessageError("Invalid packet header: " + repr(header))