Browse Source

Rewrite fragmented packet detection

master
Richard Neumann 6 months ago
parent
commit
cd6d842ff8
  1. 7
      rcon/source/client.py
  2. 5
      rcon/source/proto.py
  3. 24
      tests/test_local_minecraft_server.py

7
rcon/source/client.py

@ -12,9 +12,7 @@ __all__ = ["Client"]
class Client(BaseClient, socket_type=SOCK_STREAM):
"""An RCON client."""
def __init__(
self, *args, frag_threshold: int = 4096, frag_detect_cmd: str = "", **kwargs
):
def __init__(self, *args, frag_threshold: int = 4096, **kwargs):
"""Set an optional fragmentation threshold and
command in order to detect fragmented packets.
@ -22,7 +20,6 @@ class Client(BaseClient, socket_type=SOCK_STREAM):
"""
super().__init__(*args, **kwargs)
self.frag_threshold = frag_threshold
self.frag_detect_cmd = frag_detect_cmd
def communicate(
self, packet: Packet, raise_unexpected_terminator: bool = False
@ -44,7 +41,7 @@ class Client(BaseClient, socket_type=SOCK_STREAM):
if len(response.payload) < self.frag_threshold:
return response
self.send(Packet.make_command(self.frag_detect_cmd))
self.send(Packet.make_empty_response())
while (successor := Packet.read(file)).id == response.id:
response += successor

5
rcon/source/proto.py

@ -180,6 +180,11 @@ class Packet(NamedTuple):
b" ".join(map(partial(str.encode, encoding=encoding), args)),
)
@classmethod
def make_empty_response(cls) -> Packet:
"""Create an empty response packet."""
return cls(random_request_id(), Type.SERVERDATA_RESPONSE_VALUE, b"")
@classmethod
def make_login(cls, passwd: str, *, encoding: str = "utf-8") -> Packet:
"""Create a login packet."""

24
tests/test_local_minecraft_server.py

@ -0,0 +1,24 @@
from unittest import TestCase
from socket import socket, AF_INET
import pytest
from rcon.source import Client
HOST: str = "localhost"
PORT: int = 25575
class TestLocalMinecraftServer(TestCase):
def setUp(self):
self.client = Client(HOST, PORT, passwd="test")
@pytest.mark.skipif(
socket(AF_INET).connect_ex((HOST, PORT)) != 0,
reason="requires a local Minecraft server to be running",
)
def test_list_empty(self):
with self.client as client:
response = client.run("list")
self.assertEqual(response, "There are 0 of a max of 20 players " "online: ")
Loading…
Cancel
Save