giants-stupid-server/dpnet/netserver.py

91 lines
3.7 KiB
Python
Raw Permalink Normal View History

2019-01-22 01:30:42 +01:00
from .packet import Packet
from .EnumQuery import EnumQuery
from .EnumResponse import EnumResponse
from .CFrame import CFrame
from .DFrame import DFrame
import traceback
import uuid
from utils.logger import setup_logger
2020-05-27 14:09:44 +02:00
from giants import GameTypes, Teams
import asyncio
2019-01-22 01:30:42 +01:00
logger = setup_logger(__name__)
class Netserver(asyncio.DatagramProtocol):
2019-01-22 01:30:42 +01:00
def __init__(self, server):
self.remotesocket = None
2019-01-22 01:30:42 +01:00
self.statssocket = None
self.server = server
self.addrs = []
self.guid = uuid.uuid4().bytes
2019-02-05 01:35:22 +01:00
self.incoming_packets = []
super().__init__()
def connection_made(self, transport):
logger.debug("Connection made")
self.remotesocket = transport
2019-01-22 01:30:42 +01:00
def datagram_received(self, data, addr):
loop = asyncio.get_event_loop()
loop.create_task(self.handle_new_packet(addr, data))
2019-01-22 01:30:42 +01:00
async def handle_new_packet(self, addr, bData):
2019-01-22 01:30:42 +01:00
pPacket = Packet(bData)
first = pPacket.getByte()
if len(bData) >= 4 and first & DFrame.PACKET_COMMAND_DATA:
2020-05-27 14:09:44 +02:00
return
2019-01-22 01:30:42 +01:00
elif len(bData) >= 12 and first & CFrame.PACKET_COMMAND_FRAME:
2020-05-27 14:09:44 +02:00
return
2019-01-22 01:30:42 +01:00
elif first == EnumQuery.LEAD or first == EnumResponse.LEAD:
2019-02-15 01:49:34 +01:00
logger.debug("%s:%s > %s (ENUM)", addr[0], addr[1], bData.hex())
await self.handle_new_enum(addr, pPacket)
2019-01-22 01:30:42 +01:00
else:
logger.error("Unknown frame received")
return
async def handle_new_enum(self, addr, data):
2019-01-22 01:30:42 +01:00
# EnumQuery or EnumResponse
second = data.getByte()
if second == EnumQuery.COMMAND:
# EnumQuery
try:
eq = EnumQuery(data)
2020-05-27 14:09:44 +02:00
version, server_name, player_count, max_player_count, map_name = await self.server.on_connection_received(addr[0], addr[1])
2019-01-22 01:30:42 +01:00
er = EnumResponse()
er.Payload = eq.Payload
er.ApplicationDescSize = 0x50
er.ApplicationDescFlags = 0x41
2020-05-27 14:09:44 +02:00
er.MaxPlayers = max_player_count
er.CurrentPlayers = player_count
er.SessionName = server_name
2019-01-22 01:30:42 +01:00
er.ApplicationInstanceGUID = self.guid
er.ApplicationGUID = eq.ApplicationGUID
2019-02-05 22:33:25 +01:00
appdata = Packet()
appdata.putByte(0xff) # map ID
2020-05-27 14:09:44 +02:00
appdata.putByte(GameTypes.GTypeNull) # game type
appdata.putByte(Teams.MvRvK) # teams
2019-02-05 22:33:25 +01:00
appdata.write(b'\x00') # original: 0x00 - does not seem to affect client
2020-05-27 14:09:44 +02:00
appdata.putShort(int(version * 1000))
2019-02-05 22:33:25 +01:00
appdata.write(b'\x02\x92') # original: 0292 - does not seem to affect client
2020-05-27 14:09:44 +02:00
appdata.putShort(0) # points per capture
appdata.putShort(0) # points per kill
2019-02-05 22:33:25 +01:00
appdata.write(b'\x00\x00') # original: 0000 - does not seem to affect client
2020-05-27 14:09:44 +02:00
appdata.putShort(0) # detente time
2020-05-27 15:45:58 +02:00
appdata.write(b"\xff\xff\xff\xff") # Seems to be a checksum of current map OR linked to the number of chars in the map name
2020-05-27 14:09:44 +02:00
appdata.write(map_name.encode("ascii"))
appdata.write(b'\x00' * (32 - len(map_name)))
2019-02-05 22:33:25 +01:00
er.ApplicationReservedData = appdata.getvalue()
2020-05-27 15:45:58 +02:00
er.ApplicationReservedData += b'\x00' * (32 - len(map_name))
2019-01-22 01:30:42 +01:00
self.send_packet(addr, er.to_packet())
except Exception:
logger.error("Could not parse EnumQuery or forge EnumResponse: ")
traceback.print_exc()
return
else:
logger.error("Unknown DPLHP command: %s", second)
def send_packet(self, addr, packet):
2020-05-27 14:09:44 +02:00
self.remotesocket.sendto(packet.getvalue(), addr)