• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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 "monitor.h"
17 
18 #include <cstddef>
19 #include <utility>
20 
21 #include <napi/native_api.h>
22 #include <napi/native_common.h>
23 #include <securec.h>
24 #include <uv.h>
25 
26 #include "module_template.h"
27 #include "napi_utils.h"
28 #include "netstack_log.h"
29 #include "tls_socket.h"
30 
31 namespace OHOS {
32 namespace NetStack {
33 namespace TlsSocket {
34 namespace {
35 constexpr int PARAM_OPTION = 1;
36 constexpr int PARAM_OPTION_CALLBACK = 2;
37 constexpr std::string_view EVENT_MESSAGE = "message";
38 constexpr std::string_view EVENT_CONNECT = "connect";
39 constexpr std::string_view EVENT_CLOSE = "close";
40 constexpr std::string_view EVENT_ERROR = "error";
41 constexpr std::initializer_list<std::string_view> EVENTS = {EVENT_MESSAGE, EVENT_CONNECT, EVENT_CLOSE, EVENT_ERROR};
42 
43 constexpr const char *PROPERTY_ADDRESS = "address";
44 constexpr const char *PROPERTY_FAMILY = "family";
45 constexpr const char *PROPERTY_PORT = "port";
46 constexpr const char *PROPERTY_SIZE = "size";
47 constexpr const char *ON_MESSAGE = "message";
48 constexpr const char *ON_REMOTE_INFO = "remoteInfo";
49 
ParserNullBranch(const std::string & errMessage,uv_work_t * & work,UvWorkWrapperShared * & workWrapper)50 void ParserNullBranch(const std::string &errMessage, uv_work_t *&work, UvWorkWrapperShared *&workWrapper)
51 {
52     NETSTACK_LOGE("%{public}s", errMessage.c_str());
53     if (workWrapper != nullptr) {
54         delete workWrapper;
55         workWrapper = nullptr;
56     }
57 
58     if (work != nullptr) {
59         delete work;
60         work = nullptr;
61     }
62 }
63 
SetPropertyForWorkWrapper(UvWorkWrapperShared * workWrapper,Monitor::MessageRecvParma * messageRecvParma,napi_value arrayBuffer,napi_value remoteInfo,napi_value obj)64 void SetPropertyForWorkWrapper(UvWorkWrapperShared *workWrapper, Monitor::MessageRecvParma *messageRecvParma,
65                                napi_value arrayBuffer, napi_value remoteInfo, napi_value obj)
66 {
67     napi_value message = nullptr;
68     napi_create_typedarray(workWrapper->env, napi_uint8_array, messageRecvParma->data_.size(), arrayBuffer, 0,
69                            &message);
70     napi_value address = NapiUtils::CreateStringUtf8(workWrapper->env, messageRecvParma->remoteInfo_.GetAddress());
71     napi_value family = NapiUtils::CreateStringUtf8(workWrapper->env, messageRecvParma->remoteInfo_.GetFamily());
72     napi_value port = NapiUtils::CreateInt32(workWrapper->env, messageRecvParma->remoteInfo_.GetPort());
73     napi_value size = NapiUtils::CreateInt32(workWrapper->env, messageRecvParma->remoteInfo_.GetSize());
74     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_ADDRESS, address);
75     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_FAMILY, family);
76     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_PORT, port);
77     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_SIZE, size);
78     NapiUtils::SetNamedProperty(workWrapper->env, obj, ON_MESSAGE, message);
79     NapiUtils::SetNamedProperty(workWrapper->env, obj, ON_REMOTE_INFO, remoteInfo);
80 }
81 
EventMessageCallback(uv_work_t * work,int status)82 void EventMessageCallback(uv_work_t *work, int status)
83 {
84     (void)status;
85     if (work == nullptr) {
86         NETSTACK_LOGE("work is nullptr");
87         return;
88     }
89     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
90     auto eventManager = workWrapper->manager;
91     auto messageRecvParam = reinterpret_cast<Monitor::MessageRecvParma *>(eventManager->GetQueueData());
92     if (!messageRecvParam) {
93         NETSTACK_LOGE("messageRecvParam is nullptr");
94         return;
95     }
96 
97     napi_env env = workWrapper->env;
98     auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
99     std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
100 
101     napi_value obj = NapiUtils::CreateObject(workWrapper->env);
102     napi_value remoteInfo = NapiUtils::CreateObject(workWrapper->env);
103     void *data = nullptr;
104     napi_value arrayBuffer = NapiUtils::CreateArrayBuffer(workWrapper->env, messageRecvParam->data_.size(), &data);
105     if (data != nullptr && NapiUtils::ValueIsArrayBuffer(env, arrayBuffer) &&
106         memcpy_s(data, messageRecvParam->data_.size(), messageRecvParam->data_.c_str(),
107                  messageRecvParam->data_.size()) != EOK) {
108         delete messageRecvParam;
109         ParserNullBranch("", work, workWrapper);
110         return;
111     }
112     SetPropertyForWorkWrapper(workWrapper, messageRecvParam, arrayBuffer, remoteInfo, obj);
113 
114     if (workWrapper->manager == nullptr) {
115         delete messageRecvParam;
116         ParserNullBranch("manager is invalid", work, workWrapper);
117         return;
118     }
119     workWrapper->manager->Emit(workWrapper->type, std::make_pair(NapiUtils::GetUndefined(workWrapper->env), obj));
120     delete messageRecvParam;
121     ParserNullBranch("event message callback success", work, workWrapper);
122 }
123 
EventConnectCloseCallback(uv_work_t * work,int status)124 void EventConnectCloseCallback(uv_work_t *work, int status)
125 {
126     (void)status;
127     if (work == nullptr) {
128         NETSTACK_LOGE("work is nullptr");
129         return;
130     }
131     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
132     if (workWrapper == nullptr) {
133         NETSTACK_LOGE("workWrapper is nullptr");
134         delete work;
135         return;
136     }
137     if (workWrapper->manager == nullptr) {
138         NETSTACK_LOGE("manager is nullptr");
139         delete workWrapper;
140         delete work;
141         return;
142     }
143     napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
144     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env),
145                                              NapiUtils::GetUndefined(workWrapper->env)};
146     workWrapper->manager->Emit(workWrapper->type, arg);
147     NapiUtils::CloseScope(workWrapper->env, scope);
148     delete workWrapper;
149     delete work;
150 }
151 
EventErrorCallback(uv_work_t * work,int status)152 void EventErrorCallback(uv_work_t *work, int status)
153 {
154     (void)status;
155     if (work == nullptr) {
156         NETSTACK_LOGE("work is nullptr");
157         return;
158     }
159     auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
160     if (workWrapper == nullptr) {
161         NETSTACK_LOGE("workWrapper is nullptr");
162         delete work;
163         return;
164     }
165     std::shared_ptr<Monitor::ErrorRecvParma> errorRecvParma(static_cast<Monitor::ErrorRecvParma *>(workWrapper->data));
166     if (errorRecvParma == nullptr) {
167         NETSTACK_LOGE("monitor is nullptr");
168         delete workWrapper;
169         delete work;
170         return;
171     }
172     if (workWrapper->manager == nullptr) {
173         NETSTACK_LOGE("manager is nullptr");
174         delete workWrapper;
175         delete work;
176         return;
177     }
178     napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
179     napi_value obj = NapiUtils::CreateObject(workWrapper->env);
180     napi_value errorNumber = NapiUtils::CreateInt32(workWrapper->env, errorRecvParma->errorNumber_);
181     napi_value errorString = NapiUtils::CreateStringUtf8(workWrapper->env, errorRecvParma->errorString_);
182     NapiUtils::SetNamedProperty(workWrapper->env, obj, "errorNumber", errorNumber);
183     NapiUtils::SetNamedProperty(workWrapper->env, obj, "errorString", errorString);
184     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
185     workWrapper->manager->Emit(workWrapper->type, arg);
186     NapiUtils::CloseScope(workWrapper->env, scope);
187     delete workWrapper;
188     delete work;
189 }
190 } // namespace
191 
Monitor()192 Monitor::Monitor() {}
193 
~Monitor()194 Monitor::~Monitor() {}
195 
ParserEventForOn(const std::string event,const std::shared_ptr<TLSSocket> & tlsSocket,const std::shared_ptr<EventManager> & manager)196 void Monitor::ParserEventForOn(const std::string event, const std::shared_ptr<TLSSocket> &tlsSocket,
197                                const std::shared_ptr<EventManager> &manager)
198 {
199     if (event == EVENT_MESSAGE) {
200         AddEventMessage(tlsSocket, manager);
201     }
202     if (event == EVENT_CLOSE) {
203         tlsSocket->OnClose([this, manager]() {
204             if (manager != nullptr) {
205                 manager->EmitByUvWithoutCheckShared(std::string(EVENT_CLOSE), nullptr, EventConnectCloseCallback);
206             }
207         });
208     }
209     if (event == EVENT_CONNECT) {
210         tlsSocket->OnConnect([this, manager]() {
211             if (manager != nullptr) {
212                 manager->EmitByUvWithoutCheckShared(std::string(EVENT_CONNECT), nullptr, EventConnectCloseCallback);
213             }
214         });
215     }
216     if (event == EVENT_ERROR) {
217         tlsSocket->OnError([this, manager](auto errorNumber, auto errorString) {
218             if (manager != nullptr && manager->HasEventListener(std::string(EVENT_ERROR))) {
219                 ErrorRecvParma *errorRecvParma = new ErrorRecvParma();
220                 errorRecvParma->errorNumber_ = errorNumber;
221                 errorRecvParma->errorString_ = errorString;
222                 manager->EmitByUvWithoutCheckShared(std::string(EVENT_ERROR), static_cast<void *>(errorRecvParma),
223                     EventErrorCallback);
224             }
225         });
226     }
227 }
228 
AddEventMessage(const std::shared_ptr<TLSSocket> & tlsSocket,const std::shared_ptr<EventManager> & manager) const229 void Monitor::AddEventMessage(const std::shared_ptr<TLSSocket> &tlsSocket,
230     const std::shared_ptr<EventManager> &manager) const
231 {
232     if (tlsSocket == nullptr) {
233         return;
234     }
235     tlsSocket->OnMessage([this, manager](auto data, auto remoteInfo) {
236         if (manager != nullptr && manager->HasEventListener(std::string(EVENT_MESSAGE))) {
237             auto messageRecvParma = new (std::nothrow) MessageRecvParma();
238             if (messageRecvParma == nullptr) {
239                 return;
240             }
241             messageRecvParma->data_ = data;
242             messageRecvParma->remoteInfo_ = remoteInfo;
243             manager->SetQueueData(reinterpret_cast<void *>(messageRecvParma));
244             manager->EmitByUvWithoutCheckShared(std::string(EVENT_MESSAGE), nullptr, EventMessageCallback);
245         }
246     });
247 }
248 
On(napi_env env,napi_callback_info info)249 napi_value Monitor::On(napi_env env, napi_callback_info info)
250 {
251     napi_value thisVal = nullptr;
252     size_t paramsCount = MAX_PARAM_NUM;
253     napi_value params[MAX_PARAM_NUM] = {nullptr};
254     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
255     if (paramsCount == PARAM_OPTION) {
256         return NapiUtils::GetUndefined(env);
257     }
258     if (paramsCount != PARAM_OPTION_CALLBACK) {
259         if (NapiUtils::GetValueType(env, params[0]) != napi_string) {
260             napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
261         }
262         if (NapiUtils::GetValueType(env, params[1]) != napi_function) {
263             return NapiUtils::GetUndefined(env);
264         }
265     }
266     std::shared_ptr<EventManager> *sharedManager = nullptr;
267     napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
268     if (sharedManager == nullptr || *sharedManager == nullptr) {
269         NETSTACK_LOGE("manager is nullptr");
270         return NapiUtils::GetUndefined(env);
271     }
272     auto manager = *sharedManager;
273     auto tlsSocket = reinterpret_cast<std::shared_ptr<TLSSocket> *>(manager->GetData());
274     if (tlsSocket == nullptr) {
275         NETSTACK_LOGE("tlsSocket is null");
276         return NapiUtils::GetUndefined(env);
277     }
278 
279     const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
280     if (std::find(EVENTS.begin(), EVENTS.end(), event) == EVENTS.end()) {
281         NETSTACK_LOGE("Incorrect listening event %{public}s", event.c_str());
282         return NapiUtils::GetUndefined(env);
283     }
284     manager->AddListener(env, event, params[1], false, false);
285     auto shared = *tlsSocket;
286     if (!shared) {
287         return NapiUtils::GetUndefined(env);
288     }
289     ParserEventForOn(event, shared, manager);
290     return NapiUtils::GetUndefined(env);
291 }
292 
ParserEventForOff(const std::string event,const std::shared_ptr<TLSSocket> & tlsSocket)293 void Monitor::ParserEventForOff(const std::string event, const std::shared_ptr<TLSSocket> &tlsSocket)
294 {
295     if (event == EVENT_MESSAGE) {
296         tlsSocket->OffMessage();
297     }
298     if (event == EVENT_CLOSE) {
299         tlsSocket->OffClose();
300     }
301     if (event == EVENT_CONNECT) {
302         tlsSocket->OffConnect();
303     }
304     if (event == EVENT_ERROR) {
305         tlsSocket->OffError();
306     }
307 }
308 
Off(napi_env env,napi_callback_info info)309 napi_value Monitor::Off(napi_env env, napi_callback_info info)
310 {
311     napi_value thisVal = nullptr;
312     size_t paramsCount = MAX_PARAM_NUM;
313     napi_value params[MAX_PARAM_NUM] = {nullptr};
314     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
315     if (paramsCount == PARAM_OPTION) {
316         return NapiUtils::GetUndefined(env);
317     }
318 
319     if (paramsCount != PARAM_OPTION_CALLBACK) {
320         if (NapiUtils::GetValueType(env, params[0]) != napi_string) {
321             napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
322         }
323         if (NapiUtils::GetValueType(env, params[1]) != napi_function) {
324             return NapiUtils::GetUndefined(env);
325         }
326     }
327     std::shared_ptr<EventManager> *sharedManager = nullptr;
328     napi_unwrap(env, thisVal, reinterpret_cast<void **>(&sharedManager));
329     if (sharedManager == nullptr || *sharedManager == nullptr) {
330         NETSTACK_LOGE("manager is nullptr");
331         return NapiUtils::GetUndefined(env);
332     }
333     auto manager = *sharedManager;
334     auto tlsSocket = reinterpret_cast<std::shared_ptr<TLSSocket> *>(manager->GetData());
335     if (tlsSocket == nullptr) {
336         NETSTACK_LOGE("tlsSocket is null");
337         return NapiUtils::GetUndefined(env);
338     }
339 
340     auto shared = *tlsSocket;
341     if (!shared) {
342         return NapiUtils::GetUndefined(env);
343     }
344     const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
345     ParserEventForOff(event, shared);
346     manager->DeleteListener(event);
347     return NapiUtils::GetUndefined(env);
348 }
349 } // namespace TlsSocket
350 } // namespace NetStack
351 } // namespace OHOS
352