Skip to content

Commit

Permalink
Modify Matter.framework to allow per-controller storage. (#28533)
Browse files Browse the repository at this point in the history
* Modify Matter.framework to allow per-controller storage.

This also allows starting multiple controllers with different node IDs on a
single fabric.

Public API changes:

* It's now possible to initialize MTRDeviceControllerFactoryParams without
  storage.  When a factory is then started with those params, it will expect
  storage to be provided for every controller that is created.
* Controllers to be created in the new setup use
  MTRDeviceControllerStartupParameters, not MTRDeviceControllerStartupParams.
* When starting a controller, API clients provide a UUID for that controller
  (which is then exposed on the MTRDeviceController) and a storage delegate.
* For now, the only supported controller startup mode is for the client to
  provide the full certificate chain, operational key and vendor ID, via
  MTRDeviceControllerExternalCertificateStartupParameters.  For controllers that
  will commission devices, that means also providing an
  MTROperationalCertificateIssuer.
* The new "create a controller" API is called createController.
* The new MTRDeviceControllerStorageDelegate API provides some context for the
  key/value pairs in terms of whether they need to be stored in encrypted
  storage or not, and whether they can be shared across multiple devices and
  under what conditions.

Implementation notes:

* MTRDemuxingStorage handles directing storage requests to the right
  per-controller storage object.
* MTRDeviceControllerDataStore wraps the raw storage delegate and provides a
  semantic API on top of its key/value storage for the storage operations we
  actually want to perform.
* MTRSessionResumptionStorageBridge implements session resumption storage,
  acting as an adapter between the Matter session resumption storage API and
  MTRDeviceControllerDataStore.  In particular, it happens locating the right
  controller(s) to talk to and so on.  This avoids dealing with the default
  Matter implementation's use of non-fabric-index-scoped keys for storing
  session resumption information.

Fixes #27394

* Require consumers to provide a dispatch queue for the storage delegate.

* Address review comments.

* Apply spelling/grammar suggestions from code review

Co-authored-by: Nivi Sarkar <[email protected]>

* Address review comments.

* Address more review comments.

* Address more review comments.

* Address more review comments.

* Add some validation when deserializing node IDs and CATs.

* Stop trusting the secure coding stuff to actually enforce types correctly.

For built-in types it seems to not do that.

* Remove NSMutableArray and NSSet from controller storage classes, since we no longer encode those.

---------

Co-authored-by: Nivi Sarkar <[email protected]>
  • Loading branch information
bzbarsky-apple and nivi-apple authored Aug 31, 2023
1 parent b3c0ac1 commit 9db615b
Show file tree
Hide file tree
Showing 20 changed files with 3,195 additions and 67 deletions.
70 changes: 70 additions & 0 deletions src/darwin/Framework/CHIP/MTRDemuxingStorage.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/**
* Copyright (c) 2023 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 <Foundation/Foundation.h>
#import <Matter/MTRDeviceControllerFactory.h>

#include <lib/core/CHIPPersistentStorageDelegate.h>
#include <lib/core/DataModelTypes.h>

NS_ASSUME_NONNULL_BEGIN

/**
* A PersistentStorageDelegate implementation that does the following:
*
* 1) Ensures that any "global" storage keys are stored in RAM as needed so that
* the Matter stack has access to them.
* 2) Hands off fabric-index-specific keys to the controller that corresponds to
* that fabric index, if any.
*/
class MTRDemuxingStorage : public chip::PersistentStorageDelegate {
public:
MTRDemuxingStorage(MTRDeviceControllerFactory * factory);
~MTRDemuxingStorage() {}

// PersistentStorageDelegate API.
CHIP_ERROR SyncGetKeyValue(const char * key, void * buffer, uint16_t & size) override;

CHIP_ERROR SyncSetKeyValue(const char * key, const void * value, uint16_t size) override;

CHIP_ERROR SyncDeleteKeyValue(const char * key) override;

private:
/**
* Methods for reading/writing/deleting things. The index-specific ones
* will have the "f/index/" bit already stripped of from the front of the key.
*/
NSData * _Nullable GetGlobalValue(NSString * key);
NSData * _Nullable GetIndexSpecificValue(chip::FabricIndex index, NSString * key);

CHIP_ERROR SetGlobalValue(NSString * key, NSData * data);
CHIP_ERROR SetIndexSpecificValue(chip::FabricIndex index, NSString * key, NSData * data);

CHIP_ERROR DeleteGlobalValue(NSString * key);
CHIP_ERROR DeleteIndexSpecificValue(chip::FabricIndex index, NSString * key);

/**
* Methods for modifying our in-memory store for fully qualified keys.
*/
NSData * _Nullable GetInMemoryValue(NSString * key);
CHIP_ERROR SetInMemoryValue(NSString * key, NSData * data);
CHIP_ERROR DeleteInMemoryValue(NSString * key);

MTRDeviceControllerFactory * mFactory;
NSMutableDictionary<NSString *, NSData *> * mInMemoryStore;
};

NS_ASSUME_NONNULL_END
Loading

0 comments on commit 9db615b

Please sign in to comment.