Compare commits

...

4 Commits

Author SHA1 Message Date
a50decb470 Lua... 2023-07-24 01:30:11 +03:00
9079750576 __gracefully_kick 2023-07-24 00:03:04 +03:00
e440cdf022 Minor updates;
Memory fix.. :)
UDP Fix;
2023-07-24 00:02:23 +03:00
43fd56f327 Minor updates.. 2023-07-23 23:06:29 +03:00
6 changed files with 70 additions and 68 deletions

View File

@ -40,11 +40,6 @@ class Client:
self._connect_time = 0 self._connect_time = 0
self._last_position = {} self._last_position = {}
ev.register_event("onServerStopped", self.__gracefully_kick)
async def __gracefully_kick(self, _):
await self.kick("Server shutdown!")
@property @property
def _writer(self): def _writer(self):
return self.__writer return self.__writer
@ -112,7 +107,7 @@ class Client:
if not reason: if not reason:
reason = "Kicked!" reason = "Kicked!"
else: else:
reason = f"{reason!r}" reason = f"{reason}"
if not self.__alive: if not self.__alive:
self.log.debug(f"{self.nick}.kick('{reason}') skipped: Not alive;") self.log.debug(f"{self.nick}.kick('{reason}') skipped: Not alive;")
return return
@ -689,8 +684,8 @@ class Client:
# TODO: i18n # TODO: i18n
self.log.info(f"Disconnected, online time: {round((time.monotonic() - self._connect_time) / 60, 2)}min.") self.log.info(f"Disconnected, online time: {round((time.monotonic() - self._connect_time) / 60, 2)}min.")
self.__Core.clients[self.cid] = None self.__Core.clients[self.cid] = None
self.__Core.clients_by_id.pop(self.cid) del self.__Core.clients_by_id[self.cid]
self.__Core.clients_by_nick.pop(self.nick) del self.__Core.clients_by_nick[self.nick]
else: else:
self.log.debug(f"Removing client; Closing connection...") self.log.debug(f"Removing client; Closing connection...")
try: try:

View File

@ -116,6 +116,12 @@ class Core:
self.log.error("Error in check_alive.") self.log.error("Error in check_alive.")
self.log.exception(e) self.log.exception(e)
async def __gracefully_kick(self):
for client in self.clients:
if not client:
continue
await client.kick("Server shutdown!")
@staticmethod @staticmethod
def start_web(): def start_web():
uvconfig = uvicorn.Config("modules.WebAPISystem.app:web_app", uvconfig = uvicorn.Config("modules.WebAPISystem.app:web_app",
@ -157,7 +163,6 @@ class Core:
"version": self.BeamMP_version, "clientversion": self.client_major_version, "version": self.BeamMP_version, "clientversion": self.client_major_version,
"name": config.Server["name"], "modlist": modlist, "modstotalsize": modstotalsize, "name": config.Server["name"], "modlist": modlist, "modstotalsize": modstotalsize,
"modstotal": modstotal, "playerslist": "", "desc": config.Server['description'], "pass": False} "modstotal": modstotal, "playerslist": "", "desc": config.Server['description'], "pass": False}
self.log.debug(f"Auth: data {data}")
# Sentry? # Sentry?
ok = False ok = False
@ -169,7 +174,6 @@ class Core:
async with session.post(url, data=data, headers={"api-v": "2"}) as response: async with session.post(url, data=data, headers={"api-v": "2"}) as response:
code = response.status code = response.status
body = await response.json() body = await response.json()
self.log.debug(f"Auth: code {code}, body {body}")
ok = True ok = True
break break
except Exception as e: except Exception as e:
@ -183,19 +187,22 @@ class Core:
self.log.error("Missing/invalid json members in backend response") self.log.error("Missing/invalid json members in backend response")
raise KeyboardInterrupt raise KeyboardInterrupt
if test: status = body.get("status")
status = body.get("status") msg = body.get("msg")
msg = body.get("msg") if status == "2000":
if status == "2000": if test:
# TODO: i18n # TODO: i18n
self.log.info(f"Authenticated! {msg}") self.log.info(f"Authenticated! {msg}")
elif status == "200": elif status == "200":
if test:
self.log.info(f"Resumed authenticated session. {msg}") self.log.info(f"Resumed authenticated session. {msg}")
else: else:
self.log.error(f"Backend REFUSED the auth key. Reason: " self.log.debug(f"Auth: data {data}")
f"{msg or 'Backend did not provide a reason'}") self.log.debug(f"Auth: code {code}, body {body}")
self.log.info(f"Server still runnig, but only in Direct connect mode.") self.log.error(f"Backend REFUSED the auth key. Reason: "
self.direct = True f"{msg or 'Backend did not provide a reason'}")
self.log.info(f"Server still runnig, but only in Direct connect mode.")
self.direct = True
else: else:
self.direct = True self.direct = True
if test: if test:
@ -296,6 +303,7 @@ class Core:
ev.call_lua_event("onShutdown") ev.call_lua_event("onShutdown")
ev.call_event("onServerStopped") ev.call_event("onServerStopped")
await ev.call_async_event("onServerStopped") await ev.call_async_event("onServerStopped")
await self.__gracefully_kick()
await ev.call_async_event("_plugins_unload") await ev.call_async_event("_plugins_unload")
ev.call_event("_lua_plugins_unload") ev.call_event("_lua_plugins_unload")
self.run = False self.run = False

