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 #ifndef ARKCOMPILER_TOOLCHAIN_WEBSOCKET_WEBSOCKET_BASE_H
17 #define ARKCOMPILER_TOOLCHAIN_WEBSOCKET_WEBSOCKET_BASE_H
18
19 #include "websocket/frame_builder.h"
20 #include "websocket/web_socket_frame.h"
21
22 #include <atomic>
23 #include <functional>
24 #include <type_traits>
25
26 namespace OHOS::ArkCompiler::Toolchain {
27 enum CloseStatusCode : uint16_t {
28 NO_STATUS_CODE = 0,
29 NORMAL = 1000,
30 SERVER_GO_AWAY = 1001,
31 PROTOCOL_ERROR = 1002,
32 UNACCEPTABLE_DATA = 1003,
33 INCONSISTENT_DATA = 1007,
34 POLICY_VIOLATION = 1008,
35 MESSAGE_TOO_BIG = 1009,
36 UNEXPECTED_ERROR = 1011,
37 };
38
ToString(CloseStatusCode status)39 inline std::string ToString(CloseStatusCode status)
40 {
41 if (status == CloseStatusCode::NO_STATUS_CODE) {
42 return "";
43 }
44 std::string result;
45 PushNumberPerByte(result, EnumToNumber(status));
46 return result;
47 }
48
49 class WebSocketBase {
50 public:
51 using CloseConnectionCallback = std::function<void()>;
52 using FailConnectionCallback = std::function<void()>;
53
54 public:
55 static bool IsDecodeDisconnectMsg(const std::string& message);
56
57 WebSocketBase() = default;
58 virtual ~WebSocketBase() noexcept = default;
59
60 // Receive and decode a message.
61 // In case of control frames this method handles it accordingly and returns an empty string,
62 // otherwise returns the decoded received message.
63 std::string Decode();
64 // Send message on current connection.
65 // Returns success status.
66 bool SendReply(const std::string& message, FrameType frameType = FrameType::TEXT, bool isLast = true) const;
67
68 bool IsConnected();
69
70 void SetCloseConnectionCallback(CloseConnectionCallback cb);
71 void SetFailConnectionCallback(FailConnectionCallback cb);
72
73 // Close current websocket endpoint and connections (if any).
74 virtual void Close() = 0;
75
76 protected:
77 enum class SocketState : uint8_t {
78 UNINITED,
79 INITED,
80 CONNECTED,
81 };
82
83 enum class ConnectionCloseReason: uint8_t {
84 FAIL,
85 CLOSE,
86 };
87
88 protected:
89 static bool SetWebSocketTimeOut(int32_t fd, uint32_t timeoutLimit);
90
91 bool ReadPayload(WebSocketFrame& wsFrame);
92 void SendPongFrame(std::string payload);
93 void SendCloseFrame(CloseStatusCode status);
94 // Sending close frame and close connection.
95 void CloseConnection(CloseStatusCode status, SocketState newSocketState);
96 // Close connection socket.
97 void CloseConnectionSocket(ConnectionCloseReason status, SocketState newSocketState);
98
99 virtual bool HandleDataFrame(WebSocketFrame& wsFrame);
100 virtual bool HandleControlFrame(WebSocketFrame& wsFrame);
101
102 virtual bool ValidateIncomingFrame(const WebSocketFrame& wsFrame) = 0;
103 virtual std::string CreateFrame(bool isLast, FrameType frameType) const = 0;
104 virtual std::string CreateFrame(bool isLast, FrameType frameType, const std::string& payload) const = 0;
105 virtual std::string CreateFrame(bool isLast, FrameType frameType, std::string&& payload) const = 0;
106 virtual bool DecodeMessage(WebSocketFrame& wsFrame) const = 0;
107
108 protected:
109 std::atomic<SocketState> socketState_ {SocketState::UNINITED};
110
111 int connectionFd_ {-1};
112
113 // Callbacks used during different stages of connection lifecycle.
114 CloseConnectionCallback closeCb_;
115 FailConnectionCallback failCb_;
116
117 static constexpr char WEB_SOCKET_GUID[] = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
118 static constexpr size_t HTTP_HANDSHAKE_MAX_LEN = 1024;
119 static constexpr int SOCKET_SUCCESS = 0;
120 static constexpr std::string_view DECODE_DISCONNECT_MSG = "disconnect";
121 };
122 } // namespace OHOS::ArkCompiler::Toolchain
123
124 #endif // ARKCOMPILER_TOOLCHAIN_WEBSOCKET_WEBSOCKET_BASE_H
125