• 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 
16 #include <map>
17 #include <string>
18 
19 #include "conn_log.h"
20 #include "napi_link_enhance_error_code.h"
21 #include "napi_link_enhance_connection.h"
22 #include "napi_link_enhance_server.h"
23 #include "napi_link_enhance_utils.h"
24 #include "napi_link_enhance_object.h"
25 #include "softbus_adapter_mem.h"
26 #include "softbus_connection.h"
27 #include "softbus_utils.h"
28 
29 namespace Communication {
30 namespace OHOS::Softbus {
31 
32 EXTERN_C_START
33 
OnAcceptConnectAdapter(const char * name,uint32_t handle)34 static int32_t OnAcceptConnectAdapter(const char *name, uint32_t handle)
35 {
36     COMM_LOGI(COMM_SDK, "accept new connection, handle=%{public}u", handle);
37     CONN_CHECK_AND_RETURN_RET_LOGE(name != nullptr, SOFTBUS_INVALID_PARAM, COMM_SDK, "name is nullptr");
38     std::string serverName = name;
39     std::string deviceId = "";
40     NapiLinkEnhanceServer *enhanceServer = nullptr;
41     {
42         std::lock_guard<std::mutex> guard(NapiLinkEnhanceServer::serverMapMutex_);
43         if (NapiLinkEnhanceServer::enhanceServerMap_.count(serverName) > 0) {
44             enhanceServer = NapiLinkEnhanceServer::enhanceServerMap_[serverName];
45         }
46     }
47 
48     if (enhanceServer == nullptr || enhanceServer->env_ == nullptr ||
49         !enhanceServer->IsAcceptedEnable()) {
50         COMM_LOGE(COMM_SDK, "server status error, name=%{public}s", name);
51         return LINK_ENHANCE_PARAMETER_INVALID;
52     }
53     uint32_t inHandle = handle;
54     auto func = [enhanceServer, serverName, deviceId, inHandle]() {
55         napi_value argvOut[ARGS_SIZE_ONE] = { nullptr };
56         size_t argc = ARGS_SIZE_THREE;
57         napi_value nHandle = nullptr;
58         napi_status status = napi_create_uint32(enhanceServer->env_, inHandle, &nHandle);
59         if (status != napi_ok) {
60             return;
61         }
62 
63         napi_value argv[ARGS_SIZE_THREE] = { nullptr };
64         argv[PARAM0] = NapiGetStringRet(enhanceServer->env_, deviceId),
65         argv[PARAM1] = NapiGetStringRet(enhanceServer->env_, serverName),
66         argv[PARAM2] = nHandle;
67 
68         napi_value constructor = nullptr;
69         if (napi_get_reference_value(enhanceServer->env_,
70             NapiLinkEnhanceConnection::consRef_, &constructor) != napi_ok) {
71             COMM_LOGE(COMM_SDK, "get connection constructor failed");
72             return;
73         }
74         if (napi_new_instance(enhanceServer->env_, constructor, argc, argv, &argvOut[ARGS_SIZE_ZERO]) != napi_ok) {
75             COMM_LOGE(COMM_SDK, "create js new connection object failed");
76             return;
77         }
78         NapiCallFunction(enhanceServer->env_, enhanceServer->acceptConnectRef_, argvOut, ARGS_SIZE_ONE);
79     };
80     return DoInJsMainThread(enhanceServer->env_, std::move(func));
81 }
82 
NotifyDisconnected(NapiLinkEnhanceConnection * connection,int32_t reason)83 static int32_t NotifyDisconnected(NapiLinkEnhanceConnection *connection, int32_t reason)
84 {
85     COMM_LOGI(COMM_SDK, "disconnected, handle=%{public}u, reason=%{public}d", connection->handle_, reason);
86     if (!connection->IsDisconnectEnable()) {
87         COMM_LOGW(COMM_SDK, "not register disconnect listener");
88         return SOFTBUS_CONN_GENERAL_LISTENER_NOT_ENABLE;
89     }
90     auto func = [connection, reason]() {
91         napi_value disconnectReason = NapiGetInt32Ret(connection->env_, reason);
92         napi_value argv[ARGS_SIZE_ONE] = { nullptr };
93         argv[ARGS_SIZE_ZERO] = disconnectReason;
94         NapiCallFunction(connection->env_, connection->disconnectRef_, argv, ARGS_SIZE_ONE);
95     };
96     return DoInJsMainThread(connection->env_, std::move(func));
97 }
98 
NotifyConnectResult(NapiLinkEnhanceConnection * connection,bool success,int32_t reason)99 static int32_t NotifyConnectResult(NapiLinkEnhanceConnection *connection, bool success, int32_t reason)
100 {
101     if (!connection->IsConnectResultEnable()) {
102         COMM_LOGE(COMM_SDK, "not register connect result listener");
103         return SOFTBUS_CONN_GENERAL_LISTENER_NOT_ENABLE;
104     }
105     COMM_LOGI(COMM_SDK, "find connection object, handle=%{public}u, success=%{public}d", connection->handle_, success);
106     connection->state_ = success ? ConnectionState::STATE_CONNECTED : ConnectionState::STATE_DISCONNECTED;
107     int32_t napiReason = reason;
108     if (napiReason != 0) {
109         napiReason = ConvertToJsErrcode(reason);
110     }
111     auto func = [connection, success, napiReason]() {
112         auto changeState = std::make_shared<NapiConnectionChangeState>(connection->deviceId_,
113             success, napiReason);
114         napi_value argv[ARGS_SIZE_ONE] = { nullptr };
115         argv[ARGS_SIZE_ZERO] = changeState->ToNapiValue(connection->env_);
116         NapiCallFunction(connection->env_, connection->connectResultRef_, argv, ARGS_SIZE_ONE);
117     };
118     return DoInJsMainThread(connection->env_, std::move(func));
119 }
120 
NotifyConnectionStateChange(NapiLinkEnhanceConnection * connection,int32_t status,int32_t reason)121 static int32_t NotifyConnectionStateChange(NapiLinkEnhanceConnection *connection, int32_t status, int32_t reason)
122 {
123     if (connection->state_ == ConnectionState::STATE_CONNECTING) {
124         bool success = (status == CONNECTION_STATE_CONNECTED_SUCCESS);
125         return NotifyConnectResult(connection, success, reason);
126     }
127     if (status == CONNECTION_STATE_DISCONNECTED) {
128         return NotifyDisconnected(connection, reason);
129     }
130     return LINK_ENHANCE_PARAMETER_INVALID;
131 }
132 
OnConnectionStateChangeAdapter(uint32_t handle,int32_t status,int32_t reason)133 static int32_t OnConnectionStateChangeAdapter(uint32_t handle, int32_t status, int32_t reason)
134 {
135     COMM_LOGI(COMM_SDK, "connection state change, handle=%{public}u, state=%{public}d, reason=%{public}d", handle,
136         status, reason);
137     std::lock_guard<std::mutex> guard(NapiLinkEnhanceConnection::connectionListMutex_);
138     int32_t ret = LINK_ENHANCE_PARAMETER_INVALID;
139     for (auto iter = NapiLinkEnhanceConnection::connectionList_.begin();
140         iter != NapiLinkEnhanceConnection::connectionList_.end();) {
141         NapiLinkEnhanceConnection *connection = *iter;
142         if (handle == 0) {
143             // indicates that server is died and clear all connections
144             ret = NotifyConnectionStateChange(connection, status, reason);
145             iter = NapiLinkEnhanceConnection::connectionList_.erase(iter);
146             continue;
147         }
148         if (connection->handle_ == handle) {
149             ret = NotifyConnectionStateChange(connection, status, reason);
150             if (status != CONNECTION_STATE_CONNECTED_SUCCESS) {
151                 NapiLinkEnhanceConnection::connectionList_.erase(iter);
152             }
153             return ret;
154         } else {
155             iter++;
156         }
157     }
158     return ret;
159 }
160 
NotifyDataReceived(NapiLinkEnhanceConnection * connection,const uint8_t * data,uint32_t len)161 static void NotifyDataReceived(NapiLinkEnhanceConnection *connection, const uint8_t *data, uint32_t len)
162 {
163     if (!connection->IsDataReceiveEnable()) {
164         COMM_LOGE(COMM_SDK, "not register data recv listener");
165         return;
166     }
167     auto outData = std::shared_ptr<uint8_t>(new uint8_t[len], std::default_delete<uint8_t[]>());
168     if (outData == nullptr || memcpy_s(outData.get(), len, data, len) != EOK) {
169         return;
170     }
171     auto func = [connection, outData, len]() {
172         napi_value arrayBuffer = nullptr;
173         void *dataBuffer = nullptr;
174         int32_t status = napi_create_arraybuffer(connection->env_, len, &dataBuffer, &arrayBuffer);
175         if (status != napi_ok) {
176             COMM_LOGE(COMM_SDK, "create data array object failed");
177             return;
178         }
179         (void)memcpy_s(dataBuffer, len, outData.get(), len);
180         napi_value argv[ARGS_SIZE_ONE] = { nullptr };
181         argv[ARGS_SIZE_ZERO] = arrayBuffer;
182         NapiCallFunction(connection->env_, connection->dataReceivedRef_, argv, ARGS_SIZE_ONE);
183     };
184     (void)DoInJsMainThread(connection->env_, std::move(func));
185 }
186 
OnDataReceivedAdapter(uint32_t handle,const uint8_t * data,uint32_t len)187 static void OnDataReceivedAdapter(uint32_t handle, const uint8_t *data, uint32_t len)
188 {
189     CONN_CHECK_AND_RETURN_LOGE(data != nullptr, COMM_SDK, "data is nullptr");
190     COMM_LOGI(COMM_SDK, "connection data received, handle=%{public}u, len=%{public}u", handle, len);
191     std::lock_guard<std::mutex> guard(NapiLinkEnhanceConnection::connectionListMutex_);
192     for (uint32_t i = 0; i < NapiLinkEnhanceConnection::connectionList_.size(); i++) {
193         NapiLinkEnhanceConnection *connection = NapiLinkEnhanceConnection::connectionList_[i];
194         if (connection->handle_ == handle) {
195             COMM_LOGI(COMM_SDK, "find connection object, handle=%{public}u", handle);
196             NotifyDataReceived(connection, data, len);
197             return;
198         }
199     }
200     return;
201 }
202 
OnServiceDiedAdapter(void)203 static void OnServiceDiedAdapter(void)
204 {
205     COMM_LOGI(COMM_SDK, "service died");
206     std::lock_guard<std::mutex> guard(NapiLinkEnhanceServer::serverMapMutex_);
207     for (auto iter = NapiLinkEnhanceServer::enhanceServerMap_.begin();
208         iter != NapiLinkEnhanceServer::enhanceServerMap_.end();) {
209         NapiLinkEnhanceServer *server = iter->second;
210         if (!server->IsStopEnable()) {
211             COMM_LOGI(COMM_SDK, "server not enable stop listener");
212             iter = NapiLinkEnhanceServer::enhanceServerMap_.erase(iter);
213             continue;
214         }
215         auto func = [server]() {
216             napi_value closeReason = NapiGetInt32Ret(server->env_, LINK_ENHANCE_SERVER_DIED);
217             napi_value argv[ARGS_SIZE_ONE] = { nullptr };
218             argv[ARGS_SIZE_ZERO] = closeReason;
219             NapiCallFunction(server->env_, server->serverStopRef_, argv, ARGS_SIZE_ONE);
220         };
221         (void)DoInJsMainThread(server->env_, std::move(func));
222         iter = NapiLinkEnhanceServer::enhanceServerMap_.erase(iter);
223     }
224 }
225 
226 static IGeneralListener g_listener = {
227     .OnAcceptConnect = OnAcceptConnectAdapter,
228     .OnConnectionStateChange = OnConnectionStateChangeAdapter,
229     .OnDataReceived = OnDataReceivedAdapter,
230     .OnServiceDied = OnServiceDiedAdapter,
231 };
232 
233 /*
234  * Module initialization function
235  */
Init(napi_env env,napi_value exports)236 static napi_value Init(napi_env env, napi_value exports)
237 {
238     COMM_LOGI(COMM_SDK, "enhance manager init start");
239     NapiLinkEnhanceServer::DefineJSClass(env);
240     NapiLinkEnhanceConnection::DefineJSClass(env);
241     PropertyInit(env, exports);
242     napi_property_descriptor desc[] = {
243         DECLARE_NAPI_FUNCTION("createServer", NapiLinkEnhanceServer::Create),
244         DECLARE_NAPI_FUNCTION("createConnection", NapiLinkEnhanceConnection::Create),
245     };
246     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
247 
248     int32_t ret = GeneralRegisterListener(&g_listener);
249     if (ret != 0) {
250         COMM_LOGE(COMM_SDK, "enhance manager register listener failed ret=%{public}d", ret);
251     }
252     return exports;
253 }
254 EXTERN_C_END
255 /*
256  * Module define
257  */
258 static napi_module enhanceConnectionModule = {
259     .nm_version = 1,
260     .nm_flags = 0,
261     .nm_filename = nullptr,
262     .nm_register_func = Init,
263     .nm_modname = "distributedsched.linkEnhance",
264     .nm_priv = ((void *)0),
265     .reserved = { 0 }
266 };
267 /*
268  * Module register function
269  */
RegisterModule(void)270 extern "C" __attribute__((constructor)) void RegisterModule(void)
271 {
272     COMM_LOGI(
273         COMM_SDK, "Register enhanceConnectionModule nm_modname:%{public}s", enhanceConnectionModule.nm_modname);
274     napi_module_register(&enhanceConnectionModule);
275 }
276 } // namespace Softbus
277 } // namespace Communication