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 = 2048;
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_LOGD("lws callback client connection error");
450 NETSTACK_LOGI("Lws client connection error %{public}s", (in == nullptr) ? "null" : reinterpret_cast<char *>(in));
451 // 200 means connect failed
452 OnConnectError(reinterpret_cast<EventManager *>(user), COMMON_ERROR_CODE, GetHttpResponseFromWsi(wsi));
453 return HttpDummy(wsi, reason, user, in, len);
454 }
455
LwsCallbackClientReceive(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)456 int WebSocketExec::LwsCallbackClientReceive(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
457 {
458 NETSTACK_LOGD("lws callback client receive");
459 auto manager = reinterpret_cast<EventManager *>(user);
460 auto isFinal = lws_is_final_fragment(wsi);
461 OnMessage(manager, in, len, lws_frame_is_binary(wsi), isFinal);
462 return HttpDummy(wsi, reason, user, in, len);
463 }
464
LwsCallbackClientFilterPreEstablish(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)465 int WebSocketExec::LwsCallbackClientFilterPreEstablish(lws *wsi, lws_callback_reasons reason, void *user, void *in,
466 size_t len)
467 {
468 NETSTACK_LOGD("lws callback client filter preEstablish");
469 auto manager = reinterpret_cast<EventManager *>(user);
470 auto userData = manager->GetWebSocketUserData();
471 if (userData == nullptr) {
472 NETSTACK_LOGE("user data is null");
473 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
474 }
475
476 userData->openStatus = GetHttpResponseFromWsi(wsi);
477 char statusLine[MAX_HDR_LENGTH] = {0};
478 if (lws_hdr_copy(wsi, statusLine, MAX_HDR_LENGTH, WSI_TOKEN_HTTP) < 0 || strlen(statusLine) == 0) {
479 return HttpDummy(wsi, reason, user, in, len);
480 }
481
482 auto vec = CommonUtils::Split(statusLine, STATUS_LINE_SEP, STATUS_LINE_ELEM_NUM);
483 if (vec.size() >= FUNCTION_PARAM_TWO) {
484 userData->openMessage = vec[1];
485 }
486
487 char buffer[MAX_HDR_LENGTH] = {};
488 std::map<std::string, std::string> responseHeader;
489 for (int i = 0; i < WSI_TOKEN_COUNT; i++) {
490 if (lws_hdr_total_length(wsi, static_cast<lws_token_indexes>(i)) > 0) {
491 lws_hdr_copy(wsi, buffer, sizeof(buffer), static_cast<lws_token_indexes>(i));
492 std::string str;
493 if (lws_token_to_string(static_cast<lws_token_indexes>(i))) {
494 str =
495 std::string(reinterpret_cast<const char *>(lws_token_to_string(static_cast<lws_token_indexes>(i))));
496 }
497 if (!str.empty() && str.back() == ':') {
498 responseHeader.emplace(str.substr(0, str.size() - 1), std::string(buffer));
499 }
500 }
501 }
502 lws_hdr_custom_name_foreach(
503 wsi,
504 [](const char *name, int nlen, void *opaque) -> void {
505 auto header = static_cast<std::map<std::string, std::string> *>(opaque);
506 if (header == nullptr) {
507 return;
508 }
509 header->emplace(std::string(name).substr(0, nlen - 1), std::string(name).substr(nlen));
510 },
511 &responseHeader);
512 OnHeaderReceive(manager, responseHeader);
513 return HttpDummy(wsi, reason, user, in, len);
514 }
515
LwsCallbackClientEstablished(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)516 int WebSocketExec::LwsCallbackClientEstablished(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
517 {
518 NETSTACK_LOGD("lws callback client established");
519 auto manager = reinterpret_cast<EventManager *>(user);
520 auto userData = manager->GetWebSocketUserData();
521 if (userData == nullptr) {
522 NETSTACK_LOGE("user data is null");
523 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
524 }
525 userData->TriggerWritable();
526 userData->SetLws(wsi);
527 OnOpen(reinterpret_cast<EventManager *>(user), userData->openStatus, userData->openMessage);
528 return HttpDummy(wsi, reason, user, in, len);
529 }
530
LwsCallbackClientClosed(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)531 int WebSocketExec::LwsCallbackClientClosed(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
532 {
533 NETSTACK_LOGD("lws callback client closed");
534 auto manager = reinterpret_cast<EventManager *>(user);
535 auto userData = manager->GetWebSocketUserData();
536 if (userData == nullptr) {
537 NETSTACK_LOGE("user data is null");
538 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
539 }
540 userData->SetThreadStop(true);
541 if ((userData->closeReason).empty()) {
542 userData->Close(userData->closeStatus, LINK_DOWN);
543 }
544 if (userData->closeStatus == LWS_CLOSE_STATUS_NOSTATUS) {
545 NETSTACK_LOGE("The link is down, onError");
546 OnError(manager, COMMON_ERROR_CODE, GetHttpResponseFromWsi(wsi));
547 }
548 OnClose(reinterpret_cast<EventManager *>(user), userData->closeStatus, userData->closeReason);
549 return HttpDummy(wsi, reason, user, in, len);
550 }
551
LwsCallbackWsiDestroy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)552 int WebSocketExec::LwsCallbackWsiDestroy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
553 {
554 NETSTACK_LOGD("lws callback wsi destroy");
555 auto manager = reinterpret_cast<EventManager *>(user);
556 if (manager == nullptr) {
557 NETSTACK_LOGE("manager is null");
558 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
559 }
560 auto userData = manager->GetWebSocketUserData();
561 if (userData == nullptr) {
562 NETSTACK_LOGE("user data is null");
563 return RaiseError(manager, GetHttpResponseFromWsi(wsi));
564 }
565 userData->SetLws(nullptr);
566 return HttpDummy(wsi, reason, user, in, len);
567 }
568
LwsCallbackProtocolDestroy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)569 int WebSocketExec::LwsCallbackProtocolDestroy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
570 {
571 NETSTACK_LOGD("lws callback protocol destroy");
572 return HttpDummy(wsi, reason, user, in, len);
573 }
574
575 // len: he number of days left before it expires
LwsCallbackVhostCertAging(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)576 int WebSocketExec::LwsCallbackVhostCertAging(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
577 {
578 NETSTACK_LOGI("lws callback vhost cert aging. len: %{public}zu", len);
579 return HttpDummy(wsi, reason, user, in, len);
580 }
581
LwsCallback(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)582 int WebSocketExec::LwsCallback(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
583 {
584 NETSTACK_LOGI("lws callback reason is %{public}d", reason);
585 CallbackDispatcher dispatchers[] = {
586 {LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, LwsCallbackClientAppendHandshakeHeader},
587 {LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, LwsCallbackWsPeerInitiatedClose},
588 {LWS_CALLBACK_CLIENT_WRITEABLE, LwsCallbackClientWritable},
589 {LWS_CALLBACK_CLIENT_CONNECTION_ERROR, LwsCallbackClientConnectionError},
590 {LWS_CALLBACK_CLIENT_RECEIVE, LwsCallbackClientReceive},
591 {LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, LwsCallbackClientFilterPreEstablish},
592 {LWS_CALLBACK_CLIENT_ESTABLISHED, LwsCallbackClientEstablished},
593 {LWS_CALLBACK_CLIENT_CLOSED, LwsCallbackClientClosed},
594 {LWS_CALLBACK_WSI_DESTROY, LwsCallbackWsiDestroy},
595 {LWS_CALLBACK_PROTOCOL_DESTROY, LwsCallbackProtocolDestroy},
596 {LWS_CALLBACK_VHOST_CERT_AGING, LwsCallbackVhostCertAging},
597 };
598
599 for (const auto dispatcher : dispatchers) {
600 if (dispatcher.reason == reason) {
601 return dispatcher.callback(wsi, reason, user, in, len);
602 }
603 }
604
605 return HttpDummy(wsi, reason, user, in, len);
606 }
607
FillContextInfo(ConnectContext * context,lws_context_creation_info & info,char * proxyAds)608 void WebSocketExec::FillContextInfo(ConnectContext *context, lws_context_creation_info &info, char *proxyAds)
609 {
610 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
611 info.port = CONTEXT_PORT_NO_LISTEN;
612 info.protocols = LWS_PROTOCOLS;
613 info.fd_limit_per_thread = FD_LIMIT_PER_THREAD;
614
615 char tempUri[MAX_URI_LENGTH] = {0};
616 const char *tempProtocol = nullptr;
617 const char *tempAddress = nullptr;
618 const char *tempPath = nullptr;
619 int32_t tempPort = 0;
620
621 std::string host;
622 uint32_t port = 0;
623 std::string exclusions;
624
625 if (strcpy_s(tempUri, MAX_URI_LENGTH, context->url.c_str()) < 0) {
626 NETSTACK_LOGE("strcpy_s failed");
627 return;
628 }
629 if (lws_parse_uri(tempUri, &tempProtocol, &tempAddress, &tempPort, &tempPath) != 0) {
630 NETSTACK_LOGE("get websocket hostname failed");
631 return;
632 }
633 GetWebsocketProxyInfo(context, host, port, exclusions);
634 if (!host.empty() && !CommonUtils::IsHostNameExcluded(tempAddress, exclusions, ",")) {
635 if (strcpy_s(proxyAds, host.length() + 1, host.c_str()) != EOK) {
636 NETSTACK_LOGE("memory copy failed");
637 }
638 info.http_proxy_address = proxyAds;
639 info.http_proxy_port = port;
640 }
641 }
642
CreatConnectInfo(ConnectContext * context,lws_context * lwsContext,const std::shared_ptr<EventManager> & manager)643 bool WebSocketExec::CreatConnectInfo(ConnectContext *context, lws_context *lwsContext,
644 const std::shared_ptr<EventManager> &manager)
645 {
646 lws_client_connect_info connectInfo = {};
647 char protocol[MAX_URI_LENGTH] = {0};
648 char address[MAX_URI_LENGTH] = {0};
649 char path[MAX_URI_LENGTH] = {0};
650 char customizedProtocol[MAX_PROTOCOL_LENGTH] = {0};
651 int port = 0;
652
653 if (!ParseUrl(context, protocol, MAX_URI_LENGTH, address, MAX_URI_LENGTH, path, MAX_URI_LENGTH, &port)) {
654 NETSTACK_LOGE("ParseUrl failed");
655 context->SetErrorCode(WEBSOCKET_ERROR_CODE_URL_ERROR);
656 return false;
657 }
658 if (lwsContext == nullptr) {
659 NETSTACK_LOGE("no memory");
660 return false;
661 }
662 std::string tempHost = std::string(address) + NAME_END + std::to_string(port);
663 std::string tempOrigin = std::string(protocol) + NAME_END + PROTOCOL_DELIMITER + tempHost;
664 NETSTACK_LOGD("tempOrigin = %{private}s", tempOrigin.c_str());
665 if (strcpy_s(customizedProtocol, context->GetProtocol().length() + 1, context->GetProtocol().c_str()) != EOK) {
666 NETSTACK_LOGE("memory copy failed");
667 }
668
669 connectInfo.context = lwsContext;
670 connectInfo.port = port;
671 connectInfo.address = address;
672 connectInfo.path = path;
673 connectInfo.host = address;
674 connectInfo.origin = address;
675 connectInfo.protocol = customizedProtocol;
676
677 if (strcmp(protocol, PREFIX_HTTPS) == 0 || strcmp(protocol, PREFIX_WSS) == 0) {
678 connectInfo.ssl_connection = LCCSCF_USE_SSL | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_SELFSIGNED;
679 }
680 lws *wsi = nullptr;
681 connectInfo.pwsi = &wsi;
682 connectInfo.retry_and_idle_policy = &RETRY;
683 connectInfo.userdata = manager.get();
684 if (lws_client_connect_via_info(&connectInfo) == nullptr) {
685 NETSTACK_LOGI("ExecConnect websocket connect failed");
686 context->SetErrorCode(-1);
687 OnConnectError(manager.get(), COMMON_ERROR_CODE, 0);
688 return false;
689 }
690 return true;
691 }
692
CheckFilePath(std::string & path)693 static bool CheckFilePath(std::string &path)
694 {
695 char tmpPath[PATH_MAX] = {0};
696 if (!realpath(static_cast<const char *>(path.c_str()), tmpPath)) {
697 NETSTACK_LOGE("path is error");
698 return false;
699 }
700 path = tmpPath;
701 return true;
702 }
703
FillCaPath(ConnectContext * context,lws_context_creation_info & info)704 bool WebSocketExec::FillCaPath(ConnectContext *context, lws_context_creation_info &info)
705 {
706 if (!context->caPath_.empty()) {
707 if (!CheckFilePath(context->caPath_)) {
708 NETSTACK_LOGE("ca not exist");
709 context->SetErrorCode(WEBSOCKET_ERROR_CODE_FILE_NOT_EXIST);
710 return false;
711 }
712 info.client_ssl_ca_filepath = context->caPath_.c_str();
713 NETSTACK_LOGD("load customize CA: %{public}s", info.client_ssl_ca_filepath);
714 } else {
715 info.client_ssl_ca_dirs[0] = WEBSOCKET_SYSTEM_PREPARE_CA_PATH;
716 #ifdef HAS_NETMANAGER_BASE
717 if (NetManagerStandard::NetConnClient::GetInstance().TrustUserCa()) {
718 context->userCertPath_ = BASE_PATH + std::to_string(getuid() / UID_TRANSFORM_DIVISOR);
719 info.client_ssl_ca_dirs[1] = context->userCertPath_.c_str();
720 }
721 #endif
722 NETSTACK_LOGD("load system CA");
723 }
724 if (!context->clientCert_.empty()) {
725 char realKeyPath[PATH_MAX] = {0};
726 if (!CheckFilePath(context->clientCert_) || !realpath(context->clientKey_.Data(), realKeyPath)) {
727 NETSTACK_LOGE("client cert not exist");
728 context->SetErrorCode(WEBSOCKET_ERROR_CODE_FILE_NOT_EXIST);
729 return false;
730 }
731 context->clientKey_ = Secure::SecureChar(realKeyPath);
732 info.client_ssl_cert_filepath = context->clientCert_.c_str();
733 info.client_ssl_private_key_filepath = context->clientKey_.Data();
734 info.client_ssl_private_key_password = context->keyPassword_.Data();
735 }
736 return true;
737 }
738
ExecConnect(ConnectContext * context)739 bool WebSocketExec::ExecConnect(ConnectContext *context)
740 {
741 NETSTACK_LOGD("websocket Connect exec");
742 if (context == nullptr) {
743 NETSTACK_LOGE("context is nullptr");
744 return false;
745 }
746 if (!CommonUtils::HasInternetPermission()) {
747 context->SetPermissionDenied(true);
748 return false;
749 }
750 if (context->IsAtomicService() &&
751 !CommonUtils::IsAllowedHostname(context->GetBundleName(), CommonUtils::DOMAIN_TYPE_WEBSOCKET_REQUEST,
752 context->url)) {
753 context->SetNoAllowedHost(true);
754 return false;
755 }
756 auto manager = context->GetSharedManager();
757 if (manager == nullptr) {
758 return false;
759 }
760 lws_context_creation_info info = {};
761 char proxyAds[MAX_ADDRESS_LENGTH] = {0};
762 FillContextInfo(context, info, proxyAds);
763 if (!FillCaPath(context, info)) {
764 return false;
765 }
766 lws_context *lwsContext = nullptr;
767 std::shared_ptr<UserData> userData;
768 if (manager->GetWebSocketUserData() == nullptr) {
769 lwsContext = lws_create_context(&info);
770 userData = std::make_shared<UserData>(lwsContext);
771 userData->header = context->header;
772 manager->SetWebSocketUserData(userData);
773 } else {
774 NETSTACK_LOGE("Websocket connect already exist");
775 context->SetErrorCode(WEBSOCKET_ERROR_CODE_CONNECT_AlREADY_EXIST);
776 return false;
777 }
778 if (!CreatConnectInfo(context, lwsContext, manager)) {
779 userData->SetContext(nullptr);
780 lws_context_destroy(lwsContext);
781 manager->SetWebSocketUserData(nullptr);
782 return false;
783 }
784 std::thread serviceThread(RunService, userData, manager);
785
786 #if defined(MAC_PLATFORM) || defined(IOS_PLATFORM)
787 pthread_setname_np(WEBSOCKET_CLIENT_THREAD_RUN);
788 #else
789 pthread_setname_np(serviceThread.native_handle(), WEBSOCKET_CLIENT_THREAD_RUN);
790 #endif
791 serviceThread.detach();
792 return true;
793 }
794
ConnectCallback(ConnectContext * context)795 napi_value WebSocketExec::ConnectCallback(ConnectContext *context)
796 {
797 if (context->GetErrorCode() < 0) {
798 NETSTACK_LOGI("ConnectCallback connect failed");
799 return NapiUtils::GetBoolean(context->GetEnv(), false);
800 }
801 NETSTACK_LOGI("ConnectCallback connect success");
802 return NapiUtils::GetBoolean(context->GetEnv(), true);
803 }
804
ExecSend(SendContext * context)805 bool WebSocketExec::ExecSend(SendContext *context)
806 {
807 if (context == nullptr) {
808 NETSTACK_LOGE("context is nullptr");
809 return false;
810 }
811 if (!CommonUtils::HasInternetPermission()) {
812 context->SetPermissionDenied(true);
813 return false;
814 }
815 auto manager = context->GetSharedManager();
816 if (manager == nullptr) {
817 NETSTACK_LOGE("context is null");
818 return false;
819 }
820 auto userData = manager->GetWebSocketUserData();
821 if (userData == nullptr) {
822 NETSTACK_LOGE("user data is nullptr");
823 return false;
824 }
825 if (userData->IsClosed() || userData->IsThreadStop()) {
826 NETSTACK_LOGE("session is closed or stopped");
827 return false;
828 }
829 userData->Push(context->data, context->length, context->protocol);
830 userData->TriggerWritable();
831 NETSTACK_LOGD("lws ts send success");
832 return true;
833 }
834
SendCallback(SendContext * context)835 napi_value WebSocketExec::SendCallback(SendContext *context)
836 {
837 return NapiUtils::GetBoolean(context->GetEnv(), true);
838 }
839
ExecClose(CloseContext * context)840 bool WebSocketExec::ExecClose(CloseContext *context)
841 {
842 if (context == nullptr) {
843 NETSTACK_LOGE("context is nullptr");
844 return false;
845 }
846 if (!CommonUtils::HasInternetPermission()) {
847 context->SetPermissionDenied(true);
848 return false;
849 }
850 if (context->GetSharedManager() == nullptr) {
851 NETSTACK_LOGE("context is null");
852 return false;
853 }
854
855 auto manager = context->GetSharedManager();
856 auto userData = manager->GetWebSocketUserData();
857 if (userData == nullptr) {
858 NETSTACK_LOGE("user data is nullptr");
859 return false;
860 }
861
862 if (userData->IsClosed()) {
863 NETSTACK_LOGE("connection has been closed");
864 return false;
865 }
866 userData->Close(static_cast<lws_close_status>(context->code), context->reason);
867 userData->TriggerWritable();
868 NETSTACK_LOGI("ExecClose OK");
869 return true;
870 }
871
CloseCallback(CloseContext * context)872 napi_value WebSocketExec::CloseCallback(CloseContext *context)
873 {
874 auto manager = context->GetSharedManager();
875 if (manager != nullptr) {
876 NETSTACK_LOGD("websocket close, delete js ref");
877 manager->DeleteEventReference(context->GetEnv());
878 }
879 return NapiUtils::GetBoolean(context->GetEnv(), true);
880 }
881
CreateError(napi_env env,void * callbackPara)882 static napi_value CreateError(napi_env env, void *callbackPara)
883 {
884 auto pair = reinterpret_cast<std::pair<int, uint32_t> *>(callbackPara);
885 auto deleter = [](std::pair<int, uint32_t> *p) { delete p; };
886 std::unique_ptr<std::pair<int, uint32_t>, decltype(deleter)> handler(pair, deleter);
887 napi_value err = NapiUtils::CreateObject(env);
888 if (NapiUtils::GetValueType(env, err) != napi_object) {
889 return NapiUtils::GetUndefined(env);
890 }
891 NapiUtils::SetInt32Property(env, err, EVENT_KEY_CODE, pair->first);
892 NapiUtils::SetStringPropertyUtf8(env, err, "data", std::to_string(pair->second));
893 return err;
894 }
895
CreateOpenPara(napi_env env,void * callbackPara)896 static napi_value CreateOpenPara(napi_env env, void *callbackPara)
897 {
898 auto para = reinterpret_cast<OnOpenClosePara *>(callbackPara);
899 auto deleter = [](const OnOpenClosePara *p) { delete p; };
900 std::unique_ptr<OnOpenClosePara, decltype(deleter)> handler(para, deleter);
901 napi_value obj = NapiUtils::CreateObject(env);
902 if (NapiUtils::GetValueType(env, obj) != napi_object) {
903 return NapiUtils::GetUndefined(env);
904 }
905 NapiUtils::SetUint32Property(env, obj, EVENT_KEY_STATUS, para->status);
906 NapiUtils::SetStringPropertyUtf8(env, obj, EVENT_KEY_MESSAGE, para->message);
907 return obj;
908 }
909
CreateClosePara(napi_env env,void * callbackPara)910 static napi_value CreateClosePara(napi_env env, void *callbackPara)
911 {
912 auto para = reinterpret_cast<OnOpenClosePara *>(callbackPara);
913 auto deleter = [](const OnOpenClosePara *p) { delete p; };
914 std::unique_ptr<OnOpenClosePara, decltype(deleter)> handler(para, deleter);
915 napi_value obj = NapiUtils::CreateObject(env);
916 if (NapiUtils::GetValueType(env, obj) != napi_object) {
917 return NapiUtils::GetUndefined(env);
918 }
919 NapiUtils::SetUint32Property(env, obj, EVENT_KEY_CODE, para->status);
920 NapiUtils::SetStringPropertyUtf8(env, obj, EVENT_KEY_REASON, para->message);
921 return obj;
922 }
923
CreateTextMessagePara(napi_env env,void * callbackPara)924 static napi_value CreateTextMessagePara(napi_env env, void *callbackPara)
925 {
926 auto manager = reinterpret_cast<EventManager *>(callbackPara);
927 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
928 return NapiUtils::CreateStringUtf8(env, "");
929 }
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 auto text = NapiUtils::CreateStringUtf8(env, *msg);
936 delete msg;
937 return text;
938 }
939
CreateBinaryMessagePara(napi_env env,void * callbackPara)940 static napi_value CreateBinaryMessagePara(napi_env env, void *callbackPara)
941 {
942 auto manager = reinterpret_cast<EventManager *>(callbackPara);
943 auto msg = reinterpret_cast<std::string *>(manager->GetQueueData());
944 if (!msg) {
945 NETSTACK_LOGE("msg is nullptr");
946 return NapiUtils::GetUndefined(env);
947 }
948 void *data = nullptr;
949 napi_value arrayBuffer = NapiUtils::CreateArrayBuffer(env, msg->size(), &data);
950 if (data != nullptr && NapiUtils::ValueIsArrayBuffer(env, arrayBuffer) &&
951 memcpy_s(data, msg->size(), msg->data(), msg->size()) >= 0) {
952 delete msg;
953 return arrayBuffer;
954 }
955 delete msg;
956 return NapiUtils::GetUndefined(env);
957 }
958
OnError(EventManager * manager,int32_t code,uint32_t httpResponse)959 void WebSocketExec::OnError(EventManager *manager, int32_t code, uint32_t httpResponse)
960 {
961 NETSTACK_LOGI("OnError %{public}d", code);
962 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
963 NETSTACK_LOGE("manager is null");
964 return;
965 }
966 if (!manager->HasEventListener(EventName::EVENT_ERROR)) {
967 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_ERROR);
968 return;
969 }
970 auto pair = new std::pair<int, uint32_t>;
971 pair->first = code;
972 pair->second = httpResponse;
973 manager->EmitByUvWithoutCheckShared(EventName::EVENT_ERROR, pair, CallbackTemplate<CreateError>);
974 }
975
CreateResponseHeader(napi_env env,void * callbackPara)976 napi_value CreateResponseHeader(napi_env env, void *callbackPara)
977 {
978 auto para = reinterpret_cast<std::map<std::string, std::string> *>(callbackPara);
979 if (para == nullptr) {
980 return NapiUtils::GetUndefined(env);
981 }
982 auto deleter = [](const std::map<std::string, std::string> *p) {
983 delete p;
984 p = nullptr;
985 };
986 std::unique_ptr<std::map<std::string, std::string>, decltype(deleter)> handler(para, deleter);
987 napi_value header = NapiUtils::CreateObject(env);
988 if (NapiUtils::GetValueType(env, header) != napi_object) {
989 return NapiUtils::GetUndefined(env);
990 }
991 for (const auto &singleHeader : *para) {
992 NapiUtils::SetStringPropertyUtf8(env, header, singleHeader.first, singleHeader.second);
993 }
994 return header;
995 }
996
OnOpen(EventManager * manager,uint32_t status,const std::string & message)997 void WebSocketExec::OnOpen(EventManager *manager, uint32_t status, const std::string &message)
998 {
999 NETSTACK_LOGI("OnOpen %{public}u %{public}s", status, message.c_str());
1000 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1001 NETSTACK_LOGE("manager is null");
1002 return;
1003 }
1004 if (!manager->HasEventListener(EventName::EVENT_OPEN)) {
1005 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_OPEN);
1006 return;
1007 }
1008 auto para = new OnOpenClosePara;
1009 para->status = status;
1010 para->message = message;
1011 manager->EmitByUvWithoutCheckShared(EventName::EVENT_OPEN, para, CallbackTemplate<CreateOpenPara>);
1012 }
1013
OnClose(EventManager * manager,lws_close_status closeStatus,const std::string & closeReason)1014 void WebSocketExec::OnClose(EventManager *manager, lws_close_status closeStatus, const std::string &closeReason)
1015 {
1016 NETSTACK_LOGI("OnClose %{public}u %{public}s", closeStatus, closeReason.c_str());
1017 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1018 NETSTACK_LOGE("manager is null");
1019 return;
1020 }
1021 if (!manager->HasEventListener(EventName::EVENT_CLOSE)) {
1022 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_CLOSE);
1023 return;
1024 }
1025 auto para = new OnOpenClosePara;
1026 para->status = closeStatus;
1027 para->message = closeReason;
1028 manager->EmitByUvWithoutCheckShared(EventName::EVENT_CLOSE, para, CallbackTemplate<CreateClosePara>);
1029 }
1030
OnMessage(EventManager * manager,void * data,size_t length,bool isBinary,bool isFinal)1031 void WebSocketExec::OnMessage(EventManager *manager, void *data, size_t length, bool isBinary, bool isFinal)
1032 {
1033 NETSTACK_LOGD("OnMessage %{public}d", isBinary);
1034 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1035 NETSTACK_LOGE("manager is null");
1036 return;
1037 }
1038 if (!manager->HasEventListener(EventName::EVENT_MESSAGE)) {
1039 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_MESSAGE);
1040 return;
1041 }
1042 if (length > INT32_MAX) {
1043 NETSTACK_LOGE("data length too long");
1044 return;
1045 }
1046 HandleRcvMessage(manager, data, length, isBinary, isFinal);
1047 }
1048
HandleRcvMessage(EventManager * manager,void * data,size_t length,bool isBinary,bool isFinal)1049 void WebSocketExec::HandleRcvMessage(EventManager *manager, void *data, size_t length, bool isBinary, bool isFinal)
1050 {
1051 if (isBinary) {
1052 manager->AppendWebSocketBinaryData(data, length);
1053 if (isFinal) {
1054 const std::string &msgFromManager = manager->GetWebSocketBinaryData();
1055 auto msg = new std::string;
1056 msg->append(msgFromManager.data(), msgFromManager.size());
1057 manager->SetQueueData(msg);
1058 manager->EmitByUvWithoutCheckShared(EventName::EVENT_MESSAGE, manager,
1059 CallbackTemplate<CreateBinaryMessagePara>);
1060 manager->ClearWebSocketBinaryData();
1061 }
1062 } else {
1063 manager->AppendWebSocketTextData(data, length);
1064 if (isFinal) {
1065 const std::string &msgFromManager = manager->GetWebSocketTextData();
1066 auto msg = new (std::nothrow) std::string;
1067 if (msg == nullptr) {
1068 return;
1069 }
1070 msg->append(msgFromManager.data(), msgFromManager.size());
1071 manager->SetQueueData(msg);
1072 manager->EmitByUvWithoutCheckShared(EventName::EVENT_MESSAGE, manager,
1073 CallbackTemplate<CreateTextMessagePara>);
1074 manager->ClearWebSocketTextData();
1075 }
1076 }
1077 }
1078
OnHeaderReceive(EventManager * manager,const std::map<std::string,std::string> & headers)1079 void WebSocketExec::OnHeaderReceive(EventManager *manager, const std::map<std::string, std::string> &headers)
1080 {
1081 if (manager == nullptr || manager->innerMagic_.magicNumber != EVENT_MANAGER_MAGIC_NUMBER) {
1082 NETSTACK_LOGE("manager is null");
1083 return;
1084 }
1085
1086 if (!manager->HasEventListener(EventName::EVENT_HEADER_RECEIVE)) {
1087 NETSTACK_LOGI("no event listener: %{public}s", EventName::EVENT_HEADER_RECEIVE);
1088 return;
1089 }
1090 auto para = new std::map<std::string, std::string>(headers);
1091 manager->EmitByUvWithoutCheckShared(EventName::EVENT_HEADER_RECEIVE, para, CallbackTemplate<CreateResponseHeader>);
1092 }
1093
GetWebsocketProxyInfo(ConnectContext * context,std::string & host,uint32_t & port,std::string & exclusions)1094 void WebSocketExec::GetWebsocketProxyInfo(ConnectContext *context, std::string &host, uint32_t &port,
1095 std::string &exclusions)
1096 {
1097 if (context->GetUsingWebsocketProxyType() == WebsocketProxyType::USE_SYSTEM) {
1098 #ifdef HAS_NETMANAGER_BASE
1099 using namespace NetManagerStandard;
1100 HttpProxy websocketProxy;
1101 NetConnClient::GetInstance().GetDefaultHttpProxy(websocketProxy);
1102 host = websocketProxy.GetHost();
1103 port = websocketProxy.GetPort();
1104 exclusions = CommonUtils::ToString(websocketProxy.GetExclusionList());
1105 #endif
1106 } else if (context->GetUsingWebsocketProxyType() == WebsocketProxyType::USE_SPECIFIED) {
1107 context->GetSpecifiedWebsocketProxy(host, port, exclusions);
1108 }
1109 }
1110 } // namespace OHOS::NetStack::Websocket
1111