Skip to content

Commit aa94c75

Browse files
Sync up MTRDeviceController and MTRDeviceController_Concrete and actually start using the latter.
Specific changes: * Fix includes in MTRDeviceController_Concrete, since it uses std::optional and os_unfair_lock, and includes MTRDeviceController.h via MTRDeviceController_Concrete.h already (and has to, because of the inheritance). * Copy the assertion counter machinery into MTRDeviceController_Concrete for now. This includes the storage of the variables that machinery relies on. * Remove incorrect deviceMapLock @synthesize: this is just implemented by the superclass, no need to do anything with it in the subclass. * Switch the places that are starting a non-XPC controller to create instances of MTRDeviceController_Concrete, not MTRDeviceController.
1 parent e96ddd9 commit aa94c75

File tree

3 files changed

+123
-23
lines changed

3 files changed

+123
-23
lines changed

src/darwin/Framework/CHIP/MTRDeviceController.mm

+10-1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#import "MTRDeviceControllerLocalTestStorage.h"
3232
#import "MTRDeviceControllerStartupParams.h"
3333
#import "MTRDeviceControllerStartupParams_Internal.h"
34+
#import "MTRDeviceController_Concrete.h"
3435
#import "MTRDeviceController_XPC.h"
3536
#import "MTRDevice_Concrete.h"
3637
#import "MTRDevice_Internal.h"
@@ -82,6 +83,8 @@
8283

8384
#import <os/lock.h>
8485

86+
// TODO: These strings and their consumers in this file should probably go away,
87+
// since none of them really apply to all controllers.
8588
static NSString * const kErrorCommissionerInit = @"Init failure while initializing a commissioner";
8689
static NSString * const kErrorIPKInit = @"Init failure while initializing IPK";
8790
static NSString * const kErrorSigningKeypairInit = @"Init failure while creating signing keypair bridge";
@@ -176,7 +179,7 @@ - (nullable MTRDeviceController *)initWithParameters:(MTRDeviceControllerAbstrac
176179
auto * controllerParameters = static_cast<MTRDeviceControllerParameters *>(parameters);
177180

178181
// MTRDeviceControllerFactory will auto-start in per-controller-storage mode if necessary
179-
return [MTRDeviceControllerFactory.sharedInstance initializeController:self withParameters:controllerParameters error:error];
182+
return [MTRDeviceControllerFactory.sharedInstance initializeController:[MTRDeviceController_Concrete alloc] withParameters:controllerParameters error:error];
180183
}
181184

