| /** |
| * |
| * Copyright (c) 2020 Project CHIP Authors |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #import "CHIPDeviceController.h" |
| |
| #import "CHIPDevicePairingDelegateBridge.h" |
| #import "CHIPDevice_Internal.h" |
| #import "CHIPError_Internal.h" |
| #import "CHIPKeypair.h" |
| #import "CHIPLogging.h" |
| #import "CHIPOperationalCredentialsDelegate.h" |
| #import "CHIPP256KeypairBridge.h" |
| #import "CHIPPersistentStorageDelegateBridge.h" |
| #import "CHIPSetupPayload.h" |
| #import <setup_payload/ManualSetupPayloadGenerator.h> |
| #import <setup_payload/SetupPayload.h> |
| #import <zap-generated/CHIPClustersObjc.h> |
| |
| #import "CHIPDeviceConnectionBridge.h" |
| |
| #include <platform/CHIPDeviceBuildConfig.h> |
| |
| #include <controller/CHIPDeviceController.h> |
| #include <controller/CHIPDeviceControllerFactory.h> |
| #include <credentials/DeviceAttestationVerifier.h> |
| #include <credentials/examples/DefaultDeviceAttestationVerifier.h> |
| #include <lib/support/CHIPMem.h> |
| #include <platform/PlatformManager.h> |
| #include <setup_payload/ManualSetupPayloadGenerator.h> |
| |
| static const char * const CHIP_COMMISSIONER_DEVICE_ID_KEY = "com.zigbee.chip.commissioner.device_id"; |
| |
| static NSString * const kErrorMemoryInit = @"Init Memory failure"; |
| static NSString * const kErrorCommissionerInit = @"Init failure while initializing a commissioner"; |
| static NSString * const kErrorOperationalCredentialsInit = @"Init failure while creating operational credentials delegate"; |
| static NSString * const kErrorPairingInit = @"Init failure while creating a pairing delegate"; |
| static NSString * const kErrorPersistentStorageInit = @"Init failure while creating a persistent storage delegate"; |
| static NSString * const kErrorPairDevice = @"Failure while pairing the device"; |
| static NSString * const kErrorUnpairDevice = @"Failure while unpairing the device"; |
| static NSString * const kErrorStopPairing = @"Failure while trying to stop the pairing process"; |
| static NSString * const kErrorGetPairedDevice = @"Failure while trying to retrieve a paired device"; |
| static NSString * const kErrorNotRunning = @"Controller is not running. Call startup first."; |
| static NSString * const kInfoStackShutdown = @"Shutting down the CHIP Stack"; |
| static NSString * const kErrorSetupCodeGen = @"Generating Manual Pairing Code failed"; |
| |
| @interface CHIPDeviceController () |
| |
| // queue used to serialize all work performed by the CHIPDeviceController |
| @property (atomic, readonly) dispatch_queue_t chipWorkQueue; |
| |
| @property (readonly) chip::Controller::DeviceCommissioner * cppCommissioner; |
| @property (readonly) CHIPDevicePairingDelegateBridge * pairingDelegateBridge; |
| @property (readonly) CHIPPersistentStorageDelegateBridge * persistentStorageDelegateBridge; |
| @property (readonly) chip::FabricStorage * fabricStorage; |
| @property (readonly) CHIPOperationalCredentialsDelegate * operationalCredentialsDelegate; |
| @property (readonly) CHIPP256KeypairBridge keypairBridge; |
| @property (readonly) chip::NodeId localDeviceId; |
| @property (readonly) uint16_t listenPort; |
| @end |
| |
| // TODO Replace Shared Controller with a Controller Factory Singleton |
| @implementation CHIPDeviceController |
| |
| + (CHIPDeviceController *)sharedController |
| { |
| static CHIPDeviceController * controller = nil; |
| static dispatch_once_t onceToken; |
| dispatch_once(&onceToken, ^{ |
| // initialize the device controller |
| controller = [[CHIPDeviceController alloc] init]; |
| }); |
| return controller; |
| } |
| |
| - (instancetype)init |
| { |
| if (self = [super init]) { |
| CHIP_ERROR errorCode = CHIP_NO_ERROR; |
| |
| _chipWorkQueue = chip::DeviceLayer::PlatformMgrImpl().GetWorkQueue(); |
| |
| errorCode = chip::Platform::MemoryInit(); |
| if ([self checkForInitError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorMemoryInit]) { |
| return nil; |
| } |
| |
| _pairingDelegateBridge = new CHIPDevicePairingDelegateBridge(); |
| if ([self checkForInitError:(_pairingDelegateBridge != nullptr) logMsg:kErrorPairingInit]) { |
| return nil; |
| } |
| |
| _persistentStorageDelegateBridge = new CHIPPersistentStorageDelegateBridge(); |
| if ([self checkForInitError:(_persistentStorageDelegateBridge != nullptr) logMsg:kErrorPersistentStorageInit]) { |
| return nil; |
| } |
| |
| _operationalCredentialsDelegate = new CHIPOperationalCredentialsDelegate(); |
| if ([self checkForInitError:(_operationalCredentialsDelegate != nullptr) logMsg:kErrorOperationalCredentialsInit]) { |
| return nil; |
| } |
| } |
| return self; |
| } |
| |
| - (BOOL)isRunning |
| { |
| return self.cppCommissioner != nullptr; |
| } |
| |
| - (BOOL)shutdown |
| { |
| dispatch_async(_chipWorkQueue, ^{ |
| if (self->_cppCommissioner) { |
| CHIP_LOG_DEBUG("%@", kInfoStackShutdown); |
| self->_cppCommissioner->Shutdown(); |
| delete self->_cppCommissioner; |
| self->_cppCommissioner = nullptr; |
| } |
| }); |
| |
| // StopEventLoopTask will block until blocks are executed |
| chip::DeviceLayer::PlatformMgrImpl().StopEventLoopTask(); |
| |
| return YES; |
| } |
| |
| - (BOOL)startup:(_Nullable id<CHIPPersistentStorageDelegate>)storageDelegate |
| vendorId:(uint16_t)vendorId |
| nocSigner:(id<CHIPKeypair>)nocSigner |
| { |
| chip::DeviceLayer::PlatformMgrImpl().StartEventLoopTask(); |
| |
| __block BOOL commissionerInitialized = NO; |
| if ([self isRunning]) { |
| CHIP_LOG_DEBUG("Ignoring duplicate call to startup, Controller already started..."); |
| return YES; |
| } |
| |
| dispatch_sync(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| commissionerInitialized = YES; |
| return; |
| } |
| |
| CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| |
| _persistentStorageDelegateBridge->setFrameworkDelegate(storageDelegate); |
| // TODO Expose FabricStorage to CHIPFramework consumers. |
| _fabricStorage = new chip::SimpleFabricStorage(_persistentStorageDelegateBridge); |
| if ([self checkForStartError:(_fabricStorage != nullptr) logMsg:kErrorMemoryInit]) { |
| return; |
| } |
| // create a CHIPP256KeypairBridge here and pass it to the operationalCredentialsDelegate |
| std::unique_ptr<chip::Crypto::CHIPP256KeypairNativeBridge> nativeBridge; |
| if (nocSigner != nil) { |
| _keypairBridge.Init(nocSigner); |
| nativeBridge.reset(new chip::Crypto::CHIPP256KeypairNativeBridge(_keypairBridge)); |
| } |
| errorCode = _operationalCredentialsDelegate->init(_persistentStorageDelegateBridge, std::move(nativeBridge)); |
| if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorOperationalCredentialsInit]) { |
| return; |
| } |
| |
| // initialize NodeID if needed |
| [self _getControllerNodeId]; |
| |
| _cppCommissioner = new chip::Controller::DeviceCommissioner(); |
| if ([self checkForInitError:(_cppCommissioner != nullptr) logMsg:kErrorMemoryInit]) { |
| return; |
| } |
| |
| chip::Controller::FactoryInitParams params; |
| chip::Controller::SetupParams commissionerParams; |
| |
| if (_listenPort) { |
| params.listenPort = _listenPort; |
| } |
| |
| // Initialize device attestation verifier |
| chip::Credentials::SetDeviceAttestationVerifier(chip::Credentials::GetDefaultDACVerifier()); |
| |
| params.fabricStorage = _fabricStorage; |
| commissionerParams.storageDelegate = _persistentStorageDelegateBridge; |
| commissionerParams.deviceAddressUpdateDelegate = _pairingDelegateBridge; |
| commissionerParams.pairingDelegate = _pairingDelegateBridge; |
| |
| commissionerParams.operationalCredentialsDelegate = _operationalCredentialsDelegate; |
| |
| chip::Crypto::P256Keypair ephemeralKey; |
| errorCode = ephemeralKey.Initialize(); |
| if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { |
| return; |
| } |
| |
| NSMutableData * nocBuffer = [[NSMutableData alloc] initWithLength:chip::Controller::kMaxCHIPDERCertLength]; |
| chip::MutableByteSpan noc((uint8_t *) [nocBuffer mutableBytes], chip::Controller::kMaxCHIPDERCertLength); |
| |
| NSMutableData * rcacBuffer = [[NSMutableData alloc] initWithLength:chip::Controller::kMaxCHIPDERCertLength]; |
| chip::MutableByteSpan rcac((uint8_t *) [rcacBuffer mutableBytes], chip::Controller::kMaxCHIPDERCertLength); |
| |
| chip::MutableByteSpan icac; |
| |
| errorCode = _operationalCredentialsDelegate->GenerateNOCChainAfterValidation( |
| _localDeviceId, 0, ephemeralKey.Pubkey(), rcac, icac, noc); |
| if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { |
| return; |
| } |
| |
| commissionerParams.ephemeralKeypair = &ephemeralKey; |
| commissionerParams.controllerRCAC = rcac; |
| commissionerParams.controllerICAC = icac; |
| commissionerParams.controllerNOC = noc; |
| commissionerParams.controllerVendorId = vendorId; |
| |
| // TODO Replace Shared Controller with a Controller Factory Singleton |
| auto & factory = chip::Controller::DeviceControllerFactory::GetInstance(); |
| errorCode = factory.Init(params); |
| if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { |
| return; |
| } |
| |
| errorCode = factory.SetupCommissioner(commissionerParams, *_cppCommissioner); |
| if ([self checkForStartError:(CHIP_NO_ERROR == errorCode) logMsg:kErrorCommissionerInit]) { |
| return; |
| } |
| |
| commissionerInitialized = YES; |
| }); |
| |
| return commissionerInitialized; |
| } |
| |
| - (NSNumber *)getControllerNodeId |
| { |
| __block NSNumber * nodeID; |
| dispatch_sync(_chipWorkQueue, ^{ |
| nodeID = [self _getControllerNodeId]; |
| }); |
| return nodeID; |
| } |
| |
| - (NSNumber *)_getControllerNodeId |
| { |
| uint16_t deviceIdLength = sizeof(_localDeviceId); |
| if (CHIP_NO_ERROR |
| != _persistentStorageDelegateBridge->SyncGetKeyValue(CHIP_COMMISSIONER_DEVICE_ID_KEY, &_localDeviceId, deviceIdLength)) { |
| _localDeviceId = arc4random(); |
| _localDeviceId = _localDeviceId << 32 | arc4random(); |
| CHIP_LOG_ERROR("Assigned %llx node ID to the controller", _localDeviceId); |
| |
| _persistentStorageDelegateBridge->SyncSetKeyValue(CHIP_COMMISSIONER_DEVICE_ID_KEY, &_localDeviceId, sizeof(_localDeviceId)); |
| } else { |
| CHIP_LOG_ERROR("Found %llx node ID for the controller", _localDeviceId); |
| } |
| return [NSNumber numberWithUnsignedLongLong:_localDeviceId]; |
| } |
| |
| - (BOOL)pairDevice:(uint64_t)deviceID |
| discriminator:(uint16_t)discriminator |
| setupPINCode:(uint32_t)setupPINCode |
| error:(NSError * __autoreleasing *)error |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| __block BOOL success = NO; |
| if (![self isRunning]) { |
| success = ![self checkForError:errorCode logMsg:kErrorNotRunning error:error]; |
| return success; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| std::string manualPairingCode; |
| chip::SetupPayload payload; |
| payload.discriminator = discriminator; |
| payload.setUpPINCode = setupPINCode; |
| |
| errorCode = chip::ManualSetupPayloadGenerator(payload).payloadDecimalStringRepresentation(manualPairingCode); |
| success = ![self checkForError:errorCode logMsg:kErrorSetupCodeGen error:error]; |
| if (!success) { |
| return; |
| } |
| if ([self isRunning]) { |
| _operationalCredentialsDelegate->SetDeviceID(deviceID); |
| errorCode = self.cppCommissioner->PairDevice(deviceID, manualPairingCode.c_str()); |
| } |
| success = ![self checkForError:errorCode logMsg:kErrorPairDevice error:error]; |
| }); |
| |
| return success; |
| } |
| |
| - (BOOL)pairDevice:(uint64_t)deviceID |
| address:(NSString *)address |
| port:(uint16_t)port |
| discriminator:(uint16_t)discriminator |
| setupPINCode:(uint32_t)setupPINCode |
| error:(NSError * __autoreleasing *)error |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| __block BOOL success = NO; |
| if (![self isRunning]) { |
| success = ![self checkForError:errorCode logMsg:kErrorNotRunning error:error]; |
| return success; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| chip::Inet::IPAddress addr; |
| chip::Inet::IPAddress::FromString([address UTF8String], addr); |
| chip::Transport::PeerAddress peerAddress = chip::Transport::PeerAddress::UDP(addr, port); |
| |
| chip::RendezvousParameters params = chip::RendezvousParameters() |
| .SetSetupPINCode(setupPINCode) |
| .SetDiscriminator(discriminator) |
| .SetPeerAddress(peerAddress); |
| if ([self isRunning]) { |
| _operationalCredentialsDelegate->SetDeviceID(deviceID); |
| errorCode = self.cppCommissioner->PairDevice(deviceID, params); |
| } |
| success = ![self checkForError:errorCode logMsg:kErrorPairDevice error:error]; |
| }); |
| |
| return success; |
| } |
| |
| - (BOOL)pairDevice:(uint64_t)deviceID onboardingPayload:(NSString *)onboardingPayload error:(NSError * __autoreleasing *)error |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| __block BOOL success = NO; |
| if (![self isRunning]) { |
| success = ![self checkForError:errorCode logMsg:kErrorNotRunning error:error]; |
| return success; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| _operationalCredentialsDelegate->SetDeviceID(deviceID); |
| errorCode = self.cppCommissioner->PairDevice(deviceID, [onboardingPayload UTF8String]); |
| } |
| success = ![self checkForError:errorCode logMsg:kErrorPairDevice error:error]; |
| }); |
| return success; |
| } |
| |
| - (BOOL)unpairDevice:(uint64_t)deviceID error:(NSError * __autoreleasing *)error |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| __block BOOL success = NO; |
| if (![self isRunning]) { |
| success = ![self checkForError:errorCode logMsg:kErrorNotRunning error:error]; |
| return success; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| errorCode = self.cppCommissioner->UnpairDevice(deviceID); |
| } |
| success = ![self checkForError:errorCode logMsg:kErrorUnpairDevice error:error]; |
| }); |
| |
| return success; |
| } |
| |
| - (BOOL)stopDevicePairing:(uint64_t)deviceID error:(NSError * __autoreleasing *)error |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| __block BOOL success = NO; |
| if (![self isRunning]) { |
| success = ![self checkForError:errorCode logMsg:kErrorNotRunning error:error]; |
| return success; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| _operationalCredentialsDelegate->ResetDeviceID(); |
| errorCode = self.cppCommissioner->StopPairing(deviceID); |
| } |
| success = ![self checkForError:errorCode logMsg:kErrorStopPairing error:error]; |
| }); |
| |
| return success; |
| } |
| |
| - (BOOL)isDevicePaired:(uint64_t)deviceID error:(NSError * __autoreleasing *)error |
| { |
| __block BOOL paired = NO; |
| if (![self isRunning]) { |
| [self checkForError:CHIP_ERROR_INCORRECT_STATE logMsg:kErrorNotRunning error:error]; |
| return paired; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| paired = self.cppCommissioner->DoesDevicePairingExist(chip::PeerId().SetNodeId(deviceID)); |
| } |
| }); |
| |
| return paired; |
| } |
| |
| - (BOOL)getConnectedDevice:(uint64_t)deviceID |
| queue:(dispatch_queue_t)queue |
| completionHandler:(CHIPDeviceConnectionCallback)completionHandler |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| if (![self isRunning]) { |
| NSError * error; |
| [self checkForError:errorCode logMsg:kErrorNotRunning error:&error]; |
| dispatch_async(queue, ^{ |
| completionHandler(nil, error); |
| }); |
| return NO; |
| } |
| |
| dispatch_async(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| CHIPDeviceConnectionBridge * connectionBridge = new CHIPDeviceConnectionBridge(completionHandler, queue); |
| errorCode = connectionBridge->connect(self->_cppCommissioner, deviceID); |
| } |
| |
| NSError * error; |
| if ([self checkForError:errorCode logMsg:kErrorGetPairedDevice error:&error]) { |
| // Errors are propagated to the caller through completionHandler. |
| // No extra error handling is needed here. |
| return; |
| } |
| }); |
| |
| return YES; |
| } |
| |
| - (BOOL)openPairingWindow:(uint64_t)deviceID duration:(NSUInteger)duration error:(NSError * __autoreleasing *)error |
| { |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| if (duration > UINT16_MAX) { |
| CHIP_LOG_ERROR("Error: Duration %tu is too large. Max value %d", duration, UINT16_MAX); |
| if (error) { |
| *error = [CHIPError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; |
| } |
| return NO; |
| } |
| |
| chip::SetupPayload setupPayload; |
| err = self.cppCommissioner->OpenCommissioningWindow(deviceID, (uint16_t) duration, 0, 0, 0, setupPayload); |
| |
| if (err != CHIP_NO_ERROR) { |
| CHIP_LOG_ERROR("Error(%s): Open Pairing Window failed", chip::ErrorStr(err)); |
| if (error) { |
| *error = [CHIPError errorForCHIPErrorCode:err]; |
| } |
| return NO; |
| } |
| |
| return YES; |
| } |
| |
| - (NSString *)openPairingWindowWithPIN:(uint64_t)deviceID |
| duration:(NSUInteger)duration |
| discriminator:(NSUInteger)discriminator |
| setupPIN:(NSUInteger)setupPIN |
| error:(NSError * __autoreleasing *)error |
| { |
| CHIP_ERROR err = CHIP_NO_ERROR; |
| |
| chip::SetupPayload setupPayload; |
| |
| if (duration > UINT16_MAX) { |
| CHIP_LOG_ERROR("Error: Duration %tu is too large. Max value %d", duration, UINT16_MAX); |
| if (error) { |
| *error = [CHIPError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; |
| } |
| return nil; |
| } |
| |
| if (discriminator > 0xfff) { |
| CHIP_LOG_ERROR("Error: Discriminator %tu is too large. Max value %d", discriminator, 0xfff); |
| if (error) { |
| *error = [CHIPError errorForCHIPErrorCode:CHIP_ERROR_INVALID_INTEGER_VALUE]; |
| } |
| return nil; |
| } else { |
| setupPayload.discriminator = (uint16_t) discriminator; |
| } |
| |
| setupPIN &= ((1 << chip::kSetupPINCodeFieldLengthInBits) - 1); |
| setupPayload.setUpPINCode = (uint32_t) setupPIN; |
| |
| err = self.cppCommissioner->OpenCommissioningWindow( |
| deviceID, (uint16_t) duration, 1000, (uint16_t) discriminator, 2, setupPayload); |
| |
| if (err != CHIP_NO_ERROR) { |
| CHIP_LOG_ERROR("Error(%s): Open Pairing Window failed", chip::ErrorStr(err)); |
| if (error) { |
| *error = [CHIPError errorForCHIPErrorCode:err]; |
| } |
| return nil; |
| } |
| |
| chip::ManualSetupPayloadGenerator generator(setupPayload); |
| std::string outCode; |
| |
| if (generator.payloadDecimalStringRepresentation(outCode) == CHIP_NO_ERROR) { |
| CHIP_LOG_ERROR("Setup code is %s", outCode.c_str()); |
| } else { |
| CHIP_LOG_ERROR("Failed to get decimal setup code"); |
| return nil; |
| } |
| |
| return [NSString stringWithCString:outCode.c_str() encoding:[NSString defaultCStringEncoding]]; |
| } |
| |
| - (void)setListenPort:(uint16_t)port |
| { |
| _listenPort = port; |
| } |
| |
| - (void)updateDevice:(uint64_t)deviceID fabricId:(uint64_t)fabricId |
| { |
| __block CHIP_ERROR errorCode = CHIP_ERROR_INCORRECT_STATE; |
| if (![self isRunning]) { |
| [self checkForError:errorCode logMsg:kErrorNotRunning error:nil]; |
| return; |
| } |
| dispatch_sync(_chipWorkQueue, ^{ |
| if ([self isRunning]) { |
| errorCode = self.cppCommissioner->UpdateDevice(deviceID); |
| CHIP_LOG_ERROR("Update device address returned: %s", chip::ErrorStr(errorCode)); |
| } |
| }); |
| } |
| |
| - (void)setPairingDelegate:(id<CHIPDevicePairingDelegate>)delegate queue:(dispatch_queue_t)queue |
| { |
| dispatch_async(_chipWorkQueue, ^{ |
| self->_pairingDelegateBridge->setDelegate(delegate, queue); |
| }); |
| } |
| |
| - (BOOL)checkForInitError:(BOOL)condition logMsg:(NSString *)logMsg |
| { |
| if (condition) { |
| return NO; |
| } |
| |
| CHIP_LOG_ERROR("Error: %@", logMsg); |
| |
| if (_cppCommissioner) { |
| delete _cppCommissioner; |
| _cppCommissioner = NULL; |
| } |
| |
| if (_pairingDelegateBridge) { |
| delete _pairingDelegateBridge; |
| _pairingDelegateBridge = NULL; |
| } |
| |
| if (_persistentStorageDelegateBridge) { |
| delete _persistentStorageDelegateBridge; |
| _persistentStorageDelegateBridge = NULL; |
| } |
| |
| return YES; |
| } |
| |
| - (BOOL)checkForStartError:(BOOL)condition logMsg:(NSString *)logMsg |
| { |
| if (condition) { |
| return NO; |
| } |
| |
| CHIP_LOG_ERROR("Error: %@", logMsg); |
| |
| if (_cppCommissioner) { |
| delete _cppCommissioner; |
| _cppCommissioner = NULL; |
| } |
| |
| if (_fabricStorage) { |
| delete _fabricStorage; |
| _fabricStorage = nullptr; |
| } |
| |
| return YES; |
| } |
| |
| - (BOOL)checkForError:(CHIP_ERROR)errorCode logMsg:(NSString *)logMsg error:(NSError * __autoreleasing *)error |
| { |
| if (CHIP_NO_ERROR == errorCode) { |
| return NO; |
| } |
| |
| CHIP_LOG_ERROR("Error(%s): %s", chip::ErrorStr(errorCode), [logMsg UTF8String]); |
| if (error) { |
| *error = [CHIPError errorForCHIPErrorCode:errorCode]; |
| } |
| |
| return YES; |
| } |
| |
| - (void)dealloc |
| { |
| if (_fabricStorage) { |
| delete _fabricStorage; |
| _fabricStorage = nullptr; |
| } |
| } |
| |
| @end |