Beispiel #1
0
 def _create_packet(self, id):
     packet = Connection()
     packet.write(self.MAGIC_PREFIX)
     packet.write(struct.pack("!B", id))
     packet.write_uint(0)
     packet.write_int(self.challenge)
     return packet
Beispiel #2
0
    def read_status(self):
        request = Connection()
        request.write_varint(0)  # Request status
        self.connection.write_buffer(request)

        response = self.connection.read_buffer()
        if response.read_varint() != 0:
            raise IOError("Received invalid status response packet.")
        try:
            raw = json.loads(response.read_utf())
        except ValueError:
            raise IOError("Received invalid JSON")
        try:
            return PingResponse(raw)
        except ValueError as e:
            raise IOError("Received invalid status response: %s" % e)
Beispiel #3
0
    def test_ping(self):
        request = Connection()
        request.write_varint(1)  # Test ping
        request.write_long(self.ping_token)
        sent = datetime.datetime.now()
        self.connection.write_buffer(request)

        response = self.connection.read_buffer()
        received = datetime.datetime.now()
        if response.read_varint() != 1:
            raise IOError("Received invalid ping response packet.")
        received_token = response.read_long()
        if received_token != self.ping_token:
            raise IOError("Received mangled ping response packet (expected token %d, received %d)" % (
                self.ping_token, received_token))

        delta = (received - sent)
        # We have no trivial way of getting a time delta :(
        return (delta.days * 24 * 60 * 60 + delta.seconds) * 1000 + delta.microseconds / 1000.0
Beispiel #4
0
    def test_ping(self):
        request = Connection()
        request.write_varint(1)  # Test ping
        request.write_long(self.ping_token)
        sent = datetime.datetime.now()
        self.connection.write_buffer(request)

        response = self.connection.read_buffer()
        received = datetime.datetime.now()
        if response.read_varint() != 1:
            raise IOError("Received invalid ping response packet.")
        received_token = response.read_long()
        if received_token != self.ping_token:
            raise IOError(
                "Received mangled ping response packet (expected token %d, received %d)"
                % (self.ping_token, received_token))

        delta = received - sent
        # We have no trivial way of getting a time delta :(
        return (delta.days * 24 * 60 * 60 +
                delta.seconds) * 1000 + delta.microseconds / 1000.0
Beispiel #5
0
    def handshake(self):
        packet = Connection()
        packet.write_varint(0)
        packet.write_varint(self.version)
        packet.write_utf(self.host)
        packet.write_ushort(self.port)
        packet.write_varint(1)  # Intention to query status

        self.connection.write_buffer(packet)
Beispiel #6
0
 def setUp(self):
     self.connection = Connection()
