Add TODOs to code.

This commit is contained in:
Maxim Khomutov 2023-07-14 22:27:23 +03:00
parent 4f688d7c02
commit 5a40ab8b05
4 changed files with 42 additions and 68 deletions

View File

@ -32,11 +32,11 @@ class Client:
return True return True
res = self.writer.is_closing() res = self.writer.is_closing()
if res: if res:
self.log.debug(f"Client Disconnected") self.log.debug(f"Disconnected.")
self.alive = False self.alive = False
return True return True
else: else:
self.log.debug(f"Client Alive") self.log.debug(f"Alive.")
self.alive = True self.alive = True
return False return False
@ -44,10 +44,10 @@ class Client:
if not self.alive: if not self.alive:
self.log.debug(f"Kick({reason}) skipped;") self.log.debug(f"Kick({reason}) skipped;")
return return
# TODO: i18n
self.log.info(f"Kicked with reason: \"{reason}\"") self.log.info(f"Kicked with reason: \"{reason}\"")
await self.tcp_send(b"K" + bytes(reason, "utf-8")) await self.tcp_send(b"K" + bytes(reason, "utf-8"))
self.alive = False self.alive = False
# await self.remove_me()
async def tcp_send(self, data, to_all=False, writer=None): async def tcp_send(self, data, to_all=False, writer=None):
@ -67,7 +67,6 @@ class Client:
await client.tcp_send(data) await client.tcp_send(data)
return return
# self.log.debug(f"tcp_send({data})")
if len(data) == 10: if len(data) == 10:
data += b"." data += b"."
header = len(data).to_bytes(4, "little", signed=True) header = len(data).to_bytes(4, "little", signed=True)
@ -81,7 +80,7 @@ class Client:
async def recv(self): async def recv(self):
try: try:
header = await self.reader.read(4) # header: 4 bytes header = await self.reader.read(4)
int_header = 0 int_header = 0
for i in range(len(header)): for i in range(len(header)):
@ -121,6 +120,7 @@ class Client:
real_size = end - start real_size = end - start
writer = self.down_rw[1] if d_sock else self.writer writer = self.down_rw[1] if d_sock else self.writer
who = 'dwn' if d_sock else 'srv' who = 'dwn' if d_sock else 'srv'
if config.Server["debug"]:
self.log.debug(f"[{who}] Real size: {real_size / MB}mb; {real_size == end}, {real_size * 2 == end}") self.log.debug(f"[{who}] Real size: {real_size / MB}mb; {real_size == end}, {real_size * 2 == end}")
with open(filename, 'rb') as f: with open(filename, 'rb') as f:
@ -133,46 +133,16 @@ class Client:
except ConnectionError: except ConnectionError:
self.alive = False self.alive = False
self.log.debug(f"[{who}] Disconnected.") self.log.debug(f"[{who}] Disconnected.")
# break
return real_size return real_size
# chunk_size = 125 * MB
# if chunk_size > real_size:
# chunk_size = real_size
# chunks = math.floor(real_size / chunk_size)
# self.log.debug(f"[{who}] s:{start}, e:{end}, c:{chunks}, cz:{chunk_size/MB}mb, rs:{real_size/MB}mb")
# dw = 0
# for chunk in range(1, chunks + 1):
# chunk_end = start + (chunk_size * chunk)
# chunk_start = chunk_end - chunk_size
# # if chunk_start != 0:
# # chunk_start -= 1
# real_size -= chunk_size
# if chunk_size > real_size:
# chunk_end = real_size
# self.log.debug(f"[{who}] Chunk: {chunk}; Start: {chunk_start}; End: {chunk_end/MB};")
# with open(filename, 'rb') as f:
# f.seek(chunk_start)
# data = f.read(chunk_end)
# try:
# writer.write(data)
# await writer.drain()
# except ConnectionError:
# self.alive = False
# self.log.debug(f"[{who}] Disconnected")
# break
# dw += len(data)
# del data
# self.log.debug(f"[{who}] File sent.")
# return dw
async def sync_resources(self): async def sync_resources(self):
while self.alive: while self.alive:
data = await self.recv() data = await self.recv()
self.log.debug(f"data: {data!r}") self.log.debug(f"data: {data!r}")
if data.startswith(b"f"): if data.startswith(b"f"):
file = data[1:].decode("utf-8") file = data[1:].decode("utf-8")
self.log.debug(f"Sending File: {file}") # TODO: i18n
self.log.info(f"Requested mode: {file!r}")
size = -1 size = -1
for mod in self.Core.mods_list: for mod in self.Core.mods_list:
if type(mod) == int: if type(mod) == int:
@ -181,6 +151,7 @@ class Client:
size = mod['size'] size = mod['size']
self.log.debug("File is accept.") self.log.debug("File is accept.")
break break
self.log.debug(f"Mode size: {size}")
if size == -1: if size == -1:
await self.tcp_send(b"CO") await self.tcp_send(b"CO")
await self.kick(f"Not allowed mod: " + file) await self.kick(f"Not allowed mod: " + file)
@ -193,28 +164,20 @@ class Client:
if t > 50: if t > 50:
await self.kick("Missing download socket") await self.kick("Missing download socket")
return return
self.log.info(f"Requested mode: {file!r}")
self.log.debug(f"Mode size: {size / MB}")
msize = math.floor(size / 2) half_size = math.floor(size / 2)
# uploads = [
# asyncio.create_task(self._split_load(0, msize, False, file)), # SplitLoad_0
# asyncio.create_task(self._split_load(msize, size, True, file)) # SplitLoad_1
# ]
# await asyncio.wait(uploads)
uploads = [ uploads = [
self._split_load(0, msize, False, file), self._split_load(0, half_size, False, file),
self._split_load(msize, size, True, file) self._split_load(half_size, size, True, file)
] ]
sl0, sl1 = await asyncio.gather(*uploads) sl0, sl1 = await asyncio.gather(*uploads)
sent = sl0 + sl1 sent = sl0 + sl1
ok = sent == size ok = sent == size
lost = size - sent lost = size - sent
self.log.debug(f"SplitLoad_0: {sl0}; SplitLoad_1: {sl1}; At all ({ok}): Sent: {sent}; Lost: {lost}") self.log.debug(f"SplitLoad_0: {sl0}; SplitLoad_1: {sl1}; At all ({ok}): Sent: {sent}; Lost: {lost}")
self.log.debug(f"SplitLoad_0: {sl0 / MB}mb; "
f"SplitLoad_1: {sl1 / MB}MB; At all ({ok}): Sent: {sent / MB}mb; Lost: {lost / MB}mb")
if not ok: if not ok:
self.alive = False self.alive = False
# TODO: i18n
self.log.error(f"Error while sending.") self.log.error(f"Error while sending.")
return return
elif data.startswith(b"SR"): elif data.startswith(b"SR"):
@ -245,7 +208,7 @@ class Client:
if not self.alive: if not self.alive:
break break
else: else:
await asyncio.sleep(.2) await asyncio.sleep(.1)
self.is_disconnected() self.is_disconnected()
continue continue
code = data.decode()[0] code = data.decode()[0]
@ -257,6 +220,7 @@ class Client:
await self.tcp_send(b"Sn" + bytes(self.nick, "utf-8"), to_all=True) await self.tcp_send(b"Sn" + bytes(self.nick, "utf-8"), to_all=True)
case "C": case "C":
# Chat # Chat
ev.call_event("chat_receive", f"{data}")
await self.tcp_send(data, to_all=True) await self.tcp_send(data, to_all=True)
async def remove_me(self): async def remove_me(self):
@ -267,6 +231,7 @@ class Client:
# if self.ready: # if self.ready:
# await self.tcp_send(b"", to_all=True) # I'm disconnected. # await self.tcp_send(b"", to_all=True) # I'm disconnected.
self.log.debug(f"Removing client {self.nick}:{self.cid}") self.log.debug(f"Removing client {self.nick}:{self.cid}")
# TODO: i18n
self.log.info("Disconnected") self.log.info("Disconnected")
self.Core.clients[self.cid] = None self.Core.clients[self.cid] = None
self.Core.clients_by_id.pop(self.cid) self.Core.clients_by_id.pop(self.cid)

