• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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 {
34 constexpr int PARAM_OPTION = 1;
35 constexpr int PARAM_OPTION_CALLBACK = 2;
36 constexpr std::string_view EVENT_MESSAGE = "message";
37 constexpr std::string_view EVENT_CONNECT = "connect";
38 constexpr std::string_view EVENT_CLOSE = "close";
39 constexpr std::string_view EVENT_ERROR = "error";
40 
41 constexpr const char *PROPERTY_ADDRESS = "address";
42 constexpr const char *PROPERTY_FAMILY = "family";
43 constexpr const char *PROPERTY_PORT = "port";
44 constexpr const char *PROPERTY_SIZE = "size";
45 constexpr const char *ON_MESSAGE = "message";
46 constexpr const char *ON_REMOTE_INFO = "remoteInfo";
47 
EventMessageCallback(uv_work_t * work,int status)48 void EventMessageCallback(uv_work_t *work, int status)
49 {
50     (void)status;
51     if (work == nullptr) {
52         NETSTACK_LOGE("work is nullptr");
53         return;
54     }
55     auto workWrapper = static_cast<UvWorkWrapper *>(work->data);
56     if (workWrapper == nullptr) {
57         NETSTACK_LOGE("workWrapper is nullptr");
58         delete work;
59         return;
60     }
61     auto monitor = static_cast<Monitor *>(workWrapper->data);
62     if (monitor == nullptr) {
63         NETSTACK_LOGE("monitor is nullptr");
64         delete workWrapper;
65         delete work;
66         return;
67     }
68     napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
69     napi_value obj = NapiUtils::CreateObject(workWrapper->env);
70     napi_value remoteInfo = NapiUtils::CreateObject(workWrapper->env);
71     void *data = nullptr;
72     napi_value arrayBuffer = NapiUtils::CreateArrayBuffer(workWrapper->env, monitor->data_.size(), &data);
73     if (data != nullptr && arrayBuffer != nullptr) {
74         if (memcpy_s(data, monitor->data_.size(), monitor->data_.c_str(), monitor->data_.size()) != EOK) {
75             NETSTACK_LOGE("memcpy_s failed!");
76             delete workWrapper;
77             delete work;
78             return;
79         }
80     }
81     napi_value message = nullptr;
82     napi_create_typedarray(workWrapper->env, napi_uint8_array, monitor->data_.size(), arrayBuffer, 0, &message);
83     napi_value address = NapiUtils::CreateStringUtf8(workWrapper->env, monitor->remoteInfo_.GetAddress());
84     napi_value family = NapiUtils::CreateStringUtf8(workWrapper->env, monitor->remoteInfo_.GetFamily());
85     napi_value port = NapiUtils::CreateInt32(workWrapper->env, monitor->remoteInfo_.GetPort());
86     napi_value size = NapiUtils::CreateInt32(workWrapper->env, monitor->remoteInfo_.GetSize());
87     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_ADDRESS, address);
88     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_FAMILY, family);
89     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_PORT, port);
90     NapiUtils::SetNamedProperty(workWrapper->env, remoteInfo, PROPERTY_SIZE, size);
91     NapiUtils::SetNamedProperty(workWrapper->env, obj, ON_MESSAGE, message);
92     NapiUtils::SetNamedProperty(workWrapper->env, obj, ON_REMOTE_INFO, remoteInfo);
93     if (workWrapper->manager == nullptr) {
94         NETSTACK_LOGE("manager is nullptr");
95         delete workWrapper;
96         delete work;
97         return;
98     }
99     workWrapper->manager->Emit(workWrapper->type, std::make_pair(NapiUtils::GetUndefined(workWrapper->env), obj));
100     NapiUtils::CloseScope(workWrapper->env, scope);
101     delete workWrapper;
102     delete work;
103 }
104 
EventConnectCloseCallback(uv_work_t * work,int status)105 void EventConnectCloseCallback(uv_work_t *work, int status)
106 {
107     (void)status;
108     if (work == nullptr) {
109         NETSTACK_LOGE("work is nullptr");
110         return;
111     }
112     auto workWrapper = static_cast<UvWorkWrapper *>(work->data);
113     if (workWrapper == nullptr) {
114         NETSTACK_LOGE("workWrapper is nullptr");
115         delete work;
116         return;
117     }
118     napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
119     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env),
120                                              NapiUtils::GetUndefined(workWrapper->env)};
121     if (workWrapper->manager == nullptr) {
122         NETSTACK_LOGE("manager is nullptr");
123         delete workWrapper;
124         delete work;
125         return;
126     }
127     workWrapper->manager->Emit(workWrapper->type, arg);
128     NapiUtils::CloseScope(workWrapper->env, scope);
129     delete workWrapper;
130     delete work;
131 }
132 
EventErrorCallback(uv_work_t * work,int status)133 void EventErrorCallback(uv_work_t *work, int status)
134 {
135     (void)status;
136     if (work == nullptr) {
137         NETSTACK_LOGE("work is nullptr");
138         return;
139     }
140     auto workWrapper = static_cast<UvWorkWrapper *>(work->data);
141     if (workWrapper == nullptr) {
142         NETSTACK_LOGE("workWrapper is nullptr");
143         delete work;
144         return;
145     }
146     auto monitor = static_cast<Monitor *>(workWrapper->data);
147     if (monitor == nullptr) {
148         NETSTACK_LOGE("monitor is nullptr");
149         delete workWrapper;
150         delete work;
151         return;
152     }
153     napi_handle_scope scope = NapiUtils::OpenScope(workWrapper->env);
154     napi_value obj = NapiUtils::CreateObject(workWrapper->env);
155     napi_value errorNumber = NapiUtils::CreateInt32(workWrapper->env, monitor->errorNumber_);
156     napi_value errorString = NapiUtils::CreateStringUtf8(workWrapper->env, monitor->errorString_);
157     NapiUtils::SetNamedProperty(workWrapper->env, obj, "errorNumber", errorNumber);
158     NapiUtils::SetNamedProperty(workWrapper->env, obj, "errorString", errorString);
159     std::pair<napi_value, napi_value> arg = {NapiUtils::GetUndefined(workWrapper->env), obj};
160     if (workWrapper->manager == nullptr) {
161         NETSTACK_LOGE("manager is nullptr");
162         delete workWrapper;
163         delete work;
164         return;
165     }
166     workWrapper->manager->Emit(workWrapper->type, arg);
167     NapiUtils::CloseScope(workWrapper->env, scope);
168     delete workWrapper;
169     delete work;
170 }
171 } // namespace
172 
Monitor()173 Monitor::Monitor() : manager_(nullptr) {}
174 
~Monitor()175 Monitor::~Monitor()
176 {
177     if (manager_ != nullptr) {
178         delete manager_;
179     }
180 }
181 
On(napi_env env,napi_callback_info info)182 napi_value Monitor::On(napi_env env, napi_callback_info info)
183 {
184     napi_value thisVal = nullptr;
185     size_t paramsCount = MAX_PARAM_NUM;
186     napi_value params[MAX_PARAM_NUM] = {nullptr};
187     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
188     if (paramsCount == PARAM_OPTION) {
189         return NapiUtils::GetUndefined(env);
190     }
191     if (paramsCount != PARAM_OPTION_CALLBACK) {
192         if (NapiUtils::GetValueType(env, params[0]) != napi_string) {
193             napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
194         }
195         if (NapiUtils::GetValueType(env, params[1]) != napi_function) {
196             return NapiUtils::GetUndefined(env);
197         }
198     }
199     napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager_));
200     if (manager_ == nullptr) {
201         NETSTACK_LOGE("manager is nullptr");
202         return NapiUtils::GetUndefined(env);
203     }
204     auto tlsSocket = reinterpret_cast<TLSSocket *>(manager_->GetData());
205     if (tlsSocket == nullptr) {
206         NETSTACK_LOGE("tlsSocket is null");
207         return NapiUtils::GetUndefined(env);
208     }
209 
210     const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
211     auto itor = monitors_.find(event);
212     if (itor != monitors_.end()) {
213         NETSTACK_LOGE("monitor is exits %{public}s", event.c_str());
214         return NapiUtils::GetUndefined(env);
215     }
216     manager_->AddListener(env, event, params[1], false, false);
217     if (event == EVENT_MESSAGE) {
218         monitors_.insert(EVENT_MESSAGE);
219         tlsSocket->OnMessage([this](auto data, auto remoteInfo) {
220             this->data_ = data;
221             this->remoteInfo_ = remoteInfo;
222             manager_->EmitByUv(std::string(EVENT_MESSAGE), static_cast<void *>(this), EventMessageCallback);
223         });
224     }
225     if (event == EVENT_CLOSE) {
226         monitors_.insert(EVENT_CLOSE);
227         tlsSocket->OnClose(
228             [this]() { manager_->EmitByUv(std::string(EVENT_CLOSE), nullptr, EventConnectCloseCallback); });
229     }
230     if (event == EVENT_CONNECT) {
231         monitors_.insert(EVENT_CONNECT);
232         tlsSocket->OnConnect(
233             [this]() { manager_->EmitByUv(std::string(EVENT_CONNECT), nullptr, EventConnectCloseCallback); });
234     }
235     if (event == EVENT_ERROR) {
236         monitors_.insert(EVENT_ERROR);
237         tlsSocket->OnError([this](auto errorNumber, auto errorString) {
238             this->errorNumber_ = errorNumber;
239             this->errorString_ = errorString;
240             manager_->EmitByUv(std::string(EVENT_ERROR), static_cast<void *>(this), EventErrorCallback);
241         });
242     }
243     return NapiUtils::GetUndefined(env);
244 }
245 
Off(napi_env env,napi_callback_info info)246 napi_value Monitor::Off(napi_env env, napi_callback_info info)
247 {
248     napi_value thisVal = nullptr;
249     size_t paramsCount = MAX_PARAM_NUM;
250     napi_value params[MAX_PARAM_NUM] = {nullptr};
251     NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
252     if (paramsCount == PARAM_OPTION) {
253         return NapiUtils::GetUndefined(env);
254     }
255 
256     if (paramsCount != PARAM_OPTION_CALLBACK) {
257         if (NapiUtils::GetValueType(env, params[0]) != napi_string) {
258             napi_throw_error(env, std::to_string(PARSE_ERROR_CODE).c_str(), PARSE_ERROR_MSG);
259         }
260         if (NapiUtils::GetValueType(env, params[1]) != napi_function) {
261             return NapiUtils::GetUndefined(env);
262         }
263     }
264 
265     napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager_));
266     if (manager_ == nullptr) {
267         NETSTACK_LOGE("manager is nullptr");
268         return NapiUtils::GetUndefined(env);
269     }
270     auto tlsSocket = reinterpret_cast<TLSSocket *>(manager_->GetData());
271     if (tlsSocket == nullptr) {
272         NETSTACK_LOGE("tlsSocket is null");
273         return NapiUtils::GetUndefined(env);
274     }
275 
276     const std::string event = NapiUtils::GetStringFromValueUtf8(env, params[0]);
277     auto itor = monitors_.find(event);
278     if (itor == monitors_.end()) {
279         NETSTACK_LOGE("monitor is off %{public}s", event.c_str());
280         return NapiUtils::GetUndefined(env);
281     }
282     manager_->DeleteListener(event);
283     if (event == EVENT_MESSAGE) {
284         monitors_.erase(EVENT_MESSAGE);
285         tlsSocket->OffMessage();
286     }
287     if (event == EVENT_CLOSE) {
288         monitors_.erase(EVENT_CLOSE);
289         tlsSocket->OffClose();
290     }
291     if (event == EVENT_CONNECT) {
292         monitors_.erase(EVENT_CONNECT);
293         tlsSocket->OffConnect();
294     }
295     if (event == EVENT_ERROR) {
296         monitors_.erase(EVENT_ERROR);
297         tlsSocket->OffError();
298     }
299     return NapiUtils::GetUndefined(env);
300 }
301 } // namespace NetStack
302 } // namespace OHOS
303