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 LOGE("[WriteVector] bufPtr:%d, stepLen:%llu, totalLen:%llu, parcelLen:%llu",
82 bufPtr_ != nullptr, ULL(stepLen), ULL(totalLen_), ULL(parcelLen_));
83 isError_ = true;
84 return -E_PARSE_FAIL;
85 }
86 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &len, sizeof(uint32_t));
87 if (errCode != EOK) {
88 LOGE("[ReadVector] totalLen:%llu, parcelLen:%llu", ULL(totalLen_), ULL(parcelLen_));
89 isError_ = true;
90 return -E_SECUREC_ERROR;
91 }
92 bufPtr_ += sizeof(uint32_t);
93 for (auto iter : data) {
94 *(reinterpret_cast<T *>(bufPtr_)) = HostToNet(iter);
95 bufPtr_ += sizeof(T);
96 }
97 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
98 parcelLen_ += BYTE_8_ALIGN(stepLen);
99 return errCode;
100 }
101
102 template<typename T>
ReadVector(std::vector<T> & val)103 uint32_t ReadVector(std::vector<T> &val)
104 {
105 static_assert(std::is_pod<T>::value, "type T is not pod");
106 if (IsError()) {
107 return 0;
108 }
109 if (bufPtr_ == nullptr || parcelLen_ + sizeof(uint32_t) > totalLen_ || sizeof(T) > INT32_MAX) {
110 LOGE("[ReadVector] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu",
111 bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T));
112 isError_ = true;
113 return 0;
114 }
115 uint32_t len = *(reinterpret_cast<uint32_t *>(bufPtr_));
116 len = NetToHost(len);
117 if (len > INT32_MAX) {
118 LOGE("[ReadVector] invalid length:%u", len);
119 isError_ = true;
120 return 0;
121 }
122 uint64_t stepLen = static_cast<uint64_t>(len) * sizeof(T) + sizeof(uint32_t);
123 if (stepLen > INT32_MAX || parcelLen_ + BYTE_8_ALIGN(stepLen) > totalLen_) {
124 LOGE("[ReadVector] stepLen:%llu, totalLen:%llu, parcelLen:%llu", ULL(stepLen), ULL(totalLen_),
125 ULL(parcelLen_));
126 isError_ = true;
127 return 0;
128 }
129 bufPtr_ += sizeof(uint32_t);
130 val.resize(len);
131 for (uint32_t i = 0; i < len; i++) {
132 val[i] = NetToHost(*(reinterpret_cast<T *>(bufPtr_)));
133 bufPtr_ += sizeof(T);
134 }
135 bufPtr_ += BYTE_8_ALIGN(stepLen) - stepLen;
136 parcelLen_ += BYTE_8_ALIGN(stepLen);
137 stepLen = BYTE_8_ALIGN(stepLen);
138 return static_cast<uint32_t>(stepLen);
139 }
140
141 int WriteBlob(const char *buffer, uint32_t bufLen);
142 uint32_t ReadBlob(char *buffer, uint32_t bufLen);
143 void EightByteAlign(); // Avoid reading a single data type across 8 bytes
144 static uint32_t GetBoolLen();
145 static uint32_t GetIntLen();
146 static uint32_t GetUInt8Len();
147 static uint32_t GetUInt32Len();
148 static uint32_t GetUInt64Len();
149 static uint32_t GetInt64Len();
150 static uint32_t GetDoubleLen();
151 static uint32_t GetVectorCharLen(const std::vector<uint8_t> &data);
152
153 template<typename T>
GetVectorLen(const std::vector<T> & data)154 static uint32_t GetVectorLen(const std::vector<T> &data)
155 {
156 if (data.size() > INT32_MAX || sizeof(T) > INT32_MAX) {
157 return 0;
158 }
159 uint64_t len = sizeof(uint32_t) + static_cast<uint64_t>(data.size()) * sizeof(T);
160 len = BYTE_8_ALIGN(len);
161 if (len > INT32_MAX) {
162 return 0;
163 }
164 return static_cast<uint32_t>(len);
165 }
166
167 static uint32_t GetEightByteAlign(uint32_t len);
168 static uint32_t GetStringLen(const std::string &data);
169 #ifndef OMIT_MULTI_VER
170 static uint32_t GetMultiVerCommitLen(const MultiVerCommitNode &commit);
171 static uint32_t GetMultiVerCommitsLen(const std::vector<MultiVerCommitNode> &commits);
172 #endif
173 static uint32_t GetAppendedLen();
174
175 private:
176 template<typename T>
177 int WriteInteger(T integer);
178 template<typename T>
179 uint32_t ReadInteger(T &integer);
180
181 bool isError_ = false;
182 uint8_t *buf_ = nullptr;
183 uint8_t *bufPtr_ = nullptr;
184 uint64_t parcelLen_ = 0;
185 uint64_t totalLen_ = 0;
186 };
187
188 template<typename T>
ReadInteger(T & integer)189 uint32_t Parcel::ReadInteger(T &integer)
190 {
191 if (IsError()) {
192 return 0;
193 }
194 if (bufPtr_ == nullptr || parcelLen_ + sizeof(T) > totalLen_) {
195 LOGE("[ReadInteger] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu",
196 bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T));
197 isError_ = true;
198 return 0;
199 }
200 integer = *(reinterpret_cast<T *>(bufPtr_));
201 bufPtr_ += sizeof(T);
202 parcelLen_ += sizeof(T);
203 integer = NetToHost(integer);
204 return sizeof(T);
205 }
206
207 template<typename T>
WriteInteger(T integer)208 int Parcel::WriteInteger(T integer)
209 {
210 if (IsError()) {
211 return -E_PARSE_FAIL;
212 }
213 T inData = HostToNet(integer);
214 if (parcelLen_ + sizeof(T) > totalLen_) {
215 LOGE("[WriteInteger] totalLen:%llu, parcelLen:%llu, sizeof(T):%zu", ULL(totalLen_), ULL(parcelLen_), sizeof(T));
216 isError_ = true;
217 return -E_PARSE_FAIL;
218 }
219 errno_t errCode = memcpy_s(bufPtr_, totalLen_ - parcelLen_, &inData, sizeof(T));
220 if (errCode != EOK) {
221 LOGE("[WriteInteger] bufPtr:%d, totalLen:%llu, parcelLen:%llu, sizeof(T):%zu",
222 bufPtr_ != nullptr, ULL(totalLen_), ULL(parcelLen_), sizeof(T));
223 isError_ = true;
224 return -E_SECUREC_ERROR;
225 }
226 bufPtr_ += sizeof(T);
227 parcelLen_ += sizeof(T);
228 return errCode;
229 }
230 } // namespace DistributedDB
231
232 #endif // PARCEL_H
233
234