diff --git a/src/judas_server/backend/backend_server.py b/src/judas_server/backend/backend_server.py index 3d45dd9..d9d18ec 100644 --- a/src/judas_server/backend/backend_server.py +++ b/src/judas_server/backend/backend_server.py @@ -6,12 +6,13 @@ import selectors import socket import threading import time +import yaml from typing import Any from judas_protocol import Category, ControlAction, Message -from judas_server.backend.client import Client +from judas_server.backend.client import Client, ClientStatus class BackendServer: @@ -27,6 +28,27 @@ class BackendServer: ) self.logger.debug("Initializing Server...") + self.known_clients: dict[str, dict[str, str | float]] = {} + try: + with open("cache/known_clients.yaml", "r") as f: + self.known_clients = ( + yaml.safe_load(f).get("known_clients", {}) or {} + ) + self.logger.debug( + f"Loaded known clients: {self.known_clients}" + ) + self.logger.info( + f"Loaded {len(self.known_clients)} known clients" + ) + except FileNotFoundError: + self.logger.warning( + "known_clients.yaml not found, creating empty known clients list" + ) + with open("cache/known_clients.yaml", "w") as f: + yaml.safe_dump({"known_clients": {}}, f) + except Exception as e: + self.logger.error(f"Error loading known clients: {e}") + self.selector = selectors.DefaultSelector() self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_socket.setsockopt( @@ -41,8 +63,23 @@ class BackendServer: self.clients: dict[str, Client] = {} + if self.known_clients: + for client_id in self.known_clients: + client = Client(id=client_id, addr=None, socket=None) + client.status = ClientStatus.OFFLINE + client.last_seen = float( + self.known_clients[client_id].get("last_seen", 0.0) + ) + self.clients[client_id] = client + self.running: bool = False + def _save_known_clients(self) -> None: + """Save the list of known clients to a YAML file.""" + with open("cache/known_clients.yaml", "w") as f: + yaml.safe_dump({"known_clients": self.known_clients}, f) + self.logger.debug("Saved known clients") + def _bind_socket(self, host: str, port: int) -> None: """Bind the server socket to the specified host and port. @@ -113,6 +150,7 @@ class BackendServer: self.logger.error(f"Error unregistering client {client}: {e}") client.disconnect() + self._save_known_clients() def _send_outbound(self, sock: socket.socket, client: Client) -> None: """Queue data to be sent to a client. @@ -194,9 +232,14 @@ class BackendServer: f"Client {client.id} is already connected from {old_client.addr}, disconnecting old client..." ) self.send_close(old_client) - # self._disconnect(old_client) - # TODO: tell client not to reconnect + self.clients[client.id] = client + self.known_clients[client.id] = { + "last_seen": client.last_seen + } + self._save_known_clients() + client.status = ClientStatus.ONLINE + self.logger.info(f"[+] Registered new client {client}") else: self.logger.error(