Browse Source

Outsourced client into own module.

pull/2/head
Richard Neumann 4 years ago
parent
commit
9a38e6b7e8
  1. 2
      rcon/__init__.py
  2. 86
      rcon/client.py
  3. 2
      rcon/console.py
  4. 2
      rcon/gui.py
  5. 89
      rcon/proto.py
  6. 4
      rcon/rconclt.py
  7. 4
      rcon/rconshell.py

2
rcon/__init__.py

@ -1,8 +1,8 @@
"""RCON client library."""
from rcon.asyncio import rcon
from rcon.client import Client
from rcon.exceptions import RequestIdMismatch, WrongPassword
from rcon.proto import Client
__all__ = ['RequestIdMismatch', 'WrongPassword', 'Client', 'rcon']

86
rcon/client.py

@ -0,0 +1,86 @@
"""Synchronous client."""
from socket import socket
from typing import Optional
from rcon.exceptions import RequestIdMismatch, WrongPassword
from rcon.proto import Packet
__all__ = ['Client']
class Client:
"""An RCON client."""
__slots__ = ('_socket', 'host', 'port', 'passwd')
def __init__(self, host: str, port: int, *,
timeout: Optional[float] = None,
passwd: Optional[str] = None):
"""Initializes the base client with the SOCK_STREAM socket type."""
self._socket = socket()
self.host = host
self.port = port
self.timeout = timeout
self.passwd = passwd
def __enter__(self):
"""Attempts an auto-login if a password is set."""
self._socket.__enter__()
self.connect(login=True)
return self
def __exit__(self, typ, value, traceback):
"""Delegates to the underlying socket's exit method."""
return self._socket.__exit__(typ, value, traceback)
@property
def timeout(self) -> float:
"""Returns the socket timeout."""
return self._socket.gettimeout()
@timeout.setter
def timeout(self, timeout: float):
"""Sets the socket timeout."""
self._socket.settimeout(timeout)
def connect(self, login: bool = False) -> None:
"""Connects the socket and attempts a
login if wanted and a password is set.
"""
self._socket.connect((self.host, self.port))
if login and self.passwd is not None:
self.login(self.passwd)
def close(self) -> None:
"""Closes the socket connection."""
self._socket.close()
def communicate(self, packet: Packet) -> Packet:
"""Sends and receives a packet."""
with self._socket.makefile('wb') as file:
file.write(bytes(packet))
with self._socket.makefile('rb') as file:
return Packet.read(file)
def login(self, passwd: str) -> bool:
"""Performs a login."""
response = self.communicate(Packet.make_login(passwd))
if response.id == -1:
raise WrongPassword()
return True
def run(self, command: str, *arguments: str, raw: bool = False) -> str:
"""Runs a command."""
request = Packet.make_command(command, *arguments)
response = self.communicate(request)
if response.id != request.id:
raise RequestIdMismatch(request.id, response.id)
return response if raw else response.payload

2
rcon/console.py

@ -2,9 +2,9 @@
from getpass import getpass
from rcon.client import Client
from rcon.config import Config
from rcon.exceptions import RequestIdMismatch, WrongPassword
from rcon.proto import Client
__all__ = ['rconcmd']

2
rcon/gui.py

@ -13,9 +13,9 @@ require_version('Gtk', '3.0')
# pylint: disable=C0413
from gi.repository import Gtk
from rcon.client import Client
from rcon.config import LOG_FORMAT
from rcon.exceptions import RequestIdMismatch, WrongPassword
from rcon.proto import Client
__all__ = ['main']

89
rcon/proto.py

@ -4,19 +4,10 @@ from __future__ import annotations
from enum import Enum
from logging import getLogger
from random import randint
from socket import SOCK_STREAM, socket
from typing import IO, NamedTuple, Optional
from typing import IO, NamedTuple
from rcon.exceptions import RequestIdMismatch, WrongPassword
__all__ = [
'LittleEndianSignedInt32',
'Type',
'Packet',
'Client',
'random_request_id'
]
__all__ = ['LittleEndianSignedInt32', 'Type', 'Packet', 'random_request_id']
LOGGER = getLogger(__file__)
@ -139,79 +130,3 @@ class Packet(NamedTuple):
def make_login(cls, passwd: str) -> Packet:
"""Creates a login packet."""
return cls(random_request_id(), Type.SERVERDATA_AUTH, passwd)
class Client:
"""An RCON client."""
__slots__ = ('_socket', 'host', 'port', 'passwd')
def __init__(self, host: str, port: int, *,
timeout: Optional[float] = None,
passwd: Optional[str] = None):
"""Initializes the base client with the SOCK_STREAM socket type."""
self._socket = socket(type=SOCK_STREAM)
self.host = host
self.port = port
self.timeout = timeout
self.passwd = passwd
def __enter__(self):
"""Attempts an auto-login if a password is set."""
self._socket.__enter__()
self.connect(login=True)
return self
def __exit__(self, typ, value, traceback):
"""Delegates to the underlying socket's exit method."""
return self._socket.__exit__(typ, value, traceback)
@property
def timeout(self) -> float:
"""Returns the socket timeout."""
return self._socket.gettimeout()
@timeout.setter
def timeout(self, timeout: float):
"""Sets the socket timeout."""
self._socket.settimeout(timeout)
def connect(self, login: bool = False) -> None:
"""Connects the socket and attempts a
login if wanted and a password is set.
"""
self._socket.connect((self.host, self.port))
if login and self.passwd is not None:
self.login(self.passwd)
def close(self) -> None:
"""Closes the socket connection."""
self._socket.close()
def communicate(self, packet: Packet) -> Packet:
"""Sends and receives a packet."""
with self._socket.makefile('wb') as file:
file.write(bytes(packet))
with self._socket.makefile('rb') as file:
return Packet.read(file)
def login(self, passwd: str) -> bool:
"""Performs a login."""
response = self.communicate(Packet.make_login(passwd))
if response.id == -1:
raise WrongPassword()
return True
def run(self, command: str, *arguments: str, raw: bool = False) -> str:
"""Runs a command."""
request = Packet.make_command(command, *arguments)
response = self.communicate(request)
if response.id != request.id:
raise RequestIdMismatch(request.id, response.id)
return response if raw else response.payload

4
rcon/rconclt.py

@ -4,9 +4,9 @@ from argparse import ArgumentParser, Namespace
from logging import DEBUG, INFO, basicConfig, getLogger
from pathlib import Path
from rcon.errorhandler import ErrorHandler
from rcon.client import Client
from rcon.config import CONFIG_FILES, LOG_FORMAT, from_args
from rcon.proto import Client
from rcon.errorhandler import ErrorHandler
__all__ = ['main']

4
rcon/rconshell.py

@ -4,10 +4,10 @@ from argparse import ArgumentParser, Namespace
from logging import INFO, basicConfig, getLogger
from pathlib import Path
from rcon.errorhandler import ErrorHandler
from rcon.readline import CommandHistory
from rcon.config import CONFIG_FILES, LOG_FORMAT, from_args
from rcon.console import PROMPT, rconcmd
from rcon.errorhandler import ErrorHandler
from rcon.readline import CommandHistory
__all__ = ['get_args', 'main']

Loading…
Cancel
Save