View File

@ -121,6 +121,7 @@ class Core:
async def heartbeat(self, test=False): async def heartbeat(self, test=False):
if config.Auth["private"] or self.direct: if config.Auth["private"] or self.direct:
if test: if test:
# TODO: i18n
self.log.info(f"Server runnig in Direct connect mode.") self.log.info(f"Server runnig in Direct connect mode.")
self.direct = True self.direct = True
return return
@ -171,6 +172,7 @@ class Core:
status = body.get("status") status = body.get("status")
msg = body.get("msg") msg = body.get("msg")
if status == "2000": if status == "2000":
# TODO: i18n
self.log.info(f"Authenticated! {msg}") self.log.info(f"Authenticated! {msg}")
elif status == "200": elif status == "200":
self.log.info(f"Resumed authenticated session. {msg}") self.log.info(f"Resumed authenticated session. {msg}")
@ -186,6 +188,7 @@ class Core:
if not config.Auth['private']: if not config.Auth['private']:
raise KeyboardInterrupt raise KeyboardInterrupt
if test: if test:
# TODO: i18n
self.log.info(f"Server still runnig, but only in Direct connect mode.") self.log.info(f"Server still runnig, but only in Direct connect mode.")
if test: if test:
@ -226,24 +229,24 @@ class Core:
self.mods_list.append({"path": path, "size": size}) self.mods_list.append({"path": path, "size": size})
self.mods_list[0] += size self.mods_list[0] += size
self.log.debug(f"mods_list: {self.mods_list}") self.log.debug(f"mods_list: {self.mods_list}")
lmods = len(self.mods_list) - 1 len_mods = len(self.mods_list) - 1
if lmods > 0: if len_mods > 0:
self.log.info(f"Loaded {lmods} mods: {round(self.mods_list[0] / MB, 2)}mb") # TODO: i18n
self.log.info(f"Loaded {len_mods} mods: {round(self.mods_list[0] / MB, 2)}mb")
await self.heartbeat(True) await self.heartbeat(True)
for i in range(int(config.Game["players"] * 1.3)): for i in range(int(config.Game["players"] * 2.3)): # * 2.3 For down sock and buffer.
self.clients.append(None) self.clients.append(None)
tasks = [] tasks = []
# self.udp.start, # self.udp.start,
nrtasks = [self.tcp.start, console.start, self.stop_me, self.heartbeat, self.check_alive] f_tasks = [self.tcp.start, console.start, self.stop_me, self.heartbeat, self.check_alive]
for task in nrtasks: for task in f_tasks:
tasks.append(asyncio.create_task(task())) tasks.append(asyncio.create_task(task()))
t = asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION) t = asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
self.log.info(i18n.start) self.log.info(i18n.start)
ev.call_event("on_started") ev.call_event("on_started")
await t await t # Wait end.
# Wait the end.
except Exception as e: except Exception as e:
self.log.error(f"Exception: {e}") self.log.error(f"Exception: {e}")
self.log.exception(e) self.log.exception(e)

