1 /*
2 * Copyright (c) 2021-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 "socket_exec.h"
17
18 #include <arpa/inet.h>
19 #include <atomic>
20 #include <cerrno>
21 #include <condition_variable>
22 #include <fcntl.h>
23 #include <map>
24 #include <memory>
25 #include <mutex>
26 #include <netinet/tcp.h>
27 #include <poll.h>
28 #include <sys/socket.h>
29 #include <thread>
30 #include <unistd.h>
31
32 #include "context_key.h"
33 #include "event_list.h"
34 #include "napi_utils.h"
35 #include "netstack_common_utils.h"
36 #include "netstack_log.h"
37 #include "securec.h"
38 #include "socket_async_work.h"
39 #include "socket_module.h"
40
41 namespace OHOS::NetStack::Socket::SocketExec {
ExecGetLocalAddress(GetLocalAddressContext * context)42 bool ExecGetLocalAddress(GetLocalAddressContext *context)
43 {
44 if (context == nullptr) {
45 NETSTACK_LOGE("context is nullptr");
46 return false;
47 }
48 auto socketFD = context->GetSocketFd();
49 struct sockaddr_storage addr{};
50 socklen_t addrLen = sizeof(addr);
51 if (getsockname(socketFD, (struct sockaddr *)&addr, &addrLen) < 0) {
52 context->SetNeedThrowException(true);
53 context->SetErrorCode(errno);
54 return false;
55 }
56
57 char ipStr[INET6_ADDRSTRLEN] = {0};
58 Socket::NetAddress localAddress;
59 if (addr.ss_family == AF_INET) {
60 auto *addrIn = reinterpret_cast<struct sockaddr_in *>(&addr);
61 inet_ntop(AF_INET, &addrIn->sin_addr, ipStr, sizeof(ipStr));
62 localAddress.SetFamilyBySaFamily(AF_INET);
63 localAddress.SetRawAddress(ipStr);
64 localAddress.SetPort(ntohs(addrIn->sin_port));
65 context->localAddress_ = localAddress;
66 } else if (addr.ss_family == AF_INET6) {
67 auto *addrIn6 = reinterpret_cast<struct sockaddr_in6 *>(&addr);
68 inet_ntop(AF_INET6, &addrIn6->sin6_addr, ipStr, sizeof(ipStr));
69 localAddress.SetFamilyBySaFamily(AF_INET6);
70 localAddress.SetRawAddress(ipStr);
71 localAddress.SetPort(ntohs(addrIn6->sin6_port));
72 context->localAddress_ = localAddress;
73 }
74 return true;
75 }
76
ExecTcpServerGetLocalAddress(TcpServerGetLocalAddressContext * context)77 bool ExecTcpServerGetLocalAddress(TcpServerGetLocalAddressContext *context)
78 {
79 if (context == nullptr) {
80 NETSTACK_LOGE("context is nullptr");
81 return false;
82 }
83 auto socketFD = context->GetSocketFd();
84 struct sockaddr_storage addr{};
85 socklen_t addrLen = sizeof(addr);
86 if (getsockname(socketFD, (struct sockaddr *)&addr, &addrLen) < 0) {
87 context->SetNeedThrowException(true);
88 context->SetErrorCode(errno);
89 return false;
90 }
91
92 char ipStr[INET6_ADDRSTRLEN] = {0};
93 Socket::NetAddress localAddress;
94 if (addr.ss_family == AF_INET) {
95 auto *addrIn = reinterpret_cast<struct sockaddr_in *>(&addr);
96 inet_ntop(AF_INET, &addrIn->sin_addr, ipStr, sizeof(ipStr));
97 localAddress.SetFamilyBySaFamily(AF_INET);
98 localAddress.SetRawAddress(ipStr);
99 localAddress.SetPort(ntohs(addrIn->sin_port));
100 context->localAddress_ = localAddress;
101 } else if (addr.ss_family == AF_INET6) {
102 auto *addrIn6 = reinterpret_cast<struct sockaddr_in6 *>(&addr);
103 inet_ntop(AF_INET6, &addrIn6->sin6_addr, ipStr, sizeof(ipStr));
104 localAddress.SetFamilyBySaFamily(AF_INET6);
105 localAddress.SetRawAddress(ipStr);
106 localAddress.SetPort(ntohs(addrIn6->sin6_port));
107 context->localAddress_ = localAddress;
108 }
109 return true;
110 }
111
GetLocalAddressCallback(GetLocalAddressContext * context)112 napi_value GetLocalAddressCallback(GetLocalAddressContext *context)
113 {
114 napi_value obj = NapiUtils::CreateObject(context->GetEnv());
115 if (NapiUtils::GetValueType(context->GetEnv(), obj) != napi_object) {
116 return NapiUtils::GetUndefined(context->GetEnv());
117 }
118 auto env = context->GetEnv();
119 NapiUtils::SetStringPropertyUtf8(env, obj, KEY_ADDRESS, context->localAddress_.GetAddress());
120 NapiUtils::SetUint32Property(env, obj, KEY_FAMILY, context->localAddress_.GetJsValueFamily());
121 NapiUtils::SetUint32Property(env, obj, KEY_PORT, context->localAddress_.GetPort());
122 return obj;
123 }
124
TcpConnectionGetLocalAddressCallback(TcpConnectionGetLocalAddressContext * context)125 napi_value TcpConnectionGetLocalAddressCallback(TcpConnectionGetLocalAddressContext *context)
126 {
127 napi_value obj = NapiUtils::CreateObject(context->GetEnv());
128 if (NapiUtils::GetValueType(context->GetEnv(), obj) != napi_object) {
129 return NapiUtils::GetUndefined(context->GetEnv());
130 }
131 auto env = context->GetEnv();
132 NapiUtils::SetStringPropertyUtf8(env, obj, KEY_ADDRESS, context->localAddress_.GetAddress());
133 NapiUtils::SetUint32Property(env, obj, KEY_FAMILY, context->localAddress_.GetJsValueFamily());
134 NapiUtils::SetUint32Property(env, obj, KEY_PORT, context->localAddress_.GetPort());
135 return obj;
136 }
137
TcpServerGetLocalAddressCallback(TcpServerGetLocalAddressContext * context)138 napi_value TcpServerGetLocalAddressCallback(TcpServerGetLocalAddressContext *context)
139 {
140 napi_value obj = NapiUtils::CreateObject(context->GetEnv());
141 if (NapiUtils::GetValueType(context->GetEnv(), obj) != napi_object) {
142 return NapiUtils::GetUndefined(context->GetEnv());
143 }
144 auto env = context->GetEnv();
145 NapiUtils::SetStringPropertyUtf8(env, obj, KEY_ADDRESS, context->localAddress_.GetAddress());
146 NapiUtils::SetUint32Property(env, obj, KEY_FAMILY, context->localAddress_.GetJsValueFamily());
147 NapiUtils::SetUint32Property(env, obj, KEY_PORT, context->localAddress_.GetPort());
148 return obj;
149 }
150 } // namespace OHOS::NetStack::Socket::SocketExec
151