97 lines
3.5 KiB
Python
97 lines
3.5 KiB
Python
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)
|