1e509ee18Sopenharmony_ci/*
2e509ee18Sopenharmony_ci * Copyright (c) 2022 Huawei Device Co., Ltd.
3e509ee18Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e509ee18Sopenharmony_ci * you may not use this file except in compliance with the License.
5e509ee18Sopenharmony_ci * You may obtain a copy of the License at
6e509ee18Sopenharmony_ci *
7e509ee18Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e509ee18Sopenharmony_ci *
9e509ee18Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e509ee18Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e509ee18Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e509ee18Sopenharmony_ci * See the License for the specific language governing permissions and
13e509ee18Sopenharmony_ci * limitations under the License.
14e509ee18Sopenharmony_ci */
15e509ee18Sopenharmony_ci
16e509ee18Sopenharmony_ci#include "common/log_wrapper.h"
17e509ee18Sopenharmony_ci#include "define.h"
18e509ee18Sopenharmony_ci#include "frame_builder.h"
19e509ee18Sopenharmony_ci#include "network.h"
20e509ee18Sopenharmony_ci#include "websocket_base.h"
21e509ee18Sopenharmony_ci
22e509ee18Sopenharmony_ci#include <mutex>
23e509ee18Sopenharmony_ci
24e509ee18Sopenharmony_cinamespace OHOS::ArkCompiler::Toolchain {
25e509ee18Sopenharmony_cistatic std::string ToString(CloseStatusCode status)
26e509ee18Sopenharmony_ci{
27e509ee18Sopenharmony_ci    if (status == CloseStatusCode::NO_STATUS_CODE) {
28e509ee18Sopenharmony_ci        return "";
29e509ee18Sopenharmony_ci    }
30e509ee18Sopenharmony_ci    std::string result;
31e509ee18Sopenharmony_ci    PushNumberPerByte(result, EnumToNumber(status));
32e509ee18Sopenharmony_ci    return result;
33e509ee18Sopenharmony_ci}
34e509ee18Sopenharmony_ci
35e509ee18Sopenharmony_ciWebSocketBase::~WebSocketBase() noexcept
36e509ee18Sopenharmony_ci{
37e509ee18Sopenharmony_ci    if (connectionFd_ != -1) {
38e509ee18Sopenharmony_ci        LOGW("WebSocket connection is closed while destructing the object");
39e509ee18Sopenharmony_ci        close(connectionFd_);
40e509ee18Sopenharmony_ci        // Reset directly in order to prevent static analyzer warnings.
41e509ee18Sopenharmony_ci        connectionFd_ = -1;
42e509ee18Sopenharmony_ci    }
43e509ee18Sopenharmony_ci}
44e509ee18Sopenharmony_ci
45e509ee18Sopenharmony_ci// if the data is too large, it will be split into multiple frames, the first frame will be marked as 0x0
46e509ee18Sopenharmony_ci// and the last frame will be marked as 0x1.
47e509ee18Sopenharmony_ci// we just add the 'isLast' parameter to indicate whether it is the last frame.
48e509ee18Sopenharmony_cibool WebSocketBase::SendReply(const std::string& message, FrameType frameType, bool isLast) const
49e509ee18Sopenharmony_ci{
50e509ee18Sopenharmony_ci    if (connectionState_.load() != ConnectionState::OPEN) {
51e509ee18Sopenharmony_ci        LOGE("SendReply failed, websocket not connected");
52e509ee18Sopenharmony_ci        return false;
53e509ee18Sopenharmony_ci    }
54e509ee18Sopenharmony_ci
55e509ee18Sopenharmony_ci    const auto frame = CreateFrame(isLast, frameType, message);
56e509ee18Sopenharmony_ci    if (!SendUnderLock(frame)) {
57e509ee18Sopenharmony_ci        LOGE("SendReply: send failed");
58e509ee18Sopenharmony_ci        return false;
59e509ee18Sopenharmony_ci    }
60e509ee18Sopenharmony_ci    return true;
61e509ee18Sopenharmony_ci}
62e509ee18Sopenharmony_ci
63e509ee18Sopenharmony_ci/**
64e509ee18Sopenharmony_ci  *  The wired format of this data transmission section is described in detail through ABNFRFC5234.
65e509ee18Sopenharmony_ci  *  When receive the message, we should decode it according the spec. The structure is as follows:
66e509ee18Sopenharmony_ci  *     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
67e509ee18Sopenharmony_ci  *    +-+-+-+-+-------+-+-------------+-------------------------------+
68e509ee18Sopenharmony_ci  *    |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
69e509ee18Sopenharmony_ci  *    |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
70e509ee18Sopenharmony_ci  *    |N|V|V|V|       |S|             |   (if payload len==126/127)   |
71e509ee18Sopenharmony_ci  *    | |1|2|3|       |K|             |                               |
72e509ee18Sopenharmony_ci  *    +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
73e509ee18Sopenharmony_ci  *    |     Extended payload length continued, if payload len == 127  |
74e509ee18Sopenharmony_ci  *    + - - - - - - - - - - - - - - - +-------------------------------+
75e509ee18Sopenharmony_ci  *    |                               |Masking-key, if MASK set to 1  |
76e509ee18Sopenharmony_ci  *    +-------------------------------+-------------------------------+
77e509ee18Sopenharmony_ci  *    | Masking-key (continued)       |          Payload Data         |
78e509ee18Sopenharmony_ci  *    +-------------------------------- - - - - - - - - - - - - - - - +
79e509ee18Sopenharmony_ci  *    :                     Payload Data continued ...                :
80e509ee18Sopenharmony_ci  *    + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
81e509ee18Sopenharmony_ci  *    |                     Payload Data continued ...                |
82e509ee18Sopenharmony_ci  *    +---------------------------------------------------------------+
83e509ee18Sopenharmony_ci  */
84e509ee18Sopenharmony_ci
85e509ee18Sopenharmony_cibool WebSocketBase::ReadPayload(WebSocketFrame& wsFrame) const
86e509ee18Sopenharmony_ci{
87e509ee18Sopenharmony_ci    if (wsFrame.payloadLen == WebSocketFrame::TWO_BYTES_LENTH_ENC) {
88e509ee18Sopenharmony_ci        uint8_t recvbuf[WebSocketFrame::TWO_BYTES_LENTH] = {0};
89e509ee18Sopenharmony_ci        if (!RecvUnderLock(recvbuf, WebSocketFrame::TWO_BYTES_LENTH)) {
90e509ee18Sopenharmony_ci            LOGE("ReadPayload: Recv payloadLen == 126 failed");
91e509ee18Sopenharmony_ci            return false;
92e509ee18Sopenharmony_ci        }
93e509ee18Sopenharmony_ci        wsFrame.payloadLen = NetToHostLongLong(recvbuf, WebSocketFrame::TWO_BYTES_LENTH);
94e509ee18Sopenharmony_ci    } else if (wsFrame.payloadLen == WebSocketFrame::EIGHT_BYTES_LENTH_ENC) {
95e509ee18Sopenharmony_ci        uint8_t recvbuf[WebSocketFrame::EIGHT_BYTES_LENTH] = {0};
96e509ee18Sopenharmony_ci        if (!RecvUnderLock(recvbuf, WebSocketFrame::EIGHT_BYTES_LENTH)) {
97e509ee18Sopenharmony_ci            LOGE("ReadPayload: Recv payloadLen == 127 failed");
98e509ee18Sopenharmony_ci            return false;
99e509ee18Sopenharmony_ci        }
100e509ee18Sopenharmony_ci        wsFrame.payloadLen = NetToHostLongLong(recvbuf, WebSocketFrame::EIGHT_BYTES_LENTH);
101e509ee18Sopenharmony_ci    }
102e509ee18Sopenharmony_ci    return DecodeMessage(wsFrame);
103e509ee18Sopenharmony_ci}
104e509ee18Sopenharmony_ci
105e509ee18Sopenharmony_cibool WebSocketBase::HandleDataFrame(WebSocketFrame& wsFrame) const
106e509ee18Sopenharmony_ci{
107e509ee18Sopenharmony_ci    if (wsFrame.opcode == EnumToNumber(FrameType::TEXT)) {
108e509ee18Sopenharmony_ci        return ReadPayload(wsFrame);
109e509ee18Sopenharmony_ci    } else {
110e509ee18Sopenharmony_ci        LOGW("Received unsupported data frame, opcode = %{public}d", wsFrame.opcode);
111e509ee18Sopenharmony_ci    }
112e509ee18Sopenharmony_ci    return true;
113e509ee18Sopenharmony_ci}
114e509ee18Sopenharmony_ci
115e509ee18Sopenharmony_cibool WebSocketBase::HandleControlFrame(WebSocketFrame& wsFrame)
116e509ee18Sopenharmony_ci{
117e509ee18Sopenharmony_ci    if (wsFrame.opcode == EnumToNumber(FrameType::PING)) {
118e509ee18Sopenharmony_ci        // A Pong frame sent in response to a Ping frame must have identical
119e509ee18Sopenharmony_ci        // "Application data" as found in the message body of the Ping frame
120e509ee18Sopenharmony_ci        // being replied to.
121e509ee18Sopenharmony_ci        // https://www.rfc-editor.org/rfc/rfc6455#section-5.5.3
122e509ee18Sopenharmony_ci        if (!ReadPayload(wsFrame)) {
123e509ee18Sopenharmony_ci            LOGE("Failed to read ping frame payload");
124e509ee18Sopenharmony_ci            return false;
125e509ee18Sopenharmony_ci        }
126e509ee18Sopenharmony_ci        SendPongFrame(wsFrame.payload);
127e509ee18Sopenharmony_ci    } else if (wsFrame.opcode == EnumToNumber(FrameType::CLOSE)) {
128e509ee18Sopenharmony_ci        // might read payload to response by echoing the status code
129e509ee18Sopenharmony_ci        CloseConnection(CloseStatusCode::NO_STATUS_CODE);
130e509ee18Sopenharmony_ci    }
131e509ee18Sopenharmony_ci    return true;
132e509ee18Sopenharmony_ci}
133e509ee18Sopenharmony_ci
134e509ee18Sopenharmony_cistd::string WebSocketBase::Decode()
135e509ee18Sopenharmony_ci{
136e509ee18Sopenharmony_ci    if (auto state = connectionState_.load(); state != ConnectionState::OPEN) {
137e509ee18Sopenharmony_ci        LOGE("Decode failed: websocket not connected, state = %{public}d", EnumToNumber(state));
138e509ee18Sopenharmony_ci        return "";
139e509ee18Sopenharmony_ci    }
140e509ee18Sopenharmony_ci
141e509ee18Sopenharmony_ci    uint8_t recvbuf[WebSocketFrame::HEADER_LEN] = {0};
142e509ee18Sopenharmony_ci    if (!RecvUnderLock(recvbuf, WebSocketFrame::HEADER_LEN)) {
143e509ee18Sopenharmony_ci        LOGE("Decode failed, client websocket disconnect");
144e509ee18Sopenharmony_ci        CloseConnection(CloseStatusCode::UNEXPECTED_ERROR);
145e509ee18Sopenharmony_ci        return std::string(DECODE_DISCONNECT_MSG);
146e509ee18Sopenharmony_ci    }
147e509ee18Sopenharmony_ci    WebSocketFrame wsFrame(recvbuf);
148e509ee18Sopenharmony_ci    if (!ValidateIncomingFrame(wsFrame)) {
149e509ee18Sopenharmony_ci        LOGE("Received websocket frame is invalid - header is %02x%02x", recvbuf[0], recvbuf[1]);
150e509ee18Sopenharmony_ci        CloseConnection(CloseStatusCode::PROTOCOL_ERROR);
151e509ee18Sopenharmony_ci        return std::string(DECODE_DISCONNECT_MSG);
152e509ee18Sopenharmony_ci    }
153e509ee18Sopenharmony_ci
154e509ee18Sopenharmony_ci    if (IsControlFrame(wsFrame.opcode)) {
155e509ee18Sopenharmony_ci        if (HandleControlFrame(wsFrame)) {
156e509ee18Sopenharmony_ci            return wsFrame.payload;
157e509ee18Sopenharmony_ci        }
158e509ee18Sopenharmony_ci    } else if (HandleDataFrame(wsFrame)) {
159e509ee18Sopenharmony_ci        return wsFrame.payload;
160e509ee18Sopenharmony_ci    }
161e509ee18Sopenharmony_ci    // Unexpected data, must close the connection.
162e509ee18Sopenharmony_ci    CloseConnection(CloseStatusCode::PROTOCOL_ERROR);
163e509ee18Sopenharmony_ci    return std::string(DECODE_DISCONNECT_MSG);
164e509ee18Sopenharmony_ci}
165e509ee18Sopenharmony_ci
166e509ee18Sopenharmony_cibool WebSocketBase::IsConnected() const
167e509ee18Sopenharmony_ci{
168e509ee18Sopenharmony_ci    return connectionState_.load() == ConnectionState::OPEN;
169e509ee18Sopenharmony_ci}
170e509ee18Sopenharmony_ci
171e509ee18Sopenharmony_civoid WebSocketBase::SetCloseConnectionCallback(CloseConnectionCallback cb)
172e509ee18Sopenharmony_ci{
173e509ee18Sopenharmony_ci    closeCb_ = std::move(cb);
174e509ee18Sopenharmony_ci}
175e509ee18Sopenharmony_ci
176e509ee18Sopenharmony_civoid WebSocketBase::SetFailConnectionCallback(FailConnectionCallback cb)
177e509ee18Sopenharmony_ci{
178e509ee18Sopenharmony_ci    failCb_ = std::move(cb);
179e509ee18Sopenharmony_ci}
180e509ee18Sopenharmony_ci
181e509ee18Sopenharmony_civoid WebSocketBase::OnConnectionClose(ConnectionCloseReason status)
182e509ee18Sopenharmony_ci{
183e509ee18Sopenharmony_ci    if (status == ConnectionCloseReason::FAIL) {
184e509ee18Sopenharmony_ci        if (failCb_) {
185e509ee18Sopenharmony_ci            failCb_();
186e509ee18Sopenharmony_ci        }
187e509ee18Sopenharmony_ci    } else if (status == ConnectionCloseReason::CLOSE) {
188e509ee18Sopenharmony_ci        if (closeCb_) {
189e509ee18Sopenharmony_ci            closeCb_();
190e509ee18Sopenharmony_ci        }
191e509ee18Sopenharmony_ci    }
192e509ee18Sopenharmony_ci}
193e509ee18Sopenharmony_ci
194e509ee18Sopenharmony_civoid WebSocketBase::CloseConnectionSocket(ConnectionCloseReason status)
195e509ee18Sopenharmony_ci{
196e509ee18Sopenharmony_ci    OnConnectionClose(status);
197e509ee18Sopenharmony_ci
198e509ee18Sopenharmony_ci    {
199e509ee18Sopenharmony_ci        // Shared lock due to other thread possibly hanging on `recv` with acquired shared lock.
200e509ee18Sopenharmony_ci        std::shared_lock lock(connectionMutex_);
201e509ee18Sopenharmony_ci        int err = ShutdownSocket(connectionFd_);
202e509ee18Sopenharmony_ci        if (err != 0) {
203e509ee18Sopenharmony_ci            LOGW("Failed to shutdown client socket, errno = %{public}d", errno);
204e509ee18Sopenharmony_ci        }
205e509ee18Sopenharmony_ci    }
206e509ee18Sopenharmony_ci    {
207e509ee18Sopenharmony_ci        // Unique lock due to close and write into `connectionFd_`.
208e509ee18Sopenharmony_ci        // Note that `close` must be also done in critical section,
209e509ee18Sopenharmony_ci        // otherwise the other thread can continue using the outdated and possibly reassigned file descriptor.
210e509ee18Sopenharmony_ci        std::unique_lock lock(connectionMutex_);
211e509ee18Sopenharmony_ci        close(connectionFd_);
212e509ee18Sopenharmony_ci        // Reset directly in order to prevent static analyzer warnings.
213e509ee18Sopenharmony_ci        connectionFd_ = -1;
214e509ee18Sopenharmony_ci    }
215e509ee18Sopenharmony_ci
216e509ee18Sopenharmony_ci    auto expected = ConnectionState::CLOSING;
217e509ee18Sopenharmony_ci    if (!connectionState_.compare_exchange_strong(expected, ConnectionState::CLOSED)) {
218e509ee18Sopenharmony_ci        LOGE("In connection transition CLOSING->CLOSED got initial state = %{public}d", EnumToNumber(expected));
219e509ee18Sopenharmony_ci    }
220e509ee18Sopenharmony_ci}
221e509ee18Sopenharmony_ci
222e509ee18Sopenharmony_civoid WebSocketBase::SendPongFrame(std::string payload) const
223e509ee18Sopenharmony_ci{
224e509ee18Sopenharmony_ci    const auto frame = CreateFrame(true, FrameType::PONG, std::move(payload));
225e509ee18Sopenharmony_ci    if (!SendUnderLock(frame)) {
226e509ee18Sopenharmony_ci        LOGE("Decode: Send pong frame failed");
227e509ee18Sopenharmony_ci    }
228e509ee18Sopenharmony_ci}
229e509ee18Sopenharmony_ci
230e509ee18Sopenharmony_civoid WebSocketBase::SendCloseFrame(CloseStatusCode status) const
231e509ee18Sopenharmony_ci{
232e509ee18Sopenharmony_ci    const auto frame = CreateFrame(true, FrameType::CLOSE, ToString(status));
233e509ee18Sopenharmony_ci    if (!SendUnderLock(frame)) {
234e509ee18Sopenharmony_ci        LOGE("SendCloseFrame: Send close frame failed");
235e509ee18Sopenharmony_ci    }
236e509ee18Sopenharmony_ci}
237e509ee18Sopenharmony_ci
238e509ee18Sopenharmony_cibool WebSocketBase::CloseConnection(CloseStatusCode status)
239e509ee18Sopenharmony_ci{
240e509ee18Sopenharmony_ci    auto expected = ConnectionState::OPEN;
241e509ee18Sopenharmony_ci    if (!connectionState_.compare_exchange_strong(expected, ConnectionState::CLOSING)) {
242e509ee18Sopenharmony_ci        // Concurrent connection close detected, do nothing.
243e509ee18Sopenharmony_ci        return false;
244e509ee18Sopenharmony_ci    }
245e509ee18Sopenharmony_ci
246e509ee18Sopenharmony_ci    LOGI("Close connection, status = %{public}d", static_cast<int>(status));
247e509ee18Sopenharmony_ci    SendCloseFrame(status);
248e509ee18Sopenharmony_ci    // can close connection right after sending back close frame.
249e509ee18Sopenharmony_ci    CloseConnectionSocket(ConnectionCloseReason::CLOSE);
250e509ee18Sopenharmony_ci    return true;
251e509ee18Sopenharmony_ci}
252e509ee18Sopenharmony_ci
253e509ee18Sopenharmony_ciint WebSocketBase::GetConnectionSocket() const
254e509ee18Sopenharmony_ci{
255e509ee18Sopenharmony_ci    return connectionFd_;
256e509ee18Sopenharmony_ci}
257e509ee18Sopenharmony_ci
258e509ee18Sopenharmony_civoid WebSocketBase::SetConnectionSocket(int socketFd)
259e509ee18Sopenharmony_ci{
260e509ee18Sopenharmony_ci    connectionFd_ = socketFd;
261e509ee18Sopenharmony_ci}
262e509ee18Sopenharmony_ci
263e509ee18Sopenharmony_cistd::shared_mutex &WebSocketBase::GetConnectionMutex()
264e509ee18Sopenharmony_ci{
265e509ee18Sopenharmony_ci    return connectionMutex_;
266e509ee18Sopenharmony_ci}
267e509ee18Sopenharmony_ci
268e509ee18Sopenharmony_ciWebSocketBase::ConnectionState WebSocketBase::GetConnectionState() const
269e509ee18Sopenharmony_ci{
270e509ee18Sopenharmony_ci    return connectionState_.load();
271e509ee18Sopenharmony_ci}
272e509ee18Sopenharmony_ci
273e509ee18Sopenharmony_ciWebSocketBase::ConnectionState WebSocketBase::SetConnectionState(ConnectionState newState)
274e509ee18Sopenharmony_ci{
275e509ee18Sopenharmony_ci    return connectionState_.exchange(newState);
276e509ee18Sopenharmony_ci}
277e509ee18Sopenharmony_ci
278e509ee18Sopenharmony_cibool WebSocketBase::CompareExchangeConnectionState(ConnectionState& expected, ConnectionState newState)
279e509ee18Sopenharmony_ci{
280e509ee18Sopenharmony_ci    return connectionState_.compare_exchange_strong(expected, newState);
281e509ee18Sopenharmony_ci}
282e509ee18Sopenharmony_ci
283e509ee18Sopenharmony_cibool WebSocketBase::SendUnderLock(const std::string& message) const
284e509ee18Sopenharmony_ci{
285e509ee18Sopenharmony_ci    std::shared_lock lock(connectionMutex_);
286e509ee18Sopenharmony_ci    return Send(connectionFd_, message, 0);
287e509ee18Sopenharmony_ci}
288e509ee18Sopenharmony_ci
289e509ee18Sopenharmony_cibool WebSocketBase::SendUnderLock(const char* buf, size_t totalLen) const
290e509ee18Sopenharmony_ci{
291e509ee18Sopenharmony_ci    std::shared_lock lock(connectionMutex_);
292e509ee18Sopenharmony_ci    return Send(connectionFd_, buf, totalLen, 0);
293e509ee18Sopenharmony_ci}
294e509ee18Sopenharmony_ci
295e509ee18Sopenharmony_cibool WebSocketBase::RecvUnderLock(std::string& message) const
296e509ee18Sopenharmony_ci{
297e509ee18Sopenharmony_ci    std::shared_lock lock(connectionMutex_);
298e509ee18Sopenharmony_ci    return Recv(connectionFd_, message, 0);
299e509ee18Sopenharmony_ci}
300e509ee18Sopenharmony_ci
301e509ee18Sopenharmony_cibool WebSocketBase::RecvUnderLock(uint8_t* buf, size_t totalLen) const
302e509ee18Sopenharmony_ci{
303e509ee18Sopenharmony_ci    std::shared_lock lock(connectionMutex_);
304e509ee18Sopenharmony_ci    return Recv(connectionFd_, buf, totalLen, 0);
305e509ee18Sopenharmony_ci}
306e509ee18Sopenharmony_ci
307e509ee18Sopenharmony_ci/* static */
308e509ee18Sopenharmony_cibool WebSocketBase::IsDecodeDisconnectMsg(const std::string& message)
309e509ee18Sopenharmony_ci{
310e509ee18Sopenharmony_ci    return message == DECODE_DISCONNECT_MSG;
311e509ee18Sopenharmony_ci}
312e509ee18Sopenharmony_ci
313e509ee18Sopenharmony_ci#if !defined(OHOS_PLATFORM)
314e509ee18Sopenharmony_ci/* static */
315e509ee18Sopenharmony_cibool WebSocketBase::SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit)
316e509ee18Sopenharmony_ci{
317e509ee18Sopenharmony_ci    if (timeoutLimit > 0) {
318e509ee18Sopenharmony_ci        struct timeval timeout = {static_cast<time_t>(timeoutLimit), 0};
319e509ee18Sopenharmony_ci        if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO,
320e509ee18Sopenharmony_ci            reinterpret_cast<char *>(&timeout), sizeof(timeout)) != SOCKET_SUCCESS) {
321e509ee18Sopenharmony_ci            LOGE("SetWebSocketTimeOut setsockopt SO_SNDTIMEO failed, errno = %{public}d", errno);
322e509ee18Sopenharmony_ci            return false;
323e509ee18Sopenharmony_ci        }
324e509ee18Sopenharmony_ci        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,
325e509ee18Sopenharmony_ci            reinterpret_cast<char *>(&timeout), sizeof(timeout)) != SOCKET_SUCCESS) {
326e509ee18Sopenharmony_ci            LOGE("SetWebSocketTimeOut setsockopt SO_RCVTIMEO failed, errno = %{public}d", errno);
327e509ee18Sopenharmony_ci            return false;
328e509ee18Sopenharmony_ci        }
329e509ee18Sopenharmony_ci    }
330e509ee18Sopenharmony_ci    return true;
331e509ee18Sopenharmony_ci}
332e509ee18Sopenharmony_ci#else
333e509ee18Sopenharmony_ci/* static */
334e509ee18Sopenharmony_cibool WebSocketBase::SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit)
335e509ee18Sopenharmony_ci{
336e509ee18Sopenharmony_ci    if (timeoutLimit > 0) {
337e509ee18Sopenharmony_ci        struct timeval timeout = {static_cast<time_t>(timeoutLimit), 0};
338e509ee18Sopenharmony_ci        if (setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) != SOCKET_SUCCESS) {
339e509ee18Sopenharmony_ci            LOGE("SetWebSocketTimeOut setsockopt SO_SNDTIMEO failed, errno = %{public}d", errno);
340e509ee18Sopenharmony_ci            return false;
341e509ee18Sopenharmony_ci        }
342e509ee18Sopenharmony_ci        if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) != SOCKET_SUCCESS) {
343e509ee18Sopenharmony_ci            LOGE("SetWebSocketTimeOut setsockopt SO_RCVTIMEO failed, errno = %{public}d", errno);
344e509ee18Sopenharmony_ci            return false;
345e509ee18Sopenharmony_ci        }
346e509ee18Sopenharmony_ci    }
347e509ee18Sopenharmony_ci    return true;
348e509ee18Sopenharmony_ci}
349e509ee18Sopenharmony_ci#endif
350e509ee18Sopenharmony_ci
351e509ee18Sopenharmony_ci#if defined(WINDOWS_PLATFORM)
352e509ee18Sopenharmony_ci/* static */
353e509ee18Sopenharmony_ciint WebSocketBase::ShutdownSocket(int32_t fd)
354e509ee18Sopenharmony_ci{
355e509ee18Sopenharmony_ci    return shutdown(fd, SD_BOTH);
356e509ee18Sopenharmony_ci}
357e509ee18Sopenharmony_ci#else
358e509ee18Sopenharmony_ci/* static */
359e509ee18Sopenharmony_ciint WebSocketBase::ShutdownSocket(int32_t fd)
360e509ee18Sopenharmony_ci{
361e509ee18Sopenharmony_ci    return shutdown(fd, SHUT_RDWR);
362e509ee18Sopenharmony_ci}
363e509ee18Sopenharmony_ci#endif
364e509ee18Sopenharmony_ci} // namespace OHOS::ArkCompiler::Toolchain
365