From cc873fc4ff771f957b10894de0c1ced5bd5e7a72 Mon Sep 17 00:00:00 2001 From: Christoph Stahl Date: Fri, 31 Jan 2025 22:17:29 +0100 Subject: [PATCH] check compatible versions on connect (playback client) --- syng/__init__.py | 2 ++ syng/client.py | 27 +++++++++++++++++++++++-- syng/server.py | 51 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/syng/__init__.py b/syng/__init__.py index e69de29..c78e69b 100644 --- a/syng/__init__.py +++ b/syng/__init__.py @@ -0,0 +1,2 @@ +SYNG_VERSION = (2, 1, 1) +SYNG_PROTOCOL_VERSION = (2, 1, 0) diff --git a/syng/client.py b/syng/client.py index 5c9ac1b..3a18e8e 100644 --- a/syng/client.py +++ b/syng/client.py @@ -38,7 +38,7 @@ from yaml import load, Loader from syng.player_libmpv import Player, QRPosition -from . import jsonencoder +from . import SYNG_VERSION, jsonencoder from .entry import Entry from .sources import configure_sources, Source from .log import logger @@ -156,6 +156,27 @@ class Client: self.sio.on("search", self.handle_search) self.sio.on("client-registered", self.handle_client_registered) self.sio.on("request-config", self.handle_request_config) + self.sio.on("msg", self.handle_msg) + + async def handle_msg(self, data: dict[str, Any]) -> None: + """ + Handle the "msg" message. + + This function is used to print messages from the server to the console. + + :param data: A dictionary with the `msg` entry. + :type data: dict[str, Any] + :rtype: None + """ + + msg_type = data.get("type", "info") + match msg_type: + case "info": + logger.info(data["msg"]) + case "warning": + logger.warning(data["msg"]) + case "error": + logger.error(data["msg"]) async def handle_update_config(self, data: dict[str, Any]) -> None: """ @@ -242,6 +263,7 @@ class Client: "waiting_room": self.state.waiting_room, "recent": self.state.recent, "config": self.state.config, + "version": SYNG_VERSION, } await self.sio.emit("register-client", data) @@ -389,7 +411,8 @@ class Client: if self.state.current_source is None: # A possible race condition can occur here await self.sio.emit("get-first") else: - logger.warning("Registration failed") + reason = data.get("reason", "Unknown") + logger.warning(f"Registration failed: {reason}") await self.sio.disconnect() async def handle_request_config(self, data: dict[str, Any]) -> None: diff --git a/syng/server.py b/syng/server.py index bb72b73..a6daf9c 100644 --- a/syng/server.py +++ b/syng/server.py @@ -35,6 +35,7 @@ from profanity_check import predict from .result import Result from . import jsonencoder +from . import SYNG_VERSION, SYNG_PROTOCOL_VERSION from .log import logger from .entry import Entry from .queue import Queue @@ -746,6 +747,7 @@ class Server: - `recent`, a list of initial entries for the recent list. The entries are encoded as a dictionary. - `secret`, the secret of the room + - `version`, the version of the client as a triple of integers - `key`, a registration key given out by the server administrator This will register a new playback client to a specific room. If there @@ -779,6 +781,49 @@ class Server: :rtype: None """ + if "version" not in data: + await self.sio.emit( + "client-registered", + {"success": False, "room": None, "reason": "NO_VERSION"}, + room=sid, + ) + return + + client_version = tuple(data["version"]) + + if client_version < SYNG_PROTOCOL_VERSION: + await self.sio.emit( + "msg", + {"type": "error", "msg": "Client is incompatible and outdated. Please update."}, + room=sid, + ) + await self.sio.emit( + "client-registered", + {"success": False, "room": None, "reason": "PROTOCOL_VERSION"}, + room=sid, + ) + return + + if client_version > SYNG_VERSION: + await self.sio.emit( + "msg", + {"type": "error", "msg": "Server is outdated. Please update."}, + room=sid, + ) + await self.sio.emit( + "client-registered", + {"success": False, "room": None, "reason": "PROTOCOL_VERSION"}, + room=sid, + ) + return + + if client_version < SYNG_VERSION: + await self.sio.emit( + "msg", + {"type": "warning", "msg": "Client is compatible but outdated. Please update."}, + room=sid, + ) + def gen_id(length: int = 4) -> str: client_id = "".join([random.choice(string.ascii_letters) for _ in range(length)]) if client_id in self.clients: @@ -793,7 +838,11 @@ class Server: ): await self.sio.emit( "client-registered", - {"success": False, "room": None}, + { + "success": False, + "room": None, + "reason": "PRIVATE", + }, room=sid, ) return