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 "softbus_conn_ble_trans.h"
17
18 #include "securec.h"
19
20 #include <arpa/inet.h>
21 #include "conn_log.h"
22 #include "softbus_adapter_mem.h"
23 #include "softbus_adapter_timer.h"
24 #include "softbus_conn_ble_connection.h"
25 #include "softbus_conn_ble_manager.h"
26 #include "softbus_conn_ble_send_queue.h"
27 #include "softbus_conn_common.h"
28 #include "softbus_datahead_transform.h"
29 #include "softbus_def.h"
30 #include "softbus_conn_flow_control.h"
31
32 static const int32_t MTU_HEADER_SIZE = 3;
33 static const size_t BLE_TRANS_HEADER_SIZE = sizeof(BleTransHeader);
34
35 static ConnBleTransEventListener g_transEventListener = { 0 };
36 static struct ConnSlideWindowController *g_flowController = NULL;
37 static void *BleSendTask(void *arg);
38 static StartBleSendLPInfo g_startBleSendLPInfo = { 0 };
39
UnpackTransHeader(uint8_t * data,uint32_t dataLen,BleTransHeader * header)40 static int32_t UnpackTransHeader(uint8_t *data, uint32_t dataLen, BleTransHeader *header)
41 {
42 if (dataLen < BLE_TRANS_HEADER_SIZE) {
43 return SOFTBUS_INVALID_PARAM;
44 }
45 BleTransHeader *tmp = (BleTransHeader *)data;
46 header->seq = ntohl(tmp->seq);
47 header->size = ntohl(tmp->size);
48 header->offset = ntohl(tmp->offset);
49 header->total = ntohl(tmp->total);
50 if ((header->size != dataLen - BLE_TRANS_HEADER_SIZE) || (header->total > MAX_DATA_LEN) ||
51 (header->size > header->total) || (header->total - header->size < header->offset)) {
52 CONN_LOGW(CONN_BLE,
53 "unpack ble trans header failed, dataLen=%{public}u, total=%{public}u, currentPacketSize=%{public}u",
54 dataLen, header->total, header->size);
55 return SOFTBUS_CONN_BLE_INTERNAL_ERR;
56 }
57 return SOFTBUS_OK;
58 }
59
DiscardBuffer(ConnBleReadBuffer * buffer,bool quiet)60 void DiscardBuffer(ConnBleReadBuffer *buffer, bool quiet)
61 {
62 ConnBlePacket *it = NULL;
63 ConnBlePacket *next = NULL;
64 LIST_FOR_EACH_ENTRY_SAFE(it, next, &buffer->packets, ConnBlePacket, node) {
65 if (!quiet) {
66 CONN_LOGW(CONN_BLE, "discard packet. Seq=%{public}u, Total=%{public}u, Size=%{public}u, Offset=%{public}u",
67 it->header.seq, it->header.total, it->header.size, it->header.offset);
68 }
69 ListDelete(&it->node);
70 SoftBusFree(it->data);
71 SoftBusFree(it);
72 }
73 buffer->seq = 0;
74 buffer->total = 0;
75 buffer->received = 0;
76 }
77
ConnGattTransRecv(uint32_t connectionId,uint8_t * data,uint32_t dataLen,ConnBleReadBuffer * buffer,uint32_t * outLen)78 uint8_t *ConnGattTransRecv(
79 uint32_t connectionId, uint8_t *data, uint32_t dataLen, ConnBleReadBuffer *buffer, uint32_t *outLen)
80 {
81 CONN_CHECK_AND_RETURN_RET_LOGW(data != NULL, NULL, CONN_BLE,
82 "ble recv packet failed: invalid param, data is null, connectionId=%{public}u", connectionId);
83 CONN_CHECK_AND_RETURN_RET_LOGW(dataLen != 0, NULL, CONN_BLE,
84 "ble recv packet failed: invalid param, data len is 0, connectionId=%{public}u", connectionId);
85 CONN_CHECK_AND_RETURN_RET_LOGW(outLen != NULL, NULL, CONN_BLE,
86 "ble recv packet failed: invalid param, outLen is null, connectionId=%{public}u", connectionId);
87
88 BleTransHeader header = { 0 };
89 CONN_CHECK_AND_RETURN_RET_LOGW(UnpackTransHeader(data, dataLen, &header) == SOFTBUS_OK, NULL, CONN_BLE,
90 "unpack ble trans header failed, discard this packet, connectionId=%{public}u, dataLen=%{public}u",
91 connectionId, dataLen);
92
93 if (header.size == header.total) {
94 if (buffer->seq != 0) {
95 CONN_LOGW(CONN_BLE,
96 "there is incomple data waitting to receive, but another complete data "
97 "received this time, connId=%{public}u, packetDataLen=%{public}u, "
98 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
99 "bufferSeq=%{public}u, bufferTotal=%{public}u, bufferReceived=%{public}u",
100 connectionId, dataLen, header.seq, header.total, header.size, header.offset,
101 buffer->seq, buffer->total, buffer->received);
102 }
103 uint32_t valueLen = header.total;
104 uint8_t *value = SoftBusCalloc(sizeof(uint8_t) * valueLen);
105 CONN_CHECK_AND_RETURN_RET_LOGE(value != NULL, NULL, CONN_BLE,
106 "calloc value failed, discard this packet. connId=%{public}u, packetDataLen=%{public}u, "
107 "Seq=%{public}u, Total=%{public}u, Size=%{public}u, Offset=%{public}u",
108 connectionId, dataLen, header.seq, header.total, header.size, header.offset);
109 if (memcpy_s(value, valueLen, data + BLE_TRANS_HEADER_SIZE, header.size) != EOK) {
110 CONN_LOGE(CONN_BLE,
111 "memcpy_s value failed, discard this packet. connId=%{public}u, dataLen=%{public}u, "
112 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u",
113 connectionId, dataLen, header.seq, header.total, header.size, header.offset);
114 SoftBusFree(value);
115 return NULL;
116 }
117 CONN_LOGI(CONN_BLE,
118 "ble recv packet: receive a complete packet. "
119 "connId=%{public}u, dataLen=%{public}u, "
120 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u",
121 connectionId, dataLen, header.seq, header.total, header.size, header.offset);
122 *outLen = valueLen;
123 return value;
124 }
125
126 if (buffer->seq != 0 && (buffer->seq != header.seq || buffer->total != header.total)) {
127 CONN_LOGW(CONN_BLE,
128 "there is incomple data waitting to receive, but another incomplete data received this time or total is "
129 "difference, discard all received segmental packet. "
130 "connId=%{public}u, dataLen=%{public}u, "
131 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
132 "bufferSeq=%{public}u, bufferTotal=%{public}u, bufferReceived=%{public}u",
133 connectionId, dataLen, header.seq, header.total, header.size, header.offset, buffer->seq, buffer->total,
134 buffer->received);
135 DiscardBuffer(buffer, false);
136 }
137
138 ConnBlePacket *target = NULL;
139 ConnBlePacket *it = NULL;
140 LIST_FOR_EACH_ENTRY(it, &buffer->packets, ConnBlePacket, node) {
141 if (header.offset < it->header.offset) {
142 // mis-order packet received, we try to re-order it
143 CONN_LOGE(CONN_BLE,
144 "ble recv packet: it received an mis-order packet this time, There may be more times mis-order occured "
145 "try to re-order them. "
146 "connectionId=%{public}u, dataLen=%{public}u, "
147 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
148 "thisSeq=%{public}u, thisTotal=%{public}u, thisSize=%{public}u, thisOffset=%{public}u",
149 connectionId, dataLen, it->header.seq, it->header.total, it->header.size, it->header.offset, header.seq,
150 header.total, header.size, header.offset);
151 target = it;
152 break;
153 }
154 if (header.offset == it->header.offset) {
155 CONN_LOGE(CONN_BLE,
156 "ble recv packet: it received a duplicate packet this time, just discart this packet, "
157 "connId=%{public}u, dataLen=%{public}d, "
158 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
159 "cachedSeq=%{public}u, cachedTotal=%{public}u, cachedSize=%{public}u, cachedOffset=%{public}u, ",
160 connectionId, dataLen, header.seq, header.total, header.size, header.offset, it->header.seq,
161 it->header.total, it->header.size, it->header.offset);
162 return NULL;
163 }
164 }
165
166 ConnBlePacket *packet = SoftBusCalloc(sizeof(ConnBlePacket));
167 uint8_t *copyData = SoftBusCalloc(dataLen);
168 if (packet == NULL || copyData == NULL || memcpy_s(copyData, dataLen, data, dataLen) != EOK) {
169 CONN_LOGE(CONN_BLE,
170 "ble recv packet failed: calloc ble package or copy data failed, discard all received. "
171 "connId=%{public}u, dataLen=%{public}u, "
172 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
173 "bufferSeq=%{public}u, bufferTotal=%{public}u, bufferReceived=%{public}u",
174 connectionId, dataLen, header.seq, header.total, header.size, header.offset, buffer->seq, buffer->total,
175 buffer->received);
176 DiscardBuffer(buffer, false);
177 SoftBusFree(packet);
178 SoftBusFree(copyData);
179 return NULL;
180 }
181 ListInit(&packet->node);
182 packet->header = header;
183 // MUST NOT free copyData, as its ownship move to packet, it will be free in DiscardBuffer
184 packet->data = copyData;
185 if (target != NULL) {
186 ListAdd(target->node.prev, &packet->node);
187 } else {
188 ListTailInsert(&buffer->packets, &packet->node);
189 }
190 buffer->seq = header.seq;
191 buffer->received += header.size;
192 buffer->total = header.total;
193 if (buffer->received < buffer->total) {
194 CONN_LOGI(CONN_BLE,
195 "ble recv packet: receive a segmental packet. connId=%{public}u, dataLen=%{public}u, "
196 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u",
197 connectionId, dataLen, header.seq, header.total, header.size, header.offset);
198 return NULL;
199 }
200
201 if (buffer->received > buffer->total) {
202 CONN_LOGW(CONN_BLE,
203 "ble recv packet failed, receive data length more than expected, discard all received segmental packet"
204 "connId=%{public}u, dataLen=%{public}u, "
205 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
206 "bufferSeq=%{public}u, bufferTotal=%{public}u, bufferReceived=%{public}u",
207 connectionId, dataLen, header.seq, header.total, header.size, header.offset, buffer->seq, buffer->total,
208 buffer->received);
209 DiscardBuffer(buffer, false);
210 return NULL;
211 }
212
213 uint32_t valueLen = buffer->total;
214 uint8_t *value = SoftBusCalloc(sizeof(uint8_t) * valueLen);
215 if (value == NULL) {
216 CONN_LOGE(CONN_BLE,
217 "calloc out value failed, discard all received segmental packet. connId=%{public}u, dataLen=%{public}u, "
218 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
219 "bufferSeq=%{public}u, bufferTotal=%{public}u, bufferReceived=%{public}u",
220 connectionId, dataLen, header.seq, header.total, header.size, header.offset, buffer->seq, buffer->total,
221 buffer->received);
222 DiscardBuffer(buffer, false);
223 return NULL;
224 }
225
226 uint32_t offset = 0;
227 LIST_FOR_EACH_ENTRY(it, &buffer->packets, ConnBlePacket, node) {
228 if (it->header.offset != offset) {
229 CONN_LOGE(CONN_BLE,
230 "the packet offset is illegal, is not continous, discard all received segmental packet. "
231 "connId=%{public}u, dataLen=%{public}u, "
232 "headerSeq=%{public}u, headerTotal=%{public}u, headerSize=%{public}u, headerOffset=%{public}u, "
233 "itSeq=%{public}u, itTotal=%{public}d, itSize=%{public}d, itOffset=%{public}u",
234 connectionId, dataLen, header.seq, header.total, header.size, header.offset, it->header.seq,
235 it->header.total, it->header.size, it->header.offset);
236 DiscardBuffer(buffer, false);
237 SoftBusFree(value);
238 return NULL;
239 }
240 if (memcpy_s(value + offset, valueLen - offset, it->data + BLE_TRANS_HEADER_SIZE, it->header.size) != EOK) {
241 CONN_LOGE(CONN_BLE,
242 "memcpy_s packet to value failed, discard all received segmental packet. connId=%{public}u, "
243 "packetDataLen=%{public}u, Seq=%{public}u, Total=%{public}u, Size=%{public}u, Offset=%{public}u, "
244 "valueLen=%{public}u, currentValueOffset=%{public}u",
245 connectionId, dataLen, header.seq, header.total, header.size, header.offset, valueLen, offset);
246 DiscardBuffer(buffer, false);
247 SoftBusFree(value);
248 return NULL;
249 }
250 offset += it->header.size;
251 }
252 DiscardBuffer(buffer, true);
253 CONN_LOGI(CONN_BLE,
254 "ble recv packet: join segmental packets together. connId=%{public}u, packetDataLen=%{public}u, "
255 "Seq=%{public}u, Total=%{public}u, Size=%{public}u, Offset=%{public}u",
256 connectionId, dataLen, header.seq, header.total, header.size, header.offset);
257 *outLen = valueLen;
258 return value;
259 }
260
FreeSendNode(SendQueueNode * node)261 static void FreeSendNode(SendQueueNode *node)
262 {
263 if (node->data != NULL) {
264 SoftBusFree(node->data);
265 }
266 SoftBusFree(node);
267 }
268
ConnGattTransSend(ConnBleConnection * connection,const uint8_t * data,uint32_t dataLen,int32_t module)269 static int32_t ConnGattTransSend(ConnBleConnection *connection, const uint8_t *data, uint32_t dataLen, int32_t module)
270 {
271 const uint8_t *waitSendData = data;
272 uint32_t waitSendLen = dataLen;
273 uint32_t offset = 0;
274 const uint32_t maxPayload = connection->mtu - MTU_HEADER_SIZE - BLE_TRANS_HEADER_SIZE;
275 // the sequence field should Keep the same duaring all segmental packets
276 const uint32_t sequence = connection->sequence++;
277
278 while (waitSendLen > 0) {
279 uint32_t sendLen = waitSendLen <= maxPayload ? waitSendLen : maxPayload;
280 uint32_t amount = (uint32_t)g_flowController->apply(g_flowController, (int32_t)sendLen);
281 uint8_t *buff = (uint8_t *)SoftBusCalloc(amount + BLE_TRANS_HEADER_SIZE);
282 if (buff == NULL) {
283 return SOFTBUS_MALLOC_ERR;
284 }
285 if (memcpy_s(buff + BLE_TRANS_HEADER_SIZE, amount, waitSendData, amount) != EOK) {
286 SoftBusFree(buff);
287 return SOFTBUS_MEM_ERR;
288 }
289 BleTransHeader *header = (BleTransHeader *)buff;
290 header->total = htonl(dataLen);
291 header->size = htonl(amount);
292 header->offset = htonl(offset);
293 header->seq = htonl(sequence);
294
295 int32_t status = ConnBleSend(connection, buff, amount + BLE_TRANS_HEADER_SIZE, module);
296 CONN_LOGI(CONN_BLE,
297 "ble send packet: connId=%{public}u, module=%{public}d, "
298 "Seq=%{public}u, Total=%{public}d, Size=%{public}d, Offset=%{public}u, status=%{public}d",
299 connection->connectionId, module, sequence, dataLen, amount, offset, status);
300 if (status != SOFTBUS_OK) {
301 SoftBusFree(buff);
302 return status;
303 }
304 SoftBusFree(buff);
305 waitSendData += amount;
306 waitSendLen -= amount;
307 offset += amount;
308 }
309 return SOFTBUS_OK;
310 }
311
ConnBlePostBytesInner(uint32_t connectionId,uint8_t * data,uint32_t dataLen,int32_t pid,int32_t flag,int32_t module,int64_t seq,PostBytesFinishAction postBytesFinishAction)312 int32_t ConnBlePostBytesInner(uint32_t connectionId, uint8_t *data, uint32_t dataLen, int32_t pid, int32_t flag,
313 int32_t module, int64_t seq, PostBytesFinishAction postBytesFinishAction)
314 {
315 CONN_CHECK_AND_RETURN_RET_LOGW(data != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE,
316 "ble post bytes failed, invalid param, data is null, connId=%{public}u, pid=%{public}d, "
317 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 "",
318 connectionId, pid, dataLen, flag, module, seq);
319
320 if (dataLen == 0 || dataLen > MAX_DATA_LEN) {
321 CONN_LOGW(CONN_BLE,
322 "invalid param, data len is 0 or exceed max send length, connId=%{public}u, pid=%{public}d, "
323 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 "",
324 connectionId, pid, dataLen, flag, module, seq);
325 SoftBusFree(data);
326 return SOFTBUS_INVALID_PARAM;
327 }
328
329 ConnBleConnection *connection = ConnBleGetConnectionById(connectionId);
330 if (connection == NULL) {
331 CONN_LOGE(CONN_BLE,
332 "connection not exist, connId=%{public}u, pid=%{public}d, "
333 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 "",
334 connectionId, pid, dataLen, flag, module, seq);
335 SoftBusFree(data);
336 return SOFTBUS_CONN_BLE_CONNECTION_NOT_EXIST_ERR;
337 }
338 int32_t status = SoftBusMutexLock(&connection->lock);
339 if (status != SOFTBUS_OK) {
340 CONN_LOGE(CONN_BLE,
341 "try to lock failed, connId=%{public}u, pid=%{public}d, "
342 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 ", err=%{public}d",
343 connectionId, pid, dataLen, flag, module, seq, status);
344 ConnBleReturnConnection(&connection);
345 SoftBusFree(data);
346 return SOFTBUS_LOCK_ERR;
347 }
348 enum ConnBleConnectionState state = connection->state;
349 (void)SoftBusMutexUnlock(&connection->lock);
350 if (state != BLE_CONNECTION_STATE_EXCHANGED_BASIC_INFO && module != MODULE_CONNECTION && module != MODULE_BLE_NET) {
351 CONN_LOGE(CONN_BLE,
352 "connection is not ready, connId=%{public}u, pid=%{public}d, "
353 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64
354 ", connectionState=%{public}d",
355 connectionId, pid, dataLen, flag, module, seq, state);
356 ConnBleReturnConnection(&connection);
357 SoftBusFree(data);
358 return SOFTBUS_CONN_BLE_CONNECTION_NOT_READY_ERR;
359 }
360
361 SendQueueNode *node = (SendQueueNode *)SoftBusCalloc(sizeof(SendQueueNode));
362 if (node == NULL) {
363 CONN_LOGE(CONN_BLE,
364 "calloc send node failed, connId=%{public}u, pid=%{public}d, "
365 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 "",
366 connectionId, pid, dataLen, flag, module, seq);
367 ConnBleReturnConnection(&connection);
368 SoftBusFree(data);
369 return SOFTBUS_MALLOC_ERR;
370 }
371 node->connectionId = connectionId;
372 node->pid = pid;
373 node->flag = flag;
374 node->module = module;
375 node->seq = seq;
376 node->dataLen = dataLen;
377 node->data = data;
378 node->onPostBytesFinished = postBytesFinishAction;
379 status = ConnBleEnqueueNonBlock((const void *)node);
380 if (status != SOFTBUS_OK) {
381 CONN_LOGE(CONN_BLE,
382 "enqueue send node failed, connId=%{public}u, pid=%{public}d, "
383 "Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 ", err=%{public}d",
384 connectionId, pid, dataLen, flag, module, seq, status);
385 FreeSendNode(node);
386 ConnBleReturnConnection(&connection);
387 return status;
388 }
389 ConnBleRefreshIdleTimeout(connection);
390 CONN_LOGI(CONN_BLE,
391 "ble post bytes: "
392 "connId=%{public}u, pid=%{public}d, Len=%{public}u, Flg=%{public}d, Module=%{public}d, Seq=%{public}" PRId64 "",
393 connectionId, pid, dataLen, flag, module, seq);
394 ConnBleReturnConnection(&connection);
395
396 CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_startBleSendLPInfo.lock) == SOFTBUS_OK,
397 SOFTBUS_LOCK_ERR, CONN_BLE, "lock fail!");
398 g_startBleSendLPInfo.messagePosted = true;
399 if (!g_startBleSendLPInfo.sendTaskRunning) {
400 status = ConnStartActionAsync(NULL, BleSendTask, "BleSend_Tsk");
401 if (status != SOFTBUS_OK) {
402 CONN_LOGE(CONN_BLE, "start send task failed errno=%{public}d", status);
403 SoftBusMutexUnlock(&g_startBleSendLPInfo.lock);
404 return status;
405 }
406 g_startBleSendLPInfo.sendTaskRunning = true;
407 SoftBusMutexUnlock(&g_startBleSendLPInfo.lock);
408 CONN_LOGI(CONN_BLE, "start ble send task succ");
409 return SOFTBUS_OK;
410 }
411 SoftBusMutexUnlock(&g_startBleSendLPInfo.lock);
412 return SOFTBUS_OK;
413 }
414
BleCtrlMsgSerializeByJson(BleCtlMessageSerializationContext ctx,char ** outData,uint32_t * outDataLen)415 static int32_t BleCtrlMsgSerializeByJson(BleCtlMessageSerializationContext ctx, char **outData, uint32_t *outDataLen)
416 {
417 cJSON *json = cJSON_CreateObject();
418 if (json == NULL) {
419 return SOFTBUS_CREATE_JSON_ERR;
420 }
421 if (ctx.method == METHOD_NOTIFY_REQUEST) {
422 if (!AddNumberToJsonObject(json, CTRL_MSG_KEY_METHOD, CTRL_MSG_METHOD_NOTIFY_REQUEST) ||
423 !AddNumberToJsonObject(json, CTRL_MSG_KEY_DELTA, ctx.referenceRequest.delta) ||
424 !AddNumberToJsonObject(json, CTRL_MSG_KEY_REF_NUM, ctx.referenceRequest.referenceNumber) ||
425 !AddNumber16ToJsonObject(json, CTRL_MSG_KEY_CHALLENGE, ctx.challengeCode)) {
426 cJSON_Delete(json);
427 return SOFTBUS_CREATE_JSON_ERR;
428 }
429 } else {
430 cJSON_Delete(json);
431 return SOFTBUS_CONN_BLE_INTERNAL_ERR;
432 }
433 char *data = cJSON_PrintUnformatted(json);
434 cJSON_Delete(json);
435 if (data == NULL) {
436 return SOFTBUS_CREATE_JSON_ERR;
437 }
438 *outData = data;
439 *outDataLen = strlen(data) + 1;
440 return SOFTBUS_OK;
441 }
442
ConnBlePackCtrlMsgHeader(ConnPktHead * header,uint32_t dataLen)443 static int64_t ConnBlePackCtrlMsgHeader(ConnPktHead *header, uint32_t dataLen)
444 {
445 static int64_t ctlMsgSeqGenerator = 0;
446 int64_t seq = ctlMsgSeqGenerator++;
447
448 header->magic = MAGIC_NUMBER;
449 header->module = MODULE_CONNECTION;
450 header->seq = seq;
451 header->flag = CONN_HIGH;
452 header->len = dataLen;
453 PackConnPktHead(header);
454 return seq;
455 }
456
ConnBlePackCtlMessage(BleCtlMessageSerializationContext ctx,uint8_t ** outData,uint32_t * outDataLen)457 int64_t ConnBlePackCtlMessage(BleCtlMessageSerializationContext ctx, uint8_t **outData, uint32_t *outDataLen)
458 {
459 char *data = NULL;
460 uint32_t dataLen = 0;
461 int32_t ret = BleCtrlMsgSerializeByJson(ctx, &data, &dataLen);
462 if (ret != SOFTBUS_OK) {
463 CONN_LOGE(CONN_BLE,
464 "ble connecion pack ctl message failed: serialize json bytes failed, "
465 "connId=%{public}u, method=%{public}d", ctx.connectionId, ctx.method);
466 return ret;
467 }
468
469 uint32_t headSize = sizeof(ConnPktHead);
470 uint32_t bufLen = dataLen + headSize;
471 uint8_t *buf = (uint8_t *)SoftBusCalloc(bufLen);
472 if (buf == NULL) {
473 cJSON_free(data);
474 return SOFTBUS_MALLOC_ERR;
475 }
476 ConnPktHead *header = (ConnPktHead *)buf;
477 int64_t seq = ConnBlePackCtrlMsgHeader(header, dataLen);
478 if (memcpy_s(buf + headSize, bufLen - headSize, data, dataLen) != EOK) {
479 CONN_LOGE(CONN_BLE,
480 "ble connecion pack ctl message failed: memcpy ctl message bytes failed, "
481 "connId=%{public}u, method=%{public}d", ctx.connectionId, ctx.method);
482 cJSON_free(data);
483 SoftBusFree(buf);
484 return SOFTBUS_MEM_ERR;
485 }
486 cJSON_free(data);
487 *outData = buf;
488 *outDataLen = bufLen;
489 return seq;
490 }
491
ConnBleTransConfigPostLimit(const LimitConfiguration * configuration)492 int32_t ConnBleTransConfigPostLimit(const LimitConfiguration *configuration)
493 {
494 CONN_CHECK_AND_RETURN_RET_LOGW(
495 configuration != NULL, SOFTBUS_INVALID_PARAM, CONN_INIT, "invalid param, configuration is null");
496 CONN_CHECK_AND_RETURN_RET_LOGW(configuration->type == CONNECT_BLE, SOFTBUS_INVALID_PARAM, CONN_INIT,
497 "invalid param, not ble type, type=%{public}d", configuration->type);
498 int32_t ret = SOFTBUS_OK;
499 if (!configuration->active) {
500 ret = g_flowController->disable(g_flowController);
501 } else {
502 ret = g_flowController->enable(g_flowController, configuration->windowInMillis, configuration->quotaInBytes);
503 }
504 CONN_LOGI(CONN_BR, "config ble post limit, active=%{public}d, windows=%{public}d millis, quota=%{public}d bytes, "
505 "result=%{public}d", configuration->active, configuration->windowInMillis, configuration->quotaInBytes, ret);
506 return ret;
507 }
508
ConnCocTransRecv(uint32_t connectionId,LimitedBuffer * buffer,int32_t * outLen)509 uint8_t *ConnCocTransRecv(uint32_t connectionId, LimitedBuffer *buffer, int32_t *outLen)
510 {
511 uint32_t pktHeadLen = sizeof(ConnPktHead);
512 if (buffer->length < pktHeadLen) {
513 // not enough for ConnPktHead
514 return NULL;
515 }
516 ConnPktHead *head = (ConnPktHead *)(buffer->buffer);
517 UnpackConnPktHead(head);
518 if ((uint32_t)(head->magic) != MAGIC_NUMBER) {
519 buffer->length = 0;
520 CONN_LOGE(CONN_BLE,
521 "discard unknown data, connId=%{public}u, magicError=0x%{public}x", connectionId, head->magic);
522 return NULL;
523 }
524 if (buffer->capacity - pktHeadLen < head->len) {
525 buffer->length = 0;
526 CONN_LOGE(CONN_BLE,
527 "coc connection received unexpected data: too big, just discard, connId=%{public}u, module=%{public}d, "
528 "seq=%{public}" PRId64 ", datalen=%{public}d", connectionId, head->module, head->seq, head->len);
529 return NULL;
530 }
531 uint32_t packLen = head->len + sizeof(ConnPktHead);
532 if (buffer->length < packLen) {
533 CONN_LOGI(CONN_BLE, "coc connection received an incomplete packet continue. connId=%{public}u", connectionId);
534 return NULL;
535 }
536 uint8_t *dataCopy = SoftBusCalloc(packLen);
537 if (dataCopy == NULL) {
538 CONN_LOGE(CONN_BLE, "coc connection parse data failed: calloc failed, retry next time, connId=%{public}u, "
539 "packLen=%{public}u", connectionId, packLen);
540 return NULL;
541 }
542 if (memcpy_s(dataCopy, packLen, buffer->buffer, packLen) != EOK) {
543 CONN_LOGE(CONN_BLE, "coc connection parse data failed: memcpy_s failed, retry next time, "
544 "connId=%{public}u, packLen=%{public}u, bufferLen=%{public}u", connectionId, packLen, buffer->length);
545 SoftBusFree(dataCopy);
546 return NULL;
547 }
548
549 if (buffer->length > packLen &&
550 memmove_s(buffer->buffer, buffer->length, buffer->buffer + packLen, buffer->length - packLen) != EOK) {
551 CONN_LOGE(CONN_BLE, "coc connection parse data failed: memmove_s failed, retry next time. "
552 "connectionId=%{public}u", connectionId);
553 SoftBusFree(dataCopy);
554 return NULL;
555 }
556
557 buffer->length -= packLen;
558 if (buffer->length > 0) {
559 CONN_LOGI(CONN_BLE, "coc socket read limited buffer: leftLength=%{public}d", buffer->length);
560 }
561 *outLen = (int32_t)packLen;
562 return dataCopy;
563 }
564
ConnCocTransSend(ConnBleConnection * connection,const uint8_t * data,uint32_t dataLen,int32_t module)565 static int32_t ConnCocTransSend(ConnBleConnection *connection, const uint8_t *data, uint32_t dataLen, int32_t module)
566 {
567 uint32_t sentLen = 0;
568 while (dataLen > sentLen) {
569 uint32_t amount = (uint32_t)g_flowController->apply(g_flowController, (int32_t)(dataLen - sentLen));
570 int32_t status = ConnBleSend(connection, data + sentLen, amount, module);
571 CONN_LOGI(CONN_BLE,
572 "coc send packet: connId=%{public}u, module=%{public}d, total=%{public}u, "
573 "amount=%{public}u, sentLen=%{public}u, status=%{public}d",
574 connection->connectionId, module, dataLen, amount, sentLen, status);
575 sentLen += amount;
576 }
577 return SOFTBUS_OK;
578 }
579
BleSendTask(void * arg)580 void *BleSendTask(void *arg)
581 {
582 #define WAIT_TIME 10
583 SendQueueNode *sendNode = NULL;
584 while (true) {
585 int32_t status = ConnBleDequeueBlock((void **)(&sendNode));
586 if (status == SOFTBUS_TIMOUT && sendNode == NULL) {
587 CONN_LOGD(CONN_BLE, "ble dequeue time out err=%{public}d", status);
588 CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_startBleSendLPInfo.lock) == SOFTBUS_OK,
589 NULL, CONN_BLE, "lock fail!");
590 if (g_startBleSendLPInfo.messagePosted) {
591 CONN_LOGE(CONN_BLE, "message posted not quit");
592 g_startBleSendLPInfo.messagePosted = false;
593 SoftBusMutexUnlock(&g_startBleSendLPInfo.lock);
594 continue;
595 }
596 g_startBleSendLPInfo.sendTaskRunning = false;
597 SoftBusMutexUnlock(&g_startBleSendLPInfo.lock);
598 CONN_LOGE(CONN_BLE, "quit send loop");
599 break;
600 }
601 int32_t ret = SoftBusMutexLock(&g_startBleSendLPInfo.lock);
602 if (ret != SOFTBUS_OK) {
603 CONN_LOGE(CONN_BLE, "lock fail!");
604 FreeSendNode(sendNode);
605 sendNode = NULL;
606 return NULL;
607 }
608 g_startBleSendLPInfo.messagePosted = false;
609 SoftBusMutexUnlock(&g_startBleSendLPInfo.lock);
610 if (status != SOFTBUS_OK || sendNode == NULL) {
611 CONN_LOGW(CONN_BLE, "ble dequeue failed err=%{public}d,", status);
612 SoftBusSleepMs(WAIT_TIME);
613 continue;
614 }
615 ConnBleConnection *connection = ConnBleGetConnectionById(sendNode->connectionId);
616 if (connection == NULL) {
617 CONN_LOGE(CONN_BLE,
618 "connection is not exist, connId=%{public}u, pid=%{public}d, Len=%{public}u, Flg=%{public}d, "
619 "Module=%{public}d, Seq=%{public}" PRId64 "", sendNode->connectionId, sendNode->pid,
620 sendNode->dataLen, sendNode->flag, sendNode->module, sendNode->seq);
621 FreeSendNode(sendNode);
622 sendNode = NULL;
623 continue;
624 }
625
626 switch (connection->protocol) {
627 case BLE_GATT:
628 status = ConnGattTransSend(connection, sendNode->data, sendNode->dataLen, sendNode->module);
629 break;
630 case BLE_COC:
631 status = ConnCocTransSend(connection, sendNode->data, sendNode->dataLen, sendNode->module);
632 break;
633 default:
634 CONN_LOGE(CONN_BLE, "ble connecion trans send failed, connectionId=%{public}u, protocol=%{public}d",
635 connection->connectionId, connection->protocol);
636 }
637 ConnBleReturnConnection(&connection);
638 g_transEventListener.onPostBytesFinished(sendNode->connectionId, sendNode->dataLen, sendNode->pid,
639 sendNode->flag, sendNode->module, sendNode->seq, status);
640 if (sendNode->onPostBytesFinished != NULL) {
641 sendNode->onPostBytesFinished(sendNode->connectionId, status);
642 }
643 FreeSendNode(sendNode);
644 sendNode = NULL;
645 }
646 return NULL;
647 }
648
ConnBleInitTransModule(ConnBleTransEventListener * listener)649 int32_t ConnBleInitTransModule(ConnBleTransEventListener *listener)
650 {
651 CONN_CHECK_AND_RETURN_RET_LOGW(
652 listener != NULL, SOFTBUS_INVALID_PARAM, CONN_INIT, "init ble trans failed: invalid param, listener is null");
653 CONN_CHECK_AND_RETURN_RET_LOGW(listener->onPostBytesFinished != NULL, SOFTBUS_INVALID_PARAM, CONN_INIT,
654 "init ble trans failed: invalid param, listener onPostByteFinshed is null");
655
656 struct ConnSlideWindowController *controller = ConnSlideWindowControllerNew();
657 CONN_CHECK_AND_RETURN_RET_LOGW(controller != NULL, SOFTBUS_CONN_BLE_INTERNAL_ERR, CONN_INIT,
658 "init br trans module failed: init flow controller failed");
659
660 int32_t status = ConnBleInitSendQueue();
661 if (status != SOFTBUS_OK) {
662 CONN_LOGW(CONN_INIT, "init ble trans failed: init send queue failed, err=%{public}d", status);
663 ConnSlideWindowControllerDelete(controller);
664 return status;
665 }
666
667 status = SoftBusMutexInit(&g_startBleSendLPInfo.lock, NULL);
668 if (status != SOFTBUS_OK) {
669 CONN_LOGW(CONN_INIT, "init ble trans failed: init send lp lock failed, err=%{public}d", status);
670 ConnBleDeinitSendQueue();
671 ConnSlideWindowControllerDelete(controller);
672 return status;
673 }
674 g_transEventListener = *listener;
675 g_flowController = controller;
676 return SOFTBUS_OK;
677 }