Line data Source code
1 : /* 2 : * Copyright (c) 2021 Project CHIP Authors 3 : * 4 : * Licensed under the Apache License, Version 2.0 (the "License"); 5 : * you may not use this file except in compliance with the License. 6 : * You may obtain a copy of the License at 7 : * 8 : * http://www.apache.org/licenses/LICENSE-2.0 9 : * 10 : * Unless required by applicable law or agreed to in writing, software 11 : * distributed under the License is distributed on an "AS IS" BASIS, 12 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 : * See the License for the specific language governing permissions and 14 : * limitations under the License. 15 : */ 16 : 17 : #include <app/DefaultAttributePersistenceProvider.h> 18 : #include <lib/support/CodeUtils.h> 19 : #include <lib/support/DefaultStorageKeyAllocator.h> 20 : #include <lib/support/SafeInt.h> 21 : 22 : namespace chip { 23 : namespace app { 24 : 25 65 : CHIP_ERROR DefaultAttributePersistenceProvider::InternalWriteValue(const StorageKeyName & aKey, const ByteSpan & aValue) 26 : { 27 65 : VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE); 28 : 29 : // TODO: we may want to have a small cache for values that change a lot, so 30 : // we only write them once a bunch of changes happen or on timer or 31 : // shutdown. 32 65 : if (!CanCastTo<uint16_t>(aValue.size())) 33 : { 34 0 : return CHIP_ERROR_BUFFER_TOO_SMALL; 35 : } 36 65 : return mStorage->SyncSetKeyValue(aKey.KeyName(), aValue.data(), static_cast<uint16_t>(aValue.size())); 37 : } 38 : 39 71 : CHIP_ERROR DefaultAttributePersistenceProvider::InternalReadValue(const StorageKeyName & aKey, EmberAfAttributeType aType, 40 : size_t aSize, MutableByteSpan & aValue) 41 : { 42 71 : VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INCORRECT_STATE); 43 : 44 71 : uint16_t size = static_cast<uint16_t>(min(aValue.size(), static_cast<size_t>(UINT16_MAX))); 45 71 : ReturnErrorOnFailure(mStorage->SyncGetKeyValue(aKey.KeyName(), aValue.data(), size)); 46 65 : EmberAfAttributeType type = aType; 47 65 : if (emberAfIsStringAttributeType(type)) 48 : { 49 : // Ensure that we've read enough bytes that we are not ending up with 50 : // un-initialized memory. Should have read length + 1 (for the length 51 : // byte). 52 0 : VerifyOrReturnError(size >= emberAfStringLength(aValue.data()) + 1, CHIP_ERROR_INCORRECT_STATE); 53 : } 54 65 : else if (emberAfIsLongStringAttributeType(type)) 55 : { 56 : // Ensure that we've read enough bytes that we are not ending up with 57 : // un-initialized memory. Should have read length + 2 (for the length 58 : // bytes). 59 0 : VerifyOrReturnError(size >= emberAfLongStringLength(aValue.data()) + 2, CHIP_ERROR_INCORRECT_STATE); 60 : } 61 : else 62 : { 63 : // Ensure we got the expected number of bytes for all other types. 64 65 : VerifyOrReturnError(size == aSize, CHIP_ERROR_INVALID_ARGUMENT); 65 : } 66 65 : aValue.reduce_size(size); 67 65 : return CHIP_NO_ERROR; 68 : } 69 : 70 0 : CHIP_ERROR DefaultAttributePersistenceProvider::WriteValue(const ConcreteAttributePath & aPath, const ByteSpan & aValue) 71 : { 72 0 : return InternalWriteValue(DefaultStorageKeyAllocator::AttributeValue(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId), 73 0 : aValue); 74 : } 75 : 76 0 : CHIP_ERROR DefaultAttributePersistenceProvider::ReadValue(const ConcreteAttributePath & aPath, 77 : const EmberAfAttributeMetadata * aMetadata, MutableByteSpan & aValue) 78 : { 79 0 : return InternalReadValue(DefaultStorageKeyAllocator::AttributeValue(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId), 80 0 : aMetadata->attributeType, aMetadata->size, aValue); 81 : } 82 : 83 65 : CHIP_ERROR DefaultAttributePersistenceProvider::SafeWriteValue(const ConcreteAttributePath & aPath, const ByteSpan & aValue) 84 : { 85 65 : return InternalWriteValue( 86 130 : DefaultStorageKeyAllocator::SafeAttributeValue(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId), aValue); 87 : } 88 : 89 71 : CHIP_ERROR DefaultAttributePersistenceProvider::SafeReadValue(const ConcreteAttributePath & aPath, MutableByteSpan & aValue) 90 : { 91 142 : return InternalReadValue( 92 142 : DefaultStorageKeyAllocator::SafeAttributeValue(aPath.mEndpointId, aPath.mClusterId, aPath.mAttributeId), 0x20, 93 71 : aValue.size(), aValue); 94 : } 95 : 96 : namespace { 97 : 98 : AttributePersistenceProvider * gAttributeSaver = nullptr; 99 : 100 : } // anonymous namespace 101 : 102 : /** 103 : * Gets the global attribute saver. 104 : * 105 : * Note: When storing cluster attributes that are managed via AttributeAccessInterface, it is recommended to 106 : * use SafeAttributePersistenceProvider. See AttributePersistenceProvider and SafeAttributePersistenceProvider 107 : * class documentation for more information. 108 : */ 109 15 : AttributePersistenceProvider * GetAttributePersistenceProvider() 110 : { 111 15 : return gAttributeSaver; 112 : } 113 : 114 1 : void SetAttributePersistenceProvider(AttributePersistenceProvider * aProvider) 115 : { 116 1 : if (aProvider != nullptr) 117 : { 118 1 : gAttributeSaver = aProvider; 119 : } 120 1 : } 121 : 122 : namespace { 123 : 124 : SafeAttributePersistenceProvider * gSafeAttributeSaver = nullptr; 125 : 126 : } // anonymous namespace 127 : 128 : /** 129 : * Gets the global attribute safe saver. 130 : */ 131 0 : SafeAttributePersistenceProvider * GetSafeAttributePersistenceProvider() 132 : { 133 0 : return gSafeAttributeSaver; 134 : } 135 : 136 1 : void SetSafeAttributePersistenceProvider(SafeAttributePersistenceProvider * aProvider) 137 : { 138 1 : if (aProvider != nullptr) 139 : { 140 1 : gSafeAttributeSaver = aProvider; 141 : } 142 1 : } 143 : 144 : } // namespace app 145 : } // namespace chip