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