]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/beast/test/beast/websocket/read3.cpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / libs / beast / test / beast / websocket / read3.cpp
1 //
2 // Copyright (c) 2016-2019 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 #include <boost/asio/buffer.hpp>
16 #include <boost/asio/io_context.hpp>
17 #include <boost/asio/strand.hpp>
18 #include <boost/asio/write.hpp>
19
20 namespace boost {
21 namespace beast {
22 namespace websocket {
23
24 class read3_test : public websocket_test_suite
25 {
26 public:
27 void
28 testSuspend()
29 {
30 // suspend on read block
31 doFailLoop([&](test::fail_count& fc)
32 {
33 echo_server es{log};
34 net::io_context ioc;
35 stream<test::stream> ws{ioc, fc};
36 ws.next_layer().connect(es.stream());
37 ws.handshake("localhost", "/");
38 std::size_t count = 0;
39 ws.async_close({},
40 [&](error_code ec)
41 {
42 if(ec)
43 BOOST_THROW_EXCEPTION(
44 system_error{ec});
45 BEAST_EXPECT(++count == 1);
46 });
47 while(! ws.impl_->rd_block.is_locked())
48 ioc.run_one();
49 multi_buffer b;
50 ws.async_read(b,
51 [&](error_code ec, std::size_t)
52 {
53 if(ec != net::error::operation_aborted)
54 BOOST_THROW_EXCEPTION(
55 system_error{ec});
56 BEAST_EXPECT(++count == 2);
57 });
58 ioc.run();
59 BEAST_EXPECT(count == 2);
60 });
61
62 // suspend on release read block
63 doFailLoop([&](test::fail_count& fc)
64 {
65 echo_server es{log};
66 net::io_context ioc;
67 stream<test::stream> ws{ioc, fc};
68 ws.next_layer().connect(es.stream());
69 ws.handshake("localhost", "/");
70 std::size_t count = 0;
71 multi_buffer b;
72 ws.async_read(b,
73 [&](error_code ec, std::size_t)
74 {
75 if(ec != net::error::operation_aborted)
76 BOOST_THROW_EXCEPTION(
77 system_error{ec});
78 BEAST_EXPECT(++count == 2);
79 });
80 BOOST_ASSERT(ws.impl_->rd_block.is_locked());
81 ws.async_close({},
82 [&](error_code ec)
83 {
84 if(ec)
85 BOOST_THROW_EXCEPTION(
86 system_error{ec});
87 BEAST_EXPECT(++count == 1);
88 });
89 ioc.run();
90 BEAST_EXPECT(count == 2);
91 });
92
93 // suspend on write pong
94 doFailLoop([&](test::fail_count& fc)
95 {
96 echo_server es{log};
97 net::io_context ioc;
98 stream<test::stream> ws{ioc, fc};
99 ws.next_layer().connect(es.stream());
100 ws.handshake("localhost", "/");
101 // insert a ping
102 ws.next_layer().append(string_view(
103 "\x89\x00", 2));
104 std::size_t count = 0;
105 std::string const s = "Hello, world";
106 multi_buffer b;
107 ws.async_read(b,
108 [&](error_code ec, std::size_t)
109 {
110 if(ec)
111 BOOST_THROW_EXCEPTION(
112 system_error{ec});
113 BEAST_EXPECT(buffers_to_string(b.data()) == s);
114 ++count;
115 });
116 BEAST_EXPECT(ws.impl_->rd_block.is_locked());
117 ws.async_write(net::buffer(s),
118 [&](error_code ec, std::size_t n)
119 {
120 if(ec)
121 BOOST_THROW_EXCEPTION(
122 system_error{ec});
123 BEAST_EXPECT(n == s.size());
124 ++count;
125 });
126 BEAST_EXPECT(ws.impl_->wr_block.is_locked());
127 ioc.run();
128 BEAST_EXPECT(count == 2);
129 });
130
131 // Ignore ping when closing
132 doFailLoop([&](test::fail_count& fc)
133 {
134 echo_server es{log};
135 net::io_context ioc;
136 stream<test::stream> ws{ioc, fc};
137 ws.next_layer().connect(es.stream());
138 ws.handshake("localhost", "/");
139 std::size_t count = 0;
140 // insert fragmented message with
141 // a ping in between the frames.
142 ws.next_layer().append(string_view(
143 "\x01\x01*"
144 "\x89\x00"
145 "\x80\x01*", 8));
146 multi_buffer b;
147 ws.async_read(b,
148 [&](error_code ec, std::size_t)
149 {
150 if(ec)
151 BOOST_THROW_EXCEPTION(
152 system_error{ec});
153 BEAST_EXPECT(buffers_to_string(b.data()) == "**");
154 BEAST_EXPECT(++count == 1);
155 b.consume(b.size());
156 ws.async_read(b,
157 [&](error_code ec, std::size_t)
158 {
159 if(ec != net::error::operation_aborted)
160 BOOST_THROW_EXCEPTION(
161 system_error{ec});
162 BEAST_EXPECT(++count == 3);
163 });
164 });
165 BEAST_EXPECT(ws.impl_->rd_block.is_locked());
166 ws.async_close({},
167 [&](error_code ec)
168 {
169 if(ec)
170 BOOST_THROW_EXCEPTION(
171 system_error{ec});
172 BEAST_EXPECT(++count == 2);
173 });
174 BEAST_EXPECT(ws.impl_->wr_block.is_locked());
175 ioc.run();
176 BEAST_EXPECT(count == 3);
177 });
178
179 // See if we are already closing
180 doFailLoop([&](test::fail_count& fc)
181 {
182 echo_server es{log};
183 net::io_context ioc;
184 stream<test::stream> ws{ioc, fc};
185 ws.next_layer().connect(es.stream());
186 ws.handshake("localhost", "/");
187 std::size_t count = 0;
188 // insert fragmented message with
189 // a close in between the frames.
190 ws.next_layer().append(string_view(
191 "\x01\x01*"
192 "\x88\x00"
193 "\x80\x01*", 8));
194 multi_buffer b;
195 ws.async_read(b,
196 [&](error_code ec, std::size_t)
197 {
198 if(ec != net::error::operation_aborted)
199 BOOST_THROW_EXCEPTION(
200 system_error{ec});
201 BEAST_EXPECT(++count == 2);
202 });
203 BEAST_EXPECT(ws.impl_->rd_block.is_locked());
204 ws.async_close({},
205 [&](error_code ec)
206 {
207 if(ec)
208 BOOST_THROW_EXCEPTION(
209 system_error{ec});
210 BEAST_EXPECT(++count == 1);
211 });
212 BEAST_EXPECT(ws.impl_->wr_block.is_locked());
213 ioc.run();
214 BEAST_EXPECT(count == 2);
215 });
216 }
217
218 void
219 testParseFrame()
220 {
221 auto const bad =
222 [&](string_view s)
223 {
224 echo_server es{log};
225 net::io_context ioc;
226 stream<test::stream> ws{ioc};
227 ws.next_layer().connect(es.stream());
228 ws.handshake("localhost", "/");
229 ws.next_layer().append(s);
230 error_code ec;
231 multi_buffer b;
232 ws.read(b, ec);
233 BEAST_EXPECT(ec);
234 };
235
236 // chopped frame header
237 {
238 echo_server es{log};
239 net::io_context ioc;
240 stream<test::stream> ws{ioc};
241 ws.next_layer().connect(es.stream());
242 ws.handshake("localhost", "/");
243 ws.next_layer().append(
244 "\x81\x7e\x01");
245 std::size_t count = 0;
246 std::string const s(257, '*');
247 multi_buffer b;
248 ws.async_read(b,
249 [&](error_code ec, std::size_t)
250 {
251 ++count;
252 BEAST_EXPECTS(! ec, ec.message());
253 BEAST_EXPECT(buffers_to_string(b.data()) == s);
254 });
255 ioc.run_one();
256 es.stream().write_some(
257 net::buffer("\x01" + s));
258 ioc.run();
259 BEAST_EXPECT(count == 1);
260 }
261
262 // new data frame when continuation expected
263 bad("\x01\x01*" "\x81\x01*");
264
265 // reserved bits not cleared
266 bad("\xb1\x01*");
267 bad("\xc1\x01*");
268 bad("\xd1\x01*");
269
270 // continuation without an active message
271 bad("\x80\x01*");
272
273 // reserved bits not cleared (cont)
274 bad("\x01\x01*" "\xb0\x01*");
275 bad("\x01\x01*" "\xc0\x01*");
276 bad("\x01\x01*" "\xd0\x01*");
277
278 // reserved opcode
279 bad("\x83\x01*");
280
281 // fragmented control message
282 bad("\x09\x01*");
283
284 // invalid length for control message
285 bad("\x89\x7e\x01\x01");
286
287 // reserved bits not cleared (control)
288 bad("\xb9\x01*");
289 bad("\xc9\x01*");
290 bad("\xd9\x01*");
291
292 // unmasked frame from client
293 {
294 echo_server es{log, kind::async_client};
295 net::io_context ioc;
296 stream<test::stream> ws{ioc};
297 ws.next_layer().connect(es.stream());
298 es.async_handshake();
299 ws.accept();
300 ws.next_layer().append(
301 "\x81\x01*");
302 error_code ec;
303 multi_buffer b;
304 ws.read(b, ec);
305 BEAST_EXPECT(ec);
306 }
307
308 // masked frame from server
309 bad("\x81\x80\xff\xff\xff\xff");
310
311 // chopped control frame payload
312 {
313 echo_server es{log};
314 net::io_context ioc;
315 stream<test::stream> ws{ioc};
316 ws.next_layer().connect(es.stream());
317 ws.handshake("localhost", "/");
318 ws.next_layer().append(
319 "\x89\x02*");
320 std::size_t count = 0;
321 multi_buffer b;
322 ws.async_read(b,
323 [&](error_code ec, std::size_t)
324 {
325 ++count;
326 BEAST_EXPECTS(! ec, ec.message());
327 BEAST_EXPECT(buffers_to_string(b.data()) == "**");
328 });
329 ioc.run_one();
330 es.stream().write_some(
331 net::buffer(
332 "*" "\x81\x02**"));
333 ioc.run();
334 BEAST_EXPECT(count == 1);
335 }
336
337 // length not canonical
338 bad(string_view("\x81\x7e\x00\x7d", 4));
339 bad(string_view("\x81\x7f\x00\x00\x00\x00\x00\x00\xff\xff", 10));
340 }
341
342 void
343 testIssue802()
344 {
345 for(std::size_t i = 0; i < 100; ++i)
346 {
347 echo_server es{log, kind::async};
348 net::io_context ioc;
349 stream<test::stream> ws{ioc};
350 ws.next_layer().connect(es.stream());
351 ws.handshake("localhost", "/");
352 // too-big message frame indicates payload of 2^64-1
353 net::write(ws.next_layer(), sbuf(
354 "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"));
355 multi_buffer b;
356 error_code ec;
357 ws.read(b, ec);
358 BEAST_EXPECT(ec == error::closed);
359 BEAST_EXPECT(ws.reason().code == 1009);
360 }
361 }
362
363 void
364 testIssue807()
365 {
366 echo_server es{log};
367 net::io_context ioc;
368 stream<test::stream> ws{ioc};
369 ws.next_layer().connect(es.stream());
370 ws.handshake("localhost", "/");
371 ws.write(sbuf("Hello, world!"));
372 char buf[4];
373 net::mutable_buffer b{buf, 0};
374 auto const n = ws.read_some(b);
375 BEAST_EXPECT(n == 0);
376 }
377
378 /*
379 When the internal read buffer contains a control frame and
380 stream::async_read_some is called, it is possible for the control
381 callback to be invoked on the caller's stack instead of through
382 the executor associated with the final completion handler.
383 */
384 void
385 testIssue954()
386 {
387 echo_server es{log};
388 multi_buffer b;
389 net::io_context ioc;
390 stream<test::stream> ws{ioc};
391 ws.next_layer().connect(es.stream());
392 ws.handshake("localhost", "/");
393 // message followed by ping
394 ws.next_layer().append({
395 "\x81\x00"
396 "\x89\x00",
397 4});
398 bool called_cb = false;
399 bool called_handler = false;
400 ws.control_callback(
401 [&called_cb](frame_type, string_view)
402 {
403 called_cb = true;
404 });
405 ws.async_read(b,
406 [&](error_code, std::size_t)
407 {
408 called_handler = true;
409 });
410 BEAST_EXPECT(! called_cb);
411 BEAST_EXPECT(! called_handler);
412 ioc.run();
413 BEAST_EXPECT(! called_cb);
414 BEAST_EXPECT(called_handler);
415 ws.async_read(b,
416 [&](error_code, std::size_t)
417 {
418 });
419 BEAST_EXPECT(! called_cb);
420 }
421
422 /* Bishop Fox Hybrid Assessment issue 1
423
424 Happens with permessage-deflate enabled and a
425 compressed frame with the FIN bit set ends with an
426 invalid prefix.
427 */
428 void
429 testIssueBF1()
430 {
431 permessage_deflate pmd;
432 pmd.client_enable = true;
433 pmd.server_enable = true;
434
435 // read
436 #if 0
437 {
438 echo_server es{log};
439 net::io_context ioc;
440 stream<test::stream> ws{ioc};
441 ws.set_option(pmd);
442 ws.next_layer().connect(es.stream());
443 ws.handshake("localhost", "/");
444 // invalid 1-byte deflate block in frame
445 net::write(ws.next_layer(), sbuf(
446 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
447 }
448 #endif
449 {
450 net::io_context ioc;
451 stream<test::stream> wsc{ioc};
452 stream<test::stream> wss{ioc};
453 wsc.set_option(pmd);
454 wss.set_option(pmd);
455 wsc.next_layer().connect(wss.next_layer());
456 wsc.async_handshake(
457 "localhost", "/", [](error_code){});
458 wss.async_accept([](error_code){});
459 ioc.run();
460 ioc.restart();
461 BEAST_EXPECT(wsc.is_open());
462 BEAST_EXPECT(wss.is_open());
463 // invalid 1-byte deflate block in frame
464 net::write(wsc.next_layer(), sbuf(
465 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
466 error_code ec;
467 multi_buffer b;
468 wss.read(b, ec);
469 BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
470 }
471
472 // async read
473 #if 0
474 {
475 echo_server es{log, kind::async};
476 net::io_context ioc;
477 stream<test::stream> ws{ioc};
478 ws.set_option(pmd);
479 ws.next_layer().connect(es.stream());
480 ws.handshake("localhost", "/");
481 // invalid 1-byte deflate block in frame
482 net::write(ws.next_layer(), sbuf(
483 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
484 }
485 #endif
486 {
487 net::io_context ioc;
488 stream<test::stream> wsc{ioc};
489 stream<test::stream> wss{ioc};
490 wsc.set_option(pmd);
491 wss.set_option(pmd);
492 wsc.next_layer().connect(wss.next_layer());
493 wsc.async_handshake(
494 "localhost", "/", [](error_code){});
495 wss.async_accept([](error_code){});
496 ioc.run();
497 ioc.restart();
498 BEAST_EXPECT(wsc.is_open());
499 BEAST_EXPECT(wss.is_open());
500 // invalid 1-byte deflate block in frame
501 net::write(wsc.next_layer(), sbuf(
502 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
503 error_code ec;
504 flat_buffer b;
505 wss.async_read(b,
506 [&ec](error_code ec_, std::size_t){ ec = ec_; });
507 ioc.run();
508 BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
509 }
510 }
511
512 /* Bishop Fox Hybrid Assessment issue 2
513
514 Happens with permessage-deflate enabled,
515 and a deflate block with the BFINAL bit set
516 is encountered in a compressed payload.
517 */
518 void
519 testIssueBF2()
520 {
521 permessage_deflate pmd;
522 pmd.client_enable = true;
523 pmd.server_enable = true;
524
525 // read
526 {
527 net::io_context ioc;
528 stream<test::stream> wsc{ioc};
529 stream<test::stream> wss{ioc};
530 wsc.set_option(pmd);
531 wss.set_option(pmd);
532 wsc.next_layer().connect(wss.next_layer());
533 wsc.async_handshake(
534 "localhost", "/", [](error_code){});
535 wss.async_accept([](error_code){});
536 ioc.run();
537 ioc.restart();
538 BEAST_EXPECT(wsc.is_open());
539 BEAST_EXPECT(wss.is_open());
540 // contains a deflate block with BFINAL set
541 net::write(wsc.next_layer(), sbuf(
542 "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e"
543 "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e"
544 "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b"
545 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
546 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
547 "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4"
548 "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e"
549 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
550 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
551 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
552 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e"
553 "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
554 "\xcc\x3e\xd1\xe4\xcc\x3e"));
555 error_code ec;
556 flat_buffer b;
557 wss.read(b, ec);
558 BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
559 }
560
561 // async read
562 {
563 net::io_context ioc;
564 stream<test::stream> wsc{ioc};
565 stream<test::stream> wss{ioc};
566 wsc.set_option(pmd);
567 wss.set_option(pmd);
568 wsc.next_layer().connect(wss.next_layer());
569 wsc.async_handshake(
570 "localhost", "/", [](error_code){});
571 wss.async_accept([](error_code){});
572 ioc.run();
573 ioc.restart();
574 BEAST_EXPECT(wsc.is_open());
575 BEAST_EXPECT(wss.is_open());
576 // contains a deflate block with BFINAL set
577 net::write(wsc.next_layer(), sbuf(
578 "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e"
579 "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e"
580 "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b"
581 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
582 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
583 "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4"
584 "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e"
585 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
586 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
587 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
588 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e"
589 "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
590 "\xcc\x3e\xd1\xe4\xcc\x3e"));
591 error_code ec;
592 flat_buffer b;
593 wss.async_read(b,
594 [&ec](error_code ec_, std::size_t){ ec = ec_; });
595 ioc.run();
596 BEAST_EXPECTS(ec == zlib::error::end_of_stream, ec.message());
597 }
598 }
599
600 void
601 testMoveOnly()
602 {
603 net::io_context ioc;
604 stream<test::stream> ws{ioc};
605 ws.async_read_some(
606 net::mutable_buffer{},
607 move_only_handler{});
608 }
609
610 struct copyable_handler
611 {
612 template<class... Args>
613 void
614 operator()(Args&&...) const
615 {
616 }
617 };
618
619 void
620 testAsioHandlerInvoke()
621 {
622 // make sure things compile, also can set a
623 // breakpoint in asio_handler_invoke to make sure
624 // it is instantiated.
625 {
626 net::io_context ioc;
627 net::strand<
628 net::io_context::executor_type> s(
629 ioc.get_executor());
630 stream<test::stream> ws{ioc};
631 flat_buffer b;
632 ws.async_read(b, net::bind_executor(
633 s, copyable_handler{}));
634 }
635 }
636
637 void
638 run() override
639 {
640 testParseFrame();
641 testIssue802();
642 testIssue807();
643 testIssue954();
644 testIssueBF1();
645 testIssueBF2();
646 testMoveOnly();
647 testAsioHandlerInvoke();
648 }
649 };
650
651 BEAST_DEFINE_TESTSUITE(beast,websocket,read3);
652
653 } // websocket
654 } // beast
655 } // boost