]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/beast/test/beast/websocket/accept.cpp
update sources to ceph Nautilus 14.2.1
[ceph.git] / ceph / src / boost / libs / beast / test / beast / websocket / accept.cpp
CommitLineData
b32b8144
FG
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
11fdf7f2
TL
15#include <boost/asio/io_service.hpp>
16#include <boost/asio/strand.hpp>
17
b32b8144
FG
18namespace boost {
19namespace beast {
20namespace websocket {
21
22class accept_test : public websocket_test_suite
23{
24public:
25 template<class Wrap>
26 void
27 doTestAccept(Wrap const& w)
28 {
29 class res_decorator
30 {
31 bool& b_;
32
33 public:
34 res_decorator(res_decorator const&) = default;
35
36 explicit
37 res_decorator(bool& b)
38 : b_(b)
39 {
40 }
41
42 void
43 operator()(response_type&) const
44 {
45 this->b_ = true;
46 }
47 };
48
49 auto const big = []
50 {
51 std::string s;
52 s += "X1: " + std::string(2000, '*') + "\r\n";
53 return s;
54 }();
55
56 // request in stream
57 doStreamLoop([&](test::stream& ts)
58 {
59 stream<test::stream&> ws{ts};
60 auto tr = connect(ws.next_layer());
61 ts.append(
62 "GET / HTTP/1.1\r\n"
63 "Host: localhost\r\n"
64 "Upgrade: websocket\r\n"
65 "Connection: upgrade\r\n"
66 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
67 "Sec-WebSocket-Version: 13\r\n"
68 "\r\n");
69 ts.read_size(20);
70 w.accept(ws);
71 // VFALCO validate contents of ws.next_layer().str?
72 });
73
74 // request in stream, oversized
75 {
76 stream<test::stream> ws{ioc_,
77 "GET / HTTP/1.1\r\n"
78 "Host: localhost\r\n"
79 "Upgrade: websocket\r\n"
80 "Connection: upgrade\r\n"
81 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
82 "Sec-WebSocket-Version: 13\r\n"
83 + big +
84 "\r\n"};
85 auto tr = connect(ws.next_layer());
86 try
87 {
88 w.accept(ws);
89 fail("", __FILE__, __LINE__);
90 }
91 catch(system_error const& se)
92 {
93 // VFALCO Its the http error category...
94 BEAST_EXPECTS(
95 se.code() == http::error::buffer_overflow,
96 se.code().message());
97 }
98 }
99
100 // request in stream, decorator
101 doStreamLoop([&](test::stream& ts)
102 {
103 stream<test::stream&> ws{ts};
104 auto tr = connect(ws.next_layer());
105 ts.append(
106 "GET / HTTP/1.1\r\n"
107 "Host: localhost\r\n"
108 "Upgrade: websocket\r\n"
109 "Connection: upgrade\r\n"
110 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
111 "Sec-WebSocket-Version: 13\r\n"
112 "\r\n");
113 ts.read_size(20);
114 bool called = false;
115 w.accept_ex(ws, res_decorator{called});
116 BEAST_EXPECT(called);
117 });
118
119 // request in stream, decorator, oversized
120 {
121 stream<test::stream> ws{ioc_,
122 "GET / HTTP/1.1\r\n"
123 "Host: localhost\r\n"
124 "Upgrade: websocket\r\n"
125 "Connection: upgrade\r\n"
126 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
127 "Sec-WebSocket-Version: 13\r\n"
128 + big +
129 "\r\n"};
130 auto tr = connect(ws.next_layer());
131 try
132 {
133 bool called = false;
134 w.accept_ex(ws, res_decorator{called});
135 fail("", __FILE__, __LINE__);
136 }
137 catch(system_error const& se)
138 {
139 // VFALCO Its the http error category...
140 BEAST_EXPECTS(
141 se.code() == http::error::buffer_overflow,
142 se.code().message());
143 }
144 }
145
146 // request in buffers
147 doStreamLoop([&](test::stream& ts)
148 {
149 stream<test::stream&> ws{ts};
150 auto tr = connect(ws.next_layer());
151 w.accept(ws, sbuf(
152 "GET / HTTP/1.1\r\n"
153 "Host: localhost\r\n"
154 "Upgrade: websocket\r\n"
155 "Connection: upgrade\r\n"
156 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
157 "Sec-WebSocket-Version: 13\r\n"
158 "\r\n"
159 ));
160 });
161
162 // request in buffers, oversize
163 {
164 stream<test::stream> ws{ioc_};
165 auto tr = connect(ws.next_layer());
166 try
167 {
168 w.accept(ws, boost::asio::buffer(
169 "GET / HTTP/1.1\r\n"
170 "Host: localhost\r\n"
171 "Upgrade: websocket\r\n"
172 "Connection: upgrade\r\n"
173 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
174 "Sec-WebSocket-Version: 13\r\n"
175 + big +
176 "\r\n"
177 ));
178 fail("", __FILE__, __LINE__);
179 }
180 catch(system_error const& se)
181 {
182 BEAST_EXPECTS(
183 se.code() == error::buffer_overflow,
184 se.code().message());
185 }
186 }
187
188 // request in buffers, decorator
189 doStreamLoop([&](test::stream& ts)
190 {
191 stream<test::stream&> ws{ts};
192 auto tr = connect(ws.next_layer());
193 bool called = false;
194 w.accept_ex(ws, sbuf(
195 "GET / HTTP/1.1\r\n"
196 "Host: localhost\r\n"
197 "Upgrade: websocket\r\n"
198 "Connection: upgrade\r\n"
199 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
200 "Sec-WebSocket-Version: 13\r\n"
201 "\r\n"),
202 res_decorator{called});
203 BEAST_EXPECT(called);
204 });
205
206 // request in buffers, decorator, oversized
207 {
208 stream<test::stream> ws{ioc_};
209 auto tr = connect(ws.next_layer());
210 try
211 {
212 bool called = false;
213 w.accept_ex(ws, boost::asio::buffer(
214 "GET / HTTP/1.1\r\n"
215 "Host: localhost\r\n"
216 "Upgrade: websocket\r\n"
217 "Connection: upgrade\r\n"
218 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
219 "Sec-WebSocket-Version: 13\r\n"
220 + big +
221 "\r\n"),
222 res_decorator{called});
223 fail("", __FILE__, __LINE__);
224 }
225 catch(system_error const& se)
226 {
227 BEAST_EXPECTS(
228 se.code() == error::buffer_overflow,
229 se.code().message());
230 }
231 }
232
233 // request in buffers and stream
234 doStreamLoop([&](test::stream& ts)
235 {
236 stream<test::stream&> ws{ts};
237 auto tr = connect(ws.next_layer());
238 ts.append(
239 "Connection: upgrade\r\n"
240 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
241 "Sec-WebSocket-Version: 13\r\n"
242 "\r\n");
243 ts.read_size(16);
244 w.accept(ws, sbuf(
245 "GET / HTTP/1.1\r\n"
246 "Host: localhost\r\n"
247 "Upgrade: websocket\r\n"
248 ));
249 // VFALCO validate contents of ws.next_layer().str?
250 });
251
252 // request in buffers and stream, oversized
253 {
254 stream<test::stream> ws{ioc_,
255 "Connection: upgrade\r\n"
256 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
257 "Sec-WebSocket-Version: 13\r\n"
258 + big +
259 "\r\n"};
260 auto tr = connect(ws.next_layer());
261 try
262 {
263 w.accept(ws, sbuf(
264 "GET / HTTP/1.1\r\n"
265 "Host: localhost\r\n"
266 "Upgrade: websocket\r\n"
267 ));
268 fail("", __FILE__, __LINE__);
269 }
270 catch(system_error const& se)
271 {
272 BEAST_EXPECTS(
273 se.code() == http::error::buffer_overflow,
274 se.code().message());
275 }
276 }
277
278 // request in buffers and stream, decorator
279 doStreamLoop([&](test::stream& ts)
280 {
281 stream<test::stream&> ws{ts};
282 auto tr = connect(ws.next_layer());
283 ts.append(
284 "Connection: upgrade\r\n"
285 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
286 "Sec-WebSocket-Version: 13\r\n"
287 "\r\n");
288 ts.read_size(16);
289 bool called = false;
290 w.accept_ex(ws, sbuf(
291 "GET / HTTP/1.1\r\n"
292 "Host: localhost\r\n"
293 "Upgrade: websocket\r\n"),
294 res_decorator{called});
295 BEAST_EXPECT(called);
296 });
297
298 // request in buffers and stream, decorator, oversize
299 {
300 stream<test::stream> ws{ioc_,
301 "Connection: upgrade\r\n"
302 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
303 "Sec-WebSocket-Version: 13\r\n"
304 + big +
305 "\r\n"};
306 auto tr = connect(ws.next_layer());
307 try
308 {
309 bool called = false;
310 w.accept_ex(ws, sbuf(
311 "GET / HTTP/1.1\r\n"
312 "Host: localhost\r\n"
313 "Upgrade: websocket\r\n"),
314 res_decorator{called});
315 fail("", __FILE__, __LINE__);
316 }
317 catch(system_error const& se)
318 {
319 BEAST_EXPECTS(
320 se.code() == http::error::buffer_overflow,
321 se.code().message());
322 }
323 }
324
325 // request in message
326 doStreamLoop([&](test::stream& ts)
327 {
328 stream<test::stream&> ws{ts};
329 auto tr = connect(ws.next_layer());
330 request_type req;
331 req.method(http::verb::get);
332 req.target("/");
333 req.version(11);
334 req.insert(http::field::host, "localhost");
335 req.insert(http::field::upgrade, "websocket");
336 req.insert(http::field::connection, "upgrade");
337 req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ==");
338 req.insert(http::field::sec_websocket_version, "13");
339 w.accept(ws, req);
340 });
341
342 // request in message, decorator
343 doStreamLoop([&](test::stream& ts)
344 {
345 stream<test::stream&> ws{ts};
346 auto tr = connect(ws.next_layer());
347 request_type req;
348 req.method(http::verb::get);
349 req.target("/");
350 req.version(11);
351 req.insert(http::field::host, "localhost");
352 req.insert(http::field::upgrade, "websocket");
353 req.insert(http::field::connection, "upgrade");
354 req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ==");
355 req.insert(http::field::sec_websocket_version, "13");
356 bool called = false;
357 w.accept_ex(ws, req,
358 res_decorator{called});
359 BEAST_EXPECT(called);
360 });
361
362 // request in message, close frame in stream
363 doStreamLoop([&](test::stream& ts)
364 {
365 stream<test::stream&> ws{ts};
366 auto tr = connect(ws.next_layer());
367 request_type req;
368 req.method(http::verb::get);
369 req.target("/");
370 req.version(11);
371 req.insert(http::field::host, "localhost");
372 req.insert(http::field::upgrade, "websocket");
373 req.insert(http::field::connection, "upgrade");
374 req.insert(http::field::sec_websocket_key, "dGhlIHNhbXBsZSBub25jZQ==");
375 req.insert(http::field::sec_websocket_version, "13");
376 ts.append("\x88\x82\xff\xff\xff\xff\xfc\x17");
377 w.accept(ws, req);
378 try
379 {
380 static_buffer<1> b;
381 w.read(ws, b);
382 fail("success", __FILE__, __LINE__);
383 }
384 catch(system_error const& e)
385 {
386 if(e.code() != websocket::error::closed)
387 throw;
388 }
389 });
390
391 // failed handshake (missing Sec-WebSocket-Key)
392 doStreamLoop([&](test::stream& ts)
393 {
394 stream<test::stream&> ws{ts};
395 auto tr = connect(ws.next_layer());
396 ts.append(
397 "GET / HTTP/1.1\r\n"
398 "Host: localhost\r\n"
399 "Upgrade: websocket\r\n"
400 "Connection: upgrade\r\n"
401 "Sec-WebSocket-Version: 13\r\n"
402 "\r\n");
403 ts.read_size(20);
404 try
405 {
406 w.accept(ws);
407 fail("success", __FILE__, __LINE__);
408 }
409 catch(system_error const& e)
410 {
411 if( e.code() !=
11fdf7f2 412 websocket::error::no_sec_key &&
b32b8144
FG
413 e.code() !=
414 boost::asio::error::eof)
415 throw;
416 }
417 });
418
419 // Closed by client
420 {
421 stream<test::stream> ws{ioc_};
422 auto tr = connect(ws.next_layer());
423 tr.close();
424 try
425 {
426 w.accept(ws);
427 fail("success", __FILE__, __LINE__);
428 }
429 catch(system_error const& e)
430 {
431 if(! BEAST_EXPECTS(
432 e.code() == error::closed,
433 e.code().message()))
434 throw;
435 }
436 }
437 }
438
439 void
440 testAccept()
441 {
442 doTestAccept(SyncClient{});
443
444 yield_to([&](yield_context yield)
445 {
446 doTestAccept(AsyncClient{yield});
447 });
448
449 //
450 // Bad requests
451 //
452
453 auto const check =
454 [&](error_code const& ev, std::string const& s)
455 {
456 for(int i = 0; i < 3; ++i)
457 {
458 std::size_t n;
459 switch(i)
460 {
461 default:
462 case 0:
463 n = 1;
464 break;
465 case 1:
466 n = s.size() / 2;
467 break;
468 case 2:
469 n = s.size() - 1;
470 break;
471 }
472 stream<test::stream> ws{ioc_};
473 auto tr = connect(ws.next_layer());
474 ws.next_layer().append(
475 s.substr(n, s.size() - n));
476 try
477 {
478 ws.accept(
479 boost::asio::buffer(s.data(), n));
480 BEAST_EXPECTS(! ev, ev.message());
481 }
482 catch(system_error const& se)
483 {
484 BEAST_EXPECTS(se.code() == ev, se.what());
485 }
486 }
487 };
488
11fdf7f2
TL
489 // bad version
490 check(error::bad_http_version,
b32b8144
FG
491 "GET / HTTP/1.0\r\n"
492 "Host: localhost:80\r\n"
493 "Upgrade: WebSocket\r\n"
494 "Connection: keep-alive,upgrade\r\n"
495 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
496 "Sec-WebSocket-Version: 13\r\n"
497 "\r\n"
498 );
11fdf7f2
TL
499 // bad method
500 check(error::bad_method,
b32b8144
FG
501 "POST / HTTP/1.1\r\n"
502 "Host: localhost:80\r\n"
503 "Upgrade: WebSocket\r\n"
504 "Connection: keep-alive,upgrade\r\n"
505 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
506 "Sec-WebSocket-Version: 13\r\n"
507 "\r\n"
508 );
11fdf7f2
TL
509 // no Host
510 check(error::no_host,
b32b8144
FG
511 "GET / HTTP/1.1\r\n"
512 "Upgrade: WebSocket\r\n"
513 "Connection: keep-alive,upgrade\r\n"
514 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
515 "Sec-WebSocket-Version: 13\r\n"
516 "\r\n"
517 );
11fdf7f2
TL
518 // no Connection
519 check(error::no_connection,
b32b8144
FG
520 "GET / HTTP/1.1\r\n"
521 "Host: localhost:80\r\n"
522 "Upgrade: WebSocket\r\n"
11fdf7f2 523 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
b32b8144
FG
524 "Sec-WebSocket-Version: 13\r\n"
525 "\r\n"
526 );
11fdf7f2
TL
527 // no Connection upgrade
528 check(error::no_connection_upgrade,
b32b8144
FG
529 "GET / HTTP/1.1\r\n"
530 "Host: localhost:80\r\n"
531 "Upgrade: WebSocket\r\n"
11fdf7f2 532 "Connection: keep-alive\r\n"
b32b8144 533 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
11fdf7f2 534 "Sec-WebSocket-Version: 13\r\n"
b32b8144
FG
535 "\r\n"
536 );
11fdf7f2
TL
537 // no Upgrade
538 check(error::no_upgrade,
b32b8144
FG
539 "GET / HTTP/1.1\r\n"
540 "Host: localhost:80\r\n"
11fdf7f2 541 "Connection: upgrade\r\n"
b32b8144 542 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
11fdf7f2 543 "Sec-WebSocket-Version: 13\r\n"
b32b8144
FG
544 "\r\n"
545 );
11fdf7f2
TL
546 // no Upgrade websocket
547 check(error::no_upgrade_websocket,
b32b8144
FG
548 "GET / HTTP/1.1\r\n"
549 "Host: localhost:80\r\n"
550 "Upgrade: HTTP/2\r\n"
551 "Connection: upgrade\r\n"
552 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
553 "Sec-WebSocket-Version: 13\r\n"
554 "\r\n"
555 );
11fdf7f2
TL
556 // no Sec-WebSocket-Key
557 check(error::no_sec_key,
b32b8144
FG
558 "GET / HTTP/1.1\r\n"
559 "Host: localhost:80\r\n"
560 "Upgrade: WebSocket\r\n"
11fdf7f2 561 "Connection: keep-alive,upgrade\r\n"
b32b8144
FG
562 "Sec-WebSocket-Version: 13\r\n"
563 "\r\n"
564 );
11fdf7f2
TL
565 // bad Sec-WebSocket-Key
566 check(error::bad_sec_key,
b32b8144
FG
567 "GET / HTTP/1.1\r\n"
568 "Host: localhost:80\r\n"
569 "Upgrade: WebSocket\r\n"
570 "Connection: upgrade\r\n"
571 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQdGhlIHNhbXBsZSBub25jZQ==\r\n"
572 "Sec-WebSocket-Version: 13\r\n"
573 "\r\n"
574 );
11fdf7f2
TL
575 // no Sec-WebSocket-Version
576 check(error::no_sec_version,
b32b8144
FG
577 "GET / HTTP/1.1\r\n"
578 "Host: localhost:80\r\n"
579 "Upgrade: WebSocket\r\n"
11fdf7f2 580 "Connection: keep-alive,upgrade\r\n"
b32b8144 581 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
b32b8144
FG
582 "\r\n"
583 );
11fdf7f2
TL
584 // bad Sec-WebSocket-Version
585 check(error::bad_sec_version,
586 "GET / HTTP/1.1\r\n"
587 "Host: localhost:80\r\n"
588 "Upgrade: WebSocket\r\n"
589 "Connection: keep-alive,upgrade\r\n"
590 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
591 "Sec-WebSocket-Version: 1\r\n"
592 "\r\n"
593 );
594 // bad Sec-WebSocket-Version
595 check(error::bad_sec_version,
b32b8144
FG
596 "GET / HTTP/1.1\r\n"
597 "Host: localhost:80\r\n"
598 "Upgrade: WebSocket\r\n"
599 "Connection: upgrade\r\n"
600 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
11fdf7f2 601 "Sec-WebSocket-Version: 12\r\n"
b32b8144
FG
602 "\r\n"
603 );
604 // valid request
605 check({},
606 "GET / HTTP/1.1\r\n"
607 "Host: localhost:80\r\n"
608 "Upgrade: WebSocket\r\n"
609 "Connection: upgrade\r\n"
610 "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n"
611 "Sec-WebSocket-Version: 13\r\n"
612 "\r\n"
613 );
614 }
615
11fdf7f2
TL
616 void
617 testMoveOnly()
618 {
619 boost::asio::io_context ioc;
620 stream<test::stream> ws{ioc};
621 ws.async_accept(move_only_handler{});
622 }
623
624 struct copyable_handler
625 {
626 template<class... Args>
627 void
628 operator()(Args&&...) const
629 {
630 }
631 };
632
633 void
634 testAsioHandlerInvoke()
635 {
636 // make sure things compile, also can set a
637 // breakpoint in asio_handler_invoke to make sure
638 // it is instantiated.
639 boost::asio::io_context ioc;
640 boost::asio::io_service::strand s{ioc};
641 stream<test::stream> ws{ioc};
642 ws.async_accept(s.wrap(copyable_handler{}));
643 }
644
b32b8144
FG
645 void
646 run() override
647 {
648 testAccept();
11fdf7f2
TL
649 testMoveOnly();
650 testAsioHandlerInvoke();
b32b8144
FG
651 }
652};
653
654BEAST_DEFINE_TESTSUITE(beast,websocket,accept);
655
656} // websocket
657} // beast
658} // boost