Beispiel #7
0
class TestConnection(TestCase):
    def setUp(self):
        self.connection = Connection()

    def test_flush(self):
        self.connection.sent = bytearray.fromhex("7FAABB")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FAABB"))
        self.assertTrue(self.connection.sent == "")

    def test_receive(self):
        self.connection.receive(bytearray.fromhex("7F"))
        self.connection.receive(bytearray.fromhex("AABB"))

        self.assertEqual(self.connection.received, bytearray.fromhex("7FAABB"))

    def test_remaining(self):
        self.connection.receive(bytearray.fromhex("7F"))
        self.connection.receive(bytearray.fromhex("AABB"))

        self.assertEqual(self.connection.remaining(), 3)

    def test_send(self):
        self.connection.write(bytearray.fromhex("7F"))
        self.connection.write(bytearray.fromhex("AABB"))

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FAABB"))

    def test_read(self):
        self.connection.receive(bytearray.fromhex("7FAABB"))

        self.assertEqual(self.connection.read(2), bytearray.fromhex("7FAA"))
        self.assertEqual(self.connection.read(1), bytearray.fromhex("BB"))

    def test_readSimpleVarInt(self):
        self.connection.receive(bytearray.fromhex("0F"))

        self.assertEqual(self.connection.read_varint(), 15)

    def test_writeSimpleVarInt(self):
        self.connection.write_varint(15)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("0F"))

    def test_readBigVarInt(self):
        self.connection.receive(bytearray.fromhex("FFFFFFFF7F"))

        self.assertEqual(self.connection.read_varint(), 34359738367)

    def test_writeBigVarInt(self):
        self.connection.write_varint(2147483647)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("FFFFFFFF07"))

    def test_readInvalidVarInt(self):
        self.connection.receive(bytearray.fromhex("FFFFFFFF80"))

        self.assertRaises(IOError, self.connection.read_varint)

    def test_writeInvalidVarInt(self):
        self.assertRaises(ValueError, self.connection.write_varint, 34359738368)

    def test_readUtf(self):
        self.connection.receive(bytearray.fromhex("0D48656C6C6F2C20776F726C6421"))

        self.assertEqual(self.connection.read_utf(), "Hello, world!")

    def test_writeUtf(self):
        self.connection.write_utf("Hello, world!")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("0D48656C6C6F2C20776F726C6421"))

    def test_readEmptyUtf(self):
        self.connection.write_utf("")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("00"))

    def test_readAscii(self):
        self.connection.receive(bytearray.fromhex("48656C6C6F2C20776F726C642100"))

        self.assertEqual(self.connection.read_ascii(), "Hello, world!")

    def test_writeAscii(self):
        self.connection.write_ascii("Hello, world!")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("48656C6C6F2C20776F726C642100"))

    def test_readEmptyAscii(self):
        self.connection.write_ascii("")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("00"))

    def test_readShortNegative(self):
        self.connection.receive(bytearray.fromhex("8000"))

        self.assertEqual(self.connection.read_short(), -32768)

    def test_writeShortNegative(self):
        self.connection.write_short(-32768)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("8000"))

    def test_readShortPositive(self):
        self.connection.receive(bytearray.fromhex("7FFF"))

        self.assertEqual(self.connection.read_short(), 32767)

    def test_writeShortPositive(self):
        self.connection.write_short(32767)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FFF"))

    def test_readUShortPositive(self):
        self.connection.receive(bytearray.fromhex("8000"))

        self.assertEqual(self.connection.read_ushort(), 32768)

    def test_writeUShortPositive(self):
        self.connection.write_ushort(32768)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("8000"))

    def test_readIntNegative(self):
        self.connection.receive(bytearray.fromhex("80000000"))

        self.assertEqual(self.connection.read_int(), -2147483648)

    def test_writeIntNegative(self):
        self.connection.write_int(-2147483648)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("80000000"))

    def test_readIntPositive(self):
        self.connection.receive(bytearray.fromhex("7FFFFFFF"))

        self.assertEqual(self.connection.read_int(), 2147483647)

    def test_writeIntPositive(self):
        self.connection.write_int(2147483647)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FFFFFFF"))

    def test_readUIntPositive(self):
        self.connection.receive(bytearray.fromhex("80000000"))

        self.assertEqual(self.connection.read_uint(), 2147483648)

    def test_writeUIntPositive(self):
        self.connection.write_uint(2147483648)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("80000000"))

    def test_readLongNegative(self):
        self.connection.receive(bytearray.fromhex("8000000000000000"))

        self.assertEqual(self.connection.read_long(), -9223372036854775808)

    def test_writeLongNegative(self):
        self.connection.write_long(-9223372036854775808)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("8000000000000000"))

    def test_readLongPositive(self):
        self.connection.receive(bytearray.fromhex("7FFFFFFFFFFFFFFF"))

        self.assertEqual(self.connection.read_long(), 9223372036854775807)

    def test_writeLongPositive(self):
        self.connection.write_long(9223372036854775807)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FFFFFFFFFFFFFFF"))

    def test_readULongPositive(self):
        self.connection.receive(bytearray.fromhex("8000000000000000"))

        self.assertEqual(self.connection.read_ulong(), 9223372036854775808)

    def test_writeULongPositive(self):
        self.connection.write_ulong(9223372036854775808)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("8000000000000000"))

    def test_readBuffer(self):
        self.connection.receive(bytearray.fromhex("027FAA"))
        buffer = self.connection.read_buffer()

        self.assertEqual(buffer.received, bytearray.fromhex("7FAA"))
        self.assertEqual(self.connection.flush(), bytearray())

    def test_writeBuffer(self):
        buffer = Connection()
        buffer.write(bytearray.fromhex("7FAA"))
        self.connection.write_buffer(buffer)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("027FAA"))
Beispiel #8
0
    def test_writeBuffer(self):
        buffer = Connection()
        buffer.write(bytearray.fromhex("7FAA"))
        self.connection.write_buffer(buffer)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("027FAA"))
