1 /*
2 * Copyright (c) 2024 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 "net_connection_ffi.h"
17 #include "connection_exec.h"
18 #include "js_native_api.h"
19 #include "js_native_api_types.h"
20 #include "net_all_capabilities.h"
21 #include "net_conn_client.h"
22 #include "net_connection_impl.h"
23 #include "net_handle.h"
24 #include "net_link_info.h"
25 #include "net_manager_constants.h"
26 #include "net_specifier.h"
27 #include <arpa/inet.h>
28 #include <netdb.h>
29
30 namespace OHOS::NetManagerStandard {
31
32 constexpr int32_t NO_PERMISSION_CODE = 1;
33 constexpr int32_t RESOURCE_UNAVALIEBLE_CODE = 11;
34 constexpr int32_t NET_UNREACHABLE_CODE = 101;
35 static constexpr size_t MAX_IPV4_STR_LEN_FFI = 16;
36 static constexpr size_t MAX_IPV6_STR_LEN_FFI = 64;
37
38 EXTERN_C_START
TransErrorCode(int32_t error)39 int32_t TransErrorCode(int32_t error)
40 {
41 switch (error) {
42 case NO_PERMISSION_CODE:
43 return NETMANAGER_ERR_PERMISSION_DENIED;
44 case RESOURCE_UNAVALIEBLE_CODE:
45 return NETMANAGER_ERR_INVALID_PARAMETER;
46 case NET_UNREACHABLE_CODE:
47 return NETMANAGER_ERR_INTERNAL;
48 default:
49 return NETMANAGER_ERR_OPERATION_FAILED;
50 }
51 }
52
CJ_CreateNetConnection(CNetSpecifier netSpecifier,uint32_t timeout)53 int64_t CJ_CreateNetConnection(CNetSpecifier netSpecifier, uint32_t timeout)
54 {
55 auto connection = FFI::FFIData::Create<NetConnectionProxy>(netSpecifier, timeout);
56 if (!connection) {
57 return ERR_INVALID_INSTANCE_CODE;
58 }
59 return connection->GetID();
60 }
61
CJ_ReleaseNetConnection(int64_t connId)62 void CJ_ReleaseNetConnection(int64_t connId)
63 {
64 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
65 if (!instance) {
66 return;
67 }
68 instance->Release();
69 FFI::FFIData::Release(connId);
70 }
71
CJ_GetDefaultNet(int32_t & netId)72 int32_t CJ_GetDefaultNet(int32_t &netId)
73 {
74 NetHandle netHandle;
75 auto ret = NetConnClient::GetInstance().GetDefaultNet(netHandle);
76 if (ret == NETMANAGER_SUCCESS) {
77 netId = netHandle.GetNetId();
78 }
79 return ret;
80 }
81
ParseAddrInfo(addrinfo * res,std::vector<CNetAddress> & addresses_)82 void ParseAddrInfo(addrinfo *res, std::vector<CNetAddress> &addresses_)
83 {
84 for (addrinfo *tmp = res; tmp != nullptr; tmp = tmp->ai_next) {
85 std::string host_;
86 if (tmp->ai_family == AF_INET) {
87 auto addr = reinterpret_cast<sockaddr_in *>(tmp->ai_addr);
88 char ip[MAX_IPV4_STR_LEN_FFI] = {0};
89 inet_ntop(AF_INET, &addr->sin_addr, ip, sizeof(ip));
90 host_ = ip;
91 } else if (tmp->ai_family == AF_INET6) {
92 auto addr = reinterpret_cast<sockaddr_in6 *>(tmp->ai_addr);
93 char ip[MAX_IPV6_STR_LEN_FFI] = {0};
94 inet_ntop(AF_INET6, &addr->sin6_addr, ip, sizeof(ip));
95 host_ = ip;
96 }
97
98 uint16_t port = 0;
99 if (tmp->ai_addr->sa_family == AF_INET) {
100 auto addr4 = reinterpret_cast<sockaddr_in *>(tmp->ai_addr);
101 port = addr4->sin_port;
102 } else if (tmp->ai_addr->sa_family == AF_INET6) {
103 auto addr6 = reinterpret_cast<sockaddr_in6 *>(tmp->ai_addr);
104 port = addr6->sin6_port;
105 }
106
107 CNetAddress address = {.address = MallocCString(host_), .family = tmp->ai_addr->sa_family, .port = port};
108 addresses_.emplace_back(address);
109 }
110 }
111
CJ_GetAddressesByName(int32_t netId,const char * host)112 RetNetAddressArr CJ_GetAddressesByName(int32_t netId, const char *host)
113 {
114 RetNetAddressArr ret = {.code = NETMANAGER_ERROR, .size = 0, .data = nullptr};
115 addrinfo *res = nullptr;
116 queryparam param;
117 param.qp_type = QEURY_TYPE_NORMAL;
118 param.qp_netid = netId;
119 int status = getaddrinfo_ext(host, nullptr, nullptr, &res, ¶m);
120 if (status < 0) {
121 ret.code = TransErrorCode(errno);
122 NETMANAGER_BASE_LOGE("getaddrinfo_ext errno %{public}d %{public}s", errno, strerror(errno));
123 return ret;
124 }
125 ret.code = status;
126
127 std::vector<CNetAddress> addresses_;
128 ParseAddrInfo(res, addresses_);
129 freeaddrinfo(res);
130
131 ret.size = static_cast<int64_t>(addresses_.size());
132 if (ret.size > 0) {
133 ret.data = static_cast<CNetAddress *>(malloc(sizeof(CNetAddress) * ret.size));
134 if (ret.data == nullptr) {
135 ret.code = NETMANAGER_ERR_INTERNAL;
136 return ret;
137 }
138 for (int64_t i = 0; i < ret.size; i++) {
139 ret.data[i] = CNetAddress(addresses_[i]);
140 }
141 }
142 return ret;
143 }
144
CJ_IsDefaultNetMetered(bool & ret)145 int32_t CJ_IsDefaultNetMetered(bool &ret)
146 {
147 ret = false;
148 return NetConnClient::GetInstance().IsDefaultNetMetered(ret);
149 }
150
CJ_HasDefaultNet(bool & ret)151 int32_t CJ_HasDefaultNet(bool &ret)
152 {
153 ret = false;
154 return NetConnClient::GetInstance().HasDefaultNet(ret);
155 }
156
CJ_GetNetCapabilities(int32_t netId,CNetCapabilities & ret)157 int32_t CJ_GetNetCapabilities(int32_t netId, CNetCapabilities &ret)
158 {
159 NetHandle netHandle{netId};
160 NetAllCapabilities capabilities;
161 auto code = NetConnClient::GetInstance().GetNetCapabilities(netHandle, capabilities);
162 if (code == NETMANAGER_SUCCESS) {
163 ret.linkUpBandwidthKbps = capabilities.linkUpBandwidthKbps_;
164 ret.linkDownBandwidthKbps = capabilities.linkDownBandwidthKbps_;
165 ret.bearedTypeSize = static_cast<int64_t>(capabilities.bearerTypes_.size());
166 ret.networkCapSize = static_cast<int64_t>(capabilities.netCaps_.size());
167 if (ret.bearedTypeSize > 0) {
168 ret.bearerTypes = static_cast<int32_t *>(malloc(sizeof(int32_t) * ret.bearedTypeSize));
169 if (ret.bearerTypes == nullptr) {
170 return NETMANAGER_ERR_INTERNAL;
171 }
172 int i = 0;
173 for (auto it = capabilities.bearerTypes_.begin(); it != capabilities.bearerTypes_.end(); ++it) {
174 ret.bearerTypes[i] = *it;
175 i++;
176 }
177 }
178 if (ret.networkCapSize > 0) {
179 ret.networkCap = static_cast<int32_t *>(malloc(sizeof(int32_t) * ret.networkCapSize));
180 if (ret.networkCap == nullptr) {
181 free(ret.bearerTypes);
182 ret.bearerTypes = nullptr;
183 return NETMANAGER_ERR_INTERNAL;
184 }
185 int i = 0;
186 for (auto it = capabilities.netCaps_.begin(); it != capabilities.netCaps_.end(); ++it) {
187 ret.networkCap[i] = *it;
188 i++;
189 }
190 }
191 }
192 return code;
193 }
194
SetLinkAddr(NetLinkInfo & linkInfo,CConnectionProperties & ret)195 bool SetLinkAddr(NetLinkInfo &linkInfo, CConnectionProperties &ret)
196 {
197 if (ret.linkAddressSize > 0) {
198 ret.linkAddresses = static_cast<CLinkAddress *>(malloc(sizeof(CLinkAddress) * ret.linkAddressSize));
199 if (ret.linkAddresses == nullptr) {
200 return false;
201 }
202 int i = 0;
203 for (auto it = linkInfo.netAddrList_.begin(); it != linkInfo.netAddrList_.end(); ++it, ++i) {
204 CNetAddress netAddr{.address = MallocCString(it->address_), .family = it->family_, .port = it->port_};
205 ret.linkAddresses[i] = CLinkAddress{.address = netAddr, .prefixLength = it->prefixlen_};
206 }
207 }
208 return true;
209 }
210
SetDns(NetLinkInfo & linkInfo,CConnectionProperties & ret)211 bool SetDns(NetLinkInfo &linkInfo, CConnectionProperties &ret)
212 {
213 if (ret.dnsSize > 0) {
214 ret.dnses = static_cast<CNetAddress *>(malloc(sizeof(CNetAddress) * ret.dnsSize));
215 if (ret.dnses == nullptr) {
216 free(ret.linkAddresses);
217 ret.linkAddresses = nullptr;
218 return false;
219 }
220 int i = 0;
221 for (auto it = linkInfo.dnsList_.begin(); it != linkInfo.dnsList_.end(); ++it, ++i) {
222 ret.dnses[i] =
223 CNetAddress{.address = MallocCString(it->address_), .family = it->family_, .port = it->port_};
224 }
225 }
226 return true;
227 }
228
SetRoute(NetLinkInfo & linkInfo,CConnectionProperties & ret)229 bool SetRoute(NetLinkInfo &linkInfo, CConnectionProperties &ret)
230 {
231 if (ret.routeSize > 0) {
232 ret.routes = static_cast<CRouteInfo *>(malloc(sizeof(CRouteInfo) * ret.routeSize));
233 if (ret.routes == nullptr) {
234 free(ret.linkAddresses);
235 free(ret.dnses);
236 ret.linkAddresses = nullptr;
237 ret.dnses = nullptr;
238 return false;
239 }
240 int i = 0;
241
242 for (auto it = linkInfo.routeList_.begin(); it != linkInfo.routeList_.end(); ++it, ++i) {
243 CNetAddress destAddr = {.address = MallocCString(it->destination_.address_),
244 .family = it->destination_.family_,
245 .port = it->destination_.port_};
246 CLinkAddress dest = {.address = destAddr, .prefixLength = it->destination_.prefixlen_};
247 CNetAddress gateway = {.address = MallocCString(it->gateway_.address_),
248 .family = it->gateway_.family_,
249 .port = it->gateway_.port_};
250 ret.routes[i] = CRouteInfo{.interfaceName = MallocCString(it->iface_),
251 .destination = dest,
252 .gateway = gateway,
253 .hasGateway = it->hasGateway_,
254 .isDefaultRoute = it->isDefaultRoute_};
255 }
256 }
257 return true;
258 }
259
CJ_GetConnectionProperties(int32_t netId,CConnectionProperties & ret)260 int32_t CJ_GetConnectionProperties(int32_t netId, CConnectionProperties &ret)
261 {
262 NetHandle netHandle{netId};
263 NetLinkInfo linkInfo;
264 auto code = NetConnClient::GetInstance().GetConnectionProperties(netHandle, linkInfo);
265 if (code == NETMANAGER_SUCCESS) {
266 ret.interfaceName = MallocCString(linkInfo.ifaceName_);
267 ret.domains = MallocCString(linkInfo.domain_);
268 ret.mtu = linkInfo.mtu_;
269 ret.linkAddresses = nullptr;
270 ret.dnses = nullptr;
271 ret.routes = nullptr;
272 ret.linkAddressSize = static_cast<int64_t>(linkInfo.netAddrList_.size());
273 ret.dnsSize = static_cast<int64_t>(linkInfo.dnsList_.size());
274 ret.routeSize = static_cast<int64_t>(linkInfo.routeList_.size());
275
276 if (!SetLinkAddr(linkInfo, ret) || !SetDns(linkInfo, ret) || !SetRoute(linkInfo, ret)) {
277 free(ret.interfaceName);
278 free(ret.domains);
279 ret.interfaceName = nullptr;
280 ret.domains = nullptr;
281 return NETMANAGER_ERR_INTERNAL;
282 }
283 }
284 return code;
285 }
286
CJ_GetGlobalHttpProxy(CHttpProxy & chttpProxy)287 int32_t CJ_GetGlobalHttpProxy(CHttpProxy &chttpProxy)
288 {
289 HttpProxy httpProxy;
290 auto ret = NetConnClient::GetInstance().GetGlobalHttpProxy(httpProxy);
291 if (ret == NETMANAGER_SUCCESS) {
292 chttpProxy.host = MallocCString(httpProxy.GetHost());
293 chttpProxy.port = httpProxy.GetPort();
294 auto list = httpProxy.GetExclusionList();
295 chttpProxy.exclusionListSize = static_cast<int64_t>(list.size());
296 chttpProxy.exclusionList = MallocCStringList(list);
297 }
298 return ret;
299 }
300
CJ_GetDefaultHttpProxy(CHttpProxy & chttpProxy)301 int32_t CJ_GetDefaultHttpProxy(CHttpProxy &chttpProxy)
302 {
303 HttpProxy httpProxy;
304 auto ret = NetConnClient::GetInstance().GetDefaultHttpProxy(httpProxy);
305 if (ret == NETMANAGER_SUCCESS) {
306 chttpProxy.host = MallocCString(httpProxy.GetHost());
307 chttpProxy.port = httpProxy.GetPort();
308 auto list = httpProxy.GetExclusionList();
309 chttpProxy.exclusionListSize = static_cast<int64_t>(list.size());
310 chttpProxy.exclusionList = MallocCStringList(list);
311 }
312 return ret;
313 }
314
CJ_SetGlobalHttpProxy(CHttpProxy cHttpProxy)315 int32_t CJ_SetGlobalHttpProxy(CHttpProxy cHttpProxy)
316 {
317 std::string host(cHttpProxy.host);
318 std::string newHost = host;
319 std::list<std::string> exclusionList;
320 for (uint32_t i = 0; i < cHttpProxy.exclusionListSize; ++i) {
321 std::string tmp(cHttpProxy.exclusionList[i]);
322 std::string item = tmp;
323 exclusionList.push_back(item);
324 }
325 HttpProxy httpProxy(newHost, cHttpProxy.port, exclusionList);
326 return NetConnClient::GetInstance().SetGlobalHttpProxy(httpProxy);
327 }
328
CJ_GetAppNet(int32_t & netId)329 int32_t CJ_GetAppNet(int32_t &netId)
330 {
331 return NetConnClient::GetInstance().GetAppNet(netId);
332 }
333
CJ_SetAppNet(int32_t netId)334 int32_t CJ_SetAppNet(int32_t netId)
335 {
336 return NetConnClient::GetInstance().SetAppNet(netId);
337 }
338
CJ_GetAllNets()339 RetDataCArrI32 CJ_GetAllNets()
340 {
341 std::list<sptr<NetHandle>> netList;
342 auto code = NetConnClient::GetInstance().GetAllNets(netList);
343 CArrI32 data = {.head = nullptr, .size = 0 };
344 RetDataCArrI32 ret = {.code = code, .data = data};
345 if (code != NETMANAGER_SUCCESS) {
346 return ret;
347 }
348 auto listSize = netList.size();
349 ret.data.size = static_cast<int64_t>(listSize);
350 if (listSize > 0) {
351 int32_t *retValue = static_cast<int32_t *>(malloc(sizeof(int32_t) * listSize));
352 if (retValue == nullptr) {
353 ret.code = NETMANAGER_ERR_INTERNAL;
354 return ret;
355 }
356 int i = 0;
357 for (auto it = netList.begin(); it != netList.end(); ++it) {
358 NetHandle netHandle = *it->GetRefPtr();
359 retValue[i] = netHandle.GetNetId();
360 i++;
361 }
362 ret.data.head = retValue;
363 }
364
365 return ret;
366 }
367
CJ_EnableAirplaneMode()368 int32_t CJ_EnableAirplaneMode()
369 {
370 return NetConnClient::GetInstance().SetAirplaneMode(true);
371 }
372
CJ_DisableAirplaneMode()373 int32_t CJ_DisableAirplaneMode()
374 {
375 return NetConnClient::GetInstance().SetAirplaneMode(false);
376 }
377
CJ_ReportNetConnected(int32_t netId)378 int32_t CJ_ReportNetConnected(int32_t netId)
379 {
380 NetHandle netHandle{netId};
381 return NetConnClient::GetInstance().NetDetection(netHandle);
382 }
383
CJ_ReportNetDisconnected(int32_t netId)384 int32_t CJ_ReportNetDisconnected(int32_t netId)
385 {
386 NetHandle netHandle{netId};
387 return NetConnClient::GetInstance().NetDetection(netHandle);
388 }
389
CJ_NetHandleBindSocket(int32_t netId,int socketFd)390 int32_t CJ_NetHandleBindSocket(int32_t netId, int socketFd)
391 {
392 NetHandle handle(netId);
393 return handle.BindSocket(socketFd);
394 }
395
CJ_NetConnectionRegister(int64_t id)396 int32_t CJ_NetConnectionRegister(int64_t id)
397 {
398 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(id);
399 if (!instance) {
400 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, id);
401 return ERR_INVALID_INSTANCE_CODE;
402 }
403 return instance->RegisterCallback();
404 }
405
CJ_NetConnectionUnRegister(int64_t id)406 int32_t CJ_NetConnectionUnRegister(int64_t id)
407 {
408 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(id);
409 if (!instance) {
410 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, id);
411 return ERR_INVALID_INSTANCE_CODE;
412 }
413 return instance->UnregisterCallback();
414 }
415
CJ_OnNetAvailable(int64_t connId,void (* callback)(int32_t))416 void CJ_OnNetAvailable(int64_t connId, void (*callback)(int32_t))
417 {
418 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
419 if (!instance) {
420 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
421 return;
422 }
423 instance->OnNetAvailible(callback);
424 }
425
CJ_OnNetBlockStatusChange(int64_t connId,void (* callback)(int32_t,bool))426 void CJ_OnNetBlockStatusChange(int64_t connId, void (*callback)(int32_t, bool))
427 {
428 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
429 if (!instance) {
430 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
431 return;
432 }
433 instance->OnNetBlockStatusChange(callback);
434 }
435
CJ_OnNetCapabilitiesChange(int64_t connId,void (* callback)(CNetCapabilityInfo))436 void CJ_OnNetCapabilitiesChange(int64_t connId, void (*callback)(CNetCapabilityInfo))
437 {
438 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
439 if (!instance) {
440 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
441 return;
442 }
443 instance->OnNetCapabilitiesChange(callback);
444 }
445
CJ_OnNetConnectionPropertiesChange(int64_t connId,void (* callback)(int32_t,CConnectionProperties))446 void CJ_OnNetConnectionPropertiesChange(int64_t connId, void (*callback)(int32_t, CConnectionProperties))
447 {
448 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
449 if (!instance) {
450 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
451 return;
452 }
453 instance->OnNetConnectionPropertiesChange(callback);
454 }
455
CJ_OnNetLost(int64_t connId,void (* callback)(int32_t))456 void CJ_OnNetLost(int64_t connId, void (*callback)(int32_t))
457 {
458 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
459 if (!instance) {
460 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
461 return;
462 }
463 instance->OnNetLost(callback);
464 }
465
CJ_OnNetUnavailable(int64_t connId,void (* callback)())466 void CJ_OnNetUnavailable(int64_t connId, void (*callback)())
467 {
468 auto instance = FFI::FFIData::GetData<NetConnectionProxy>(connId);
469 if (!instance) {
470 NETMANAGER_BASE_LOGE("NetConnectionProxy instance not exist %{public}" PRId64, connId);
471 return;
472 }
473 instance->OnNetUnavailable(callback);
474 }
475
MallocCString(const std::string & origin)476 char *MallocCString(const std::string &origin)
477 {
478 if (origin.empty()) {
479 return nullptr;
480 }
481 auto len = origin.length() + 1;
482 char *res = static_cast<char *>(malloc(sizeof(char) * len));
483 if (res == nullptr) {
484 return nullptr;
485 }
486 return std::char_traits<char>::copy(res, origin.c_str(), len);
487 }
488
MallocCStringList(std::list<std::string> & list)489 char **MallocCStringList(std::list<std::string> &list)
490 {
491 auto size = list.size();
492 if (size <= 0) {
493 return nullptr;
494 }
495 auto arr = static_cast<char **>(malloc(sizeof(char *) * size));
496 if (arr == nullptr) {
497 return nullptr;
498 }
499 int i = 0;
500 for (auto it = list.begin(); it != list.end(); ++it) {
501 arr[i] = MallocCString(*it);
502 i++;
503 }
504 return arr;
505 }
506
FfiConvertNetHandle2Napi(napi_env env,uint32_t netId)507 napi_value FfiConvertNetHandle2Napi(napi_env env, uint32_t netId)
508 {
509 NetHandle netHandle{netId};
510 return ConnectionExec::CreateNetHandle(env, &netHandle);
511 }
512 EXTERN_C_END
513 } // namespace OHOS::NetManagerStandard