View File

@ -40,6 +40,7 @@ class Core:
def create_client(self, *args, **kwargs) -> Client: ... def create_client(self, *args, **kwargs) -> Client: ...
def get_clients_list(self, need_cid=False) -> str: ... def get_clients_list(self, need_cid=False) -> str: ...
async def check_alive(self) -> None: ... async def check_alive(self) -> None: ...
async def __gracefully_kick(self): ...
@staticmethod @staticmethod
def start_web() -> None: ... def start_web() -> None: ...
def stop_me(self) -> None: ... def stop_me(self) -> None: ...

View File

@ -23,8 +23,9 @@ class UDPServer(asyncio.DatagramTransport):
self.port = port self.port = port
self.run = False self.run = False
def connection_made(self, transport): def connection_made(self, *args, **kwargs): ...
... def pause_writing(self, *args, **kwargs): ...
def resume_writing(self, *args, **kwargs): ...
async def handle_datagram(self, data, addr): async def handle_datagram(self, data, addr):
try: try:
@ -58,9 +59,10 @@ class UDPServer(asyncio.DatagramTransport):
case _: case _:
self.log.debug(f"[{cid}] Unknown code: {code}") self.log.debug(f"[{cid}] Unknown code: {code}")
else: else:
self.log.debug(f"Client not found.") self.log.debug(f"[{cid}] Client not found.")
except Exception as e: except Exception as e:
self.log.error(f"Error handle_datagram: {e}") self.log.error(f"Error handle_datagram: {e}")
def datagram_received(self, *args, **kwargs): def datagram_received(self, *args, **kwargs):
@ -79,8 +81,9 @@ class UDPServer(asyncio.DatagramTransport):
async def _start(self): async def _start(self):
self.log.debug("Starting UDP server.") self.log.debug("Starting UDP server.")
try: while self.Core.run:
while self.Core.run: try:
await asyncio.sleep(0.2) await asyncio.sleep(0.2)
d = UDPServer d = UDPServer
@ -90,21 +93,19 @@ class UDPServer(asyncio.DatagramTransport):
) )
d.transport = self.transport d.transport = self.transport
if not self.run: self.log.debug(f"UDP server started on {self.transport.get_extra_info('sockname')}")
self.log.debug(f"UDP server started on {self.transport.get_extra_info('sockname')}")
self.run = True self.run = True
while not self.transport.is_closing(): while not self.transport.is_closing():
await asyncio.sleep(0.2) await asyncio.sleep(0.2)
except OSError as e:
self.log.error("Cannot bind port or other error") except OSError as e:
self.log.exception(e) self.run = False
except Exception as e: self.Core.run = False
self.log.error(f"Error: {e}") self.log.error(f"Cannot bind port or other error: {e}")
self.log.exception(e) except Exception as e:
finally: self.log.error(f"Error: {e}")
self.run = False self.log.exception(e)
self.Core.run = False
def _stop(self): def _stop(self):
self.log.debug("Stopping UDP server") self.log.debug("Stopping UDP server")