Beispiel #9
0
 def _create_packet(self):
     packet = Connection()
     packet.write(self.MAGIC_PREFIX)
     packet.write(struct.pack("!B", self.PACKET_TYPE_QUERY))
     packet.write_uint(self._generate_session_id())
     packet.write_int(self.challenge)
     packet.write(self.PADDING)
     return packet
Beispiel #10
0
 async def _read_packet(self):
     packet = Connection()
     packet.receive(await self.connection.read(self.connection.remaining()))
     packet.read(1 + 4)
     return packet
Beispiel #11
0
class TestMinecraftServer:
    def setup_method(self):
        self.socket = Connection()
        self.server = MinecraftServer("localhost", port=25565)

    def test_ping(self):
        self.socket.receive(bytearray.fromhex("09010000000001C54246"))

        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = self.socket
            latency = self.server.ping(ping_token=29704774, version=47)

        assert self.socket.flush() == bytearray.fromhex(
            "0F002F096C6F63616C686F737463DD0109010000000001C54246")
        assert self.socket.remaining(
        ) == 0, "Data is pending to be read, but should be empty"
        assert latency >= 0

    def test_ping_retry(self):
        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = None
            with patch("mcstatus.server.ServerPinger") as pinger:
                pinger.side_effect = [Exception, Exception, Exception]
                with pytest.raises(Exception):
                    self.server.ping()
                assert pinger.call_count == 3

    def test_status(self):
        self.socket.receive(
            bytearray.fromhex(
                "6D006B7B226465736372697074696F6E223A2241204D696E65637261667420536572766572222C22706C6179657273223A7B226D6178223A32302C226F6E6C696E65223A307D2C2276657273696F6E223A7B226E616D65223A22312E38222C2270726F746F636F6C223A34377D7D09010000000001C54246"
            ))

        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = self.socket
            info = self.server.status(ping_token=29704774, version=47)

        assert self.socket.flush() == bytearray.fromhex(
            "0F002F096C6F63616C686F737463DD01010009010000000001C54246")
        assert self.socket.remaining(
        ) == 0, "Data is pending to be read, but should be empty"
        assert info.raw == {
            "description": "A Minecraft Server",
            "players": {
                "max": 20,
                "online": 0
            },
            "version": {
                "name": "1.8",
                "protocol": 47
            },
        }
        assert info.latency >= 0

    def test_status_retry(self):
        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = None
            with patch("mcstatus.server.ServerPinger") as pinger:
                pinger.side_effect = [Exception, Exception, Exception]
                with pytest.raises(Exception):
                    self.server.status()
                assert pinger.call_count == 3

    def test_query(self):
        self.socket.receive(
            bytearray.fromhex("090000000035373033353037373800"))
        self.socket.receive(
            bytearray.fromhex(
                "00000000000000000000000000000000686f73746e616d650041204d696e656372616674205365727665720067616d657479706500534d500067616d655f6964004d494e4543524146540076657273696f6e00312e3800706c7567696e7300006d617000776f726c64006e756d706c61796572730033006d6178706c617965727300323000686f7374706f727400323535363500686f73746970003139322e3136382e35362e31000001706c617965725f000044696e6e6572626f6e6500446a696e6e69626f6e650053746576650000"
            ))

        self.socket.remaining = Mock()
        self.socket.remaining.side_effect = [15, 208]

        with patch("mcstatus.server.UDPSocketConnection") as connection:
            connection.return_value = self.socket
            info = self.server.query()

        conn_bytes = self.socket.flush()
        assert conn_bytes[:3] == bytearray.fromhex("FEFD09")
        assert info.raw == {
            "hostname": "A Minecraft Server",
            "gametype": "SMP",
            "game_id": "MINECRAFT",
            "version": "1.8",
            "plugins": "",
            "map": "world",
            "numplayers": "3",
            "maxplayers": "20",
            "hostport": "25565",
            "hostip": "192.168.56.1",
        }

    def test_query_retry(self):
        with patch("mcstatus.server.UDPSocketConnection") as connection:
            connection.return_value = None
            with patch("mcstatus.server.ServerQuerier") as querier:
                querier.side_effect = [Exception, Exception, Exception]
                with pytest.raises(Exception):
                    self.server.query()
                assert querier.call_count == 3

    def test_by_address_no_srv(self):
        with patch("dns.resolver.resolve") as resolve:
            resolve.return_value = []
            self.server = MinecraftServer.lookup("example.org")
            resolve.assert_called_once_with("_minecraft._tcp.example.org",
                                            "SRV")
        assert self.server.host == "example.org"
        assert self.server.port == 25565

    def test_by_address_invalid_srv(self):
        with patch("dns.resolver.resolve") as resolve:
            resolve.side_effect = [Exception]
            self.server = MinecraftServer.lookup("example.org")
            resolve.assert_called_once_with("_minecraft._tcp.example.org",
                                            "SRV")
        assert self.server.host == "example.org"
        assert self.server.port == 25565

    def test_by_address_with_srv(self):
        with patch("dns.resolver.resolve") as resolve:
            answer = Mock()
            answer.target = "different.example.org."
            answer.port = 12345
            resolve.return_value = [answer]
            self.server = MinecraftServer.lookup("example.org")
            resolve.assert_called_once_with("_minecraft._tcp.example.org",
                                            "SRV")
        assert self.server.host == "different.example.org"
        assert self.server.port == 12345

    def test_by_address_with_port(self):
        self.server = MinecraftServer.lookup("example.org:12345")
        assert self.server.host == "example.org"
        assert self.server.port == 12345

    def test_by_address_with_multiple_ports(self):
        with pytest.raises(ValueError):
            MinecraftServer.lookup("example.org:12345:6789")

    def test_by_address_with_invalid_port(self):
        with pytest.raises(ValueError):
            MinecraftServer.lookup("example.org:port")
