Skip to content

Commit

Permalink
[Darwin] New XPC Service (#34961)
Browse files Browse the repository at this point in the history
* empty xpc service files

* XPC service needs to be C++ to use MTRLogging

* add tests; stub method signature

* start configuring test XPC listener

* add first test method to XPC service protocol

* tests: remove peformance test; add headers

* make MTRXPCService testable

* more working lines of XPC listener setup

* add dummy XPC service for testing

* add replying method to service protocol / implementation

* remove log - reply contents can be asserted

* make test interesting

* linty formatty

* remove personal development team from pbxproj

* fix new file headers

* less whitespace

* Restyled by whitespace

* Restyled by clang-format

* add new XPC device controller

* sketch out a first XPC method

* store WIP for rebase

* fix pbxproj merge mistake

* make WIP slightly more sensible

* WIP: remote proxy obj in `MTRDeviceController_XPC`

* more experiments

* WIP:  return type issue

run `MTRXPCServiceTests testMTRXPCServiceSetup` and see selection of proxy object method in `MTRDeviceController_XPC.m`/`initWithXPCListenerEndpointForTesting` around line 44 to see the problem.

* add `MTRDevice_XPC`

nothing exciting yet

* add device controller over XPC parameters stub

* add init split for XPC device controllers

not yet implemented, but there

* rename new XPC parameters class

`OverXPC` is already taken / means something else

* Restyled by whitespace

* Restyled by clang-format

* remove failing exploratory test

* lintfix

* Examples

* quickly attempt to fix test

unused variable -> warning -> error

* Restyled by whitespace

* Restyled by clang-format

* inevitably the file will need to be obj-C++

* prepare to use mach service name to create XPC connection

* allow for other XPC controller connection types for now

once mach service is working, i don't expect to need others, but easier to collapse classes than raise.

* constant for well-known matter plugin service name

* note to self and re-ordering of this code now what `XPCParameters` is a subclass

* XPC parameters should support secure coding

* don't keep around object proxy; make a new one when needed.  try calling the `checkIn` method when connecting.  remove old test methods that served their purpose.

* that doesn't need to be there.

* Restyled by whitespace

* Restyled by clang-format

* no longer fighting with compiler, have some `instancetype`

* extremely normal object construction

* somehow this header got thrown out

* Restyled by whitespace

* Restyled by clang-format

* Updating XPC interfaces

* hide `initWithMachServiceName:options:` constructor

tvOS/iOS compilation issues need a look

* make `MTRDeviceController_XPC` an XPC client

via `MTRXPCClientProtocol_MTRDeviceController`, which for the moment is empty

* remove initial tests

they served their purpose well but are no longer relevant

* call mach service constructor when appropriate

also logging

* remove some obsolete test methods

* more obsoletes fixed

* more obsolete removal and logging tweaks

* buildability tweaks

* Moving along

* Fixing header

* Fixing macros and codable

* Adding invoke?

* Restyled by whitespace

* Restyled by clang-format

* Actually hooking up to XPCConnection

* Actually hooking up to XPCConnection

* Adding XPC Parameters

* Adding XPC Parameter hookup

* Restyled by whitespace

* Restyled by clang-format

* true => YES

---------

Co-authored-by: Restyled.io <commits@restyled.io>
Co-authored-by: Justin Wood <woody@apple.com>
  • Loading branch information
3 people authored and pull[bot] committed Jan 24, 2025
1 parent 57962e5 commit 5fbd1a9
Show file tree
Hide file tree
Showing 18 changed files with 872 additions and 38 deletions.
6 changes: 3 additions & 3 deletions src/darwin/Framework/CHIP/MTRCluster.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ MTR_AVAILABLE(ios(17.4), macos(14.4), watchos(10.4), tvos(17.4))
* treated as if a default-initialized object was passed in.
*/
MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
@interface MTRWriteParams : NSObject <NSCopying>
@interface MTRWriteParams : NSObject <NSCopying, NSSecureCoding>

/**
* Controls whether the write is a timed write.
Expand Down Expand Up @@ -109,7 +109,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
* treated as if a default-initialized object was passed in.
*/
MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
@interface MTRReadParams : NSObject <NSCopying>
@interface MTRReadParams : NSObject <NSCopying, NSSecureCoding>

/**
* Whether the read/subscribe is fabric-filtered. The default is YES.
Expand Down Expand Up @@ -152,7 +152,7 @@ MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
* treated as if a default-initialized object was passed in.
*/
MTR_AVAILABLE(ios(16.1), macos(13.0), watchos(9.1), tvos(16.1))
@interface MTRSubscribeParams : MTRReadParams
@interface MTRSubscribeParams : MTRReadParams <NSCopying, NSSecureCoding>

/**
* Whether the subscribe should replace already-existing
Expand Down
123 changes: 123 additions & 0 deletions src/darwin/Framework/CHIP/MTRCluster.mm
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ - (instancetype)init
return self;
}

#pragma mark - Copying

- (id)copyWithZone:(NSZone * _Nullable)zone
{
auto other = [[MTRWriteParams alloc] init];
Expand All @@ -77,6 +79,38 @@ - (id)copyWithZone:(NSZone * _Nullable)zone
return other;
}

#pragma mark - Coding

+ (BOOL)supportsSecureCoding
{
return YES;
}

static NSString * sTimedWriteTimeoutCodingKey = @"sTimedWriteTimeoutKey";
static NSString * sDataVersionCodingKey = @"sDataVersionKey";

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
self = [super init];

if (self == nil) {
return nil;
}

self.timedWriteTimeout = [decoder decodeObjectOfClass:[NSNumber class] forKey:sTimedWriteTimeoutCodingKey];
self.dataVersion = [decoder decodeObjectOfClass:[NSNumber class] forKey:sDataVersionCodingKey];

return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
if (self.timedWriteTimeout)
[coder encodeObject:self.timedWriteTimeout forKey:sTimedWriteTimeoutCodingKey];
if (self.dataVersion)
[coder encodeObject:self.dataVersion forKey:sDataVersionCodingKey];
}

@end

@implementation MTRReadParams
Expand All @@ -89,6 +123,43 @@ - (instancetype)init
return self;
}

#pragma mark - Coding

+ (BOOL)supportsSecureCoding
{
return YES;
}

static NSString * sFilterByFabricCoderKey = @"sFilterByFabricKey";
static NSString * sMinEventNumberCoderKey = @"sMinEventNumberKey";
static NSString * sAssumeUnknownAttributesReportableCoderKey = @"sAssumeUnknownAttributesReportableKey";

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
self = [super init];

if (self == nil) {
return nil;
}

self.filterByFabric = [decoder decodeBoolForKey:sFilterByFabricCoderKey];
self.assumeUnknownAttributesReportable = [decoder decodeBoolForKey:sAssumeUnknownAttributesReportableCoderKey];
self.minEventNumber = [decoder decodeObjectOfClass:[NSNumber class] forKey:sMinEventNumberCoderKey];

return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeBool:self.filterByFabric forKey:sFilterByFabricCoderKey];
[coder encodeBool:self.assumeUnknownAttributesReportable forKey:sAssumeUnknownAttributesReportableCoderKey];

if (self.minEventNumber)
[coder encodeObject:self.minEventNumber forKey:sMinEventNumberCoderKey];
}

#pragma mark - Copying

- (id)copyWithZone:(NSZone * _Nullable)zone
{
auto other = [[MTRReadParams alloc] init];
Expand All @@ -98,6 +169,8 @@ - (id)copyWithZone:(NSZone * _Nullable)zone
return other;
}

#pragma mark - Other

- (void)toReadPrepareParams:(chip::app::ReadPrepareParams &)readPrepareParams
{
readPrepareParams.mIsFabricFiltered = self.filterByFabric;
Expand All @@ -121,18 +194,68 @@ - (instancetype)initWithMinInterval:(NSNumber *)minInterval maxInterval:(NSNumbe
return self;
}

#pragma mark - Copying
- (id)copyWithZone:(NSZone * _Nullable)zone
{
auto other = [[MTRSubscribeParams alloc] initWithMinInterval:self.minInterval maxInterval:self.maxInterval];

other.filterByFabric = self.filterByFabric;
other.minEventNumber = self.minEventNumber;
other.assumeUnknownAttributesReportable = self.assumeUnknownAttributesReportable;
other.replaceExistingSubscriptions = self.replaceExistingSubscriptions;
other.reportEventsUrgently = self.reportEventsUrgently;
other.resubscribeAutomatically = self.resubscribeAutomatically;
other.minInterval = self.minInterval;
other.maxInterval = self.maxInterval;

return other;
}

#pragma mark - Coding
+ (BOOL)supportsSecureCoding
{
return YES;
}

static NSString * sReplaceExistingSubscriptionsCoderKey = @"sFilterByFabricKey";
static NSString * sReportEventsUrgentlyCoderKey = @"sMinEventNumberKey";
static NSString * sResubscribeAutomaticallyCoderKey = @"sAssumeUnknownAttributesReportableKey";
static NSString * sMinIntervalKeyCoderKey = @"sMinIntervalKeyKey";
static NSString * sMaxIntervalKeyCoderKey = @"sMaxIntervalKeyKey";

- (nullable instancetype)initWithCoder:(NSCoder *)decoder
{
self = [super initWithCoder:decoder];

if (self == nil) {
return nil;
}

self.replaceExistingSubscriptions = [decoder decodeBoolForKey:sReplaceExistingSubscriptionsCoderKey];
self.reportEventsUrgently = [decoder decodeBoolForKey:sReportEventsUrgentlyCoderKey];
self.resubscribeAutomatically = [decoder decodeBoolForKey:sResubscribeAutomaticallyCoderKey];
self.minInterval = [decoder decodeObjectOfClass:[NSNumber class] forKey:sMinIntervalKeyCoderKey];
self.maxInterval = [decoder decodeObjectOfClass:[NSNumber class] forKey:sMaxIntervalKeyCoderKey];

return self;
}

- (void)encodeWithCoder:(NSCoder *)coder
{
[super encodeWithCoder:coder];

[coder encodeBool:self.replaceExistingSubscriptions forKey:sReplaceExistingSubscriptionsCoderKey];
[coder encodeBool:self.reportEventsUrgently forKey:sReportEventsUrgentlyCoderKey];
[coder encodeBool:self.resubscribeAutomatically forKey:sResubscribeAutomaticallyCoderKey];

if (self.minInterval)
[coder encodeObject:self.minInterval forKey:sMinIntervalKeyCoderKey];
if (self.maxInterval)
[coder encodeObject:self.maxInterval forKey:sMaxIntervalKeyCoderKey];
}

#pragma mark - Main

- (void)toReadPrepareParams:(chip::app::ReadPrepareParams &)readPrepareParams
{
[super toReadPrepareParams:readPrepareParams];
Expand Down
47 changes: 47 additions & 0 deletions src/darwin/Framework/CHIP/MTRDefines_Internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,50 @@ typedef struct {} variable_hidden_by_mtr_hide;

// Default timed interaction timeout, in ms, if another one is not provided.
#define MTR_DEFAULT_TIMED_INTERACTION_TIMEOUT_MS 10000

#pragma mark - XPC Defines

#define MTR_SIMPLE_REMOTE_XPC_GETTER(XPC_CONNECTION, NAME, TYPE, DEFAULT_VALUE, GETTER_NAME, PREFIX) \
\
-(TYPE) NAME \
{ \
__block TYPE outValue = DEFAULT_VALUE; \
\
NSXPCConnection * xpcConnection = XPC_CONNECTION; \
\
[[xpcConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { \
MTR_LOG_ERROR("Error: %@", error); \
}] PREFIX \
GETTER_NAME:^(TYPE returnValue) { \
outValue = returnValue; \
}]; \
\
return outValue; \
}

#define MTR_SIMPLE_REMOTE_XPC_COMMAND(XPC_CONNECTION, METHOD_SIGNATURE, ADDITIONAL_ARGUMENTS, PREFIX) \
\
-(void) METHOD_SIGNATURE \
{ \
NSXPCConnection * xpcConnection = XPC_CONNECTION; \
\
[[xpcConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { \
MTR_LOG_ERROR("Error: %@", error); \
}] PREFIX ADDITIONAL_ARGUMENTS]; \
}

#define MTR_COMPLEX_REMOTE_XPC_GETTER(XPC_CONNECTION, SIGNATURE, TYPE, DEFAULT_VALUE, ADDITIONAL_ARGUMENTS, PREFIX) \
-(TYPE) SIGNATURE \
{ \
__block TYPE outValue = DEFAULT_VALUE; \
\
NSXPCConnection * xpcConnection = XPC_CONNECTION; \
\
[[xpcConnection synchronousRemoteObjectProxyWithErrorHandler:^(NSError * _Nonnull error) { \
MTR_LOG_ERROR("Error: %@", error); \
}] PREFIX ADDITIONAL_ARGUMENTS:^(TYPE returnValue) { \
outValue = returnValue; \
}]; \
\
return outValue; \
}
7 changes: 6 additions & 1 deletion src/darwin/Framework/CHIP/MTRDeviceController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#import "MTRDeviceControllerLocalTestStorage.h"
#import "MTRDeviceControllerStartupParams.h"
#import "MTRDeviceControllerStartupParams_Internal.h"
#import "MTRDeviceController_XPC.h"
#import "MTRDevice_Concrete.h"
#import "MTRDevice_Internal.h"
#import "MTRError_Internal.h"
Expand Down Expand Up @@ -144,7 +145,11 @@ - (instancetype)initForSubclasses

- (nullable MTRDeviceController *)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters error:(NSError * __autoreleasing *)error
{
if (![parameters isKindOfClass:MTRDeviceControllerParameters.class]) {
if ([parameters isKindOfClass:MTRXPCDeviceControllerParameters.class]) {
MTRXPCDeviceControllerParameters * resolvedParameters = (MTRXPCDeviceControllerParameters *) parameters;
MTR_LOG("Starting up with XPC Device Controller Parameters: %@", parameters);
return [[MTRDeviceController_XPC alloc] initWithUniqueIdentifier:resolvedParameters.uniqueIdentifier xpConnectionBlock:resolvedParameters.xpcConnectionBlock];
} else if (![parameters isKindOfClass:MTRDeviceControllerParameters.class]) {
MTR_LOG_ERROR("Unsupported type of MTRDeviceControllerAbstractParameters: %@", parameters);
if (error) {
*error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INVALID_ARGUMENT];
Expand Down
22 changes: 22 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,26 @@ MTR_AVAILABLE(ios(17.6), macos(14.6), watchos(10.6), tvos(17.6))

@end

MTR_NEWLY_AVAILABLE
@interface MTRXPCDeviceControllerParameters : MTRDeviceControllerAbstractParameters

- (instancetype)init NS_UNAVAILABLE;
+ (instancetype)new NS_UNAVAILABLE;

/**
* A controller created from this way will connect to a remote instance of an MTRDeviceController loaded in an XPC Service
*
* @param xpcConnectionBlock The XPC Connection block that will return an NSXPCConnection to the indended listener.
*
* @param uniqueIdentifier The unique id to assign to the controller.
*
*/
- (instancetype)initWithXPConnectionBlock:(NSXPCConnection * (^)(void) )xpcConnectionBlock
uniqueIdentifier:(NSUUID *)uniqueIdentifier;

@property (atomic, readonly, retain) NSUUID * uniqueIdentifier MTR_NEWLY_AVAILABLE;
@property (readonly, strong, nonatomic) NSXPCConnection * (^xpcConnectionBlock)(void) MTR_NEWLY_AVAILABLE;

@end

NS_ASSUME_NONNULL_END
17 changes: 17 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerStartupParams.mm
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,23 @@ - (instancetype)initWithStorageDelegate:(id<MTRDeviceControllerStorageDelegate>)
}
@end

