Skip to content

Commit

Permalink
[darwin-framework-tool][XPC] Add a XPC server registry.
Browse files Browse the repository at this point in the history
  • Loading branch information
vivien-apple committed Dec 4, 2024
1 parent 38ad07d commit 2329976
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 7 deletions.
1 change: 1 addition & 0 deletions examples/darwin-framework-tool/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ executable("darwin-framework-tool") {
"commands/common/PreferencesStorage.mm",
"commands/common/RemoteDataModelLogger.h",
"commands/common/RemoteDataModelLogger.mm",
"commands/common/xpc/XPCServerRegistry.mm",
"commands/configuration/Commands.h",
"commands/configuration/ResetMRPParametersCommand.h",
"commands/configuration/ResetMRPParametersCommand.mm",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ class CHIPCommandBridge : public Command {
AddArgument("commissioner-vendor-id", 0, UINT16_MAX, &mCommissionerVendorId,
"The vendor id to use for darwin-framework-tool. If not provided, chip::VendorId::TestVendor1 (65521, 0xFFF1) will be "
"used.");
AddArgument("use-xpc", 0, 1, &mUseXPC, "This option uses the XPC implementation.");
AddArgument("use-xpc-service-name", &mUseXPCServiceName, "The name of the XPC service to connect to.");
AddArgument("use-xpc-controller-id", &mUseXPCControllerId, "The id of the XPC controller to connect with.");
}

/////////// Command Interface /////////
Expand Down Expand Up @@ -168,4 +171,7 @@ class CHIPCommandBridge : public Command {
chip::Optional<char *> mPaaTrustStorePath;
chip::Optional<chip::VendorId> mCommissionerVendorId;
std::string mCurrentIdentity;
chip::Optional<bool> mUseXPC;
chip::Optional<char *> mUseXPCServiceName;
chip::Optional<char *> mUseXPCControllerId;
};
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#import "DeviceDelegate.h"
#include "MTRError_Utils.h"

#include "xpc/XPCServerRegistry.h"

#include <map>
#include <string>

Expand All @@ -45,6 +47,17 @@
bool CHIPCommandBridge::sUseSharedStorage = true;
constexpr char kTrustStorePathVariable[] = "PAA_TRUST_STORE_PATH";

namespace {
NSString * ToNSString(const chip::Optional<char *> & string)
{
if (!string.HasValue()) {
return nil;
}

return @(string.Value());
}
}

CHIP_ERROR CHIPCommandBridge::Run()
{
// In interactive mode, we want to avoid memory accumulating in the main autorelease pool,
Expand Down Expand Up @@ -143,6 +156,8 @@
productAttestationAuthorityCertificates = nil;
}

[[XPCServerRegistry sharedInstance] start];

sUseSharedStorage = mCommissionerSharedStorage.ValueOr(false);
if (sUseSharedStorage) {
return SetUpStackWithSharedStorage(productAttestationAuthorityCertificates);
Expand Down Expand Up @@ -202,7 +217,16 @@

params.productAttestationAuthorityCertificates = productAttestationAuthorityCertificates;

__auto_type * controller = [[MTRDeviceController alloc] initWithParameters:params error:&error];
MTRDeviceController * controller = nil;
if (mUseXPC.ValueOr(false) || mUseXPCServiceName.HasValue()) {
__auto_type * identifier = uuidString;
if (commissionerName.compare(identities[i]) == 0 && mUseXPCControllerId.HasValue()) {
identifier = ToNSString(mUseXPCControllerId);
}
controller = [[XPCServerRegistry sharedInstance] createController:identifier serviceName:ToNSString(mUseXPCServiceName) params:params error:&error];
} else {
controller = [[MTRDeviceController alloc] initWithParameters:params error:&error];
}
VerifyOrReturnError(nil != controller, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Controller startup failure: %@", error));
mControllers[identities[i]] = controller;
}
Expand Down Expand Up @@ -237,12 +261,21 @@
params.nodeId = @(mCommissionerNodeId.Value());
}

// We're not sure whether we're creating a new fabric or using an existing one, so just try both.
auto controller = [factory createControllerOnExistingFabric:params error:&error];
if (controller == nil) {
// Maybe we didn't have this fabric yet.
params.vendorID = @(mCommissionerVendorId.ValueOr(chip::VendorId::TestVendor1));
controller = [factory createControllerOnNewFabric:params error:&error];
MTRDeviceController * controller = nil;
if (mUseXPC.ValueOr(false) || mUseXPCServiceName.HasValue()) {
__auto_type * identifier = @(identities[i]);
if (commissionerName.compare(identities[i]) == 0 && mUseXPCControllerId.HasValue()) {
identifier = ToNSString(mUseXPCControllerId);
}
controller = [[XPCServerRegistry sharedInstance] createController:identifier serviceName:ToNSString(mUseXPCServiceName) params:params error:&error];
} else {
// We're not sure whether we're creating a new fabric or using an existing one, so just try both.
controller = [factory createControllerOnExistingFabric:params error:&error];
if (controller == nil) {
// Maybe we didn't have this fabric yet.
params.vendorID = @(mCommissionerVendorId.ValueOr(chip::VendorId::TestVendor1));
controller = [factory createControllerOnNewFabric:params error:&error];
}
}
VerifyOrReturnError(nil != controller, MTRErrorToCHIPErrorCode(error), ChipLogError(chipTool, "Controller startup failure: %@", error));
mControllers[identities[i]] = controller;
Expand All @@ -256,6 +289,8 @@
if (IsInteractive()) {
return;
}

[[XPCServerRegistry sharedInstance] stop];
ShutdownCommissioner();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* 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 <Matter/Matter.h>

NS_ASSUME_NONNULL_BEGIN

@protocol XPCServerBaseProtocol <NSObject>
- (void)start;
- (void)stop;
@end

@protocol XPCServerExternalCertificateParametersProtocol <XPCServerBaseProtocol, NSXPCListenerDelegate>
- (MTRDeviceController *)createController:(MTRDeviceControllerExternalCertificateParameters *)params error:(NSError * __autoreleasing *)error;
@end

@protocol XPCServerStartupParametersProtocol <XPCServerBaseProtocol, NSXPCListenerDelegate>
- (MTRDeviceController *)createController:(MTRDeviceControllerStartupParams *)params error:(NSError * __autoreleasing *)error;
@end

@protocol XPCServerExternalCertificateParametersWithServiceNameProtocol <XPCServerBaseProtocol>
- (MTRDeviceController *)createController:(NSString *)controllerID serviceName:(NSString *)serviceName error:(NSError * __autoreleasing *)error;
@end

@protocol XPCServerStartupParametersWithServiceNameProtocol <XPCServerBaseProtocol>
- (MTRDeviceController *)createController:(NSString *)controllerID serviceName:(NSString *)serviceName error:(NSError * __autoreleasing *)error;
@end

@interface XPCServerRegistry : NSObject
- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;
+ (XPCServerRegistry *)sharedInstance;

- (void)register:(id<XPCServerBaseProtocol>)server;

- (void)start;
- (void)stop;
- (MTRDeviceController *)createController:(NSString * _Nullable)controllerId serviceName:(NSString * _Nullable)serviceName params:(id)params error:(NSError * __autoreleasing *)error;
@end

NS_ASSUME_NONNULL_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) 2024 Project CHIP Authors
* All rights reserved.
*
* 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 "XPCServerRegistry.h"

@interface XPCServerRegistry ()
@property (strong, nonatomic) NSMutableArray<id<XPCServerBaseProtocol>> * servers;
@end

@implementation XPCServerRegistry
- (instancetype)init
{
if ((self = [super init])) {
_servers = [NSMutableArray new];
}

return self;
}

+ (XPCServerRegistry *)sharedInstance
{
static XPCServerRegistry * registry = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
registry = [[XPCServerRegistry alloc] init];
});
return registry;
}