Beispiel #12
0
 def setUp(self):
     self.pinger = ServerPinger(Connection(),
                                host="localhost",
                                port=25565,
                                version=44)
Beispiel #13
0
class TestConnection:
    def setup_method(self):
        self.connection = Connection()

    def test_flush(self):
        self.connection.sent = bytearray.fromhex("7FAABB")

        assert self.connection.flush() == bytearray.fromhex("7FAABB")
        assert self.connection.sent == ""

    def test_receive(self):
        self.connection.receive(bytearray.fromhex("7F"))
        self.connection.receive(bytearray.fromhex("AABB"))

        assert self.connection.received == bytearray.fromhex("7FAABB")

    def test_remaining(self):
        self.connection.receive(bytearray.fromhex("7F"))
        self.connection.receive(bytearray.fromhex("AABB"))

        assert self.connection.remaining() == 3

    def test_send(self):
        self.connection.write(bytearray.fromhex("7F"))
        self.connection.write(bytearray.fromhex("AABB"))

        assert self.connection.flush() == bytearray.fromhex("7FAABB")

    def test_read(self):
        self.connection.receive(bytearray.fromhex("7FAABB"))

        assert self.connection.read(2) == bytearray.fromhex("7FAA")
        assert self.connection.read(1) == bytearray.fromhex("BB")

    def test_readSimpleVarInt(self):
        self.connection.receive(bytearray.fromhex("0F"))

        assert self.connection.read_varint() == 15

    def test_writeSimpleVarInt(self):
        self.connection.write_varint(15)

        assert self.connection.flush() == bytearray.fromhex("0F")

    def test_readBigVarInt(self):
        self.connection.receive(bytearray.fromhex("FFFFFFFF7F"))

        assert self.connection.read_varint() == 34359738367

    def test_writeBigVarInt(self):
        self.connection.write_varint(2147483647)

        assert self.connection.flush() == bytearray.fromhex("FFFFFFFF07")

    def test_readInvalidVarInt(self):
        self.connection.receive(bytearray.fromhex("FFFFFFFF80"))

        with pytest.raises(IOError):
            self.connection.read_varint()

    def test_writeInvalidVarInt(self):
        with pytest.raises(ValueError):
            self.connection.write_varint(34359738368)

    def test_readUtf(self):
        self.connection.receive(bytearray.fromhex("0D48656C6C6F2C20776F726C6421"))

        assert self.connection.read_utf() == "Hello, world!"

    def test_writeUtf(self):
        self.connection.write_utf("Hello, world!")

        assert self.connection.flush() == bytearray.fromhex("0D48656C6C6F2C20776F726C6421")

    def test_readEmptyUtf(self):
        self.connection.write_utf("")

        assert self.connection.flush() == bytearray.fromhex("00")

    def test_readAscii(self):
        self.connection.receive(bytearray.fromhex("48656C6C6F2C20776F726C642100"))

        assert self.connection.read_ascii() == "Hello, world!"

    def test_writeAscii(self):
        self.connection.write_ascii("Hello, world!")

        assert self.connection.flush() == bytearray.fromhex("48656C6C6F2C20776F726C642100")

    def test_readEmptyAscii(self):
        self.connection.write_ascii("")

        assert self.connection.flush() == bytearray.fromhex("00")

    def test_readShortNegative(self):
        self.connection.receive(bytearray.fromhex("8000"))

        assert self.connection.read_short() == -32768

    def test_writeShortNegative(self):
        self.connection.write_short(-32768)

        assert self.connection.flush() == bytearray.fromhex("8000")

    def test_readShortPositive(self):
        self.connection.receive(bytearray.fromhex("7FFF"))

        assert self.connection.read_short() == 32767

    def test_writeShortPositive(self):
        self.connection.write_short(32767)

        assert self.connection.flush() == bytearray.fromhex("7FFF")

    def test_readUShortPositive(self):
        self.connection.receive(bytearray.fromhex("8000"))

        assert self.connection.read_ushort() == 32768

    def test_writeUShortPositive(self):
        self.connection.write_ushort(32768)

        assert self.connection.flush() == bytearray.fromhex("8000")

    def test_readIntNegative(self):
        self.connection.receive(bytearray.fromhex("80000000"))

        assert self.connection.read_int() == -2147483648

    def test_writeIntNegative(self):
        self.connection.write_int(-2147483648)

        assert self.connection.flush() == bytearray.fromhex("80000000")

    def test_readIntPositive(self):
        self.connection.receive(bytearray.fromhex("7FFFFFFF"))

        assert self.connection.read_int() == 2147483647

    def test_writeIntPositive(self):
        self.connection.write_int(2147483647)

        assert self.connection.flush() == bytearray.fromhex("7FFFFFFF")

    def test_readUIntPositive(self):
        self.connection.receive(bytearray.fromhex("80000000"))

        assert self.connection.read_uint() == 2147483648

    def test_writeUIntPositive(self):
        self.connection.write_uint(2147483648)

        assert self.connection.flush() == bytearray.fromhex("80000000")

    def test_readLongNegative(self):
        self.connection.receive(bytearray.fromhex("8000000000000000"))

        assert self.connection.read_long() == -9223372036854775808

    def test_writeLongNegative(self):
        self.connection.write_long(-9223372036854775808)

        assert self.connection.flush() == bytearray.fromhex("8000000000000000")

    def test_readLongPositive(self):
        self.connection.receive(bytearray.fromhex("7FFFFFFFFFFFFFFF"))

        assert self.connection.read_long() == 9223372036854775807

    def test_writeLongPositive(self):
        self.connection.write_long(9223372036854775807)

        assert self.connection.flush() == bytearray.fromhex("7FFFFFFFFFFFFFFF")

    def test_readULongPositive(self):
        self.connection.receive(bytearray.fromhex("8000000000000000"))

        assert self.connection.read_ulong() == 9223372036854775808

    def test_writeULongPositive(self):
        self.connection.write_ulong(9223372036854775808)

        assert self.connection.flush() == bytearray.fromhex("8000000000000000")

    def test_readBuffer(self):
        self.connection.receive(bytearray.fromhex("027FAA"))
        buffer = self.connection.read_buffer()

        assert buffer.received == bytearray.fromhex("7FAA")
        assert self.connection.flush() == bytearray()

    def test_writeBuffer(self):
        buffer = Connection()
        buffer.write(bytearray.fromhex("7FAA"))
        self.connection.write_buffer(buffer)

        assert self.connection.flush() == bytearray.fromhex("027FAA")
