1 /*
2  * Copyright (c) 2023-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 #include "local_socket_context.h"
16 
17 #include "context_key.h"
18 #include "event_manager.h"
19 #include "napi_utils.h"
20 #include "netstack_log.h"
21 #include "socket_constant.h"
22 
23 namespace OHOS::NetStack::Socket {
GetSocketFd() const24 int LocalSocketBaseContext::GetSocketFd() const
25 {
26     if (manager_ == nullptr) {
27         return -1;
28     }
29     LocalSocketManager *pMgr = reinterpret_cast<LocalSocketManager *>(manager_->GetData());
30     return (pMgr != nullptr) ? pMgr->sockfd_ : -1;
31 }
32 
SetSocketFd(int sock)33 void LocalSocketBaseContext::SetSocketFd(int sock)
34 {
35     if (manager_ == nullptr) {
36         return;
37     }
38     if (auto pMgr = reinterpret_cast<LocalSocketManager *>(manager_->GetData()); pMgr != nullptr) {
39         pMgr->sockfd_ = sock;
40     }
41 }
42 
GetErrorCode() const43 int32_t LocalSocketBaseContext::GetErrorCode() const
44 {
45     auto err = BaseContext::GetErrorCode();
46     if (err == PARSE_ERROR_CODE) {
47         return PARSE_ERROR_CODE;
48     }
49 
50     if (BaseContext::IsPermissionDenied()) {
51         return PERMISSION_DENIED_CODE;
52     }
53 
54 #if defined(IOS_PLATFORM)
55     err = ErrCodePlatformAdapter::GetOHOSErrCode(err);
56 #endif
57     return err + SOCKET_ERROR_CODE_BASE;
58 }
59 
GetErrorMessage() const60 std::string LocalSocketBaseContext::GetErrorMessage() const
61 {
62     if (BaseContext::IsPermissionDenied()) {
63         return PERMISSION_DENIED_MSG;
64     }
65 
66     auto errCode = BaseContext::GetErrorCode();
67     if (errCode == PARSE_ERROR_CODE) {
68         return PARSE_ERROR_MSG;
69     }
70 #if defined(IOS_PLATFORM)
71     std::string errMessage;
72     ErrCodePlatformAdapter::GetOHOSErrMessage(errCode, errMessage);
73     return errMessage;
74 #else
75     char err[MAX_ERR_NUM] = {0};
76     (void)strerror_r(errCode, err, MAX_ERR_NUM);
77     return err;
78 #endif
79 }
80 
CheckParamsWithOptions(napi_value * params,size_t paramsCount)81 bool LocalSocketBaseContext::CheckParamsWithOptions(napi_value *params, size_t paramsCount)
82 {
83     if (paramsCount == PARAM_JUST_OPTIONS) {
84         if (NapiUtils::GetValueType(GetEnv(), params[0]) != napi_object) {
85             NETSTACK_LOGE("first param is not object");
86             SetNeedThrowException(true);
87             SetError(PARSE_ERROR_CODE, PARSE_ERROR_MSG);
88             return false;
89         }
90     } else if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
91         if (NapiUtils::GetValueType(GetEnv(), params[0]) != napi_object) {
92             NETSTACK_LOGE("first param is not object");
93             SetNeedThrowException(true);
94             SetError(PARSE_ERROR_CODE, PARSE_ERROR_MSG);
95             return false;
96         }
97         if (NapiUtils::GetValueType(GetEnv(), params[1]) != napi_function) {
98             NETSTACK_LOGE("second param is not function");
99             return false;
100         }
101     } else {
102         NETSTACK_LOGE("invalid param count");
103         return false;
104     }
105     return true;
106 }
107 
CheckParamsWithoutOptions(napi_value * params,size_t paramsCount)108 bool LocalSocketBaseContext::CheckParamsWithoutOptions(napi_value *params, size_t paramsCount)
109 {
110     if (paramsCount == PARAM_NONE) {
111         return true;
112     }
113     if (paramsCount == PARAM_JUST_CALLBACK) {
114         if (NapiUtils::GetValueType(GetEnv(), params[0]) == napi_function) {
115             return true;
116         } else {
117             NETSTACK_LOGE("only one param and it is not callback");
118             SetNeedThrowException(true);
119             SetError(PARSE_ERROR_CODE, PARSE_ERROR_MSG);
120         }
121     }
122     return false;
123 }
124 
ParseParams(napi_value * params,size_t paramsCount)125 void LocalSocketBindContext::ParseParams(napi_value *params, size_t paramsCount)
126 {
127     if (!CheckParamsWithOptions(params, paramsCount)) {
128         return;
129     }
130     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_ADDRESS)) {
131         socketPath_ = NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], KEY_ADDRESS);
132         NETSTACK_LOGD("LocalSocketBindContext parse, path: %{public}s", socketPath_.c_str());
133     } else {
134         NETSTACK_LOGE("params do not contain socket path");
135     }
136     if (socketPath_.empty()) {
137         NETSTACK_LOGE("socket path is empty");
138     }
139     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
140         SetParseOK(SetCallback(params[1]) == napi_ok);
141         return;
142     }
143     SetParseOK(true);
144 }
145 
GetSocketPath() const146 const std::string &LocalSocketBindContext::GetSocketPath() const
147 {
148     return socketPath_;
149 }
150 
ParseParams(napi_value * params,size_t paramsCount)151 void LocalSocketConnectContext::ParseParams(napi_value *params, size_t paramsCount)
152 {
153     if (!CheckParamsWithOptions(params, paramsCount)) {
154         return;
155     }
156     if (!NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_ADDRESS)) {
157         NETSTACK_LOGE("no property named address");
158     }
159     napi_value netAddress = NapiUtils::GetNamedProperty(GetEnv(), params[0], KEY_ADDRESS);
160     if (!NapiUtils::HasNamedProperty(GetEnv(), netAddress, KEY_ADDRESS)) {
161         NETSTACK_LOGE("address is empty");
162     }
163     socketPath_ = NapiUtils::GetStringPropertyUtf8(GetEnv(), netAddress, KEY_ADDRESS);
164     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_TIMEOUT)) {
165         timeout_ = NapiUtils::GetInt32Property(GetEnv(), params[0], KEY_TIMEOUT);
166     }
167     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
168         SetParseOK(SetCallback(params[1]) == napi_ok);
169         return;
170     }
171     SetParseOK(true);
172 }
173 
GetSocketPath() const174 const std::string &LocalSocketConnectContext::GetSocketPath() const
175 {
176     return socketPath_;
177 }
178 
GetTimeoutMs() const179 int LocalSocketConnectContext::GetTimeoutMs() const
180 {
181     return timeout_;
182 }
183 
GetData(napi_value sendOptions)184 bool LocalSocketSendContext::GetData(napi_value sendOptions)
185 {
186     if (!NapiUtils::HasNamedProperty(GetEnv(), sendOptions, KEY_DATA)) {
187         return false;
188     }
189     napi_value jsData = NapiUtils::GetNamedProperty(GetEnv(), sendOptions, KEY_DATA);
190     if (NapiUtils::GetValueType(GetEnv(), jsData) == napi_string) {
191         std::string data = NapiUtils::GetStringFromValueUtf8(GetEnv(), jsData);
192         if (data.empty()) {
193             NETSTACK_LOGE("string data is empty");
194             return true;
195         }
196         options_.SetBuffer(data);
197         return true;
198     }
199 
200     if (NapiUtils::ValueIsArrayBuffer(GetEnv(), jsData)) {
201         size_t length = 0;
202         void *data = NapiUtils::GetInfoFromArrayBufferValue(GetEnv(), jsData, &length);
203         if (data == nullptr || length == 0) {
204             NETSTACK_LOGE("arraybuffer data is empty");
205             return true;
206         }
207         options_.SetBuffer(data, length);
208         return true;
209     }
210     return false;
211 }
212 
ParseParams(napi_value * params,size_t paramsCount)213 void LocalSocketSendContext::ParseParams(napi_value *params, size_t paramsCount)
214 {
215     if (!CheckParamsWithOptions(params, paramsCount)) {
216         return;
217     }
218     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_ENCODING)) {
219         std::string encoding = NapiUtils::GetStringPropertyUtf8(GetEnv(), params[0], KEY_ENCODING);
220         options_.SetEncoding(encoding);
221     }
222     if (!GetData(params[0])) {
223         return;
224     }
225     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
226         SetParseOK(SetCallback(params[1]) == napi_ok);
227         return;
228     }
229     SetParseOK(true);
230 }
231 
GetOptionsRef()232 LocalSocketOptions &LocalSocketSendContext::GetOptionsRef()
233 {
234     return options_;
235 }
236 
ParseParams(napi_value * params,size_t paramsCount)237 void LocalSocketCloseContext::ParseParams(napi_value *params, size_t paramsCount)
238 {
239     if (!CheckParamsWithoutOptions(params, paramsCount)) {
240         return;
241     }
242     if (paramsCount != PARAM_NONE) {
243         SetParseOK(SetCallback(params[0]) == napi_ok);
244         return;
245     }
246     SetParseOK(true);
247 }
248 
ParseParams(napi_value * params,size_t paramsCount)249 void LocalSocketGetStateContext::ParseParams(napi_value *params, size_t paramsCount)
250 {
251     if (!CheckParamsWithoutOptions(params, paramsCount)) {
252         return;
253     }
254     if (paramsCount != PARAM_NONE) {
255         SetParseOK(SetCallback(params[0]) == napi_ok);
256         return;
257     }
258     SetParseOK(true);
259 }
260 
GetStateRef()261 SocketStateBase &LocalSocketGetStateContext::GetStateRef()
262 {
263     return state_;
264 }
265 
ParseParams(napi_value * params,size_t paramsCount)266 void LocalSocketGetSocketFdContext::ParseParams(napi_value *params, size_t paramsCount)
267 {
268     if (!CheckParamsWithoutOptions(params, paramsCount)) {
269         return;
270     }
271     if (paramsCount != PARAM_NONE) {
272         SetParseOK(SetCallback(params[0]) == napi_ok);
273         return;
274     }
275     SetParseOK(true);
276 }
277 
ParseParams(napi_value * params,size_t paramsCount)278 void LocalSocketSetExtraOptionsContext::ParseParams(napi_value *params, size_t paramsCount)
279 {
280     if (!CheckParamsWithOptions(params, paramsCount)) {
281         return;
282     }
283     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_RECEIVE_BUFFER_SIZE)) {
284         options_.SetReceiveBufferSize(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_RECEIVE_BUFFER_SIZE));
285         options_.SetRecvBufSizeFlag(true);
286     }
287     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SEND_BUFFER_SIZE)) {
288         options_.SetSendBufferSize(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_SEND_BUFFER_SIZE));
289         options_.SetSendBufSizeFlag(true);
290     }
291     if (NapiUtils::HasNamedProperty(GetEnv(), params[0], KEY_SOCKET_TIMEOUT)) {
292         options_.SetSocketTimeout(NapiUtils::GetUint32Property(GetEnv(), params[0], KEY_SOCKET_TIMEOUT));
293         options_.SetTimeoutFlag(true);
294     }
295     if (paramsCount == PARAM_OPTIONS_AND_CALLBACK) {
296         SetParseOK(SetCallback(params[1]) == napi_ok);
297         return;
298     }
299     SetParseOK(true);
300 }
301 
GetOptionsRef()302 LocalExtraOptions &LocalSocketSetExtraOptionsContext::GetOptionsRef()
303 {
304     return options_;
305 }
306 
ParseParams(napi_value * params,size_t paramsCount)307 void LocalSocketGetExtraOptionsContext::ParseParams(napi_value *params, size_t paramsCount)
308 {
309     if (!CheckParamsWithoutOptions(params, paramsCount)) {
310         return;
311     }
312     if (paramsCount != PARAM_NONE) {
313         SetParseOK(SetCallback(params[0]) == napi_ok);
314         return;
315     }
316     SetParseOK(true);
317 }
318 
GetOptionsRef()319 LocalExtraOptions &LocalSocketGetExtraOptionsContext::GetOptionsRef()
320 {
321     return options_;
322 }
323 
ParseParams(napi_value * params,size_t paramsCount)324 void LocalSocketGetLocalAddressContext::ParseParams(napi_value *params, size_t paramsCount)
325 {
326     if (paramsCount != PARAM_NONE) {
327         NETSTACK_LOGE("get local address param error");
328         SetNeedThrowException(true);
329         SetError(PARSE_ERROR_CODE, PARSE_ERROR_MSG);
330         return;
331     }
332     SetParseOK(true);
333 }
334 
SetSocketPath(const std::string socketPath)335 void LocalSocketGetLocalAddressContext::SetSocketPath(const std::string socketPath)
336 {
337     socketPath_ = socketPath;
338 }
339 
GetSocketPath()340 std::string LocalSocketGetLocalAddressContext::GetSocketPath()
341 {
342     return socketPath_;
343 }
344 } // namespace OHOS::NetStack::Socket
345