]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/websocket/handshake.cpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / libs / beast / test / beast / websocket / handshake.cpp
1 //
2 // Copyright (w) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9
10 // Test that header file is self-contained.
11 #include <boost/beast/websocket/stream.hpp>
12
13 #include "test.hpp"
14
15 namespace boost {
16 namespace beast {
17 namespace websocket {
18
19 class handshake_test : public websocket_test_suite
20 {
21 public:
22 template<class Wrap>
23 void
24 doTestHandshake(Wrap const& w)
25 {
26 class req_decorator
27 {
28 bool& b_;
29
30 public:
31 req_decorator(req_decorator const&) = default;
32
33 explicit
34 req_decorator(bool& b)
35 : b_(b)
36 {
37 }
38
39 void
40 operator()(request_type&) const
41 {
42 b_ = true;
43 }
44 };
45
46 // handshake
47 doStreamLoop([&](test::stream& ts)
48 {
49 echo_server es{log};
50 ws_type ws{ts};
51 ws.next_layer().connect(es.stream());
52 try
53 {
54 w.handshake(ws, "localhost", "/");
55 }
56 catch(...)
57 {
58 ts.close();
59 throw;
60 }
61 ts.close();
62 });
63
64 // handshake, response
65 doStreamLoop([&](test::stream& ts)
66 {
67 echo_server es{log};
68 ws_type ws{ts};
69 ws.next_layer().connect(es.stream());
70 response_type res;
71 try
72 {
73 w.handshake(ws, res, "localhost", "/");
74 // VFALCO validate res?
75 }
76 catch(...)
77 {
78 ts.close();
79 throw;
80 }
81 ts.close();
82 });
83
84 // handshake, decorator
85 doStreamLoop([&](test::stream& ts)
86 {
87 echo_server es{log};
88 ws_type ws{ts};
89 ws.next_layer().connect(es.stream());
90 bool called = false;
91 try
92 {
93 w.handshake_ex(ws, "localhost", "/",
94 req_decorator{called});
95 BEAST_EXPECT(called);
96 }
97 catch(...)
98 {
99 ts.close();
100 throw;
101 }
102 ts.close();
103 });
104
105 // handshake, response, decorator
106 doStreamLoop([&](test::stream& ts)
107 {
108 echo_server es{log};
109 ws_type ws{ts};
110 ws.next_layer().connect(es.stream());
111 bool called = false;
112 response_type res;
113 try
114 {
115 w.handshake_ex(ws, res, "localhost", "/",
116 req_decorator{called});
117 // VFALCO validate res?
118 BEAST_EXPECT(called);
119 }
120 catch(...)
121 {
122 ts.close();
123 throw;
124 }
125 ts.close();
126 });
127 }
128
129 void
130 testHandshake()
131 {
132 doTestHandshake(SyncClient{});
133
134 yield_to([&](yield_context yield)
135 {
136 doTestHandshake(AsyncClient{yield});
137 });
138
139 auto const check =
140 [&](std::string const& s)
141 {
142 stream<test::stream> ws{ioc_};
143 auto tr = connect(ws.next_layer());
144 ws.next_layer().append(s);
145 tr.close();
146 try
147 {
148 ws.handshake("localhost:80", "/");
149 fail();
150 }
151 catch(system_error const& se)
152 {
153 BEAST_EXPECT(se.code() == error::handshake_failed);
154 }
155 };
156 // wrong HTTP version
157 check(
158 "HTTP/1.0 101 Switching Protocols\r\n"
159 "Server: beast\r\n"
160 "Upgrade: WebSocket\r\n"
161 "Connection: upgrade\r\n"
162 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
163 "Sec-WebSocket-Version: 13\r\n"
164 "\r\n"
165 );
166 // wrong status
167 check(
168 "HTTP/1.1 200 OK\r\n"
169 "Server: beast\r\n"
170 "Upgrade: WebSocket\r\n"
171 "Connection: upgrade\r\n"
172 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
173 "Sec-WebSocket-Version: 13\r\n"
174 "\r\n"
175 );
176 // missing upgrade token
177 check(
178 "HTTP/1.1 101 Switching Protocols\r\n"
179 "Server: beast\r\n"
180 "Upgrade: HTTP/2\r\n"
181 "Connection: upgrade\r\n"
182 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
183 "Sec-WebSocket-Version: 13\r\n"
184 "\r\n"
185 );
186 // missing connection token
187 check(
188 "HTTP/1.1 101 Switching Protocols\r\n"
189 "Server: beast\r\n"
190 "Upgrade: WebSocket\r\n"
191 "Connection: keep-alive\r\n"
192 "Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=\r\n"
193 "Sec-WebSocket-Version: 13\r\n"
194 "\r\n"
195 );
196 // missing accept key
197 check(
198 "HTTP/1.1 101 Switching Protocols\r\n"
199 "Server: beast\r\n"
200 "Upgrade: WebSocket\r\n"
201 "Connection: upgrade\r\n"
202 "Sec-WebSocket-Version: 13\r\n"
203 "\r\n"
204 );
205 // wrong accept key
206 check(
207 "HTTP/1.1 101 Switching Protocols\r\n"
208 "Server: beast\r\n"
209 "Upgrade: WebSocket\r\n"
210 "Connection: upgrade\r\n"
211 "Sec-WebSocket-Accept: *\r\n"
212 "Sec-WebSocket-Version: 13\r\n"
213 "\r\n"
214 );
215 }
216
217 // Compression Extensions for WebSocket
218 //
219 // https://tools.ietf.org/html/rfc7692
220 //
221 void
222 testExtRead()
223 {
224 detail::pmd_offer po;
225
226 auto const accept =
227 [&](string_view s)
228 {
229 http::fields f;
230 f.set(http::field::sec_websocket_extensions, s);
231 po = detail::pmd_offer();
232 detail::pmd_read(po, f);
233 BEAST_EXPECT(po.accept);
234 };
235
236 auto const reject =
237 [&](string_view s)
238 {
239 http::fields f;
240 f.set(http::field::sec_websocket_extensions, s);
241 po = detail::pmd_offer();
242 detail::pmd_read(po, f);
243 BEAST_EXPECT(! po.accept);
244 };
245
246 // duplicate parameters
247 reject("permessage-deflate; server_max_window_bits=8; server_max_window_bits=8");
248
249 // missing value
250 reject("permessage-deflate; server_max_window_bits");
251 reject("permessage-deflate; server_max_window_bits=");
252
253 // invalid value
254 reject("permessage-deflate; server_max_window_bits=-1");
255 reject("permessage-deflate; server_max_window_bits=7");
256 reject("permessage-deflate; server_max_window_bits=16");
257 reject("permessage-deflate; server_max_window_bits=999999999999999999999999");
258 reject("permessage-deflate; server_max_window_bits=9a");
259
260 // duplicate parameters
261 reject("permessage-deflate; client_max_window_bits=8; client_max_window_bits=8");
262
263 // optional value excluded
264 accept("permessage-deflate; client_max_window_bits");
265 BEAST_EXPECT(po.client_max_window_bits == -1);
266 accept("permessage-deflate; client_max_window_bits=");
267 BEAST_EXPECT(po.client_max_window_bits == -1);
268
269 // invalid value
270 reject("permessage-deflate; client_max_window_bits=-1");
271 reject("permessage-deflate; client_max_window_bits=7");
272 reject("permessage-deflate; client_max_window_bits=16");
273 reject("permessage-deflate; client_max_window_bits=999999999999999999999999");
274
275 // duplicate parameters
276 reject("permessage-deflate; server_no_context_takeover; server_no_context_takeover");
277
278 // valueless parameter
279 accept("permessage-deflate; server_no_context_takeover");
280 BEAST_EXPECT(po.server_no_context_takeover);
281 accept("permessage-deflate; server_no_context_takeover=");
282 BEAST_EXPECT(po.server_no_context_takeover);
283
284 // disallowed value
285 reject("permessage-deflate; server_no_context_takeover=-1");
286 reject("permessage-deflate; server_no_context_takeover=x");
287 reject("permessage-deflate; server_no_context_takeover=\"yz\"");
288 reject("permessage-deflate; server_no_context_takeover=999999999999999999999999");
289
290 // duplicate parameters
291 reject("permessage-deflate; client_no_context_takeover; client_no_context_takeover");
292
293 // valueless parameter
294 accept("permessage-deflate; client_no_context_takeover");
295 BEAST_EXPECT(po.client_no_context_takeover);
296 accept("permessage-deflate; client_no_context_takeover=");
297 BEAST_EXPECT(po.client_no_context_takeover);
298
299 // disallowed value
300 reject("permessage-deflate; client_no_context_takeover=-1");
301 reject("permessage-deflate; client_no_context_takeover=x");
302 reject("permessage-deflate; client_no_context_takeover=\"yz\"");
303 reject("permessage-deflate; client_no_context_takeover=999999999999999999999999");
304
305 // unknown extension parameter
306 reject("permessage-deflate; unknown");
307 reject("permessage-deflate; unknown=");
308 reject("permessage-deflate; unknown=1");
309 reject("permessage-deflate; unknown=x");
310 reject("permessage-deflate; unknown=\"xy\"");
311 }
312
313 void
314 testExtWrite()
315 {
316 detail::pmd_offer po;
317
318 auto const check =
319 [&](string_view match)
320 {
321 http::fields f;
322 detail::pmd_write(f, po);
323 BEAST_EXPECT(
324 f[http::field::sec_websocket_extensions]
325 == match);
326 };
327
328 po.accept = true;
329 po.server_max_window_bits = 0;
330 po.client_max_window_bits = 0;
331 po.server_no_context_takeover = false;
332 po.client_no_context_takeover = false;
333
334 check("permessage-deflate");
335
336 po.server_max_window_bits = 10;
337 check("permessage-deflate; server_max_window_bits=10");
338
339 po.server_max_window_bits = -1;
340 check("permessage-deflate; server_max_window_bits");
341
342 po.server_max_window_bits = 0;
343 po.client_max_window_bits = 10;
344 check("permessage-deflate; client_max_window_bits=10");
345
346 po.client_max_window_bits = -1;
347 check("permessage-deflate; client_max_window_bits");
348
349 po.client_max_window_bits = 0;
350 po.server_no_context_takeover = true;
351 check("permessage-deflate; server_no_context_takeover");
352
353 po.server_no_context_takeover = false;
354 po.client_no_context_takeover = true;
355 check("permessage-deflate; client_no_context_takeover");
356 }
357
358 void
359 testExtNegotiate()
360 {
361 permessage_deflate pmd;
362
363 auto const reject =
364 [&](
365 string_view offer)
366 {
367 detail::pmd_offer po;
368 {
369 http::fields f;
370 f.set(http::field::sec_websocket_extensions, offer);
371 detail::pmd_read(po, f);
372 }
373 http::fields f;
374 detail::pmd_offer config;
375 detail::pmd_negotiate(f, config, po, pmd);
376 BEAST_EXPECT(! config.accept);
377 };
378
379 auto const accept =
380 [&](
381 string_view offer,
382 string_view result)
383 {
384 detail::pmd_offer po;
385 {
386 http::fields f;
387 f.set(http::field::sec_websocket_extensions, offer);
388 detail::pmd_read(po, f);
389 }
390 http::fields f;
391 detail::pmd_offer config;
392 detail::pmd_negotiate(f, config, po, pmd);
393 auto const got =
394 f[http::field::sec_websocket_extensions];
395 BEAST_EXPECTS(got == result, got);
396 {
397 detail::pmd_offer poc;
398 detail::pmd_read(poc, f);
399 detail::pmd_normalize(poc);
400 BEAST_EXPECT(poc.accept);
401 }
402 BEAST_EXPECT(config.server_max_window_bits != 0);
403 BEAST_EXPECT(config.client_max_window_bits != 0);
404 };
405
406 pmd.server_enable = true;
407 pmd.server_max_window_bits = 15;
408 pmd.client_max_window_bits = 15;
409 pmd.server_no_context_takeover = false;
410 pmd.client_no_context_takeover = false;
411
412 // default
413 accept(
414 "permessage-deflate",
415 "permessage-deflate");
416
417 // non-default server_max_window_bits
418 accept(
419 "permessage-deflate; server_max_window_bits=14",
420 "permessage-deflate; server_max_window_bits=14");
421
422 // explicit default server_max_window_bits
423 accept(
424 "permessage-deflate; server_max_window_bits=15",
425 "permessage-deflate");
426
427 // minimum window size of 8 bits (a zlib bug)
428 accept(
429 "permessage-deflate; server_max_window_bits=8",
430 "permessage-deflate; server_max_window_bits=9");
431
432 // non-default server_max_window_bits setting
433 pmd.server_max_window_bits = 10;
434 accept(
435 "permessage-deflate",
436 "permessage-deflate; server_max_window_bits=10");
437
438 // clamped server_max_window_bits setting #1
439 pmd.server_max_window_bits = 10;
440 accept(
441 "permessage-deflate; server_max_window_bits=14",
442 "permessage-deflate; server_max_window_bits=10");
443
444 // clamped server_max_window_bits setting #2
445 pmd.server_max_window_bits=8;
446 accept(
447 "permessage-deflate; server_max_window_bits=14",
448 "permessage-deflate; server_max_window_bits=9");
449
450 pmd.server_max_window_bits = 15;
451
452 // present with no value
453 accept(
454 "permessage-deflate; client_max_window_bits",
455 "permessage-deflate");
456
457 // present with no value, non-default setting
458 pmd.client_max_window_bits = 10;
459 accept(
460 "permessage-deflate; client_max_window_bits",
461 "permessage-deflate; client_max_window_bits=10");
462
463 // absent, non-default setting
464 pmd.client_max_window_bits = 10;
465 reject(
466 "permessage-deflate");
467 }
468
469 void
470 run() override
471 {
472 testHandshake();
473 testExtRead();
474 testExtWrite();
475 testExtNegotiate();
476 }
477 };
478
479 BEAST_DEFINE_TESTSUITE(beast,websocket,handshake);
480
481 } // websocket
482 } // beast
483 } // boost