1 /* 2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H 17 #define DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H 18 #include <cstdint> 19 #include <map> 20 #include <memory> 21 #include <string> 22 #include <vector> 23 24 #include "api/visibility.h" 25 #include "endian_converter.h" 26 #include "parcel.h" 27 #include "securec.h" 28 29 namespace OHOS::MiscServices { 30 #pragma pack(1) 31 struct TLVHead { 32 uint16_t tag; 33 uint32_t len; 34 std::uint8_t value[0]; 35 }; 36 #pragma pack() 37 struct RawMem { 38 uintptr_t buffer; 39 size_t bufferLen; 40 // notice:Keep the parcel reference to prevent the memory in the parcel from being destructed 41 std::shared_ptr<OHOS::Parcel> parcel; 42 }; 43 44 /* 45 * Common tag definitions. 46 * Product should use after TAG_BUFF 47 **/ 48 enum COMMON_TAG : uint16_t { 49 TAG_VECTOR_ITEM = 0x0000, 50 TAG_MAP_KEY, 51 TAG_MAP_VALUE, 52 53 TAG_BUFF = 0x0100, 54 }; 55 struct API_EXPORT TLVObject { 56 public: TLVObjectTLVObject57 TLVObject() : total_(0), cursor_(0) 58 { 59 } 60 virtual bool Encode(std::vector<std::uint8_t> &buffer) = 0; 61 virtual bool Decode(const std::vector<std::uint8_t> &buffer) = 0; 62 virtual size_t Count() = 0; 63 InitTLVObject64 inline void Init(std::vector<std::uint8_t> &buffer) 65 { 66 buffer.resize(Count()); 67 total_ = buffer.size(); 68 cursor_ = 0; 69 } 70 CountTLVObject71 static inline size_t Count(bool value) 72 { 73 return sizeof(value) + sizeof(TLVHead); 74 } CountTLVObject75 static inline size_t Count(int8_t value) 76 { 77 return sizeof(value) + sizeof(TLVHead); 78 } CountTLVObject79 static inline size_t Count(int16_t value) 80 { 81 return sizeof(value) + sizeof(TLVHead); 82 } CountTLVObject83 static inline size_t Count(int32_t value) 84 { 85 return sizeof(value) + sizeof(TLVHead); 86 } CountTLVObject87 static inline size_t Count(int64_t value) 88 { 89 return sizeof(value) + sizeof(TLVHead); 90 } CountTLVObject91 static inline size_t Count(uint32_t value) 92 { 93 return sizeof(value) + sizeof(TLVHead); 94 } CountTLVObject95 static inline size_t Count(const std::string &value) 96 { 97 return value.size() + sizeof(TLVHead); 98 } CountTLVObject99 static inline size_t Count(const RawMem &value) 100 { 101 return value.bufferLen + sizeof(TLVHead); 102 } CountTLVObject103 static inline size_t Count(TLVObject &value) 104 { 105 return value.Count() + sizeof(TLVHead); 106 } 107 template<typename T> CountTLVObject108 inline size_t Count(std::shared_ptr<T> &value) 109 { 110 if (value == nullptr) { 111 return 0; 112 } 113 return Count(*value); 114 } 115 template<typename T> CountTLVObject116 inline size_t Count(std::vector<T> &value) 117 { 118 size_t expectSize = sizeof(TLVHead); 119 for (auto &item : value) { 120 expectSize += Count(item); 121 } 122 return expectSize; 123 } CountTLVObject124 static inline size_t Count(std::vector<uint8_t> &value) 125 { 126 size_t expectSize = sizeof(TLVHead); 127 expectSize += value.size(); 128 return expectSize; 129 } CountTLVObject130 static inline size_t Count(std::map<std::string, std::vector<uint8_t>> &value) 131 { 132 size_t expectSize = sizeof(TLVHead); 133 for (auto &item : value) { 134 expectSize += Count(item.first); 135 expectSize += Count(item.second); 136 } 137 return expectSize; 138 } 139 140 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, bool value); 141 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int8_t value); 142 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int16_t value); 143 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int32_t value); 144 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, int64_t value); 145 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, uint32_t value); 146 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, const std::string &value); 147 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, const RawMem &value); 148 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, TLVObject &value); 149 template<typename T> WriteTLVObject150 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::vector<T> &value) 151 { 152 if (!HasExpectBuffer(buffer, sizeof(TLVHead))) { 153 return false; 154 } 155 auto tagCursor = cursor_; 156 cursor_ += sizeof(TLVHead); 157 auto valueCursor = cursor_; 158 bool ret = WriteValue(buffer, value); 159 WriteHead(buffer, type, tagCursor, cursor_ - valueCursor); 160 return ret; 161 } 162 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::vector<uint8_t> &value); 163 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::map<std::string, std::vector<uint8_t>> &value); 164 template<typename T> WriteTLVObject165 bool Write(std::vector<std::uint8_t> &buffer, uint16_t type, std::shared_ptr<T> &value) 166 { 167 if (value == nullptr) { 168 return true; 169 } 170 return Write(buffer, type, *value); 171 } 172 bool ReadHead(const std::vector<std::uint8_t> &buffer, TLVHead &head); 173 bool ReadValue(const std::vector<std::uint8_t> &buffer, bool &value, const TLVHead &head); 174 bool ReadValue(const std::vector<std::uint8_t> &buffer, int8_t &value, const TLVHead &head); 175 bool ReadValue(const std::vector<std::uint8_t> &buffer, int16_t &value, const TLVHead &head); 176 bool ReadValue(const std::vector<std::uint8_t> &buffer, int32_t &value, const TLVHead &head); 177 bool ReadValue(const std::vector<std::uint8_t> &buffer, int64_t &value, const TLVHead &head); 178 bool ReadValue(const std::vector<std::uint8_t> &buffer, uint32_t &value, const TLVHead &head); 179 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::string &value, const TLVHead &head); 180 bool ReadValue(const std::vector<std::uint8_t> &buffer, RawMem &rawMem, const TLVHead &head); 181 bool ReadValue(const std::vector<std::uint8_t> &buffer, TLVObject &value, const TLVHead &head); 182 template<typename T> ReadValueTLVObject183 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::vector<T> &value, const TLVHead &head) 184 { 185 auto vectorEnd = cursor_ + head.len; 186 for (; cursor_ < vectorEnd;) { 187 // V: item value 188 TLVHead valueHead{}; 189 bool ret = ReadHead(buffer, valueHead); 190 T item{}; 191 ret = ret && ReadValue(buffer, item, valueHead); 192 if (!ret) { 193 return false; 194 } 195 value.push_back(item); 196 } 197 return true; 198 } 199 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::vector<uint8_t> &value, const TLVHead &head); 200 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::map<std::string, std::vector<uint8_t>> &value, 201 const TLVHead &head); 202 203 template<typename T> ReadValueTLVObject204 bool ReadValue(const std::vector<std::uint8_t> &buffer, std::shared_ptr<T> &value, const TLVHead &head) 205 { 206 value = std::make_shared<T>(); 207 if (value == nullptr) { 208 return false; 209 } 210 return ReadValue(buffer, *value, head); 211 } 212 213 protected: 214 virtual ~TLVObject() = default; SkipTLVObject215 inline bool Skip(size_t len, size_t total) 216 { 217 if (total < len || total - len < cursor_) { 218 return false; 219 } 220 cursor_ += len; 221 return true; 222 } IsEnoughTLVObject223 inline bool IsEnough() const 224 { 225 return cursor_ < total_; 226 } 227 228 size_t total_ = 0; 229 230 private: 231 bool Encode(std::vector<std::uint8_t> &buffer, size_t &cursor, size_t total); 232 bool Decode(const std::vector<std::uint8_t> &buffer, size_t &cursor, size_t total); WriteHeadTLVObject233 static inline void WriteHead(std::vector<std::uint8_t> &buffer, uint16_t type, size_t tagCursor, uint32_t len) 234 { 235 auto *tlvHead = reinterpret_cast<TLVHead *>(buffer.data() + tagCursor); 236 tlvHead->tag = HostToNet(type); 237 tlvHead->len = HostToNet(len); 238 } 239 template<typename T> WriteBasicTLVObject240 bool WriteBasic(std::vector<std::uint8_t> &buffer, uint16_t type, T value) 241 { 242 if (!HasExpectBuffer(buffer, sizeof(TLVHead) + sizeof(value))) { 243 return false; 244 } 245 auto *tlvHead = reinterpret_cast<TLVHead *>(buffer.data() + cursor_); 246 tlvHead->tag = HostToNet(type); 247 tlvHead->len = HostToNet((uint32_t)sizeof(value)); 248 auto valueBuff = HostToNet(value); 249 auto ret = memcpy_s(tlvHead->value, sizeof(value), &valueBuff, sizeof(value)); 250 if (ret != EOK) { 251 return false; 252 } 253 cursor_ += sizeof(TLVHead) + sizeof(value); 254 return true; 255 } 256 257 template<typename T> WriteValueTLVObject258 bool WriteValue(std::vector<std::uint8_t> &buffer, std::vector<T> &value) 259 { 260 // items iterator 261 bool ret = true; 262 for (T &item : value) { 263 // V:item value 264 ret = ret && Write(buffer, TAG_VECTOR_ITEM, item); 265 } 266 return ret; 267 } 268 269 template<typename T> ReadBasicValueTLVObject270 bool ReadBasicValue(const std::vector<std::uint8_t> &buffer, T &value, const TLVHead &head) 271 { 272 if (head.len != sizeof(T) || head.len == 0) { 273 return false; 274 } 275 if (!HasExpectBuffer(buffer, head.len)) { 276 return false; 277 } 278 auto ret = memcpy_s(&value, sizeof(T), buffer.data() + cursor_, sizeof(T)); 279 if (ret != EOK) { 280 return false; 281 } 282 value = NetToHost(value); 283 cursor_ += sizeof(T); 284 return true; 285 } 286 HasExpectBufferTLVObject287 inline bool HasExpectBuffer(const std::vector<std::uint8_t> &buffer, uint32_t expectLen) const 288 { 289 return buffer.size() >= cursor_ && buffer.size() - cursor_ >= expectLen; 290 } 291 292 size_t cursor_ = 0; 293 }; 294 } // namespace OHOS::MiscServices 295 #endif // DISTRIBUTEDDATAMGR_PASTEBOARD_TLV_OBJECT_H 296