From a6d1a749f3f8862395eda5bf891ae37c350e3199 Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Wed, 17 Jan 2024 11:13:48 +0100 Subject: [PATCH 1/5] crossbar: enable auto fragmentation of outgoing WebSocket messages Larger labgrid remote infrastructure setups with a big number of exported resources are limited by the maximum WebSocket payload size of 1M in autobahn [1]. Future patches in labgrid will increase the maximum payload size from 1M to 10M to allow larger setups. In oder to be able to send these payloads, enable auto fragmentation of outgoing WebSocket messages into multiple WebSocket frames [2] in the crossbar configuration. Use 65536 bytes which is the value set in the ApplicationRunner [3]. [1] https://github.com/crossbario/autobahn-python/blob/359f868f9db410586cf01c071220994d8d7f165a/autobahn/asyncio/wamp.py#L223 [2] https://github.com/crossbario/crossbar/blob/master/docs/WebSocket-Options.rst [3] https://github.com/crossbario/autobahn-python/blob/359f868f9db410586cf01c071220994d8d7f165a/autobahn/asyncio/wamp.py#L224 Signed-off-by: Bastian Krause --- .crossbar/config-anonymous.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.crossbar/config-anonymous.yaml b/.crossbar/config-anonymous.yaml index b12e8d70d..8771a5aa1 100644 --- a/.crossbar/config-anonymous.yaml +++ b/.crossbar/config-anonymous.yaml @@ -28,6 +28,8 @@ workers: directory: ../web ws: type: websocket + options: + auto_fragment_size: 65536 auth: anonymous: type: static From 2c8cc737f13064f879dbd9e742502c30a96b864d Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Tue, 16 Jan 2024 23:12:03 +0100 Subject: [PATCH 2/5] remote/common: add monkey patch function for maxMessagePayloadSize in WampWebSocketClientFactory.setProtocolOptions Larger labgrid remote infrastructure setups with a big number of exported resources are limited by the maximum WebSocket payload size of 1M in autobahn [1]: When calling `get_resources()` in this situation, labgrid-client simply hangs. In crossbar's log errors occur: tried to send WebSocket message with size 1068476 exceeding payload limit of 1048576 octets There is no easy way of setting this WebSocket option, since it's set in `ApplicationRunner.run()` [2], which would need to be duplicated into labgrid's source code in its entirety. For an upstream approach, see [3] which was reverted without comment in [4]. So increase the maximum payload size from 1M to 10M by monkey patching maxMessagePayloadSize in WampWebSocketClientFactory.setProtocolOptions(). In oder to be able to actually send these payload sizes, a previous patch already enabled auto fragmentation of outgoing WebSocket messages into multiple WebSocket frames in crossbar's configuration. [1] https://github.com/crossbario/autobahn-python/blob/359f868f9db410586cf01c071220994d8d7f165a/autobahn/asyncio/wamp.py#L223 [2] https://github.com/crossbario/autobahn-python/blob/359f868f9db410586cf01c071220994d8d7f165a/autobahn/asyncio/wamp.py#L90 [3] https://github.com/crossbario/autobahn-python/pull/912 [4] https://github.com/crossbario/autobahn-python/pull/921 Signed-off-by: Bastian Krause --- doc/conf.py | 1 + labgrid/remote/common.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/doc/conf.py b/doc/conf.py index b1f470dc7..139f530f0 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -186,6 +186,7 @@ 'autobahn', 'autobahn.asyncio', 'autobahn.asyncio.wamp', + 'autobahn.asyncio.websocket', 'autobahn.wamp', 'autobahn.wamp.types', 'autobahn.twisted', diff --git a/labgrid/remote/common.py b/labgrid/remote/common.py index e3a7023c5..142455eb2 100644 --- a/labgrid/remote/common.py +++ b/labgrid/remote/common.py @@ -18,6 +18,7 @@ 'ReservationState', 'Reservation', 'enable_tcp_nodelay', + 'monkey_patch_max_msg_payload_size_ws_option', ] TAG_KEY = re.compile(r"[a-z][a-z0-9_]+") @@ -312,3 +313,36 @@ def enable_tcp_nodelay(session): """ s = session._transport.transport.get_extra_info('socket') s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, True) + + +def monkey_patch_max_msg_payload_size_ws_option(): + """ + The default maxMessagePayloadSize in autobahn is 1M. For larger setups with a big number of + exported resources, this becomes the limiting factor. + Increase maxMessagePayloadSize in WampWebSocketClientFactory.setProtocolOptions() by monkey + patching it, so autobahn.asyncio.wamp.ApplicationRunner effectively sets the increased value. + + This function must be called before ApplicationRunner is instanciated. + """ + from autobahn.asyncio.websocket import WampWebSocketClientFactory + + original_method = WampWebSocketClientFactory.setProtocolOptions + + def set_protocol_options(*args, **kwargs): + new_max_message_payload_size = 10485760 + + # maxMessagePayloadSize given as positional arg + args = list(args) + try: + args[9] = max((args[9], new_max_message_payload_size)) + except IndexError: + pass + + # maxMessagePayloadSize given as kwarg + kwarg_name = "maxMessagePayloadSize" + if kwarg_name in kwargs and kwargs[kwarg_name] is not None: + kwargs[kwarg_name] = max((kwargs[kwarg_name], new_max_message_payload_size)) + + return original_method(*args, **kwargs) + + WampWebSocketClientFactory.setProtocolOptions = set_protocol_options From 6bd531a32af02f44ff15db29f37801eeed47abf8 Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Tue, 16 Jan 2024 23:13:10 +0100 Subject: [PATCH 3/5] remote/coordinator: apply maxMessagePayloadSize monkey patch for WampWebSocketClientFactory.setProtocolOptions() Signed-off-by: Bastian Krause --- labgrid/remote/coordinator.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/labgrid/remote/coordinator.py b/labgrid/remote/coordinator.py index f8572ddce..29b45d83b 100644 --- a/labgrid/remote/coordinator.py +++ b/labgrid/remote/coordinator.py @@ -19,6 +19,9 @@ from ..util import atomic_replace, yaml +monkey_patch_max_msg_payload_size_ws_option() + + class Action(Enum): ADD = 0 DEL = 1 From 7930f12222054b13ebd330d9c05f244ddef46270 Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Tue, 16 Jan 2024 23:13:21 +0100 Subject: [PATCH 4/5] remote/exporter: apply maxMessagePayloadSize monkey patch for WampWebSocketClientFactory.setProtocolOptions() Signed-off-by: Bastian Krause --- labgrid/remote/exporter.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/labgrid/remote/exporter.py b/labgrid/remote/exporter.py index 288ea3a62..3bf2de171 100755 --- a/labgrid/remote/exporter.py +++ b/labgrid/remote/exporter.py @@ -18,10 +18,12 @@ from autobahn.asyncio.wamp import ApplicationRunner, ApplicationSession from .config import ResourceConfig -from .common import ResourceEntry, enable_tcp_nodelay +from .common import ResourceEntry, enable_tcp_nodelay, monkey_patch_max_msg_payload_size_ws_option from ..util import get_free_port, labgrid_version +monkey_patch_max_msg_payload_size_ws_option() + __version__ = labgrid_version() exports: Dict[str, Type[ResourceEntry]] = {} reexec = False From 54b15185832575f50ca1aa1b7abfb65abcf4a632 Mon Sep 17 00:00:00 2001 From: Bastian Krause Date: Tue, 16 Jan 2024 23:12:56 +0100 Subject: [PATCH 5/5] remote/client: apply maxMessagePayloadSize monkey patch for WampWebSocketClientFactory.setProtocolOptions() Signed-off-by: Bastian Krause --- labgrid/remote/client.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/labgrid/remote/client.py b/labgrid/remote/client.py index 4f97502c8..235238187 100755 --- a/labgrid/remote/client.py +++ b/labgrid/remote/client.py @@ -23,7 +23,7 @@ from autobahn.asyncio.wamp import ApplicationSession from .common import (ResourceEntry, ResourceMatch, Place, Reservation, ReservationState, TAG_KEY, - TAG_VAL, enable_tcp_nodelay) + TAG_VAL, enable_tcp_nodelay, monkey_patch_max_msg_payload_size_ws_option) from .. import Environment, Target, target_factory from ..exceptions import NoDriverFoundError, NoResourceFoundError, InvalidConfigError from ..resource.remote import RemotePlaceManager, RemotePlace @@ -34,6 +34,7 @@ from ..logging import basicConfig, StepLogger txaio.config.loop = asyncio.get_event_loop() # pylint: disable=no-member +monkey_patch_max_msg_payload_size_ws_option() class Error(Exception):