diff --git a/src/uds/transports/HTML5RDP/html5rdp.py b/src/uds/transports/HTML5RDP/html5rdp.py index 53d544cd5..d8f885a68 100644 --- a/src/uds/transports/HTML5RDP/html5rdp.py +++ b/src/uds/transports/HTML5RDP/html5rdp.py @@ -381,12 +381,16 @@ def get_link( 'user': creds_info.username or None, 'password': creds_info.password or None, 'domain': creds_info.domain or None, - 'nla': self.nla.as_bool(), - 'verify_ssl': False, 'best_experience': self.best_experience.as_bool(), - 'allow_audio': self.enable_audio.as_bool(), - 'allow_mic': self.enable_microphone.as_bool(), - 'allow_clipboard': self.allow_clipboard.as_bool(), + 'options': { + 'nla': self.nla.as_bool(), + 'verify_ssl': False, + }, + 'redirections': { + 'clipboard': self.allow_clipboard.as_bool(), + 'audio': self.enable_audio.as_bool(), + 'mic': self.enable_microphone.as_bool(), + }, 'allow_upload': self.enable_file_sharing.value in ('up', 'true'), 'allow_download': self.enable_file_sharing.value in ('down', 'true'), 'session_quality': self.session_quality.as_int(), @@ -395,11 +399,11 @@ def get_link( } # Webcam redirection (matches Rust WebcamSettings). Only sent when enabled, - # so the gateway keeps conn_data.webcam = None otherwise. WebcamSettings is + # so the gateway keeps redirections.webcam = None otherwise. WebcamSettings is # #[serde(default)] on the gateway, so omitted keys fall back to its defaults. # cam_width/cam_height are filled at runtime from the browser's getUserMedia. if self.enable_webcam.as_bool(): - extra['webcam'] = { + extra['redirections']['webcam'] = { 'enabled': True, 'codec': self.webcam_codec.value, 'quality': self.webcam_quality.as_int(), diff --git a/tests/transports/test_html5rdp.py b/tests/transports/test_html5rdp.py index e537c7a22..1d24ac727 100644 --- a/tests/transports/test_html5rdp.py +++ b/tests/transports/test_html5rdp.py @@ -99,12 +99,12 @@ def test_transport_get_link(self) -> None: link, extra = self._get_link_extra(transport, userservice, user, transport_model, ip='10.0.0.1') self.assertEqual(extra['user'], 'testuser') - self.assertEqual(extra['nla'], True) - self.assertEqual(extra['verify_ssl'], False) + self.assertEqual(extra['options']['nla'], True) + self.assertEqual(extra['options']['verify_ssl'], False) self.assertEqual(extra['best_experience'], True) - self.assertEqual(extra['allow_audio'], True) - self.assertEqual(extra['allow_mic'], False) - self.assertEqual(extra['allow_clipboard'], True) + self.assertEqual(extra['redirections']['audio'], True) + self.assertEqual(extra['redirections']['mic'], False) + self.assertEqual(extra['redirections']['clipboard'], True) self.assertEqual(extra['allow_upload'], True) self.assertEqual(extra['allow_download'], True) self.assertEqual(extra['session_quality'], 3) @@ -141,11 +141,11 @@ def test_nla_direct(self) -> None: transport.nla.value = True _, extra = self._get_link_extra(transport, userservice, user, transport_model) - self.assertTrue(extra['nla']) + self.assertTrue(extra['options']['nla']) transport.nla.value = False _, extra = self._get_link_extra(transport, userservice, user, transport_model) - self.assertFalse(extra['nla']) + self.assertFalse(extra['options']['nla']) def test_clipboard_direct(self) -> None: """Test allow_clipboard field maps directly to extra.""" @@ -154,11 +154,11 @@ def test_clipboard_direct(self) -> None: transport.allow_clipboard.value = True _, extra = self._get_link_extra(transport, userservice, user, transport_model) - self.assertTrue(extra['allow_clipboard']) + self.assertTrue(extra['redirections']['clipboard']) transport.allow_clipboard.value = False _, extra = self._get_link_extra(transport, userservice, user, transport_model) - self.assertFalse(extra['allow_clipboard']) + self.assertFalse(extra['redirections']['clipboard']) def test_best_experience_direct(self) -> None: """Test best_experience field maps directly to extra.""" @@ -190,14 +190,20 @@ def test_extra_keys_match_rust_connection_data(self) -> None: userservice, user, transport_model = _make_mocks() _, extra = self._get_link_extra(transport, userservice, user, transport_model) - # Fields in rdphtml5 ConnectionData (excluding host/port/notify_ticket set by broker) + # Top-level fields in rdphtml5 ConnectionData (excluding host/port/notify_ticket set by broker) valid_rust_fields = { - 'user_id', 'host', 'port', 'verify_ssl', 'user', 'password', 'domain', - 'best_experience', 'nla', 'allow_audio', 'allow_mic', 'allow_clipboard', + 'user_id', 'host', 'port', 'user', 'password', 'domain', + 'best_experience', 'options', 'redirections', 'allow_upload', 'allow_download', 'session_quality', 'allow_quality_switch', 'notify_ticket', 'target_fps', 'rail_app', 'rail_args', 'rail_working_dir', 'title', } + valid_options_fields = {'nla', 'verify_ssl'} + valid_redirections_fields = {'clipboard', 'audio', 'mic', 'webcam'} for key in extra: self.assertIn(key, valid_rust_fields, f"Extra key '{key}' not found in Rust ConnectionData") + for key in extra['options']: + self.assertIn(key, valid_options_fields, f"Options key '{key}' not found in Rust ConnectionData") + for key in extra['redirections']: + self.assertIn(key, valid_redirections_fields, f"Redirections key '{key}' not found in Rust ConnectionData")