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