- (void)start
{
for (id<XPCServerBaseProtocol> server in _servers) {
[server start];
}
}

- (void)stop
{
for (id<XPCServerBaseProtocol> server in _servers) {
[server start];
}
}

- (void)register:(id<XPCServerBaseProtocol>)server
{
[_servers addObject:server];
}

- (MTRDeviceController *)createController:(NSString * _Nullable)controllerId serviceName:(NSString * _Nullable)serviceName params:(id)params error:(NSError * __autoreleasing *)error
{
return [self createControllerInternal:controllerId serviceName:serviceName params:params error:error];
}

- (MTRDeviceController *)createControllerInternal:(NSString * _Nullable)controllerId serviceName:(NSString * _Nullable)serviceName params:(id)params error:(NSError * __autoreleasing *)error
{
BOOL isExternalCertificateParameters = [params isKindOfClass:[MTRDeviceControllerExternalCertificateParameters class]];
BOOL isStartupParameters = [params isKindOfClass:[MTRDeviceControllerStartupParams class]];
for (id server in _servers) {
if (controllerId && serviceName) {
if ([server conformsToProtocol:@protocol(XPCServerExternalCertificateParametersWithServiceNameProtocol)] && isExternalCertificateParameters) {
return [server createController:controllerId serviceName:serviceName error:error];
}

if ([server conformsToProtocol:@protocol(XPCServerStartupParametersWithServiceNameProtocol)] && isStartupParameters) {
return [server createController:controllerId serviceName:serviceName error:error];
}
} else {
if ([server conformsToProtocol:@protocol(XPCServerExternalCertificateParametersProtocol)] && isExternalCertificateParameters) {
return [server createController:params error:error];
}

if ([server conformsToProtocol:@protocol(XPCServerStartupParametersProtocol)] && isStartupParameters) {
return [server createController:params error:error];
}
}
}

__auto_type * userInfo = @{ NSLocalizedDescriptionKey : @"No XPC servers support this configuration." };
*error = [NSError errorWithDomain:@"Error" code:0 userInfo:userInfo];
return nil;
}

@end

0 comments on commit 2329976

Please sign in to comment.