From 024712cc8d266ddaea9c0dd8f1d5e581b0112d46 Mon Sep 17 00:00:00 2001 From: HipsterCat Date: Tue, 5 Feb 2019 01:35:22 +0100 Subject: [PATCH] Moar things --- dpnet/DN_MSG_INTERNAL_SEND_CONNECT_INFO.py | 177 ++++++++++++++++ dpnet/netserver.py | 228 ++++++++++++--------- dpnet/session.py | 5 +- giants/__init__.py | 2 + giants/player.py | 14 +- server.py | 46 +++-- 6 files changed, 360 insertions(+), 112 deletions(-) create mode 100644 dpnet/DN_MSG_INTERNAL_SEND_CONNECT_INFO.py diff --git a/dpnet/DN_MSG_INTERNAL_SEND_CONNECT_INFO.py b/dpnet/DN_MSG_INTERNAL_SEND_CONNECT_INFO.py new file mode 100644 index 0000000..5713f0b --- /dev/null +++ b/dpnet/DN_MSG_INTERNAL_SEND_CONNECT_INFO.py @@ -0,0 +1,177 @@ +from .packet import Packet +from .DFrame import DFrame +from giants import APPLICATION_GUID + + +class DN_NAMETABLE_ENTRY_INFO: + def __init__(self): + self.dpnid = 0 + self.dpnidOwner = 0 + self.dwFlags = 0 + self.dwVersion = 0 + self.dwVersionNotUsed = 0 + self.dwDNETVersion = 7 + self.dwNameOffset = 0 + self.dwNameSize = 0 + self.dwDataOffset = 0 + self.dwDataSize = 0 + self.dwURLOffset = 0 + self.dwURLSize = 0 + self.URL = b'' + self.Data = b'' + self.Name = b'' + + def to_packet(self): + p = Packet() + p.putULong(self.dpnid) + p.putULong(self.dpnidOwner) + p.putULong(self.dwFlags) + p.putULong(self.dwVersion) + p.putULong(self.dwVersionNotUsed) + p.putULong(self.dwDNETVersion) + p.putULong(self.dwNameOffset) + p.putULong(self.dwNameSize) + p.putULong(self.dwDataOffset) + p.putULong(self.dwDataSize) + p.putULong(self.dwURLOffset) + p.putULong(self.dwURLSize) + return p + +class DN_MSG_INTERNAl_SEND_CONNECT_INFO(DFrame): + dwPacketType = 0xc2 + + def __init__(self, netserver, newplayer, packet=None): + super().__init__(packet) + self.Command = DFrame.PACKET_COMMAND_DATA | DFrame.PACKET_COMMAND_RELIABLE | DFrame.PACKET_COMMAND_SEQUENTIAL | DFrame.PACKET_COMMAND_POLL | DFrame.PACKET_COMMAND_NEW_MSG | DFrame.PACKET_COMMAND_END_MSG | DFrame.PACKET_COMMAND_USER_1 + self.Control = 0x00 + self.netserver = netserver + self.newplayer = newplayer + self.dwPacketType = DN_MSG_INTERNAl_SEND_CONNECT_INFO.dwPacketType + self.dwReplyOffset = 0 + self.dwReplySize = 0 + self.dwSize = 0x50 + self.dwFlags = 0x41 + self.dwMaxPlayers = netserver.server.maxplayers + self.dwCurrentPlayers = len(netserver.server.players) + len(netserver.server.tempplayers) + self.dwSessionNameOffset = 0 + self.dwSessionNameSize = len((netserver.server.name+"\x00").encode("utf-16-le")) + self.dwPasswordOffset = 0 + self.dwPasswordSize = 0 + self.dwReservedDataOffset = 0 + self.dwReservedDataSize = 0 + self.dwApplicationReservedDataOffset = 0 + self.dwApplicationReservedDataSize = 0 + self.guidInstance = netserver.guid + self.guidApplication = APPLICATION_GUID + self.dpnid = newplayer.id + self.dwVersion = 0x21 + self.dwVersionNotUsed = 0 + self.dwEntryCount = 0 + self.dwMembershipCount = 0 + self.DN_NameTable_Entry_Info = [] + self.DN_NameTable_Membership_Info = [] + self.ApplicationReservedData = b'' + self.ReservedData = b'' + self.Password = b'' + self.SessionName = (netserver.server.name+"\x00").encode("utf-16-le") + self.Reply = b'' + + if packet: + self.parse(packet) + + def parse(self, packet): + pass + + def to_packet(self): + var = 108 + + s = self.netserver.server.players[0] + entry_server = DN_NAMETABLE_ENTRY_INFO() + self.DN_NameTable_Entry_Info.append(entry_server) + + p = self.newplayer + entry_player = DN_NAMETABLE_ENTRY_INFO() + self.DN_NameTable_Entry_Info.append(entry_player) + + self.dwEntryCount = len(self.DN_NameTable_Entry_Info) + self.dwMembershipCount = len(self.DN_NameTable_Membership_Info) + + entry_server.dpnid = s.id + entry_server.dwFlags = 0x0402 + + entry_player.dpnid = p.id + entry_player.dwFlags = 0x0200 + entry_player.Name = (p.name+"\x00").encode("utf-16-le") + + var = var + self.dwEntryCount * 48 # 48=size of DN_NAMETABLE_ENTRY_INFO + entry_player.dwNameOffset = var + entry_player.dwNameSize = len(entry_player.Name) + + var += entry_player.dwNameSize + + if self.ApplicationReservedData: + self.dwApplicationReservedDataSize = len(self.ApplicationReservedData) + self.dwApplicationReservedDataOffset = var + var += self.dwApplicationReservedDataSize + if self.ReservedData: + self.dwReservedDataSize = len(self.ReservedData) + self.dwReservedDataOffset = var + var += self.dwReservedDataSize + if self.Password: + self.dwPasswordSize = len(self.Password) + self.dwPasswordOffset = var + var += self.dwPasswordSize + if self.SessionName: + self.dwSessionNameSize = len(self.SessionName) + self.dwSessionNameOffset = var + var += self.dwSessionNameSize + if self.Reply: + self.dwReplySize = len(self.Reply) + self.dwReplyOffset = var + var += self.dwReplySize + + packet = Packet() + packet.putULong(self.dwPacketType) + packet.putULong(self.dwReplyOffset) + packet.putULong(self.dwReplySize) + packet.putULong(self.dwSize) + packet.putULong(self.dwFlags) + packet.putULong(self.dwMaxPlayers) + packet.putULong(self.dwCurrentPlayers) + packet.putULong(self.dwSessionNameOffset) + packet.putULong(self.dwSessionNameSize) + packet.putULong(self.dwPasswordOffset) + packet.putULong(self.dwPasswordSize) + packet.putULong(self.dwReservedDataOffset) + packet.putULong(self.dwReservedDataSize) + packet.putULong(self.dwApplicationReservedDataOffset) + packet.putULong(self.dwApplicationReservedDataSize) + packet.putBytes(self.guidInstance) + packet.putBytes(self.guidApplication) + packet.putULong(self.dpnid) + packet.putULong(self.dwVersion) + packet.putULong(self.dwVersionNotUsed) + packet.putULong(self.dwEntryCount) + packet.putULong(self.dwMembershipCount) + + for entry in self.DN_NameTable_Entry_Info: + packet.putBytes(entry.to_packet().getvalue()) + for entry in self.DN_NameTable_Membership_Info: + packet.putBytes(entry.to_packet().getvalue()) + + if entry_player.URL: + packet.putBytes(entry_player.URL) + if entry_player.Data: + packet.putBytes(entry_player.Data) + if entry_player.Name: + packet.putBytes(entry_player.Name) + + packet.putBytes(self.ApplicationReservedData) + packet.putBytes(self.ReservedData) + packet.putBytes(self.Password) + packet.putBytes(self.SessionName) + packet.putBytes(self.Reply) + + self.Payload = packet.getvalue() + + return super().to_packet() diff --git a/dpnet/netserver.py b/dpnet/netserver.py index f9565c3..2e16e27 100644 --- a/dpnet/netserver.py +++ b/dpnet/netserver.py @@ -10,8 +10,12 @@ import threading import traceback import uuid import struct +from _datetime import datetime from utils.logger import setup_logger -from giants.player import Player +from giants.player import Player, PlayerPhases +import time +from giants import APPLICATION_GUID +from .DN_MSG_INTERNAL_SEND_CONNECT_INFO import DN_MSG_INTERNAl_SEND_CONNECT_INFO logger = setup_logger(__name__) @@ -23,21 +27,35 @@ class Netserver: self.server = server self.addrs = [] self.guid = uuid.uuid4().bytes + self.incoming_packets = [] def run(self): self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) self.socket.bind((self.server.listen_ip, self.server.listen_port)) logger.debug("Listening to %s:%s", self.server.listen_ip, self.server.listen_port) - gameserverthread = threading.Thread(target=self.handle_packets) - gameserverthread.start() + networkthread = threading.Thread(target=self.handle_packets) + networkthread.start() if self.server.register_with_ms: ms = MasterServer(self.server) ms.register() + while self.server.running: + start = datetime.now() + self.read_packets() + self.server.update() + self.send_packets() + sleep_ms = (start-datetime.now()).total_seconds()+1/self.server.ticks + if sleep_ms > 0: + time.sleep(sleep_ms) - gameserverthread.join() - #statsserverthread.join() + networkthread.join() + + def read_packets(self): + pass + + def send_packets(self): + pass def handle_packets(self): while True: @@ -79,7 +97,7 @@ class Netserver: er.ApplicationReservedData += b'\x00\x04\x00' # game type and teams er.ApplicationReservedData += struct.pack(" # \x9c\x53\xf4\xdd: Three Way Island - Canyons @@ -101,6 +119,7 @@ class Netserver: try: cframe = CFrame(data) session = self.get_session(addr) + player = self.get_player(session) if session else None if cframe.ExtOpCode == CFrame.FRAME_EXOPCODE_CONNECT: # CONNECT CFRAME if session and session.Full: @@ -123,6 +142,17 @@ class Netserver: session.port = addr[1] self.addrs.append(session) session.send_cframe_connected(cframe) + player = Player("Unknown", session) + + def bxor(b1, b2): # use xor for bytes + result = bytearray() + for b1, b2 in zip(b1, b2): + result.append(b1 ^ b2) + return result + player.id = struct.unpack(">L", bxor(struct.pack("