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