Skip to content

Commit d32e5fd

Browse files
Add a Matter.framework API for configuring MRP parameters.
Also fixes a typo in the ReliableMessageMgr API Matter.framework uses.
1 parent 1c20301 commit d32e5fd

13 files changed

+334
-3
lines changed

examples/darwin-framework-tool/BUILD.gn

+5
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,11 @@ executable("darwin-framework-tool") {
193193
"commands/common/MTRLogging.h",
194194
"commands/common/RemoteDataModelLogger.h",
195195
"commands/common/RemoteDataModelLogger.mm",
196+
"commands/configuration/Commands.h",
197+
"commands/configuration/ResetMRPParametersCommand.h",
198+
"commands/configuration/ResetMRPParametersCommand.mm",
199+
"commands/configuration/SetMRPParametersCommand.h",
200+
"commands/configuration/SetMRPParametersCommand.mm",
196201
"commands/delay/Commands.h",
197202
"commands/delay/SleepCommand.h",
198203
"commands/delay/SleepCommand.mm",

examples/darwin-framework-tool/commands/common/CHIPCommandBridge.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ inline constexpr char kIdentityGamma[] = "gamma";
3434

3535
class CHIPCommandBridge : public Command {
3636
public:
37-
CHIPCommandBridge(const char * commandName)
38-
: Command(commandName)
37+
CHIPCommandBridge(const char * commandName, const char * helpText = nullptr)
38+
: Command(commandName, helpText)
3939
{
4040
AddArgument("commissioner-name", &mCommissionerName);
4141
AddArgument("commissioner-nodeId", 0, UINT64_MAX, &mCommissionerNodeId,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*
17+
*/
18+
19+
#pragma once
20+
21+
#import <Matter/Matter.h>
22+
23+
#include "ResetMRPParametersCommand.h"
24+
#include "SetMRPParametersCommand.h"
25+
26+
void registerCommandsConfiguration(Commands & commands)
27+
{
28+
const char * clusterName = "Configuration";
29+
30+
commands_list clusterCommands = {
31+
make_unique<SetMRPParametersCommand>(),
32+
make_unique<ResetMRPParametersCommand>(),
33+
};
34+
35+
commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for configuring various state of the Matter framework.");
36+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#import <Matter/Matter.h>
21+
22+
#include "../common/CHIPCommandBridge.h"
23+
24+
class ResetMRPParametersCommand : public CHIPCommandBridge
25+
{
26+
public:
27+
ResetMRPParametersCommand() : CHIPCommandBridge("reset-mrp-parameters", "Reset MRP parameters to default values.") {}
28+
29+
protected:
30+
/////////// CHIPCommandBridge Interface /////////
31+
CHIP_ERROR RunCommand() override;
32+
33+
// Our command is synchronous, so no need to wait.
34+
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::kZero; }
35+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "ResetMRPParametersCommand.h"
19+
20+
CHIP_ERROR ResetMRPParametersCommand::RunCommand()
21+
{
22+
MTRSetMessageReliabilityParameters(nil, nil, nil, nil);
23+
return CHIP_NO_ERROR;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#pragma once
19+
20+
#import <Matter/Matter.h>
21+
22+
#include "../common/CHIPCommandBridge.h"
23+
24+
class SetMRPParametersCommand : public CHIPCommandBridge
25+
{
26+
public:
27+
SetMRPParametersCommand() :
28+
CHIPCommandBridge("set-mrp-parameters", "Set various MRP parameters. At least one value must be provided.")
29+
{
30+
AddArgument("idle-interval", 0, UINT32_MAX, &mIdleRetransmitMs,
31+
"Our MRP idle interval (SII) in milliseconds. Defaults to current value if not set.");
32+
AddArgument("active-interval", 0, UINT32_MAX, &mActiveRetransmitMs,
33+
"Our MRP active interval (SAI) in milliseconds. Defaults to current value if not set.");
34+
AddArgument("active-threshold", 0, UINT32_MAX, &mActiveThresholdMs,
35+
"Our MRP active threshold: how long we stay in active mode before transitioning to idle mode. Defaults to "
36+
"current value if not set.");
37+
AddArgument("additional-retransmit-delay", 0, UINT32_MAX, &mAdditionalRetransmitDelayMs,
38+
"Additional delay between retransmits that we do. Defaults to current value if not set.");
39+
}
40+
41+
protected:
42+
/////////// CHIPCommandBridge Interface /////////
43+
CHIP_ERROR RunCommand() override;
44+
45+
// Our command is synchronous, so no need to wait.
46+
chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::kZero; }
47+
48+
chip::Optional<uint32_t> mIdleRetransmitMs;
49+
chip::Optional<uint32_t> mActiveRetransmitMs;
50+
chip::Optional<uint32_t> mActiveThresholdMs;
51+
chip::Optional<uint64_t> mAdditionalRetransmitDelayMs;
52+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
* Copyright (c) 2024 Project CHIP Authors
3+
* All rights reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
#include "SetMRPParametersCommand.h"
19+
20+
using namespace chip;
21+
22+
namespace {
23+
24+
template <typename T>
25+
NSNumber * _Nullable AsNumber(const Optional<T> & value)
26+
{
27+
if (!value.HasValue()) {
28+
return nil;
29+
}
30+
31+
return @(value.Value());
32+
}
33+
34+
} // anonymous namespace
35+
36+
CHIP_ERROR SetMRPParametersCommand::RunCommand()
37+
{
38+
if (!mIdleRetransmitMs.HasValue() && !mActiveRetransmitMs.HasValue() && !mActiveThresholdMs.HasValue() && !mAdditionalRetransmitDelayMs.HasValue()) {
39+
ChipLogError(chipTool, "set-mrp-parameters needs to have at least one argument provided");
40+
return CHIP_ERROR_INVALID_ARGUMENT;
41+
}
42+
43+
MTRSetMessageReliabilityParameters(AsNumber(mIdleRetransmitMs),
44+
AsNumber(mActiveRetransmitMs),
45+
AsNumber(mActiveThresholdMs),
46+
AsNumber(mAdditionalRetransmitDelayMs));
47+
return CHIP_NO_ERROR;
48+
}

examples/darwin-framework-tool/main.mm

+2
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
#include "commands/bdx/Commands.h"
2424
#include "commands/common/Commands.h"
25+
#include "commands/configuration/Commands.h"
2526
#include "commands/delay/Commands.h"
2627
#include "commands/discover/Commands.h"
2728
#include "commands/interactive/Commands.h"
@@ -46,6 +47,7 @@ int main(int argc, const char * argv[])
4647
registerCommandsPayload(commands);
4748
registerClusterOtaSoftwareUpdateProviderInteractive(commands);
4849
registerCommandsStorage(commands);
50+
registerCommandsConfiguration(commands);
4951
registerClusters(commands);
5052
return commands.Run(argc, (char **) argv);
5153
}

src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h

+33
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,39 @@ MTR_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
179179

180180
@end
181181

182+
/**
183+
* Set the Message Reliability Protocol parameters for all controllers. This
184+
* allows control over retransmit delays to account for high-latency networks.
185+
*
186+
* Setting all arguments to nil will reset to the MRP parameters to their
187+
* default values.
188+
*
189+
* Setting some argumetns to non-nil will change just those values, keeping
190+
* current values for any arguments that are nil (not resetting them to
191+
* defaults).
192+
*
193+
* Non-nil arguments are specified as an integer number of milliseconds.
194+
*
195+
* @param idleRetransmitMs the minimal interval between retransmits for someone
196+
* sending messages to us, when they think we are
197+
* "idle" and might have our radio only turned on
198+
* intermittently.
199+
* @param activeRetransmitMs the minimal interval between retransmits for
200+
* someone sending messages to us, when they think we
201+
* are "active" and have the radio turned on
202+
* consistently.
203+
* @param activeThresholdMs the amount of time we will stay in "active" mode after
204+
* network activity.
205+
* @param additionalRetransmitDelayMs additional delay between retransmits for
206+
* messages we send, on top of whatever delay
207+
* the other side requests via its MRP
208+
* parameters.
209+
*/
210+
MTR_EXTERN MTR_NEWLY_AVAILABLE void MTRSetMessageReliabilityParameters(NSNumber * _Nullable idleRetransmitMs,
211+
NSNumber * _Nullable activeRetransmitMs,
212+
NSNumber * _Nullable activeThresholdMs,
213+
NSNumber * _Nullable additionalRetransmitDelayMs);
214+
182215
MTR_DEPRECATED(
183216
"Please use MTRDeviceControllerFactoryParams", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4))
184217
@interface MTRControllerFactoryParams : MTRDeviceControllerFactoryParams

src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm

+67
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,12 @@
4848
#import "MTRServerCluster_Internal.h"
4949
#import "MTRServerEndpoint_Internal.h"
5050
#import "MTRSessionResumptionStorageBridge.h"
51+
#import "MTRUnfairLock.h"
5152
#import "NSDataSpanConversion.h"
5253

5354
#import <os/lock.h>
5455

56+
#include <app/server/Dnssd.h>
5557
#include <app/util/af.h>
5658
#include <controller/CHIPDeviceControllerFactory.h>
5759
#include <credentials/CHIPCert.h>
@@ -62,6 +64,8 @@
6264
#include <crypto/RawKeySessionKeystore.h>
6365
#include <lib/support/Pool.h>
6466
#include <lib/support/TestPersistentStorageDelegate.h>
67+
#include <messaging/ReliableMessageMgr.h>
68+
#include <messaging/ReliableMessageProtocolConfig.h>
6569
#include <platform/PlatformManager.h>
6670

6771
#include <cstdlib>
@@ -968,6 +972,33 @@ - (MTRDeviceController * _Nullable)maybeInitializeOTAProvider:(MTRDeviceControll
968972
return controller;
969973
}
970974

975+
- (void)resetOperationalAdvertising
976+
{
977+
if (![self checkIsRunning:nil]) {
978+
// No need to reset anything; we are not running, so not
979+
// advertising.
980+
return;
981+
}
982+
983+
if (!self.advertiseOperational) {
984+
// No need to reset anything; we are not advertising the things that
985+
// would need to get reset.
986+
return;
987+
}
988+
989+
std::lock_guard lock(_controllersLock);
990+
if (_controllers.count != 0) {
991+
// We have a running controller. That means we likely need to reset
992+
// operational advertising for that controller.
993+
dispatch_async(_chipWorkQueue, ^{
994+
// StartServer() is the only API we have for resetting DNS-SD
995+
// advertising. It sure would be nice if there were a "restart"
996+
// that was a no-op if the DNS-SD server was not already
997+
// running.
998+
app::DnssdServer::Instance().StartServer();
999+
});
1000+
}
1001+
}
9711002
@end
9721003

9731004
@implementation MTRDeviceControllerFactory (InternalMethods)
@@ -1449,3 +1480,39 @@ - (void)setCdCerts:(nullable NSArray<NSData *> *)cdCerts
14491480
}
14501481

14511482
@end
1483+
1484+
void MTRSetMessageReliabilityParameters(NSNumber * _Nullable idleRetransmitMs,
1485+
NSNumber * _Nullable activeRetransmitMs,
1486+
NSNumber * _Nullable activeThresholdMs,
1487+
NSNumber * _Nullable additionalRetransmitDelayMs)
1488+
{
1489+
bool resetAdvertising = false;
1490+
if (idleRetransmitMs == nil && activeRetransmitMs == nil && activeThresholdMs == nil && additionalRetransmitDelayMs == nil) {
1491+
Messaging::ReliableMessageMgr::SetAdditionalMRPBackoffTime(NullOptional);
1492+
resetAdvertising = ReliableMessageProtocolConfig::SetLocalMRPConfig(NullOptional);
1493+
} else {
1494+
if (additionalRetransmitDelayMs != nil) {
1495+
System::Clock::Milliseconds64 additionalBackoff(additionalRetransmitDelayMs.unsignedLongLongValue);
1496+
Messaging::ReliableMessageMgr::SetAdditionalMRPBackoffTime(MakeOptional(additionalBackoff));
1497+
}
1498+
1499+
// Get current MRP parameters, then override the things we were asked to
1500+
// override.
1501+
ReliableMessageProtocolConfig mrpConfig = GetLocalMRPConfig().ValueOr(GetDefaultMRPConfig());
1502+
if (idleRetransmitMs != nil) {
1503+
mrpConfig.mIdleRetransTimeout = System::Clock::Milliseconds32(idleRetransmitMs.unsignedLongValue);
1504+
}
1505+
if (activeRetransmitMs != nil) {
1506+
mrpConfig.mActiveRetransTimeout = System::Clock::Milliseconds32(activeRetransmitMs.unsignedLongValue);
1507+
}
1508+
if (activeThresholdMs != nil) {
1509+
mrpConfig.mActiveThresholdTime = System::Clock::Milliseconds32(activeThresholdMs.unsignedLongValue);
1510+
}
1511+
1512+
resetAdvertising = ReliableMessageProtocolConfig::SetLocalMRPConfig(MakeOptional(mrpConfig));
1513+
}
1514+
1515+
if (resetAdvertising) {
1516+
[[MTRDeviceControllerFactory sharedInstance] resetOperationalAdvertising];
1517+
}
1518+
}

0 commit comments

Comments
 (0)