Skip to content

Commit

Permalink
Moved base class for Packet in mojang.api.net.common
Browse files Browse the repository at this point in the history
  • Loading branch information
Lucino772 committed Apr 19, 2021
1 parent a66fcd6 commit a32eeca
Show file tree
Hide file tree
Showing 9 changed files with 124 additions and 107 deletions.
File renamed without changes.
2 changes: 1 addition & 1 deletion mojang/api/net/query/packets/handshake.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import struct
import time

from .base import Packet
from ...common.packet import Packet

class HandhakeRequest(Packet):
magic: int = 0xFEFD
Expand Down
2 changes: 1 addition & 1 deletion mojang/api/net/query/packets/stats.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import struct

from .base import Packet
from ...common.packet import Packet

class BasicStatsRequest(Packet):
magic: int = 0xFEFD
Expand Down
105 changes: 0 additions & 105 deletions mojang/api/net/rcon.py

This file was deleted.

1 change: 1 addition & 0 deletions mojang/api/net/rcon/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .client import RconClient
78 changes: 78 additions & 0 deletions mojang/api/net/rcon/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import struct
import socket
import select

from ..common.packet import Packet
from .packets.login import LoginRequest, LoginResponse
from .packets.command import CommandRequest, CommandResponse

class RconClient:

def __init__(self, host: str, port: int, password: str):
self.__sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.__host = (host, port)
self.__password = password

self.__id__ = 0

@property
def _new_id(self):
self.__id__ += 1
return self.__id__

def _recv(self, cls: Packet = None):
if select.select([self.__sock], [], [], 1)[0]:
with self.__sock.makefile('rb') as stream:
packet_length = struct.unpack('<i', stream.read(4))[0]

data = b''
while len(data) < packet_length:
_data = stream.read(packet_length - len(data))
if _data:
data += _data
if cls:
return cls.create_from(data)
else:
return data

def _send(self, packet: Packet):
if select.select([], [self.__sock], [], 1)[1]:
with self.__sock.makefile('wb') as stream:
data = bytes(packet)
stream.write(struct.pack('<i', len(data)))
stream.write(data)

def connect(self):
self.__sock.connect(self.__host)
self.__sock.setblocking(False)
self._authenticate()

def _authenticate(self):
packet = LoginRequest(id=self._new_id, payload=self.__password)
self._send(packet)

r_packet = self._recv(LoginResponse)

if r_packet.type != 2 or r_packet.id == -1:
raise Exception('Authentication Failed !')

def run_cmd(self, cmd: str):
packet = CommandRequest(id=self._new_id, payload=cmd)
self._send(packet)

response = ''
try:
while 1:
r_packet = self._recv(CommandResponse)
if r_packet is None:
break

if r_packet.type != 0 or r_packet.id != packet.id:
raise Exception('Error while getting the response')

response += r_packet.payload
finally:
return response

def close(self):
self.__sock.close()
Empty file.
22 changes: 22 additions & 0 deletions mojang/api/net/rcon/packets/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import struct

from ...common.packet import Packet

class CommandRequest(Packet):
type: int = 2
id: int
payload: str

def _bytes(self):
encoded_payload = self.payload.encode('ascii')
return struct.pack('<ii{}s2s'.format(len(encoded_payload)), self.id, self.type, encoded_payload, b'\0\0')

class CommandResponse(Packet):
type: int
id: int
payload: str

@classmethod
def _parse(cls, buffer: bytes):
request_id, _type, payload = struct.unpack_from('<ii{}s'.format(len(buffer) - 10), buffer)
return dict(type=_type,id=request_id,payload=payload.decode('ascii'))
21 changes: 21 additions & 0 deletions mojang/api/net/rcon/packets/login.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import struct

from ...common.packet import Packet

class LoginRequest(Packet):
type: int = 3
id: int
payload: str

def _bytes(self):
encoded_payload = self.payload.encode('ascii')
return struct.pack('<ii{}s2s'.format(len(encoded_payload)), self.id, self.type, encoded_payload, b'\0\0')

class LoginResponse(Packet):
type: int
id: int

@classmethod
def _parse(cls, buffer: bytes):
request_id, _type, _ = struct.unpack_from('<ii{}s'.format(len(buffer) - 10), buffer)
return dict(type=_type,id=request_id)

0 comments on commit a32eeca

Please sign in to comment.