1 | /* |
2 | * IXWebSocket.h |
3 | * Author: Benjamin Sergeant |
4 | * Copyright (c) 2017-2018 Machine Zone, Inc. All rights reserved. |
5 | * |
6 | * WebSocket RFC |
7 | * https://tools.ietf.org/html/rfc6455 |
8 | */ |
9 | |
10 | #pragma once |
11 | |
12 | #include "IXProgressCallback.h" |
13 | #include "IXSocketTLSOptions.h" |
14 | #include "IXWebSocketCloseConstants.h" |
15 | #include "IXWebSocketErrorInfo.h" |
16 | #include "IXWebSocketHttpHeaders.h" |
17 | #include "IXWebSocketMessage.h" |
18 | #include "IXWebSocketPerMessageDeflateOptions.h" |
19 | #include "IXWebSocketSendInfo.h" |
20 | #include "IXWebSocketSendData.h" |
21 | #include "IXWebSocketTransport.h" |
22 | #include <atomic> |
23 | #include <condition_variable> |
24 | #include <mutex> |
25 | #include <string> |
26 | #include <thread> |
27 | |
28 | namespace ix |
29 | { |
30 | // https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Ready_state_constants |
31 | enum class ReadyState |
32 | { |
33 | Connecting = 0, |
34 | Open = 1, |
35 | Closing = 2, |
36 | Closed = 3 |
37 | }; |
38 | |
39 | using OnMessageCallback = std::function<void(const WebSocketMessagePtr&)>; |
40 | |
41 | using OnTrafficTrackerCallback = std::function<void(size_t size, bool incoming)>; |
42 | |
43 | class WebSocket |
44 | { |
45 | public: |
46 | WebSocket(); |
47 | ~WebSocket(); |
48 | |
49 | void setUrl(const std::string& url); |
50 | |
51 | // send extra headers in client handshake request |
52 | void (const WebSocketHttpHeaders& ); |
53 | void setPerMessageDeflateOptions( |
54 | const WebSocketPerMessageDeflateOptions& perMessageDeflateOptions); |
55 | void setTLSOptions(const SocketTLSOptions& socketTLSOptions); |
56 | void setPingInterval(int pingIntervalSecs); |
57 | void enablePong(); |
58 | void disablePong(); |
59 | void enablePerMessageDeflate(); |
60 | void disablePerMessageDeflate(); |
61 | void addSubProtocol(const std::string& subProtocol); |
62 | void setHandshakeTimeout(int handshakeTimeoutSecs); |
63 | |
64 | // Run asynchronously, by calling start and stop. |
65 | void start(); |
66 | |
67 | // stop is synchronous |
68 | void stop(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, |
69 | const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage); |
70 | |
71 | // Run in blocking mode, by connecting first manually, and then calling run. |
72 | WebSocketInitResult connect(int timeoutSecs); |
73 | void run(); |
74 | |
75 | // send is in text mode by default |
76 | WebSocketSendInfo send(const std::string& data, |
77 | bool binary = false, |
78 | const OnProgressCallback& onProgressCallback = nullptr); |
79 | WebSocketSendInfo sendBinary(const std::string& data, |
80 | const OnProgressCallback& onProgressCallback = nullptr); |
81 | WebSocketSendInfo sendBinary(const IXWebSocketSendData& data, |
82 | const OnProgressCallback& onProgressCallback = nullptr); |
83 | // does not check for valid UTF-8 characters. Caller must check that. |
84 | WebSocketSendInfo sendUtf8Text(const std::string& text, |
85 | const OnProgressCallback& onProgressCallback = nullptr); |
86 | // does not check for valid UTF-8 characters. Caller must check that. |
87 | WebSocketSendInfo sendUtf8Text(const IXWebSocketSendData& text, |
88 | const OnProgressCallback& onProgressCallback = nullptr); |
89 | WebSocketSendInfo sendText(const std::string& text, |
90 | const OnProgressCallback& onProgressCallback = nullptr); |
91 | WebSocketSendInfo ping(const std::string& text); |
92 | |
93 | void close(uint16_t code = WebSocketCloseConstants::kNormalClosureCode, |
94 | const std::string& reason = WebSocketCloseConstants::kNormalClosureMessage); |
95 | |
96 | void setOnMessageCallback(const OnMessageCallback& callback); |
97 | bool isOnMessageCallbackRegistered() const; |
98 | static void setTrafficTrackerCallback(const OnTrafficTrackerCallback& callback); |
99 | static void resetTrafficTrackerCallback(); |
100 | |
101 | ReadyState getReadyState() const; |
102 | static std::string readyStateToString(ReadyState readyState); |
103 | |
104 | const std::string getUrl() const; |
105 | const WebSocketPerMessageDeflateOptions getPerMessageDeflateOptions() const; |
106 | int getPingInterval() const; |
107 | size_t bufferedAmount() const; |
108 | |
109 | void enableAutomaticReconnection(); |
110 | void disableAutomaticReconnection(); |
111 | bool isAutomaticReconnectionEnabled() const; |
112 | void setMaxWaitBetweenReconnectionRetries(uint32_t maxWaitBetweenReconnectionRetries); |
113 | void setMinWaitBetweenReconnectionRetries(uint32_t minWaitBetweenReconnectionRetries); |
114 | uint32_t getMaxWaitBetweenReconnectionRetries() const; |
115 | uint32_t getMinWaitBetweenReconnectionRetries() const; |
116 | const std::vector<std::string>& getSubProtocols(); |
117 | |
118 | private: |
119 | WebSocketSendInfo sendMessage(const IXWebSocketSendData& message, |
120 | SendMessageKind sendMessageKind, |
121 | const OnProgressCallback& callback = nullptr); |
122 | |
123 | bool isConnected() const; |
124 | bool isClosing() const; |
125 | void checkConnection(bool firstConnectionAttempt); |
126 | static void invokeTrafficTrackerCallback(size_t size, bool incoming); |
127 | |
128 | // Server |
129 | WebSocketInitResult connectToSocket(std::unique_ptr<Socket>, |
130 | int timeoutSecs, |
131 | bool enablePerMessageDeflate); |
132 | |
133 | WebSocketTransport _ws; |
134 | |
135 | std::string _url; |
136 | WebSocketHttpHeaders ; |
137 | |
138 | WebSocketPerMessageDeflateOptions _perMessageDeflateOptions; |
139 | |
140 | SocketTLSOptions _socketTLSOptions; |
141 | |
142 | mutable std::mutex _configMutex; // protect all config variables access |
143 | |
144 | OnMessageCallback _onMessageCallback; |
145 | static OnTrafficTrackerCallback _onTrafficTrackerCallback; |
146 | |
147 | std::atomic<bool> _stop; |
148 | std::thread _thread; |
149 | std::mutex _writeMutex; |
150 | |
151 | // Automatic reconnection |
152 | std::atomic<bool> _automaticReconnection; |
153 | static const uint32_t kDefaultMaxWaitBetweenReconnectionRetries; |
154 | static const uint32_t kDefaultMinWaitBetweenReconnectionRetries; |
155 | uint32_t _maxWaitBetweenReconnectionRetries; |
156 | uint32_t _minWaitBetweenReconnectionRetries; |
157 | |
158 | // Make the sleeping in the automatic reconnection cancellable |
159 | std::mutex _sleepMutex; |
160 | std::condition_variable _sleepCondition; |
161 | |
162 | std::atomic<int> _handshakeTimeoutSecs; |
163 | static const int kDefaultHandShakeTimeoutSecs; |
164 | |
165 | // enable or disable PONG frame response to received PING frame |
166 | bool _enablePong; |
167 | static const bool kDefaultEnablePong; |
168 | |
169 | // Optional ping and pong timeout |
170 | int _pingIntervalSecs; |
171 | int _pingTimeoutSecs; |
172 | static const int kDefaultPingIntervalSecs; |
173 | static const int kDefaultPingTimeoutSecs; |
174 | |
175 | // Subprotocols |
176 | std::vector<std::string> _subProtocols; |
177 | |
178 | friend class WebSocketServer; |
179 | }; |
180 | } // namespace ix |
181 | |