giantsd/dpnet/session.py

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)