22
22
23
23
#include < lib/core/CASEAuthTag.h>
24
24
#include < lib/core/NodeId.h>
25
+ #include < lib/support/CodeUtils.h>
25
26
#include < lib/support/SafeInt.h>
26
27
27
28
// FIXME: Are these good key strings? https://github.com/project-chip/connectedhomeip/issues/28973
@@ -106,7 +107,8 @@ static bool IsValidCATNumber(id _Nullable value)
106
107
@implementation MTRDeviceControllerDataStore {
107
108
id <MTRDeviceControllerStorageDelegate> _storageDelegate;
108
109
dispatch_queue_t _storageDelegateQueue;
109
- MTRDeviceController * _controller;
110
+ // Controller owns us, so we have to make sure to not keep it alive.
111
+ __weak MTRDeviceController * _controller;
110
112
// Array of nodes with resumption info, oldest-stored first.
111
113
NSMutableArray <NSNumber *> * _nodesWithResumptionInfo;
112
114
}
@@ -126,7 +128,9 @@ - (nullable instancetype)initWithController:(MTRDeviceController *)controller
126
128
__block id resumptionNodeList;
127
129
dispatch_sync (_storageDelegateQueue, ^{
128
130
@autoreleasepool {
129
- resumptionNodeList = [_storageDelegate controller: _controller
131
+ // NOTE: controller, not our weak ref, since we know it's still
132
+ // valid under this sync dispatch.
133
+ resumptionNodeList = [_storageDelegate controller: controller
130
134
valueForKey: sResumptionNodeListKey
131
135
securityLevel: MTRStorageSecurityLevelSecure
132
136
sharingType: MTRStorageSharingTypeNotShared];
@@ -154,9 +158,12 @@ - (nullable instancetype)initWithController:(MTRDeviceController *)controller
154
158
- (void )fetchAttributeDataForAllDevices : (MTRDeviceControllerDataStoreClusterDataHandler)clusterDataHandler
155
159
{
156
160
__block NSDictionary <NSString *, id > * dataStoreSecureLocalValues = nil ;
161
+ MTRDeviceController * controller = _controller;
162
+ VerifyOrReturn (controller != nil ); // No way to call delegate without controller.
163
+
157
164
dispatch_sync (_storageDelegateQueue, ^{
158
165
if ([self ->_storageDelegate respondsToSelector: @selector (valuesForController:securityLevel:sharingType: )]) {
159
- dataStoreSecureLocalValues = [self ->_storageDelegate valuesForController: self ->_controller securityLevel: MTRStorageSecurityLevelSecure sharingType: MTRStorageSharingTypeNotShared];
166
+ dataStoreSecureLocalValues = [self ->_storageDelegate valuesForController: controller securityLevel: MTRStorageSecurityLevelSecure sharingType: MTRStorageSharingTypeNotShared];
160
167
}
161
168
});
162
169
@@ -177,32 +184,35 @@ - (nullable MTRCASESessionResumptionInfo *)findResumptionInfoByResumptionID:(NSD
177
184
178
185
- (void )storeResumptionInfo : (MTRCASESessionResumptionInfo *)resumptionInfo
179
186
{
187
+ MTRDeviceController * controller = _controller;
188
+ VerifyOrReturn (controller != nil ); // No way to call delegate without controller.
189
+
180
190
auto * oldInfo = [self findResumptionInfoByNodeID: resumptionInfo.nodeID];
181
191
dispatch_sync (_storageDelegateQueue, ^{
182
192
if (oldInfo != nil ) {
183
193
// Remove old resumption id key. No need to do that for the
184
194
// node id, because we are about to overwrite it.
185
- [_storageDelegate controller: _controller
195
+ [_storageDelegate controller: controller
186
196
removeValueForKey: ResumptionByResumptionIDKey (oldInfo.resumptionID)
187
197
securityLevel: MTRStorageSecurityLevelSecure
188
198
sharingType: MTRStorageSharingTypeNotShared];
189
199
[_nodesWithResumptionInfo removeObject: resumptionInfo.nodeID];
190
200
}
191
201
192
- [_storageDelegate controller: _controller
202
+ [_storageDelegate controller: controller
193
203
storeValue: resumptionInfo
194
204
forKey: ResumptionByNodeIDKey (resumptionInfo.nodeID)
195
205
securityLevel: MTRStorageSecurityLevelSecure
196
206
sharingType: MTRStorageSharingTypeNotShared];
197
- [_storageDelegate controller: _controller
207
+ [_storageDelegate controller: controller
198
208
storeValue: resumptionInfo
199
209
forKey: ResumptionByResumptionIDKey (resumptionInfo.resumptionID)
200
210
securityLevel: MTRStorageSecurityLevelSecure
201
211
sharingType: MTRStorageSharingTypeNotShared];
202
212
203
213
// Update our resumption info node list.
204
214
[_nodesWithResumptionInfo addObject: resumptionInfo.nodeID];
205
- [_storageDelegate controller: _controller
215
+ [_storageDelegate controller: controller
206
216
storeValue: [_nodesWithResumptionInfo copy ]
207
217
forKey: sResumptionNodeListKey
208
218
securityLevel: MTRStorageSecurityLevelSecure
@@ -212,17 +222,20 @@ - (void)storeResumptionInfo:(MTRCASESessionResumptionInfo *)resumptionInfo
212
222
213
223
- (void )clearAllResumptionInfo
214
224
{
225
+ MTRDeviceController * controller = _controller;
226
+ VerifyOrReturn (controller != nil ); // No way to call delegate without controller.
227
+
215
228
// Can we do less dispatch? We would need to have a version of
216
229
// _findResumptionInfoWithKey that assumes we are already on the right queue.
217
230
for (NSNumber * nodeID in _nodesWithResumptionInfo) {
218
231
auto * oldInfo = [self findResumptionInfoByNodeID: nodeID];
219
232
if (oldInfo != nil ) {
220
233
dispatch_sync (_storageDelegateQueue, ^{
221
- [_storageDelegate controller: _controller
234
+ [_storageDelegate controller: controller
222
235
removeValueForKey: ResumptionByResumptionIDKey (oldInfo.resumptionID)
223
236
securityLevel: MTRStorageSecurityLevelSecure
224
237
sharingType: MTRStorageSharingTypeNotShared];
225
- [_storageDelegate controller: _controller
238
+ [_storageDelegate controller: controller
226
239
removeValueForKey: ResumptionByNodeIDKey (oldInfo.nodeID)
227
240
securityLevel: MTRStorageSecurityLevelSecure
228
241
sharingType: MTRStorageSharingTypeNotShared];
@@ -235,9 +248,12 @@ - (void)clearAllResumptionInfo
235
248
236
249
- (CHIP_ERROR)storeLastLocallyUsedNOC : (MTRCertificateTLVBytes)noc
237
250
{
251
+ MTRDeviceController * controller = _controller;
252
+ VerifyOrReturnError (controller != nil , CHIP_ERROR_PERSISTED_STORAGE_FAILED); // No way to call delegate without controller.
253
+
238
254
__block BOOL ok;
239
255
dispatch_sync (_storageDelegateQueue, ^{
240
- ok = [_storageDelegate controller: _controller
256
+ ok = [_storageDelegate controller: controller
241
257
storeValue: noc
242
258
forKey: sLastLocallyUsedNOCKey
243
259
securityLevel: MTRStorageSecurityLevelSecure
@@ -248,10 +264,13 @@ - (CHIP_ERROR)storeLastLocallyUsedNOC:(MTRCertificateTLVBytes)noc
248
264
249
265
- (MTRCertificateTLVBytes _Nullable)fetchLastLocallyUsedNOC
250
266
{
267
+ MTRDeviceController * controller = _controller;
268
+ VerifyOrReturnValue (controller != nil , nil ); // No way to call delegate without controller.
269
+
251
270
__block id data;
252
271
dispatch_sync (_storageDelegateQueue, ^{
253
272
@autoreleasepool {
254
- data = [_storageDelegate controller: _controller
273
+ data = [_storageDelegate controller: controller
255
274
valueForKey: sLastLocallyUsedNOCKey
256
275
securityLevel: MTRStorageSecurityLevelSecure
257
276
sharingType: MTRStorageSharingTypeNotShared];
@@ -271,6 +290,9 @@ - (MTRCertificateTLVBytes _Nullable)fetchLastLocallyUsedNOC
271
290
272
291
- (nullable MTRCASESessionResumptionInfo *)_findResumptionInfoWithKey : (nullable NSString *)key
273
292
{
293
+ MTRDeviceController * controller = _controller;
294
+ VerifyOrReturnValue (controller != nil , nil ); // No way to call delegate without controller.
295
+
274
296
// key could be nil if [NSString stringWithFormat] returns nil for some reason.
275
297
if (key == nil ) {
276
298
return nil ;
@@ -279,7 +301,7 @@ - (nullable MTRCASESessionResumptionInfo *)_findResumptionInfoWithKey:(nullable
279
301
__block id resumptionInfo;
280
302
dispatch_sync (_storageDelegateQueue, ^{
281
303
@autoreleasepool {
282
- resumptionInfo = [_storageDelegate controller: _controller
304
+ resumptionInfo = [_storageDelegate controller: controller
283
305
valueForKey: key
284
306
securityLevel: MTRStorageSecurityLevelSecure
285
307
sharingType: MTRStorageSharingTypeNotShared];
@@ -318,9 +340,12 @@ - (nullable MTRCASESessionResumptionInfo *)_findResumptionInfoWithKey:(nullable
318
340
319
341
- (id )_fetchAttributeCacheValueForKey : (NSString *)key expectedClass : (Class )expectedClass ;
320
342
{
343
+ MTRDeviceController * controller = _controller;
344
+ VerifyOrReturnValue (controller != nil , nil ); // No way to call delegate without controller.
345
+
321
346
id data;
322
347
@autoreleasepool {
323
- data = [_storageDelegate controller: _controller
348
+ data = [_storageDelegate controller: controller
324
349
valueForKey: key
325
350
securityLevel: MTRStorageSecurityLevelSecure
326
351
sharingType: MTRStorageSharingTypeNotShared];
@@ -338,7 +363,10 @@ - (id)_fetchAttributeCacheValueForKey:(NSString *)key expectedClass:(Class)expec
338
363
339
364
- (BOOL )_storeAttributeCacheValue : (id )value forKey : (NSString *)key
340
365
{
341
- return [_storageDelegate controller: _controller
366
+ MTRDeviceController * controller = _controller;
367
+ VerifyOrReturnValue (controller != nil , NO ); // No way to call delegate without controller.
368
+
369
+ return [_storageDelegate controller: controller
342
370
storeValue: value
343
371
forKey: key
344
372
securityLevel: MTRStorageSecurityLevelSecure
@@ -347,15 +375,21 @@ - (BOOL)_storeAttributeCacheValue:(id)value forKey:(NSString *)key
347
375
348
376
- (BOOL )_bulkStoreAttributeCacheValues : (NSDictionary <NSString *, id<NSSecureCoding >> *)values
349
377
{
350
- return [_storageDelegate controller: _controller
378
+ MTRDeviceController * controller = _controller;
379
+ VerifyOrReturnValue (controller != nil , NO ); // No way to call delegate without controller.
380
+
381
+ return [_storageDelegate controller: controller
351
382
storeValues: values
352
383
securityLevel: MTRStorageSecurityLevelSecure
353
384
sharingType: MTRStorageSharingTypeNotShared];
354
385
}
355
386
356
387
- (BOOL )_removeAttributeCacheValueForKey : (NSString *)key
357
388
{
358
- return [_storageDelegate controller: _controller
389
+ MTRDeviceController * controller = _controller;
390
+ VerifyOrReturnValue (controller != nil , NO ); // No way to call delegate without controller.
391
+
392
+ return [_storageDelegate controller: controller
359
393
removeValueForKey: key
360
394
securityLevel: MTRStorageSecurityLevelSecure
361
395
sharingType: MTRStorageSharingTypeNotShared];
0 commit comments