Commit 81a40a0f authored by Dom Sekotill's avatar Dom Sekotill
Browse files

Remove "Unimplemented" message type

Closes #8
parent 9b9afed2
Loading
Loading
Loading
Loading
+5 −16
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@ from .buffer import FixedSizeBuffer
from .exceptions import InvalidMessage
from .exceptions import NeedsMore
from .exceptions import UnexpectedMessage
from .exceptions import UnimplementedWarning
from .exceptions import UnknownMessage
from .messages import *

EventMessage: TypeAlias = Union[
@@ -92,12 +92,6 @@ All messages that can be sent from a filter to an MTA
"""


class Unimplemented(messages.BytesMessage, ident=b"\x00"):
	"""
	A message that has not been implemented by this package yet
	"""


MTA_EVENT_RESPONSES = {
	messages.Negotiate.ident: {
		messages.Negotiate.ident,
@@ -181,7 +175,6 @@ MTA_EVENT_RESPONSES = {
	},
	messages.Abort.ident: None,
	messages.Close.ident: None,
	Unimplemented.ident: {messages.Continue.ident},
}

UPDATE_RESPONSES = {
@@ -213,7 +206,7 @@ class FilterProtocol:
	def read_from(
		self,
		buf: FixedSizeBuffer,
	) -> Iterable[MTAMessage|Unimplemented]:
	) -> Iterable[MTAMessage]:
		"""
		Return an iterator yielding each complete message from a buffer

@@ -227,13 +220,9 @@ class FilterProtocol:
				message, size = messages.Message.unpack(buf)
			except NeedsMore:
				return
			except NotImplementedError as exc:
				if len(exc.args) != 1:
					raise  # pragma: no-cover
				data = exc.args[0]
				warn(UnimplementedWarning(f"unimplemented message: {data!r}"))
				yield Unimplemented(data)
				del buf[:len(data)]
			except UnknownMessage as exc:
				del buf[:len(exc.contents)]
				raise
			else:
				yield self._check_recv(message)
				message.release()
+29 −8
Original line number Diff line number Diff line
# Copyright 2022 Dominik Sekotill <dom.sekotill@kodo.org.uk>
# Copyright 2022-2023 Dominik Sekotill <dom.sekotill@kodo.org.uk>
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
@@ -8,9 +8,11 @@
Exceptions raised by the package
"""

from typing import TYPE_CHECKING

__all__ = [
	"InsufficientSpace", "NeedsMore", "UnexpectedMessage", "InvalidMessage",
	"UnimplementedWarning",
	"UnknownMessage",
]


@@ -26,6 +28,31 @@ class NeedsMore(Exception):
	"""


class UnknownMessage(ValueError):
	"""
	Raised by the message unpacker to indicate that it lacks a class for the message

	The first (and only) argument to the exception is the message that could not be
	unpacked.
	"""

	if TYPE_CHECKING:
		def __init__(self, message: bytes): ...

	def __str__(self) -> str:  # pragma: no-cover
		contents = self.contents
		message = f"{contents[:50]!r} (trimmed)" if len(contents) > 50 else repr(contents)
		return f"unknown message: {message}"

	@property
	def contents(self) -> bytes:
		"""
		The byte string that could not be unpacked
		"""
		assert isinstance(self.args[0], bytes)
		return self.args[0]


class UnexpectedMessage(TypeError):
	"""
	Raised by a protocol to indicate a message that is not expected in the current state
@@ -39,9 +66,3 @@ class InvalidMessage(UnexpectedMessage):
	"""
	Raised by a protocol to indicate a message that is unknown to the state machine
	"""


class UnimplementedWarning(Warning):
	"""
	Warning of an unknown message type
	"""
+2 −1
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@ from typing_extensions import Self

from .exceptions import InsufficientSpace
from .exceptions import NeedsMore
from .exceptions import UnknownMessage

if TYPE_CHECKING:
	from .buffer import FixedSizeBuffer
@@ -262,7 +263,7 @@ class Message(metaclass=ABCMeta):
		try:
			msg_class = cls._message_classes[ident]
		except KeyError:
			raise NotImplementedError(buf[:end].tobytes())
			raise UnknownMessage(buf[:end].tobytes())
		else:
			with buf[hdr_size:end] as data:
				return msg_class.from_buffer(data), end
+0 −6
Original line number Diff line number Diff line
@@ -12,7 +12,6 @@ from kilter.protocol import messages
from kilter.protocol.buffer import SimpleBuffer
from kilter.protocol.core import FilterMessage
from kilter.protocol.core import FilterProtocol
from kilter.protocol.core import Unimplemented


async def server() -> None:
@@ -63,11 +62,6 @@ async def process_client(client: trio.SocketStream, nursery: trio.Nursery) -> No
						messages.Unknown() | messages.Header() | messages.EndOfHeaders() | \
						messages.Body() | messages.EndOfMessage():
						await send_channel.send(messages.Continue())
					case Unimplemented():
						logging.warning(f"don't know how to respond to {message!r}, send Continue")
						await send_channel.send(messages.Continue())
					case _:
						logging.warning(f"don't know how to respond to {message!r}")


async def client_sender(
+7 −7
Original line number Diff line number Diff line
@@ -9,11 +9,10 @@ from ipaddress import IPv4Address

from kilter.protocol.buffer import SimpleBuffer
from kilter.protocol.core import FilterProtocol
from kilter.protocol.core import Unimplemented
from kilter.protocol.exceptions import InvalidMessage
from kilter.protocol.exceptions import NeedsMore
from kilter.protocol.exceptions import UnexpectedMessage
from kilter.protocol.exceptions import UnimplementedWarning
from kilter.protocol.exceptions import UnknownMessage
from kilter.protocol.messages import NoDataMessage
from kilter.protocol.messages import *

@@ -60,18 +59,19 @@ class FilterProtocolTests(unittest.TestCase):

	def test_read_unimplemented(self) -> None:
		"""
		Check that unknown messages cause a warning to be issued, and are yielded raw
		Check that unknown messages cause UnknownMessage to be raised
		"""
		buf = SimpleBuffer(20)
		buf[:] = b"\x00\x00\x00\x01S"
		buf[:] = msg = b"\x00\x00\x00\x01S"

		with self.assertWarns(UnimplementedWarning):
			for msg in FilterProtocol().read_from(buf):
				self.assertIsInstance(msg, Unimplemented)
		with self.assertRaises(UnknownMessage) as exc_cm:
			for _ in FilterProtocol().read_from(buf):
				break
			else:
				self.fail("No messages read")

		assert exc_cm.exception.contents == msg

	def test_read_unexpected(self) -> None:
		"""
		Check that reading an available message before a response raises UnexpectedMessage
Loading