View File

@ -73,9 +73,9 @@ class EventsSystem:
f"async_event={async_event}, lua_event={lua}):") f"async_event={async_event}, lua_event={lua}):")
if lua: if lua:
if event_name not in self.__lua_events: if event_name not in self.__lua_events:
self.__lua_events.update({str(event_name): [{"func": event_func, "name": lua}]}) self.__lua_events.update({str(event_name): [{"func_name": event_func, "lua": lua}]})
else: else:
self.__lua_events[event_name].append({"func": event_func, "name": lua}) self.__lua_events[event_name].append({"func_name": event_func, "lua": lua})
self.log.debug("Register ok") self.log.debug("Register ok")
return return
@ -141,13 +141,18 @@ class EventsSystem:
funcs_data = [] funcs_data = []
if event_name in self.__lua_events.keys(): if event_name in self.__lua_events.keys():
for data in self.__lua_events[event_name]: for data in self.__lua_events[event_name]:
func = data['func'] lua = data['lua']
func_name = data["func_name"]
try: try:
func = lua.globals()[func_name]
if not func:
self.log.warning(f"Cannot trigger local event: '{func_name}' not found!")
continue
fd = func(*args) fd = func(*args)
funcs_data.append(fd) funcs_data.append(fd)
except Exception as e: except Exception as e:
# TODO: i18n # TODO: i18n
self.log.error(f'Error while calling lua event "{event_name}"; In function: "{data["name"]}"') self.log.error(f'Error while calling lua event "{event_name}"; In function: "{func_name}"')
self.log.exception(e) self.log.exception(e)
else: else:
# TODO: i18n # TODO: i18n

View File

