diff --git a/README.md b/README.md index 6c12b7d..d536047 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ BeamingDrive Multiplayer (BeamMP) server compatible with BeamMP clients. - [ ] TCP Server part: - [x] Handle code - [x] Understanding beamp header - - [ ] Authorization + - [X] Authorization - [ ] Upload mods - - [ ] UDP Server part: - [ ] Connecting to the world - - [ ] Any.... + - [ ] UDP Server part: + - [ ] Players synchronizations - [x] Additional: - [x] Events System - [x] Plugins support diff --git a/src/core/tcp_server.py b/src/core/tcp_server.py index 5f7ba90..9dc725e 100644 --- a/src/core/tcp_server.py +++ b/src/core/tcp_server.py @@ -5,9 +5,10 @@ # Licence: FPA # (c) kuitoi.su 2023 import asyncio -import socket import traceback +import aiohttp + from core import utils @@ -52,30 +53,57 @@ class TCPServer: # return DeComp(Data); return data - async def auth_client(self, sock): + async def auth_client(self, reader, writer): # TODO: Authentication - client = self.Core.create_client(sock) - self.log.debug(f"Client: \"IP: {client.addr!r}; ID: {client.cid}\" - Authentication!") + client = self.Core.create_client(reader, writer) + self.log.info(f"Identifying new ClientConnection...") data = await self.recv(client) self.log.debug(f"recv1 data: {data}") if len(data) > 50: - client.kick("Too long data") + await client.kick("Too long data") return if "VC2.0" not in data.decode("utf-8"): - client.kick("Outdated Version.") + await client.kick("Outdated Version.") return else: - pass - # self.log.debug('tcp_send(b"A")') - # client.tcp_send(b"A") + await client.tcp_send(b"A") # Accepted client version + # await client.tcp_send(b"S") # Ask client key - # data = await self.recv(client) - # self.log.debug(f"recv2 data: {data}") + data = await self.recv(client) + self.log.debug(f"recv2 data: {data}") + if len(data) > 50: + await client.kick("Invalid Key (too long)!") + return + client.key = data.decode("utf-8") + async with aiohttp.ClientSession() as session: + url = 'https://auth.beammp.com/pkToUser' + async with session.post(url, data={'key': client.key}) as response: + res = await response.json() + self.log.debug(f"res: {res}") + try: + if res.get("error"): + await client.kick('Invalid key! Please restart your game.') + return + client.nick = res["username"] + client.roles = res["roles"] + client.guest = res["guest"] + except Exception as e: + self.log.error(f"Auth error: {e}") + await client.kick('Invalid authentication data! Try to econnect in 5 minutes.') - client.kick("TODO Authentication") - return False + # TODO: Password party - async def handle_download(self, sock): + ev.call_event("on_auth", client) + + if len(self.Core.clients) > config.Game["players"]: + await client.kick("Server full!") + else: + self.log.info("Identification success") + self.Core.insert_client(client) + + return True, client + + async def handle_download(self, writer): # TODO: HandleDownload self.log.debug(f"Client: \"IP: {0!r}; ID: {0}\" - HandleDownload!") return False diff --git a/src/core/tcp_server.pyi b/src/core/tcp_server.pyi index 10c00c7..967e5a9 100644 --- a/src/core/tcp_server.pyi +++ b/src/core/tcp_server.pyi @@ -4,8 +4,10 @@ # Version 0.1.2 # Licence: FPA # (c) kuitoi.su 2023 +import asyncio from asyncio import StreamWriter, StreamReader import socket +from typing import Tuple from core import utils, Core from core.core import Client @@ -17,11 +19,12 @@ class TCPServer: self.Core = core self.host = host self.port = port + self.loop = asyncio.get_event_loop() async def recv(self, client: Client) -> bytes: ... - async def auth_client(self, sock: socket.socket) -> None: ... - async def handle_download(self, sock: socket.socket) -> None: ... - async def handle_code(self, code: str, sock: socket.socket) -> None: ... - async def handle_client(self, sock: socket.socket) -> None: ... + async def auth_client(self, reader: StreamReader, writer: StreamWriter) -> Tuple[bool, Client]: ... + async def handle_download(self, writer: StreamWriter) -> bool: ... + async def handle_code(self, code: str, reader: StreamReader, writer: StreamWriter) -> bool: ... + async def handle_client(self, reader: StreamReader, writer: StreamWriter) -> None: ... async def start(self) -> None: ... async def stop(self) -> None: ...