Compare commits

..

No commits in common. "dd2c461581973eb1341e13d48a2b044ed1265397" and "dcafef918a0c9b1e6169431da5d69cb11a43590f" have entirely different histories.

9 changed files with 203 additions and 315 deletions

View File

@ -11,21 +11,17 @@ BeamingDrive Multiplayer (BeamMP) server compatible with BeamMP clients.
- [x] Private access (Without key, Direct connect) - [x] Private access (Without key, Direct connect)
- [x] Public access (With key, listing in Launcher) - [x] Public access (With key, listing in Launcher)
- [X] Player authentication - [X] Player authentication
- [ ] KuiToi System
- [ ] Servers counter
- [ ] Players counter
- [ ] Etc.
- [ ] TCP Server part: - [ ] TCP Server part:
- [x] Handle code - [x] Handle code
- [x] Understanding BeamMP header - [x] Understanding BeamMP header
- [ ] Upload mods - [ ] Upload mods
- [x] Connecting to the world - [x] Connecting to the world
- [x] Chat - [x] Chat
- [x] Players online counter - [ ] Player counter _(Code: Ss)_
- [ ] Car state synchronizations _(Codes: We, Vi)_ - [ ] Car state synchronizations _(Codes: We, Vi)_
- [ ] "ABG:" (compressed data) - [ ] "ABG:" (compressed data)
- [x] Decompress data - [x] Decompress data
- [ ] Vehicle data _(Code: Os)_ - [ ] Vehicle data
- [ ] UDP Server part: - [ ] UDP Server part:
- [ ] Players synchronizations _(Code: Zp)_ - [ ] Players synchronizations _(Code: Zp)_
- [ ] Ping _(Code: p)_ - [ ] Ping _(Code: p)_

View File

@ -2,7 +2,7 @@
# File core.__init__.py # File core.__init__.py
# Written by: SantaSpeen # Written by: SantaSpeen
# Version 1.3 # Version 1.3
# Core version: 0.2.1 # Core version: 0.2.0
# Licence: FPA # Licence: FPA
# (c) kuitoi.su 2023 # (c) kuitoi.su 2023
# Special thanks to: AI Sage(https://poe.com/Sage), AI falcon-40b-v7(https://OpenBuddy.ai) # Special thanks to: AI Sage(https://poe.com/Sage), AI falcon-40b-v7(https://OpenBuddy.ai)
@ -10,8 +10,8 @@
__title__ = 'KuiToi-Server' __title__ = 'KuiToi-Server'
__description__ = 'BeamingDrive Multiplayer server compatible with BeamMP clients.' __description__ = 'BeamingDrive Multiplayer server compatible with BeamMP clients.'
__url__ = 'https://github.com/kuitoi/kuitoi-Server' __url__ = 'https://github.com/kuitoi/kuitoi-Server'
__version__ = '0.2.1' __version__ = '0.2.0'
__build__ = 874 __build__ = 776
__author__ = 'SantaSpeen' __author__ = 'SantaSpeen'
__author_email__ = 'admin@kuitoi.su' __author_email__ = 'admin@kuitoi.su'
__license__ = "FPA" __license__ = "FPA"

View File

