|
41 | 41 | #import "MTROperationalCredentialsDelegate.h"
|
42 | 42 | #import "MTRP256KeypairBridge.h"
|
43 | 43 | #import "MTRPersistentStorageDelegateBridge.h"
|
| 44 | +#import "MTRServerEndpoint_Internal.h" |
44 | 45 | #import "MTRSetupPayload.h"
|
45 | 46 | #import "NSDataSpanConversion.h"
|
46 | 47 | #import "NSStringSpanConversion.h"
|
|
55 | 56 |
|
56 | 57 | #include <app-common/zap-generated/cluster-objects.h>
|
57 | 58 | #include <app/data-model/List.h>
|
| 59 | +#include <app/server/Dnssd.h> |
58 | 60 | #include <controller/CHIPDeviceController.h>
|
59 | 61 | #include <controller/CHIPDeviceControllerFactory.h>
|
60 | 62 | #include <controller/CommissioningWindowOpener.h>
|
61 | 63 | #include <credentials/FabricTable.h>
|
62 | 64 | #include <credentials/GroupDataProvider.h>
|
63 | 65 | #include <credentials/attestation_verifier/DacOnlyPartialAttestationVerifier.h>
|
64 | 66 | #include <credentials/attestation_verifier/DefaultDeviceAttestationVerifier.h>
|
| 67 | +#include <inet/InetInterface.h> |
65 | 68 | #include <lib/core/CHIPVendorIdentifiers.hpp>
|
66 | 69 | #include <platform/LockTracker.h>
|
67 | 70 | #include <platform/PlatformManager.h>
|
68 | 71 | #include <setup_payload/ManualSetupPayloadGenerator.h>
|
69 | 72 | #include <system/SystemClock.h>
|
70 | 73 |
|
71 | 74 | #include <atomic>
|
| 75 | +#include <dns_sd.h> |
72 | 76 |
|
73 | 77 | #import <os/lock.h>
|
74 | 78 |
|
@@ -121,6 +125,9 @@ @implementation MTRDeviceController {
|
121 | 125 | os_unfair_lock _deviceMapLock; // protects nodeIDToDeviceMap
|
122 | 126 | MTRCommissionableBrowser * _commissionableBrowser;
|
123 | 127 | MTRAttestationTrustStoreBridge * _attestationTrustStoreBridge;
|
| 128 | + |
| 129 | + // _serverEndpoints is only touched on the Matter queue. |
| 130 | + NSMutableArray<MTRServerEndpoint *> * _serverEndpoints; |
124 | 131 | }
|
125 | 132 |
|
126 | 133 | - (nullable instancetype)initWithParameters:(MTRDeviceControllerAbstractParameters *)parameters error:(NSError * __autoreleasing *)error
|
@@ -221,6 +228,7 @@ - (instancetype)initWithFactory:(MTRDeviceControllerFactory *)factory
|
221 | 228 | _factory = factory;
|
222 | 229 | _deviceMapLock = OS_UNFAIR_LOCK_INIT;
|
223 | 230 | _nodeIDToDeviceMap = [NSMutableDictionary dictionary];
|
| 231 | + _serverEndpoints = [[NSMutableArray alloc] init]; |
224 | 232 | _commissionableBrowser = nil;
|
225 | 233 |
|
226 | 234 | _deviceControllerDelegateBridge = new MTRDeviceControllerDelegateBridge();
|
@@ -285,6 +293,11 @@ - (void)shutDownCppController
|
285 | 293 | {
|
286 | 294 | assertChipStackLockedByCurrentThread();
|
287 | 295 |
|
| 296 | + // Shut down all our endpoints. |
| 297 | + for (MTRServerEndpoint * endpoint in [_serverEndpoints copy]) { |
| 298 | + [self removeServerEndpointOnMatterQueue:endpoint]; |
| 299 | + } |
| 300 | + |
288 | 301 | if (_cppCommissioner) {
|
289 | 302 | auto * commissionerToShutDown = _cppCommissioner;
|
290 | 303 | // Flag ourselves as not running before we start shutting down
|
@@ -947,6 +960,71 @@ - (NSData * _Nullable)attestationChallengeForDeviceID:(NSNumber *)deviceID
|
947 | 960 | return [self syncRunOnWorkQueueWithReturnValue:block error:nil];
|
948 | 961 | }
|
949 | 962 |
|
| 963 | +- (BOOL)addServerEndpoint:(MTRServerEndpoint *)endpoint |
| 964 | +{ |
| 965 | + VerifyOrReturnValue([self checkIsRunning], NO); |
| 966 | + |
| 967 | + if (![_factory addServerEndpoint:endpoint]) { |
| 968 | + return NO; |
| 969 | + } |
| 970 | + |
| 971 | + if (![endpoint associateWithController:self]) { |
| 972 | + MTR_LOG_ERROR("Failed to associate MTRServerEndpoint with MTRDeviceController"); |
| 973 | + [_factory removeServerEndpoint:endpoint]; |
| 974 | + return NO; |
| 975 | + } |
| 976 | + |
| 977 | + [self asyncDispatchToMatterQueue:^() { |
| 978 | + [self->_serverEndpoints addObject:endpoint]; |
| 979 | + [endpoint registerMatterEndpoint]; |
| 980 | + } |
| 981 | + errorHandler:^(NSError * error) { |
| 982 | + MTR_LOG_ERROR("Unexpected failure dispatching to Matter queue on running controller in addServerEndpoint"); |
| 983 | + }]; |
| 984 | + return YES; |
| 985 | +} |
| 986 | + |
| 987 | +- (void)removeServerEndpoint:(MTRServerEndpoint *)endpoint queue:(dispatch_queue_t)queue completion:(dispatch_block_t)completion |
| 988 | +{ |
| 989 | + [self removeServerEndpointInternal:endpoint queue:queue completion:completion]; |
| 990 | +} |
| 991 | + |
| 992 | +- (void)removeServerEndpoint:(MTRServerEndpoint *)endpoint |
| 993 | +{ |
| 994 | + [self removeServerEndpointInternal:endpoint queue:nil completion:nil]; |
| 995 | +} |
| 996 | + |
| 997 | +- (void)removeServerEndpointInternal:(MTRServerEndpoint *)endpoint queue:(dispatch_queue_t _Nullable)queue completion:(dispatch_block_t _Nullable)completion |
| 998 | +{ |
| 999 | + VerifyOrReturn([self checkIsRunning]); |
| 1000 | + |
| 1001 | + // We need to unhook the endpoint from the Matter side before we can start |
| 1002 | + // tearing it down. |
| 1003 | + [self asyncDispatchToMatterQueue:^() { |
| 1004 | + [self removeServerEndpointOnMatterQueue:endpoint]; |
| 1005 | + if (queue != nil && completion != nil) { |
| 1006 | + dispatch_async(queue, completion); |
| 1007 | + } |
| 1008 | + } |
| 1009 | + errorHandler:^(NSError * error) { |
| 1010 | + // Error means we got shut down, so the endpoint is removed now. |
| 1011 | + if (queue != nil && completion != nil) { |
| 1012 | + dispatch_async(queue, completion); |
| 1013 | + } |
| 1014 | + }]; |
| 1015 | +} |
| 1016 | + |
| 1017 | +- (void)removeServerEndpointOnMatterQueue:(MTRServerEndpoint *)endpoint |
| 1018 | +{ |
| 1019 | + assertChipStackLockedByCurrentThread(); |
| 1020 | + |
| 1021 | + [endpoint unregisterMatterEndpoint]; |
| 1022 | + [_serverEndpoints removeObject:endpoint]; |
| 1023 | + [endpoint invalidate]; |
| 1024 | + |
| 1025 | + [_factory removeServerEndpoint:endpoint]; |
| 1026 | +} |
| 1027 | + |
950 | 1028 | - (BOOL)checkForInitError:(BOOL)condition logMsg:(NSString *)logMsg
|
951 | 1029 | {
|
952 | 1030 | if (condition) {
|
@@ -1230,6 +1308,52 @@ - (void)downloadLogFromNodeWithID:(NSNumber *)nodeID
|
1230 | 1308 | completion:completion];
|
1231 | 1309 | }
|
1232 | 1310 |
|
| 1311 | +- (NSArray<MTRAccessGrant *> *)accessGrantsForClusterPath:(MTRClusterPath *)clusterPath |
| 1312 | +{ |
| 1313 | + assertChipStackLockedByCurrentThread(); |
| 1314 | + |
| 1315 | + for (MTRServerEndpoint * endpoint in _serverEndpoints) { |
| 1316 | + if ([clusterPath.endpoint isEqual:endpoint.endpointID]) { |
| 1317 | + return [endpoint matterAccessGrantsForCluster:clusterPath.cluster]; |
| 1318 | + } |
| 1319 | + } |
| 1320 | + |
| 1321 | + // Nothing matched, no grants. |
| 1322 | + return @[]; |
| 1323 | +} |
| 1324 | + |
| 1325 | +- (nullable NSNumber *)neededReadPrivilegeForClusterID:(NSNumber *)clusterID attributeID:(NSNumber *)attributeID |
| 1326 | +{ |
| 1327 | + assertChipStackLockedByCurrentThread(); |
| 1328 | + |
| 1329 | + for (MTRServerEndpoint * endpoint in _serverEndpoints) { |
| 1330 | + for (MTRServerCluster * cluster in endpoint.serverClusters) { |
| 1331 | + if (![cluster.clusterID isEqual:clusterID]) { |
| 1332 | + continue; |
| 1333 | + } |
| 1334 | + |
| 1335 | + for (MTRServerAttribute * attr in cluster.attributes) { |
| 1336 | + if (![attr.attributeID isEqual:attributeID]) { |
| 1337 | + continue; |
| 1338 | + } |
| 1339 | + |
| 1340 | + return @(attr.requiredReadPrivilege); |
| 1341 | + } |
| 1342 | + } |
| 1343 | + } |
| 1344 | + |
| 1345 | + return nil; |
| 1346 | +} |
| 1347 | + |
| 1348 | +#ifdef DEBUG |
| 1349 | ++ (void)forceLocalhostAdvertisingOnly |
| 1350 | +{ |
| 1351 | + auto interfaceIndex = chip::Inet::InterfaceId::PlatformType(kDNSServiceInterfaceIndexLocalOnly); |
| 1352 | + auto interfaceId = chip::Inet::InterfaceId(interfaceIndex); |
| 1353 | + chip::app::DnssdServer::Instance().SetInterfaceId(interfaceId); |
| 1354 | +} |
| 1355 | +#endif // DEBUG |
| 1356 | + |
1233 | 1357 | @end
|
1234 | 1358 |
|
1235 | 1359 | /**
|
|
0 commit comments