mirror of
https://github.com/kuitoi/kuitoi-Server.git
synced 2026-06-18 14:41:21 +00:00
I have sockets..
This commit is contained in:
@@ -35,7 +35,7 @@ from modules import Console
|
|||||||
from modules import MultiLanguage
|
from modules import MultiLanguage
|
||||||
from core.core import Core
|
from core.core import Core
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.new_event_loop()
|
||||||
asyncio.set_event_loop(loop)
|
asyncio.set_event_loop(loop)
|
||||||
log = get_logger("init")
|
log = get_logger("init")
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ builtins.config = config
|
|||||||
log.debug("Initializing console...")
|
log.debug("Initializing console...")
|
||||||
console = Console()
|
console = Console()
|
||||||
console.builtins_hook()
|
console.builtins_hook()
|
||||||
console.logger_hook()
|
# console.logger_hook()
|
||||||
console.add_command("stop", console.stop, "stop - Just shutting down the server.\nUsage: stop", "Server shutdown.")
|
console.add_command("stop", console.stop, "stop - Just shutting down the server.\nUsage: stop", "Server shutdown.")
|
||||||
console.add_command("exit", console.stop, "stop - Just shutting down the server.\nUsage: stop", "Server shutdown.")
|
console.add_command("exit", console.stop, "stop - Just shutting down the server.\nUsage: stop", "Server shutdown.")
|
||||||
|
|
||||||
|
|||||||
+66
-73
@@ -5,10 +5,51 @@
|
|||||||
# Licence: FPA
|
# Licence: FPA
|
||||||
# (c) kuitoi.su 2023
|
# (c) kuitoi.su 2023
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import socket
|
||||||
import struct
|
import struct
|
||||||
from asyncio import StreamWriter, StreamReader
|
import traceback
|
||||||
|
|
||||||
from core import utils
|
from core import utils
|
||||||
|
from .tcp_server import TCPServer
|
||||||
|
from .udp_server import UDPServer
|
||||||
|
|
||||||
|
|
||||||
|
class Client:
|
||||||
|
|
||||||
|
def __init__(self, sock):
|
||||||
|
self.cid = 0
|
||||||
|
self.nick = None
|
||||||
|
self.log = utils.get_logger("client")
|
||||||
|
self.addr = sock.getsockname()
|
||||||
|
self.socket = sock
|
||||||
|
self.loop = asyncio.get_event_loop()
|
||||||
|
self.alive = True
|
||||||
|
|
||||||
|
def is_disconnected(self):
|
||||||
|
if not self.alive:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
keep_alive = self.socket.getsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE)
|
||||||
|
if keep_alive:
|
||||||
|
return False
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
self.alive = False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def kick(self, reason):
|
||||||
|
self.log.info(f"Client: \"IP: {self.addr!r}; ID: {self.cid}\" - kicked with reason: \"{reason}\"")
|
||||||
|
self.socket.send(b"K" + bytes(reason, "utf-8"))
|
||||||
|
self.socket.close()
|
||||||
|
self.alive = False
|
||||||
|
|
||||||
|
def tcp_send(self, data):
|
||||||
|
header = b"C\x00\x00\x00\x00"
|
||||||
|
# size = len(data)
|
||||||
|
# to_send = bytearray(size + len(data))
|
||||||
|
# to_send[0:len(data)] = size.to_bytes(len(data), byteorder='big')
|
||||||
|
# to_send[len(data):] = data
|
||||||
|
self.socket.send(header + b"\x00" + data + b"\x00")
|
||||||
|
|
||||||
|
|
||||||
class Core:
|
class Core:
|
||||||
@@ -16,88 +57,40 @@ class Core:
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.log = utils.get_logger("core")
|
self.log = utils.get_logger("core")
|
||||||
self.clients = {}
|
self.clients = {}
|
||||||
self.loop = None
|
self.clients_counter = 0
|
||||||
|
self.server_ip = config.Server["server_ip"]
|
||||||
|
self.server_port = config.Server["server_port"]
|
||||||
|
self.loop = asyncio.get_event_loop()
|
||||||
|
self.tcp = TCPServer
|
||||||
|
self.udp = UDPServer
|
||||||
|
|
||||||
async def tpc_send(self, data, sync):
|
def create_client(self, *args, **kwargs):
|
||||||
pass
|
cl = Client(*args, **kwargs)
|
||||||
|
self.clients_counter += 1
|
||||||
|
cl.id = self.clients_counter
|
||||||
|
self.clients.update({cl.id: cl})
|
||||||
|
return cl
|
||||||
|
|
||||||
async def tcp_rcv(self, writer: StreamWriter):
|
async def check_alive(self):
|
||||||
|
await asyncio.sleep(5)
|
||||||
sock = writer.get_extra_info('socket')
|
self.log.debug(f"Checking if clients is alive")
|
||||||
print(writer.transport)
|
for cl in self.clients.values():
|
||||||
recv = writer._loop.sock_recv
|
d = await cl.is_disconnected()
|
||||||
header_data = b''
|
if d:
|
||||||
while True:
|
self.log.debug(f"Client ID: {cl.id} died...")
|
||||||
chunk = await recv(sock, 1024)
|
|
||||||
if not chunk:
|
|
||||||
break
|
|
||||||
header_data += chunk
|
|
||||||
print(header_data)
|
|
||||||
return
|
|
||||||
|
|
||||||
async def kick_client(self, writer: StreamWriter, reason: str):
|
|
||||||
self.log.info(
|
|
||||||
f"Client: \"IP: {writer.get_extra_info('peername')!r}; Nick: {None}\" - kicked with reason: \"{reason}\"")
|
|
||||||
writer.write(b"K" + bytes(reason, "utf-8"))
|
|
||||||
await writer.drain()
|
|
||||||
writer.close()
|
|
||||||
|
|
||||||
async def auth_client(self, writer: StreamWriter):
|
|
||||||
# TODO: Authentication
|
|
||||||
addr = writer.get_extra_info('peername')
|
|
||||||
self.log.debug(f"Client: \"IP: {addr!r}; Nick: {None}\" - started authentication!")
|
|
||||||
data = await self.tcp_rcv(writer)
|
|
||||||
self.log.info(data)
|
|
||||||
await self.kick_client(writer, "TODO")
|
|
||||||
|
|
||||||
async def tpc_handle_client(self, reader, writer: StreamWriter):
|
|
||||||
while True:
|
|
||||||
data = await reader.read(2048)
|
|
||||||
if not data:
|
|
||||||
break
|
|
||||||
message = data.decode("utf-8").strip()
|
|
||||||
addr = writer.get_extra_info('peername')
|
|
||||||
self.log.debug(f"Received {message!r} from {addr!r}")
|
|
||||||
code = message[0]
|
|
||||||
self.log.debug(f"Client code: {code!r}")
|
|
||||||
match code:
|
|
||||||
case "C":
|
|
||||||
await self.auth_client(writer)
|
|
||||||
case "D":
|
|
||||||
# TODO: HandleDownload
|
|
||||||
await self.kick_client(writer, "TODO: HandleDownload")
|
|
||||||
case "P":
|
|
||||||
# TODO: Понять что это и зачем...
|
|
||||||
writer.write(b"P")
|
|
||||||
# writer.close()
|
|
||||||
case _:
|
|
||||||
self.log.error(f"Unknown code: {code}")
|
|
||||||
await self.kick_client(writer, "Unknown code")
|
|
||||||
await self.kick_client(writer, "Error while connecting..")
|
|
||||||
|
|
||||||
async def tcp_part(self, host, port):
|
|
||||||
server = await asyncio.start_server(self.tpc_handle_client, host, port)
|
|
||||||
self.loop = server.get_loop()
|
|
||||||
print(f"TCP Serving on {server.sockets[0].getsockname()}")
|
|
||||||
async with server:
|
|
||||||
await server.serve_forever()
|
|
||||||
|
|
||||||
async def udp_part(self, server_ip, server_port):
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def main(self):
|
async def main(self):
|
||||||
server_ip = config.Server["server_ip"]
|
self.tcp = self.tcp(self, self.server_ip, self.server_port)
|
||||||
server_port = config.Server["server_port"]
|
self.udp = self.udp(self, self.server_ip, self.server_port)
|
||||||
self.log.info(i18n.ready)
|
self.log.info(i18n.ready)
|
||||||
|
# while True:
|
||||||
while True:
|
|
||||||
try:
|
try:
|
||||||
tasks = [console.start(), self.tcp_part(server_ip, server_port), self.udp_part(server_ip, server_port)]
|
tasks = [console.start(), self.tcp.start(), self.udp.start()] # self.check_alive()
|
||||||
await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
|
await asyncio.wait(tasks, return_when=asyncio.FIRST_EXCEPTION)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
await asyncio.sleep(1)
|
await asyncio.sleep(1)
|
||||||
print("Error: " + str(e))
|
print("Error: " + str(e))
|
||||||
# traceback.print_exc()
|
traceback.print_exc()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
# Developed by KuiToi Dev
|
||||||
|
# File core.core.pyi
|
||||||
|
# Written by: SantaSpeen
|
||||||
|
# Version 0.1.2
|
||||||
|
# Licence: FPA
|
||||||
|
# (c) kuitoi.su 2023
|
||||||
|
import asyncio
|
||||||
|
from asyncio import StreamWriter, AbstractEventLoop, StreamReader
|
||||||
|
from asyncio.trsock import TransportSocket
|
||||||
|
|
||||||
|
from core import utils
|
||||||
|
from .tcp_server import TCPServer
|
||||||
|
from .udp_server import UDPServer
|
||||||
|
class Client:
|
||||||
|
def __init__(self, reader: StreamReader, writer: StreamWriter):
|
||||||
|
self.cid: int = 0
|
||||||
|
self.nick: str = None
|
||||||
|
self.log = utils.get_logger("client")
|
||||||
|
self.writer: StreamWriter = writer
|
||||||
|
self.reader: StreamReader = reader
|
||||||
|
self.addr: tuple = writer.get_extra_info('peername')
|
||||||
|
self.socket: TransportSocket = writer.get_extra_info('socket')
|
||||||
|
self.loop: AbstractEventLoop = asyncio.get_event_loop()
|
||||||
|
self.alive = True
|
||||||
|
def is_disconnected(self) -> bool: ...
|
||||||
|
def kick(self, reason: str) -> None: ...
|
||||||
|
def tcp_send(self, data: bytes) -> None: ...
|
||||||
|
|
||||||
|
|
||||||
|
class Core:
|
||||||
|
def __init__(self):
|
||||||
|
self.clients_counter: int = 0
|
||||||
|
self.log = utils.get_logger("core")
|
||||||
|
self.clients = dict()
|
||||||
|
self.server_ip = config.Server["server_ip"]
|
||||||
|
self.server_port = config.Server["server_port"]
|
||||||
|
self.loop = asyncio.get_event_loop()
|
||||||
|
self.tcp = TCPServer
|
||||||
|
self.udp = UDPServer
|
||||||
|
def create_client(self, *args, **kwargs) -> Client: ...
|
||||||
|
async def check_alive(self) -> None: ...
|
||||||
|
async def main(self) -> None: ...
|
||||||
|
def start(self) -> None: ...
|
||||||
|
def stop(self) -> None: ...
|
||||||
|
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
# Developed by KuiToi Dev
|
||||||
|
# File core.tcp_server.py
|
||||||
|
# Written by: SantaSpeen
|
||||||
|
# Version 0.1.2
|
||||||
|
# Licence: FPA
|
||||||
|
# (c) kuitoi.su 2023
|
||||||
|
import asyncio
|
||||||
|
import socket
|
||||||
|
import traceback
|
||||||
|
|
||||||
|
from core import utils
|
||||||
|
|
||||||
|
|
||||||
|
class TCPServer:
|
||||||
|
def __init__(self, core, host, port):
|
||||||
|
self.log = utils.get_logger("TCPServer")
|
||||||
|
self.Core = core
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
async def send(self, data, sync):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def recv(self, client):
|
||||||
|
not_alive = client.is_disconnected()
|
||||||
|
if not not_alive:
|
||||||
|
self.log.debug(f"Client with ID {client.cid} disconnected")
|
||||||
|
return ""
|
||||||
|
data = b""
|
||||||
|
while True:
|
||||||
|
chunk = await client.loop.sock_recv(client.socket, 10)
|
||||||
|
if not chunk:
|
||||||
|
break
|
||||||
|
data += chunk
|
||||||
|
return data
|
||||||
|
|
||||||
|
async def auth_client(self, sock):
|
||||||
|
# TODO: Authentication
|
||||||
|
client = self.Core.create_client(sock)
|
||||||
|
self.log.debug(f"Client: \"IP: {client.addr!r}; ID: {client.cid}\" - started authentication!")
|
||||||
|
data = await self.recv(client)
|
||||||
|
self.log.debug(f"recv1 data: {data}")
|
||||||
|
if len(data) > 50:
|
||||||
|
client.kick("Too long data")
|
||||||
|
return
|
||||||
|
if "VC2.0" not in data.decode("utf-8"):
|
||||||
|
client.kick("Outdated Version.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
self.log.debug('tcp_send(b"A")')
|
||||||
|
client.tcp_send(b"A")
|
||||||
|
|
||||||
|
data = await self.recv(client)
|
||||||
|
self.log.debug(f"recv2 data: {data}")
|
||||||
|
|
||||||
|
client.kick("TODO Authentication")
|
||||||
|
|
||||||
|
async def handle_client(self, sock):
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = sock.recv(1)
|
||||||
|
if not data:
|
||||||
|
break
|
||||||
|
message = data.decode("utf-8").strip()
|
||||||
|
addr = sock.getsockname()
|
||||||
|
self.log.debug(f"Received {message!r} from {addr!r}")
|
||||||
|
code = message[0]
|
||||||
|
match code:
|
||||||
|
case "C":
|
||||||
|
await self.auth_client(sock)
|
||||||
|
case "D":
|
||||||
|
# TODO: HandleDownload
|
||||||
|
print("TODO: HandleDownload")
|
||||||
|
case "P":
|
||||||
|
# TODO: Понять что это и зачем...
|
||||||
|
sock.sendall(b"P")
|
||||||
|
case _:
|
||||||
|
self.log.error(f"Unknown code: {code}")
|
||||||
|
except Exception as e:
|
||||||
|
print("Error:", e)
|
||||||
|
traceback.print_exc()
|
||||||
|
break
|
||||||
|
print("Error while connecting..")
|
||||||
|
|
||||||
|
# async def start(self):
|
||||||
|
# self.log.debug("Starting TCP server.")
|
||||||
|
# server = await asyncio.start_server(self.handle_client, self.host, self.port, family=socket.AF_INET)
|
||||||
|
# self.log.debug(f"Serving on {server.sockets[0].getsockname()}")
|
||||||
|
# async with server:
|
||||||
|
# await server.serve_forever()
|
||||||
|
|
||||||
|
async def start(self):
|
||||||
|
self.log.debug("Starting TCP server.")
|
||||||
|
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
server_socket.bind((self.host, self.port))
|
||||||
|
server_socket.listen(config.Game["players"])
|
||||||
|
self.log.debug(f"Serving on {server_socket.getsockname()}")
|
||||||
|
server_socket.setblocking(False)
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
while True:
|
||||||
|
sock, _ = await loop.sock_accept(server_socket)
|
||||||
|
loop.create_task(self.handle_client(sock))
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Developed by KuiToi Dev
|
||||||
|
# File core.tcp_server.pyi
|
||||||
|
# Written by: SantaSpeen
|
||||||
|
# Version 0.1.2
|
||||||
|
# Licence: FPA
|
||||||
|
# (c) kuitoi.su 2023
|
||||||
|
from asyncio import StreamWriter, StreamReader
|
||||||
|
import socket
|
||||||
|
|
||||||
|
from core import utils, Core
|
||||||
|
from core.core import Client
|
||||||
|
|
||||||
|
|
||||||
|
class TCPServer:
|
||||||
|
def __init__(self, core: Core, host, port):
|
||||||
|
self.log = utils.get_logger("TCPServer")
|
||||||
|
self.Core = core
|
||||||
|
self.host = host
|
||||||
|
self.port = port
|
||||||
|
|
||||||
|
async def send(self, data, sync) -> None: ...
|
||||||
|
|
||||||
|
async def recv(self, writer: Client) -> bytes: ...
|
||||||
|
|
||||||
|
async def auth_client(self, sock: socket.socket) -> None: ...
|
||||||
|
|
||||||
|
async def handle_client(self, sock: socket.socket) -> None: ...
|
||||||
|
|
||||||
|
async def start(self) -> None: ...
|
||||||
|
|
||||||
Reference in New Issue
Block a user