@ -45,8 +45,6 @@ class EventTimer:
# noinspection PyPep8Naming # noinspection PyPep8Naming
class MP: class MP:
# In ./in_lua.lua
def __init__(self, name: str, lua: LuaRuntime): def __init__(self, name: str, lua: LuaRuntime):
self.loaded = False self.loaded = False
self._event_waiters = [] self._event_waiters = []
@ -81,25 +79,13 @@ class MP:
self.log.debug("request MP.GetServerVersion()") self.log.debug("request MP.GetServerVersion()")
return ev.call_event("_get_BeamMP_version")[0] return ev.call_event("_get_BeamMP_version")[0]
def _reg_ev(self):
for event in self._event_waiters:
self.RegisterEvent(*event)
def RegisterEvent(self, event_name: str, function_name: str) -> None: def RegisterEvent(self, event_name: str, function_name: str) -> None:
self.log.debug("request MP.RegisterEvent()") self.log.debug("request MP.RegisterEvent()")
if not self.loaded: ev.register_event(event_name, function_name, lua=self._lua)
self.log.debug("MP.RegisterEvent: plugin not loaded, waiting...")
self._event_waiters.append([event_name, function_name])
return
event_func = self._lua.globals()[function_name]
if not event_func:
self.log.warning(f"Can't register '{event_name}': not found function: '{function_name}'")
return
ev.register_event(event_name, event_func, lua=function_name)
if event_name not in self._local_events: if event_name not in self._local_events:
self._local_events.update({str(event_name): [event_func]}) self._local_events.update({str(event_name): [function_name]})
else: else:
self._local_events[event_name].append(event_func) self._local_events[event_name].append(function_name)
self.log.debug("Register ok (local)") self.log.debug("Register ok (local)")
def CreateEventTimer(self, event_name: str, interval_ms: int, strategy: int = None): def CreateEventTimer(self, event_name: str, interval_ms: int, strategy: int = None):
@ -120,13 +106,20 @@ class MP:
self.log.debug(f"Calling local lua event: '{event_name}'") self.log.debug(f"Calling local lua event: '{event_name}'")
funcs_data = [] funcs_data = []
if event_name in self._local_events.keys(): if event_name in self._local_events.keys():
for func in self._local_events[event_name]: for func_name in self._local_events[event_name]:
try: try:
funcs_data.append(func(*args)) func = self._lua.globals()[func_name]
if not func:
self.log.warning(f"Cannot trigger local event: '{func_name}' not found!")
continue
fd = func(*args)
funcs_data.append(fd)
except Exception as e: except Exception as e:
self.log.error(f'Error while calling "{event_name}"; In function: "{func}"') # TODO: i18n
self.log.error(f'Error while calling lua event "{event_name}"; In function: "{func_name}"')
self.log.exception(e) self.log.exception(e)
else: else:
# TODO: i18n
self.log.warning(f"Event {event_name} does not exist, maybe ev.call_lua_event() or MP.Trigger<>Event()?. " self.log.warning(f"Event {event_name} does not exist, maybe ev.call_lua_event() or MP.Trigger<>Event()?. "
f"Just skipping it...") f"Just skipping it...")
@ -272,7 +265,7 @@ class MP:
return self._lua.table_from(client.identifiers) return self._lua.table_from(client.identifiers)
return self._lua.table() return self._lua.table()
def Set(self, *args): def Set(self, *_):
self.log.debug("request Set") self.log.debug("request Set")
self.log.warning("KuiToi cannot support this: MP.Set()") self.log.warning("KuiToi cannot support this: MP.Set()")
@ -636,7 +629,7 @@ class LuaPluginsLoader:
lua = LuaRuntime(encoding=config.enc, source_encoding=config.enc, unpack_returned_tuples=True) lua = LuaRuntime(encoding=config.enc, source_encoding=config.enc, unpack_returned_tuples=True)
lua_globals = lua.globals() lua_globals = lua.globals()
lua_globals.printRaw = lua.globals().print lua_globals.printRaw = lua.globals().print
lua_globals.exit = lambda x: self.log.info(f"{name}: You can't disable server..") lua_globals.exit = lambda x: self.log.info(f"KuiToi: You can't disable server..")
mp = MP(name, lua) mp = MP(name, lua)
lua_globals.MP = mp lua_globals.MP = mp
lua_globals.print = mp._print lua_globals.print = mp._print
@ -648,7 +641,7 @@ class LuaPluginsLoader:
lua_globals.package.path += f';{p0};{p1}' lua_globals.package.path += f';{p0};{p1}'
with open("modules/PluginsLoader/add_in.lua", "r") as f: with open("modules/PluginsLoader/add_in.lua", "r") as f:
lua.execute(f.read()) lua.execute(f.read())
self.lua_plugins.update({name: {"lua": lua, "ok": False, "th": None, "stop_th": None}}) self.lua_plugins.update({name: {"lua": lua, "ok": False}})
plugin_path = os.path.join(self.plugins_dir, name) plugin_path = os.path.join(self.plugins_dir, name)
for file in os.listdir(plugin_path): for file in os.listdir(plugin_path):
path = f"plugins/{name}/{file}" path = f"plugins/{name}/{file}"
@ -660,7 +653,6 @@ class LuaPluginsLoader:
self.log.error(f"Cannot load lua plugin from `{path}`: {e}") self.log.error(f"Cannot load lua plugin from `{path}`: {e}")
try: try:
lua_globals.MP.loaded = True lua_globals.MP.loaded = True
lua_globals.MP._reg_ev()
lua_globals.MP.TriggerLocalEvent("onInit") lua_globals.MP.TriggerLocalEvent("onInit")
lua_globals.onInit() lua_globals.onInit()
self.lua_plugins[name]['ok'] = True self.lua_plugins[name]['ok'] = True
@ -672,8 +664,8 @@ class LuaPluginsLoader:
def unload(self, _): def unload(self, _):
self.log.debug("Unloading lua plugins") self.log.debug("Unloading lua plugins")
for k, data in self.lua_plugins.items(): for name, data in self.lua_plugins.items():
if data['ok']: if data['ok']:
self.log.debug(f"Unloading lua plugin: {k}") self.log.info(f"Unloading lua plugin: {name}")
for k, v in data['lua'].globals().MP._event_timers.items(): for _, timer in data['lua'].globals().MP._event_timers.items():
v.stop() timer.stop()