Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync csa branch with main #282

Merged
merged 17 commits into from
Feb 14, 2025
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
92f9f0b
[Darwin] MTRDevice _deviceMayBeReachable should mark inactive session…
jtung-apple Feb 13, 2025
ecb3c14
For thread devices throttle the response to BlockQuery by an interval…
nivi-apple Feb 13, 2025
fb68f28
Explicitly specify the notifier dependency that ICDShellCommands need…
jmartinez-silabs Feb 13, 2025
4e1c44b
Improve logging around persistent browse in Matter.framework. (#37559)
bzbarsky-apple Feb 13, 2025
f35f910
Change Thread OTA throttling algorithm in Matter.framework. (#37562)
bzbarsky-apple Feb 13, 2025
5065dd9
Log Matter operational advertisement removals in Matter.framework. (#…
bzbarsky-apple Feb 13, 2025
96bf5df
[Linux] Optimize generated glib D-Bus integration stubs (#37492)
arkq Feb 13, 2025
a3af0c2
Add camera device type. (#37570)
pidarped Feb 13, 2025
9d99ef2
Add src/platform/darwin to the Xcode project (#37571)
ksperling-apple Feb 13, 2025
94a47ad
test: Close commissioner session to properly cleanup resources (#37522)
swan-amazon Feb 14, 2025
1b3f616
Stop logging the Wi-Fi SSID in MTRCommissioningParameters. (#37576)
bzbarsky-apple Feb 14, 2025
9e94a9f
[PASESession] TLV Reading Fixes (#37383)
Alami-Amine Feb 14, 2025
91a08f3
Adjust documentation script name and images. (#37584)
andy31415 Feb 14, 2025
f2f61ac
PICS documentation: Phase 1 (#37183)
cecille Feb 14, 2025
6d1f573
[Silabs] Implement WifiSleepManager (#37569)
mkardous-silabs Feb 14, 2025
0a21983
Support clang build coverage execution for unit tests (#37563)
andy31415 Feb 14, 2025
3ef6d93
Merge branch 'main' into automation/update_main
mkardous-silabs Feb 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion examples/platform/silabs/shell/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,8 @@ source_set("icd") {

public_configs = [ ":icd-shell-config" ]

deps = [ "${shell_dependency_path}:matter-shell" ]
deps = [
"${chip_root}/src/app/icd/server:notifier",
"${shell_dependency_path}:matter-shell",
]
}
27 changes: 27 additions & 0 deletions src/app/zap-templates/zcl/data-model/chip/matter-devices.xml
Original file line number Diff line number Diff line change
Expand Up @@ -843,6 +843,33 @@ limitations under the License.
</include>
</clusters>
</deviceType>
<deviceType>
<name>MA-camera</name>
<domain>CHIP</domain>
<typeName>Camera</typeName>
<profileId editable="false">0x0103</profileId>
<deviceId editable="false">0x0142</deviceId>
<class>Simple</class>
<scope>Endpoint</scope>
<clusters>
<include cluster="Camera AV Settings User Level Management" client="false" server="false" clientLocked="true" serverLocked="false"></include>
<include cluster="Camera AV Stream Management" client="false" server="true" clientLocked="true" serverLocked="true">
<features>
<feature code="ADO" name="Audio"></feature>
<feature code="SNP" name="Snapshot"></feature>
<feature code="VDO" name="Video"></feature>
</features>
</include>
<include cluster="Occupancy Sensing" client="false" server="false" clientLocked="true" serverLocked="false"></include>
<include cluster="Push AV Stream Transport" client="false" server="false" clientLocked="true" serverLocked="false"></include>
<include cluster="TLS Certificate Management" client="false" server="true" clientLocked="true" serverLocked="true"></include>
<include cluster="TLS Client Management" client="false" server="false" clientLocked="true" serverLocked="false"></include>
<include cluster="Time Synchronization" client="false" server="true" clientLocked="true" serverLocked="true"></include>
<include cluster="WebRTC Transport Provider" client="false" server="true" clientLocked="true" serverLocked="true"></include>
<include cluster="WebRTC Transport Requestor" client="true" server="false" clientLocked="true" serverLocked="true"></include>
<include cluster="Zone Management" client="false" server="false" clientLocked="true" serverLocked="false"></include>
</clusters>
</deviceType>
<deviceType>
<name>MA-pump</name>
<domain>CHIP</domain>
Expand Down
2 changes: 1 addition & 1 deletion src/controller/python/chip/ble/LinuxImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
#include <platform/Linux/bluez/AdapterIterator.h>
#include <platform/Linux/bluez/BluezObjectManager.h>
#include <platform/Linux/bluez/ChipDeviceScanner.h>
#include <platform/Linux/dbus/bluez/DbusBluez.h>
#include <platform/Linux/dbus/bluez/DBusBluez.h>
#include <platform/PlatformManager.h>
#include <system/SystemClock.h>
#include <system/SystemLayer.h>
Expand Down
2 changes: 0 additions & 2 deletions src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1133,8 +1133,6 @@ - (void)operationalInstanceAdded:(chip::PeerId &)operationalID
for (MTRDeviceController_Concrete * controller in controllersCopy) {
auto * compressedFabricId = controller.compressedFabricID;
if (compressedFabricId != nil && compressedFabricId.unsignedLongLongValue == operationalID.GetCompressedFabricId()) {
ChipLogProgress(Controller, "Notifying controller at fabric index %u about new operational node 0x" ChipLogFormatX64,
controller.fabricIndex, ChipLogValueX64(operationalID.GetNodeId()));
[controller operationalInstanceAdded:@(operationalID.GetNodeId())];
}

Expand Down
5 changes: 5 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceController_Concrete.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,11 @@ NS_ASSUME_NONNULL_BEGIN
queue:(dispatch_queue_t)queue
completion:(void (^)(NSURL * _Nullable url, NSError * _Nullable error))completion;

/**
* Returns YES if the MTRDevice corrresponding to the given node ID is known to be a thread device, NO otherwise.
*/
- (BOOL)definitelyUsesThreadForDevice:(chip::NodeId)nodeID;

/**
* Will return chip::kUndefinedFabricIndex if we do not have a fabric index.
*/
Expand Down
36 changes: 24 additions & 12 deletions src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1429,33 +1429,42 @@ - (BOOL)checkIsRunning:(NSError * __autoreleasing *)error
return NO;
}

- (void)getSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion
- (BOOL)definitelyUsesThreadForDevice:(chip::NodeId)nodeID
{
// TODO: Figure out whether the synchronization here makes sense. What
// happens if this call happens mid-suspend or mid-resume?
if (self.suspended) {
MTR_LOG_ERROR("%@ suspended: can't get session for node %016llX-%016llx (%llu)", self, self.compressedFabricID.unsignedLongLongValue, nodeID, nodeID);
// TODO: Can we do a better error here?
completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
return;
if (!chip::IsOperationalNodeId(nodeID)) {
return NO;
}

// Get the corresponding MTRDevice object to determine if the case/subscription pool is to be used
// Get the corresponding MTRDevice object for the node id
MTRDevice * device = [self deviceForNodeID:@(nodeID)];

// TODO: Can we not just assume this isKindOfClass test is true? Would be
// really nice if we had compile-time checking for this somehow...
if (![device isKindOfClass:MTRDevice_Concrete.class]) {
MTR_LOG_ERROR("%@ somehow has %@ instead of MTRDevice_Concrete for node ID 0x%016llX (%llu)", self, device, nodeID, nodeID);
completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
return;
return NO;
}

auto * concreteDevice = static_cast<MTRDevice_Concrete *>(device);

BOOL usesThread = [concreteDevice deviceUsesThread];
return usesThread;
}

- (void)getSessionForNode:(chip::NodeId)nodeID completion:(MTRInternalDeviceConnectionCallback)completion
{
// TODO: Figure out whether the synchronization here makes sense. What
// happens if this call happens mid-suspend or mid-resume?
if (self.suspended) {
MTR_LOG_ERROR("%@ suspended: can't get session for node %016llX-%016llx (%llu)", self, self.compressedFabricID.unsignedLongLongValue, nodeID, nodeID);
// TODO: Can we do a better error here?
completion(nullptr, chip::NullOptional, [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE], nil);
return;
}

// In the case that this device is known to use thread, queue this with subscription attempts as well, to
// help with throttling Thread traffic.
if ([concreteDevice deviceUsesThread]) {
if ([self definitelyUsesThreadForDevice:nodeID]) {
MTRAsyncWorkItem * workItem = [[MTRAsyncWorkItem alloc] initWithQueue:dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)];
[workItem setReadyHandler:^(id _Nonnull context, NSInteger retryCount, MTRAsyncWorkCompletionBlock _Nonnull workItemCompletion) {
MTRInternalDeviceConnectionCallback completionWrapper = ^(chip::Messaging::ExchangeManager * _Nullable exchangeManager,
Expand Down Expand Up @@ -1666,6 +1675,9 @@ - (void)invalidateCASESessionForNode:(NSNumber *)nodeID;

- (void)operationalInstanceAdded:(NSNumber *)nodeID
{
MTR_LOG("%@ at fabric index %u notified about new operational node 0x%016llx (%llu)", self, self.fabricIndex,
nodeID.unsignedLongLongValue, nodeID.unsignedLongLongValue);

// If we don't have an existing MTRDevice for this node ID, that's fine;
// nothing to do.
MTRDevice * device = [self _deviceForNodeID:nodeID createIfNeeded:NO];
Expand Down
21 changes: 20 additions & 1 deletion src/darwin/Framework/CHIP/MTRDevice_Concrete.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4786,9 +4786,28 @@ - (void)_deviceMayBeReachable
[self _resetSubscription];
}

auto peerScopeId = commissioner->GetPeerScopedId(self->_nodeID.unsignedLongLongValue);
auto caseSessionMgr = commissioner->CASESessionMgr();
VerifyOrDie(caseSessionMgr != nullptr);
caseSessionMgr->ReleaseSession(commissioner->GetPeerScopedId(self->_nodeID.unsignedLongLongValue));
caseSessionMgr->ReleaseSession(peerScopeId);

// TODO: make this configurable - for now use 1.5 second
#define MTRDEVICE_ACTIVE_SESSION_THRESHOLD_MILLISECONDS (15000)
auto sessionMgr = commissioner->SessionMgr();
VerifyOrDie(sessionMgr != nullptr);
sessionMgr->ForEachMatchingSession(peerScopeId, [](auto * session) {
auto secureSession = session->AsSecureSession();
if (!secureSession) {
return;
}

auto threshold = System::Clock::Timeout(MTRDEVICE_ACTIVE_SESSION_THRESHOLD_MILLISECONDS);
if ((System::SystemClock().GetMonotonicTimestamp() - session->GetLastPeerActivityTime()) < threshold) {
return;
}

session->MarkAsDefunct();
});

std::lock_guard lock(self->_lock);
// Use _ensureSubscriptionForExistingDelegates so that the subscriptions
Expand Down
4 changes: 4 additions & 0 deletions src/darwin/Framework/CHIP/MTROTAImageTransferHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ class MTROTAImageTransferHandler : public chip::bdx::AsyncResponder {
MTROTAImageTransferHandlerWrapper * mOTAImageTransferHandlerWrapper;

bool mNeedToCallTransferSessionEnd = false;

bool mIsPeerNodeAKnownThreadDevice = NO;

chip::System::Clock::Milliseconds32 mBDXThrottleIntervalForThreadDevices;
};

NS_ASSUME_NONNULL_END
48 changes: 46 additions & 2 deletions src/darwin/Framework/CHIP/MTROTAImageTransferHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
#import "MTROTAUnsolicitedBDXMessageHandler.h"
#import "NSStringSpanConversion.h"

#include <chrono>
#include <platform/Darwin/UserDefaults.h>

using namespace chip;
using namespace chip::bdx;
using namespace chip::app;
Expand All @@ -31,6 +34,14 @@
// Timeout for the BDX transfer session. The OTA Spec mandates this should be >= 5 minutes.
constexpr System::Clock::Timeout kBdxTimeout = System::Clock::Seconds16(5 * 60);

// For thread devices, we may want to throttle sending Blocks in response to BlockQuery messages
// to avoid spamming the network with too many BDX messages. For now, default to the old 50ms
// polling interval we used to have.
// To override the throttle interval,
// use ` defaults write <domain> BDXThrottleIntervalForThreadDevicesInMSecs <throttleIntervalinMsecs>`
// See UserDefaults.mm for details.
constexpr auto kBdxThrottleDefaultInterval = System::Clock::Milliseconds32(50);

constexpr bdx::TransferRole kBdxRole = bdx::TransferRole::kSender;

// An ARC-managed object that lets us do weak references to a MTROTAImageTransferHandler
Expand All @@ -53,7 +64,7 @@ - (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *
}
@end

MTROTAImageTransferHandler::MTROTAImageTransferHandler(chip::System::Layer * layer)
MTROTAImageTransferHandler::MTROTAImageTransferHandler(System::Layer * layer)
{
assertChipStackLockedByCurrentThread();

Expand All @@ -78,6 +89,10 @@ - (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *
VerifyOrReturnError(mDelegate != nil, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mDelegateNotificationQueue != nil, CHIP_ERROR_INCORRECT_STATE);

mIsPeerNodeAKnownThreadDevice = [controller definitelyUsesThreadForDevice:mPeer.GetNodeId()];

mBDXThrottleIntervalForThreadDevices = Platform::GetUserDefaultBDXThrottleIntervalForThread().value_or(kBdxThrottleDefaultInterval);

BitFlags<bdx::TransferControlFlags> flags(bdx::TransferControlFlags::kReceiverDrive);

return AsyncResponder::Init(mSystemLayer, exchangeCtx, kBdxRole, flags, kMaxBdxBlockSize, kBdxTimeout);
Expand Down Expand Up @@ -233,6 +248,10 @@ - (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *
{
assertChipStackLockedByCurrentThread();

// For thread devices, we need to throttle sending the response to
// BlockQuery, so need to track when we started handling BlockQuery.
auto startBlockQueryHandlingTimestamp = System::SystemClock().GetMonotonicTimestamp();

auto blockSize = @(mTransfer.GetTransferBlockSize());
auto blockIndex = @(mTransfer.GetNextBlockNum());

Expand All @@ -241,7 +260,7 @@ - (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *

MTROTAImageTransferHandlerWrapper * __weak weakWrapper = mOTAImageTransferHandlerWrapper;

auto completionHandler = ^(NSData * _Nullable data, BOOL isEOF) {
auto respondWithBlock = ^(NSData * _Nullable data, BOOL isEOF) {
[controller
asyncDispatchToMatterQueue:^() {
assertChipStackLockedByCurrentThread();
Expand Down Expand Up @@ -283,6 +302,31 @@ - (instancetype)initWithMTROTAImageTransferHandler:(MTROTAImageTransferHandler *
return CHIP_ERROR_INCORRECT_STATE;
}

void (^completionHandler)(NSData * _Nullable data, BOOL isEOF) = nil;

// If the peer node is a Thread device, check how much time has elapsed since we started processing the BlockQuery,
// round it up to the nearest multiple of kBdxThrottleDefaultInterval, and respond with the block at that point.
if (mIsPeerNodeAKnownThreadDevice) {
completionHandler = ^(NSData * _Nullable data, BOOL isEOF) {
auto timeElapsed = System::SystemClock().GetMonotonicTimestamp() - startBlockQueryHandlingTimestamp;
// Integer division rounds down, so dividing by mBDXThrottleIntervalForThreadDevices and then multiplying
// by it again rounds down to the nearest multiple of mBDXThrottleIntervalForThreadDevices.
auto remainder = timeElapsed - (timeElapsed / mBDXThrottleIntervalForThreadDevices) * mBDXThrottleIntervalForThreadDevices;

if (remainder == System::Clock::Milliseconds32(0)) {
respondWithBlock(data, isEOF);
} else {
auto nsRemaining = std::chrono::duration_cast<std::chrono::nanoseconds>(remainder);
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, nsRemaining.count());
dispatch_after(time, delegateQueue, ^{
respondWithBlock(data, isEOF);
});
}
};
} else {
completionHandler = respondWithBlock;
}

dispatch_async(delegateQueue, ^{
if ([strongDelegate respondsToSelector:@selector(handleBDXQueryForNodeID:
controller:blockSize:blockIndex:bytesToSkip:completion:)]) {
Expand Down
13 changes: 8 additions & 5 deletions src/darwin/Framework/CHIP/MTROperationalBrowser.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import <Foundation/Foundation.h>

#import "MTRDeviceControllerFactory_Internal.h"
#import "MTRLogging_Internal.h"
#import "MTROperationalBrowser.h"

#include <cinttypes>
Expand Down Expand Up @@ -125,18 +126,20 @@
return;
}

if (!(aFlags & kDNSServiceFlagsAdd)) {
// We only care about new things appearing.
return;
}

chip::PeerId peerId;
CHIP_ERROR err = chip::Dnssd::ExtractIdFromInstanceName(aName, &peerId);
if (err != CHIP_NO_ERROR) {
ChipLogError(Controller, "Invalid instance name: '%s'\n", aName);
return;
}

if (!(aFlags & kDNSServiceFlagsAdd)) {
// We mostly only care about new things appearing, but log it when things
// disappear.
MTR_LOG("Matter operational instance advertisement removed: '%s'\n", aName);
return;
}

ChipLogProgress(Controller, "Notifying controller factory about new operational instance: '%s'", aName);
[self->mDeviceControllerFactory operationalInstanceAdded:peerId];
}
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading