Skip to content

Commit 3904739

Browse files
bzbarsky-applepull[bot]
authored andcommitted
Allow creating Darwin controllers via alloc/initWithParameters. (#29025)
* Allow creating Darwin controllers via alloc/initWithParameters. * Address review comment.
1 parent f118d64 commit 3904739

13 files changed

+183
-197
lines changed

src/darwin/Framework/CHIP/MTRDeviceController.h

+21-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323

2424
@class MTRBaseDevice;
2525

26+
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
27+
@class MTRDeviceControllerParameters;
28+
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
29+
2630
NS_ASSUME_NONNULL_BEGIN
2731

2832
MTR_DEPRECATED("Please use MTRBaseDevice deviceWithNodeID", ios(16.1, 16.4), macos(13.0, 13.3), watchos(9.1, 9.4), tvos(16.1, 16.4))
@@ -37,11 +41,27 @@ typedef void (^MTRDeviceConnectionCallback)(MTRBaseDevice * _Nullable device, NS
3741
@interface MTRDeviceController : NSObject
3842

3943
/**
40-
* Controllers are created via the MTRDeviceControllerFactory object.
44+
* Controllers are created via the MTRDeviceControllerFactory object or
45+
* initialized via initWithParameters:error:.
4146
*/
4247
- (instancetype)init NS_UNAVAILABLE;
4348
+ (instancetype)new NS_UNAVAILABLE;
4449

50+
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
51+
/**
52+
* Initialize a device controller with the provided parameters. This will:
53+
*
54+
* 1) Auto-start the MTRDeviceControllerFactory in storage-per-controller mode
55+
* if it has not already been started.
56+
* 2) Return nil or a running controller.
57+
*
58+
* Once this returns non-nil, it's the caller's resposibility to call shutdown
59+
* on the controller to avoid leaking it.
60+
*/
61+
- (nullable instancetype)initWithParameters:(MTRDeviceControllerParameters *)parameters
62+
error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE;
63+
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
64+
4565
/**
4666
* If true, the controller has not been shut down yet.
4767
*/

src/darwin/Framework/CHIP/MTRDeviceController.mm

+20
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@
1616
*/
1717
#import <Matter/MTRDefines.h>
1818

19+
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
20+
#import <Matter/MTRDeviceControllerParameters.h>
21+
#else
22+
#import "MTRDeviceControllerParameters_Wrapper.h"
23+
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
24+
1925
#import "MTRDeviceController_Internal.h"
2026

2127
#import "MTRAttestationTrustStoreBridge.h"
@@ -119,6 +125,20 @@ @interface MTRDeviceController () {
119125

120126
@implementation MTRDeviceController
121127

128+
- (nullable instancetype)initWithParameters:(MTRDeviceControllerParameters *)parameters error:(NSError * __autoreleasing *)error
129+
{
130+
__auto_type * factory = [MTRDeviceControllerFactory sharedInstance];
131+
if (!factory.isRunning) {
132+
auto * params = [[MTRDeviceControllerFactoryParams alloc] initWithoutStorage];
133+
134+
if (![factory startControllerFactory:params error:error]) {
135+
return nil;
136+
}
137+
}
138+
139+
return [factory initializeController:self withParameters:parameters error:error];
140+
}
141+
122142
- (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
123143
queue:(dispatch_queue_t)queue
124144
storageDelegate:(id<MTRDeviceControllerStorageDelegate> _Nullable)storageDelegate

src/darwin/Framework/CHIP/MTRDeviceControllerFactory.h

+3-28
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
#import <Foundation/Foundation.h>
2424
#import <Matter/MTRCertificates.h>
2525
#import <Matter/MTRDefines.h>
26-
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
27-
#import <Matter/MTRDeviceControllerStartupParameters.h>
28-
#else
29-
@class MTRDeviceControllerStartupParameters;
30-
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
3126

3227
NS_ASSUME_NONNULL_BEGIN
3328

@@ -42,6 +37,9 @@ NS_ASSUME_NONNULL_BEGIN
4237

4338
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
4439
@interface MTRDeviceControllerFactoryParams : NSObject
40+
41+
- (instancetype)init NS_UNAVAILABLE;
42+
4543
/*
4644
* Storage used to store persistent information for the fabrics the
4745
* controllers ends up interacting with. This is only used if "initWithStorage"
@@ -98,15 +96,6 @@ API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
9896
*/
9997
- (instancetype)initWithStorage:(id<MTRStorage>)storage;
10098

101-
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
102-
/*
103-
* Initialize the device controller factory without storage. In this mode,
104-
* device controllers will need to have per-controller storage provided to allow
105-
* storing controller-specific information.
106-
*/
107-
- (instancetype)init MTR_NEWLY_AVAILABLE;
108-
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
109-
11099
@end
111100

112101
API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
@@ -188,20 +177,6 @@ API_AVAILABLE(ios(16.4), macos(13.3), watchos(9.4), tvos(16.4))
188177
- (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControllerStartupParams *)startupParams
189178
error:(NSError * __autoreleasing *)error;
190179

191-
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
192-
/**
193-
* Create an MTRDeviceController. Returns nil on failure.
194-
*
195-
* This method will fail if there is already a controller running for the given
196-
* node identity.
197-
*
198-
* This method will fail if the controller factory was not initialized in
199-
* storage-per-controller mode.
200-
*/
201-
- (MTRDeviceController * _Nullable)createController:(MTRDeviceControllerStartupParameters *)startupParameters
202-
error:(NSError * __autoreleasing *)error MTR_NEWLY_AVAILABLE;
203-
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
204-
205180
@end
206181

207182
MTR_DEPRECATED(

src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm

+75-85
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@
1717
#import "MTRDeviceControllerFactory.h"
1818
#import "MTRDeviceControllerFactory_Internal.h"
1919

20+
#import <Matter/MTRDefines.h>
21+
22+
#if MTR_PER_CONTROLLER_STORAGE_ENABLED
23+
#import <Matter/MTRDeviceControllerParameters.h>
24+
#else
25+
#import "MTRDeviceControllerParameters_Wrapper.h"
26+
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
27+
2028
#import "MTRCertificates.h"
2129
#import "MTRControllerAccessControl.h"
2230
#import "MTRDemuxingStorage.h"
@@ -34,9 +42,6 @@
3442
#import "MTRPersistentStorageDelegateBridge.h"
3543
#import "MTRSessionResumptionStorageBridge.h"
3644
#import "NSDataSpanConversion.h"
37-
#if !MTR_PER_CONTROLLER_STORAGE_ENABLED
38-
#import "MTRDeviceControllerStartupParameters_Wrapper.h"
39-
#endif // MTR_PER_CONTROLLER_STORAGE_ENABLED
4045

4146
#import <os/lock.h>
4247

@@ -547,8 +552,12 @@ - (void)stopControllerFactory
547552
* The fabricChecker block will run on the Matter queue, and is expected to
548553
* return nil if pre-startup fabric table checks fail, and set fabricError to
549554
* the right error value in that situation.
555+
*
556+
* The provided controller is expected to have just been allocated and to not be
557+
* initialized yet.
550558
*/
551-
- (MTRDeviceController * _Nullable)_startDeviceController:(id)startupParams
559+
- (MTRDeviceController * _Nullable)_startDeviceController:(MTRDeviceController *)controller
560+
startupParams:(id)startupParams
552561
fabricChecker:(MTRDeviceControllerStartupParamsInternal * (^)(FabricTable * fabricTable,
553562
MTRDeviceController * controller,
554563
CHIP_ERROR & fabricError))fabricChecker
@@ -566,8 +575,8 @@ - (MTRDeviceController * _Nullable)_startDeviceController:(id)startupParams
566575
NSUUID * uniqueIdentifier;
567576
id<MTROTAProviderDelegate> _Nullable otaProviderDelegate;
568577
dispatch_queue_t _Nullable otaProviderDelegateQueue;
569-
if ([startupParams isKindOfClass:[MTRDeviceControllerStartupParameters class]]) {
570-
MTRDeviceControllerStartupParameters * params = startupParams;
578+
if ([startupParams isKindOfClass:[MTRDeviceControllerParameters class]]) {
579+
MTRDeviceControllerParameters * params = startupParams;
571580
storageDelegate = params.storageDelegate;
572581
storageDelegateQueue = params.storageDelegateQueue;
573582
uniqueIdentifier = params.uniqueIdentifier;
@@ -608,20 +617,35 @@ - (MTRDeviceController * _Nullable)_startDeviceController:(id)startupParams
608617
otaProviderDelegateQueue = self.otaProviderDelegateQueue;
609618
}
610619

611-
// Create the controller, so we start the event loop, since we plan to do
612-
// our fabric table operations there.
613-
auto * controller = [self _createController:storageDelegate
614-
storageDelegateQueue:storageDelegateQueue
615-
otaProviderDelegate:otaProviderDelegate
616-
otaProviderDelegateQueue:otaProviderDelegateQueue
617-
uniqueIdentifier:uniqueIdentifier];
620+
controller = [controller initWithFactory:self
621+
queue:_chipWorkQueue
622+
storageDelegate:storageDelegate
623+
storageDelegateQueue:storageDelegateQueue
624+
otaProviderDelegate:otaProviderDelegate
625+
otaProviderDelegateQueue:otaProviderDelegateQueue
626+
uniqueIdentifier:uniqueIdentifier];
618627
if (controller == nil) {
619628
if (error != nil) {
620-
*error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_NO_MEMORY];
629+
*error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT];
621630
}
622631
return nil;
623632
}
624633

634+
if ([_controllers count] == 0) {
635+
// Bringing up the first controller. Start the event loop now. If we
636+
// fail to bring it up, its cleanup will stop the event loop again.
637+
chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask();
638+
dispatch_sync(_chipWorkQueue, ^{
639+
self->_operationalBrowser = new MTROperationalBrowser(self, self->_chipWorkQueue);
640+
});
641+
}
642+
643+
// Add the controller to _controllers now, so if we fail partway through its
644+
// startup we will still do the right cleanups.
645+
os_unfair_lock_lock(&_controllersLock);
646+
[_controllers addObject:controller];
647+
os_unfair_lock_unlock(&_controllersLock);
648+
625649
__block MTRDeviceControllerStartupParamsInternal * params = nil;
626650
__block CHIP_ERROR fabricError = CHIP_NO_ERROR;
627651

@@ -716,7 +740,8 @@ - (MTRDeviceController * _Nullable)createControllerOnExistingFabric:(MTRDeviceCo
716740
return nil;
717741
}
718742

719-
return [self _startDeviceController:startupParams
743+
return [self _startDeviceController:[MTRDeviceController alloc]
744+
startupParams:startupParams
720745
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
721746
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
722747
const FabricInfo * fabric = nullptr;
@@ -792,7 +817,8 @@ - (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControl
792817
return nil;
793818
}
794819

795-
return [self _startDeviceController:startupParams
820+
return [self _startDeviceController:[MTRDeviceController alloc]
821+
startupParams:startupParams
796822
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
797823
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
798824
const FabricInfo * fabric = nullptr;
@@ -825,73 +851,6 @@ - (MTRDeviceController * _Nullable)createControllerOnNewFabric:(MTRDeviceControl
825851
error:error];
826852
}
827853

828-
- (MTRDeviceController * _Nullable)createController:(MTRDeviceControllerStartupParameters *)startupParameters
829-
error:(NSError * __autoreleasing *)error
830-
{
831-
[self _assertCurrentQueueIsNotMatterQueue];
832-
833-
return [self _startDeviceController:startupParameters
834-
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
835-
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
836-
auto advertiseOperational = self.advertiseOperational && startupParameters.shouldAdvertiseOperational;
837-
auto * params =
838-
[[MTRDeviceControllerStartupParamsInternal alloc] initForNewController:controller
839-
fabricTable:fabricTable
840-
keystore:self->_keystore
841-
advertiseOperational:advertiseOperational
842-
params:startupParameters
843-
error:fabricError];
844-
if (params != nil) {
845-
if (params.productAttestationAuthorityCertificates == nil) {
846-
params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
847-
}
848-
if (params.certificationDeclarationCertificates == nil) {
849-
params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
850-
}
851-
}
852-
return params;
853-
}
854-
error:error];
855-
}
856-
857-
- (MTRDeviceController * _Nullable)_createController:(id<MTRDeviceControllerStorageDelegate> _Nullable)storageDelegate
858-
storageDelegateQueue:(dispatch_queue_t _Nullable)storageDelegateQueue
859-
otaProviderDelegate:(id<MTROTAProviderDelegate> _Nullable)otaProviderDelegate
860-
otaProviderDelegateQueue:(dispatch_queue_t _Nullable)otaProviderDelegateQueue
861-
uniqueIdentifier:(NSUUID *)uniqueIdentifier
862-
{
863-
[self _assertCurrentQueueIsNotMatterQueue];
864-
865-
MTRDeviceController * controller = [[MTRDeviceController alloc] initWithFactory:self
866-
queue:_chipWorkQueue
867-
storageDelegate:storageDelegate
868-
storageDelegateQueue:storageDelegateQueue
869-
otaProviderDelegate:otaProviderDelegate
870-
otaProviderDelegateQueue:otaProviderDelegateQueue
871-
uniqueIdentifier:uniqueIdentifier];
872-
if (controller == nil) {
873-
MTR_LOG_ERROR("Failed to init controller");
874-
return nil;
875-
}
876-
877-
if ([_controllers count] == 0) {
878-
// Bringing up the first controller. Start the event loop now. If we
879-
// fail to bring it up, its cleanup will stop the event loop again.
880-
chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask();
881-
dispatch_sync(_chipWorkQueue, ^{
882-
self->_operationalBrowser = new MTROperationalBrowser(self, self->_chipWorkQueue);
883-
});
884-
}
885-
886-
// Add the controller to _controllers now, so if we fail partway through its
887-
// startup we will still do the right cleanups.
888-
os_unfair_lock_lock(&_controllersLock);
889-
[_controllers addObject:controller];
890-
os_unfair_lock_unlock(&_controllersLock);
891-
892-
return controller;
893-
}
894-
895854
// Finds a fabric that matches the given params, if one exists.
896855
//
897856
// Returns NO on failure, YES on success. If YES is returned, the
@@ -1126,6 +1085,37 @@ - (void)operationalInstanceAdded:(chip::PeerId &)operationalID
11261085
}
11271086
}
11281087

1088+
- (MTRDeviceController * _Nullable)initializeController:(MTRDeviceController *)controller
1089+
withParameters:(MTRDeviceControllerParameters *)parameters
1090+
error:(NSError * __autoreleasing *)error
1091+
{
1092+
[self _assertCurrentQueueIsNotMatterQueue];
1093+
1094+
return [self _startDeviceController:controller
1095+
startupParams:parameters
1096+
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
1097+
FabricTable * fabricTable, MTRDeviceController * controller, CHIP_ERROR & fabricError) {
1098+
auto advertiseOperational = self.advertiseOperational && parameters.shouldAdvertiseOperational;
1099+
auto * params =
1100+
[[MTRDeviceControllerStartupParamsInternal alloc] initForNewController:controller
1101+
fabricTable:fabricTable
1102+
keystore:self->_keystore
1103+
advertiseOperational:advertiseOperational
1104+
params:parameters
1105+
error:fabricError];
1106+
if (params != nil) {
1107+
if (params.productAttestationAuthorityCertificates == nil) {
1108+
params.productAttestationAuthorityCertificates = self.productAttestationAuthorityCertificates;
1109+
}
1110+
if (params.certificationDeclarationCertificates == nil) {
1111+
params.certificationDeclarationCertificates = self.certificationDeclarationCertificates;
1112+
}
1113+
}
1114+
return params;
1115+
}
1116+
error:error];
1117+
}
1118+
11291119
- (PersistentStorageDelegate *)storageDelegate
11301120
{
11311121
return _persistentStorageDelegate;
@@ -1176,7 +1166,7 @@ - (instancetype)initWithStorage:(id<MTRStorage>)storage
11761166
return self;
11771167
}
11781168

1179-
- (instancetype)init
1169+
- (instancetype)initWithoutStorage
11801170
{
11811171
if (!(self = [super init])) {
11821172
return nil;
@@ -1191,7 +1181,7 @@ - (instancetype)init
11911181
_productAttestationAuthorityCertificates = nil;
11921182
_certificationDeclarationCertificates = nil;
11931183
_port = nil;
1194-
_shouldStartServer = NO;
1184+
_shouldStartServer = YES;
11951185

11961186
return self;
11971187
}

0 commit comments

Comments
 (0)