Skip to content

Commit

Permalink
Account for existing controller that is asserted in factory when crea…
Browse files Browse the repository at this point in the history
…ting a new one
  • Loading branch information
anush-apple committed Aug 22, 2024
1 parent 0b3cf45 commit 7324f94
Show file tree
Hide file tree
Showing 5 changed files with 108 additions and 0 deletions.
48 changes: 48 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <Foundation/Foundation.h>
#include <MTRDeviceController.h>
#include <MTRUtilities.h>
#import <Matter/MTRDefines.h>
#import <Matter/MTRDeviceControllerParameters.h>

Expand Down Expand Up @@ -129,6 +132,10 @@ @implementation MTRDeviceController {
std::atomic<std::optional<uint64_t>> _storedCompressedFabricID;
MTRP256KeypairBridge _signingKeypairBridge;
MTRP256KeypairBridge _operationalKeypairBridge;

NSNumber * _fabricID;
NSNumber * _nodeID;
NSData * _rootPublicKey;
}

- (os_unfair_lock_t)deviceMapLock
Expand Down Expand Up @@ -304,6 +311,9 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory

_storedFabricIndex = chip::kUndefinedFabricIndex;
_storedCompressedFabricID = std::nullopt;
_nodeID = nil;
_fabricID = nil;
_rootPublicKey = nil;

_storageBehaviorConfiguration = storageBehaviorConfiguration;
}
Expand All @@ -330,6 +340,26 @@ - (NSUInteger)shutdownPrecheck
return assertionCount;
}

- (BOOL)matchesPendingShutdownWithParams:(MTRDeviceControllerParameters *)parameters
{
if (!parameters.operationalCertificate || !parameters.rootCertificate) {
return FALSE;
}
NSNumber *nodeID = [MTRDeviceControllerParameters nodeIDFromNOC:parameters.operationalCertificate];
NSNumber *fabricID = [MTRDeviceControllerParameters nodeIDFromNOC:parameters.operationalCertificate];
NSData *publicKey = [MTRDeviceControllerParameters publicKeyFromCertificate:parameters.rootCertificate];

__block BOOL matches = FALSE;
dispatch_sync(_chipWorkQueue, ^{
matches = self.keepRunningAssertionCounter > 0 &&
self.shutdownPending &&
MTREqualObjects(nodeID, self->_nodeID) &&
MTREqualObjects(fabricID, self->_fabricID) &&
MTREqualObjects(publicKey, self->_rootPublicKey);
});
return matches;
}

