1 /*
2 * Copyright (c) 2023 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 <cstring>
17 #include <iostream>
18 #include <securec.h>
19 #include <string>
20
21 #include "netstack_log.h"
22 #include "websocket_client_innerapi.h"
23
24 static constexpr const char *PATH_START = "/";
25 static constexpr const char *NAME_END = ":";
26 static constexpr const char *STATUS_LINE_SEP = " ";
27 static constexpr const size_t STATUS_LINE_ELEM_NUM = 2;
28 static constexpr const char *PREFIX_HTTPS = "https";
29 static constexpr const char *PREFIX_WSS = "wss";
30 static constexpr const int MAX_URI_LENGTH = 1024;
31 static constexpr const int MAX_HDR_LENGTH = 1024;
32 static constexpr const int MAX_HEADER_LENGTH = 8192;
33 static constexpr const size_t MAX_DATA_LENGTH = 4 * 1024 * 1024;
34 static constexpr const int FD_LIMIT_PER_THREAD = 1 + 1 + 1;
35 static constexpr const int CLOSE_RESULT_FROM_SERVER_CODE = 1001;
36 static constexpr const int CLOSE_RESULT_FROM_CLIENT_CODE = 1000;
37 static constexpr const char *LINK_DOWN = "The link is down";
38 static constexpr const char *CLOSE_REASON_FORM_SERVER = "websocket close from server";
39 static constexpr const int FUNCTION_PARAM_TWO = 2;
40 static constexpr const char *WEBSOCKET_CLIENT_THREAD_RUN = "OS_NET_WSCli";
41 static std::atomic<int> g_clientID(0);
42 namespace OHOS::NetStack::WebSocketClient {
43 static const lws_retry_bo_t RETRY = {
44 .secs_since_valid_ping = 0, /* force PINGs after secs idle */
45 .secs_since_valid_hangup = 10, /* hangup after secs idle */
46 .jitter_percent = 20,
47 };
48
WebSocketClient()49 WebSocketClient::WebSocketClient()
50 {
51 clientContext = new ClientContext();
52 clientContext->SetClientId(++g_clientID);
53 }
54
~WebSocketClient()55 WebSocketClient::~WebSocketClient()
56 {
57 delete clientContext;
58 clientContext = nullptr;
59 }
60
GetClientContext() const61 ClientContext *WebSocketClient::GetClientContext() const
62 {
63 return clientContext;
64 }
65
RunService(WebSocketClient * Client)66 void RunService(WebSocketClient *Client)
67 {
68 if (Client->GetClientContext()->GetContext() == nullptr) {
69 return;
70 }
71 while (!Client->GetClientContext()->IsThreadStop()) {
72 lws_service(Client->GetClientContext()->GetContext(), 0);
73 }
74 }
75
HttpDummy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)76 int HttpDummy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
77 {
78 int ret = lws_callback_http_dummy(wsi, reason, user, in, len);
79 return ret;
80 }
81
82 struct CallbackDispatcher {
83 lws_callback_reasons reason;
84 int (*callback)(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len);
85 };
86
LwsCallbackClientAppendHandshakeHeader(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)87 int LwsCallbackClientAppendHandshakeHeader(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
88 {
89 WebSocketClient *client = static_cast<WebSocketClient *>(user);
90 if (client->GetClientContext() == nullptr) {
91 NETSTACK_LOGE("Callback ClientContext is nullptr");
92 return -1;
93 }
94 NETSTACK_LOGD("ClientId:%{public}d, Lws Callback AppendHandshakeHeader,",
95 client->GetClientContext()->GetClientId());
96 auto payload = reinterpret_cast<unsigned char **>(in);
97 if (payload == nullptr || (*payload) == nullptr || len == 0) {
98 return -1;
99 }
100 auto payloadEnd = (*payload) + len;
101 for (const auto &pair : client->GetClientContext()->header) {
102 std::string name = pair.first + NAME_END;
103 if (lws_add_http_header_by_name(wsi, reinterpret_cast<const unsigned char *>(name.c_str()),
104 reinterpret_cast<const unsigned char *>(pair.second.c_str()),
105 static_cast<int>(strlen(pair.second.c_str())), payload, payloadEnd)) {
106 return -1;
107 }
108 }
109 return HttpDummy(wsi, reason, user, in, len);
110 }
111
LwsCallbackWsPeerInitiatedClose(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)112 int LwsCallbackWsPeerInitiatedClose(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
113 {
114 WebSocketClient *client = static_cast<WebSocketClient *>(user);
115 if (client->GetClientContext() == nullptr) {
116 NETSTACK_LOGE("Lws Callback ClientContext is nullptr");
117 return -1;
118 }
119 NETSTACK_LOGD("ClientId:%{public}d,Callback WsPeerInitiatedClose", client->GetClientContext()->GetClientId());
120 if (in == nullptr || len < sizeof(uint16_t)) {
121 NETSTACK_LOGE("Lws Callback WsPeerInitiatedClose");
122 client->GetClientContext()->Close(LWS_CLOSE_STATUS_NORMAL, "");
123 return HttpDummy(wsi, reason, user, in, len);
124 }
125 uint16_t closeStatus = ntohs(*reinterpret_cast<uint16_t *>(in));
126 std::string closeReason;
127 closeReason.append(reinterpret_cast<char *>(in) + sizeof(uint16_t), len - sizeof(uint16_t));
128 client->GetClientContext()->Close(static_cast<lws_close_status>(closeStatus), closeReason);
129 return HttpDummy(wsi, reason, user, in, len);
130 }
131
LwsCallbackClientWritable(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)132 int LwsCallbackClientWritable(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
133 {
134 WebSocketClient *client = static_cast<WebSocketClient *>(user);
135 if (client->GetClientContext() == nullptr) {
136 NETSTACK_LOGE("Lws Callback ClientContext is nullptr");
137 return -1;
138 }
139 NETSTACK_LOGD("ClientId:%{public}d,Callback CallbackClientWritable,",
140 client->GetClientContext()->GetClientId());
141 if (client->GetClientContext()->IsClosed()) {
142 NETSTACK_LOGD("ClientId:%{public}d,Callback ClientWritable need to close",
143 client->GetClientContext()->GetClientId());
144 lws_close_reason(
145 wsi, client->GetClientContext()->closeStatus,
146 reinterpret_cast<unsigned char *>(const_cast<char *>(client->GetClientContext()->closeReason.c_str())),
147 strlen(client->GetClientContext()->closeReason.c_str()));
148 // here do not emit error, because we close it
149 return -1;
150 }
151 SendData sendData = client->GetClientContext()->Pop();
152 if (sendData.data == nullptr || sendData.length == 0) {
153 return HttpDummy(wsi, reason, user, in, len);
154 }
155 const char *message = sendData.data;
156 size_t messageLen = sendData.length;
157 auto buffer = std::make_unique<unsigned char[]>(LWS_PRE + messageLen);
158 if (buffer == nullptr) {
159 return -1;
160 }
161 int result = memcpy_s(buffer.get() + LWS_PRE, LWS_PRE + messageLen, message, messageLen);
162 if (result != 0) {
163 return -1;
164 }
165 free(sendData.data);
166 int bytesSent = lws_write(wsi, buffer.get() + LWS_PRE, messageLen, sendData.protocol);
167 NETSTACK_LOGD("ClientId:%{public}d,Client Writable send data length = %{public}d",
168 client->GetClientContext()->GetClientId(), bytesSent);
169 return HttpDummy(wsi, reason, user, in, len);
170 }
171
LwsCallbackClientConnectionError(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)172 int LwsCallbackClientConnectionError(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
173 {
174 WebSocketClient *client = static_cast<WebSocketClient *>(user);
175 NETSTACK_LOGE("ClientId:%{public}d,Callback ClientConnectionError", client->GetClientContext()->GetClientId());
176 std::string buf;
177 char *data = static_cast<char *>(in);
178 buf.assign(data, len);
179 ErrorResult errorResult;
180 errorResult.errorCode = WebSocketErrorCode::WEBSOCKET_CONNECTION_ERROR;
181 errorResult.errorMessage = data;
182 client->onErrorCallback_(client, errorResult);
183 return HttpDummy(wsi, reason, user, in, len);
184 }
185
LwsCallbackClientReceive(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)186 int LwsCallbackClientReceive(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
187 {
188 WebSocketClient *client = static_cast<WebSocketClient *>(user);
189 NETSTACK_LOGD("ClientId:%{public}d,Callback ClientReceive", client->GetClientContext()->GetClientId());
190 std::string buf;
191 char *data = static_cast<char *>(in);
192 buf.assign(data, len);
193 client->onMessageCallback_(client, data, len);
194 return HttpDummy(wsi, reason, user, in, len);
195 }
196
Split(const std::string & str,const std::string & sep,size_t size)197 std::vector<std::string> Split(const std::string &str, const std::string &sep, size_t size)
198 {
199 std::string s = str;
200 std::vector<std::string> res;
201 while (!s.empty()) {
202 if (res.size() + 1 == size) {
203 res.emplace_back(s);
204 break;
205 }
206 auto pos = s.find(sep);
207 if (pos == std::string::npos) {
208 res.emplace_back(s);
209 break;
210 }
211 res.emplace_back(s.substr(0, pos));
212 s = s.substr(pos + sep.size());
213 }
214 return res;
215 }
216
LwsCallbackClientFilterPreEstablish(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)217 int LwsCallbackClientFilterPreEstablish(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
218 {
219 WebSocketClient *client = static_cast<WebSocketClient *>(user);
220 if (client->GetClientContext() == nullptr) {
221 NETSTACK_LOGE("Callback ClientContext is nullptr");
222 return -1;
223 }
224 client->GetClientContext()->openStatus = lws_http_client_http_response(wsi);
225 NETSTACK_LOGD("ClientId:%{public}d, libwebsockets Callback ClientFilterPreEstablish openStatus = %{public}d",
226 client->GetClientContext()->GetClientId(), client->GetClientContext()->openStatus);
227 char statusLine[MAX_HDR_LENGTH] = {0};
228 if (lws_hdr_copy(wsi, statusLine, MAX_HDR_LENGTH, WSI_TOKEN_HTTP) < 0 || strlen(statusLine) == 0) {
229 return HttpDummy(wsi, reason, user, in, len);
230 }
231 auto vec = Split(statusLine, STATUS_LINE_SEP, STATUS_LINE_ELEM_NUM);
232 if (vec.size() >= FUNCTION_PARAM_TWO) {
233 client->GetClientContext()->openMessage = vec[1];
234 }
235 return HttpDummy(wsi, reason, user, in, len);
236 }
237
LwsCallbackClientEstablished(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)238 int LwsCallbackClientEstablished(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
239 {
240 WebSocketClient *client = static_cast<WebSocketClient *>(user);
241 if (client->GetClientContext() == nullptr) {
242 NETSTACK_LOGE("libwebsockets Callback ClientContext is nullptr");
243 return -1;
244 }
245 NETSTACK_LOGI("ClientId:%{public}d,Callback ClientEstablished", client->GetClientContext()->GetClientId());
246 OpenResult openResult;
247 openResult.status = client->GetClientContext()->openStatus;
248 openResult.message = client->GetClientContext()->openMessage.c_str();
249 client->onOpenCallback_(client, openResult);
250
251 return HttpDummy(wsi, reason, user, in, len);
252 }
253
LwsCallbackClientClosed(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)254 int LwsCallbackClientClosed(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
255 {
256 WebSocketClient *client = static_cast<WebSocketClient *>(user);
257 if (client->GetClientContext() == nullptr) {
258 NETSTACK_LOGE("Callback ClientContext is nullptr");
259 return -1;
260 }
261 NETSTACK_LOGI("ClientId:%{public}d,Callback ClientClosed", client->GetClientContext()->GetClientId());
262 std::string buf;
263 char *data = static_cast<char *>(in);
264 buf.assign(data, len);
265 CloseResult closeResult;
266 closeResult.code = CLOSE_RESULT_FROM_SERVER_CODE;
267 closeResult.reason = CLOSE_REASON_FORM_SERVER;
268 client->onCloseCallback_(client, closeResult);
269 client->GetClientContext()->SetThreadStop(true);
270 if ((client->GetClientContext()->closeReason).empty()) {
271 client->GetClientContext()->Close(client->GetClientContext()->closeStatus, LINK_DOWN);
272 }
273 return HttpDummy(wsi, reason, user, in, len);
274 }
275
LwsCallbackWsiDestroy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)276 int LwsCallbackWsiDestroy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
277 {
278 WebSocketClient *client = static_cast<WebSocketClient *>(user);
279 if (client->GetClientContext() == nullptr) {
280 NETSTACK_LOGE("Callback ClientContext is nullptr");
281 return -1;
282 }
283 NETSTACK_LOGI("Lws Callback LwsCallbackWsiDestroy");
284 return HttpDummy(wsi, reason, user, in, len);
285 }
286
LwsCallbackProtocolDestroy(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)287 int LwsCallbackProtocolDestroy(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
288 {
289 NETSTACK_LOGI("Lws Callback ProtocolDestroy");
290 return HttpDummy(wsi, reason, user, in, len);
291 }
292
LwsCallback(lws * wsi,lws_callback_reasons reason,void * user,void * in,size_t len)293 int LwsCallback(lws *wsi, lws_callback_reasons reason, void *user, void *in, size_t len)
294 {
295 constexpr CallbackDispatcher dispatchers[] = {
296 {LWS_CALLBACK_CLIENT_APPEND_HANDSHAKE_HEADER, LwsCallbackClientAppendHandshakeHeader},
297 {LWS_CALLBACK_WS_PEER_INITIATED_CLOSE, LwsCallbackWsPeerInitiatedClose},
298 {LWS_CALLBACK_CLIENT_WRITEABLE, LwsCallbackClientWritable},
299 {LWS_CALLBACK_CLIENT_CONNECTION_ERROR, LwsCallbackClientConnectionError},
300 {LWS_CALLBACK_CLIENT_RECEIVE, LwsCallbackClientReceive},
301 {LWS_CALLBACK_CLIENT_FILTER_PRE_ESTABLISH, LwsCallbackClientFilterPreEstablish},
302 {LWS_CALLBACK_CLIENT_ESTABLISHED, LwsCallbackClientEstablished},
303 {LWS_CALLBACK_CLIENT_CLOSED, LwsCallbackClientClosed},
304 {LWS_CALLBACK_WSI_DESTROY, LwsCallbackWsiDestroy},
305 {LWS_CALLBACK_PROTOCOL_DESTROY, LwsCallbackProtocolDestroy},
306 };
307 auto it = std::find_if(std::begin(dispatchers), std::end(dispatchers),
308 [&reason](const CallbackDispatcher &dispatcher) { return dispatcher.reason == reason; });
309 if (it != std::end(dispatchers)) {
310 return it->callback(wsi, reason, user, in, len);
311 }
312 return HttpDummy(wsi, reason, user, in, len);
313 }
314
315 static struct lws_protocols protocols[] = {{"lws-minimal-client1", LwsCallback, 0, 0, 0, NULL, 0},
316 LWS_PROTOCOL_LIST_TERM};
317
FillContextInfo(lws_context_creation_info & info)318 static void FillContextInfo(lws_context_creation_info &info)
319 {
320 info.options = LWS_SERVER_OPTION_DO_SSL_GLOBAL_INIT;
321 info.port = CONTEXT_PORT_NO_LISTEN;
322 info.protocols = protocols;
323 info.fd_limit_per_thread = FD_LIMIT_PER_THREAD;
324 }
325
ParseUrl(const std::string url,char * prefix,char * address,char * path,int * port)326 bool ParseUrl(const std::string url, char *prefix, char *address, char *path, int *port)
327 {
328 char uri[MAX_URI_LENGTH] = {0};
329 if (strcpy_s(uri, MAX_URI_LENGTH, url.c_str()) < 0) {
330 NETSTACK_LOGE("strcpy_s failed");
331 return false;
332 }
333 const char *tempPrefix = nullptr;
334 const char *tempAddress = nullptr;
335 const char *tempPath = nullptr;
336 (void)lws_parse_uri(uri, &tempPrefix, &tempAddress, port, &tempPath);
337 if (strcpy_s(prefix, MAX_URI_LENGTH, tempPrefix) < 0) {
338 NETSTACK_LOGE("strcpy_s failed");
339 return false;
340 }
341 if (strcpy_s(address, MAX_URI_LENGTH, tempAddress) < 0) {
342 NETSTACK_LOGE("strcpy_s failed");
343 return false;
344 }
345 if (strcpy_s(path, MAX_URI_LENGTH, tempPath) < 0) {
346 NETSTACK_LOGE("strcpy_s failed");
347 return false;
348 }
349 return true;
350 }
351
CreatConnectInfo(const std::string url,lws_context * lwsContext,WebSocketClient * client)352 int CreatConnectInfo(const std::string url, lws_context *lwsContext, WebSocketClient *client)
353 {
354 lws_client_connect_info connectInfo = {};
355 char prefix[MAX_URI_LENGTH] = {0};
356 char address[MAX_URI_LENGTH] = {0};
357 char pathWithoutStart[MAX_URI_LENGTH] = {0};
358 int port = 0;
359 if (!ParseUrl(url, prefix, address, pathWithoutStart, &port)) {
360 return WebSocketErrorCode::WEBSOCKET_CONNECTION_PARSEURL_ERROR;
361 }
362 std::string path = PATH_START + std::string(pathWithoutStart);
363
364 connectInfo.context = lwsContext;
365 connectInfo.address = address;
366 connectInfo.port = port;
367 connectInfo.path = path.c_str();
368 connectInfo.host = address;
369 connectInfo.origin = address;
370
371 connectInfo.local_protocol_name = "lws-minimal-client1";
372 connectInfo.retry_and_idle_policy = &RETRY;
373 if (strcmp(prefix, PREFIX_HTTPS) == 0 || strcmp(prefix, PREFIX_WSS) == 0) {
374 connectInfo.ssl_connection =
375 LCCSCF_USE_SSL | LCCSCF_SKIP_SERVER_CERT_HOSTNAME_CHECK | LCCSCF_ALLOW_INSECURE | LCCSCF_ALLOW_SELFSIGNED;
376 }
377 lws *wsi = nullptr;
378 connectInfo.pwsi = &wsi;
379 connectInfo.userdata = client;
380 if (lws_client_connect_via_info(&connectInfo) == nullptr) {
381 NETSTACK_LOGE("Connect lws_context_destroy");
382 return WebSocketErrorCode::WEBSOCKET_CONNECTION_TO_SERVER_FAIL;
383 }
384 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
385 }
386
Connect(std::string url,struct OpenOptions options)387 int WebSocketClient::Connect(std::string url, struct OpenOptions options)
388 {
389 NETSTACK_LOGI("ClientId:%{public}d, Connect start", this->GetClientContext()->GetClientId());
390 if (!options.headers.empty()) {
391 if (options.headers.size() > MAX_HEADER_LENGTH) {
392 return WebSocketErrorCode::WEBSOCKET_ERROR_NO_HEADR_EXCEEDS;
393 }
394 for (const auto &item : options.headers) {
395 const std::string &key = item.first;
396 const std::string &value = item.second;
397 this->GetClientContext()->header[key] = value;
398 }
399 }
400 lws_context_creation_info info = {};
401 FillContextInfo(info);
402 lws_context *lwsContext = lws_create_context(&info);
403 if (lwsContext == nullptr) {
404 return WebSocketErrorCode::WEBSOCKET_CONNECTION_NO_MEMOERY;
405 }
406 this->GetClientContext()->SetContext(lwsContext);
407 int ret = CreatConnectInfo(url, lwsContext, this);
408 if (ret != WEBSOCKET_NONE_ERR) {
409 NETSTACK_LOGE("websocket CreatConnectInfo error");
410 GetClientContext()->SetContext(nullptr);
411 lws_context_destroy(lwsContext);
412 return ret;
413 }
414 std::thread serviceThread(RunService, this);
415 #if defined(MAC_PLATFORM) || defined(IOS_PLATFORM)
416 pthread_setname_np(WEBSOCKET_CLIENT_THREAD_RUN);
417 #else
418 pthread_setname_np(serviceThread.native_handle(), WEBSOCKET_CLIENT_THREAD_RUN);
419 #endif
420 serviceThread.detach();
421 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
422 }
423
Send(char * data,size_t length)424 int WebSocketClient::Send(char *data, size_t length)
425 {
426 if (data == nullptr) {
427 return WebSocketErrorCode::WEBSOCKET_SEND_DATA_NULL;
428 }
429 if (length == 0) {
430 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
431 }
432 if (length > MAX_DATA_LENGTH) {
433 return WebSocketErrorCode::WEBSOCKET_DATA_LENGTH_EXCEEDS;
434 }
435 if (this->GetClientContext() == nullptr) {
436 return WebSocketErrorCode::WEBSOCKET_ERROR_NO_CLIENTCONTEX;
437 }
438
439 lws_write_protocol protocol = (strlen(data) == length) ? LWS_WRITE_TEXT : LWS_WRITE_BINARY;
440 auto dataCopy = reinterpret_cast<char *>(malloc(length));
441 if (dataCopy == nullptr) {
442 NETSTACK_LOGE("webSocketClient malloc error");
443 return WEBSOCKET_SEND_NO_MEMOERY_ERROR;
444 } else if (memcpy_s(dataCopy, length, data, length) != EOK) {
445 free(dataCopy);
446 NETSTACK_LOGE("webSocketClient malloc copy error");
447 return WEBSOCKET_SEND_NO_MEMOERY_ERROR;
448 }
449 this->GetClientContext()->Push(dataCopy, length, protocol);
450 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
451 }
452
Close(CloseOption options)453 int WebSocketClient::Close(CloseOption options)
454 {
455 NETSTACK_LOGI("Close start");
456 if (this->GetClientContext() == nullptr) {
457 return WebSocketErrorCode::WEBSOCKET_ERROR_NO_CLIENTCONTEX;
458 }
459 if (this->GetClientContext()->openStatus == 0)
460 return WebSocketErrorCode::WEBSOCKET_ERROR_HAVE_NO_CONNECT;
461
462 if (options.reason == nullptr || options.code == 0) {
463 options.reason = "";
464 options.code = CLOSE_RESULT_FROM_CLIENT_CODE;
465 }
466 this->GetClientContext()->Close(static_cast<lws_close_status>(options.code), options.reason);
467 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
468 }
469
Registcallback(OnOpenCallback onOpen,OnMessageCallback onMessage,OnErrorCallback onError,OnCloseCallback onClose)470 int WebSocketClient::Registcallback(OnOpenCallback onOpen, OnMessageCallback onMessage, OnErrorCallback onError,
471 OnCloseCallback onClose)
472 {
473 onMessageCallback_ = onMessage;
474 onCloseCallback_ = onClose;
475 onErrorCallback_ = onError;
476 onOpenCallback_ = onOpen;
477 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
478 }
479
Destroy()480 int WebSocketClient::Destroy()
481 {
482 NETSTACK_LOGI("Destroy start");
483 if (this->GetClientContext()->GetContext() == nullptr) {
484 return WebSocketErrorCode::WEBSOCKET_ERROR_HAVE_NO_CONNECT_CONTEXT;
485 }
486 this->GetClientContext()->SetContext(nullptr);
487 lws_context_destroy(this->GetClientContext()->GetContext());
488 return WebSocketErrorCode::WEBSOCKET_NONE_ERR;
489 }
490
491 } // namespace OHOS::NetStack::WebSocketClient