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 #include "serial_buffer.h"
17 #include <new>
18 #include "communicator_type_define.h"
19 #include "db_errno.h"
20 #include "log_print.h"
21 #include "securec.h"
22
23 namespace DistributedDB {
~SerialBuffer()24 SerialBuffer::~SerialBuffer()
25 {
26 if (!isExternalStackMemory_ && oringinalBytes_ != nullptr) {
27 delete[] oringinalBytes_;
28 }
29 oringinalBytes_ = nullptr;
30 bytes_ = nullptr;
31 externalBytes_ = nullptr;
32 }
33
SetExtendHeadLength(uint32_t extendHeaderLen)34 void SerialBuffer::SetExtendHeadLength(uint32_t extendHeaderLen)
35 {
36 extendHeadLen_ = extendHeaderLen;
37 }
38
GetExtendHeadLength() const39 uint32_t SerialBuffer::GetExtendHeadLength() const
40 {
41 return extendHeadLen_;
42 }
43
44 // In case buffer be directly send out, so padding is needed
AllocBufferByPayloadLength(uint32_t inPayloadLen,uint32_t inHeaderLen)45 int SerialBuffer::AllocBufferByPayloadLength(uint32_t inPayloadLen, uint32_t inHeaderLen)
46 {
47 if (oringinalBytes_ != nullptr || bytes_ != nullptr || externalBytes_ != nullptr ||
48 BYTE_8_ALIGN(static_cast<uint64_t>(payloadLen_) + static_cast<uint64_t>(headerLen_)) > INT32_MAX) {
49 return -E_NOT_PERMIT;
50 }
51
52 payloadLen_ = inPayloadLen;
53 headerLen_ = inHeaderLen;
54 totalLen_ = BYTE_8_ALIGN(payloadLen_ + headerLen_);
55 paddingLen_ = totalLen_ - payloadLen_ - headerLen_;
56 if (totalLen_ == 0 || totalLen_ > MAX_TOTAL_LEN) {
57 return -E_INVALID_ARGS;
58 }
59 oringinalBytes_ = new (std::nothrow) uint8_t[totalLen_ + extendHeadLen_]();
60 if (oringinalBytes_ == nullptr) {
61 return -E_OUT_OF_MEMORY;
62 }
63 bytes_ = oringinalBytes_ + extendHeadLen_;
64 return E_OK;
65 }
66
67 // In case assemble fragment to frame, so no padding is needed, using frameLen as inTotalLen
AllocBufferByTotalLength(uint32_t inTotalLen,uint32_t inHeaderLen)68 int SerialBuffer::AllocBufferByTotalLength(uint32_t inTotalLen, uint32_t inHeaderLen)
69 {
70 if (bytes_ != nullptr || externalBytes_ != nullptr) {
71 return -E_NOT_PERMIT;
72 }
73 if (inTotalLen == 0 || inTotalLen > MAX_TOTAL_LEN || inTotalLen < inHeaderLen) {
74 return -E_INVALID_ARGS;
75 }
76
77 totalLen_ = inTotalLen;
78 headerLen_ = inHeaderLen;
79 payloadLen_ = totalLen_ - headerLen_;
80 paddingLen_ = 0;
81 bytes_ = new (std::nothrow) uint8_t[inTotalLen]();
82 if (bytes_ == nullptr) {
83 return -E_OUT_OF_MEMORY;
84 }
85 oringinalBytes_ = bytes_;
86 return E_OK;
87 }
88
89 // In case directly received, inTotalLen not include the padding, using frameLen as inTotalLen
SetExternalBuff(const uint8_t * buff,uint32_t inTotalLen,uint32_t inHeaderLen)90 int SerialBuffer::SetExternalBuff(const uint8_t *buff, uint32_t inTotalLen, uint32_t inHeaderLen)
91 {
92 if (bytes_ != nullptr || externalBytes_ != nullptr) {
93 return -E_NOT_PERMIT;
94 }
95 if (buff == nullptr || inTotalLen == 0 || inTotalLen > MAX_TOTAL_LEN || inTotalLen < inHeaderLen) {
96 return -E_INVALID_ARGS;
97 }
98
99 totalLen_ = inTotalLen;
100 headerLen_ = inHeaderLen;
101 payloadLen_ = totalLen_ - headerLen_;
102 paddingLen_ = 0;
103 isExternalStackMemory_ = true;
104 externalBytes_ = buff;
105 return E_OK;
106 }
107
Clone(int & outErrorNo)108 SerialBuffer *SerialBuffer::Clone(int &outErrorNo)
109 {
110 if (totalLen_ == 0) {
111 outErrorNo = -E_INVALID_ARGS;
112 return nullptr;
113 }
114 SerialBuffer *twinBuffer = new (std::nothrow) SerialBuffer();
115 if (twinBuffer == nullptr) {
116 outErrorNo = -E_OUT_OF_MEMORY;
117 return nullptr;
118 }
119 if (bytes_ == nullptr) {
120 twinBuffer->bytes_ = nullptr;
121 } else {
122 twinBuffer->bytes_ = new (std::nothrow) uint8_t[totalLen_];
123 if (twinBuffer->bytes_ == nullptr) {
124 outErrorNo = -E_OUT_OF_MEMORY;
125 delete twinBuffer;
126 twinBuffer = nullptr;
127 return nullptr;
128 }
129 errno_t errCode = memcpy_s(twinBuffer->bytes_, totalLen_, bytes_, totalLen_);
130 if (errCode != EOK) {
131 outErrorNo = -E_SECUREC_ERROR;
132 delete[] twinBuffer->bytes_;
133 twinBuffer->bytes_ = nullptr;
134 delete twinBuffer;
135 twinBuffer = nullptr;
136 return nullptr;
137 }
138 }
139 twinBuffer->oringinalBytes_ = twinBuffer->bytes_;
140 twinBuffer->externalBytes_ = externalBytes_;
141 twinBuffer->totalLen_ = totalLen_;
142 twinBuffer->headerLen_ = headerLen_;
143 twinBuffer->payloadLen_ = payloadLen_;
144 twinBuffer->paddingLen_ = paddingLen_;
145 twinBuffer->isExternalStackMemory_ = isExternalStackMemory_;
146 twinBuffer->extendHeadLen_ = extendHeadLen_;
147 outErrorNo = E_OK;
148 return twinBuffer;
149 }
150
ConvertForCrossThread()151 int SerialBuffer::ConvertForCrossThread()
152 {
153 if (totalLen_ == 0) {
154 return -E_INVALID_ARGS;
155 }
156 if (externalBytes_ == nullptr) {
157 // No associated external stack memory. Do nothing and return E_OK.
158 return E_OK;
159 }
160 // Logic guarantee all the member value: isExternalStackMemory_ is true; bytes_ is nullptr; totalLen_ is correct.
161 bytes_ = new (std::nothrow) uint8_t[totalLen_];
162 if (bytes_ == nullptr) {
163 return -E_OUT_OF_MEMORY;
164 }
165 errno_t errCode = memcpy_s(bytes_, totalLen_, externalBytes_, totalLen_);
166 if (errCode != EOK) {
167 delete[] bytes_;
168 bytes_ = nullptr;
169 return -E_SECUREC_ERROR;
170 }
171 // Reset external related info
172 externalBytes_ = nullptr;
173 isExternalStackMemory_ = false;
174 oringinalBytes_ = bytes_;
175 extendHeadLen_ = 0;
176 return E_OK;
177 }
178
GetSize() const179 uint32_t SerialBuffer::GetSize() const
180 {
181 if (bytes_ == nullptr && externalBytes_ == nullptr) {
182 return 0;
183 }
184 return totalLen_;
185 }
186
GetOringinalAddr() const187 uint8_t *SerialBuffer::GetOringinalAddr() const
188 {
189 return oringinalBytes_;
190 }
191
GetWritableBytesForEntireBuffer()192 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForEntireBuffer()
193 {
194 if (bytes_ == nullptr) {
195 return std::make_pair(nullptr, 0);
196 } else {
197 return std::make_pair(bytes_, totalLen_);
198 }
199 }
200
GetWritableBytesForEntireFrame()201 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForEntireFrame()
202 {
203 if (bytes_ == nullptr) {
204 return std::make_pair(nullptr, 0);
205 } else {
206 return std::make_pair(bytes_, totalLen_ - paddingLen_);
207 }
208 }
209
GetWritableBytesForHeader()210 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForHeader()
211 {
212 if (bytes_ == nullptr) {
213 return std::make_pair(nullptr, 0);
214 } else {
215 return std::make_pair(bytes_, headerLen_);
216 }
217 }
218
GetWritableBytesForPayload()219 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForPayload()
220 {
221 if (bytes_ == nullptr) {
222 return std::make_pair(nullptr, 0);
223 } else {
224 return std::make_pair(bytes_ + headerLen_, payloadLen_);
225 }
226 }
227
228 // For receive case, using Const Function
GetReadOnlyBytesForEntireBuffer() const229 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForEntireBuffer() const
230 {
231 if (isExternalStackMemory_) {
232 return std::make_pair(externalBytes_, totalLen_);
233 } else if (bytes_ != nullptr) {
234 return std::make_pair(bytes_, totalLen_);
235 } else {
236 return std::make_pair(nullptr, 0);
237 }
238 }
239
GetReadOnlyBytesForEntireFrame() const240 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForEntireFrame() const
241 {
242 if (isExternalStackMemory_) {
243 return std::make_pair(externalBytes_, totalLen_ - paddingLen_);
244 } else if (bytes_ != nullptr) {
245 return std::make_pair(bytes_, totalLen_ - paddingLen_);
246 } else {
247 return std::make_pair(nullptr, 0);
248 }
249 }
250
GetReadOnlyBytesForHeader() const251 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForHeader() const
252 {
253 if (isExternalStackMemory_) {
254 return std::make_pair(externalBytes_, headerLen_);
255 } else if (bytes_ != nullptr) {
256 return std::make_pair(bytes_, headerLen_);
257 } else {
258 return std::make_pair(nullptr, 0);
259 }
260 }
261
GetReadOnlyBytesForPayload() const262 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForPayload() const
263 {
264 if (isExternalStackMemory_) {
265 return std::make_pair(externalBytes_ + headerLen_, payloadLen_);
266 } else if (bytes_ != nullptr) {
267 return std::make_pair(bytes_ + headerLen_, payloadLen_);
268 } else {
269 return std::make_pair(nullptr, 0);
270 }
271 }
272 } // namespace DistributedDB
273