- (void)addRunAssertion
{
dispatch_sync(_chipWorkQueue, ^{
Expand All @@ -356,6 +386,13 @@ - (void)removeRunAssertion;
}
}

- (void)clearPendingShutdown
{
dispatch_sync(_chipWorkQueue, ^{
self.shutdownPending = FALSE;
});
}

- (void)shutdown
{
NSUInteger assertionCount = [self shutdownPrecheck];
Expand Down Expand Up @@ -424,6 +461,9 @@ - (void)shutDownCppController
// shuts down.
_storedFabricIndex = chip::kUndefinedFabricIndex;
_storedCompressedFabricID = std::nullopt;
_nodeID = nil;
_fabricID = nil;
_rootPublicKey = nil;
delete commissionerToShutDown;
if (_operationalCredentialsDelegate != nil) {
_operationalCredentialsDelegate->SetDeviceCommissioner(nullptr);
Expand Down Expand Up @@ -665,6 +705,14 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams

self->_storedFabricIndex = fabricIdx;
self->_storedCompressedFabricID = _cppCommissioner->GetCompressedFabricId();

chip::Crypto::P256PublicKey rootPublicKey;
if (_cppCommissioner->GetRootPublicKey(rootPublicKey) == CHIP_NO_ERROR) {
self->_rootPublicKey = [NSData dataWithBytes:rootPublicKey.Bytes() length:rootPublicKey.Length()];
self->_nodeID = @(_cppCommissioner->GetNodeId());
self->_fabricID = @(_cppCommissioner->GetFabricId());
}

commissionerInitialized = YES;

MTR_LOG("%@ startup succeeded for nodeID 0x%016llX", self, self->_cppCommissioner->GetNodeId());
Expand Down
20 changes: 20 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerFactory.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/

#import "MTRDeviceControllerFactory.h"
#include <MTRDeviceController_Concrete.h>
#import "MTRDeviceControllerFactory_Internal.h"

#import <Matter/MTRDefines.h>
Expand Down Expand Up @@ -1133,12 +1134,31 @@ - (void)operationalInstanceAdded:(chip::PeerId &)operationalID
}
}

- (nullable MTRDeviceController *)_findControllerMatchingParams:(MTRDeviceControllerParameters *)parameters
{
std::lock_guard lock(_controllersLock);
for (MTRDeviceController *controller in _controllers) {
if ([controller matchesPendingShutdownWithParams:parameters]) {
MTR_LOG("%@ Found existing controller %@ that is pending shutdown and matching parameters, re-using it", self, controller);
[controller clearPendingShutdown];
return controller;
}
}
return nil;
}

- (nullable MTRDeviceController *)initializeController:(MTRDeviceController *)controller
withParameters:(MTRDeviceControllerParameters *)parameters
error:(NSError * __autoreleasing *)error
{
[self _assertCurrentQueueIsNotMatterQueue];

// If there is a controller already running with matching parameters, re-use it
MTRDeviceController *existingController = [self _findControllerMatchingParams:parameters];
if (existingController) {
return existingController;
}

return [self _startDeviceController:controller
startupParams:parameters
fabricChecker:^MTRDeviceControllerStartupParamsInternal *(
Expand Down
25 changes: 25 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/

#import "MTRDeviceControllerStartupParams.h"
#include <MTRDefines.h>
#include <lib/core/CHIPError.h>
#import "MTRCertificates.h"
#import "MTRConversion.h"
#import "MTRDeviceControllerStartupParams_Internal.h"
Expand Down Expand Up @@ -306,6 +308,29 @@ - (void)setOTAProviderDelegate:(id<MTROTAProviderDelegate>)otaProviderDelegate q
_otaProviderDelegateQueue = queue;
}

+ (nullable NSNumber *)nodeIDFromNOC:(MTRCertificateDERBytes)noc
{
NSNumber *nodeID = nil;
ExtractNodeIDFromNOC(noc, &nodeID);
return nodeID;
}

+ (nullable NSNumber *)fabricIDFromNOC:(MTRCertificateDERBytes)noc
{
NSNumber *fabricID = nil;
ExtractFabricIDFromNOC(noc, &fabricID);
return fabricID;
}

+ (NSData *)publicKeyFromCertificate:(MTRCertificateDERBytes)certificate
{
Crypto::P256PublicKey pubKey;
if (ExtractPubkeyFromX509Cert(AsByteSpan(certificate), pubKey) != CHIP_NO_ERROR) {
return nil;
}
return [NSData dataWithBytes:pubKey.Bytes() length:pubKey.Length()];
}

@end

@implementation MTRDeviceControllerExternalCertificateParameters
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, strong, readonly, nullable) id<MTROTAProviderDelegate> otaProviderDelegate;
@property (nonatomic, strong, readonly, nullable) dispatch_queue_t otaProviderDelegateQueue;

+ (nullable NSNumber *)nodeIDFromNOC:(MTRCertificateDERBytes)noc;
+ (nullable NSNumber *)fabricIDFromNOC:(MTRCertificateDERBytes)noc;
+ (NSData *)publicKeyFromCertificate:(MTRCertificateDERBytes)certificate;

@end

@interface MTRDeviceControllerStartupParamsInternal : MTRDeviceControllerStartupParams
Expand Down
11 changes: 11 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceController_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#import <Matter/MTRDiagnosticLogsType.h>
#import <Matter/MTROTAProviderDelegate.h>

@class MTRDeviceControllerParameters;
@class MTRDeviceControllerStartupParamsInternal;
@class MTRDeviceControllerFactory;
@class MTRDevice;
Expand Down Expand Up @@ -314,6 +315,16 @@ NS_ASSUME_NONNULL_BEGIN
*/
- (NSUInteger)shutdownPrecheck;

/**
* This method returns TRUE if this controller matches the fabric reference and node ID as listed in the parameters.
*/
- (BOOL)matchesPendingShutdownWithParams:(MTRDeviceControllerParameters *)parameters;

/**
* Clear any pending shutdown request.
*/
- (void)clearPendingShutdown;

@end

/**
Expand Down

0 comments on commit 7324f94

Please sign in to comment.