182185
- (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
@@ -1718,6 +1721,9 @@ + (void)forceLocalhostAdvertisingOnly
17181721

17191722
@end
17201723

1724+
// TODO: This should not be in the superclass: either move to
1725+
// MTRDeviceController_Concrete.mm, or move into a separate .h/.mm pair of
1726+
// files.
17211727
@implementation MTRDevicePairingDelegateShim
17221728
- (instancetype)initWithDelegate:(id<MTRDevicePairingDelegate>)delegate
17231729
{
@@ -1770,6 +1776,9 @@ - (void)onPairingDeleted:(NSError * _Nullable)error
17701776
* Shim to allow us to treat an MTRNOCChainIssuer as an
17711777
* MTROperationalCertificateIssuer.
17721778
*/
1779+
// TODO: This should not be in the superclass: either move to
1780+
// MTRDeviceController_Concrete.mm, or move into a separate .h/.mm pair of
1781+
// files.
17731782
@interface MTROperationalCertificateChainIssuerShim : NSObject <MTROperationalCertificateIssuer>
17741783
@property (nonatomic, readonly) id<MTRNOCChainIssuer> nocChainIssuer;
17751784
@property (nonatomic, readonly) BOOL shouldSkipAttestationCertificateValidation;

src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm

+3-2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#import "MTRDeviceController.h"
2929
#import "MTRDeviceControllerStartupParams.h"
3030
#import "MTRDeviceControllerStartupParams_Internal.h"
31+
#import "MTRDeviceController_Concrete.h"
3132
#import "MTRDeviceController_Internal.h"
3233
#import "MTRDiagnosticLogsDownloader.h"
3334
#import "MTRError_Internal.h"
@@ -669,7 +670,7 @@ - (MTRDeviceController * _Nullable)createControllerOnExistingFabric:(MTRDeviceCo
669670
return existingController;
670671
}
671672

672-
return [self _startDeviceController:[MTRDeviceController alloc]
673+
return [self _startDeviceController:[MTRDeviceController_Concrete alloc]
673674
startupParams:startupParams
674675
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
675676
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
@@ -741,7 +742,7 @@ - (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControl
741742
return nil;
742743
}
743744

744-
return [self _startDeviceController:[MTRDeviceController alloc]
745+
return [self _startDeviceController:[MTRDeviceController_Concrete alloc]
745746
startupParams:startupParams
746747
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
747748
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {

src/darwin/Framework/CHIP/MTRDeviceController_Concrete.mm

+110-20
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
#import "MTRCommissionableBrowserResult_Internal.h"
2727
#import "MTRCommissioningParameters.h"
2828
#import "MTRConversion.h"
29-
#import "MTRDeviceController.h"
3029
#import "MTRDeviceControllerDelegateBridge.h"
3130
#import "MTRDeviceControllerFactory_Internal.h"
3231
#import "MTRDeviceControllerLocalTestStorage.h"
@@ -50,6 +49,7 @@
5049
#import "MTRSetupPayload.h"
5150
#import "MTRTimeUtils.h"
5251
#import "MTRUnfairLock.h"
52+
#import "MTRUtilities.h"
5353
#import "NSDataSpanConversion.h"
5454
#import "NSStringSpanConversion.h"
5555
#import <setup_payload/ManualSetupPayloadGenerator.h>
@@ -80,8 +80,11 @@
8080

8181
#include <atomic>
8282
#include <dns_sd.h>
83+
#include <optional>
8384
#include <string>
8485

86+
#import <os/lock.h>
87+
8588
typedef void (^SyncWorkQueueBlock)(void);
8689
typedef id (^SyncWorkQueueBlockWithReturnValue)(void);
8790
typedef BOOL (^SyncWorkQueueBlockWithBoolReturnValue)(void);
@@ -114,19 +117,29 @@ @interface MTRDeviceController_Concrete ()
114117
@end
115118

116119
@implementation MTRDeviceController_Concrete {
117-
// queue used to serialize all work performed by the MTRDeviceController
118120
std::atomic<chip::FabricIndex> _storedFabricIndex;
119121
std::atomic<std::optional<uint64_t>> _storedCompressedFabricID;
120122
MTRP256KeypairBridge _signingKeypairBridge;
121123
MTRP256KeypairBridge _operationalKeypairBridge;
124+
125+
// Counters to track assertion status and access controlled by the _assertionLock
126+
// TODO: Figure out whether they should live here or in the base class (or
127+
// go away completely!), which depends on how the shutdown codepaths get set up.
128+
NSUInteger _keepRunningAssertionCounter;
129+
BOOL _shutdownPending;
130+
os_unfair_lock _assertionLock;
122131
}
123132

124-
// MTRDeviceController ivar internal access
133+
// TODO: Figure out whether uniqueIdentifier storage should live in the superclass. It
134+
// probably should!
125135
@synthesize uniqueIdentifier = _uniqueIdentifier;
136+
// TODO: Figure out whether the work queue storage lives here or in the superclass
137+
// Right now we seem to have both?
126138
@synthesize chipWorkQueue = _chipWorkQueue;
127139
@synthesize controllerDataStore = _controllerDataStore;
140+
// TODO: For these remaining ivars, figure out whether they should live here or
141+
// on the superclass. Should not be both.
128142
@synthesize factory = _factory;
129-
@synthesize deviceMapLock = _deviceMapLock;
130143
@synthesize otaProviderDelegate = _otaProviderDelegate;
131144
@synthesize otaProviderDelegateQueue = _otaProviderDelegateQueue;
132145
@synthesize commissionableBrowser = _commissionableBrowser;
@@ -165,7 +178,7 @@ - (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParamete
165178
MTR_LOG_DEBUG("%s: got standard parameters, getting standard device controller from factory", __PRETTY_FUNCTION__);
166179
auto * controllerParameters = static_cast<MTRDeviceControllerParameters *>(parameters);
167180

168-
// or, if necessary, MTRDeviceControllerFactory will auto-start in per-controller-storage mode if necessary
181+
// Start us up normally. MTRDeviceControllerFactory will auto-start in per-controller-storage mode if necessary.
169182
MTRDeviceControllerFactory * factory = MTRDeviceControllerFactory.sharedInstance;
170183
id controller = [factory initializeController:self
171184
withParameters:controllerParameters
@@ -196,6 +209,12 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
196209
// Make sure our storage is all set up to work as early as possible,
197210
// before we start doing anything else with the controller.
198211
_uniqueIdentifier = uniqueIdentifier;
212+
213+
// Setup assertion variables
214+
_keepRunningAssertionCounter = 0;
215+
_shutdownPending = NO;
216+
_assertionLock = OS_UNFAIR_LOCK_INIT;
217+
199218
if (storageDelegate != nil) {
200219
if (storageDelegateQueue == nil) {
201220
MTR_LOG_ERROR("storageDelegate provided without storageDelegateQueue");
@@ -269,6 +288,7 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
269288
_otaProviderDelegateQueue = otaProviderDelegateQueue;
270289
_chipWorkQueue = queue;
271290
_factory = factory;
291+
// TODO: Shouldn't nodeIDToDeviceMap just be set up by initForSubclasses?
272292
self.nodeIDToDeviceMap = [NSMapTable strongToWeakObjectsMapTable];
273293
_serverEndpoints = [[NSMutableArray alloc] init];
274294
_commissionableBrowser = nil;
@@ -310,6 +330,10 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
310330
_concurrentSubscriptionPool = [[MTRAsyncWorkQueue alloc] initWithContext:self width:concurrentSubscriptionPoolSize];
311331

312332
_storedFabricIndex = chip::kUndefinedFabricIndex;
333+
_storedCompressedFabricID = std::nullopt;
334+
self.nodeID = nil;
335+
self.fabricID = nil;
336+
self.rootPublicKey = nil;
313337

314338
_storageBehaviorConfiguration = storageBehaviorConfiguration;
315339
}
@@ -326,8 +350,68 @@ - (BOOL)isRunning
326350
return _cppCommissioner != nullptr;
327351
}
328352

353+
- (BOOL)matchesPendingShutdownControllerWithOperationalCertificate:(nullable MTRCertificateDERBytes)operationalCertificate andRootCertificate:(nullable MTRCertificateDERBytes)rootCertificate
354+
{
355+
if (!operationalCertificate || !rootCertificate) {
356+
return FALSE;
357+
}
358+
NSNumber * nodeID = [MTRDeviceControllerParameters nodeIDFromNOC:operationalCertificate];
359+
NSNumber * fabricID = [MTRDeviceControllerParameters fabricIDFromNOC:operationalCertificate];
360+
NSData * publicKey = [MTRDeviceControllerParameters publicKeyFromCertificate:rootCertificate];
361+
362+
std::lock_guard lock(_assertionLock);
363+
364+
// If any of the local above are nil, the return will be false since MTREqualObjects handles them correctly
365+
return _keepRunningAssertionCounter > 0 && _shutdownPending && MTREqualObjects(nodeID, self.nodeID) && MTREqualObjects(fabricID, self.fabricID) && MTREqualObjects(publicKey, self.rootPublicKey);
366+
}
367+
368+
- (void)addRunAssertion
369+
{
370+
std::lock_guard lock(_assertionLock);
371+
372+
// Only take an assertion if running
373+
if ([self isRunning]) {
374+
++_keepRunningAssertionCounter;
375+
MTR_LOG("%@ Adding keep running assertion, total %lu", self, static_cast<unsigned long>(_keepRunningAssertionCounter));
376+
}
377+
}
378+
379+
- (void)removeRunAssertion;
380+
{
381+
std::lock_guard lock(_assertionLock);
382+
383+
if (_keepRunningAssertionCounter > 0) {
384+
--_keepRunningAssertionCounter;
385+
MTR_LOG("%@ Removing keep running assertion, total %lu", self, static_cast<unsigned long>(_keepRunningAssertionCounter));
386+
387+
if ([self isRunning] && _keepRunningAssertionCounter == 0 && _shutdownPending) {
388+
MTR_LOG("%@ All assertions removed and shutdown is pending, shutting down", self);
389+
[self finalShutdown];
390+
}
391+
}
392+
}
393+
394+
- (void)clearPendingShutdown
395+
{
396+
std::lock_guard lock(_assertionLock);
397+
_shutdownPending = NO;
398+
}
399+
329400
- (void)shutdown
330401
{
402+
std::lock_guard lock(_assertionLock);
403+
404+
if (_keepRunningAssertionCounter > 0) {
405+
MTR_LOG("%@ Pending shutdown since %lu assertions are present", self, static_cast<unsigned long>(_keepRunningAssertionCounter));
406+
_shutdownPending = YES;
407+
return;
408+
}
409+
[self finalShutdown];
410+
}
411+
412+
- (void)finalShutdown
413+
{
414+
os_unfair_lock_assert_owner(&_assertionLock);
331415
MTR_LOG("%@ shutdown called", self);
332416
if (_cppCommissioner == nullptr) {
333417
// Already shut down.
@@ -383,11 +467,17 @@ - (void)shutDownCppController
383467
// shutdown completes, in case it wants to write to storage as it
384468
// shuts down.
385469
_storedFabricIndex = chip::kUndefinedFabricIndex;
470+
_storedCompressedFabricID = std::nullopt;
471+
self.nodeID = nil;
472+
self.fabricID = nil;
473+
self.rootPublicKey = nil;
474+
386475
delete commissionerToShutDown;
387476
if (_operationalCredentialsDelegate != nil) {
388477
_operationalCredentialsDelegate->SetDeviceCommissioner(nullptr);
389478
}
390479
}
480+
_shutdownPending = NO;
391481
}
392482

393483
- (void)deinitFromFactory
@@ -622,6 +712,15 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams
622712
}
623713

624714
self->_storedFabricIndex = fabricIdx;
715+
self->_storedCompressedFabricID = _cppCommissioner->GetCompressedFabricId();
716+
717+
chip::Crypto::P256PublicKey rootPublicKey;
718+
if (_cppCommissioner->GetRootPublicKey(rootPublicKey) == CHIP_NO_ERROR) {
719+
self.rootPublicKey = [NSData dataWithBytes:rootPublicKey.Bytes() length:rootPublicKey.Length()];
720+
self.nodeID = @(_cppCommissioner->GetNodeId());
721+
self.fabricID = @(_cppCommissioner->GetFabricId());
722+
}
723+
625724
commissionerInitialized = YES;
626725

627726
MTR_LOG("%@ startup succeeded for nodeID 0x%016llX", self, self->_cppCommissioner->GetNodeId());
@@ -669,7 +768,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams
669768
});
670769
}];
671770
}
672-
MTR_LOG("%s: startup: %@", __PRETTY_FUNCTION__, self);
771+
MTR_LOG("%@ startup: %@", NSStringFromClass(self.class), self);
673772

674773
return YES;
675774
}
@@ -1279,6 +1378,9 @@ - (BOOL)checkForStartError:(CHIP_ERROR)errorCode logMsg:(NSString *)logMsg
12791378
return YES;
12801379
}
12811380

1381+
// TODO: Figure out whether this should live here or in superclass; we shouldn't
1382+
// have two copies of this thing. Probably after removing code from the
1383+
// superclass that should not be there.
12821384
+ (BOOL)checkForError:(CHIP_ERROR)errorCode logMsg:(NSString *)logMsg error:(NSError * __autoreleasing *)error
12831385
{
12841386
if (CHIP_NO_ERROR == errorCode) {
@@ -1472,20 +1574,8 @@ - (BOOL)syncRunOnWorkQueueWithBoolReturnValue:(SyncWorkQueueBlockWithBoolReturnV
14721574

14731575
- (nullable NSNumber *)compressedFabricID
14741576
{
1475-
assertChipStackLockedByCurrentThread();
1476-
1477-
if (!_cppCommissioner) {
1478-
return nil;
1479-
}
1480-
1481-
return @(_cppCommissioner->GetCompressedFabricId());
1482-
}
1483-
1484-
- (NSNumber * _Nullable)syncGetCompressedFabricID
1485-
{
1486-
return [self syncRunOnWorkQueueWithReturnValue:^NSNumber * {
1487-
return [self compressedFabricID];
1488-
} error:nil];
1577+
auto storedValue = _storedCompressedFabricID.load();
1578+
return storedValue.has_value() ? @(storedValue.value()) : nil;
14891579
}
14901580

14911581
- (CHIP_ERROR)isRunningOnFabric:(chip::FabricTable *)fabricTable

0 commit comments

Comments
 (0)