View File

@ -23,10 +23,12 @@ class TCPServer:
async def auth_client(self, reader, writer): async def auth_client(self, reader, writer):
client = self.Core.create_client(reader, writer) client = self.Core.create_client(reader, writer)
# TODO: i18n
self.log.info(f"Identifying new ClientConnection...") self.log.info(f"Identifying new ClientConnection...")
data = await client.recv() data = await client.recv()
self.log.debug(f"Version: {data}") self.log.debug(f"Version: {data}")
if data.decode("utf-8") != f"VC{self.Core.client_major_version}": if data.decode("utf-8") != f"VC{self.Core.client_major_version}":
# TODO: i18n
await client.kick("Outdated Version.") await client.kick("Outdated Version.")
return False, client return False, client
else: else:
@ -35,6 +37,7 @@ class TCPServer:
data = await client.recv() data = await client.recv()
self.log.debug(f"Key: {data}") self.log.debug(f"Key: {data}")
if len(data) > 50: if len(data) > 50:
# TODO: i18n
await client.kick("Invalid Key (too long)!") await client.kick("Invalid Key (too long)!")
return False, client return False, client
client.key = data.decode("utf-8") client.key = data.decode("utf-8")
@ -46,6 +49,7 @@ class TCPServer:
res = await response.json() res = await response.json()
self.log.debug(f"res: {res}") self.log.debug(f"res: {res}")
if res.get("error"): if res.get("error"):
# TODO: i18n
await client.kick('Invalid key! Please restart your game.') await client.kick('Invalid key! Please restart your game.')
return False, client return False, client
client.nick = res["username"] client.nick = res["username"]
@ -54,6 +58,7 @@ class TCPServer:
# noinspection PyProtectedMember # noinspection PyProtectedMember
client._update_logger() client._update_logger()
except Exception as e: except Exception as e:
# TODO: i18n
self.log.error(f"Auth error: {e}") self.log.error(f"Auth error: {e}")
await client.kick('Invalid authentication data! Try to reconnect in 5 minutes.') await client.kick('Invalid authentication data! Try to reconnect in 5 minutes.')
return False, client return False, client
@ -62,15 +67,18 @@ class TCPServer:
if not _client: if not _client:
continue continue
if _client.nick == client.nick and _client.guest == client.guest: if _client.nick == client.nick and _client.guest == client.guest:
# TODO: i18n
await client.kick('Stale Client (replaced by new client)') await client.kick('Stale Client (replaced by new client)')
return False, client return False, client
ev.call_event("auth_ok", client) ev.call_event("auth_ok", client)
if len(self.Core.clients_by_id) > config.Game["players"]: if len(self.Core.clients_by_id) > config.Game["players"]:
# TODO: i18n
await client.kick("Server full!") await client.kick("Server full!")
return False, client return False, client
else: else:
# TODO: i18n
self.log.info("Identification success") self.log.info("Identification success")
await self.Core.insert_client(client) await self.Core.insert_client(client)
@ -103,6 +111,7 @@ class TCPServer:
await writer.drain() await writer.drain()
writer.close() writer.close()
case _: case _:
# TODO: i18n
self.log.error(f"Unknown code: {code}") self.log.error(f"Unknown code: {code}")
writer.close() writer.close()
return False, None return False, None
@ -123,6 +132,7 @@ class TCPServer:
del cl del cl
break break
except Exception as e: except Exception as e:
# TODO: i18n
self.log.error("Error while connecting..") self.log.error("Error while connecting..")
self.log.exception(e) self.log.exception(e)
traceback.print_exc() traceback.print_exc()
@ -139,6 +149,7 @@ class TCPServer:
async with server: async with server:
await server.serve_forever() await server.serve_forever()
except OSError as e: except OSError as e:
# TODO: i18n
self.log.error("Cannot bind port") self.log.error("Cannot bind port")
raise e raise e
except BaseException as e: except BaseException as e:

