From a8a84f1738ccb012f2438617802443d4455b726e Mon Sep 17 00:00:00 2001 From: wufengshan Date: Fri, 9 May 2025 10:57:49 +0800 Subject: [PATCH] add general connection Signed-off-by: wufengshan --- .../common/softbus_adapter_bt_common.c | 26 + .../softbus_adapter_bt_common_virtual.c | 8 + .../include/softbus_adapter_bt_common.h | 2 + core/common/include/softbus_def.h | 1 + .../ble/include/softbus_conn_ble_connection.h | 3 + .../ble/src/softbus_conn_ble_connection.c | 14 + .../ble/src/softbus_conn_ble_virtual.c | 11 + core/connection/conn.gni | 19 +- .../connection/general/general_connection.gni | 28 + .../general/softbus_conn_general_connection.c | 1253 +++++++++++++++++ .../general/softbus_conn_general_connection.h | 97 ++ .../general/softbus_conn_general_negoation.c | 143 ++ .../general/softbus_conn_general_negoation.h | 71 + .../interface/softbus_conn_interface.h | 4 + core/connection/manager/softbus_conn_ipc.c | 87 ++ core/connection/manager/softbus_conn_ipc.h | 36 + .../connection/manager/softbus_conn_manager.c | 11 +- core/frame/common/src/softbus_server_frame.c | 1 + .../standard/init/src/softbus_server.cpp | 153 +- .../standard/init/src/softbus_server_stub.cpp | 18 +- ...neral_connection_server_proxy_standard.cpp | 8 +- .../service/src/general_client_connection.c | 2 +- .../standard/src/softbus_client_stub.cpp | 2 +- 23 files changed, 1977 insertions(+), 21 deletions(-) create mode 100644 core/connection/general/general_connection.gni create mode 100644 core/connection/general/softbus_conn_general_connection.c create mode 100644 core/connection/general/softbus_conn_general_connection.h create mode 100644 core/connection/general/softbus_conn_general_negoation.c create mode 100644 core/connection/general/softbus_conn_general_negoation.h create mode 100644 core/connection/manager/softbus_conn_ipc.c create mode 100644 core/connection/manager/softbus_conn_ipc.h diff --git a/adapter/common/net/bluetooth/common/softbus_adapter_bt_common.c b/adapter/common/net/bluetooth/common/softbus_adapter_bt_common.c index bbe5f7550b..688c897ae6 100644 --- a/adapter/common/net/bluetooth/common/softbus_adapter_bt_common.c +++ b/adapter/common/net/bluetooth/common/softbus_adapter_bt_common.c @@ -19,9 +19,13 @@ #include "c_header/ohos_bt_def.h" #include "c_header/ohos_bt_gap.h" +#include "c_header/ohos_bt_socket.h" + #include "comm_log.h" #include "securec.h" #include "softbus_def.h" +#include "softbus_utils.h" +#include "softbus_common.h" #include "softbus_error_code.h" #define STATE_LISTENER_MAX_NUM 20 @@ -288,6 +292,28 @@ int SoftBusSetBtName(const char *name) return SOFTBUS_COMM_BLUETOOTH_UNDERLAY_SET_NAME_ERR; } +int SoftBusGetRandomAddress(const char *addr, char *out, int tokenId) +{ + uint8_t binaryAddr[BT_ADDR_LEN] = { 0 }; + int32_t status = ConvertBtMacToBinary(addr, BT_MAC_LEN, binaryAddr, BT_ADDR_LEN); + COMM_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, status, + COMM_ADAPTER, "covert mac failed, status=%{public}d", status); + BdAddr bdAddr = {0}; + status = memcpy_s(bdAddr.addr, OHOS_BD_ADDR_LEN, (unsigned char*)binaryAddr, BT_ADDR_LEN); + COMM_CHECK_AND_RETURN_RET_LOGE(status == EOK, SOFTBUS_MEM_ERR, + COMM_ADAPTER, "memcpy failed, status=%{public}d", status); + + BdAddr randomAddr = {0}; + status = GetRamdomAddress(&bdAddr, &randomAddr, tokenId); + COMM_CHECK_AND_RETURN_RET_LOGE(status == OHOS_BT_STATUS_SUCCESS, status, + COMM_ADAPTER, "get random address failed, status=%{public}d", status); + + status = ConvertBtMacToStr(out, BT_MAC_LEN, randomAddr.addr, sizeof(randomAddr.addr)); + COMM_CHECK_AND_RETURN_RET_LOGE(status == OHOS_BT_STATUS_SUCCESS, status, + COMM_ADAPTER, "covert mac to str failed, status=%{public}d", status); + return SOFTBUS_OK; +} + void SoftBusComputeWaitBleSendDataTime(uint32_t waitMillis, SoftBusSysTime *outtime) { #define USECTONSEC 1000 diff --git a/adapter/common/net/bluetooth/common/softbus_adapter_bt_common_virtual.c b/adapter/common/net/bluetooth/common/softbus_adapter_bt_common_virtual.c index e3510d17e7..c0252a0944 100644 --- a/adapter/common/net/bluetooth/common/softbus_adapter_bt_common_virtual.c +++ b/adapter/common/net/bluetooth/common/softbus_adapter_bt_common_virtual.c @@ -61,6 +61,14 @@ int SoftBusSetBtName(const char *name) return SOFTBUS_FUNC_NOT_SUPPORT; } +int SoftBusGetRandomAddress(const char *addr, char *out, int tokenId) +{ + (void)addr; + (void)out; + (void)tokenId; + return SOFTBUS_FUNC_NOT_SUPPORT; +} + int SoftBusBtInit(void) { return SOFTBUS_OK; diff --git a/adapter/common/net/bluetooth/include/softbus_adapter_bt_common.h b/adapter/common/net/bluetooth/include/softbus_adapter_bt_common.h index 1a18a18c46..4f3fae30d9 100644 --- a/adapter/common/net/bluetooth/include/softbus_adapter_bt_common.h +++ b/adapter/common/net/bluetooth/include/softbus_adapter_bt_common.h @@ -127,6 +127,8 @@ int SoftBusRemoveBtStateListener(int listenerId); void SoftBusComputeWaitBleSendDataTime(uint32_t waitMillis, SoftBusSysTime *outtime); +int SoftBusGetRandomAddress(const char *addr, char *out, int tokenId); + int SoftBusBtInit(void); #ifdef __cplusplus diff --git a/core/common/include/softbus_def.h b/core/common/include/softbus_def.h index 8e0e99d114..bc68d2173b 100644 --- a/core/common/include/softbus_def.h +++ b/core/common/include/softbus_def.h @@ -88,6 +88,7 @@ extern "C" { #define FILE_PRIORITY_BK 0x08 #define GENERAL_SEND_DATA_MAX_LEN 1024 +#define GENERAL_NAME_SIZE_MAX 256 typedef struct { SoftBusMutex lock; diff --git a/core/connection/ble/include/softbus_conn_ble_connection.h b/core/connection/ble/include/softbus_conn_ble_connection.h index 8d2a3226b0..28d05c15d8 100644 --- a/core/connection/ble/include/softbus_conn_ble_connection.h +++ b/core/connection/ble/include/softbus_conn_ble_connection.h @@ -127,6 +127,7 @@ typedef struct { // ble Quick connection fails due to scan failures bool underlayerFastConnectFailedScanFailure; + bool isNeedDisconnect; bool isOccupied; } ConnBleConnection; @@ -190,6 +191,8 @@ int32_t ConnBleUpdateConnectionPriority(ConnBleConnection *connection, ConnectBl int32_t ConnBleSend(ConnBleConnection *connection, const uint8_t *data, uint32_t dataLen, int32_t module); // connection will be disconnected forcely when idle more than CONNECTION_IDLE_DISCONNECT_TIMEOUT_MILLIS void ConnBleRefreshIdleTimeout(ConnBleConnection *connection); +void ConnBleCancelIdleTimeout(ConnBleConnection *connection); + void ConnBleOccupy(ConnBleConnection *connection); // complement connection device id diff --git a/core/connection/ble/src/softbus_conn_ble_connection.c b/core/connection/ble/src/softbus_conn_ble_connection.c index 309de6da97..13f4a82fc2 100644 --- a/core/connection/ble/src/softbus_conn_ble_connection.c +++ b/core/connection/ble/src/softbus_conn_ble_connection.c @@ -523,10 +523,24 @@ void ConnBleRefreshIdleTimeout(ConnBleConnection *connection) { ConnRemoveMsgFromLooper( &g_bleConnectionAsyncHandler, MSG_CONNECTION_IDLE_DISCONNECT_TIMEOUT, connection->connectionId, 0, NULL); + CONN_CHECK_AND_RETURN_LOGD(connection->isNeedDisconnect, CONN_BLE, + "no need refresh idle timeout, connId=%{public}u", connection->connectionId); ConnPostMsgToLooper(&g_bleConnectionAsyncHandler, MSG_CONNECTION_IDLE_DISCONNECT_TIMEOUT, connection->connectionId, 0, NULL, CONNECTION_IDLE_DISCONNECT_TIMEOUT_MILLIS); } +void ConnBleCancelIdleTimeout(ConnBleConnection *connection) +{ + ConnRemoveMsgFromLooper( + &g_bleConnectionAsyncHandler, MSG_CONNECTION_IDLE_DISCONNECT_TIMEOUT, connection->connectionId, 0, NULL); + int32_t status = SoftBusMutexLock(&connection->lock); + CONN_CHECK_AND_RETURN_LOGW(status == SOFTBUS_OK, CONN_BLE, + "lock faild, connId=%{public}u, err=%{public}d", connection->connectionId, status); + connection->isNeedDisconnect = false; + CONN_LOGI(CONN_BLE, "cancel idle timout, connId=%{public}u", connection->connectionId); + (void)SoftBusMutexUnlock(&connection->lock); +} + void ConnBleInnerComplementDeviceId(ConnBleConnection *connection) { if (strlen(connection->udid) != 0) { diff --git a/core/connection/ble/src/softbus_conn_ble_virtual.c b/core/connection/ble/src/softbus_conn_ble_virtual.c index 664f6aa56c..4ddbf86983 100644 --- a/core/connection/ble/src/softbus_conn_ble_virtual.c +++ b/core/connection/ble/src/softbus_conn_ble_virtual.c @@ -46,3 +46,14 @@ void ConnBleReturnConnection(ConnBleConnection **connection) { (void)connection; } + +ConnBleConnection *ConnBleGetConnectionById(uint32_t connectionId) +{ + (void)connectionId; + return NULL; +} + +void ConnBleCancelIdleTimeout(ConnBleConnection *connection) +{ + (void)connection; +} \ No newline at end of file diff --git a/core/connection/conn.gni b/core/connection/conn.gni index 172ff72c52..33b04439c3 100644 --- a/core/connection/conn.gni +++ b/core/connection/conn.gni @@ -15,23 +15,30 @@ import("../../core/connection/ble/conn_ble.gni") import("../../core/connection/br/conn_br.gni") import("../../dsoftbus.gni") +import("$dsoftbus_root_path/core/connection/general/general_connection.gni") + #import("//foundation/communication/dsoftbus/core/connection/common/conn_common.gni") import("../../core/connection/tcp/conn_tcp.gni") CONN_SERVER_DEFINES = [] -conn_manager_src = ble_connection_src + br_connection_src + tcp_connection_src -conn_manager_inc = ble_connection_inc + br_connection_inc + tcp_connection_inc +conn_manager_src = ble_connection_src + br_connection_src + tcp_connection_src + + general_connection_src +conn_manager_inc = ble_connection_inc + br_connection_inc + tcp_connection_inc + + general_connection_inc conn_manager_external_deps = ble_connection_external_deps conn_manager_common_deps = [ "$dsoftbus_dfx_path:softbus_dfx" ] conn_manager_src += [ "$dsoftbus_root_path/core/connection/manager/softbus_conn_manager.c", "$dsoftbus_root_path/core/connection/manager/softbus_conn_flow_control.c", + "$dsoftbus_root_path/core/connection/manager/softbus_conn_ipc.c", ] conn_manager_inc += [ + "$dsoftbus_root_path/interfaces/kits/connection", "$dsoftbus_root_path/core/connection/manager", "$dsoftbus_root_path/core/connection/interface", "$dsoftbus_root_path/core/common/include", "$dsoftbus_root_path/core/connection/coap/include", + "$dsoftbus_root_path/core/connection/ipc/include", ] if (dsoftbus_feature_conn_tcp_comm) { CONN_SERVER_DEFINES += [ "DSOFTBUS_FEATURE_CONN_TCP_COMM" ] @@ -83,13 +90,9 @@ if (dsoftbus_feature_ex_kits) { conn_manager_inc += [ "$dsoftbus_root_path/core/connection/ipc/include" ] if (defined(ohos_lite)) { if (ohos_kernel_type == "liteos_m") { - conn_manager_src += [ - "$dsoftbus_root_path/core/connection/ipc/mini/general_connection_client_proxy.c", - ] + conn_manager_src += [ "$dsoftbus_root_path/core/connection/ipc/mini/general_connection_client_proxy.c" ] } else { - conn_manager_src += [ - "$dsoftbus_root_path/core/connection/ipc/small/general_connection_client_proxy.c", - ] + conn_manager_src += [ "$dsoftbus_root_path/core/connection/ipc/small/general_connection_client_proxy.c" ] } } else { conn_manager_src += [ diff --git a/core/connection/general/general_connection.gni b/core/connection/general/general_connection.gni new file mode 100644 index 0000000000..2c988b9984 --- /dev/null +++ b/core/connection/general/general_connection.gni @@ -0,0 +1,28 @@ +# Copyright (c) 2025 Huawei Device Co., Ltd. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import("../../../dsoftbus.gni") + +general_connection_inc = [] +general_connection_src = [] + +general_connection_inc += [ + "$dsoftbus_root_path/dfx/interface/include", + "$dsoftbus_root_path/core/connection/general", +] + +general_connection_src += [ + "$dsoftbus_root_path/core/connection/general/softbus_conn_general_connection.c", + "$dsoftbus_root_path/core/connection/general/softbus_conn_general_negoation.c", +] diff --git a/core/connection/general/softbus_conn_general_connection.c b/core/connection/general/softbus_conn_general_connection.c new file mode 100644 index 0000000000..c160387804 --- /dev/null +++ b/core/connection/general/softbus_conn_general_connection.c @@ -0,0 +1,1253 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "softbus_conn_general_connection.h" + +#include +#include +#include "securec.h" + +#include "conn_log.h" +#include "softbus_adapter_mem.h" +#include "softbus_adapter_bt_common.h" +#include "softbus_conn_ble_manager.h" +#include "softbus_conn_manager.h" +#include "bus_center_manager.h" + +#define INVALID_UNDERLAY_HANDLE (-1) +#define GENERAL_CONNECT_TIMEOUT_MILLIS (10 * 1000) +#define GENERAL_CONNECT_DISCONNECT_DELAY (100) + +#define GENERAL_PSM (128) + +#define GENERAL_PKGNAME_MAX_COUNT (10) + +static uint64_t g_seq = 0; + +enum GeneralFeatureCapability { + GENERAL_FEATURE_SUPPORT_COC = 1 +}; + +typedef struct { + SoftBusList *connections; +} GeneralManager; + +enum GeneralMgrLooperMsg { + GENERAL_MGR_MSG_MERGE_CMD, + GENERAL_MGR_MSG_CONNECT_TIMEOUT, + GENERAL_MGR_MSG_DISCONNECT_DELAY, +}; + +static void ConnReturnGeneralConnection(struct GeneralConnection **connection); +struct GeneralConnection *GetConnectionByGeneralId(uint32_t generalId); +static void ConnRemoveGeneralConnection(struct GeneralConnection *connection); +static void GeneralManagerMsgHandler(SoftBusMessage *msg); +static int GeneralCompareConnectionLooperEventFunc(const SoftBusMessage *msg, void *args); +static void MergeConnection(uint32_t generalId); +static void OnConnectTimeout(uint32_t generalId); +static void DisconnectDelay(uint32_t connectionId); + +static void OnCommConnectSucc(uint32_t requestId, uint32_t connectionId, const ConnectionInfo *info); +static void OnCommConnectFail(uint32_t requestId, int32_t reason); + +static GeneralConnectionListener g_generalConnectionListener; +static GeneralManager g_generalManager; +static GeneralNames g_names; +static SoftBusMutex g_requestIdLock; +static uint32_t g_requestId = 1; + +static ConnectResult g_result = { + .OnConnectSuccessed = OnCommConnectSucc, + .OnConnectFailed = OnCommConnectFail, +}; + +static SoftBusHandlerWrapper g_generalManagerSyncHandler = { + .handler = { + .name = (char *)"GeneralManagerAsyncHandler", + .HandleMessage = GeneralManagerMsgHandler, + // assign when initiation + .looper = NULL, + }, + .eventCompareFunc = GeneralCompareConnectionLooperEventFunc, +}; + +static int GeneralCompareConnectionLooperEventFunc(const SoftBusMessage *msg, void *args) +{ + SoftBusMessage *ctx = (SoftBusMessage *)args; + CONN_CHECK_AND_RETURN_RET_LOGE(msg->what == ctx->what, COMPARE_FAILED, CONN_BLE, "compade failed"); + switch (ctx->what) { + case GENERAL_MGR_MSG_MERGE_CMD: { + if (msg->arg1 == ctx->arg1) { + return COMPARE_SUCCESS; + } + return COMPARE_FAILED; + } + case GENERAL_MGR_MSG_CONNECT_TIMEOUT: { + if (msg->arg1 == ctx->arg1) { + return COMPARE_SUCCESS; + } + return COMPARE_FAILED; + } + case GENERAL_MGR_MSG_DISCONNECT_DELAY: { + if (msg->arg1 == ctx->arg1) { + return COMPARE_SUCCESS; + } + return COMPARE_FAILED; + } + default: + break; + } + if (ctx->arg1 != 0) { + CONN_LOGE(CONN_BLE, + "context not use, what=%{public}d, arg1=%{public}" PRIu64 ", objIsNull=%{public}d", + ctx->what, ctx->arg1, ctx->obj == NULL); + return COMPARE_FAILED; + } + return COMPARE_SUCCESS; +} + +static void GeneralManagerMsgHandler(SoftBusMessage *msg) +{ + CONN_CHECK_AND_RETURN_LOGW(msg != NULL, CONN_BLE, "msg is null"); + switch (msg->what) { + case GENERAL_MGR_MSG_MERGE_CMD: + MergeConnection((uint32_t)msg->arg1); + break; + case GENERAL_MGR_MSG_CONNECT_TIMEOUT: + OnConnectTimeout((uint32_t)msg->arg1); + break; + case GENERAL_MGR_MSG_DISCONNECT_DELAY: + DisconnectDelay((uint32_t)msg->arg1); + break; + default: + CONN_LOGW(CONN_BLE, "unexpected msg, what=%{public}d", msg->what); + break; + } +} + +static int32_t SendInner(OutData *outData, uint32_t underlayerHandle, int32_t module, int32_t pid) +{ + ConnPostData buff = {0}; + buff.seq = g_seq++; + buff.flag = CONN_HIGH; + buff.pid = pid; + + uint32_t size = ConnGetHeadSize(); + buff.len = outData->dataLen + size; + buff.buf = (char *)SoftBusCalloc(buff.len); + buff.module = module; + if (buff.buf == NULL || memcpy_s(buff.buf + size, outData->dataLen, outData->data, outData->dataLen) != EOK) { + SoftBusFree(buff.buf); + CONN_LOGE(CONN_BLE, "malloc error"); + return SOFTBUS_MEM_ERR; + } + int32_t ret = ConnPostBytes(underlayerHandle, &buff); + if (ret < 0) { + CONN_LOGE(CONN_BLE, "send fail, err=%{public}d, underlayHandle=%{public}u", ret, underlayerHandle); + } + return ret; +} + +static OutData *PackData(struct GeneralConnection *generalConnection, const uint8_t *data, uint32_t dataLen) +{ + OutData *outData = (OutData *)SoftBusCalloc(sizeof(OutData)); + CONN_CHECK_AND_RETURN_RET_LOGE(outData != NULL, NULL, CONN_BLE, "malloc outData err"); + outData->dataLen = GENERAL_CONNECTION_HEADER_SIZE + dataLen; + outData->data = (uint8_t *)SoftBusCalloc(outData->dataLen); + if (outData->data == NULL) { + CONN_LOGE(CONN_BLE, "malloc outData->data err"); + SoftBusFree(outData); + return NULL; + } + GeneralConnectionHead *header = (GeneralConnectionHead *)outData->data; + header->headLen = GENERAL_CONNECTION_HEADER_SIZE; + header->localId = generalConnection->generalId; + header->peerId = generalConnection->peerGeneralId; + header->msgType = GENERAL_CONNECTION_MSG_TYPE_NORMAL; + + if (memcpy_s(outData->data + GENERAL_CONNECTION_HEADER_SIZE, + outData->dataLen - GENERAL_CONNECTION_HEADER_SIZE, data, dataLen) != EOK) { + FreeOutData(outData); + outData = NULL; + } + return outData; +} + +static void ConnReturnGeneralConnection(struct GeneralConnection **generalConnection) +{ + CONN_CHECK_AND_RETURN_LOGE(generalConnection != NULL, CONN_BLE, "connection is null"); + CONN_CHECK_AND_RETURN_LOGE(*generalConnection != NULL, CONN_BLE, "*connection is null"); + + struct GeneralConnection *underlayer = *generalConnection; + underlayer->dereference(underlayer); + *generalConnection = NULL; +} + +struct GeneralConnection *GetConnectionByGeneralId(uint32_t generalId) +{ + int32_t ret = SoftBusMutexLock(&g_generalManager.connections->lock); + CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, NULL, CONN_BLE, "lock failed"); + struct GeneralConnection *it = NULL; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (it->generalId == generalId) { + it->reference(it); + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return it; + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return NULL; +} + +static void ConnRemoveGeneralConnection(struct GeneralConnection *generalConnection) +{ + CONN_CHECK_AND_RETURN_LOGE(generalConnection != NULL, CONN_BLE, "connection is null"); + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_generalManager.connections->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + + struct GeneralConnection *it = NULL; + bool exist = false; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (it->generalId == generalConnection->generalId) { + exist = true; + break; + } + } + if (exist) { + ListDelete(&generalConnection->node); + ConnReturnGeneralConnection(&generalConnection); + } else { + CONN_LOGW(CONN_BLE, "connection not exist, generalId=%{public}u", generalConnection->generalId); + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); +} + +struct GeneralConnection *GetGeneralConnectionByReqId(uint32_t reqId) +{ + CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_generalManager.connections->lock) == SOFTBUS_OK, NULL, CONN_BLE, + "lock failed"); + struct GeneralConnection *it = NULL; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (it->requestId == reqId) { + it->reference(it); + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return it; + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return NULL; +} + +struct GeneralConnection *GetGeneralConnectionByParam(const char *pkgName, int32_t pid) +{ + CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_generalManager.connections->lock) == SOFTBUS_OK, NULL, CONN_BLE, + "lock failed"); + struct GeneralConnection *it = NULL; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (StrCmpIgnoreCase(it->info.pkgName, pkgName) == 0 && it->info.pid == pid) { + it->reference(it); + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return it; + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return NULL; +} + +static int32_t GeneralSendResetMessage(struct GeneralConnection *generalConnection) +{ + GeneralConnectionInfo info = {0}; + info.localId = generalConnection->generalId; + info.peerId = generalConnection->peerGeneralId; + OutData *data = GeneralConnectionPackMsg(&info, GENERAL_CONNECTION_MSG_TYPE_RESET); + CONN_CHECK_AND_RETURN_RET_LOGE(data != NULL, SOFTBUS_CONN_BLE_GENERAL_PACK_ERROR, CONN_BLE, + "pack data failed, generalId=%{public}u", generalConnection->generalId); + CONN_LOGI(CONN_BLE, "send reset msg, generalId=%{public}u", generalConnection->generalId); + int32_t status = SendInner(data, generalConnection->underlayerHandle, MODULE_BLE_GENERAL, 0); + FreeOutData(data); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "send failed, generalId=%{public}u, err=%{public}d", generalConnection->generalId, status); + ConnDisconnectDevice(generalConnection->underlayerHandle); + return status; + } + if (generalConnection->isClient && + ConnPostMsgToLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_DISCONNECT_DELAY, + generalConnection->underlayerHandle, 0, NULL, GENERAL_CONNECT_DISCONNECT_DELAY) != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "post msg failed"); + return SOFTBUS_CONN_BLE_GENERAL_POST_MSG_FAILED; + } + return SOFTBUS_OK; +} + +static void ClearAllGeneralConnection(const char *pkgName, int32_t pid) +{ + CONN_LOGW(CONN_BLE, "clean up connections"); + ListNode waitNotifyDisconnect = {0}; + ListInit(&waitNotifyDisconnect); + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_generalManager.connections->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + struct GeneralConnection *it = NULL; + struct GeneralConnection *next = NULL; + LIST_FOR_EACH_ENTRY_SAFE(it, next, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (StrCmpIgnoreCase(it->info.pkgName, pkgName) == 0 && it->info.pid == pid) { + ListDelete(&it->node); + ListAdd(&waitNotifyDisconnect, &it->node); + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + + struct GeneralConnection *item = NULL; + struct GeneralConnection *nextItem = NULL; + LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &waitNotifyDisconnect, struct GeneralConnection, node) { + ListDelete(&item->node); + GeneralSendResetMessage(it); + ConnReturnGeneralConnection(&item); + } +} + +static int32_t GeneralSendMergeMessage(struct GeneralConnection *generalConnection, uint32_t updateHandle) +{ + GeneralConnectionInfo info = {0}; + info.localId = generalConnection->generalId; + info.peerId = generalConnection->peerGeneralId; + info.updateHandle = updateHandle; + OutData *data = GeneralConnectionPackMsg(&info, GENERAL_CONNECTION_MSG_TYPE_MERGE); + CONN_CHECK_AND_RETURN_RET_LOGE(data != NULL, SOFTBUS_CONN_BLE_GENERAL_PACK_ERROR, CONN_BLE, + "pack data failed, generalId=%{public}u", generalConnection->generalId); + int32_t status = SendInner(data, generalConnection->underlayerHandle, MODULE_BLE_GENERAL, 0); + FreeOutData(data); + CONN_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, SOFTBUS_CONN_BLE_GENERAL_PACK_ERROR, CONN_BLE, + "send failed, generalId=%{public}u, err=%{public}d", generalConnection->generalId, status); + return status; +} + +static int32_t GeneralSessionNegotiation( + struct GeneralConnection *generalConnection, int32_t ackStatus, GeneralConnectionMsgType type) +{ + GeneralConnectionInfo info = {0}; + if (strcpy_s(info.name, GENERAL_NAME_LEN, generalConnection->info.name) != EOK || + strcpy_s(info.bundleName, BUNDLE_NAME_MAX, generalConnection->info.bundleName) != EOK) { + CONN_LOGE(CONN_BLE, "copy address failed, generalId=%{public}u", generalConnection->generalId); + return SOFTBUS_STRCPY_ERR; + } + info.ackStatus = ackStatus; + info.localId = generalConnection->generalId; + info.peerId = generalConnection->peerGeneralId; + info.abilityBitSet = generalConnection->abilityBitSet; + OutData *data = GeneralConnectionPackMsg(&info, type); + CONN_CHECK_AND_RETURN_RET_LOGE(data != NULL, SOFTBUS_CONN_BLE_GENERAL_PACK_ERROR, CONN_BLE, + "pack data failed, generalId=%{public}u", generalConnection->generalId); + CONN_LOGI(CONN_BLE, "send session negotiation msg, generalId=%{public}u", generalConnection->generalId); + int32_t status = SendInner(data, generalConnection->underlayerHandle, MODULE_BLE_GENERAL, 0); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "send failed, generalId=%{public}u, err=%{public}d", generalConnection->generalId, status); + } + FreeOutData(data); + return status; +} + +static int32_t StartConnConnectDevice(const char *addr, + BleProtocolType protocol, ConnectResult *result, uint32_t requestId) +{ + ConnectOption option = { + .type = CONNECT_BLE, + .bleOption.protocol = protocol, + .bleOption.fastestConnectEnable = true, + .bleOption.psm = GENERAL_PSM, + }; + if (strcpy_s(option.bleOption.bleMac, BT_MAC_LEN, addr) != EOK) { + CONN_LOGE(CONN_BLE, "copy mac failed"); + return SOFTBUS_STRCPY_ERR; + } + int32_t status = ConnConnectDevice(&option, requestId, result); + CONN_LOGI(CONN_BLE, "connect device, status=%{public}d, requestId=%{public}d", status, g_requestId); + return status; +} + +static int32_t SetConnectionDeviceId(struct GeneralConnection *generalConnection) +{ + ConnBleConnection *bleConnection = ConnBleGetConnectionById(generalConnection->underlayerHandle); + CONN_CHECK_AND_RETURN_RET_LOGE(bleConnection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "can not get ble connection, generalId=%{public}u, underlayerHandle=%{public}u", + generalConnection->generalId, generalConnection->underlayerHandle); + ConnBleCancelIdleTimeout(bleConnection); + ConnBleFeatureBitSet featureBitSet = bleConnection->featureBitSet; + bool isSupportNetWorkIdExchange = + (featureBitSet & (1 << BLE_FEATURE_SUPPORT_SUPPORT_NETWORKID_BASICINFO_EXCAHNGE)) != 0; + generalConnection->isSupportNetWorkIdExchange = (bleConnection->protocol == BLE_COC || isSupportNetWorkIdExchange); + int32_t ret = EOK; + if (generalConnection->isSupportNetWorkIdExchange) { + ret = memcpy_s(generalConnection->networkId, NETWORK_ID_BUF_LEN, bleConnection->networkId, NETWORK_ID_BUF_LEN); + } else { + ret = memcpy_s(generalConnection->udid, UDID_BUF_LEN, bleConnection->udid, UDID_BUF_LEN); + } + if (ret != EOK) { + CONN_LOGE(CONN_BLE, "server copy networkId failed, generalId=%{public}u", generalConnection->generalId); + } + ret = memcpy_s(generalConnection->addr, BT_MAC_LEN, bleConnection->addr, BT_MAC_LEN); + ConnBleReturnConnection(&bleConnection); + CONN_CHECK_AND_RETURN_RET_LOGE(ret == EOK, SOFTBUS_MEM_ERR, CONN_BLE, + "copy mac failed, err=%{public}d", ret); + return SOFTBUS_OK; +} + +static void OnCommConnectSucc(uint32_t requestId, uint32_t connectionId, const ConnectionInfo *info) +{ + struct GeneralConnection *generalConnection = GetGeneralConnectionByReqId(requestId); + CONN_CHECK_AND_RETURN_LOGE(generalConnection != NULL, CONN_BLE, "get connection failed"); + int32_t status = SOFTBUS_OK; + do { + if (SoftBusMutexLock(&generalConnection->lock) != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "lock failed, generalId=%{public}u", generalConnection->generalId); + status = SOFTBUS_LOCK_ERR; + break; + } + generalConnection->underlayerHandle = connectionId; + (void)SoftBusMutexUnlock(&generalConnection->lock); + status = SetConnectionDeviceId(generalConnection); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, + "can not get deviceId, generalId=%{public}u, underlayerHandle=%{public}u, err=%{public}d", + generalConnection->generalId, connectionId, status); + break; + } + CONN_LOGI(CONN_BLE, + "on connect succ, begin handshake, generalId=%{public}u, underlayerHandle=%{public}u", + generalConnection->generalId, connectionId); + status = GeneralSessionNegotiation(generalConnection, 0, GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE); + } while (false); + if (status != SOFTBUS_OK) { + ConnRemoveMsgFromLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_CONNECT_TIMEOUT, + generalConnection->generalId, 0, NULL); + g_generalConnectionListener.onConnectFailed(&generalConnection->info, + generalConnection->generalId, status); + ConnDisconnectDevice(generalConnection->underlayerHandle); + ConnRemoveGeneralConnection(generalConnection); + } + ConnReturnGeneralConnection(&generalConnection); +} + +static uint32_t GenerateRequestId(void) +{ + int32_t ret = SoftBusMutexLock(&g_requestIdLock); + CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, g_requestId, CONN_BLE, "lock failed"); + uint32_t reqId = g_requestId++; + (void)SoftBusMutexUnlock(&g_requestIdLock); + return reqId; +} + +static void OnCommConnectFail(uint32_t requestId, int32_t reason) +{ + struct GeneralConnection *connection = GetGeneralConnectionByReqId(requestId); + CONN_CHECK_AND_RETURN_LOGE(connection != NULL, CONN_BLE, "get connection failed"); + CONN_LOGE(CONN_BLE, + "on connect failed, generalId=%{public}u, reason=%{public}d", + connection->generalId, reason); + ConnRemoveMsgFromLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_CONNECT_TIMEOUT, + connection->generalId, 0, NULL); + if (connection->protocol == BLE_GATT) { + g_generalConnectionListener.onConnectFailed(&connection->info, connection->generalId, reason); + ConnRemoveGeneralConnection(connection); + ConnReturnGeneralConnection(&connection); + return; + } + if (connection->protocol == BLE_COC) { + CONN_LOGI(CONN_BLE, + "connect failed, try to connect gatt, generalId=%{public}u", connection->generalId); + int32_t status = SoftBusMutexLock(&connection->lock); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "lock failed, error=%{public}d", status); + g_generalConnectionListener.onConnectFailed(&connection->info, connection->generalId, status); + ConnRemoveGeneralConnection(connection); + ConnReturnGeneralConnection(&connection); + return; + } + connection->protocol = BLE_GATT; + connection->requestId = GenerateRequestId(); + (void)SoftBusMutexUnlock(&connection->lock); + status = StartConnConnectDevice(connection->addr, BLE_GATT, &g_result, connection->requestId); + if (status != SOFTBUS_OK) { + g_generalConnectionListener.onConnectFailed(&connection->info, connection->generalId, status); + ConnRemoveGeneralConnection(connection); + ConnReturnGeneralConnection(&connection); + return; + } + } + ConnReturnGeneralConnection(&connection); +} + +static void UpdateConnectionState(struct GeneralConnection *generalConnection, + enum GeneralConnState expectedState, enum GeneralConnState nextState) +{ + int32_t status = SoftBusMutexLock(&generalConnection->lock); + CONN_CHECK_AND_RETURN_LOGE(status == SOFTBUS_OK, CONN_BLE, "lock failed"); + if (generalConnection->state != expectedState) { + CONN_LOGW(CONN_BLE, + "unexpected state, actualState=%{public}d, expectedState=%{public}d, nextState=%{public}d", + generalConnection->state, expectedState, nextState); + (void)SoftBusMutexUnlock(&generalConnection->lock); + return; + } + generalConnection->state = nextState; + (void)SoftBusMutexUnlock(&generalConnection->lock); +} + +static uint32_t AllocateGeneralIdUnsafe(void) +{ + static uint16_t nextId = 0; + uint32_t generalId = (CONNECT_BLE_GENERAL << CONNECT_TYPE_SHIFT) + (++nextId); + struct GeneralConnection *it = NULL; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (generalId == it->generalId) { + return 0; + } + } + return generalId; +} + +static bool FindInfoFromServer(GeneralConnectionInfo *info, struct GeneralConnection *generalConnection) +{ + int32_t status = SoftBusMutexLock(&g_names.names->lock); + CONN_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, false, CONN_BLE, "lock failed"); + + Name *it = NULL; + bool found = false; + LIST_FOR_EACH_ENTRY(it, &g_names.names->list, Name, node) { + if (StrCmpIgnoreCase(it->info.name, info->name) == 0 && + StrCmpIgnoreCase(it->info.bundleName, info->bundleName) == 0) { + found = true; + break; + } + } + (void)SoftBusMutexUnlock(&g_names.names->lock); + if (!found) { + return false; + } + status = SoftBusMutexLock(&generalConnection->lock); + CONN_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, false, CONN_BLE, "lock failed"); + if (strcpy_s(generalConnection->info.name, GENERAL_NAME_LEN, it->info.name) != EOK || + strcpy_s(generalConnection->info.pkgName, PKG_NAME_SIZE_MAX, it->info.pkgName) != EOK || + strcpy_s(generalConnection->info.bundleName, BUNDLE_NAME_MAX, it->info.bundleName) != EOK) { + CONN_LOGE(CONN_BLE, "copy failed"); + (void)SoftBusMutexUnlock(&generalConnection->lock); + return false; + } + generalConnection->info.pid = it->info.pid; + (void)SoftBusMutexUnlock(&generalConnection->lock); + return true; +} + +static void OnReuseConnectSucc(uint32_t requestId, uint32_t connectionId, const ConnectionInfo *info) +{ + (void)requestId; + (void)connectionId; + (void)info; +} + +static void OnReuseConnectFail(uint32_t requestId, int32_t reason) +{ + (void)requestId; + (void)reason; +} + +static bool IsLocalStartMerge(struct GeneralConnection *generalConnection) +{ + int32_t status = SoftBusMutexLock(&generalConnection->lock); + CONN_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, false, CONN_BLE, "lock failed"); + bool isSupportNetWorkIdExchange = generalConnection->isSupportNetWorkIdExchange; + (void)SoftBusMutexUnlock(&generalConnection->lock); + + char localUdid[UDID_BUF_LEN] = {0}; + char localNetworkId[NETWORK_ID_BUF_LEN] = {0}; + status = isSupportNetWorkIdExchange ? + LnnGetLocalStrInfo(STRING_KEY_NETWORKID, localNetworkId, NETWORK_ID_BUF_LEN) : + LnnGetLocalStrInfo(STRING_KEY_DEV_UDID, localUdid, UDID_BUF_LEN); + CONN_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, false, + CONN_BLE, "get local str info failed, error=%{public}d", status); + return isSupportNetWorkIdExchange ? (strcmp(localNetworkId, generalConnection->networkId) > 0): + (strcmp(localUdid, generalConnection->udid) > 0); +} + +static void MergeConnectionInner(struct GeneralConnection *out, + struct GeneralConnection *generalConnection) +{ + CONN_LOGI(CONN_BLE, "outgeneralId=%{public}u, generalId=%{public}u", out->generalId, + generalConnection->generalId); + CONN_CHECK_AND_RETURN_LOGE(IsLocalStartMerge(generalConnection), CONN_BLE, "wait peer start merge"); + // merge underlayer connection need reconnect it, and wait peer disconnect + ConnectResult result = { + .OnConnectSuccessed = OnReuseConnectSucc, + .OnConnectFailed = OnReuseConnectFail, + }; + (void)StartConnConnectDevice(generalConnection->addr, generalConnection->protocol, &result, 0); + CONN_LOGI(CONN_BLE, "merge connection, before generalId=%{public}u", out->generalId); + GeneralSendMergeMessage(out, generalConnection->peerGeneralId); + int32_t status = SoftBusMutexLock(&out->lock); + CONN_CHECK_AND_RETURN_LOGE(status == SOFTBUS_OK, CONN_BLE, "lock failed"); + out->underlayerHandle = generalConnection->underlayerHandle; + (void)SoftBusMutexUnlock(&out->lock); +} + +static void DisconnectDelay(uint32_t connectionId) +{ + ConnDisconnectDevice(connectionId); +} + +static bool IsSameDevice(struct GeneralConnection *generalConnectionLf, struct GeneralConnection *generalConnectionRf) +{ + bool isSupportNetWorkIdExchange = generalConnectionLf->isSupportNetWorkIdExchange; + return isSupportNetWorkIdExchange ? + (StrCmpIgnoreCase(generalConnectionLf->networkId, generalConnectionRf->networkId) == 0): + (StrCmpIgnoreCase(generalConnectionLf->udid, generalConnectionRf->udid) == 0); +} + +static void MergeConnection(uint32_t generalId) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(generalId); + CONN_CHECK_AND_RETURN_LOGE(generalConnection != NULL, CONN_BLE, "connection is null"); + + if (SoftBusMutexLock(&g_generalManager.connections->lock) != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "try to get connection lock failed"); + ConnReturnGeneralConnection(&generalConnection); + return; + } + struct GeneralConnection *it = NULL; + struct GeneralConnection *out = NULL; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (IsSameDevice(generalConnection, it) && it->underlayerHandle != generalConnection->underlayerHandle) { + out = it; + out->reference(out); + break; + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + if (out != NULL && out->state == STATE_CONNECTED) { + MergeConnectionInner(out, generalConnection); + } + if (out != NULL) { + out->dereference(out); + } + ConnReturnGeneralConnection(&generalConnection); +} + +static void OnConnectTimeout(uint32_t generalId) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(generalId); + CONN_CHECK_AND_RETURN_LOGE(generalConnection != NULL, CONN_BLE, "connection is null"); + g_generalConnectionListener.onConnectFailed(&generalConnection->info, + generalConnection->generalId, SOFTBUS_CONN_BLE_GENERAL_CONNECT_TIMEOUT); + GeneralSendResetMessage(generalConnection); + ConnRemoveGeneralConnection(generalConnection); + ConnReturnGeneralConnection(&generalConnection); +} + +static void ConnFreeGeneralConnection(struct GeneralConnection *generalConnection) +{ + SoftBusMutexDestroy(&generalConnection->lock); + SoftBusFree(generalConnection); +} + +static void Reference(struct GeneralConnection *target) +{ + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&target->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + target->objectRc += 1; + (void)SoftBusMutexUnlock(&target->lock); +} + +static void Dereference(struct GeneralConnection *underlayer) +{ + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&underlayer->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + underlayer->objectRc -= 1; + int32_t objectRc = underlayer->objectRc; + (void)SoftBusMutexUnlock(&underlayer->lock); + if (objectRc <= 0) { + CONN_LOGI(CONN_BLE, "release connection, generalId=%{public}u", underlayer->generalId); + ConnFreeGeneralConnection(underlayer); + } +} + +static bool IsAllowSave(const char *pkgName, bool isFindServer) +{ + int32_t count = 0; + if (!isFindServer) { + CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_generalManager.connections->lock) == SOFTBUS_OK, + false, CONN_BLE, "lock failed"); + struct GeneralConnection *it = NULL; + LIST_FOR_EACH_ENTRY(it, &g_generalManager.connections->list, struct GeneralConnection, node) { + if (StrCmpIgnoreCase(it->info.pkgName, pkgName) == 0) { + count += 1; + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + } else { + CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexLock(&g_names.names->lock) == SOFTBUS_OK, + SOFTBUS_LOCK_ERR, CONN_BLE, "lock failed"); + Name *item = NULL; + LIST_FOR_EACH_ENTRY(item, &g_names.names->list, Name, node) { + if (StrCmpIgnoreCase(item->info.pkgName, pkgName) == 0) { + count += 1; + } + } + (void)SoftBusMutexUnlock(&g_names.names->lock); + } + if (count > GENERAL_PKGNAME_MAX_COUNT) { + CONN_LOGE(CONN_BLE, "create pkgName is max,not allowed"); + return false; + } + return true; +} + +static struct GeneralConnection *CreateConnection(const GeneralConnectionParam *param, const char *addr, + int32_t underlayerHandle, bool isClient, int32_t *errorCode) +{ + if (!IsAllowSave(param->pkgName, false)) { + CONN_LOGE(CONN_BLE, "add pkg name is max"); + *errorCode = SOFTBUS_CONN_BLE_GENERAL_CREATE_CLIENT_MAX; + return NULL; + } + + struct GeneralConnection *connection = (struct GeneralConnection *)SoftBusCalloc(sizeof(struct GeneralConnection)); + CONN_CHECK_AND_RETURN_RET_LOGW(connection != NULL, NULL, CONN_BLE, "calloc connection failed"); + ListInit(&connection->node); + connection->underlayerHandle = underlayerHandle; + if (strcpy_s(connection->addr, BT_MAC_LEN, addr) != EOK || + strcpy_s(connection->info.name, GENERAL_NAME_LEN, param->name) != EOK || + strcpy_s(connection->info.pkgName, PKG_NAME_SIZE_MAX, param->pkgName) != EOK || + strcpy_s(connection->info.bundleName, BUNDLE_NAME_MAX, param->bundleName) != EOK) { + CONN_LOGE(CONN_BLE, "copy failed"); + SoftBusFree(connection); + *errorCode = SOFTBUS_STRCPY_ERR; + return NULL; + } + connection->reference = Reference; + connection->dereference = Dereference; + connection->info.pid = param->pid; + if (SoftBusMutexInit(&connection->lock, NULL) != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "init lock failed"); + ConnFreeGeneralConnection(connection); + *errorCode = SOFTBUS_LOCK_ERR; + return NULL; + } + connection->protocol = BLE_COC; + connection->objectRc = 1; + connection->isClient = isClient; + connection->requestId = GenerateRequestId(); + connection->state = STATE_CONNECTING; + connection->abilityBitSet = 1 << GENERAL_FEATURE_SUPPORT_COC; + return connection; +} + +int32_t SaveConnection(struct GeneralConnection *connection) +{ + CONN_CHECK_AND_RETURN_RET_LOGW( + connection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, "invalid param, connection is null"); + int32_t ret = SoftBusMutexLock(&g_generalManager.connections->lock); + CONN_CHECK_AND_RETURN_RET_LOGE( + ret == SOFTBUS_OK, SOFTBUS_LOCK_ERR, CONN_BLE, "invalid param, connection is null"); + uint32_t generalId = 0; + do { + generalId = AllocateGeneralIdUnsafe(); + } while (generalId == 0); + connection->generalId = generalId; + connection->reference(connection); + ListAdd(&g_generalManager.connections->list, &connection->node); + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + return SOFTBUS_OK; +} + +static void UpdatePeerGeneralId(struct GeneralConnection *connection, GeneralConnectionInfo *info) +{ + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&connection->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + connection->peerGeneralId = info->peerId; + (void)SoftBusMutexUnlock(&connection->lock); +} + +static int32_t ProcessHandshakeMessage(uint32_t connectionId, GeneralConnectionInfo *info) +{ + GeneralConnectionParam param = {0}; + int32_t ret = SOFTBUS_OK; + char addr[BT_MAC_LEN] = {0}; + struct GeneralConnection *generalConnection = CreateConnection(¶m, addr, connectionId, false, &ret); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, ret, CONN_BLE, + "create connection failed"); + ret = SaveConnection(generalConnection); + if (ret != SOFTBUS_OK) { + generalConnection->dereference(generalConnection); + return ret; + } + UpdatePeerGeneralId(generalConnection, info); + CONN_LOGI(CONN_BLE, "process handshake message, peer generalId=%{public}u, local generalId=%{public}u", + generalConnection->peerGeneralId, generalConnection->generalId); + ret = SetConnectionDeviceId(generalConnection); + if (ret != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "set param failed, error=%{public}d", ret); + ConnRemoveGeneralConnection(generalConnection); + generalConnection->dereference(generalConnection); + return ret; + } + bool exit = FindInfoFromServer(info, generalConnection); + int32_t status = SOFTBUS_OK; + if (!exit) { + status = SOFTBUS_CONN_BLE_GENERAL_SERVER_NOT_OPENED; + } + ret = GeneralSessionNegotiation(generalConnection, status, GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE_ACK); + if (ret != SOFTBUS_OK || status != SOFTBUS_OK) { + GeneralSendResetMessage(generalConnection); + ConnRemoveGeneralConnection(generalConnection); + generalConnection->dereference(generalConnection); + return ret; + } + UpdateConnectionState(generalConnection, STATE_CONNECTING, STATE_CONNECTED); + CONN_LOGI(CONN_BLE, "server accept, generalId=%{public}u", generalConnection->generalId); + g_generalConnectionListener.onAcceptConnect(&generalConnection->info, generalConnection->generalId); + uint32_t generalId = generalConnection->generalId; + generalConnection->dereference(generalConnection); + CONN_CHECK_AND_RETURN_RET_LOGE(ConnPostMsgToLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_MERGE_CMD, + generalId, 0, NULL, 0) == SOFTBUS_OK, ret, CONN_BLE, + "post merge msg failed"); + return ret; +} + +static void NotifyConnectFailed(struct GeneralConnection *generalConnection, int32_t reason) +{ + if (generalConnection->state == STATE_CONNECTED) { + g_generalConnectionListener.onConnectionDisconnected(&generalConnection->info, + generalConnection->generalId, reason); + return; + } + if (generalConnection->isClient) { + g_generalConnectionListener.onConnectFailed(&generalConnection->info, + generalConnection->generalId, reason); + } +} + +static int32_t ProcessMergeMessage(uint32_t connectionId, GeneralConnectionInfo *info) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(info->localId); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "connection is null, generalId=%{public}u", info->localId); + ConnDisconnectDevice(connectionId); + struct GeneralConnection *mergedConnection = GetConnectionByGeneralId(info->updateHandle); + if (mergedConnection == NULL) { + CONN_LOGE(CONN_BLE, "can not get connection, generalId=%{public}u", info->updateHandle); + ConnReturnGeneralConnection(&generalConnection); + return SOFTBUS_INVALID_PARAM; + } + uint32_t mergedHandle = mergedConnection->underlayerHandle; + ConnReturnGeneralConnection(&mergedConnection); + int32_t ret = SoftBusMutexLock(&generalConnection->lock); + if (ret != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "locak failed, generalId=%{public}u, err=%{public}d", + generalConnection->generalId, ret); + ConnReturnGeneralConnection(&generalConnection); + return SOFTBUS_LOCK_ERR; + } + CONN_LOGI(CONN_BLE, "recv merge msg, generalId=%{public}u, before handle =%{public}u, update handle =%{public}u", + generalConnection->generalId, generalConnection->underlayerHandle, mergedHandle); + generalConnection->underlayerHandle = mergedHandle; + (void)SoftBusMutexUnlock(&generalConnection->lock); + ConnReturnGeneralConnection(&generalConnection); + return SOFTBUS_OK; +} + +static int32_t ProcessResetMessage(uint32_t connectionId, GeneralConnectionInfo *info) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(info->localId); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "connection is null, generalId=%{public}u", info->localId); + CONN_LOGI(CONN_BLE, "recv reset msg, generalId=%{public}u", generalConnection->generalId); + ConnRemoveMsgFromLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_CONNECT_TIMEOUT, + generalConnection->generalId, 0, NULL); + + NotifyConnectFailed(generalConnection, SOFTBUS_CONN_BLE_GENERAL_PEER_CONNECTION_CLOSE); + if (generalConnection->isClient) { + ConnDisconnectDevice(generalConnection->underlayerHandle); + } + ConnRemoveGeneralConnection(generalConnection); + ConnReturnGeneralConnection(&generalConnection); + return SOFTBUS_OK; +} + +static void UpdateGeneralConnectionByInfo(struct GeneralConnection *generalConnection, GeneralConnectionInfo *info) +{ + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&generalConnection->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + generalConnection->abilityBitSet = info->abilityBitSet; + generalConnection->peerGeneralId = info->peerId; + (void)SoftBusMutexUnlock(&generalConnection->lock); +} + +static int32_t ProcessHandShakeAck(GeneralConnectionInfo *info) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(info->localId); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "connection is null, generalId=%{public}u", info->peerId); + ConnRemoveMsgFromLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_CONNECT_TIMEOUT, + generalConnection->generalId, 0, NULL); + if (info->ackStatus != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "hand shake failed, ackStatus=%{public}d, generalId=%{public}u", + info->ackStatus, generalConnection->generalId); + ConnReturnGeneralConnection(&generalConnection); + g_generalConnectionListener.onConnectFailed(&generalConnection->info, + generalConnection->generalId, info->ackStatus); + return info->ackStatus; + } + UpdateGeneralConnectionByInfo(generalConnection, info); + UpdateConnectionState(generalConnection, STATE_CONNECTING, STATE_CONNECTED); + CONN_LOGI(CONN_BLE, "recv handshake ack, ackStatus=%{public}d, report connect success, generalId=%{public}u", + info->ackStatus, generalConnection->generalId); + g_generalConnectionListener.onConnectSuccess(&generalConnection->info, generalConnection->generalId); + if (ConnPostMsgToLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_MERGE_CMD, + generalConnection->generalId, 0, NULL, 0) != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "post merage msg failed"); + } + ConnReturnGeneralConnection(&generalConnection); + return SOFTBUS_OK; +} + +static int32_t ProcessInnerMessageByType( + uint32_t connectionId, GeneralConnectionMsgType msgType, GeneralConnectionInfo *info) +{ + switch (msgType) { + case GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE: + return ProcessHandshakeMessage(connectionId, info); + case GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE_ACK: + return ProcessHandShakeAck(info); + case GENERAL_CONNECTION_MSG_TYPE_MERGE: + return ProcessMergeMessage(connectionId, info); + case GENERAL_CONNECTION_MSG_TYPE_RESET: + return ProcessResetMessage(connectionId, info); + default: + return SOFTBUS_CONN_BLE_GENERAL_MSG_NOT_FOUND; + } + return SOFTBUS_OK; +} + +static void OnCommConnected(uint32_t connectionId, const ConnectionInfo *info) +{ + (void)connectionId; + (void)info; +} + +static void OnCommDisconnected(uint32_t connectionId, const ConnectionInfo *info) +{ + CONN_CHECK_AND_RETURN_LOGE(SoftBusMutexLock(&g_generalManager.connections->lock) == SOFTBUS_OK, CONN_BLE, + "lock failed"); + CONN_LOGI(CONN_BLE, "on connect disconnected, connectionId=%{public}u", connectionId); + struct GeneralConnection *it = NULL; + struct GeneralConnection *next = NULL; + ListNode waitNotify = {0}; + ListInit(&waitNotify); + LIST_FOR_EACH_ENTRY_SAFE(it, next, &g_generalManager.connections->list, + struct GeneralConnection, node) { + if (it->underlayerHandle == connectionId) { + CONN_LOGI(CONN_BLE, "remove connection, generalId=%{public}u", it->generalId); + ListDelete(&it->node); + ListAdd(&waitNotify, &it->node); + } + } + (void)SoftBusMutexUnlock(&g_generalManager.connections->lock); + + struct GeneralConnection *item = NULL; + struct GeneralConnection *nextItem = NULL; + LIST_FOR_EACH_ENTRY_SAFE(item, nextItem, &waitNotify, struct GeneralConnection, node) { + ListDelete(&item->node); + NotifyConnectFailed(item, SOFTBUS_CONN_BLE_GENERAL_CONNECTION_CLOSE); + ConnReturnGeneralConnection(&item); + } +} + +static void OnCommDataReceived(uint32_t connectionId, ConnModule moduleId, int64_t seq, char *data, int32_t len) +{ + if (data == NULL || len <= 0 || moduleId != MODULE_BLE_GENERAL) { + CONN_LOGE(CONN_BLE, "invalid param, connectionId=%{public}u", connectionId); + return; + } + GeneralConnectionHead *head = (GeneralConnectionHead *)data; + GeneralConnectionMsgType msgType = head->msgType; + if (msgType >= GENERAL_CONNECTION_MSG_TYPE_MAX || len < head->headLen) { + CONN_LOGE(CONN_BLE, "invalid msgType, msgType=%{public}d, msgType=%{public}d, msgType=%{public}d", + msgType, len, head->headLen); + return; + } + GeneralConnectionInfo info = {0}; + info.peerId = head->localId; + info.localId = head->peerId; + uint32_t recvDataLen = len - head->headLen; + uint8_t *recvData = (uint8_t *)data + head->headLen; + CONN_LOGI(CONN_BLE, "handle=%{public}u" + "recv data len=%{public}d, seq=%{public}" PRId64 ", msgtype=%{public}u", info.localId, len, seq, msgType); + if (msgType == GENERAL_CONNECTION_MSG_TYPE_NORMAL) { + struct GeneralConnection *connection = GetConnectionByGeneralId(head->peerId); + CONN_CHECK_AND_RETURN_LOGE(connection != NULL, CONN_BLE, "conncetion is null"); + CONN_LOGI(CONN_BLE, "recv data generalId=%{public}u, len=%{public}d", + connection->generalId, recvDataLen); + g_generalConnectionListener.onDataReceived(&connection->info, + connection->generalId, recvData, recvDataLen); + ConnReturnGeneralConnection(&connection); + return; + } + int32_t status = GeneralConnectionUnpackMsg(recvData, recvDataLen, &info, head->msgType); + CONN_CHECK_AND_RETURN_LOGE(status == SOFTBUS_OK, CONN_BLE, "pack msg failed, handle=%{public}u, status=%{public}d", + info.localId, status); + status = ProcessInnerMessageByType(connectionId, msgType, &info); + CONN_LOGD(CONN_BLE, "process inner msg, handle=%{public}u, status=%{public}d", info.localId, status); +} + +static Name *NewNameNode(const GeneralConnectionParam *param) +{ + Name *nameNode = (Name *)SoftBusCalloc(sizeof(Name)); + CONN_CHECK_AND_RETURN_RET_LOGE(nameNode != NULL, NULL, CONN_BLE, "nameNode is null"); + ListInit(&nameNode->node); + if ((strcpy_s(nameNode->info.bundleName, BUNDLE_NAME_MAX, param->bundleName) != EOK) || + (strcpy_s(nameNode->info.name, GENERAL_NAME_LEN, param->name) != EOK) || + (strcpy_s(nameNode->info.pkgName, PKG_NAME_SIZE_MAX, param->pkgName) != EOK)) { + CONN_LOGE(CONN_BLE, "memcpy failed"); + SoftBusFree(nameNode); + return NULL; + } + nameNode->info.pid = param->pid; + return nameNode; +} + +static void FreeNameNode(Name **nameNode) +{ + SoftBusFree(*nameNode); + *nameNode = NULL; +} + +static int32_t RegisterListener(const GeneralConnectionListener *listener) +{ + CONN_CHECK_AND_RETURN_RET_LOGE(listener != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, "listener is null"); + CONN_CHECK_AND_RETURN_RET_LOGE(listener->onConnectFailed != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "listener onConnectFailed is null"); + CONN_CHECK_AND_RETURN_RET_LOGE(listener->onDataReceived != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "listener onDataReceived is null"); + CONN_CHECK_AND_RETURN_RET_LOGE(listener->onAcceptConnect != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "listener onAcceptConnect is null"); + CONN_CHECK_AND_RETURN_RET_LOGE(listener->onConnectSuccess != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "listener onConnectSuccess is null"); + CONN_CHECK_AND_RETURN_RET_LOGE(listener->onConnectionDisconnected != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "listener onConnectionDisconnected is null"); + g_generalConnectionListener = *listener; + return SOFTBUS_OK; +} + +static int32_t Connect(const GeneralConnectionParam *param, const char *addr) +{ + ConnectResult result = { + .OnConnectSuccessed = OnCommConnectSucc, + .OnConnectFailed = OnCommConnectFail, + }; + int32_t status = SOFTBUS_OK; + struct GeneralConnection *generalConnection = CreateConnection(param, addr, + INVALID_UNDERLAY_HANDLE, true, &status); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, status, CONN_BLE, + "create connection failed"); + status = SaveConnection(generalConnection); + if (status != SOFTBUS_OK) { + generalConnection->dereference(generalConnection); + return status; + } + status= StartConnConnectDevice(generalConnection->addr, BLE_COC, &result, generalConnection->requestId); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "connect failed, err=%{public}d", status); + ConnRemoveGeneralConnection(generalConnection); + generalConnection->dereference(generalConnection); + return SOFTBUS_CONN_BLE_GENERAL_CONNECT_FAILED; + } + status = ConnPostMsgToLooper(&g_generalManagerSyncHandler, GENERAL_MGR_MSG_CONNECT_TIMEOUT, + generalConnection->generalId, 0, NULL, GENERAL_CONNECT_TIMEOUT_MILLIS); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "post timeout msg failed, err=%{public}d", status); + ConnRemoveGeneralConnection(generalConnection); + generalConnection->dereference(generalConnection); + return status; + } + CONN_LOGI(CONN_BLE, "recv connect request, handle=%{public}u, requestId=%{public}u", + generalConnection->generalId, generalConnection->requestId); + uint32_t handle = generalConnection->generalId; + generalConnection->dereference(generalConnection); + return handle; +} + +static int32_t Send(uint32_t generalHandle, const uint8_t *data, uint32_t dataLen, int32_t pid) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(generalHandle); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "connection is null, generalId=%{public}u", generalHandle); + int32_t status = SoftBusMutexLock(&generalConnection->lock); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "lock failed, handle=%{public}u, err=%{public}u", + generalConnection->generalId, status); + ConnReturnGeneralConnection(&generalConnection); + return SOFTBUS_LOCK_ERR; + } + uint32_t underlayerHandle = generalConnection->underlayerHandle; + (void)SoftBusMutexUnlock(&generalConnection->lock); + + OutData *outData = PackData(generalConnection, data, dataLen); + ConnReturnGeneralConnection(&generalConnection); + CONN_CHECK_AND_RETURN_RET_LOGE(outData != NULL, SOFTBUS_MALLOC_ERR, CONN_BLE, + "outdata is null, generalId=%{public}u", generalHandle); + CONN_LOGI(CONN_BLE, "send data, handle=%{public}u, len=%{public}u", generalHandle, dataLen); + status = SendInner(outData, underlayerHandle, MODULE_BLE_GENERAL, pid); + FreeOutData(outData); + return status; +} + +static void Disconnect(uint32_t generalHandle) +{ + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(generalHandle); + CONN_CHECK_AND_RETURN_LOGE(generalConnection != NULL, CONN_BLE, + "connection is null, generalId=%{public}u", generalHandle); + CONN_LOGI(CONN_BLE, "disconnect connection, generalId=%{public}u, connectionId=%{public}u", + generalHandle, generalConnection->underlayerHandle); + GeneralSendResetMessage(generalConnection); + ConnRemoveGeneralConnection(generalConnection); + ConnReturnGeneralConnection(&generalConnection); + return; +} + +static int32_t GetPeerDeviceId(uint32_t generalHandle, char *addr, uint32_t length, uint32_t tokenId) +{ + if (length != BT_MAC_LEN) { + CONN_LOGE(CONN_BLE, "invalid param, generalId=%{public}u, len=%{public}u", generalHandle, length); + return SOFTBUS_INVALID_PARAM; + } + struct GeneralConnection *generalConnection = GetConnectionByGeneralId(generalHandle); + CONN_CHECK_AND_RETURN_RET_LOGE(generalConnection != NULL, SOFTBUS_INVALID_PARAM, CONN_BLE, + "connection is null, generalId=%{public}u", generalHandle); + int32_t status = SoftBusGetRandomAddress(generalConnection->addr, addr, (int32_t)tokenId); + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "get mac failed, generalId=%{public}u", generalHandle); + } + ConnReturnGeneralConnection(&generalConnection); + return status; +} + +static int32_t CreateServer(const GeneralConnectionParam *param) +{ + if (!IsAllowSave(param->pkgName, true)) { + CONN_LOGE(CONN_BLE, "add pkg name is max"); + return SOFTBUS_CONN_BLE_GENERAL_CREATE_SERVER_MAX; + } + int32_t status = SoftBusMutexLock(&g_names.names->lock); + CONN_CHECK_AND_RETURN_RET_LOGE(status == SOFTBUS_OK, SOFTBUS_LOCK_ERR, + CONN_BLE, "lock names failed"); + Name *it = NULL; + bool exit = false; + LIST_FOR_EACH_ENTRY(it, &g_names.names->list, Name, node) { + if (StrCmpIgnoreCase(it->info.name, param->name) == 0 && + StrCmpIgnoreCase(it->info.bundleName, param->bundleName) == 0) { + exit = true; + break; + } + } + if (exit) { + CONN_LOGE(CONN_BLE, "server name already exit, not allowed"); + (void)SoftBusMutexUnlock(&g_names.names->lock); + return SOFTBUS_CONN_BLE_GENERAL_DUPLICATE_SERVER; + } + Name *nameNode = NewNameNode(param); + if (nameNode == NULL) { + CONN_LOGE(CONN_BLE, "nameNode is null"); + (void)SoftBusMutexUnlock(&g_names.names->lock); + return SOFTBUS_MALLOC_ERR; + } + ListAdd(&g_names.names->list, &nameNode->node); + (void)SoftBusMutexUnlock(&g_names.names->lock); + return SOFTBUS_OK; +} + +static void CloseServer(const GeneralConnectionParam *param) +{ + int32_t status = SoftBusMutexLock(&g_names.names->lock); + CONN_CHECK_AND_RETURN_LOGE(status == SOFTBUS_OK, CONN_BLE, "lock names failed"); + Name *it = NULL; + Name *next = NULL; + LIST_FOR_EACH_ENTRY_SAFE(it, next, &g_names.names->list, Name, node) { + if (StrCmpIgnoreCase(it->info.name, param->name) == 0 && + StrCmpIgnoreCase(it->info.bundleName, param->bundleName) == 0) { + ListDelete(&it->node); + FreeNameNode(&it); + } + } + (void)SoftBusMutexUnlock(&g_names.names->lock); + return; +} + +static GeneralConnectionManager g_manager = { + .registerListener = RegisterListener, + .createServer = CreateServer, + .closeServer = CloseServer, + .connect = Connect, + .send = Send, + .disconnect = Disconnect, + .getPeerDeviceId = GetPeerDeviceId, + .cleanupGeneralConnection = ClearAllGeneralConnection, +}; + +GeneralConnectionManager *GetGeneralConnectionManager(void) +{ + return &g_manager; +} + +int32_t InitGeneralConnectionManager(void) +{ + ConnectCallback connCb = { + .OnConnected = OnCommConnected, + .OnDisconnected = OnCommDisconnected, + .OnDataReceived = OnCommDataReceived, + }; + int32_t ret = SoftBusMutexInit(&g_requestIdLock, NULL); + CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_INIT, "init lock failed"); + ret = ConnSetConnectCallback(MODULE_BLE_GENERAL, &connCb); + if (ret != SOFTBUS_OK) { + CONN_LOGE(CONN_INIT, "set callback failed"); + SoftBusMutexDestroy(&g_requestIdLock); + return ret; + } + + SoftBusList *connections = CreateSoftBusList(); + if (connections == NULL) { + CONN_LOGE(CONN_INIT, "create connections list failed"); + SoftBusMutexDestroy(&g_requestIdLock); + return SOFTBUS_CREATE_LIST_ERR; + } + g_generalManager.connections = connections; + SoftBusList *names = CreateSoftBusList(); + if (names == NULL) { + CONN_LOGE(CONN_INIT, "create names list failed"); + SoftBusMutexDestroy(&g_requestIdLock); + DestroySoftBusList(g_generalManager.connections); + return SOFTBUS_CREATE_LIST_ERR; + } + g_names.names = names; + + g_generalManagerSyncHandler.handler.looper = GetLooper(LOOP_TYPE_CONN); + if (g_generalManagerSyncHandler.handler.looper == NULL) { + CONN_LOGE(CONN_INIT, "create names list failed"); + SoftBusMutexDestroy(&g_requestIdLock); + DestroySoftBusList(g_generalManager.connections); + DestroySoftBusList(g_names.names); + return SOFTBUS_LOOPER_ERR; + } + CONN_LOGI(CONN_INIT, "init success"); + return SOFTBUS_OK; +} \ No newline at end of file diff --git a/core/connection/general/softbus_conn_general_connection.h b/core/connection/general/softbus_conn_general_connection.h new file mode 100644 index 0000000000..936516c8eb --- /dev/null +++ b/core/connection/general/softbus_conn_general_connection.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SOFTBUS_CONN_GENERAL_CONNECTION_H +#define SOFTBUS_CONN_GENERAL_CONNECTION_H + +#include "softbus_conn_general_negoation.h" +#include "softbus_conn_interface.h" +#include "softbus_utils.h" + +#include "stdint.h" +#ifdef __cplusplus +extern "C" { +#endif + +enum GeneralConnState { + STATE_CONNECTING, + STATE_CONNECTED, +}; + +typedef struct { + int32_t pid; + char name[GENERAL_NAME_LEN]; + char pkgName[PKG_NAME_SIZE_MAX]; + char bundleName[BUNDLE_NAME_MAX]; +} GeneralConnectionParam; + +typedef struct { + ListNode node; + GeneralConnectionParam info; +} Name; + +typedef struct { + SoftBusList *names; +} GeneralNames; + +struct GeneralConnection { + ListNode node; + uint32_t requestId; + uint32_t generalId; + uint32_t peerGeneralId; + uint32_t abilityBitSet; + uint32_t underlayerHandle; + int32_t objectRc; + BleProtocolType protocol; + char udid[UDID_BUF_LEN]; + char networkId[NETWORK_ID_BUF_LEN]; + char addr[BT_MAC_LEN]; + bool isSupportNetWorkIdExchange; + bool isClient; + enum GeneralConnState state; + GeneralConnectionParam info; + void (*reference)(struct GeneralConnection *self); + void (*dereference)(struct GeneralConnection *self); + SoftBusMutex lock; +}; + +typedef struct { + void (*onConnectSuccess)(GeneralConnectionParam *info, uint32_t generalHandle); + void (*onConnectFailed)(GeneralConnectionParam *info, uint32_t generalHandle, int32_t reason); + void (*onAcceptConnect)(GeneralConnectionParam *info, uint32_t generalHandle); + void (*onDataReceived)(GeneralConnectionParam *info, uint32_t generalHandle, const uint8_t *data, uint32_t dataLen); + void (*onConnectionDisconnected)(GeneralConnectionParam *info, uint32_t generalHandle, int32_t reason); +} GeneralConnectionListener; + +typedef struct { + int32_t (*registerListener)(const GeneralConnectionListener *listener); + int32_t (*createServer)(const GeneralConnectionParam *param); + void (*closeServer)(const GeneralConnectionParam *param); + + int32_t (*connect)(const GeneralConnectionParam *param, const char *addr); + int32_t (*send)(uint32_t generalHandle, const uint8_t *data, uint32_t dataLen, int32_t pid); + + void (*disconnect)(uint32_t generalHandle); + int32_t (*getPeerDeviceId)(uint32_t generalHandle, char *addr, uint32_t length, uint32_t tokenId); + void (*cleanupGeneralConnection)(const char *pkgName, int32_t pid); +} GeneralConnectionManager; + +GeneralConnectionManager *GetGeneralConnectionManager(void); +int32_t InitGeneralConnectionManager(void); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* SOFTBUS_CONN_GENERAL_CONNECTION_H */ \ No newline at end of file diff --git a/core/connection/general/softbus_conn_general_negoation.c b/core/connection/general/softbus_conn_general_negoation.c new file mode 100644 index 0000000000..2ece319163 --- /dev/null +++ b/core/connection/general/softbus_conn_general_negoation.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "softbus_conn_general_negoation.h" +#include "softbus_json_utils.h" +#include "conn_log.h" +#include "softbus_error_code.h" +#include "softbus_adapter_mem.h" +#include "string.h" + +#define NAME "name" +#define ABILITY "ability" +#define ERR "err" +#define DATA_LEN "data_len" +#define BUNDLE_NAME "bundle_name" +#define UPDATE_HANDLE "update_handle" + + +static OutData *ConstructOutData(GeneralConnectionInfo *info, GeneralConnectionMsgType msgType, const char *payload) +{ + OutData *outData = (OutData *)SoftBusCalloc(sizeof(OutData)); + if (outData == NULL) { + CONN_LOGE(CONN_BLE, "malloc err"); + return NULL; + } + outData->dataLen = strlen(payload) + GENERAL_CONNECTION_HEADER_SIZE; + outData->data = (uint8_t *)SoftBusCalloc(outData->dataLen); + if (outData->data == NULL || memcpy_s(outData->data + GENERAL_CONNECTION_HEADER_SIZE, + outData->dataLen - GENERAL_CONNECTION_HEADER_SIZE, payload, strlen(payload)) != EOK) { + FreeOutData(outData); + CONN_LOGE(CONN_BLE, "malloc or memcpy err"); + return NULL; + } + GeneralConnectionHead *header = (GeneralConnectionHead *)outData->data; + header->headLen = GENERAL_CONNECTION_HEADER_SIZE; + header->localId = info->localId; + header->peerId = info->peerId; + header->msgType = msgType; + return outData; +} + +OutData *GeneralConnectionPackMsg(GeneralConnectionInfo *info, GeneralConnectionMsgType msgType) +{ + cJSON *json = cJSON_CreateObject(); + CONN_CHECK_AND_RETURN_RET_LOGE(json != NULL, NULL, CONN_BLE, "create json object failed"); + int32_t status = SOFTBUS_OK; + switch (msgType) { + case GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE: + if (!AddStringToJsonObject(json, NAME, info->name) || + !AddNumberToJsonObject(json, ABILITY, info->abilityBitSet) || + !AddStringToJsonObject(json, BUNDLE_NAME, info->bundleName)) { + status = SOFTBUS_CREATE_JSON_ERR; + } + break; + case GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE_ACK: + if (!AddNumberToJsonObject(json, ERR, info->ackStatus) || + !AddNumberToJsonObject(json, ABILITY, info->abilityBitSet)) { + status = SOFTBUS_CREATE_JSON_ERR; + } + break; + case GENERAL_CONNECTION_MSG_TYPE_RESET: + break; + case GENERAL_CONNECTION_MSG_TYPE_MERGE: + if (!AddNumberToJsonObject(json, UPDATE_HANDLE, info->updateHandle)) { + status = SOFTBUS_CREATE_JSON_ERR; + } + break; + default: + status = SOFTBUS_INVALID_PARAM; + break; + } + if (status != SOFTBUS_OK) { + CONN_LOGE(CONN_BLE, "add json falied, status=%{public}d", status); + cJSON_Delete(json); + return NULL; + } + + char *payload = cJSON_PrintUnformatted(json); + cJSON_Delete(json); + CONN_CHECK_AND_RETURN_RET_LOGE(payload != NULL, NULL, CONN_BLE, "cJSON_PrintUnformatted failed"); + OutData *outData = ConstructOutData(info, msgType, payload); + if (outData == NULL) { + cJSON_free(payload); + CONN_LOGE(CONN_BLE, "outData is null"); + return NULL; + } + cJSON_free(payload); + return outData; +} + +int32_t GeneralConnectionUnpackMsg(const uint8_t *data, uint32_t dataLen, GeneralConnectionInfo *info, + GeneralConnectionMsgType parseMsgType) +{ + cJSON *json = cJSON_ParseWithLength((char *)data, dataLen); + CONN_CHECK_AND_RETURN_RET_LOGE(json != NULL, SOFTBUS_PARSE_JSON_ERR, CONN_BLE, "parse json failed"); + int32_t status = SOFTBUS_OK; + switch (parseMsgType) { + case GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE: + if (!GetJsonObjectStringItem(json, NAME, info->name, GENERAL_NAME_LEN) || + !GetJsonObjectNumberItem(json, ABILITY, (int32_t *)&(info->abilityBitSet)) || + !GetJsonObjectStringItem(json, BUNDLE_NAME, info->bundleName, BUNDLE_NAME_MAX)) { + status = SOFTBUS_PARSE_JSON_ERR; + } + break; + case GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE_ACK: + if (!GetJsonObjectSignedNumberItem(json, ERR, &(info->ackStatus)) || + !GetJsonObjectNumberItem(json, ABILITY, (int32_t *)&(info->abilityBitSet))) { + status = SOFTBUS_PARSE_JSON_ERR; + } + break; + case GENERAL_CONNECTION_MSG_TYPE_RESET: + break; + case GENERAL_CONNECTION_MSG_TYPE_MERGE: + if (!GetJsonObjectNumberItem(json, UPDATE_HANDLE, (int32_t *)&(info->updateHandle))) { + status = SOFTBUS_CREATE_JSON_ERR; + } + break; + default: + status = SOFTBUS_INVALID_PARAM; + break; + } + cJSON_Delete(json); + return status; +} + +void FreeOutData(OutData *outData) +{ + CONN_CHECK_AND_RETURN_LOGE(outData != NULL, CONN_BLE, "outData is null"); + SoftBusFree(outData->data); + SoftBusFree(outData); +} \ No newline at end of file diff --git a/core/connection/general/softbus_conn_general_negoation.h b/core/connection/general/softbus_conn_general_negoation.h new file mode 100644 index 0000000000..21e28f96af --- /dev/null +++ b/core/connection/general/softbus_conn_general_negoation.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef SOFTBUS_CONN_GENERAL_NEGOATION_H +#define SOFTBUS_CONN_GENERAL_NEGOATION_H + +#include "softbus_common.h" +#include "softbus_conn_common.h" +#include "softbus_conn_interface.h" +#include "softbus_utils.h" + +#include "stdint.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define GENERAL_NAME_LEN (30) +#define BUNDLE_NAME_MAX (256) + +typedef enum { + GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE = 0, + GENERAL_CONNECTION_MSG_TYPE_HANDSHAKE_ACK, + GENERAL_CONNECTION_MSG_TYPE_RESET, + GENERAL_CONNECTION_MSG_TYPE_MERGE, + GENERAL_CONNECTION_MSG_TYPE_NORMAL = 12, + GENERAL_CONNECTION_MSG_TYPE_MAX = 22, +} GeneralConnectionMsgType; +typedef struct { + int32_t msgType; + int32_t localId; + int32_t peerId; + int32_t headLen; +} GeneralConnectionHead; + +typedef uint32_t GeneralConnAbilityBitSet; +static const size_t GENERAL_CONNECTION_HEADER_SIZE = sizeof(GeneralConnectionHead); + +typedef struct { + char name[GENERAL_NAME_LEN]; + char bundleName[BUNDLE_NAME_MAX]; + GeneralConnAbilityBitSet abilityBitSet; + uint32_t peerId; + uint32_t localId; + int32_t ackStatus; + uint32_t updateHandle; +} GeneralConnectionInfo; + +typedef struct { + uint8_t *data; + uint32_t dataLen; +} OutData; + +OutData *GeneralConnectionPackMsg(GeneralConnectionInfo *info, GeneralConnectionMsgType msgType); +int32_t GeneralConnectionUnpackMsg(const uint8_t *data, uint32_t dataLen, GeneralConnectionInfo *info, + GeneralConnectionMsgType parseMsgType); +void FreeOutData(OutData *outData); +#ifdef __cplusplus +} +#endif /* _cplusplus */ +#endif /* SOFTBUS_CONN_GENERAL_NEGOATION_H */ \ No newline at end of file diff --git a/core/connection/interface/softbus_conn_interface.h b/core/connection/interface/softbus_conn_interface.h index 1c99f47f49..d6204c4db2 100644 --- a/core/connection/interface/softbus_conn_interface.h +++ b/core/connection/interface/softbus_conn_interface.h @@ -53,6 +53,7 @@ typedef enum { MODULE_SESSION_KEY_AUTH = 26, MODULE_BLE_NET = 100, MODULE_BLE_CONN = 101, + MODULE_BLE_GENERAL = 102, MODULE_NIP_BR_CHANNEL = 201, MODULE_OLD_NEARBY = 300, } ConnModule; @@ -66,6 +67,7 @@ typedef enum { CONNECT_BLE_DIRECT, CONNECT_HML, CONNECT_TRIGGER_HML, + CONNECT_BLE_GENERAL, CONNECT_TYPE_MAX } ConnectType; @@ -438,6 +440,8 @@ int32_t ConnGetTypeByConnectionId(uint32_t connectionId, ConnectType *type); */ int32_t ConnConfigPostLimit(const LimitConfiguration *configuration); +void ConnDeathCallback(const char *pkgName, int32_t pid); + #ifdef __cplusplus #if __cplusplus } diff --git a/core/connection/manager/softbus_conn_ipc.c b/core/connection/manager/softbus_conn_ipc.c new file mode 100644 index 0000000000..37c1cb8814 --- /dev/null +++ b/core/connection/manager/softbus_conn_ipc.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "softbus_conn_ipc.h" +#include "softbus_conn_general_connection.h" + +#include "general_connection_client_proxy.h" +#include "conn_log.h" +#include "softbus_connection.h" + +static void GeneralDataReceived(GeneralConnectionParam *info, + uint32_t generalHandle, const uint8_t *data, uint32_t dataLen) +{ + ClientIpcOnDataReceived(info->pkgName, info->pid, generalHandle, data, dataLen); +} + +static void GeneralConnectionDisconnected(GeneralConnectionParam *info, uint32_t generalHandle, int32_t reason) +{ + ClientIpcOnConnectionStateChange(info->pkgName, info->pid, generalHandle, CONNECTION_STATE_DISCONNECTED, reason); +} + +static void GeneralAcceptConnect(GeneralConnectionParam *info, uint32_t generalHandle) +{ + ClientIpcOnAcceptConnect(info->pkgName, info->pid, info->name, generalHandle); +} + +static void GeneralConnectFail(GeneralConnectionParam *info, uint32_t generalHandle, int32_t reason) +{ + ClientIpcOnConnectionStateChange(info->pkgName, info->pid, generalHandle, CONNECTION_STATE_CONNECTED_FAILED, reason); +} + +static void GeneralConnectSuccess(GeneralConnectionParam *info, uint32_t generalHandle) +{ + ClientIpcOnConnectionStateChange(info->pkgName, info->pid, generalHandle, CONNECTION_STATE_CONNECTED_SUCCESS, 0); +} + +GeneralConnectionListener g_baseListener = { + .onConnectSuccess = GeneralConnectSuccess, + .onConnectFailed = GeneralConnectFail, + .onAcceptConnect = GeneralAcceptConnect, + .onDataReceived = GeneralDataReceived, + .onConnectionDisconnected = GeneralConnectionDisconnected, +}; + +void ClearGeneralConnection(const char *pkgName, int32_t pid) +{ + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == NULL) { + COMM_LOGE(CONN_COMMON, "manager is null"); + return; + } + manager->cleanupGeneralConnection(pkgName, pid); +} + +int32_t InitGeneralConnection() +{ + int32_t ret = InitGeneralConnectionManager(); + if (ret != SOFTBUS_OK) { + COMM_LOGE(CONN_COMMON, "init general manager failed, err=%{public}d", ret); + return SOFTBUS_NO_INIT; + } + + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == NULL) { + COMM_LOGE(CONN_COMMON, "manager is null"); + return SOFTBUS_NO_INIT; + } + ret = manager->registerListener(&g_baseListener); + if (ret != SOFTBUS_OK) { + COMM_LOGE(CONN_COMMON, "init general manager failed, err=%{public}d", ret); + return SOFTBUS_NO_INIT; + } + COMM_LOGI(CONN_COMMON, "init and refister listener success"); + return SOFTBUS_OK; +} \ No newline at end of file diff --git a/core/connection/manager/softbus_conn_ipc.h b/core/connection/manager/softbus_conn_ipc.h new file mode 100644 index 0000000000..d9d1c8bffa --- /dev/null +++ b/core/connection/manager/softbus_conn_ipc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SOFTBUS_CONN_IPC_H +#define SOFTBUS_CONN_IPC_H + +#include "stdint.h" + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif +#endif + +void ClearGeneralConnection(const char *pkgName, int32_t pid); + +int32_t InitGeneralConnection(); + +#ifdef __cplusplus +#if __cplusplus +} +#endif +#endif +#endif /* SOFTBUS_CONN_IPC_H */ diff --git a/core/connection/manager/softbus_conn_manager.c b/core/connection/manager/softbus_conn_manager.c index d0767daa07..749a8e7679 100644 --- a/core/connection/manager/softbus_conn_manager.c +++ b/core/connection/manager/softbus_conn_manager.c @@ -34,6 +34,7 @@ #include "softbus_socket.h" #include "softbus_tcp_connect_manager.h" #include "softbus_utils.h" +#include "softbus_conn_ipc.h" ConnectFuncInterface *g_connManager[CONNECT_TYPE_MAX] = { 0 }; static SoftBusList *g_listenerList = NULL; @@ -51,7 +52,7 @@ static int32_t ModuleCheck(ConnModule moduleId) ConnModule id[] = { MODULE_TRUST_ENGINE, MODULE_HICHAIN, MODULE_AUTH_SDK, MODULE_AUTH_CONNECTION, MODULE_MESSAGE_SERVICE, MODULE_AUTH_CHANNEL, MODULE_AUTH_MSG, MODULE_BLUETOOTH_MANAGER, MODULE_CONNECTION, MODULE_DIRECT_CHANNEL, MODULE_PROXY_CHANNEL, MODULE_DEVICE_AUTH, MODULE_P2P_LINK, MODULE_UDP_INFO, - MODULE_PKG_VERIFY, MODULE_META_AUTH, MODULE_P2P_NEGO, MODULE_BLE_NET, MODULE_BLE_CONN }; + MODULE_PKG_VERIFY, MODULE_META_AUTH, MODULE_P2P_NEGO, MODULE_BLE_NET, MODULE_BLE_CONN, MODULE_BLE_GENERAL }; int32_t i; int32_t idNum = sizeof(id) / sizeof(ConnModule); @@ -328,6 +329,11 @@ void ConnUnSetConnectCallback(ConnModule moduleId) return; } +void ConnDeathCallback(const char *pkgName, int32_t pid) +{ + ClearGeneralConnection(pkgName, pid); +} + int32_t ConnTypeIsSupport(ConnectType type) { return ConnTypeCheck(type); @@ -552,6 +558,9 @@ int32_t ConnServerInit(void) return SOFTBUS_CREATE_LIST_ERR; } } + CONN_CHECK_AND_RETURN_RET_LOGE(InitGeneralConnection() == SOFTBUS_OK, + SOFTBUS_CONN_INTERNAL_ERR, CONN_COMMON, "init failed."); + CONN_CHECK_AND_RETURN_RET_LOGE(SoftBusMutexInit(&g_ReqLock, NULL) == SOFTBUS_OK, SOFTBUS_CONN_INTERNAL_ERR, CONN_COMMON, "g_ReqLock init lock failed."); diff --git a/core/frame/common/src/softbus_server_frame.c b/core/frame/common/src/softbus_server_frame.c index 1c4d023774..8e12f2c7f2 100644 --- a/core/frame/common/src/softbus_server_frame.c +++ b/core/frame/common/src/softbus_server_frame.c @@ -160,4 +160,5 @@ void ClientDeathCallback(const char *pkgName, int32_t pid) TransServerDeathCallback(pkgName, pid); BusCenterServerDeathCallback(pkgName); AuthServerDeathCallback(pkgName, pid); + ConnDeathCallback(pkgName, pid); } diff --git a/core/frame/standard/init/src/softbus_server.cpp b/core/frame/standard/init/src/softbus_server.cpp index 88d308eacc..cdf997149a 100644 --- a/core/frame/standard/init/src/softbus_server.cpp +++ b/core/frame/standard/init/src/softbus_server.cpp @@ -31,6 +31,13 @@ #include "trans_spec_object.h" #include "lnn_lane_interface.h" #include "general_connection_client_proxy.h" +#include "softbus_conn_general_connection.h" + +#ifdef SUPPORT_BUNDLENAME +#include "bundle_mgr_proxy.h" +#include "iservice_registry.h" +#include "system_ability_definition.h" +#endif #define SOFTBUS_IPC_THREAD_NUM 32 #define OPEN_AUTH_BR_CONNECT_TIMEOUT_MILLIS (15 * 1000) @@ -474,33 +481,169 @@ int32_t SoftBusServer::SetDisplayName(const char *pkgName, const char *nameData, return LnnIpcSetDisplayName(pkgName, nameData, len); } -int32_t SoftBusServer::CreateServer(const char *pkgName, const char *name) +#ifdef SUPPORT_BUNDLENAME +static int32_t FillBundleName(char *bundleNameStr, uint32_t size) { + pid_t callingUid = OHOS::IPCSkeleton::GetCallingUid(); + std::string bundleName; + sptr systemAbilityManager = + SystemAbilityManagerClient::GetInstance().GetSystemAbilityManager(); + if (systemAbilityManager == nullptr) { + COMM_LOGE(COMM_SVC, "Failed to get system ability manager."); + return SOFTBUS_TRANS_SYSTEM_ABILITY_MANAGER_FAILED; + } + sptr remoteObject = systemAbilityManager->GetSystemAbility(BUNDLE_MGR_SERVICE_SYS_ABILITY_ID); + if (remoteObject == nullptr) { + COMM_LOGE(COMM_SVC, "Failed to get bundle manager service."); + return SOFTBUS_TRANS_GET_SYSTEM_ABILITY_FAILED; + } + sptr bundleMgr = iface_cast(remoteObject); + if (bundleMgr == nullptr) { + COMM_LOGE(COMM_SVC, "iface_cast failed"); + return SOFTBUS_TRANS_GET_BUNDLE_MGR_FAILED; + } + if (bundleMgr->GetNameForUid(callingUid, bundleName) != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "get bundleName failed"); + return SOFTBUS_TRANS_GET_BUNDLENAME_FAILED; + } + + if (strcpy_s(bundleNameStr, size, bundleName.c_str()) != EOK) { + COMM_LOGE(COMM_SVC, "copy name failed"); + return SOFTBUS_STRCPY_ERR; + } return SOFTBUS_OK; } +#endif + +int32_t SoftBusServer::CreateServer(const char *pkgName, const char *name) +{ + GeneralConnectionParam param = {0}; + param.pid = OHOS::IPCSkeleton::GetCallingPid(); + if (strcpy_s(param.name, GENERAL_NAME_LEN, name) != EOK) { + COMM_LOGE(COMM_SVC, "copy name failed"); + return SOFTBUS_STRCPY_ERR; + } + if (strcpy_s(param.pkgName, PKG_NAME_SIZE_MAX, pkgName) != EOK) { + COMM_LOGE(COMM_SVC, "copy pkgName failed"); + return SOFTBUS_STRCPY_ERR; + } + if (strcpy_s(param.name, GENERAL_NAME_LEN, name) != EOK) { + COMM_LOGE(COMM_SVC, "copy name failed"); + return SOFTBUS_STRCPY_ERR; + } + int32_t ret = SOFTBUS_OK; +#ifdef SUPPORT_BUNDLENAME + ret = FillBundleName(param.bundleName, BUNDLE_NAME_MAX); + if (ret != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "get bundle name failed"); + return ret; + } +#endif + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == nullptr || manager->createServer == nullptr) { + COMM_LOGE(COMM_SVC, "invalid param"); + return SOFTBUS_NO_INIT; + } + ret = manager->createServer(¶m); + if (ret != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "createServer failed,ret=%{public}d", ret); + } + COMM_LOGI(COMM_SVC, "create server success"); + return ret; +} int32_t SoftBusServer::RemoveServer(const char *pkgName, const char *name) { - return SOFTBUS_OK; + GeneralConnectionParam param = {0}; + int32_t ret = SOFTBUS_OK; +#ifdef SUPPORT_BUNDLENAME + ret = FillBundleName(param.bundleName, BUNDLE_NAME_MAX); + if (ret != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "get bundle name failed!"); + return ret; + } +#endif + if (strcpy_s(param.name, GENERAL_NAME_LEN, name) != EOK) { + COMM_LOGE(COMM_SVC, "copy name failed"); + return SOFTBUS_STRCPY_ERR; + } + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == nullptr || manager->closeServer == nullptr) { + COMM_LOGE(COMM_SVC, "invalid param"); + return SOFTBUS_NO_INIT; + } + manager->closeServer(¶m); + COMM_LOGI(COMM_SVC, "remove server success"); + return ret; } int32_t SoftBusServer::Connect(const char *pkgName, const char *name, const Address *address) { - return SOFTBUS_OK; + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == nullptr || manager->connect == nullptr) { + COMM_LOGE(COMM_SVC, "invalid param"); + return SOFTBUS_NO_INIT; + } + GeneralConnectionParam param = {0}; + if (strcpy_s(param.name, GENERAL_NAME_LEN, name) != EOK) { + COMM_LOGE(COMM_SVC, "copy name failed"); + return SOFTBUS_STRCPY_ERR; + } + if (strcpy_s(param.pkgName, PKG_NAME_SIZE_MAX, pkgName) != EOK) { + COMM_LOGE(COMM_SVC, "copy pkgName failed"); + return SOFTBUS_STRCPY_ERR; + } +#ifdef SUPPORT_BUNDLENAME + int32_t ret = FillBundleName(param.bundleName, BUNDLE_NAME_MAX); + if (ret != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "get bundle name failed"); + return ret; + } +#endif + param.pid = OHOS::IPCSkeleton::GetCallingPid(); + int32_t handle = manager->connect(¶m, address->addr.ble.mac); + COMM_LOGI(COMM_SVC, "connect start, handle=%{public}d", handle); + return handle; } int32_t SoftBusServer::Disconnect(uint32_t handle) { + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == nullptr || manager->disconnect == nullptr) { + COMM_LOGE(COMM_SVC, "invalid param"); + return SOFTBUS_NO_INIT; + } + manager->disconnect(handle); + COMM_LOGI(COMM_SVC, "disconnect success, handle=%{public}d", handle); return SOFTBUS_OK; } int32_t SoftBusServer::Send(uint32_t handle, const uint8_t *data, uint32_t len) { - return SOFTBUS_OK; + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == nullptr || manager->send == nullptr) { + COMM_LOGE(COMM_SVC, "invalid param"); + return SOFTBUS_NO_INIT; + } + int32_t ret = manager->send(handle, data, len, OHOS::IPCSkeleton::GetCallingPid()); + if (ret != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "send failed, handle=%{public}d", handle); + } + return ret; } int32_t SoftBusServer::ConnGetPeerDeviceId(uint32_t handle, char *deviceId, uint32_t len) { - return SOFTBUS_OK; + GeneralConnectionManager *manager = GetGeneralConnectionManager(); + if (manager == nullptr || manager->getPeerDeviceId == nullptr) { + COMM_LOGE(COMM_SVC, "invalid param"); + return SOFTBUS_NO_INIT; + } + uint32_t callingTokenId = IPCSkeleton::GetCallingTokenID(); + int32_t ret = manager->getPeerDeviceId(handle, deviceId, len, callingTokenId); + if (ret != SOFTBUS_OK) { + COMM_LOGE(COMM_SVC, "get peer deviceId failed, handle=%{public}d", handle); + } + return ret; } } // namespace OHOS diff --git a/core/frame/standard/init/src/softbus_server_stub.cpp b/core/frame/standard/init/src/softbus_server_stub.cpp index d062c0d37c..15da4f87b9 100644 --- a/core/frame/standard/init/src/softbus_server_stub.cpp +++ b/core/frame/standard/init/src/softbus_server_stub.cpp @@ -39,7 +39,7 @@ #include "system_ability_definition.h" #endif -const char *g_limitPkgName = "dms"; +const char *g_limitPkgName = "ohos.distributedschedule.dms"; #define READ_PARCEL_WITH_RET(parcel, type, data, retVal) \ do { \ @@ -1904,12 +1904,24 @@ int32_t SoftBusServerStub::ConnectInner(MessageParcel &data, MessageParcel &repl COMM_LOGE(COMM_SVC, "read name failed!"); return SOFTBUS_IPC_ERR; } - Address *address = const_cast
(reinterpret_cast(data.ReadRawData(sizeof(Address)))); + Address connectAddress; + const char *address = data.ReadCString(); if (address == nullptr) { COMM_LOGE(COMM_SVC, "read address fail, address is nullptr"); return SOFTBUS_IPC_ERR; } - int32_t handle = Connect(pkgName, name, address); + int32_t len = strnlen(address, BT_MAC_LEN); + if (len != (BT_MAC_LEN - 1) || strcpy_s(connectAddress.addr.ble.mac, BT_MAC_LEN, address) != EOK) { + COMM_LOGE(COMM_SVC, "read address fail, address is=%{public}s", address); + return SOFTBUS_IPC_ERR; + } + int32_t addrType = data.ReadInt32(); + if (addrType < CONNECTION_ADDR_WLAN || addrType > CONNECTION_ADDR_MAX) { + COMM_LOGE(COMM_SVC, "read addrType fail, addrType= %{public}d", addrType); + return SOFTBUS_IPC_ERR; + } + connectAddress.addrType = static_cast(addrType); + int32_t handle = Connect(pkgName, name, &connectAddress); if (!reply.WriteInt32(handle)) { COMM_LOGE(COMM_SVC, "write handle failed"); return SOFTBUS_IPC_ERR; diff --git a/sdk/connection/ipc/standard/src/general_connection_server_proxy_standard.cpp b/sdk/connection/ipc/standard/src/general_connection_server_proxy_standard.cpp index 61f7b034f4..3420b43e91 100644 --- a/sdk/connection/ipc/standard/src/general_connection_server_proxy_standard.cpp +++ b/sdk/connection/ipc/standard/src/general_connection_server_proxy_standard.cpp @@ -391,8 +391,12 @@ int32_t ConnectionServerProxy::Connect(const char *pkgName, const char *name, co CONN_LOGE(CONN_COMMON, "write name failed"); return SOFTBUS_IPC_ERR; } - if (!data.WriteRawData((void *)address, sizeof(Address))) { - CONN_LOGE(CONN_COMMON, "write address failed!"); + if (!data.WriteCString(address->addr.ble.mac)) { + CONN_LOGE(CONN_COMMON, "write address failed"); + return SOFTBUS_IPC_ERR; + } + if (!data.WriteInt32(address->addrType)) { + CONN_LOGE(CONN_COMMON, "write addrType failed"); return SOFTBUS_IPC_ERR; } MessageParcel reply; diff --git a/sdk/connection/service/src/general_client_connection.c b/sdk/connection/service/src/general_client_connection.c index be251d3141..3fe4738f44 100644 --- a/sdk/connection/service/src/general_client_connection.c +++ b/sdk/connection/service/src/general_client_connection.c @@ -26,7 +26,7 @@ static IGeneralListener *g_connectionListener = NULL; static SoftBusMutex g_connectionListenerLock; -const char *g_limitPkgName = "dms"; +const char *g_limitPkgName = "ohos.distributedschedule.dms"; static bool IsValidListener(IGeneralListener *listener) { diff --git a/sdk/frame/standard/src/softbus_client_stub.cpp b/sdk/frame/standard/src/softbus_client_stub.cpp index 7177292703..f50c01e878 100644 --- a/sdk/frame/standard/src/softbus_client_stub.cpp +++ b/sdk/frame/standard/src/softbus_client_stub.cpp @@ -973,7 +973,7 @@ int32_t SoftBusClientStub::OnDataReceivedInner(MessageParcel &data, MessageParce COMM_LOGE(COMM_SDK, "OnDataReceivedInner read len failed!"); return SOFTBUS_IPC_ERR; } - const uint8_t *dataPtr = (const uint8_t *)data.ReadRawData(len); + const uint8_t *dataPtr = (const uint8_t *)data.ReadBuffer(len); if (dataPtr == nullptr) { COMM_LOGE(COMM_SDK, "OnDataReceivedInner read data failed!"); return SOFTBUS_IPC_ERR; -- Gitee