• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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