@ -1,12 +1,11 @@
# Developed by KuiToi Dev # Developed by KuiToi Dev
# File core.core.py # File core.core.py
# Written by: SantaSpeen # Written by: SantaSpeen
# Core version: 0.2.1 # Version 0.2.0
# Licence: FPA # Licence: FPA
# (c) kuitoi.su 2023 # (c) kuitoi.su 2023
import asyncio import asyncio
import os import os
import random
import zlib import zlib
from threading import Thread from threading import Thread
@ -37,8 +36,8 @@ class Client:
self.alive = True self.alive = True
def _update_logger(self): def _update_logger(self):
self.log = utils.get_logger(f"client({self.nick}:{self.cid})")
self.log.debug(f"Update logger") self.log.debug(f"Update logger")
self.log = utils.get_logger(f"client({self.nick}:{self.cid})")
def is_disconnected(self): def is_disconnected(self):
if not self.alive: if not self.alive:
@ -56,10 +55,11 @@ class Client:
async def kick(self, reason): async def kick(self, reason):
self.log.info(f"Client: \"IP: {self.addr!r}; ID: {self.cid}\" - kicked with reason: \"{reason}\"") self.log.info(f"Client: \"IP: {self.addr!r}; ID: {self.cid}\" - 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.writer.close()
# await self.writer.wait_closed()
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):
# TNetwork.cpp; Line: 383 # TNetwork.cpp; Line: 383
# BeamMP TCP protocol sends a header of 4 bytes, followed by the data. # BeamMP TCP protocol sends a header of 4 bytes, followed by the data.
@ -67,33 +67,18 @@ class Client:
# ^------^^---...-^ # ^------^^---...-^
# size data # size data
if writer is None:
writer = self.writer
if to_all:
for client in self.Core.clients:
if not client:
continue
await client.tcp_send(data)
return
self.log.debug(f"tcp_send({data})") 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)
self.log.debug(f'len(data) {len(data)}; send {header + data}') self.log.debug(f'len(data) {len(data)}; send {header + data}')
try: self.writer.write(header + data)
writer.write(header + data) await self.writer.drain()
await writer.drain()
except ConnectionError:
self.log.debug('Disconnected')
self.alive = False
async def recv(self, kostil=False): async def recv(self):
# if not self.is_disconnected(): # if not self.is_disconnected():
# self.log.debug(f"Client with {self.nick}({self.cid}) disconnected") # self.log.debug(f"Client with {self.nick}({self.cid}) disconnected")
# return b"" # return b""
try:
header = await self.reader.read(4) # header: 4 bytes header = await self.reader.read(4) # header: 4 bytes
int_header = 0 int_header = 0
@ -101,14 +86,6 @@ class Client:
int_header += header[i] int_header += header[i]
if int_header <= 0: if int_header <= 0:
await asyncio.sleep(0.1)
if not self.alive:
self.log.debug(f"Disconnected")
self.writer.close()
return b''
if kostil:
return
self.log.debug(f"Header: {header}")
await self.kick("Invalid packet - header negative") await self.kick("Invalid packet - header negative")
return b"" return b""
@ -118,7 +95,7 @@ class Client:
f"assuming malicious intent and disconnecting the client.") f"assuming malicious intent and disconnecting the client.")
return b"" return b""
data = await self.reader.read(100 * MB) data = await self.reader.read(101 * MB)
self.log.debug(f"header: `{header}`; int_header: `{int_header}`; data: `{data}`;") self.log.debug(f"header: `{header}`; int_header: `{int_header}`; data: `{data}`;")
if len(data) != int_header: if len(data) != int_header:
@ -130,35 +107,23 @@ class Client:
self.log.debug(f"ABG: {data}") self.log.debug(f"ABG: {data}")
return data return data
return data return data
except ConnectionError:
self.alive = False
await self.remove_me()
return b""
async def sync_resources(self): async def sync_resources(self):
while True: while True:
data = await self.recv() data = await self.recv()
if not data:
await asyncio.sleep(.1)
continue
self.log.debug(f"Received: {data}")
if data.startswith(b"f"): if data.startswith(b"f"):
# TODO: SendFile # TODO: SendFile
file = data[1:].decode("utf-8") pass
self.log.debug(f"Sending File: {file}")
await self.kick(f"TODO: SendFile({file})")
elif data.startswith(b"SR"): elif data.startswith(b"SR"):
# TODO: Create mods list
self.log.debug("Sending Mod Info") self.log.debug("Sending Mod Info")
mod_list = '%s;%s;' mods = []
for mod in self.Core.mods_list: mod_list = b''
if type(mod) == int: # * code *
continue if len(mods) == 0:
mod_list = (mod_list % (mod['path'], mod['size'])).replace(";", ";%s;")
mod_list = mod_list.replace("%s;", "")
if len(mod_list) == 0:
await self.tcp_send(b"-") await self.tcp_send(b"-")
else: else:
await self.tcp_send(bytes(mod_list, "utf-8")) await self.tcp_send(mod_list)
data = await self.recv() data = await self.recv()
if data == b"Done": if data == b"Done":
await self.tcp_send(b"M/levels/" + bytes(config.Game['map'], 'utf-8') + b"/info.json") await self.tcp_send(b"M/levels/" + bytes(config.Game['map'], 'utf-8') + b"/info.json")
@ -166,6 +131,7 @@ class Client:
async def looper(self): async def looper(self):
# self.is_disconnected() # self.is_disconnected()
self.log.debug(f"Alive: {self.alive}")
await self.tcp_send(b"P" + bytes(f"{self.cid}", "utf-8")) await self.tcp_send(b"P" + bytes(f"{self.cid}", "utf-8"))
await self.sync_resources() await self.sync_resources()
while self.alive: while self.alive:
@ -173,31 +139,19 @@ class Client:
if data == b"": if data == b"":
if not self.alive: if not self.alive:
break break
elif self.is_disconnected():
break
else: else:
await asyncio.sleep(.2)
continue continue
code = data.decode()[0] code = data.decode()[0]
self.log.debug(f"Received code: {code}, data: {data}") self.log.debug(f"Code: {code}, data: {data}")
match code: match code:
case "H": case "H":
# Client connected # Client connected
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"))
case "C": case "C":
# Chat # Chat
await self.tcp_send(data, to_all=True) await self.tcp_send(data)
async def remove_me(self):
self.log.debug(f"Removing client {self.nick}({self.cid})")
await asyncio.sleep(0.3)
if not self.writer.is_closing():
self.writer.close()
if (self.cid > 0 or self.nick is not None) and self.Core.clients_by_id.get(self.cid):
_, down_w = self.down_rw
if down_w and not down_w.is_closing():
down_w.close()
self.Core.clients[self.cid] = None
self.Core.clients_by_id.pop(self.cid)
self.Core.clients_by_nick.pop(self.nick)
class Core: class Core:
@ -223,60 +177,40 @@ class Core:
self.client_major_version = "2.0" self.client_major_version = "2.0"
self.BeamMP_version = "3.2.0" self.BeamMP_version = "3.2.0"
def get_client(self, cid=None, nick=None): def get_client(self, sock=None, cid=None, nick=None):
if cid: if cid:
return self.clients_by_id.get(cid) return self.clients_by_id.get(cid)
if nick: if nick:
return self.clients_by_nick.get(nick) return self.clients_by_nick.get(nick)
if sock:
return self.clients_by_nick.get(sock.getsockname())
async def insert_client(self, client): def insert_client(self, client):
await asyncio.sleep(random.randint(3, 9) * 0.01) self.log.debug(f"Inserting client: {client.cid}")
cid = 0 self.clients_by_nick.update({client.nick: client})
for _client in self.clients: self.clients_by_id.update({client.cid: client})
if not _client: self.clients[client.cid] = client
break
if _client.cid == cid: def create_client(self, *args, **kwargs):
client = Client(*args, **kwargs)
cid = 1
for client in self.clients:
if client.cid == cid:
cid += 1 cid += 1
else: else:
break break
await asyncio.sleep(random.randint(3, 9) * 0.01)
if not self.clients[cid]:
client.cid = cid client.cid = cid
self.clients_by_nick.update({client.nick: client})
self.log.debug(f"Inserting client: id{client.cid}")
self.clients_by_id.update({client.cid: client})
self.clients[client.cid] = client
client._update_logger() client._update_logger()
return self.log.debug(f"Create client; client.cid: {client.cid};")
await self.insert_client(client)
def create_client(self, *args, **kwargs):
self.log.debug(f"Create client")
client = Client(core=self, *args, **kwargs)
return client return client
def get_clients_list(self, need_cid=False):
out = ""
for client in self.clients:
if not client:
continue
out += f"{client.nick}"
if need_cid:
out += f":{client.cid}"
out += ","
if out:
out = out[:-1]
return out
async def check_alive(self): async def check_alive(self):
maxp = config.Game['players'] await asyncio.sleep(5)
while self.run: self.log.debug(f"Checking if clients is alive")
await asyncio.sleep(1)
ca = f"Ss{len(self.clients_by_id)}/{maxp}:{self.get_clients_list()}"
for client in self.clients: for client in self.clients:
if not client: d = client.is_disconnected()
continue if d:
await client.tcp_send(bytes(ca, "utf-8")) self.log.debug(f"Client ID: {client.cid} died...")
@staticmethod @staticmethod
def start_web(): def start_web():
@ -289,10 +223,10 @@ class Core:
webapp.uvserver = uvserver webapp.uvserver = uvserver
uvserver.run() uvserver.run()
async def stop_me(self): @staticmethod
async def stop_me():
while webapp.data_run[0]: while webapp.data_run[0]:
await asyncio.sleep(1) await asyncio.sleep(1)
self.run = False
raise KeyboardInterrupt raise KeyboardInterrupt
# noinspection SpellCheckingInspection,PyPep8Naming # noinspection SpellCheckingInspection,PyPep8Naming
@ -312,7 +246,6 @@ class Core:
modstotalsize = self.mods_list[0] modstotalsize = self.mods_list[0]
modstotal = len(self.mods_list) - 1 modstotal = len(self.mods_list) - 1
while self.run: while self.run:
try:
data = {"uuid": config.Auth["key"], "players": len(self.clients), "maxplayers": config.Game["players"], data = {"uuid": config.Auth["key"], "players": len(self.clients), "maxplayers": config.Game["players"],
"port": config.Server["server_port"], "map": f"/levels/{config.Game['map']}/info.json", "port": config.Server["server_port"], "map": f"/levels/{config.Game['map']}/info.json",
"private": config.Auth['private'], "version": self.BeamMP_version, "private": config.Auth['private'], "version": self.BeamMP_version,
@ -371,17 +304,11 @@ class Core:
return ok return ok
await asyncio.sleep(5) await asyncio.sleep(5)
except Exception as e:
self.log.error(f"Error in heartbeat: {e}")
async def main(self): async def main(self):
self.run = True self.run = True
self.tcp = self.tcp(self, self.server_ip, self.server_port) self.tcp = self.tcp(self, self.server_ip, self.server_port)
self.udp = self.udp(self, self.server_ip, self.server_port) self.udp = self.udp(self, self.server_ip, self.server_port)
console.add_command(
"list",
lambda x: f"Players list: {self.get_clients_list(True)}"
)
try: try:
# WebApi Start # WebApi Start
if config.WebAPI["enabled"]: if config.WebAPI["enabled"]:
@ -409,11 +336,9 @@ class Core:
self.log.info(f"Loaded {lmods} mods: {round(self.mods_list[0] / MB, 2)}mb") self.log.info(f"Loaded {lmods} 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)):
self.clients.append(None)
tasks = [] tasks = []
# self.udp.start, # self.check_alive()
nrtasks = [self.tcp.start, console.start, self.stop_me, self.heartbeat, self.check_alive] nrtasks = [self.tcp.start, self.udp.start, console.start, self.stop_me, self.heartbeat, ]
for task in nrtasks: for task in nrtasks:
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)
@ -429,7 +354,7 @@ class Core:
pass pass
finally: finally:
self.tcp.stop() self.tcp.stop()
# self.udp.stop() self.udp.stop()
self.run = False self.run = False
def start(self): def start(self):

View File

@ -24,7 +24,7 @@ class Client:
self.addr = writer.get_extra_info("sockname") self.addr = writer.get_extra_info("sockname")
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
self.Core = core self.Core = core
self.cid: int = 0 self.cid = 0
self.key: str = None self.key: str = None
self.nick: str = None self.nick: str = None
self.roles: str = None self.roles: str = None
@ -32,12 +32,12 @@ class Client:
self.alive = True self.alive = True
def is_disconnected(self) -> bool: ... def is_disconnected(self) -> bool: ...
async def kick(self, reason: str) -> None: ... async def kick(self, reason: str) -> None: ...
async def tcp_send(self, data: bytes, to_all:bool = False, writer: StreamWriter = None) -> None: ... async def tcp_send(self, data: bytes) -> None: ...
async def sync_resources(self) -> None: ... async def sync_resources(self) -> None: ...
async def recv(self) -> bytes: ... async def recv(self) -> bytes: ...
async def looper(self) -> None: ... async def looper(self) -> None: ...
def _update_logger(self) -> None: ... def _update_logger(self) -> None: ...
async def remove_me(self) -> None: ...
class Core: class Core:
def __init__(self): def __init__(self):
@ -45,7 +45,7 @@ class Core:
self.loop = asyncio.get_event_loop() self.loop = asyncio.get_event_loop()
self.run = False self.run = False
self.direct = False self.direct = False
self.clients: List[Client | None]= [] self.clients: List[Client]= []
self.clients_by_id: Dict[{int: Client}]= {} self.clients_by_id: Dict[{int: Client}]= {}
self.clients_by_nick: Dict[{str: Client}] = {} self.clients_by_nick: Dict[{str: Client}] = {}
self.clients_counter: int = 0 self.clients_counter: int = 0
@ -59,13 +59,13 @@ class Core:
self.web_stop: Callable = lambda: None self.web_stop: Callable = lambda: None
self.client_major_version = "2.0" self.client_major_version = "2.0"
self.BeamMP_version = "3.2.0" self.BeamMP_version = "3.2.0"
async def insert_client(self, client: Client) -> None: ... def insert_client(self, client: Client) -> None: ...
def create_client(self, *args, **kwargs) -> Client: ... def create_client(self, *args, **kwargs) -> Client: ...
def get_clients_list(self, need_cid=False) -> str: ...
async def check_alive(self) -> None: ... async def check_alive(self) -> None: ...
@staticmethod @staticmethod
def start_web() -> None: ... def start_web() -> None: ...
def stop_me(self) -> None: ... @staticmethod
def stop_me() -> None: ...
async def heartbeat(self, test=False) -> None: ... async def heartbeat(self, test=False) -> None: ...
async def main(self) -> None: ... async def main(self) -> None: ...
def start(self) -> None: ... def start(self) -> None: ...

View File

@ -1,13 +1,11 @@
# Developed by KuiToi Dev # Developed by KuiToi Dev
# File core.tcp_server.py # File core.tcp_server.py
# Written by: SantaSpeen # Written by: SantaSpeen
# Core version: 0.2.1 # Version 0.2.0
# Licence: FPA # Licence: FPA
# (c) kuitoi.su 2023 # (c) kuitoi.su 2023
import asyncio import asyncio
import traceback import traceback
from asyncio import AbstractEventLoop
from threading import Thread
import aiohttp import aiohttp
@ -17,11 +15,10 @@ from core import utils
class TCPServer: class TCPServer:
def __init__(self, core, host, port): def __init__(self, core, host, port):
self.log = utils.get_logger("TCPServer") self.log = utils.get_logger("TCPServer")
self.loop = asyncio.get_event_loop()
self.Core = core self.Core = core
self.host = host self.host = host
self.port = port self.port = port
self.run = False self.loop = asyncio.get_event_loop()
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)
@ -40,58 +37,49 @@ class TCPServer:
await client.kick("Invalid Key (too long)!") await client.kick("Invalid Key (too long)!")
return False, None return False, None
client.key = data.decode("utf-8") client.key = data.decode("utf-8")
try:
async with aiohttp.ClientSession() as session: async with aiohttp.ClientSession() as session:
url = 'https://auth.beammp.com/pkToUser' url = 'https://auth.beammp.com/pkToUser'
async with session.post(url, data={'key': client.key}) as response: async with session.post(url, data={'key': client.key}) as response:
res = await response.json() res = await response.json()
self.log.debug(f"res: {res}") self.log.debug(f"res: {res}")
try:
if res.get("error"): if res.get("error"):
await client.kick('Invalid key! Please restart your game.') await client.kick('Invalid key! Please restart your game.')
return False, None return
client.nick = res["username"] client.nick = res["username"]
client.roles = res["roles"] client.roles = res["roles"]
client.guest = res["guest"] client.guest = res["guest"]
client._update_logger() client._update_logger()
except Exception as e: except Exception as e:
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 connect in 5 minutes.')
return False, None
for _client in self.Core.clients: for _client in self.Core.clients:
if not _client:
continue
if _client.nick == client.nick and _client.guest == client.guest: if _client.nick == client.nick and _client.guest == client.guest:
await client.kick('Stale Client (replaced by new client)') await client.kick('Stale Client (replaced by new client)')
return False, None
ev.call_event("on_auth", client) ev.call_event("on_auth", client)
if len(self.Core.clients_by_id) > config.Game["players"]: if len(self.Core.clients) > config.Game["players"]:
await client.kick("Server full!") await client.kick("Server full!")
return False, None
else: else:
self.log.info("Identification success") self.log.info("Identification success")
await self.Core.insert_client(client) self.Core.insert_client(client)
return True, client return True, client
async def set_down_rw(self, reader, writer): async def set_down_rw(self, reader, writer):
try: try:
cid = (await reader.read(1))[0] cid = (await reader.read(1)).decode() # FIXME: wtf? 1 byte?
ok = False self.log.debug(f"Client: \"ID: {cid}\" - HandleDownload!")
if not cid.isdigit():
return False
for _client in self.Core.clients: for _client in self.Core.clients:
if not _client:
continue
if _client.cid == cid: if _client.cid == cid:
_client.down_rw = (reader, writer) _client.down_rw = (reader, writer)
ok = True return True
self.log.debug(f"Client: {_client.nick}:{cid} - HandleDownload!")
if not ok:
writer.close()
self.log.debug(f"Unknown client - HandleDownload")
finally: finally:
return return False
async def handle_code(self, code, reader, writer): async def handle_code(self, code, reader, writer):
match code: match code:
@ -99,17 +87,17 @@ class TCPServer:
result, client = await self.auth_client(reader, writer) result, client = await self.auth_client(reader, writer)
if result: if result:
await client.looper() await client.looper()
return result, client return True
return False
case "D": case "D":
await self.set_down_rw(reader, writer) return await self.set_down_rw(reader, writer)
case "P": case "P":
writer.write(b"P") writer.write(b"P")
await writer.drain() await writer.drain()
writer.close() return True
case _: case _:
self.log.error(f"Unknown code: {code}") self.log.error(f"Unknown code: {code}")
writer.close() return False
return False, None
async def handle_client(self, reader, writer): async def handle_client(self, reader, writer):
while True: while True:
@ -119,37 +107,28 @@ class TCPServer:
break break
code = data.decode() code = data.decode()
self.log.debug(f"Received {code!r} from {writer.get_extra_info('sockname')!r}") self.log.debug(f"Received {code!r} from {writer.get_extra_info('sockname')!r}")
# task = asyncio.create_task(self.handle_code(code, reader, writer)) result = await self.handle_code(code, reader, writer)
# await asyncio.wait([task], return_when=asyncio.FIRST_EXCEPTION) if not result:
_, cl = await self.handle_code(code, reader, writer)
if cl:
await cl.remove_me()
break break
except Exception as e: except Exception as e:
self.log.error("Error while connecting..") self.log.error("Error while connecting..")
self.log.exception(e) self.log.error(f"Error: {e}")
traceback.print_exc() traceback.print_exc()
break break
async def start(self): async def start(self):
self.log.debug("Starting TCP server.") self.log.debug("Starting TCP server.")
self.run = True
try: try:
server = await asyncio.start_server(self.handle_client, self.host, self.port, server = await asyncio.start_server(self.handle_client, self.host, self.port,
backlog=int(config.Game["players"] * 1.3)) backlog=int(config.Game["players"] * 1.3))
except OSError as e:
self.log.error(f"Error: {e}")
self.Core.run = False
raise e
self.log.debug(f"TCP server started on {server.sockets[0].getsockname()!r}") self.log.debug(f"TCP server started on {server.sockets[0].getsockname()!r}")
while True: while True:
async with server: async with server:
await server.serve_forever() await server.serve_forever()
except OSError as e:
self.log.error("Cannot bind port")
raise e
except BaseException as e:
self.log.error(f"Error: {e}")
raise e
finally:
self.run = False
self.Core.run = False
def stop(self): def stop(self):
self.log.debug("Stopping TCP server") self.log.debug("Stopping TCP server")

View File

@ -15,14 +15,13 @@ from core.core import Client
class TCPServer: class TCPServer:
def __init__(self, core: Core, host, port): def __init__(self, core: Core, host, port):
self.log = utils.get_logger("TCPServer") self.log = utils.get_logger("TCPServer")
self.loop = asyncio.get_event_loop()
self.Core = core self.Core = core
self.host = host self.host = host
self.port = port self.port = port
self.run = False self.loop = asyncio.get_event_loop()
async def auth_client(self, reader: StreamReader, writer: StreamWriter) -> Tuple[bool, Client]: ... async def auth_client(self, reader: StreamReader, writer: StreamWriter) -> Tuple[bool, Client]: ...
async def set_down_rw(self, reader: StreamReader, writer: StreamWriter) -> bool: ... async def set_down_rw(self, reader: StreamReader, writer: StreamWriter) -> bool: ...
async def handle_code(self, code: str, reader: StreamReader, writer: StreamWriter) -> Tuple[bool, Client]: ... async def handle_code(self, code: str, reader: StreamReader, writer: StreamWriter) -> bool: ...
async def handle_client(self, reader: StreamReader, writer: StreamWriter) -> None: ... async def handle_client(self, reader: StreamReader, writer: StreamWriter) -> None: ...
async def start(self) -> None: ... async def start(self) -> None: ...
async def stop(self) -> None: ... async def stop(self) -> None: ...

View File

@ -14,47 +14,43 @@ class UDPServer:
def __init__(self, core, host, port): def __init__(self, core, host, port):
self.log = utils.get_logger("UDPServer") self.log = utils.get_logger("UDPServer")
self.loop = asyncio.get_event_loop()
self.Core = core self.Core = core
self.host = host self.host = host
self.port = port self.port = port
self.run = False self.loop = asyncio.get_event_loop()
async def handle_client(self, reader, writer): async def handle_client(self, srv_sock):
while True: while True:
try: try:
data = await reader.read(1) data, addr = await self.loop.sock_recv(srv_sock, 1024)
if not data: if not data:
break break
code = data.decode() code = data.decode()
self.log.debug(f"Received {code!r} from {writer.get_extra_info('sockname')!r}") self.log.debug(f"Received {code!r} from {addr!r}")
# await self.handle_code(code, reader, writer) # if not await self.handle_code(code, sock):
# task = asyncio.create_task(self.handle_code(code, reader, writer)) # break
# await asyncio.wait([task], return_when=asyncio.FIRST_EXCEPTION)
if not writer.is_closing():
writer.close()
self.log.debug("Disconnected.")
break
except Exception as e: except Exception as e:
self.log.error("Error while connecting..")
self.log.error(f"Error: {e}") self.log.error(f"Error: {e}")
traceback.print_exc() traceback.print_exc()
break break
srv_sock.close()
self.log.error("Error while connecting..")
async def start(self): async def start(self):
self.log.debug("Starting UDP server.")
self.run = True
try:
pass pass
except OSError as e: # self.log.debug("Starting UDP server.")
self.log.error("Cannot bind port or other error") # await self.stop()
raise e # srv_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except BaseException as e: # srv_sock.bind((self.host, self.port))
self.log.error(f"Error: {e}") # self.log.debug(f"Serving on {srv_sock.getsockname()}")
raise e # try:
finally: # await self.handle_client(srv_sock)
self.run = False # except Exception as e:
self.Core.run = False # self.log.error(f"Error: {e}")
# traceback.print_exc()
# finally:
# await self.stop()
def stop(self): def stop(self):
self.log.debug("Stopping UDP server") pass
# self.log.debug("Stopping UDP server")

View File

@ -13,11 +13,10 @@ class UDPServer:
def __init__(self, core, host, port): def __init__(self, core, host, port):
self.log = utils.get_logger("UDPServer") self.log = utils.get_logger("UDPServer")
self.loop = asyncio.get_event_loop()
self.Core = core self.Core = core
self.host = host self.host = host
self.port = port self.port = port
self.run = False self.loop = asyncio.get_event_loop()
async def handle_client(self, srv_sock) -> None: ... async def handle_client(self, srv_sock) -> None: ...
async def start(self) -> None: ... async def start(self) -> None: ...

View File

@ -26,7 +26,6 @@ class Console:
prompt_out="", prompt_out="",
not_found="Command \"%s\" not found in alias.", not_found="Command \"%s\" not found in alias.",
debug=False) -> None: debug=False) -> None:
self.__logger = get_logger("console")
self.__is_run = False self.__is_run = False
self.__prompt_in = prompt_in self.__prompt_in = prompt_in
self.__prompt_out = prompt_out self.__prompt_out = prompt_out
@ -45,11 +44,10 @@ class Console:
self.completer = NestedCompleter.from_nested_dict(self.__alias) self.completer = NestedCompleter.from_nested_dict(self.__alias)
def __debug(self, *x): def __debug(self, *x):
self.__logger.debug(f"{x}") if self.__is_debug:
# if self.__is_debug: x = list(x)
# x = list(x) x.insert(0, "\r CONSOLE DEBUG:")
# x.insert(0, "\r CONSOLE DEBUG:") self.__print(*x)
# self.__print(*x)
def __getitem__(self, item): def __getitem__(self, item):
print(item) print(item)
@ -134,8 +132,7 @@ class Console:
print_formatted_text(s) print_formatted_text(s)
def log(self, s: AnyStr) -> None: def log(self, s: AnyStr) -> None:
self.__logger.info(f"{s}") self.write(s)
# self.write(s)
def __lshift__(self, s: AnyStr) -> None: def __lshift__(self, s: AnyStr) -> None:
self.write(s) self.write(s)
@ -199,20 +196,17 @@ class Console:
cmd_s = cmd_in.split(" ") cmd_s = cmd_in.split(" ")
cmd = cmd_s[0] cmd = cmd_s[0]
if cmd == "": if cmd == "":
continue pass
else: else:
command_object = self.__func.get(cmd) command_object = self.__func.get(cmd)
if command_object: if command_object:
out = command_object['f'](cmd_s[1:]) self.log(str(command_object['f'](cmd_s[1:])))
if out:
self.log(out)
else: else:
self.log(self.__not_found % cmd) self.log(self.__not_found % cmd)
except KeyboardInterrupt: except KeyboardInterrupt:
raise KeyboardInterrupt raise KeyboardInterrupt
except Exception as e: except Exception as e:
print(f"Error in console.py: {e}") print(f"Error in console.py: {e}")
self.__logger.exception(e)
async def start(self): async def start(self):
self.__is_run = True self.__is_run = True