• 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 #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;
133             twinBuffer = nullptr;
134             return nullptr;
135         }
136     }
137     twinBuffer->oringinalBytes_ = twinBuffer->bytes_;
138     twinBuffer->externalBytes_ = externalBytes_;
139     twinBuffer->totalLen_ = totalLen_;
140     twinBuffer->headerLen_ = headerLen_;
141     twinBuffer->payloadLen_ = payloadLen_;
142     twinBuffer->paddingLen_ = paddingLen_;
143     twinBuffer->isExternalStackMemory_ = isExternalStackMemory_;
144     twinBuffer->extendHeadLen_ = extendHeadLen_;
145     outErrorNo = E_OK;
146     return twinBuffer;
147 }
148 
ConvertForCrossThread()149 int SerialBuffer::ConvertForCrossThread()
150 {
151     if (totalLen_ == 0) {
152         return -E_INVALID_ARGS;
153     }
154     if (externalBytes_ == nullptr) {
155         // No associated external stack memory. Do nothing and return E_OK.
156         return E_OK;
157     }
158     // Logic guarantee all the member value: isExternalStackMemory_ is true; bytes_ is nullptr; totalLen_ is correct.
159     bytes_ = new (std::nothrow) uint8_t[totalLen_];
160     if (bytes_ == nullptr) {
161         return -E_OUT_OF_MEMORY;
162     }
163     errno_t errCode = memcpy_s(bytes_, totalLen_, externalBytes_, totalLen_);
164     if (errCode != EOK) {
165         delete[] bytes_;
166         bytes_ = nullptr;
167         return -E_SECUREC_ERROR;
168     }
169     // Reset external related info
170     externalBytes_ = nullptr;
171     isExternalStackMemory_ = false;
172     oringinalBytes_ = bytes_;
173     extendHeadLen_ = 0;
174     return E_OK;
175 }
176 
GetSize() const177 uint32_t SerialBuffer::GetSize() const
178 {
179     if (bytes_ == nullptr && externalBytes_ == nullptr) {
180         return 0;
181     }
182     return totalLen_;
183 }
184 
GetOringinalAddr() const185 uint8_t *SerialBuffer::GetOringinalAddr() const
186 {
187     return oringinalBytes_;
188 }
189 
GetWritableBytesForEntireBuffer()190 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForEntireBuffer()
191 {
192     if (bytes_ == nullptr) {
193         return std::make_pair(nullptr, 0);
194     } else {
195         return std::make_pair(bytes_, totalLen_);
196     }
197 }
198 
GetWritableBytesForEntireFrame()199 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForEntireFrame()
200 {
201     if (bytes_ == nullptr) {
202         return std::make_pair(nullptr, 0);
203     } else {
204         return std::make_pair(bytes_, totalLen_ - paddingLen_);
205     }
206 }
207 
GetWritableBytesForHeader()208 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForHeader()
209 {
210     if (bytes_ == nullptr) {
211         return std::make_pair(nullptr, 0);
212     } else {
213         return std::make_pair(bytes_, headerLen_);
214     }
215 }
216 
GetWritableBytesForPayload()217 std::pair<uint8_t *, uint32_t> SerialBuffer::GetWritableBytesForPayload()
218 {
219     if (bytes_ == nullptr) {
220         return std::make_pair(nullptr, 0);
221     } else {
222         return std::make_pair(bytes_ + headerLen_, payloadLen_);
223     }
224 }
225 
226 // For receive case, using Const Function
GetReadOnlyBytesForEntireBuffer() const227 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForEntireBuffer() const
228 {
229     if (isExternalStackMemory_) {
230         return std::make_pair(externalBytes_, totalLen_);
231     } else if (bytes_ != nullptr) {
232         return std::make_pair(bytes_, totalLen_);
233     } else {
234         return std::make_pair(nullptr, 0);
235     }
236 }
237 
GetReadOnlyBytesForEntireFrame() const238 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForEntireFrame() const
239 {
240     if (isExternalStackMemory_) {
241         return std::make_pair(externalBytes_, totalLen_ - paddingLen_);
242     } else if (bytes_ != nullptr) {
243         return std::make_pair(bytes_, totalLen_ - paddingLen_);
244     } else {
245         return std::make_pair(nullptr, 0);
246     }
247 }
248 
GetReadOnlyBytesForHeader() const249 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForHeader() const
250 {
251     if (isExternalStackMemory_) {
252         return std::make_pair(externalBytes_, headerLen_);
253     } else if (bytes_ != nullptr) {
254         return std::make_pair(bytes_, headerLen_);
255     } else {
256         return std::make_pair(nullptr, 0);
257     }
258 }
259 
GetReadOnlyBytesForPayload() const260 std::pair<const uint8_t *, uint32_t> SerialBuffer::GetReadOnlyBytesForPayload() const
261 {
262     if (isExternalStackMemory_) {
263         return std::make_pair(externalBytes_ + headerLen_, payloadLen_);
264     } else if (bytes_ != nullptr) {
265         return std::make_pair(bytes_ + headerLen_, payloadLen_);
266     } else {
267         return std::make_pair(nullptr, 0);
268     }
269 }
270 } // namespace DistributedDB
271