• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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