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