from threading import Timer from utils.logger import setup_logger from dpnet.CFrame import CFrame from dpnet.DFrame import DFrame import asyncio logger = setup_logger(__name__) class Session: def __init__(self, server, serversock): self.serversock = serversock self.server = server self.ip = "" self.port = 0 self.SessID = 0 self.next_expected_seq = 0 self.next_send = 0 self.Full = False self.LastMsgID = 0 self.connect_retry_timer_num = 0 self.connect_retry_timer = False self.lock = asyncio.Lock() def send(self, packet): rawpacket = packet.to_packet() rawbytes = rawpacket.getvalue() self.serversock.sendto(rawbytes, (self.ip, self.port)) if len(rawbytes) >= 4 and rawbytes[0] & DFrame.PACKET_COMMAND_DATA: self.next_send += 1 def setup_Connect_Retry_Timer(self): time = 0.2 * pow(2, self.connect_retry_timer_num) if time > 5: return False t = Timer(time, self._send_connected) t.start() return t def cancel_Connect_Retry_Timer(self): if self.connect_retry_timer: self.connect_retry_timer.cancel() self.connect_retry_timer_num = 0 def _send_connected(self): response = CFrame() response.ExtOpCode = CFrame.FRAME_EXOPCODE_CONNECTED response.RspId = self.LastMsgID response.SessID = self.SessID logger.debug("Timer sending CONNECTED") self.send(response) self.connect_retry_timer = self.setup_Connect_Retry_Timer() async def send_gamedata(self, bPayload, **kwargs): acknow = kwargs.get("acknow", False) dframe = DFrame() dframe.Command = DFrame.PACKET_COMMAND_DATA | DFrame.PACKET_COMMAND_RELIABLE | DFrame.PACKET_COMMAND_SEQUENTIAL | DFrame.PACKET_COMMAND_NEW_MSG | DFrame.PACKET_COMMAND_END_MSG if acknow: dframe.Command = dframe.Command | DFrame.PACKET_COMMAND_POLL dframe.Control = 0x00 dframe.Seq = self.next_send dframe.NRcv = self.next_expected_seq dframe.Payload = bPayload logger.debug(" %s:%s < %s (GAMEDATA)", self.ip, self.port, bPayload.hex()) self.send(dframe) if acknow: await self.lock.acquire() return dframe def send_cframe_connected(self, connect): response = CFrame() response.ExtOpCode = CFrame.FRAME_EXOPCODE_CONNECTED response.RspId = connect.MsgID response.SessID = connect.SessID logger.debug(" %s:%s < %s (CFRAME CONNECTED)", self.ip, self.port, response.to_packet().getvalue().hex()) self.send(response) def send_cframe_sack(self): r = CFrame() r.Command = CFrame.PACKET_COMMAND_FRAME r.ExtOpCode = CFrame.FRAME_EXOPCODE_SACK r.Flags = CFrame.SACK_FLAGS_RESPONSE r.NRecv = self.next_expected_seq r.NSeq = self.next_send logger.debug(" %s:%s < %s (CFRAME SACK)", self.ip, self.port, r.to_packet().getvalue().hex()) self.send(r) def send_dframe_keepalive(self): dframe = DFrame() dframe.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.Control = DFrame.PACKET_CONTROL_KEEPALIVE_OR_CORRELATE dframe.Seq = self.next_send dframe.NRcv = self.next_expected_seq dframe.SessID = self.SessID self.send(dframe)