• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "websocket.h"
17 
18 #include "define.h"
19 #include "log_wrapper.h"
20 #include "securec.h"
21 
22 namespace OHOS::ArkCompiler::Toolchain {
23 /**
24  *  SendMessage in WebSocket has 3 situations:
25  *    1. message's length <= 125
26  *    2. message's length >= 126 && messages's length < 65536
27  *    3. message's length >= 65536
28  */
29 
SendReply(const std::string & message) const30 void WebSocket::SendReply(const std::string& message) const
31 {
32     if (socketState_ != SocketState::CONNECTED) {
33         LOGE("SendReply failed, websocket not connected");
34         return;
35     }
36     const size_t msgLen = message.length();
37     const uint32_t headerSize = 11; // 11: the maximum expandable length
38     std::unique_ptr<char []> msgBuf = std::make_unique<char []>(msgLen + headerSize);
39     char* sendBuf = msgBuf.get();
40     uint32_t sendMsgLen;
41     sendBuf[0] = 0x81; // 0x81: the text message sent by the server should start with '0x81'.
42 
43     // Depending on the length of the messages, server will use shift operation to get the res
44     // and store them in the buffer.
45     if (msgLen <= 125) { // 125: situation 1 when message's length <= 125
46         sendBuf[1] = msgLen;
47         sendMsgLen = 2; // 2: the length of header frame is 2
48     } else if (msgLen < 65536) { // 65536: message's length
49         sendBuf[1] = 126; // 126: payloadLen according to the spec
50         sendBuf[2] = ((msgLen >> 8) & 0xff); // 8: shift right by 8 bits => res * (256^1)
51         sendBuf[3] = (msgLen & 0xff); // 3: store len's data => res * (256^0)
52         sendMsgLen = 4; // 4: the length of header frame is 4
53     } else {
54         sendBuf[1] = 127; // 127: payloadLen according to the spec
55         for (int32_t i = 2; i <= 5; i++) { // 2 ~ 5: unused bits
56             sendBuf[i] = 0;
57         }
58         sendBuf[6] = ((msgLen & 0xff000000) >> 24); // 6: shift 24 bits => res * (256^3)
59         sendBuf[7] = ((msgLen & 0x00ff0000) >> 16); // 7: shift 16 bits => res * (256^2)
60         sendBuf[8] = ((msgLen & 0x0000ff00) >> 8);  // 8: shift 8 bits => res * (256^1)
61         sendBuf[9] = (msgLen & 0x000000ff); // 9: res * (256^0)
62         sendMsgLen = 10; // 10: the length of header frame is 10
63     }
64     if (memcpy_s(sendBuf + sendMsgLen, msgLen, message.c_str(), msgLen) != EOK) {
65         LOGE("SendReply: memcpy_s failed");
66         return;
67     }
68     sendBuf[sendMsgLen + msgLen] = '\0';
69     if (!Send(client_, sendBuf, sendMsgLen + msgLen, 0)) {
70         LOGE("SendReply: send failed");
71         return;
72     }
73 }
74 
HttpProtocolDecode(const std::string & request,HttpProtocol & req)75 bool WebSocket::HttpProtocolDecode(const std::string& request, HttpProtocol& req)
76 {
77     if (request.find("GET") == std::string::npos) {
78         LOGE("Handshake failed: lack of necessary info");
79         return false;
80     }
81     std::vector<std::string> reqStr = ProtocolSplit(request, EOL);
82     for (size_t i = 0; i < reqStr.size(); i++) {
83         if (i == 0) {
84             std::vector<std::string> headers = ProtocolSplit(reqStr.at(i), " ");
85             req.version = headers.at(2); // 2: to get the version param
86         } else if (i < reqStr.size() - 1) {
87             std::vector<std::string> headers = ProtocolSplit(reqStr.at(i), ": ");
88             if (reqStr.at(i).find("Connection") != std::string::npos) {
89                 req.connection = headers.at(1); // 1: to get the connection param
90             } else if (reqStr.at(i).find("Upgrade") != std::string::npos) {
91                 req.upgrade = headers.at(1); // 1: to get the upgrade param
92             } else if (reqStr.at(i).find("Sec-WebSocket-Key") != std::string::npos) {
93                 req.secWebSocketKey = headers.at(1); // 1: to get the secWebSocketKey param
94             }
95         }
96     }
97     return true;
98 }
99 
100 /**
101   *  The wired format of this data transmission section is described in detail through ABNFRFC5234.
102   *  When receive the message, we should decode it according the spec. The structure is as follows:
103   *     0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
104   *    +-+-+-+-+-------+-+-------------+-------------------------------+
105   *    |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
106   *    |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
107   *    |N|V|V|V|       |S|             |   (if payload len==126/127)   |
108   *    | |1|2|3|       |K|             |                               |
109   *    +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
110   *    |     Extended payload length continued, if payload len == 127  |
111   *    + - - - - - - - - - - - - - - - +-------------------------------+
112   *    |                               |Masking-key, if MASK set to 1  |
113   *    +-------------------------------+-------------------------------+
114   *    | Masking-key (continued)       |          Payload Data         |
115   *    +-------------------------------- - - - - - - - - - - - - - - - +
116   *    :                     Payload Data continued ...                :
117   *    + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
118   *    |                     Payload Data continued ...                |
119   *    +---------------------------------------------------------------+
120   */
121 
HandleFrame(WebSocketFrame & wsFrame)122 bool WebSocket::HandleFrame(WebSocketFrame& wsFrame)
123 {
124     if (wsFrame.payloadLen == 126) { // 126: the payloadLen read from frame
125         char recvbuf[PAYLOAD_LEN + 1] = {0};
126         if (!Recv(client_, recvbuf, PAYLOAD_LEN, 0)) {
127             LOGE("HandleFrame: Recv payloadLen == 126 failed");
128             return false;
129         }
130 
131         uint16_t msgLen = 0;
132         if (memcpy_s(&msgLen, sizeof(recvbuf), recvbuf, sizeof(recvbuf) - 1) != EOK) {
133             LOGE("HandleFrame: memcpy_s failed");
134             return false;
135         }
136         wsFrame.payloadLen = ntohs(msgLen);
137     } else if (wsFrame.payloadLen > 126) { // 126: the payloadLen read from frame
138         char recvbuf[EXTEND_PAYLOAD_LEN + 1] = {0};
139         if (!Recv(client_, recvbuf, EXTEND_PAYLOAD_LEN, 0)) {
140             LOGE("HandleFrame: Recv payloadLen > 127 failed");
141             return false;
142         }
143         wsFrame.payloadLen = NetToHostLongLong(recvbuf, EXTEND_PAYLOAD_LEN);
144     }
145     return DecodeMessage(wsFrame);
146 }
147 
DecodeMessage(WebSocketFrame & wsFrame)148 bool WebSocket::DecodeMessage(WebSocketFrame& wsFrame)
149 {
150     if (wsFrame.payloadLen == 0 || wsFrame.payloadLen > UINT64_MAX) {
151         LOGE("ReadMsg length error, expected greater than zero and less than UINT64_MAX");
152         return false;
153     }
154     uint64_t msgLen = wsFrame.payloadLen;
155     wsFrame.payload = std::make_unique<char []>(msgLen + 1);
156     if (wsFrame.mask == 1) {
157         char buf[msgLen + 1];
158         if (!Recv(client_, wsFrame.maskingkey, SOCKET_MASK_LEN, 0)) {
159             LOGE("DecodeMessage: Recv maskingkey failed");
160             return false;
161         }
162 
163         if (!Recv(client_, buf, msgLen, 0)) {
164             LOGE("DecodeMessage: Recv message with mask failed");
165             return false;
166         }
167 
168         for (uint64_t i = 0; i < msgLen; i++) {
169             uint64_t j = i % SOCKET_MASK_LEN;
170             wsFrame.payload.get()[i] = buf[i] ^ wsFrame.maskingkey[j];
171         }
172     } else {
173         char buf[msgLen + 1];
174         if (!Recv(client_, buf, msgLen, 0)) {
175             LOGE("DecodeMessage: Recv message without mask failed");
176             return false;
177         }
178 
179         if (memcpy_s(wsFrame.payload.get(), msgLen, buf, msgLen) != EOK) {
180             LOGE("DecodeMessage: memcpy_s failed");
181             return false;
182         }
183     }
184     wsFrame.payload.get()[msgLen] = '\0';
185     return true;
186 }
187 
ProtocolUpgrade(const HttpProtocol & req)188 bool WebSocket::ProtocolUpgrade(const HttpProtocol& req)
189 {
190     std::string rawKey = req.secWebSocketKey + WEB_SOCKET_GUID;
191     unsigned const char* webSocketKey = reinterpret_cast<unsigned const char*>(std::move(rawKey).c_str());
192     unsigned char hash[SHA_DIGEST_LENGTH + 1];
193     SHA1(webSocketKey, strlen(reinterpret_cast<const char*>(webSocketKey)), hash);
194     hash[SHA_DIGEST_LENGTH] = '\0';
195     unsigned char encodedKey[ENCODED_KEY_LEN];
196     EVP_EncodeBlock(encodedKey, reinterpret_cast<const unsigned char*>(hash), SHA_DIGEST_LENGTH);
197     std::string response;
198 
199     std::ostringstream sstream;
200     sstream << "HTTP/1.1 101 Switching Protocols" << EOL;
201     sstream << "Connection: upgrade" << EOL;
202     sstream << "Upgrade: websocket" << EOL;
203     sstream << "Sec-WebSocket-Accept: " << encodedKey << EOL;
204     sstream << EOL;
205     response = sstream.str();
206     if (!Send(client_, response.c_str(), response.length(), 0)) {
207         LOGE("ProtocolUpgrade: Send failed");
208         return false;
209     }
210     return true;
211 }
212 
Decode()213 std::string WebSocket::Decode()
214 {
215     if (socketState_ != SocketState::CONNECTED) {
216         LOGE("Decode failed, websocket not connected!");
217         return "";
218     }
219     char recvbuf[SOCKET_HEADER_LEN + 1];
220     if (!Recv(client_, recvbuf, SOCKET_HEADER_LEN, 0)) {
221         LOGE("Decode failed, client websocket disconnect");
222         socketState_ = SocketState::INITED;
223 #if defined(OHOS_PLATFORM)
224         shutdown(client_, SHUT_RDWR);
225         close(client_);
226         client_ = -1;
227 #else
228         close(client_);
229         client_ = -1;
230 #endif
231         return "";
232     }
233     WebSocketFrame wsFrame;
234     int32_t index = 0;
235     wsFrame.fin = static_cast<uint8_t>(recvbuf[index] >> 7); // 7: shift right by 7 bits to get the fin
236     wsFrame.opcode = static_cast<uint8_t>(recvbuf[index] & 0xf);
237     if (wsFrame.opcode == 0x1) { // 0x1: 0x1 means a text frame
238         index++;
239         wsFrame.mask = static_cast<uint8_t>((recvbuf[index] >> 7) & 0x1); // 7: to get the mask
240         wsFrame.payloadLen = recvbuf[index] & 0x7f;
241         if (HandleFrame(wsFrame)) {
242             return wsFrame.payload.get();
243         }
244         return "";
245     } else if (wsFrame.opcode == 0x9) { // 0x9: 0x9 means a ping frame
246         // send pong frame
247         char pongFrame[SOCKET_HEADER_LEN] = {0};
248         pongFrame[0] = 0x8a; // 0x8a: 0x8a means a pong frame
249         pongFrame[1] = 0x0;
250         if (!Send(client_, pongFrame, SOCKET_HEADER_LEN, 0)) {
251             LOGE("Decode: Send pong frame failed");
252             return "";
253         }
254     }
255     return "";
256 }
257 
HttpHandShake()258 bool WebSocket::HttpHandShake()
259 {
260     char msgBuf[SOCKET_HANDSHAKE_LEN] = {0};
261     ssize_t msgLen = recv(client_, msgBuf, SOCKET_HANDSHAKE_LEN, 0);
262     if (msgLen <= 0) {
263         LOGE("ReadMsg failed, msgLen = %{public}ld, errno = %{public}d", static_cast<long>(msgLen), errno);
264         return false;
265     } else {
266         msgBuf[msgLen - 1] = '\0';
267         HttpProtocol req;
268         if (!HttpProtocolDecode(msgBuf, req)) {
269             LOGE("HttpHandShake: Upgrade failed");
270             return false;
271         } else if (req.connection.find("Upgrade") != std::string::npos &&
272             req.upgrade.find("websocket") != std::string::npos && req.version.compare("HTTP/1.1") == 0) {
273             ProtocolUpgrade(req);
274         }
275     }
276     return true;
277 }
278 
279 #if !defined(OHOS_PLATFORM)
InitTcpWebSocket(int port,uint32_t timeoutLimit)280 bool WebSocket::InitTcpWebSocket(int port, uint32_t timeoutLimit)
281 {
282     if (port < 0) {
283         LOGE("InitTcpWebSocket invalid port");
284         return false;
285     }
286 
287     if (socketState_ != SocketState::UNINITED) {
288         LOGI("InitTcpWebSocket websocket has inited");
289         return true;
290     }
291 #if defined(WINDOWS_PLATFORM)
292     WORD sockVersion = MAKEWORD(2, 2); // 2: version 2.2
293     WSADATA wsaData;
294     if (WSAStartup(sockVersion, &wsaData) != 0) {
295         LOGE("InitTcpWebSocket WSA init failed");
296         return false;
297     }
298 #endif
299     fd_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
300     if (fd_ < SOCKET_SUCCESS) {
301         LOGE("InitTcpWebSocket socket init failed, errno = %{public}d", errno);
302         return false;
303     }
304     // allow specified port can be used at once and not wait TIME_WAIT status ending
305     int sockOptVal = 1;
306     if ((setsockopt(fd_, SOL_SOCKET, SO_REUSEADDR,
307         reinterpret_cast<char *>(&sockOptVal), sizeof(sockOptVal))) != SOCKET_SUCCESS) {
308         LOGE("InitTcpWebSocket setsockopt SO_REUSEADDR failed, errno = %{public}d", errno);
309         close(fd_);
310         fd_ = -1;
311         return false;
312     }
313 
314     // set send and recv timeout
315     if (!SetWebSocketTimeOut(fd_, timeoutLimit)) {
316         LOGE("InitTcpWebSocket SetWebSocketTimeOut failed");
317         close(fd_);
318         fd_ = -1;
319         return false;
320     }
321 
322     sockaddr_in addr_sin = {0};
323     addr_sin.sin_family = AF_INET;
324     addr_sin.sin_port = htons(port);
325     addr_sin.sin_addr.s_addr = INADDR_ANY;
326     if (bind(fd_, reinterpret_cast<struct sockaddr*>(&addr_sin), sizeof(addr_sin)) < SOCKET_SUCCESS) {
327         LOGE("InitTcpWebSocket bind failed, errno = %{public}d", errno);
328         close(fd_);
329         fd_ = -1;
330         return false;
331     }
332     if (listen(fd_, 1) < SOCKET_SUCCESS) {
333         LOGE("InitTcpWebSocket listen failed, errno = %{public}d", errno);
334         close(fd_);
335         fd_ = -1;
336         return false;
337     }
338     socketState_ = SocketState::INITED;
339     return true;
340 }
341 
ConnectTcpWebSocket()342 bool WebSocket::ConnectTcpWebSocket()
343 {
344     if (socketState_ == SocketState::UNINITED) {
345         LOGE("ConnectTcpWebSocket failed, websocket not inited");
346         return false;
347     }
348     if (socketState_ == SocketState::CONNECTED) {
349         LOGI("ConnectTcpWebSocket websocket has connected");
350         return true;
351     }
352 
353     if ((client_ = accept(fd_, nullptr, nullptr)) < SOCKET_SUCCESS) {
354         LOGI("ConnectTcpWebSocket accept has exited");
355         socketState_ = SocketState::UNINITED;
356         close(fd_);
357         fd_ = -1;
358         return false;
359     }
360 
361     if (!HttpHandShake()) {
362         LOGE("ConnectTcpWebSocket HttpHandShake failed");
363         socketState_ = SocketState::UNINITED;
364         close(client_);
365         client_ = -1;
366         close(fd_);
367         fd_ = -1;
368         return false;
369     }
370     socketState_ = SocketState::CONNECTED;
371     return true;
372 }
373 #else
InitUnixWebSocket(const std::string & sockName,uint32_t timeoutLimit)374 bool WebSocket::InitUnixWebSocket(const std::string& sockName, uint32_t timeoutLimit)
375 {
376     if (socketState_ != SocketState::UNINITED) {
377         LOGI("InitUnixWebSocket websocket has inited");
378         return true;
379     }
380     fd_ = socket(AF_UNIX, SOCK_STREAM, 0); // 0: defautlt protocol
381     if (fd_ < SOCKET_SUCCESS) {
382         LOGE("InitUnixWebSocket socket init failed, errno = %{public}d", errno);
383         return false;
384     }
385     // set send and recv timeout
386     if (!SetWebSocketTimeOut(fd_, timeoutLimit)) {
387         LOGE("InitUnixWebSocket SetWebSocketTimeOut failed");
388         close(fd_);
389         fd_ = -1;
390         return false;
391     }
392 
393     struct sockaddr_un un;
394     if (memset_s(&un, sizeof(un), 0, sizeof(un)) != EOK) {
395         LOGE("InitUnixWebSocket memset_s failed");
396         close(fd_);
397         fd_ = -1;
398         return false;
399     }
400     un.sun_family = AF_UNIX;
401     if (strcpy_s(un.sun_path + 1, sizeof(un.sun_path) - 1, sockName.c_str()) != EOK) {
402         LOGE("InitUnixWebSocket strcpy_s failed");
403         close(fd_);
404         fd_ = -1;
405         return false;
406     }
407     un.sun_path[0] = '\0';
408     uint32_t len = offsetof(struct sockaddr_un, sun_path) + strlen(sockName.c_str()) + 1;
409     if (bind(fd_, reinterpret_cast<struct sockaddr*>(&un), static_cast<int32_t>(len)) < SOCKET_SUCCESS) {
410         LOGE("InitUnixWebSocket bind failed, errno = %{public}d", errno);
411         close(fd_);
412         fd_ = -1;
413         return false;
414     }
415     if (listen(fd_, 1) < SOCKET_SUCCESS) { // 1: connection num
416         LOGE("InitUnixWebSocket listen failed, errno = %{public}d", errno);
417         close(fd_);
418         fd_ = -1;
419         return false;
420     }
421     socketState_ = SocketState::INITED;
422     return true;
423 }
424 
ConnectUnixWebSocket()425 bool WebSocket::ConnectUnixWebSocket()
426 {
427     if (socketState_ == SocketState::UNINITED) {
428         LOGE("ConnectUnixWebSocket failed, websocket not inited");
429         return false;
430     }
431     if (socketState_ == SocketState::CONNECTED) {
432         LOGI("ConnectUnixWebSocket websocket has connected");
433         return true;
434     }
435 
436     if ((client_ = accept(fd_, nullptr, nullptr)) < SOCKET_SUCCESS) {
437         LOGI("ConnectUnixWebSocket accept has exited");
438         socketState_ = SocketState::UNINITED;
439         close(fd_);
440         fd_ = -1;
441         return false;
442     }
443     if (!HttpHandShake()) {
444         LOGE("ConnectUnixWebSocket HttpHandShake failed");
445         socketState_ = SocketState::UNINITED;
446         shutdown(client_, SHUT_RDWR);
447         close(client_);
448         client_ = -1;
449         shutdown(fd_, SHUT_RDWR);
450         close(fd_);
451         fd_ = -1;
452         return false;
453     }
454     socketState_ = SocketState::CONNECTED;
455     return true;
456 }
457 #endif
458 
IsConnected()459 bool WebSocket::IsConnected()
460 {
461     return socketState_ == SocketState::CONNECTED;
462 }
463 
Close()464 void WebSocket::Close()
465 {
466     if (socketState_ == SocketState::UNINITED) {
467         return;
468     }
469     if (socketState_ == SocketState::CONNECTED) {
470 #if defined(OHOS_PLATFORM)
471         shutdown(client_, SHUT_RDWR);
472 #endif
473         close(client_);
474         client_ = -1;
475     }
476     socketState_ = SocketState::UNINITED;
477     usleep(10000); // 10000: time for websocket to enter the accept
478 #if defined(OHOS_PLATFORM)
479     shutdown(fd_, SHUT_RDWR);
480 #endif
481     close(fd_);
482     fd_ = -1;
483 }
484 
NetToHostLongLong(char * buf,uint32_t len)485 uint64_t WebSocket::NetToHostLongLong(char* buf, uint32_t len)
486 {
487     uint64_t result = 0;
488     for (uint32_t i = 0; i < len; i++) {
489         result |= static_cast<unsigned char>(buf[i]);
490         if ((i + 1) < len) {
491             result <<= 8; // 8: result need shift left 8 bits in order to big endian convert to int
492         }
493     }
494     return result;
495 }
496 
Recv(int32_t client,char * buf,size_t totalLen,int32_t flags) const497 bool WebSocket::Recv(int32_t client, char* buf, size_t totalLen, int32_t flags) const
498 {
499     size_t recvLen = 0;
500     while (recvLen < totalLen) {
501         ssize_t len = recv(client, buf + recvLen, totalLen - recvLen, flags);
502         if (len <= 0) {
503             LOGE("Recv payload in while failed, websocket disconnect, len = %{public}ld, errno = %{public}d",
504                  static_cast<long>(len), errno);
505             return false;
506         }
507         recvLen += static_cast<size_t>(len);
508     }
509     buf[totalLen] = '\0';
510     return true;
511 }
512 
Send(int32_t client,const char * buf,size_t totalLen,int32_t flags) const513 bool WebSocket::Send(int32_t client, const char* buf, size_t totalLen, int32_t flags) const
514 {
515     size_t sendLen = 0;
516     while (sendLen < totalLen) {
517         ssize_t len = send(client, buf + sendLen, totalLen - sendLen, flags);
518         if (len <= 0) {
519             LOGE("Send Message in while failed, websocket disconnect, len = %{public}ld, errno = %{public}d",
520                  static_cast<long>(len), errno);
521             return false;
522         }
523         sendLen += static_cast<size_t>(len);
524     }
525     return true;
526 }
527 
528 #if !defined(OHOS_PLATFORM)
SetWebSocketTimeOut(int32_t fd,uint32_t timeoutLimit)529 bool WebSocket::SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit)
530 {
531     if (timeoutLimit > 0) {
532         struct timeval timeout = {timeoutLimit, 0};
533         if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
534             reinterpret_cast<char *>(&timeout), sizeof(timeout)) != SOCKET_SUCCESS) {
535             LOGE("SetWebSocketTimeOut setsockopt SO_SNDTIMEO failed, errno = %{public}d", errno);
536             return false;
537         }
538         if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
539             reinterpret_cast<char *>(&timeout), sizeof(timeout)) != SOCKET_SUCCESS) {
540             LOGE("SetWebSocketTimeOut setsockopt SO_RCVTIMEO failed, errno = %{public}d", errno);
541             return false;
542         }
543     }
544     return true;
545 }
546 #else
SetWebSocketTimeOut(int32_t fd,uint32_t timeoutLimit)547 bool WebSocket::SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit)
548 {
549     if (timeoutLimit > 0) {
550         struct timeval timeout = {timeoutLimit, 0};
551         if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != SOCKET_SUCCESS) {
552             LOGE("SetWebSocketTimeOut setsockopt SO_SNDTIMEO failed, errno = %{public}d", errno);
553             return false;
554         }
555         if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != SOCKET_SUCCESS) {
556             LOGE("SetWebSocketTimeOut setsockopt SO_RCVTIMEO failed, errno = %{public}d", errno);
557             return false;
558         }
559     }
560     return true;
561 }
562 #endif
563 } // namespace OHOS::ArkCompiler::Toolchain
564