• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "proxy_connection.h"
16 
17 #include "securec.h"
18 #include "c_header/ohos_bt_def.h"
19 #include "c_header/ohos_bt_socket.h"
20 #include "conn_log.h"
21 #include "softbus_adapter_mem.h"
22 #include "softbus_conn_common.h"
23 #include "softbus_error_code.h"
24 #include "softbus_utils.h"
25 #include "wrapper_br_interface.h"
26 
27 typedef struct {
28     uint32_t channelId;
29     ProxyBrConnectStateCallback callback;
30 } ProxyBrConnectContext;
31 
32 static SppSocketDriver *g_sppDriver = NULL;
33 ProxyEventListener g_eventListener = { 0 };
34 
LegacyBrLoopRead(struct ProxyConnection * connection)35 static int32_t LegacyBrLoopRead(struct ProxyConnection *connection)
36 {
37 #define BUFFER_SIZE (1024 * 2)
38     uint8_t *buffer = (uint8_t *)SoftBusCalloc(BUFFER_SIZE);
39     CONN_CHECK_AND_RETURN_RET_LOGE(buffer != NULL, SOFTBUS_MALLOC_ERR, CONN_PROXY, "create buffer failed");
40     uint32_t channelId = connection->channelId;
41     int32_t ret = SOFTBUS_OK;
42     while (true) {
43         ret = SoftBusMutexLock(&connection->lock);
44         if (ret != SOFTBUS_OK) {
45             CONN_LOGE(CONN_PROXY, "get lock failed, channelId=%{public}u, err=%{public}d", channelId, ret);
46             ret = SOFTBUS_LOCK_ERR;
47             break;
48         }
49         int32_t socketHandle = connection->socketHandle;
50         (void)SoftBusMutexUnlock(&connection->lock);
51         if (socketHandle == BR_INVALID_SOCKET_HANDLE) {
52             ret = BR_INVALID_SOCKET_HANDLE;
53             break;
54         }
55         int32_t recvLen = g_sppDriver->Read(socketHandle, buffer, BUFFER_SIZE);
56         if (recvLen == BR_READ_SOCKET_CLOSED) {
57             CONN_LOGW(CONN_PROXY,
58                 "br connection read return, connection closed, channelId=%{public}u, socketHandle=%{public}d",
59                 channelId, socketHandle);
60             ret = SOFTBUS_CONN_BR_UNDERLAY_SOCKET_CLOSED;
61             break;
62         }
63         if (recvLen < 0) {
64             CONN_LOGE(CONN_PROXY,
65                 "br connection read return, channelId=%{public}u, socketHandle=%{public}d, error=%{public}d", channelId,
66                 socketHandle, recvLen);
67             ret = SOFTBUS_CONN_BR_UNDERLAY_READ_FAIL;
68             break;
69         }
70         g_eventListener.onDataReceived(channelId, buffer, recvLen);
71     }
72     SoftBusFree(buffer);
73     return ret;
74 }
75 
BrConnectCallback(const BdAddr * bdAddr,BtUuid uuid,int32_t status,int32_t result)76 static void BrConnectCallback(const BdAddr *bdAddr, BtUuid uuid, int32_t status, int32_t result)
77 {
78     (void)bdAddr;
79     (void)uuid;
80     (void)status;
81     (void)result;
82 }
83 
StartClientConnect(struct ProxyConnection * connection)84 static int32_t StartClientConnect(struct ProxyConnection *connection)
85 {
86     uint8_t binaryAddr[BT_ADDR_LEN] = { 0 };
87     int32_t ret = ConvertBtMacToBinary(connection->brMac, BT_MAC_LEN, binaryAddr, BT_ADDR_LEN);
88     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK,
89         ret, CONN_PROXY, "convert btMac to binary failed, error=%{public}d", ret);
90     BtSocketConnectionCallback callback = {
91         .connStateCb = BrConnectCallback,
92     };
93     int32_t socketHandle = g_sppDriver->Connect(connection->proxyChannel.uuid, binaryAddr, &callback);
94     if (socketHandle < 0) {
95         CONN_LOGE(CONN_PROXY, "connect failed, socketHandle=%{public}d", socketHandle);
96         return SOFTBUS_CONN_BR_UNDERLAY_CONNECT_FAIL;
97     }
98     if (SoftBusMutexLock(&connection->lock) != SOFTBUS_OK) {
99         CONN_LOGE(CONN_PROXY, "get lock failed, connId=%{public}u", connection->channelId);
100         g_sppDriver->DisConnect(socketHandle);
101         return SOFTBUS_LOCK_ERR;
102     }
103 
104     if (connection->state != PROXY_CHANNEL_CONNECTING) {
105         CONN_LOGE(CONN_PROXY,
106             "channelId=%{public}u, unexpectedState=%{public}d", connection->channelId, connection->state);
107         g_sppDriver->DisConnect(socketHandle);
108         connection->state = PROXY_CHANNEL_DISCONNECTED;
109         (void)SoftBusMutexUnlock(&connection->lock);
110         return SOFTBUS_CONN_BR_INTERNAL_ERR;
111     }
112     connection->socketHandle = socketHandle;
113     (void)SoftBusMutexUnlock(&connection->lock);
114     CONN_LOGI(CONN_PROXY, "connect success, socketHandle=%{public}d", socketHandle);
115     return SOFTBUS_OK;
116 }
117 
ProxyBrClientConnect(void * data)118 static void *ProxyBrClientConnect(void *data)
119 {
120     const char *name = "Proxy_Conn";
121     SoftBusThread threadSelf = SoftBusThreadGetSelf();
122     SoftBusThreadSetName(threadSelf, name);
123     ProxyBrConnectContext *ctx = (ProxyBrConnectContext *)(data);
124     CONN_CHECK_AND_RETURN_RET_LOGW(ctx != NULL, NULL, CONN_PROXY, "ctx is null");
125     uint32_t channelId = ctx->channelId;
126     ProxyBrConnectStateCallback callback = ctx->callback;
127     SoftBusFree(data);
128     CONN_CHECK_AND_RETURN_RET_LOGE(callback.onConnectSuccess != NULL, NULL, CONN_PROXY,
129         "onConnectSuccess is null");
130     CONN_CHECK_AND_RETURN_RET_LOGE(callback.onConnectFail != NULL, NULL, CONN_PROXY,
131         "onConnectFail is null");
132     struct ProxyConnection *connection = GetProxyChannelManager()->getConnectionById(channelId);
133     CONN_CHECK_AND_RETURN_RET_LOGW(
134         connection != NULL, NULL, CONN_PROXY, "connection is null, channelId=%{public}u", channelId);
135     char anomizeAddress[BT_MAC_LEN] = { 0 };
136     ConvertAnonymizeMacAddress(anomizeAddress, BT_MAC_LEN, connection->brMac, BT_MAC_LEN);
137     CONN_LOGI(CONN_PROXY,
138         "start legacy br connect, channelId=%{public}u, addr=%{public}s", channelId, anomizeAddress);
139     int32_t ret = SOFTBUS_OK;
140     do {
141         ret = StartClientConnect(connection);
142         if (ret != SOFTBUS_OK) {
143             callback.onConnectFail(connection->channelId, ret);
144             break;
145         }
146         callback.onConnectSuccess(connection->channelId);
147         ret = LegacyBrLoopRead(connection);
148         CONN_LOGW(CONN_PROXY, "client loop read exit, channelId=%{public}u, socketHandle=%{public}d, error=%{public}d",
149             connection->channelId, connection->socketHandle, ret);
150         if (SoftBusMutexLock(&connection->lock) != SOFTBUS_OK) {
151             CONN_LOGE(CONN_PROXY, "lock connection failed, channelId=%{public}u", connection->channelId);
152             g_sppDriver->DisConnect(connection->socketHandle);
153             g_eventListener.onDisconnected(connection->channelId, SOFTBUS_LOCK_ERR);
154             break;
155         }
156         if (connection->socketHandle != BR_INVALID_SOCKET_HANDLE) {
157             g_sppDriver->DisConnect(connection->socketHandle);
158             connection->socketHandle = BR_INVALID_SOCKET_HANDLE;
159         }
160         connection->state = PROXY_CHANNEL_DISCONNECTED;
161         (void)SoftBusMutexUnlock(&connection->lock);
162         g_eventListener.onDisconnected(connection->channelId, ret);
163     } while (false);
164     connection->dereference(connection);
165     return NULL;
166 }
167 
ProxyBrConnect(struct ProxyConnection * connection,const ProxyBrConnectStateCallback * callback)168 int32_t ProxyBrConnect(struct ProxyConnection *connection, const ProxyBrConnectStateCallback *callback)
169 {
170     CONN_CHECK_AND_RETURN_RET_LOGE(connection != NULL, SOFTBUS_INVALID_PARAM, CONN_PROXY,
171         "connection is null");
172     CONN_CHECK_AND_RETURN_RET_LOGE(callback != NULL, SOFTBUS_INVALID_PARAM, CONN_PROXY,
173         "callback is null");
174     ProxyBrConnectContext *ctx = (ProxyBrConnectContext *)SoftBusCalloc(sizeof(ProxyBrConnectContext));
175     CONN_CHECK_AND_RETURN_RET_LOGE(ctx != NULL, SOFTBUS_LOCK_ERR, CONN_PROXY,
176         "calloc failed, connId=%{public}u", connection->channelId);
177     ctx->channelId = connection->channelId;
178     ctx->callback = *callback;
179     int32_t status = ConnStartActionAsync(ctx, ProxyBrClientConnect, NULL);
180     if (status != SOFTBUS_OK) {
181         CONN_LOGE(CONN_PROXY, "start connect thread failed, connId=%{public}u, error=%{public}d",
182             connection->channelId, status);
183         SoftBusFree(ctx);
184         return status;
185     }
186     return SOFTBUS_OK;
187 }
188 
Disconnect(struct ProxyConnection * connection)189 static int32_t Disconnect(struct ProxyConnection *connection)
190 {
191     CONN_CHECK_AND_RETURN_RET_LOGE(connection != NULL,
192                                    SOFTBUS_INVALID_PARAM, CONN_PROXY, "connection is null");
193     int32_t ret = SoftBusMutexLock(&connection->lock);
194     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_PROXY,
195         "br disconnect lock failed, connId=%{public}u, ret=%{public}d", connection->channelId, ret);
196     int32_t socketHandle = connection->socketHandle;
197     if (connection->socketHandle == BR_INVALID_SOCKET_HANDLE) {
198         connection->state = PROXY_CHANNEL_DISCONNECTED;
199         SoftBusMutexUnlock(&connection->lock);
200         return SOFTBUS_OK;
201     }
202     connection->socketHandle = BR_INVALID_SOCKET_HANDLE;
203     connection->state = PROXY_CHANNEL_DISCONNECTED;
204     SoftBusMutexUnlock(&connection->lock);
205     // ensure that the underlayer schedules read/write before disconnection
206     SoftBusSleepMs(WAIT_DISCONNECT_TIME_MS);
207     return g_sppDriver->DisConnect(socketHandle);
208 }
209 
Send(struct ProxyConnection * connection,const uint8_t * data,uint32_t dataLen)210 static int32_t Send(struct ProxyConnection *connection, const uint8_t *data, uint32_t dataLen)
211 {
212     CONN_CHECK_AND_RETURN_RET_LOGE(connection != NULL,
213                                    SOFTBUS_INVALID_PARAM, CONN_PROXY, "connection is null");
214     int32_t ret = SoftBusMutexLock(&connection->lock);
215     CONN_CHECK_AND_RETURN_RET_LOGE(ret == SOFTBUS_OK, ret, CONN_PROXY,
216         "lock connection failed, channelId=%{public}u, ret=%{public}d", connection->channelId, ret);
217     if (connection->state != PROXY_CHANNEL_CONNECTED) {
218         CONN_LOGE(CONN_PROXY, "connection is not ready, currentState=%{public}d", connection->state);
219         SoftBusMutexUnlock(&connection->lock);
220         return SOFTBUS_INVALID_PARAM;
221     }
222     SoftBusMutexUnlock(&connection->lock);
223 
224     int32_t waitWriteLen = (int32_t)dataLen;
225     while (waitWriteLen > 0) {
226         int32_t ret = SoftBusMutexLock(&connection->lock);
227         if (ret != SOFTBUS_OK) {
228             return ret;
229         }
230         int32_t socketHandle = connection->socketHandle;
231         SoftBusMutexUnlock(&connection->lock);
232 
233         if (socketHandle == BR_INVALID_SOCKET_HANDLE) {
234             CONN_LOGE(CONN_PROXY, "invalid handle");
235             return SOFTBUS_INVALID_PARAM;
236         }
237         int32_t written = g_sppDriver->Write(socketHandle, data, waitWriteLen);
238         if (written < 0) {
239             CONN_LOGE(CONN_PROXY,
240                 "send data failed, channelId=%{public}u, totalLen=%{public}u, waitWriteLen=%{public}d, "
241                 "alreadyWriteLen=%{public}d, error=%{public}d",
242                 connection->channelId, dataLen, waitWriteLen, dataLen - waitWriteLen, written);
243             return SOFTBUS_CONN_BR_UNDERLAY_WRITE_FAIL;
244         }
245         data += written;
246         waitWriteLen -= written;
247     }
248     return SOFTBUS_OK;
249 }
250 
RegisterEventListener(const ProxyEventListener * listener)251 int32_t RegisterEventListener(const ProxyEventListener *listener)
252 {
253     CONN_CHECK_AND_RETURN_RET_LOGE(listener != NULL, SOFTBUS_INVALID_PARAM, CONN_PROXY, "listener is null");
254     CONN_CHECK_AND_RETURN_RET_LOGE(listener->onDisconnected != NULL, SOFTBUS_INVALID_PARAM,
255         CONN_PROXY, "onDisconnected is null");
256     CONN_CHECK_AND_RETURN_RET_LOGE(listener->onDataReceived != NULL, SOFTBUS_INVALID_PARAM,
257         CONN_PROXY, "onDataReceived is null");
258     g_eventListener = *listener;
259     g_sppDriver = InitSppSocketDriver();
260     CONN_CHECK_AND_RETURN_RET_LOGE(g_sppDriver != NULL, SOFTBUS_CONN_PROXY_INTERNAL_ERR, CONN_INIT,
261         "init spp socket driver failed");
262     return SOFTBUS_OK;
263 }
264 
265 ProxyBrConnectionManager g_proxyBrConnection = {
266     .connect = ProxyBrConnect,
267     .disconnect = Disconnect,
268     .send = Send,
269     .registerEventListener = RegisterEventListener,
270 };
271 
GetProxyBrConnectionManager(void)272 ProxyBrConnectionManager *GetProxyBrConnectionManager(void)
273 {
274     return &g_proxyBrConnection;
275 }