1 /*
2 * Copyright (c) 2021 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 PARCEL_H
17 #define PARCEL_H
18
19 #include <vector>
20 #include <cstdint>
21 #include <string>
22 #include <type_traits>
23
24 #include "endian_convert.h"
25 #include "securec.h"
26 #include "macro_utils.h"
27 #include "db_errno.h"
28 #include "log_print.h"
29 #ifndef OMIT_MULTI_VER
30 #include "multi_ver_def.h"
31 #endif
32
33 namespace DistributedDB {
34 class Parcel {
35 public:
36 Parcel(uint8_t *inBuf, uint32_t length);
37 ~Parcel();
38 bool IsError() const;
39 int WriteBool(bool data);
40 uint32_t ReadBool(bool &data);
41 int WriteInt(int data);
42 uint32_t ReadInt(int &val);
43 int WriteUInt8(uint8_t data);
44 uint32_t ReadUInt8(uint8_t &val);
45 int WriteDouble(double data);
46 uint32_t ReadDouble(double &val);
47 int WriteInt64(int64_t data);
48 uint32_t ReadInt64(int64_t &val);
49 int WriteUInt32(uint32_t data);
50 uint32_t ReadUInt32(uint32_t &val);
51 int WriteUInt64(uint64_t data);
52 uint32_t ReadUInt64(uint64_t &val);
53 int WriteVectorChar(const std::vector<uint8_t> &data);
54 uint32_t ReadVectorChar(std::vector<uint8_t> &val);
55 int WriteString(const std::string &inVal);
56 uint32_t ReadString(std::string &outVal);
57 bool IsContinueRead();
58 #ifndef OMIT_MULTI_VER
59 int WriteMultiVerCommit(const MultiVerCommitNode &commit);
60 uint32_t ReadMultiVerCommit(MultiVerCommitNode &commit);
61 int WriteMultiVerCommits(const std::vector<MultiVerCommitNode> &commits);
62 uint32_t ReadMultiVerCommits(std::vector<MultiVerCommitNode> &commits);
63 #endif
64
65 template<typename T>
WriteVector(const std::vector<T> & data)66 int WriteVector(const std::vector<T> &data)
67 {
68 static_assert(std::is_pod<T>::value, "type T is not pod");
69 if (data.size() > INT32_MAX || sizeof(T) > INT32_MAX) {
70 LOGE("[WriteVector] invalid vector. vec.size:%zu, sizeof(T):%zu", data.size(), sizeof(T));
71 isError_ = true;
72 return -E_PARSE_FAIL;
73 }
74 if (IsError()) {
75 return -E_PARSE_FAIL;
76 }
77 uint32_t len = data.size();
78 uint64_t stepLen = static_cast<uint64_t>(data.size()) * sizeof(T) + sizeof(uint32_t);
79 len = HostToNet(len);
80 if (bufPtr_ == nullptr || stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_ ||
81 parcelLen_ + sizeof(uint32_t) > totalLen_) {
82 LOGE("[WriteVector] bufPtr:%d, stepLen:%llu, totalLen:%llu, parcelLen:%llu",
83 bufPtr_ != nullptr, ULL(stepLen), ULL(totalLen_), ULL(parcelLen_));
84 isError_ = true;
85 return -E_PARSE_FAIL;
86 }
87 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &len, sizeof(uint32_t));
88 if (errCode != EOK) {
89 LOGE("[ReadVector] totalLen:%llu, parcelLen:%llu", ULL(totalLen_), ULL(parcelLen_));
90 isError_ = true;
91 return -E_SECUREC_ERROR;
92 }
93 bufPtr_ += sizeof(uint32_t);
94 for (auto iter : data) {
95 *(reinterpret_cast<T *>(bufPtr_)) = HostToNet(iter);
96 bufPtr_ += sizeof(T);
97 }
98 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
99 parcelLen_ += BYTE_8_ALIGN(stepLen);
100 return errCode;
101 }
102
103 template<typename T>
ReadVector(std::vector<T> & val)104 uint32_t ReadVector(std::vector<T> &val)
105 {
106 static_assert(std::is_pod<T>::value, "type T is not pod");
107 if (IsError()) {
108 return 0;
109 }
110 if (bufPtr_ == nullptr || parcelLen_ + sizeof(uint32_t) > totalLen_ || sizeof(T) > INT32_MAX) {
111 LOGE("[ReadVector] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu",
112 bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T));
113 isError_ = true;
114 return 0;
115 }
116 uint32_t len = *(reinterpret_cast<uint32_t *>(bufPtr_));
117 len = NetToHost(len);
118 if (len > INT32_MAX) {
119 LOGE("[ReadVector] invalid length:%u", len);
120 isError_ = true;
121 return 0;
122 }
123 uint64_t stepLen = static_cast<uint64_t>(len) * sizeof(T) + sizeof(uint32_t);
124 if (stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) {
125 LOGE("[ReadVector] stepLen:%llu, totalLen:%llu, parcelLen:%llu", ULL(stepLen), ULL(totalLen_),
126 ULL(parcelLen_));
127 isError_ = true;
128 return 0;
129 }
130 bufPtr_ += sizeof(uint32_t);
131 val.resize(len);
132 for (uint32_t i = 0; i < len; i++) {
133 val[i] = NetToHost(*(reinterpret_cast<T *>(bufPtr_)));
134 bufPtr_ += sizeof(T);
135 }
136 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
137 parcelLen_ += BYTE_8_ALIGN(stepLen);
138 stepLen = BYTE_8_ALIGN(stepLen);
139 return static_cast<uint32_t>(stepLen);
140 }
141
142 int WriteBlob(const char *buffer, uint32_t bufLen);
143 uint32_t ReadBlob(char *buffer, uint32_t bufLen);
144 void EightByteAlign(); // Avoid reading a single data type across 8 bytes
145 static uint32_t GetBoolLen();
146 static uint32_t GetIntLen();
147 static uint32_t GetUInt8Len();
148 static uint32_t GetUInt32Len();
149 static uint32_t GetUInt64Len();
150 static uint32_t GetInt64Len();
151 static uint32_t GetDoubleLen();
152 static uint32_t GetVectorCharLen(const std::vector<uint8_t> &data);
153
154 template<typename T>
GetVectorLen(const std::vector<T> & data)155 static uint32_t GetVectorLen(const std::vector<T> &data)
156 {
157 if (data.size() > INT32_MAX || sizeof(T) > INT32_MAX) {
158 return 0;
159 }
160 uint64_t len = sizeof(uint32_t) + static_cast<uint64_t>(data.size()) * sizeof(T);
161 len = BYTE_8_ALIGN(len);
162 if (len > INT32_MAX) {
163 return 0;
164 }
165 return static_cast<uint32_t>(len);
166 }
167
168 static uint32_t GetEightByteAlign(uint32_t len);
169 static uint32_t GetStringLen(const std::string &data);
170 #ifndef OMIT_MULTI_VER
171 static uint32_t GetMultiVerCommitLen(const MultiVerCommitNode &commit);
172 static uint32_t GetMultiVerCommitsLen(const std::vector<MultiVerCommitNode> &commits);
173 #endif
174 static uint32_t GetAppendedLen();
175
176 private:
177 template<typename T>
178 int WriteInteger(T integer);
179 template<typename T>
180 uint32_t ReadInteger(T &integer);
181
182 bool isError_ = false;
183 uint8_t *buf_ = nullptr;
184 uint8_t *bufPtr_ = nullptr;
185 uint64_t parcelLen_ = 0;
186 uint64_t totalLen_ = 0;
187 };
188
189 template<typename T>
ReadInteger(T & integer)190 uint32_t Parcel::ReadInteger(T &integer)
191 {
192 if (IsError()) {
193 return 0;
194 }
195 if (bufPtr_ == nullptr || parcelLen_ + sizeof(T) > totalLen_) {
196 LOGE("[ReadInteger] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu",
197 bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T));
198 isError_ = true;
199 return 0;
200 }
201 integer = *(reinterpret_cast<T *>(bufPtr_));
202 bufPtr_ += sizeof(T);
203 parcelLen_ += sizeof(T);
204 integer = NetToHost(integer);
205 return sizeof(T);
206 }
207
208 template<typename T>
WriteInteger(T integer)209 int Parcel::WriteInteger(T integer)
210 {
211 if (IsError()) {
212 return -E_PARSE_FAIL;
213 }
214 T inData = HostToNet(integer);
215 if (parcelLen_ + sizeof(T) > totalLen_) {
216 LOGE("[WriteInteger] totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", ULL(totalLen_), ULL(parcelLen_), sizeof(T));
217 isError_ = true;
218 return -E_PARSE_FAIL;
219 }
220 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &inData, sizeof(T));
221 if (errCode != EOK) {
222 LOGE("[WriteInteger] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu",
223 bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T));
224 isError_ = true;
225 return -E_SECUREC_ERROR;
226 }
227 bufPtr_ += sizeof(T);
228 parcelLen_ += sizeof(T);
229 return errCode;
230 }
231 } // namespace DistributedDB
232
233 #endif // PARCEL_H
234
235