View File

@ -3,9 +3,11 @@ import builtins
from core import get_logger from core import get_logger
# noinspection PyShadowingBuiltins
class EventsSystem: class EventsSystem:
def __init__(self): def __init__(self):
# TODO: default events
self.__events = { self.__events = {
"on_started": [self.on_started], "on_started": [self.on_started],
"on_stop": [self.on_stop], "on_stop": [self.on_stop],
@ -20,6 +22,7 @@ class EventsSystem:
def register_event(self, event_name, event_func): def register_event(self, event_name, event_func):
self.log.debug(f"register_event({event_name}, {event_func}):") self.log.debug(f"register_event({event_name}, {event_func}):")
if not callable(event_func): if not callable(event_func):
# TODO: i18n
self.log.error(f"Cannot add event '{event_name}'. " self.log.error(f"Cannot add event '{event_name}'. "
f"Use `KuiToi.add_event({event_name}', function)` instead. Skipping it...") f"Use `KuiToi.add_event({event_name}', function)` instead. Skipping it...")
return return
@ -34,13 +37,5 @@ class EventsSystem:
for event in self.__events[event_name]: for event in self.__events[event_name]:
event(*data) event(*data)
else: else:
# TODO: i18n
self.log.warning(f"Event {event_name} does not exist. Just skipping it...") self.log.warning(f"Event {event_name} does not exist. Just skipping it...")
def on_started(self):
pass
def on_stop(self):
pass
def on_auth(self, client):
pass