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