Final commit before archive
This commit is contained in:
5
sampy/handlers/__init__.py
Normal file
5
sampy/handlers/__init__.py
Normal file
@@ -0,0 +1,5 @@
|
||||
from . import mainHandler
|
||||
from . import serverQueryHandler
|
||||
from . import handshakeHandler
|
||||
from . import unknownHandler
|
||||
from . import queueHandler
|
||||
18
sampy/handlers/handshakeHandler.py
Normal file
18
sampy/handlers/handshakeHandler.py
Normal file
@@ -0,0 +1,18 @@
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from ..network.enums import types as TYPE
|
||||
from .. import glob
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def handle(client: "Client", data: bytes) -> bytes:
|
||||
challenge = (client.ip_uint ^ glob.challenge_short) & TYPE.MAX_USHORT
|
||||
challenge_solution = challenge ^ 0x6969 # 0x6969 being client_version?
|
||||
|
||||
challenge_answer = struct.unpack_from(b">H", data, 1)[0]
|
||||
|
||||
if challenge_answer != challenge_solution:
|
||||
return struct.pack(b">BH", 0x1A, challenge)
|
||||
client.state = 1 # CHALLENGE_PASSED
|
||||
return b"\x19\x00" # 0x19: Valid_challenge; leading 0x00 byte due to some routers shitting itself if only 1 byte is sent/received
|
||||
31
sampy/handlers/mainHandler.py
Normal file
31
sampy/handlers/mainHandler.py
Normal file
@@ -0,0 +1,31 @@
|
||||
from importlib import reload
|
||||
|
||||
import random
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from . import handshakeHandler
|
||||
from . import unknownHandler
|
||||
from . import queueHandler
|
||||
|
||||
from ..helpers.byteFormater import readable_bytes
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
HANDLERS = {
|
||||
0x18: handshakeHandler.handle,
|
||||
0x00: unknownHandler.handle,
|
||||
0xe3: queueHandler.handle
|
||||
}
|
||||
|
||||
def handle(client: "Client", data: bytes) -> bytes:
|
||||
out: bytes = HANDLERS.get(data[0], unimplemented)(client, data)
|
||||
|
||||
return out
|
||||
|
||||
def unimplemented(client: "Client", data: bytes) -> bytes:
|
||||
logger.debug("[%s] sent unhandled data: %s" % (client.addr, readable_bytes(data)))
|
||||
return bytes([x for x in range(1,32,1)])
|
||||
|
||||
def restart():
|
||||
reload(handshakeHandler)
|
||||
53
sampy/handlers/old_mainHandler.py
Normal file
53
sampy/handlers/old_mainHandler.py
Normal file
@@ -0,0 +1,53 @@
|
||||
"""
|
||||
if client.state == 0: # Perform handshake if possible
|
||||
client.state = 1
|
||||
return b"\x1a\x1e\xd1\xd1"
|
||||
if client.state == 1:
|
||||
client.state = 2
|
||||
return b"\x19\x00"
|
||||
if client.state == 2:
|
||||
client.state = 3
|
||||
return b"\xe3\x00\x00", b"\x00\x00\x42\x98\x0c\x11\x33\x45\x30\x42\x33\x33\x35\x32\x37\x34\x46\x39\x31\x43\x39\x39\x00"
|
||||
if client.state == 3:
|
||||
client.state = 4
|
||||
return
|
||||
if client.state == 4:
|
||||
client.state = 5
|
||||
return b"\xe3\x01\x00", b"\x00\x80\x42\x68\x22\xc0\xa8\x02\x87\xfb\xaa\x00\x00\x04\x41\x00\x00"
|
||||
if client.state <= 7:
|
||||
client.state += 1
|
||||
return
|
||||
if client.state == 8:
|
||||
client.state = 9
|
||||
return b"\xe5\x02\x00\x02\x00\x02\x80\x00"
|
||||
if client.state == 9:
|
||||
client.state = 10
|
||||
return b"\x01\x00\x32\x28\x06\xbf\xf9\xca\x0f\x03\x00\x87\x00\x29\x04\x00\x64\x90\x09\xaa\xf9\xca\x0f\xbf\xf9\xca\x0f\x05\x00\x87\x00\x17", b"\x03\x00\x32\x28\x06\xc5\xf9\xca\x0f"
|
||||
if client.state == 10:
|
||||
client.state = 11
|
||||
return b"\x03\x80\x32\x48\x09\xb0\xf9\xca\x0f\xd1\xf9\xca\x0f"
|
||||
if client.state == 11:
|
||||
client.state = 12
|
||||
return b"\xe3\x07\x00"
|
||||
if client.state == 12:
|
||||
client.state = 13
|
||||
return b"\x04\x00\x48\x80\x00\x11\xe0\x14\x3c\xe2\x0e\x2f\x9c\xa0\xf0\x09\x00\x91\x00\x80\x0f\xc1\x00\x14\x8b\xcb\x61\x00\x00\x80\x38\x8d\x00\x00\x8c\x42\x40\x20\x00\x00\x00\x00\x10\x10\x00\x00\x00\xc0\x16\xf1\x20\x33\xc0\x00\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\xa0\x00\x00\x00\x08\x00\x00\x00\x04\x00\x00\x00\x05\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
if client.state == 13:
|
||||
client.state = 14
|
||||
return
|
||||
if client.state == 14:
|
||||
client.state = 15
|
||||
return b"\xe3\x0a\x00", b"\x05\x00\x48\x80\x80\x13\xe0\x14\x0c\xe6\x01\xbc\xcf\x44\x40\x8e\x5a\x74\x45\xdf\xe7\x54\x10\x0b\x00\x91\x01\x80\x27\xc0\x14\x9d\xe6\x01\xbc\xcf\x44\x40\x8e\x5a\x74\x45\xdf\xe7\x54\x10\x0c\x00\x91\x02\x00\x28\x40\x14\x9e\xe6\x81\xbc\xcf\x44\x40\x8e\x5a\x74\x45\xdf\xe7\x54\x10\x20\x0d\x00\x82\x6c\x04\x14\x80\xcf\x00\x20\x3f\xe0\x00\x00\x00\x00\x03\x79\x9e\x88\x81\x1c\xb4\xe8\x8b\xbf\xce\xa8\x27\xb2\x50\xc8\x60\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
if client.state == 15:
|
||||
client.state = 16
|
||||
return
|
||||
if client.state == 16:
|
||||
client.state = 17
|
||||
return b"\xe3\x0b\x00", b"\x07\x00\x42\x20\x14\x81\xf8\x01"
|
||||
if client.state == 17:
|
||||
client.state = 18
|
||||
return
|
||||
if client.state == 18:
|
||||
#client.state = 19
|
||||
return b"\xe3\x0c\x00", b"\x07\x80\x38\x40\x00\x11\x40\xd0\x00\x00\x00\x00"
|
||||
"""
|
||||
11
sampy/handlers/queueHandler.py
Normal file
11
sampy/handlers/queueHandler.py
Normal file
@@ -0,0 +1,11 @@
|
||||
import logging
|
||||
import struct
|
||||
|
||||
from ..network.enums import types as TYPE
|
||||
from .. import glob
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def handle(client: "Client", data: bytes) -> bytes:
|
||||
|
||||
return b""
|
||||
120
sampy/handlers/serverQueryHandler.py
Normal file
120
sampy/handlers/serverQueryHandler.py
Normal file
@@ -0,0 +1,120 @@
|
||||
import struct
|
||||
import logging
|
||||
|
||||
from .. import glob
|
||||
from ..helpers import dataHelper
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.propagate = False # Disable console logging
|
||||
|
||||
def handle(client, data):
|
||||
ping_ip = ".".join((str(x) for x in struct.unpack(b"<4B", data[4:8])))
|
||||
ping_port = struct.unpack(b"<H", data[9:11])[0]
|
||||
|
||||
logger.debug("[%s] -> Pinging to %s:%d" % (client.addr, ping_ip, ping_port))
|
||||
|
||||
if len(data) == 11: # We should add our data ontop
|
||||
if data[-1:] in RESPONSE:
|
||||
data += RESPONSE[data[-1:]]()
|
||||
|
||||
logger.debug("[%s] <- %s" % (client.addr, data))
|
||||
|
||||
return data
|
||||
|
||||
def query_i():
|
||||
len_hostname = len(glob.config["server"]["hostname"])
|
||||
len_mode = len(glob.config["server"]["mode"])
|
||||
len_language = len(glob.config["server"]["language"])
|
||||
|
||||
packet = struct.pack(b"<?HHI%dsI%dsI%ds" % (len_hostname, len_mode, len_language),
|
||||
False,
|
||||
len(get_online_players()),
|
||||
glob.config["server"]["max_players"],
|
||||
len_hostname,
|
||||
glob.config["server"]["hostname"].encode(),
|
||||
len_mode,
|
||||
glob.config["server"]["mode"].encode(),
|
||||
len_language,
|
||||
glob.config["server"]["language"].encode())
|
||||
|
||||
return packet
|
||||
|
||||
def query_r():
|
||||
packet_data = []
|
||||
|
||||
rules = get_rules()
|
||||
packet_data.append(len(rules)) # len_rules
|
||||
|
||||
for name, value in rules.items():
|
||||
packet_data.append([
|
||||
len(name), name,
|
||||
len(value), value
|
||||
])
|
||||
|
||||
flat_packet_data = dataHelper.flatten(packet_data)
|
||||
|
||||
packet = struct.pack(b"<H" + b"B%dsB%ds" * flat_packet_data[0] # using len_rules
|
||||
% tuple(len(y) for x in rules.items() for y in x), # tuple of only rules entries
|
||||
*flat_packet_data)
|
||||
|
||||
return packet
|
||||
|
||||
def query_c():
|
||||
packet_data = []
|
||||
|
||||
players_scores = get_players_scores()
|
||||
packet_data.append(len(players_scores))
|
||||
|
||||
for name, value in players_scores.items():
|
||||
packet_data.append([
|
||||
len(name), name,
|
||||
value
|
||||
])
|
||||
|
||||
flat_packet_data = dataHelper.flatten(packet_data)
|
||||
|
||||
packet = struct.pack(b"<H" + b"B%dsI" * flat_packet_data[0]
|
||||
% tuple(len(x) for x in players_scores.keys()),
|
||||
*flat_packet_data)
|
||||
|
||||
return packet
|
||||
|
||||
def query_d():
|
||||
packet_data = []
|
||||
|
||||
players = get_online_players()
|
||||
packet_data.append(len(players))
|
||||
|
||||
for player in players:
|
||||
packet_data.append([
|
||||
player["id"],
|
||||
len(player["nick"]), player["nick"],
|
||||
player["score"],
|
||||
player["ping"]
|
||||
])
|
||||
|
||||
flat_packet_data = dataHelper.flatten(packet_data)
|
||||
|
||||
packet = struct.pack(b"<H" + b"cc%dsII" * flat_packet_data[0]
|
||||
% [len(player["nick"]) for player in players],
|
||||
*flat_packet_data)
|
||||
|
||||
return packet
|
||||
|
||||
def get_online_players(): #TODO: Get data from server's client objects
|
||||
return [
|
||||
{"nick": b"Sunpy", "score": 64, "ping": 8, "id": 1} # replace id with function to get player's id
|
||||
]
|
||||
|
||||
def get_rules(): #TODO
|
||||
return {b"Rule name sample": b"Rule value", b"weburl": b"https://git.osufx.com/Sunpy/sampy"}
|
||||
|
||||
def get_players_scores(): #TODO
|
||||
return {b"Sunpy": 64, b"username": 123}
|
||||
|
||||
RESPONSE = { #TODO?: p (https://wiki.sa-mp.com/wiki/Query_Mechanism) (We dont really need to do the last handler as it happens somewhat automatically)
|
||||
b"i": query_i,
|
||||
b"r": query_r,
|
||||
b"c": query_c,
|
||||
b"d": query_d
|
||||
}
|
||||
16
sampy/handlers/unknownHandler.py
Normal file
16
sampy/handlers/unknownHandler.py
Normal file
@@ -0,0 +1,16 @@
|
||||
import struct
|
||||
|
||||
index = 0
|
||||
def handle(client: "Client", data: bytes) -> bytes:
|
||||
global index
|
||||
data = LOOKUP[index]
|
||||
|
||||
client.send_immediate(data[:3])
|
||||
|
||||
index = (index + 1) % 2
|
||||
return data[3:]
|
||||
|
||||
LOOKUP = [
|
||||
bytes([int(x,16) for x in "e3 00 00 00 00 42 98 0c 11 33 30 45 39 33 39 33 33 36 39 42 35 36 38 43 32 00".split(" ")]),
|
||||
bytes([int(x,16) for x in "e3 01 00 00 80 42 68 22 c0 a8 02 85 dc f8 01 00 e0 57 00 00".split(" ")])
|
||||
]
|
||||
Reference in New Issue
Block a user