diff --git a/lib/connector/meshcore_connector.dart b/lib/connector/meshcore_connector.dart index 7b46c113..d4d914bc 100644 --- a/lib/connector/meshcore_connector.dart +++ b/lib/connector/meshcore_connector.dart @@ -4795,8 +4795,11 @@ class MeshCoreConnector extends ChangeNotifier { 'cannot derive a transport key for region "$regionName"', ); } - await setChannelSendScope(key); try { + // Inside the try so a lost ack on the set (the firmware may already have + // applied the scope) still runs the clear below, rather than leaking the + // scope onto the next unscoped send. + await setChannelSendScope(key); await sendFrame( frame, channelSendQueueId: channelSendQueueId, diff --git a/test/connector/channel_scope_send_test.dart b/test/connector/channel_scope_send_test.dart index d1912c43..404da8a9 100644 --- a/test/connector/channel_scope_send_test.dart +++ b/test/connector/channel_scope_send_test.dart @@ -69,4 +69,19 @@ void main() { expect(sent, isEmpty); }, ); + + test('a failed set-scope still attempts a clear (no scope leak)', () async { + await connector.channelRegionScopeStoreForTest.setScope(0, 'oki'); + var calls = 0; + connector.sendFrameOverrideForTest = (_) { + calls++; + if (calls == 1) throw Exception('lost ack on set-scope'); + }; + await expectLater( + connector.sendChannelFrameScopedForTest(0, frame), + throwsA(isA()), + ); + // call 1 = set-scope (threw); call 2 = clear-scope run from the finally. + expect(calls, 2); + }); }