Skip to content

Commit

Permalink
Raise InvalidServerVersion when Server is too old too
Browse files Browse the repository at this point in the history
Currently InvalidServerVersion was only raised when the client was
too old (Server wasn't able to handle such an old client anymore),
e.g. after a backwards incompatible change Server side.

However, if the client was newer than the Server schema version, no
error was raised. This essentially never triggered the add-on update
logic in Core.

This change makes sure that we raise InvalidServerVersion when the
Server is too old for the client too. We also add properties to the
Exception so a client can figure out which situation we are dealing
with (too old/too new) and act accordingly.
  • Loading branch information
agners committed Jun 25, 2024
1 parent 0764463 commit 8c22aa5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 23 deletions.
43 changes: 22 additions & 21 deletions matter_server/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from chip.clusters import Objects as Clusters
from chip.clusters.Types import NullValue

from matter_server.common.const import SCHEMA_VERSION
from matter_server.common.errors import ERROR_MAP, NodeNotExists

from ..common.helpers.util import (
Expand Down Expand Up @@ -535,14 +536,13 @@ async def update_node(
APICommand.UPDATE_NODE, node_id=node_id, software_version=software_version
)

async def send_command(
def _prepare_message(
self,
command: str,
require_schema: int | None = None,
**kwargs: Any,
) -> Any:
"""Send a command and get a response."""
if not self.connection.connected or not self._loop:
) -> CommandMessage:
if not self.connection.connected:
raise InvalidState("Not connected")

if (
Expand All @@ -552,14 +552,29 @@ async def send_command(
):
raise InvalidServerVersion(
"Command not available due to incompatible server version. Update the Matter "
f"Server to a version that supports at least api schema {require_schema}."
f"Server to a version that supports at least api schema {require_schema}.",
SCHEMA_VERSION,
self.server_info.schema_version,
self.server_info.min_supported_schema_version,
)

message = CommandMessage(
return CommandMessage(
message_id=uuid.uuid4().hex,
command=command,
args=kwargs,
)

async def send_command(
self,
command: str,
require_schema: int | None = None,
**kwargs: Any,
) -> Any:
"""Send a command and get a response."""
if not self._loop:
raise InvalidState("Not connected")

message = self._prepare_message(command, require_schema, **kwargs)
future: asyncio.Future[Any] = self._loop.create_future()
self._result_futures[message.message_id] = future
await self.connection.send_message(message)
Expand All @@ -575,22 +590,8 @@ async def send_command_no_wait(
**kwargs: Any,
) -> None:
"""Send a command without waiting for the response."""
if not self.server_info:
raise InvalidState("Not connected")

if (
require_schema is not None
and require_schema > self.server_info.schema_version
):
raise InvalidServerVersion(
"Command not available due to incompatible server version. Update the Matter "
f"Server to a version that supports at least api schema {require_schema}."
)
message = CommandMessage(
message_id=uuid.uuid4().hex,
command=command,
args=kwargs,
)
message = self._prepare_message(command, require_schema, **kwargs)
await self.connection.send_message(message)

async def get_diagnostics(self) -> ServerDiagnostics:
Expand Down
7 changes: 5 additions & 2 deletions matter_server/client/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,16 @@ async def connect(self) -> None:
self.server_info = info

# basic check for server schema version compatibility
if info.min_supported_schema_version > SCHEMA_VERSION:
if info.min_supported_schema_version > SCHEMA_VERSION > info.schema_version:
# our schema version is too low and can't be handled by the server anymore.
await self._ws_client.close()
raise InvalidServerVersion(
f"Matter schema version is incompatible: {SCHEMA_VERSION}, "
f"the server requires at least {info.min_supported_schema_version} "
" - update the Matter client to a more recent version or downgrade the server."
" - update the Matter client to a more recent version or downgrade the server.",
SCHEMA_VERSION,
info.schema_version,
info.min_supported_schema_version,
)

LOGGER.info(
Expand Down
13 changes: 13 additions & 0 deletions matter_server/client/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,16 @@ class InvalidMessage(MatterClientException):

class InvalidServerVersion(MatterClientException):
"""Exception raised when connected to server with incompatible version."""

def __init__(
self,
msg: str,
client_schema_version: int,
server_schema_version: int,
min_supported_schema_version: int,
):
"""Initialize an invalid server version error."""
super().__init__(msg)
self.client_schema_version = client_schema_version
self.server_schema_version = server_schema_version
self.min_supported_schema_version = min_supported_schema_version

0 comments on commit 8c22aa5

Please sign in to comment.