1 /*
2 * Copyright (c) 2022-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 "websocket_exec.h"
17
18 #include <atomic>
19 #include <memory>
20 #include <queue>
21 #include <thread>
22 #include <unistd.h>
23
24 #include "constant.h"
25 #include "napi_utils.h"
26 #include "netstack_common_utils.h"
27 #include "netstack_log.h"
28 #include "securec.h"
29
30 #ifdef HAS_NETMANAGER_BASE
31 #include "http_proxy.h"
32 #include "net_conn_client.h"
33 #endif
34
35 static constexpr const char *PROTOCOL_DELIMITER = "//";
36
37 static constexpr const char *NAME_END = ":";
38
39 static constexpr const char *STATUS_LINE_SEP = " ";
40
41 static constexpr const size_t STATUS_LINE_ELEM_NUM = 2;
42
43 static constexpr const char *PREFIX_HTTPS = "https";
44
45 static constexpr const char *PREFIX_WSS = "wss";
46
47 static constexpr const char *PREFIX_WS = "ws";
48
49 static constexpr const int MAX_URI_LENGTH = 1024;
50
51 static constexpr const int MAX_HDR_LENGTH = 1024;
52
53 static constexpr const int MAX_PROTOCOL_LENGTH = 1024;
54
55 static constexpr const int MAX_ADDRESS_LENGTH = 1024;
56
57 static constexpr const int FD_LIMIT_PER_THREAD = 1 + 1 + 1;
58
59 static constexpr const int COMMON_ERROR_CODE = 200;
60
61 static constexpr const char *EVENT_KEY_CODE = "code";
62
63 static constexpr const char *EVENT_KEY_STATUS = "status";
64
65 static constexpr const char *EVENT_KEY_REASON = "reason";
66
67 static constexpr const char *EVENT_KEY_MESSAGE = "message";
68
69 static constexpr const char *LINK_DOWN = "The link is down";
70
71 static constexpr const int32_t UID_TRANSFORM_DIVISOR = 200000;
72
73 static constexpr const char *BASE_PATH = "/data/certificates/user_cacerts/";
74
75 static constexpr const char *WEBSOCKET_SYSTEM_PREPARE_CA_PATH = "/etc/security/certificates";
76
77 static constexpr const char *WEBSOCKET_CLIENT_THREAD_RUN = "OS_NET_WSJsCli";
78
79 namespace OHOS::NetStack::Websocket {
80 static const lws_protocols LWS_PROTOCOLS[] = {
81 {"lws-minimal-client", WebSocketExec::LwsCallback, 0, 0},
82 {nullptr, nullptr, 0, 0}, // this line is needed
83 };
84
85 static const lws_retry_bo_t RETRY = {
86 .secs_since_valid_ping = 30,
87 .secs_since_valid_hangup = 60,
88 .jitter_percent = 20,
89 };
90
91 struct CallbackDispatcher {
92 lws_callback_reasons reason;
93 int (*callback)(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len);
94 };
95
96 struct OnOpenClosePara {
OnOpenCloseParaOHOS::NetStack::Websocket::OnOpenClosePara97 OnOpenClosePara() : status(0) {}
98 uint32_t status;
99 std::string message;
100 };
101
102 static const std::vector<std::string> WS_PREFIX = {PREFIX_WSS, PREFIX_WS};
103
104 class UserData {
105 public:
106 struct SendData {
SendDataOHOS::NetStack::Websocket::UserData::SendData107 SendData(void *paraData, size_t paraLength, lws_write_protocol paraProtocol)
108 : data(paraData), length(paraLength), protocol(paraProtocol)
109 {
110 }
111
112 SendData() = delete;
113
114 ~SendData() = default;
115
116 void *data;
117 size_t length;
118 lws_write_protocol protocol;
119 };
120
UserData(lws_context * context)121 explicit UserData(lws_context *context)
122 : closeStatus(LWS_CLOSE_STATUS_NOSTATUS), openStatus(0), closed_(false), threadStop_(false), context_(context)
123 {
124 }
125
IsClosed()126 bool IsClosed()
127 {
128 std::lock_guard<std::mutex> lock(mutex_);
129 return closed_;
130 }
131
IsThreadStop()132 bool IsThreadStop()
133 {
134 return threadStop_.load();
135 }
136
SetThreadStop(bool threadStop)137 void SetThreadStop(bool threadStop)
138 {
139 threadStop_.store(threadStop);
140 }
141
Close(lws_close_status status,const std::string & reason)142 void Close(lws_close_status status, const std::string &reason)
143 {
144 std::lock_guard<std::mutex> lock(mutex_);
145 closeStatus = status;
146 closeReason = reason;
147 closed_ = true;
148 }
149
Push(void * data,size_t length,lws_write_protocol protocol)150 void Push(void *data, size_t length, lws_write_protocol protocol)
151 {
152 std::lock_guard<std::mutex> lock(mutex_);
153 dataQueue_.emplace(data, length, protocol);
154 }
155
Pop()156 SendData Pop()
157 {
158 std::lock_guard<std::mutex> lock(mutex_);
159 if (dataQueue_.empty()) {
160 return {nullptr, 0, LWS_WRITE_TEXT};
161 }
162 SendData data = dataQueue_.front();
163 dataQueue_.pop();
164 return data;
165 }
166
SetContext(lws_context * context)167 void SetContext(lws_context *context)
168 {
169 context_ = context;
170 }
171
GetContext()172 lws_context *GetContext()
173 {
174 return context_;
175 }
176
IsEmpty()177 bool IsEmpty()
178 {
179 std::lock_guard<std::mutex> lock(mutex_);
180 if (dataQueue_.empty()) {
181 return true;
182 }
183 return false;
184 }
185
SetLws(lws * wsi)186 void SetLws(lws *wsi)
187 {
188 std::lock_guard<std::mutex> lock(mutexForLws_);
189 if (wsi == nullptr) {
190 NETSTACK_LOGD("set wsi nullptr");
191 }
192 wsi_ = wsi;
193 }
194
TriggerWritable()195 void TriggerWritable()
196 {
197 std::lock_guard<std::mutex> lock(mutexForLws_);
198 if (wsi_ == nullptr) {
199 NETSTACK_LOGE("wsi is nullptr, can not trigger");
200 return;
201 }
202 lws_callback_on_writable(wsi_);
203 }
204
205 std::map<std::string, std::string> header;
206
207 lws_close_status closeStatus;
208
209 std::string closeReason;
210
211 uint32_t openStatus;
212
213 std::string openMessage;
214
215 private:
216 volatile bool closed_;
217
218 std::atomic_bool threadStop_;
219
220 std::mutex mutex_;
221
222 std::mutex mutexForLws_;
223
224 lws_context *context_;
225
226 std::queue<SendData> dataQueue_;
227
228 lws *wsi_ = nullptr;
229 };
230
CallbackTemplate(uv_work_t * work,int status)231 template <napi_value (*MakeJsValue)(napi_env, void *)> static void CallbackTemplate(uv_work_t *work, int status)
232 {
233 (void)status;
234
235 auto workWrapper = static_cast<UvWorkWrapperShared *>(work->data);
236 napi_env env = workWrapper->env;
237 auto closeScope = [env](napi_handle_scope scope) { NapiUtils::CloseScope(env, scope); };
238 std::unique_ptr<napi_handle_scope__, decltype(closeScope)> scope(NapiUtils::OpenScope(env), closeScope);
239
240 napi_value obj = MakeJsValue(env, workWrapper->data);
241 auto undefined = NapiUtils::GetUndefined(workWrapper->env);
242 std::pair<napi_value, napi_value> arg = {undefined, obj};
243 if (workWrapper->manager) {
244 workWrapper->manager->Emit(workWrapper->type, arg);
245 if (workWrapper->type == EventName::EVENT_MESSAGE &&
246 workWrapper->manager->HasEventListener(EventName::EVENT_DATA_END)) {
247 workWrapper->manager->Emit(EventName::EVENT_DATA_END, {undefined, undefined});
248 }
249 }
250 delete workWrapper;
251 delete work;
252 }
253
ParseUrl(ConnectContext * context,char * protocol,size_t protocolLen,char * address,size_t addressLen,char * path,size_t pathLen,int * port)254 bool WebSocketExec::ParseUrl(ConnectContext *context, char *protocol, size_t protocolLen, char *address,
255 size_t addressLen, char *path, size_t pathLen, int *port)
256 {
257 char uri[MAX_URI_LENGTH] = {0};
258 if (strcpy_s(uri, MAX_URI_LENGTH, context->url.c_str()) < 0) {
259 NETSTACK_LOGE("strcpy_s failed");
260 return false;
261 }
262 const char *tempProt = nullptr;
263 const char *tempAddress = nullptr;
264 const char *tempPath = nullptr;
265 (void)lws_parse_uri(uri, &tempProt, &tempAddress, port, &tempPath);
266 if (strcpy_s(protocol, protocolLen, tempProt) < 0) {
267 NETSTACK_LOGE("strcpy_s failed");
268 return false;
269 }
270 if (std::find(WS_PREFIX.begin(), WS_PREFIX.end(), protocol) == WS_PREFIX.end()) {
271 NETSTACK_LOGE("protocol failed");
272 return false;
273 }
274 if (strcpy_s(address, addressLen, tempAddress) < 0) {
275 NETSTACK_LOGE("strcpy_s failed");
276 return false;
277 }
278 if (strcpy_s(path, pathLen, tempPath) < 0) {
279 NETSTACK_LOGE("strcpy_s failed");
280 return false;
281 }
282 return true;
283 }
284
RunService(std::shared_ptr<UserData> userData,std::shared_ptr<EventManager> manager)285 void RunService(std::shared_ptr<UserData> userData, std::shared_ptr<EventManager> manager)
286 {
287 NETSTACK_LOGI("websocket run service start");
288 int res = 0;
289 lws_context *context = userData->GetContext();
290 if (context == nullptr) {
291 NETSTACK_LOGE("context is null");
292 return;
293 }
294 while (res >= 0 && !userData->IsThreadStop()) {
295 res = lws_service(context, 0);
296 }
297 lws_context_destroy(context);
298 userData->SetContext(nullptr);
299 manager->SetWebSocketUserData(nullptr);
300 NETSTACK_LOGI("websocket run service end");
301 }
302
RaiseError(EventManager * manager,uint32_t httpResponse)303 int WebSocketExec::RaiseError(EventManager *manager, uint32_t httpResponse)
304 {
305 OnError(manager, COMMON_ERROR_CODE, httpResponse);
306 return -1;
307 }
308
GetHttpResponseFromWsi(lws * wsi)309 uint32_t WebSocketExec::GetHttpResponseFromWsi(lws *wsi)
310 {
311 if (wsi == nullptr) {
312 return 0;
313 }
314 return lws_http_client_http_response(wsi);
315 }
316
HttpDummy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)317 int WebSocketExec::HttpDummy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
318 {
319 int ret = lws_callback_http_dummy(wsi, reason, user, in, len);
320 if (ret < 0) {
321 OnError(reinterpret_cast<EventManager *>(user), COMMON_ERROR_CODE, GetHttpResponseFromWsi(wsi));
322 }
323 return 0;
324 }
325
LwsCallbackClientAppendHandshakeHeader(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)326 int WebSocketExec::LwsCallbackClientAppendHandshakeHeader(lws *wsi, lws_callback_reasons reason, void *user, void *in,
327 size_t len)
328 {
329 NETSTACK_LOGD("lws callback client append handshake header");
330 auto manager = reinterpret_cast<EventManager *>(user);
331 auto userData = manager->GetWebSocketUserData();
332 if (userData == nullptr) {
333 NETSTACK_LOGE("user data is null");
334 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
335 }
336
337 auto payload = reinterpret_cast<unsigned char **>(in);
338 if (payload == nullptr || (*payload) == nullptr || len == 0) {
339 NETSTACK_LOGE("header payload is null, do not append header");
340 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
341 }
342 auto payloadEnd = (*payload) + len;
343 for (const auto &pair : userData->header) {
344 std::string name = pair.first + NAME_END;
345 if (lws_add_http_header_by_name(wsi, reinterpret_cast<const unsigned char *>(name.c_str()),
346 reinterpret_cast<const unsigned char *>(pair.second.c_str()),
347 static_cast<int>(strlen(pair.second.c_str())), payload, payloadEnd)) {
348 NETSTACK_LOGE("add header failed");
349 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
350 }
351 }
352 NETSTACK_LOGI("add header OK");
353 return HttpDummy(wsi, reason, user, in, len);
354 }
355
LwsCallbackWsPeerInitiatedClose(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)356 int WebSocketExec::LwsCallbackWsPeerInitiatedClose(lws *wsi, lws_callback_reasons reason, void *user, void *in,
357 size_t len)
358 {
359 NETSTACK_LOGD("lws callback ws peer initiated close");
360 auto manager = reinterpret_cast<EventManager *>(user);
361 auto userData = manager->GetWebSocketUserData();
362 if (userData == nullptr) {
363 NETSTACK_LOGE("user data is null");
364 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
365 }
366
367 if (in == nullptr || len < sizeof(uint16_t)) {
368 NETSTACK_LOGI("No close reason");
369 userData->Close(LWS_CLOSE_STATUS_NORMAL, "");
370 return HttpDummy(wsi, reason, user, in, len);
371 }
372
373 uint16_t closeStatus = ntohs(*reinterpret_cast<uint16_t *>(in));
374 std::string closeReason;
375 closeReason.append(reinterpret_cast<char *>(in) + sizeof(uint16_t), len - sizeof(uint16_t));
376 userData->Close(static_cast<lws_close_status>(closeStatus), closeReason);
377 return HttpDummy(wsi, reason, user, in, len);
378 }
379
LwsCallbackClientWritable(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)380 int WebSocketExec::LwsCallbackClientWritable(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
381 {
382 NETSTACK_LOGD("lws callback client writable");
383 auto manager = reinterpret_cast<EventManager *>(user);
384 auto userData = manager->GetWebSocketUserData();
385 if (userData == nullptr) {
386 NETSTACK_LOGE("user data is null");
387 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
388 }
389 if (userData->IsClosed()) {
390 NETSTACK_LOGI("need to close");
391 lws_close_reason(wsi, userData->closeStatus,
392 reinterpret_cast<unsigned char *>(const_cast<char *>(userData->closeReason.c_str())),
393 strlen(userData->closeReason.c_str()));
394 // here do not emit error, because we close it
395 return -1;
396 }
397 auto sendData = userData->Pop();
398 if (sendData.data == nullptr || sendData.length == 0) {
399 return HttpDummy(wsi, reason, user, in, len);
400 }
401 int sendLength = lws_write(wsi, reinterpret_cast<unsigned char *>(sendData.data) + LWS_SEND_BUFFER_PRE_PADDING,
402 sendData.length, sendData.protocol);
403 free(sendData.data);
404 NETSTACK_LOGD("lws send data length is %{public}d", sendLength);
405 if (!userData->IsEmpty()) {
406 userData->TriggerWritable();
407 }
408 return HttpDummy(wsi, reason, user, in, len);
409 }
410
CreateConnectError(napi_env env,void * callbackPara)411 static napi_value CreateConnectError(napi_env env, void *callbackPara)
412 {
413 auto pair = reinterpret_cast<std::pair<int, uint32_t> *>(callbackPara);
414 auto deleter = [](std::pair<int, uint32_t> *p) { delete p; };
415 std::unique_ptr<std::pair<int, uint32_t>, decltype(deleter)> handler(pair, deleter);
416 napi_value err = NapiUtils::CreateObject(env);
417 if (NapiUtils::GetValueType(env, err) != napi_object) {
418 return NapiUtils::GetUndefined(env);
419 }
420 NapiUtils::SetInt32Property(env, err, EVENT_KEY_CODE, pair->first);
421 NapiUtils::SetStringPropertyUtf8(env, err, "data", std::to_string(pair->second));
422 return err;
423 }
424
OnConnectError(EventManager * manager,int32_t code,uint32_t httpResponse)425 void OnConnectError(EventManager *manager, int32_t code, uint32_t httpResponse)
426 {
427 NETSTACK_LOGI("OnError %{public}d", code);
428 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
429 NETSTACK_LOGE("manager is null");
430 return;
431 }
432 if (auto userData = manager->GetWebSocketUserData(); userData != nullptr) {
433 NETSTACK_LOGI("OnConnectError SetThreadStop");
434 userData->SetThreadStop(true);
435 }
436 if (!manager->HasEventListener(EventName::EVENT_ERROR)) {
437 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_ERROR);
438 return;
439 }
440 auto pair = new std::pair<int, uint32_t>;
441 pair->first = code;
442 pair->second = httpResponse;
443 manager->EmitByUvWithoutCheckShared(EventName::EVENT_ERROR, pair, CallbackTemplate<CreateConnectError>);
444 }
445
LwsCallbackClientConnectionError(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)446 int WebSocketExec::LwsCallbackClientConnectionError(lws *wsi, lws_callback_reasons reason, void *user, void *in,
447 size_t len)
448 {
449 NETSTACK_LOGI("Lws client connection error %{public}s", (in == nullptr) ? "null" : reinterpret_cast<char *>(in));
450 // 200 means connect failed
451 OnConnectError(reinterpret_cast<EventManager *>(user), COMMON_ERROR_CODE, GetHttpResponseFromWsi(wsi));
452 return HttpDummy(wsi, reason, user, in, len);
453 }
454
LwsCallbackClientReceive(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)455 int WebSocketExec::LwsCallbackClientReceive(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
456 {
457 NETSTACK_LOGD("lws callback client receive");
458 auto manager = reinterpret_cast<EventManager *>(user);
459 auto isFinal = lws_is_final_fragment(wsi);
460 OnMessage(manager, in, len, lws_frame_is_binary(wsi), isFinal);
461 return HttpDummy(wsi, reason, user, in, len);
462 }
463
LwsCallbackClientFilterPreEstablish(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)464 int WebSocketExec::LwsCallbackClientFilterPreEstablish(lws *wsi, lws_callback_reasons reason, void *user, void *in,
465 size_t len)
466 {
467 NETSTACK_LOGD("lws callback client filter preEstablish");
468 auto manager = reinterpret_cast<EventManager *>(user);
469 auto userData = manager->GetWebSocketUserData();
470 if (userData == nullptr) {
471 NETSTACK_LOGE("user data is null");
472 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
473 }
474
475 userData->openStatus = GetHttpResponseFromWsi(wsi);
476 char statusLine[MAX_HDR_LENGTH] = {0};
477 if (lws_hdr_copy(wsi, statusLine, MAX_HDR_LENGTH, WSI_TOKEN_HTTP) < 0 || strlen(statusLine) == 0) {
478 return HttpDummy(wsi, reason, user, in, len);
479 }
480
481 auto vec = CommonUtils::Split(statusLine, STATUS_LINE_SEP, STATUS_LINE_ELEM_NUM);
482 if (vec.size() >= FUNCTION_PARAM_TWO) {
483 userData->openMessage = vec[1];
484 }
485
486 char buffer[MAX_HDR_LENGTH] = {};
487 std::map<std::string, std::string> responseHeader;
488 for (int i = 0; i < WSI_TOKEN_COUNT; i++) {
489 if (lws_hdr_total_length(wsi, static_cast<lws_token_indexes>(i)) > 0) {
490 lws_hdr_copy(wsi, buffer, sizeof(buffer), static_cast<lws_token_indexes>(i));
491 std::string str;
492 if (lws_token_to_string(static_cast<lws_token_indexes>(i))) {
493 str =
494 std::string(reinterpret_cast<const char *>(lws_token_to_string(static_cast<lws_token_indexes>(i))));
495 }
496 if (!str.empty() && str.back() == ':') {
497 responseHeader.emplace(str.substr(0, str.size() - 1), std::string(buffer));
498 }
499 }
500 }
501 lws_hdr_custom_name_foreach(
502 wsi,
503 [](const char *name, int nlen, void *opaque) -> void {
504 auto header = static_cast<std::map<std::string, std::string> *>(opaque);
505 if (header == nullptr) {
506 return;
507 }
508 header->emplace(std::string(name).substr(0, nlen - 1), std::string(name).substr(nlen));
509 },
510 &responseHeader);
511 OnHeaderReceive(manager, responseHeader);
512 return HttpDummy(wsi, reason, user, in, len);
513 }
514
LwsCallbackClientEstablished(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)515 int WebSocketExec::LwsCallbackClientEstablished(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
516 {
517 NETSTACK_LOGD("lws callback client established");
518 auto manager = reinterpret_cast<EventManager *>(user);
519 auto userData = manager->GetWebSocketUserData();
520 if (userData == nullptr) {
521 NETSTACK_LOGE("user data is null");
522 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
523 }
524 userData->TriggerWritable();
525 userData->SetLws(wsi);
526 OnOpen(reinterpret_cast<EventManager *>(user), userData->openStatus, userData->openMessage);
527 return HttpDummy(wsi, reason, user, in, len);
528 }
529
LwsCallbackClientClosed(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)530 int WebSocketExec::LwsCallbackClientClosed(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
531 {
532 NETSTACK_LOGD("lws callback client closed");
533 auto manager = reinterpret_cast<EventManager *>(user);
534 auto userData = manager->GetWebSocketUserData();
535 if (userData == nullptr) {
536 NETSTACK_LOGE("user data is null");
537 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
538 }
539 userData->SetThreadStop(true);
540 if ((userData->closeReason).empty()) {
541 userData->Close(userData->closeStatus, LINK_DOWN);
542 }
543 if (userData->closeStatus == LWS_CLOSE_STATUS_NOSTATUS) {
544 NETSTACK_LOGE("The link is down, onError");
545 OnError(manager, COMMON_ERROR_CODE, GetHttpResponseFromWsi(wsi));
546 }
547 OnClose(reinterpret_cast<EventManager *>(user), userData->closeStatus, userData->closeReason);
548 return HttpDummy(wsi, reason, user, in, len);
549 }
550
LwsCallbackWsiDestroy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)551 int WebSocketExec::LwsCallbackWsiDestroy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
552 {
553 NETSTACK_LOGD("lws callback wsi destroy");
554 auto manager = reinterpret_cast<EventManager *>(user);
555 if (manager == nullptr) {
556 NETSTACK_LOGE("manager is null");
557 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
558 }
559 auto userData = manager->GetWebSocketUserData();
560 if (userData == nullptr) {
561 NETSTACK_LOGE("user data is null");
562 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
563 }
564 userData->SetLws(nullptr);
565 return HttpDummy(wsi, reason, user, in, len);
566 }
567
LwsCallbackProtocolDestroy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)568 int WebSocketExec::LwsCallbackProtocolDestroy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
569 {
570 NETSTACK_LOGD("lws callback protocol destroy");
571 return HttpDummy(wsi, reason, user, in, len);
572 }
573
LwsCallback(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)574 int WebSocketExec::LwsCallback(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
575 {
576 NETSTACK_LOGI("lws callback reason is %{public}d", reason);
577 CallbackDispatcher dispatchers[] = {
578 {LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, LwsCallbackClientAppendHandshakeHeader},
579 {LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, LwsCallbackWsPeerInitiatedClose},
580 {LWS_CALLBACK_CLIENT_WRITEABLE, LwsCallbackClientWritable},
581 {LWS_CALLBACK_CLIENT_CONNECTION_ERROR, LwsCallbackClientConnectionError},
582 {LWS_CALLBACK_CLIENT_RECEIVE, LwsCallbackClientReceive},
583 {LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, LwsCallbackClientFilterPreEstablish},
584 {LWS_CALLBACK_CLIENT_ESTABLISHED, LwsCallbackClientEstablished},
585 {LWS_CALLBACK_CLIENT_CLOSED, LwsCallbackClientClosed},
586 {LWS_CALLBACK_WSI_DESTROY, LwsCallbackWsiDestroy},
587 {LWS_CALLBACK_PROTOCOL_DESTROY, LwsCallbackProtocolDestroy},
588 };
589
590 for (const auto dispatcher : dispatchers) {
591 if (dispatcher.reason == reason) {
592 return dispatcher.callback(wsi, reason, user, in, len);
593 }
594 }
595
596 return HttpDummy(wsi, reason, user, in, len);
597 }
598
FillContextInfo(ConnectContext * context,lws_context_creation_info & info,char * proxyAds)599 void WebSocketExec::FillContextInfo(ConnectContext *context, lws_context_creation_info &info, char *proxyAds)
600 {
601 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
602 info.port = CONTEXT_PORT_NO_LISTEN;
603 info.protocols = LWS_PROTOCOLS;
604 info.fd_limit_per_thread = FD_LIMIT_PER_THREAD;
605
606 char tempUri[MAX_URI_LENGTH] = {0};
607 const char *tempProtocol = nullptr;
608 const char *tempAddress = nullptr;
609 const char *tempPath = nullptr;
610 int32_t tempPort = 0;
611
612 std::string host;
613 uint32_t port = 0;
614 std::string exclusions;
615
616 if (strcpy_s(tempUri, MAX_URI_LENGTH, context->url.c_str()) < 0) {
617 NETSTACK_LOGE("strcpy_s failed");
618 return;
619 }
620 if (lws_parse_uri(tempUri, &tempProtocol, &tempAddress, &tempPort, &tempPath) != 0) {
621 NETSTACK_LOGE("get websocket hostname failed");
622 return;
623 }
624 GetWebsocketProxyInfo(context, host, port, exclusions);
625 if (!host.empty() && !CommonUtils::IsHostNameExcluded(tempAddress, exclusions, ",")) {
626 if (strcpy_s(proxyAds, host.length() + 1, host.c_str()) != EOK) {
627 NETSTACK_LOGE("memory copy failed");
628 }
629 info.http_proxy_address = proxyAds;
630 info.http_proxy_port = port;
631 }
632 }
633
CreatConnectInfo(ConnectContext * context,lws_context * lwsContext,const std::shared_ptr<EventManager> & manager)634 bool WebSocketExec::CreatConnectInfo(ConnectContext *context, lws_context *lwsContext,
635 const std::shared_ptr<EventManager> &manager)
636 {
637 lws_client_connect_info connectInfo = {};
638 char protocol[MAX_URI_LENGTH] = {0};
639 char address[MAX_URI_LENGTH] = {0};
640 char path[MAX_URI_LENGTH] = {0};
641 char customizedProtocol[MAX_PROTOCOL_LENGTH] = {0};
642 int port = 0;
643
644 if (!ParseUrl(context, protocol, MAX_URI_LENGTH, address, MAX_URI_LENGTH, path, MAX_URI_LENGTH, &port)) {
645 NETSTACK_LOGE("ParseUrl failed");
646 context->SetErrorCode(WEBSOCKET_ERROR_CODE_URL_ERROR);
647 return false;
648 }
649 if (lwsContext == nullptr) {
650 NETSTACK_LOGE("no memory");
651 return false;
652 }
653 std::string tempHost = std::string(address) + NAME_END + std::to_string(port);
654 std::string tempOrigin = std::string(protocol) + NAME_END + PROTOCOL_DELIMITER + tempHost;
655 NETSTACK_LOGD("tempOrigin = %{private}s", tempOrigin.c_str());
656 if (strcpy_s(customizedProtocol, context->GetProtocol().length() + 1, context->GetProtocol().c_str()) != EOK) {
657 NETSTACK_LOGE("memory copy failed");
658 }
659
660 connectInfo.context = lwsContext;
661 connectInfo.port = port;
662 connectInfo.address = address;
663 connectInfo.path = path;
664 connectInfo.host = address;
665 connectInfo.origin = address;
666 connectInfo.protocol = customizedProtocol;
667
668 if (strcmp(protocol, PREFIX_HTTPS) == 0 || strcmp(protocol, PREFIX_WSS) == 0) {
669 connectInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_SELFSIGNED;
670 }
671 lws *wsi = nullptr;
672 connectInfo.pwsi = &wsi;
673 connectInfo.retry_and_idle_policy = &RETRY;
674 connectInfo.userdata = manager.get();
675 if (lws_client_connect_via_info(&connectInfo) == nullptr) {
676 NETSTACK_LOGI("ExecConnect websocket connect failed");
677 context->SetErrorCode(-1);
678 OnConnectError(manager.get(), COMMON_ERROR_CODE, 0);
679 return false;
680 }
681 return true;
682 }
683
CheckFilePath(std::string & path)684 static bool CheckFilePath(std::string &path)
685 {
686 char tmpPath[PATH_MAX] = {0};
687 if (!realpath(static_cast<const char *>(path.c_str()), tmpPath)) {
688 NETSTACK_LOGE("path is error");
689 return false;
690 }
691 path = tmpPath;
692 return true;
693 }
694
FillCaPath(ConnectContext * context,lws_context_creation_info & info)695 bool WebSocketExec::FillCaPath(ConnectContext *context, lws_context_creation_info &info)
696 {
697 if (!context->caPath_.empty()) {
698 if (!CheckFilePath(context->caPath_)) {
699 NETSTACK_LOGE("ca not exist");
700 context->SetErrorCode(WEBSOCKET_ERROR_CODE_FILE_NOT_EXIST);
701 return false;
702 }
703 info.client_ssl_ca_filepath = context->caPath_.c_str();
704 NETSTACK_LOGD("load customize CA: %{public}s", info.client_ssl_ca_filepath);
705 } else {
706 info.client_ssl_ca_dirs[0] = WEBSOCKET_SYSTEM_PREPARE_CA_PATH;
707 context->userCertPath_ = BASE_PATH + std::to_string(getuid() / UID_TRANSFORM_DIVISOR);
708 info.client_ssl_ca_dirs[1] = context->userCertPath_.c_str();
709 NETSTACK_LOGD("load system CA");
710 }
711 if (!context->clientCert_.empty()) {
712 char realKeyPath[PATH_MAX] = {0};
713 if (!CheckFilePath(context->clientCert_) || !realpath(context->clientKey_.Data(), realKeyPath)) {
714 NETSTACK_LOGE("client cert not exist");
715 context->SetErrorCode(WEBSOCKET_ERROR_CODE_FILE_NOT_EXIST);
716 return false;
717 }
718 context->clientKey_ = Secure::SecureChar(realKeyPath);
719 info.client_ssl_cert_filepath = context->clientCert_.c_str();
720 info.client_ssl_private_key_filepath = context->clientKey_.Data();
721 info.client_ssl_private_key_password = context->keyPassword_.Data();
722 }
723 return true;
724 }
725
ExecConnect(ConnectContext * context)726 bool WebSocketExec::ExecConnect(ConnectContext *context)
727 {
728 NETSTACK_LOGD("websocket Connect exec");
729 if (context == nullptr) {
730 NETSTACK_LOGE("context is nullptr");
731 return false;
732 }
733 if (!CommonUtils::HasInternetPermission()) {
734 context->SetPermissionDenied(true);
735 return false;
736 }
737 if (context->IsAtomicService() &&
738 !CommonUtils::IsAllowedHostname(context->GetBundleName(), CommonUtils::DOMAIN_TYPE_WEBSOCKET_REQUEST,
739 context->url)) {
740 context->SetNoAllowedHost(true);
741 return false;
742 }
743 auto manager = context->GetSharedManager();
744 if (manager == nullptr) {
745 return false;
746 }
747 lws_context_creation_info info = {};
748 char proxyAds[MAX_ADDRESS_LENGTH] = {0};
749 FillContextInfo(context, info, proxyAds);
750 if (!FillCaPath(context, info)) {
751 return false;
752 }
753 lws_context *lwsContext = nullptr;
754 std::shared_ptr<UserData> userData;
755 if (manager->GetWebSocketUserData() == nullptr) {
756 lwsContext = lws_create_context(&info);
757 userData = std::make_shared<UserData>(lwsContext);
758 userData->header = context->header;
759 manager->SetWebSocketUserData(userData);
760 } else {
761 NETSTACK_LOGE("Websocket connect already exist");
762 context->SetErrorCode(WEBSOCKET_ERROR_CODE_CONNECT_AlREADY_EXIST);
763 return false;
764 }
765 if (!CreatConnectInfo(context, lwsContext, manager)) {
766 userData->SetContext(nullptr);
767 lws_context_destroy(lwsContext);
768 manager->SetWebSocketUserData(nullptr);
769 return false;
770 }
771 std::thread serviceThread(RunService, userData, manager);
772
773 #if defined(MAC_PLATFORM) || defined(IOS_PLATFORM)
774 pthread_setname_np(WEBSOCKET_CLIENT_THREAD_RUN);
775 #else
776 pthread_setname_np(serviceThread.native_handle(), WEBSOCKET_CLIENT_THREAD_RUN);
777 #endif
778 serviceThread.detach();
779 return true;
780 }
781
ConnectCallback(ConnectContext * context)782 napi_value WebSocketExec::ConnectCallback(ConnectContext *context)
783 {
784 if (context->GetErrorCode() < 0) {
785 NETSTACK_LOGI("ConnectCallback connect failed");
786 return NapiUtils::GetBoolean(context->GetEnv(), false);
787 }
788 NETSTACK_LOGI("ConnectCallback connect success");
789 return NapiUtils::GetBoolean(context->GetEnv(), true);
790 }
791
ExecSend(SendContext * context)792 bool WebSocketExec::ExecSend(SendContext *context)
793 {
794 if (context == nullptr) {
795 NETSTACK_LOGE("context is nullptr");
796 return false;
797 }
798 if (!CommonUtils::HasInternetPermission()) {
799 context->SetPermissionDenied(true);
800 return false;
801 }
802 auto manager = context->GetSharedManager();
803 if (manager == nullptr) {
804 NETSTACK_LOGE("context is null");
805 return false;
806 }
807 auto userData = manager->GetWebSocketUserData();
808 if (userData == nullptr) {
809 NETSTACK_LOGE("user data is nullptr");
810 return false;
811 }
812 if (userData->IsClosed() || userData->IsThreadStop()) {
813 NETSTACK_LOGE("session is closed or stopped");
814 return false;
815 }
816 userData->Push(context->data, context->length, context->protocol);
817 userData->TriggerWritable();
818 NETSTACK_LOGD("lws ts send success");
819 return true;
820 }
821
SendCallback(SendContext * context)822 napi_value WebSocketExec::SendCallback(SendContext *context)
823 {
824 return NapiUtils::GetBoolean(context->GetEnv(), true);
825 }
826
ExecClose(CloseContext * context)827 bool WebSocketExec::ExecClose(CloseContext *context)
828 {
829 if (context == nullptr) {
830 NETSTACK_LOGE("context is nullptr");
831 return false;
832 }
833 if (!CommonUtils::HasInternetPermission()) {
834 context->SetPermissionDenied(true);
835 return false;
836 }
837 if (context->GetSharedManager() == nullptr) {
838 NETSTACK_LOGE("context is null");
839 return false;
840 }
841
842 auto manager = context->GetSharedManager();
843 auto userData = manager->GetWebSocketUserData();
844 if (userData == nullptr) {
845 NETSTACK_LOGE("user data is nullptr");
846 return false;
847 }
848
849 if (userData->IsClosed()) {
850 NETSTACK_LOGE("connection has been closed");
851 return false;
852 }
853 userData->Close(static_cast<lws_close_status>(context->code), context->reason);
854 userData->TriggerWritable();
855 NETSTACK_LOGI("ExecClose OK");
856 return true;
857 }
858
CloseCallback(CloseContext * context)859 napi_value WebSocketExec::CloseCallback(CloseContext *context)
860 {
861 auto manager = context->GetSharedManager();
862 if (manager != nullptr) {
863 NETSTACK_LOGD("websocket close, delete js ref");
864 manager->DeleteEventReference(context->GetEnv());
865 }
866 return NapiUtils::GetBoolean(context->GetEnv(), true);
867 }
868
CreateError(napi_env env,void * callbackPara)869 static napi_value CreateError(napi_env env, void *callbackPara)
870 {
871 auto pair = reinterpret_cast<std::pair<int, uint32_t> *>(callbackPara);
872 auto deleter = [](std::pair<int, uint32_t> *p) { delete p; };
873 std::unique_ptr<std::pair<int, uint32_t>, decltype(deleter)> handler(pair, deleter);
874 napi_value err = NapiUtils::CreateObject(env);
875 if (NapiUtils::GetValueType(env, err) != napi_object) {
876 return NapiUtils::GetUndefined(env);
877 }
878 NapiUtils::SetInt32Property(env, err, EVENT_KEY_CODE, pair->first);
879 NapiUtils::SetStringPropertyUtf8(env, err, "data", std::to_string(pair->second));
880 return err;
881 }
882
CreateOpenPara(napi_env env,void * callbackPara)883 static napi_value CreateOpenPara(napi_env env, void *callbackPara)
884 {
885 auto para = reinterpret_cast<OnOpenClosePara *>(callbackPara);
886 auto deleter = [](const OnOpenClosePara *p) { delete p; };
887 std::unique_ptr<OnOpenClosePara, decltype(deleter)> handler(para, deleter);
888 napi_value obj = NapiUtils::CreateObject(env);
889 if (NapiUtils::GetValueType(env, obj) != napi_object) {
890 return NapiUtils::GetUndefined(env);
891 }
892 NapiUtils::SetUint32Property(env, obj, EVENT_KEY_STATUS, para->status);
893 NapiUtils::SetStringPropertyUtf8(env, obj, EVENT_KEY_MESSAGE, para->message);
894 return obj;
895 }
896
CreateClosePara(napi_env env,void * callbackPara)897 static napi_value CreateClosePara(napi_env env, void *callbackPara)
898 {
899 auto para = reinterpret_cast<OnOpenClosePara *>(callbackPara);
900 auto deleter = [](const OnOpenClosePara *p) { delete p; };
901 std::unique_ptr<OnOpenClosePara, decltype(deleter)> handler(para, deleter);
902 napi_value obj = NapiUtils::CreateObject(env);
903 if (NapiUtils::GetValueType(env, obj) != napi_object) {
904 return NapiUtils::GetUndefined(env);
905 }
906 NapiUtils::SetUint32Property(env, obj, EVENT_KEY_CODE, para->status);
907 NapiUtils::SetStringPropertyUtf8(env, obj, EVENT_KEY_REASON, para->message);
908 return obj;
909 }
910
CreateTextMessagePara(napi_env env,void * callbackPara)911 static napi_value CreateTextMessagePara(napi_env env, void *callbackPara)
912 {
913 auto manager = reinterpret_cast<EventManager *>(callbackPara);
914 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
915 return NapiUtils::CreateStringUtf8(env, "");
916 }
917 auto msg = reinterpret_cast<std::string *>(manager->GetQueueData());
918 if (!msg) {
919 NETSTACK_LOGE("msg is nullptr");
920 return NapiUtils::GetUndefined(env);
921 }
922 auto text = NapiUtils::CreateStringUtf8(env, *msg);
923 delete msg;
924 return text;
925 }
926
CreateBinaryMessagePara(napi_env env,void * callbackPara)927 static napi_value CreateBinaryMessagePara(napi_env env, void *callbackPara)
928 {
929 auto manager = reinterpret_cast<EventManager *>(callbackPara);
930 auto msg = reinterpret_cast<std::string *>(manager->GetQueueData());
931 if (!msg) {
932 NETSTACK_LOGE("msg is nullptr");
933 return NapiUtils::GetUndefined(env);
934 }
935 void *data = nullptr;
936 napi_value arrayBuffer = NapiUtils::CreateArrayBuffer(env, msg->size(), &data);
937 if (data != nullptr && NapiUtils::ValueIsArrayBuffer(env, arrayBuffer) &&
938 memcpy_s(data, msg->size(), msg->data(), msg->size()) >= 0) {
939 delete msg;
940 return arrayBuffer;
941 }
942 delete msg;
943 return NapiUtils::GetUndefined(env);
944 }
945
OnError(EventManager * manager,int32_t code,uint32_t httpResponse)946 void WebSocketExec::OnError(EventManager *manager, int32_t code, uint32_t httpResponse)
947 {
948 NETSTACK_LOGI("OnError %{public}d", code);
949 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
950 NETSTACK_LOGE("manager is null");
951 return;
952 }
953 if (!manager->HasEventListener(EventName::EVENT_ERROR)) {
954 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_ERROR);
955 return;
956 }
957 auto pair = new std::pair<int, uint32_t>;
958 pair->first = code;
959 pair->second = httpResponse;
960 manager->EmitByUvWithoutCheckShared(EventName::EVENT_ERROR, pair, CallbackTemplate<CreateError>);
961 }
962
CreateResponseHeader(napi_env env,void * callbackPara)963 napi_value CreateResponseHeader(napi_env env, void *callbackPara)
964 {
965 auto para = reinterpret_cast<std::map<std::string, std::string> *>(callbackPara);
966 if (para == nullptr) {
967 return NapiUtils::GetUndefined(env);
968 }
969 auto deleter = [](const std::map<std::string, std::string> *p) {
970 delete p;
971 p = nullptr;
972 };
973 std::unique_ptr<std::map<std::string, std::string>, decltype(deleter)> handler(para, deleter);
974 napi_value header = NapiUtils::CreateObject(env);
975 if (NapiUtils::GetValueType(env, header) != napi_object) {
976 return NapiUtils::GetUndefined(env);
977 }
978 for (const auto &singleHeader : *para) {
979 NapiUtils::SetStringPropertyUtf8(env, header, singleHeader.first, singleHeader.second);
980 }
981 return header;
982 }
983
OnOpen(EventManager * manager,uint32_t status,const std::string & message)984 void WebSocketExec::OnOpen(EventManager *manager, uint32_t status, const std::string &message)
985 {
986 NETSTACK_LOGI("OnOpen %{public}u %{public}s", status, message.c_str());
987 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
988 NETSTACK_LOGE("manager is null");
989 return;
990 }
991 if (!manager->HasEventListener(EventName::EVENT_OPEN)) {
992 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_OPEN);
993 return;
994 }
995 auto para = new OnOpenClosePara;
996 para->status = status;
997 para->message = message;
998 manager->EmitByUvWithoutCheckShared(EventName::EVENT_OPEN, para, CallbackTemplate<CreateOpenPara>);
999 }
1000
OnClose(EventManager * manager,lws_close_status closeStatus,const std::string & closeReason)1001 void WebSocketExec::OnClose(EventManager *manager, lws_close_status closeStatus, const std::string &closeReason)
1002 {
1003 NETSTACK_LOGI("OnClose %{public}u %{public}s", closeStatus, closeReason.c_str());
1004 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1005 NETSTACK_LOGE("manager is null");
1006 return;
1007 }
1008 if (!manager->HasEventListener(EventName::EVENT_CLOSE)) {
1009 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_CLOSE);
1010 return;
1011 }
1012 auto para = new OnOpenClosePara;
1013 para->status = closeStatus;
1014 para->message = closeReason;
1015 manager->EmitByUvWithoutCheckShared(EventName::EVENT_CLOSE, para, CallbackTemplate<CreateClosePara>);
1016 }
1017
OnMessage(EventManager * manager,void * data,size_t length,bool isBinary,bool isFinal)1018 void WebSocketExec::OnMessage(EventManager *manager, void *data, size_t length, bool isBinary, bool isFinal)
1019 {
1020 NETSTACK_LOGD("OnMessage %{public}d", isBinary);
1021 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1022 NETSTACK_LOGE("manager is null");
1023 return;
1024 }
1025 if (!manager->HasEventListener(EventName::EVENT_MESSAGE)) {
1026 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_MESSAGE);
1027 return;
1028 }
1029 if (length > INT32_MAX) {
1030 NETSTACK_LOGE("data length too long");
1031 return;
1032 }
1033 HandleRcvMessage(manager, data, length, isBinary, isFinal);
1034 }
1035
HandleRcvMessage(EventManager * manager,void * data,size_t length,bool isBinary,bool isFinal)1036 void WebSocketExec::HandleRcvMessage(EventManager *manager, void *data, size_t length, bool isBinary, bool isFinal)
1037 {
1038 if (isBinary) {
1039 manager->AppendWebSocketBinaryData(data, length);
1040 if (isFinal) {
1041 const std::string &msgFromManager = manager->GetWebSocketBinaryData();
1042 auto msg = new std::string;
1043 msg->append(msgFromManager.data(), msgFromManager.size());
1044 manager->SetQueueData(msg);
1045 manager->EmitByUvWithoutCheckShared(EventName::EVENT_MESSAGE, manager,
1046 CallbackTemplate<CreateBinaryMessagePara>);
1047 manager->ClearWebSocketBinaryData();
1048 }
1049 } else {
1050 manager->AppendWebSocketTextData(data, length);
1051 if (isFinal) {
1052 const std::string &msgFromManager = manager->GetWebSocketTextData();
1053 auto msg = new (std::nothrow) std::string;
1054 if (msg == nullptr) {
1055 return;
1056 }
1057 msg->append(msgFromManager.data(), msgFromManager.size());
1058 manager->SetQueueData(msg);
1059 manager->EmitByUvWithoutCheckShared(EventName::EVENT_MESSAGE, manager,
1060 CallbackTemplate<CreateTextMessagePara>);
1061 manager->ClearWebSocketTextData();
1062 }
1063 }
1064 }
1065
OnHeaderReceive(EventManager * manager,const std::map<std::string,std::string> & headers)1066 void WebSocketExec::OnHeaderReceive(EventManager *manager, const std::map<std::string, std::string> &headers)
1067 {
1068 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1069 NETSTACK_LOGE("manager is null");
1070 return;
1071 }
1072
1073 if (!manager->HasEventListener(EventName::EVENT_HEADER_RECEIVE)) {
1074 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_HEADER_RECEIVE);
1075 return;
1076 }
1077 auto para = new std::map<std::string, std::string>(headers);
1078 manager->EmitByUvWithoutCheckShared(EventName::EVENT_HEADER_RECEIVE, para, CallbackTemplate<CreateResponseHeader>);
1079 }
1080
GetWebsocketProxyInfo(ConnectContext * context,std::string & host,uint32_t & port,std::string & exclusions)1081 void WebSocketExec::GetWebsocketProxyInfo(ConnectContext *context, std::string &host, uint32_t &port,
1082 std::string &exclusions)
1083 {
1084 if (context->GetUsingWebsocketProxyType() == WebsocketProxyType::USE_SYSTEM) {
1085 #ifdef HAS_NETMANAGER_BASE
1086 using namespace NetManagerStandard;
1087 HttpProxy websocketProxy;
1088 NetConnClient::GetInstance().GetDefaultHttpProxy(websocketProxy);
1089 host = websocketProxy.GetHost();
1090 port = websocketProxy.GetPort();
1091 exclusions = CommonUtils::ToString(websocketProxy.GetExclusionList());
1092 #endif
1093 } else if (context->GetUsingWebsocketProxyType() == WebsocketProxyType::USE_SPECIFIED) {
1094 context->GetSpecifiedWebsocketProxy(host, port, exclusions);
1095 }
1096 }
1097 } // namespace OHOS::NetStack::Websocket
1098