Beispiel #14
0
 def setup_method(self):
     self.connection = Connection()
Beispiel #15
0
    def test_writeBuffer(self):
        buffer = Connection()
        buffer.write(bytearray.fromhex("7FAA"))
        self.connection.write_buffer(buffer)

        assert self.connection.flush() == bytearray.fromhex("027FAA")
Beispiel #16
0
 def setUp(self):
     self.connection = Connection()
Beispiel #17
0
class TestConnection(TestCase):
    def setUp(self):
        self.connection = Connection()

    def test_flush(self):
        self.connection.sent = bytearray.fromhex("7FAABB")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FAABB"))
        self.assertTrue(self.connection.sent == "")

    def test_receive(self):
        self.connection.receive(bytearray.fromhex("7F"))
        self.connection.receive(bytearray.fromhex("AABB"))

        self.assertEqual(self.connection.received, bytearray.fromhex("7FAABB"))

    def test_remaining(self):
        self.connection.receive(bytearray.fromhex("7F"))
        self.connection.receive(bytearray.fromhex("AABB"))

        self.assertEqual(self.connection.remaining(), 3)

    def test_send(self):
        self.connection.write(bytearray.fromhex("7F"))
        self.connection.write(bytearray.fromhex("AABB"))

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FAABB"))

    def test_read(self):
        self.connection.receive(bytearray.fromhex("7FAABB"))

        self.assertEqual(self.connection.read(2), bytearray.fromhex("7FAA"))
        self.assertEqual(self.connection.read(1), bytearray.fromhex("BB"))

    def test_readSimpleVarInt(self):
        self.connection.receive(bytearray.fromhex("0F"))

        self.assertEqual(self.connection.read_varint(), 15)

    def test_writeSimpleVarInt(self):
        self.connection.write_varint(15)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("0F"))

    def test_readBigVarInt(self):
        self.connection.receive(bytearray.fromhex("FFFFFFFF7F"))

        self.assertEqual(self.connection.read_varint(), 34359738367)

    def test_writeBigVarInt(self):
        self.connection.write_varint(2147483647)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("FFFFFFFF07"))

    def test_readInvalidVarInt(self):
        self.connection.receive(bytearray.fromhex("FFFFFFFF80"))

        self.assertRaises(IOError, self.connection.read_varint)

    def test_writeInvalidVarInt(self):
        self.assertRaises(ValueError, self.connection.write_varint,
                          34359738368)

    def test_readUtf(self):
        self.connection.receive(
            bytearray.fromhex("0D48656C6C6F2C20776F726C6421"))

        self.assertEqual(self.connection.read_utf(), "Hello, world!")

    def test_writeUtf(self):
        self.connection.write_utf("Hello, world!")

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("0D48656C6C6F2C20776F726C6421"))

    def test_readEmptyUtf(self):
        self.connection.write_utf("")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("00"))

    def test_readAscii(self):
        self.connection.receive(
            bytearray.fromhex("48656C6C6F2C20776F726C642100"))

        self.assertEqual(self.connection.read_ascii(), "Hello, world!")

    def test_writeAscii(self):
        self.connection.write_ascii("Hello, world!")

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("48656C6C6F2C20776F726C642100"))

    def test_readEmptyAscii(self):
        self.connection.write_ascii("")

        self.assertEqual(self.connection.flush(), bytearray.fromhex("00"))

    def test_readShortNegative(self):
        self.connection.receive(bytearray.fromhex("8000"))

        self.assertEqual(self.connection.read_short(), -32768)

    def test_writeShortNegative(self):
        self.connection.write_short(-32768)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("8000"))

    def test_readShortPositive(self):
        self.connection.receive(bytearray.fromhex("7FFF"))

        self.assertEqual(self.connection.read_short(), 32767)

    def test_writeShortPositive(self):
        self.connection.write_short(32767)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("7FFF"))

    def test_readUShortPositive(self):
        self.connection.receive(bytearray.fromhex("8000"))

        self.assertEqual(self.connection.read_ushort(), 32768)

    def test_writeUShortPositive(self):
        self.connection.write_ushort(32768)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("8000"))

    def test_readIntNegative(self):
        self.connection.receive(bytearray.fromhex("80000000"))

        self.assertEqual(self.connection.read_int(), -2147483648)

    def test_writeIntNegative(self):
        self.connection.write_int(-2147483648)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("80000000"))

    def test_readIntPositive(self):
        self.connection.receive(bytearray.fromhex("7FFFFFFF"))

        self.assertEqual(self.connection.read_int(), 2147483647)

    def test_writeIntPositive(self):
        self.connection.write_int(2147483647)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("7FFFFFFF"))

    def test_readUIntPositive(self):
        self.connection.receive(bytearray.fromhex("80000000"))

        self.assertEqual(self.connection.read_uint(), 2147483648)

    def test_writeUIntPositive(self):
        self.connection.write_uint(2147483648)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("80000000"))

    def test_readLongNegative(self):
        self.connection.receive(bytearray.fromhex("8000000000000000"))

        self.assertEqual(self.connection.read_long(), -9223372036854775808)

    def test_writeLongNegative(self):
        self.connection.write_long(-9223372036854775808)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("8000000000000000"))

    def test_readLongPositive(self):
        self.connection.receive(bytearray.fromhex("7FFFFFFFFFFFFFFF"))

        self.assertEqual(self.connection.read_long(), 9223372036854775807)

    def test_writeLongPositive(self):
        self.connection.write_long(9223372036854775807)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("7FFFFFFFFFFFFFFF"))

    def test_readULongPositive(self):
        self.connection.receive(bytearray.fromhex("8000000000000000"))

        self.assertEqual(self.connection.read_ulong(), 9223372036854775808)

    def test_writeULongPositive(self):
        self.connection.write_ulong(9223372036854775808)

        self.assertEqual(self.connection.flush(),
                         bytearray.fromhex("8000000000000000"))

    def test_readBuffer(self):
        self.connection.receive(bytearray.fromhex("027FAA"))
        buffer = self.connection.read_buffer()

        self.assertEqual(buffer.received, bytearray.fromhex("7FAA"))
        self.assertEqual(self.connection.flush(), bytearray())

    def test_writeBuffer(self):
        buffer = Connection()
        buffer.write(bytearray.fromhex("7FAA"))
        self.connection.write_buffer(buffer)

        self.assertEqual(self.connection.flush(), bytearray.fromhex("027FAA"))
