CppServer  1.0.4.0
C++ Server Library
ws_client.cpp
Go to the documentation of this file.
1 
9 #include "server/ws/ws_client.h"
10 
11 namespace CppServer {
12 namespace WS {
13 
15 {
16  _sync_connect = true;
17  return HTTPClient::Connect();
18 }
19 
20 bool WSClient::Connect(const std::shared_ptr<Asio::TCPResolver>& resolver)
21 {
22  _sync_connect = true;
23  return HTTPClient::Connect(resolver);
24 }
25 
27 {
28  _sync_connect = false;
29  return HTTPClient::ConnectAsync();
30 }
31 
32 bool WSClient::ConnectAsync(const std::shared_ptr<Asio::TCPResolver>& resolver)
33 {
34  _sync_connect = false;
35  return HTTPClient::ConnectAsync(resolver);
36 }
37 
39 {
40  // Clear WebSocket send/receive buffers
42 
43  // Fill the WebSocket upgrade HTTP request
45 
46  // Set empty body of the WebSocket upgrade HTTP request
47  _request.SetBody();
48 
49  // Send the WebSocket upgrade HTTP request
50  if (_sync_connect)
51  Send(_request.cache());
52  else
54 }
55 
57 {
58  // Disconnect WebSocket
59  if (_ws_handshaked)
60  {
61  _ws_handshaked = false;
63  }
64 
65  // Reset WebSocket upgrade HTTP request and response
66  _request.Clear();
67  _response.Clear();
68 
69  // Clear WebSocket send/receive buffers
71 
72  // Initialize new WebSocket random nonce
73  InitWSNonce();
74 }
75 
76 void WSClient::onReceived(const void* buffer, size_t size)
77 {
78  // Check for WebSocket handshaked status
79  if (_ws_handshaked)
80  {
81  // Prepare receive frame
82  PrepareReceiveFrame(buffer, size);
83  return;
84  }
85 
86  HTTPClient::onReceived(buffer, size);
87 }
88 
90 {
91  // Check for WebSocket handshaked status
92  if (_ws_handshaked)
93  return;
94 
95  // Try to perform WebSocket upgrade
96  if (!PerformClientUpgrade(response, id()))
97  {
98  HTTPClient::onReceivedResponseHeader(response);
99  return;
100  }
101 }
102 
104 {
105  // Check for WebSocket handshaked status
106  if (_ws_handshaked)
107  {
108  // Prepare receive frame from the remaining response body
109  auto body = response.body();
110  PrepareReceiveFrame(body.data(), body.size());
111  return;
112  }
113 
114  HTTPClient::onReceivedResponse(response);
115 }
116 
117 void WSClient::onReceivedResponseError(const HTTP::HTTPResponse& response, const std::string& error)
118 {
119  // Check for WebSocket handshaked status
120  if (_ws_handshaked)
121  {
122  onError(asio::error::fault, "WebSocket error", error);
123  return;
124  }
125 
126  HTTPClient::onReceivedResponseError(response, error);
127 }
128 
130 {
131  std::string result;
132 
133  if (!_ws_handshaked)
134  return result;
135 
136  std::vector<uint8_t> cache;
137 
138  // Receive WebSocket frame data
139  while (!_ws_final_received)
140  {
141  while (!_ws_frame_received)
142  {
143  size_t required = RequiredReceiveFrameSize();
144  cache.resize(required);
145  size_t received = HTTPClient::Receive(cache.data(), required);
146  if (received != required)
147  return result;
148  PrepareReceiveFrame(cache.data(), received);
149  }
150  if (!_ws_final_received)
151  PrepareReceiveFrame(nullptr, 0);
152  }
153 
154  // Copy WebSocket frame data
156  PrepareReceiveFrame(nullptr, 0);
157  return result;
158 }
159 
160 std::string WSClient::ReceiveText(const CppCommon::Timespan& timeout)
161 {
162  std::string result;
163 
164  if (!_ws_handshaked)
165  return result;
166 
167  std::vector<uint8_t> cache;
168 
169  // Receive WebSocket frame data
170  while (!_ws_final_received)
171  {
172  while (!_ws_frame_received)
173  {
174  size_t required = RequiredReceiveFrameSize();
175  cache.resize(required);
176  size_t received = HTTPClient::Receive(cache.data(), required, timeout);
177  if (received != required)
178  return result;
179  PrepareReceiveFrame(cache.data(), received);
180  }
181  if (!_ws_final_received)
182  PrepareReceiveFrame(nullptr, 0);
183  }
184 
185  // Copy WebSocket frame data
187  PrepareReceiveFrame(nullptr, 0);
188  return result;
189 }
190 
191 std::vector<uint8_t> WSClient::ReceiveBinary()
192 {
193  std::vector<uint8_t> result;
194 
195  if (!_ws_handshaked)
196  return result;
197 
198  std::vector<uint8_t> cache;
199 
200  // Receive WebSocket frame data
201  while (!_ws_final_received)
202  {
203  while (!_ws_frame_received)
204  {
205  size_t required = RequiredReceiveFrameSize();
206  cache.resize(required);
207  size_t received = HTTPClient::Receive(cache.data(), required);
208  if (received != required)
209  return result;
210  PrepareReceiveFrame(cache.data(), received);
211  }
212  if (!_ws_final_received)
213  PrepareReceiveFrame(nullptr, 0);
214  }
215 
216  // Copy WebSocket frame data
218  PrepareReceiveFrame(nullptr, 0);
219  return result;
220 }
221 
222 std::vector<uint8_t> WSClient::ReceiveBinary(const CppCommon::Timespan& timeout)
223 {
224  std::vector<uint8_t> result;
225 
226  if (!_ws_handshaked)
227  return result;
228 
229  std::vector<uint8_t> cache;
230 
231  // Receive WebSocket frame data
232  while (!_ws_final_received)
233  {
234  while (!_ws_frame_received)
235  {
236  size_t required = RequiredReceiveFrameSize();
237  cache.resize(required);
238  size_t received = HTTPClient::Receive(cache.data(), required, timeout);
239  if (received != required)
240  return result;
241  PrepareReceiveFrame(cache.data(), received);
242  }
243  if (!_ws_final_received)
244  PrepareReceiveFrame(nullptr, 0);
245  }
246 
247  // Copy WebSocket frame data
249  PrepareReceiveFrame(nullptr, 0);
250  return result;
251 }
252 
253 } // namespace WS
254 } // namespace CppServer
virtual size_t Send(const void *buffer, size_t size)
Send data to the server (synchronous)
Definition: tcp_client.cpp:505
virtual bool SendAsync(const void *buffer, size_t size)
Send data to the server (asynchronous)
Definition: tcp_client.cpp:603
virtual void onError(int error, const std::string &category, const std::string &message)
Handle error notification.
Definition: tcp_client.h:320
HTTPResponse _response
HTTP response.
Definition: http_client.h:165
HTTPRequest _request
HTTP request.
Definition: http_client.h:163
HTTPRequest & SetBody(std::string_view body="")
Set the HTTP request body.
const std::string & cache() const noexcept
Get the HTTP request cache content.
Definition: http_request.h:77
HTTPRequest & Clear()
Clear the HTTP request cache.
HTTPResponse & Clear()
Clear the HTTP response cache.
std::string_view body() const noexcept
Get the HTTP response body.
Definition: http_response.h:77
bool ConnectAsync() override
Connect the client (asynchronous)
Definition: ws_client.cpp:26
std::string ReceiveText()
Definition: ws_client.cpp:129
void onReceivedResponse(const HTTP::HTTPResponse &response) override
Handle HTTP response received notification.
Definition: ws_client.cpp:103
void onReceivedResponseHeader(const HTTP::HTTPResponse &response) override
Handle HTTP response header received notification.
Definition: ws_client.cpp:89
void onDisconnected() override
Handle client disconnected notification.
Definition: ws_client.cpp:56
bool Connect() override
Connect the client (synchronous)
Definition: ws_client.cpp:14
void onReceivedResponseError(const HTTP::HTTPResponse &response, const std::string &error) override
Handle HTTP response error notification.
Definition: ws_client.cpp:117
std::vector< uint8_t > ReceiveBinary()
Definition: ws_client.cpp:191
void onConnected() override
Handle client connected notification.
Definition: ws_client.cpp:38
void onReceived(const void *buffer, size_t size) override
Handle buffer received notification.
Definition: ws_client.cpp:76
size_t _ws_payload_size
Received frame payload size.
Definition: ws.h:180
bool _ws_frame_received
Received frame flag.
Definition: ws.h:174
void InitWSNonce()
Initialize WebSocket random nonce.
Definition: ws.cpp:21
void PrepareReceiveFrame(const void *buffer, size_t size)
Prepare WebSocket receive frame.
Definition: ws.cpp:273
virtual void onWSConnecting(HTTP::HTTPRequest &request)
Handle WebSocket client connecting notification.
Definition: ws.h:107
std::vector< uint8_t > _ws_receive_final_buffer
Receive final buffer.
Definition: ws.h:184
bool PerformClientUpgrade(const HTTP::HTTPResponse &response, const CppCommon::UUID &id)
Perform WebSocket client upgrade.
Definition: ws.cpp:26
void ClearWSBuffers()
Clear WebSocket send/receive buffers.
Definition: ws.cpp:484
size_t RequiredReceiveFrameSize()
Required WebSocket receive frame size.
Definition: ws.cpp:458
bool _ws_final_received
Received final flag.
Definition: ws.h:176
size_t _ws_header_size
Received frame header size.
Definition: ws.h:178
virtual void onWSDisconnected()
Handle WebSocket client disconnected notification.
Definition: ws.h:132
bool _ws_handshaked
Handshaked flag.
Definition: ws.h:169
C++ Server project definitions.
Definition: asio.h:56
WebSocket client definition.