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 }