Beispiel #18
0
 def setup_method(self):
     self.querier = ServerQuerier(Connection())
Beispiel #19
0
 def setUp(self):
     self.socket = Connection()
     self.server = MinecraftServer("localhost", port=25565)
Beispiel #20
0
    def handshake(self):
        packet = Connection()
        packet.write_varint(0)
        packet.write_varint(self.version)
        packet.write_utf(self.host)
        packet.write_short(self.port)
        packet.write_varint(1)  # Intention to query status

        self.connection.write_buffer(packet)
Beispiel #21
0
 def _read_packet(self):
     packet = Connection()
     packet.receive(self.connection.read(self.connection.remaining()))
     packet.read(1 + 4)
     return packet
Beispiel #22
0
 def setup_method(self):
     self.socket = Connection()
     self.server = MinecraftServer("localhost", port=25565)
Beispiel #23
0
 def _create_handshake_packet(self):
     packet = Connection()
     packet.write(self.MAGIC_PREFIX)
     packet.write(struct.pack("!B", self.PACKET_TYPE_CHALLENGE))
     packet.write_uint(self._generate_session_id())
     return packet
Beispiel #24
0
 def setUp(self):
     self.querier = ServerQuerier(Connection())
Beispiel #25
0
class TestMinecraftServer(TestCase):
    def setUp(self):
        self.socket = Connection()
        self.server = MinecraftServer("localhost", port=25565)

    def test_ping(self):
        self.socket.receive(bytearray.fromhex("09010000000001C54246"))

        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = self.socket
            latency = self.server.ping(ping_token=29704774, version=47)

        self.assertEqual(self.socket.flush(), bytearray.fromhex("0F002F096C6F63616C686F737463DD0109010000000001C54246"))
        self.assertEqual(self.socket.remaining(), 0, msg="Data is pending to be read, but should be empty")
        self.assertTrue(latency >= 0)

    def test_ping_retry(self):
        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = None
            with patch("mcstatus.server.ServerPinger") as pinger:
                pinger.side_effect = [Exception, Exception, Exception]
                self.assertRaises(Exception, self.server.ping)
                self.assertEqual(pinger.call_count, 3)

    def test_status(self):
        self.socket.receive(bytearray.fromhex("6D006B7B226465736372697074696F6E223A2241204D696E65637261667420536572766572222C22706C6179657273223A7B226D6178223A32302C226F6E6C696E65223A307D2C2276657273696F6E223A7B226E616D65223A22312E38222C2270726F746F636F6C223A34377D7D09010000000001C54246"))

        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = self.socket
            info = self.server.status(ping_token=29704774, version=47)

        self.assertEqual(self.socket.flush(), bytearray.fromhex("0F002F096C6F63616C686F737463DD01010009010000000001C54246"))
        self.assertEqual(self.socket.remaining(), 0, msg="Data is pending to be read, but should be empty")
        self.assertEqual(info.raw, {"description":"A Minecraft Server","players":{"max":20,"online":0},"version":{"name":"1.8","protocol":47}})
        self.assertTrue(info.latency >= 0)

    def test_status_retry(self):
        with patch("mcstatus.server.TCPSocketConnection") as connection:
            connection.return_value = None
            with patch("mcstatus.server.ServerPinger") as pinger:
                pinger.side_effect = [Exception, Exception, Exception]
                self.assertRaises(Exception, self.server.status)
                self.assertEqual(pinger.call_count, 3)

    def test_query(self):
        self.socket.receive(bytearray.fromhex("090000000035373033353037373800"))
        self.socket.receive(bytearray.fromhex("00000000000000000000000000000000686f73746e616d650041204d696e656372616674205365727665720067616d657479706500534d500067616d655f6964004d494e4543524146540076657273696f6e00312e3800706c7567696e7300006d617000776f726c64006e756d706c61796572730033006d6178706c617965727300323000686f7374706f727400323535363500686f73746970003139322e3136382e35362e31000001706c617965725f000044696e6e6572626f6e6500446a696e6e69626f6e650053746576650000"))

        self.socket.remaining = Mock()
        self.socket.remaining.side_effect = [15, 208]

        with patch("mcstatus.server.UDPSocketConnection") as connection:
            connection.return_value = self.socket
            info = self.server.query()

        self.assertEqual(self.socket.flush(), bytearray.fromhex("FEFD090000000000000000FEFD000000000021FEDCBA00000000"))
        self.assertEqual(info.raw, {
            "hostname": "A Minecraft Server",
            "gametype": "SMP",
            "game_id": "MINECRAFT",
            "version": "1.8",
            "plugins": "",
            "map": "world",
            "numplayers": "3",
            "maxplayers": "20",
            "hostport": "25565",
            "hostip": "192.168.56.1",
        })

    def test_query_retry(self):
        with patch("mcstatus.server.UDPSocketConnection") as connection:
            connection.return_value = None
            with patch("mcstatus.server.ServerQuerier") as querier:
                querier.side_effect = [Exception, Exception, Exception]
                self.assertRaises(Exception, self.server.query)
                self.assertEqual(querier.call_count, 3)

    def test_by_address_no_srv(self):
        with patch("dns.resolver.query") as query:
            query.return_value = []
            self.server = MinecraftServer.lookup("example.org")
            query.assert_called_once_with("_minecraft._tcp.example.org", "SRV")
        self.assertEqual(self.server.host, "example.org")
        self.assertEqual(self.server.port, 25565)

    def test_by_address_invalid_srv(self):
        with patch("dns.resolver.query") as query:
            query.side_effect = [Exception]
            self.server = MinecraftServer.lookup("example.org")
            query.assert_called_once_with("_minecraft._tcp.example.org", "SRV")
        self.assertEqual(self.server.host, "example.org")
        self.assertEqual(self.server.port, 25565)

    def test_by_address_with_srv(self):
        with patch("dns.resolver.query") as query:
            answer = Mock()
            answer.target = "different.example.org."
            answer.port = 12345
            query.return_value = [answer]
            self.server = MinecraftServer.lookup("example.org")
            query.assert_called_once_with("_minecraft._tcp.example.org", "SRV")
        self.assertEqual(self.server.host, "different.example.org")
        self.assertEqual(self.server.port, 12345)

    def test_by_address_with_port(self):
        self.server = MinecraftServer.lookup("example.org:12345")
        self.assertEqual(self.server.host, "example.org")
        self.assertEqual(self.server.port, 12345)

    def test_by_address_with_multiple_ports(self):
        self.assertRaises(ValueError, MinecraftServer.lookup, "example.org:12345:6789")

    def test_by_address_with_invalid_port(self):
        self.assertRaises(ValueError, MinecraftServer.lookup, "example.org:port")