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