• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &param);
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