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