@implementation MTRXPCDeviceControllerParameters

@synthesize uniqueIdentifier = _uniqueIdentifier;
@synthesize xpcConnectionBlock = _xpcConnectionBlock;

- (instancetype)initWithXPConnectionBlock:(NSXPCConnection * (^)(void) )xpcConnectionBlock
uniqueIdentifier:(NSUUID *)uniqueIdentifier;
{
if (self = [super _initInternal]) {
_xpcConnectionBlock = [xpcConnectionBlock copy];
_uniqueIdentifier = [uniqueIdentifier copy];
}

return self;
}
@end

@implementation MTRDeviceControllerStartupParamsInternal

- (instancetype)initWithParams:(MTRDeviceControllerStartupParams *)params
Expand Down
31 changes: 31 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerXPCParameters.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright (c) 2024 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 <Matter/Matter.h>

NS_ASSUME_NONNULL_BEGIN

@interface MTRDeviceControllerXPCParameters : MTRDeviceControllerParameters
@end

@interface MTRDeviceControllerMachServiceXPCParameters : MTRDeviceControllerXPCParameters

@property (atomic, retain) NSString * machServiceName;
@property (atomic, readwrite) NSXPCConnectionOptions connectionOptions;

@end

NS_ASSUME_NONNULL_END
35 changes: 35 additions & 0 deletions src/darwin/Framework/CHIP/MTRDeviceControllerXPCParameters.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) 2024 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 "MTRDeviceControllerXPCParameters.h"

@implementation MTRDeviceControllerXPCParameters

+ (BOOL)supportsSecureCoding
{
return YES;
}

@end

@implementation MTRDeviceControllerMachServiceXPCParameters

+ (BOOL)supportsSecureCoding
{
return YES;
}

@end
Loading

0 comments on commit 5fbd1a9

Please sign in to comment.