2 // Copyright (w) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
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)
7 // Official repository: https://github.com/boostorg/beast
10 // Test that header file is self-contained.
11 #include <boost/beast/websocket/stream.hpp>
15 #include <boost/asio/write.hpp>
17 #include <boost/beast/core/buffers_to_string.hpp>
23 class read_test
: public websocket_test_suite
37 fail("", __FILE__
, __LINE__
);
39 catch(system_error
const& se
)
41 if(se
.code() != error::closed
)
44 ws
.reason().code
== code
);
59 fail("", __FILE__
, __LINE__
);
61 catch(system_error
const& se
)
70 doTestRead(Wrap
const& w
)
72 using boost::asio::buffer
;
74 permessage_deflate pmd
;
75 pmd
.client_enable
= false;
76 pmd
.server_enable
= false;
81 stream
<test::stream
> ws
{ioc_
};
82 ws
.next_layer().connect(es
.stream());
83 ws
.handshake("localhost", "/");
89 fail("", __FILE__
, __LINE__
);
91 catch(system_error
const& se
)
94 se
.code() == boost::asio::error::operation_aborted
,
99 // empty, fragmented message
100 doTest(pmd
, [&](ws_type
& ws
)
102 ws
.next_layer().append(
104 "\x01\x00" "\x80\x00", 4));
107 BEAST_EXPECT(b
.size() == 0);
111 // triggers "fill the read buffer first"
112 doTest(pmd
, [&](ws_type
& ws
)
114 w
.write_raw(ws
, sbuf(
115 "\x01\x81\xff\xff\xff\xff"));
116 w
.write_raw(ws
, sbuf(
118 w
.write_raw(ws
, sbuf(
119 "\x80\x81\xff\xff\xff\xff\xd5"));
122 BEAST_EXPECT(to_string(b
.data()) == "**");
126 doTest(pmd
, [&](ws_type
& ws
)
128 put(ws
.next_layer().buffer(), cbuf(
130 bool invoked
= false;
131 auto cb
= [&](frame_type kind
, string_view
)
133 BEAST_EXPECT(! invoked
);
134 BEAST_EXPECT(kind
== frame_type::ping
);
137 ws
.control_callback(cb
);
138 w
.write(ws
, sbuf("Hello"));
141 BEAST_EXPECT(invoked
);
142 BEAST_EXPECT(ws
.got_text());
143 BEAST_EXPECT(to_string(b
.data()) == "Hello");
147 doTest(pmd
, [&](ws_type
& ws
)
149 put(ws
.next_layer().buffer(), cbuf(
151 bool invoked
= false;
152 auto cb
= [&](frame_type kind
, string_view
)
154 BEAST_EXPECT(! invoked
);
155 BEAST_EXPECT(kind
== frame_type::close
);
158 ws
.control_callback(cb
);
159 w
.write(ws
, sbuf("Hello"));
160 doReadTest(w
, ws
, close_code::none
);
164 doTest(pmd
, [&](ws_type
& ws
)
168 [&](frame_type kind
, string_view s
)
170 BEAST_EXPECT(kind
== frame_type::pong
);
171 BEAST_EXPECT(! once
);
173 BEAST_EXPECT(s
== "");
175 ws
.control_callback(cb
);
178 w
.write(ws
, sbuf("Hello"));
182 BEAST_EXPECT(ws
.got_binary());
183 BEAST_EXPECT(to_string(b
.data()) == "Hello");
186 // ping then fragmented message
187 doTest(pmd
, [&](ws_type
& ws
)
191 [&](frame_type kind
, string_view s
)
193 BEAST_EXPECT(kind
== frame_type::pong
);
194 BEAST_EXPECT(! once
);
196 BEAST_EXPECT(s
== "payload");
198 ws
.control_callback(cb
);
200 w
.write_some(ws
, false, sbuf("Hello, "));
201 w
.write_some(ws
, false, sbuf(""));
202 w
.write_some(ws
, true, sbuf("World!"));
206 BEAST_EXPECT(to_string(b
.data()) == "Hello, World!");
209 // masked message, big
210 doStreamLoop([&](test::stream
& ts
)
212 echo_server es
{log
, kind::async_client
};
214 ws
.next_layer().connect(es
.stream());
216 es
.async_handshake();
220 std::string
const s(2000, '*');
221 ws
.auto_fragment(false);
223 w
.write(ws
, buffer(s
));
226 BEAST_EXPECT(ws
.got_text());
227 BEAST_EXPECT(to_string(b
.data()) == s
);
228 ws
.next_layer().close();
238 doFailLoop([&](test::fail_counter
& fc
)
240 echo_server es
{log
, kind::async
};
241 boost::asio::io_context ioc
;
242 stream
<test::stream
> ws
{ioc
, fc
};
243 ws
.next_layer().connect(es
.stream());
244 ws
.handshake("localhost", "/");
245 // Cause close to be received
247 std::size_t count
= 0;
250 [&](error_code ec
, std::size_t)
253 if(ec
!= error::closed
)
254 BOOST_THROW_EXCEPTION(
258 BEAST_EXPECT(count
== 1);
262 doTest(pmd
, [&](ws_type
& ws
)
267 boost::asio::error::operation_aborted
);
271 doTest(pmd
, [&](ws_type
& ws
)
273 std::string
const s
= "Hello, world!";
274 ws
.auto_fragment(false);
276 w
.write(ws
, buffer(s
));
281 fail("", __FILE__
, __LINE__
);
283 catch(system_error
const& se
)
285 if(se
.code() != error::buffer_overflow
)
291 doTest(pmd
, [&](ws_type
& ws
)
293 auto const s
= std::string(2000, '*') +
296 w
.write(ws
, buffer(s
));
297 doReadTest(w
, ws
, close_code::bad_payload
);
300 // invalid fixed frame header
301 doTest(pmd
, [&](ws_type
& ws
)
303 w
.write_raw(ws
, cbuf(
304 0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
305 doReadTest(w
, ws
, close_code::protocol_error
);
309 doTest(pmd
, [&](ws_type
& ws
)
311 put(ws
.next_layer().buffer(), cbuf(
312 0x88, 0x02, 0x03, 0xed));
313 doFailTest(w
, ws
, error::failed
);
316 // message size above 2^64
317 doTest(pmd
, [&](ws_type
& ws
)
319 w
.write_some(ws
, false, sbuf("*"));
320 w
.write_raw(ws
, cbuf(
321 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
322 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
323 doReadTest(w
, ws
, close_code::too_big
);
326 // message size exceeds max
327 doTest(pmd
, [&](ws_type
& ws
)
329 ws
.read_message_max(1);
330 w
.write(ws
, sbuf("**"));
331 doFailTest(w
, ws
, error::failed
);
335 doTest(pmd
, [&](ws_type
& ws
)
337 put(ws
.next_layer().buffer(), cbuf(
338 0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
339 doFailTest(w
, ws
, error::failed
);
343 doTest(pmd
, [&](ws_type
& ws
)
345 std::string
const s
=
346 "Hello, world!" "\xc0";
347 w
.write(ws
, buffer(s
));
348 doReadTest(w
, ws
, close_code::bad_payload
);
351 // incomplete utf8, big
352 doTest(pmd
, [&](ws_type
& ws
)
354 std::string
const s
=
356 std::string(4000, '*') + "\xc0";
357 ws
.next_layer().append(s
);
363 b
.commit(w
.read_some(ws
, b
.prepare(4000)));
365 while(! ws
.is_message_done());
367 catch(system_error
const& se
)
369 if(se
.code() != error::failed
)
377 [&](error_code ev
, string_view s
)
380 stream
<test::stream
> ws
{ioc_
};
381 ws
.next_layer().connect(es
.stream());
382 w
.handshake(ws
, "localhost", "/");
383 ws
.next_layer().append(s
);
389 fail("", __FILE__
, __LINE__
);
391 catch(system_error
const& se
)
393 BEAST_EXPECTS(se
.code() == ev
,
394 se
.code().message());
396 ws
.next_layer().close();
403 // invalid close code 1005
409 "\x88\x06\xfc\x15\x0f\xd7\x73\x43");
413 "\x88\x06\xfc\x15utf8");
417 // permessage-deflate
420 pmd
.client_enable
= true;
421 pmd
.server_enable
= true;
422 pmd
.client_max_window_bits
= 9;
423 pmd
.server_max_window_bits
= 9;
426 // message size limit
427 doTest(pmd
, [&](ws_type
& ws
)
429 std::string
const s
= std::string(128, '*');
430 w
.write(ws
, buffer(s
));
431 ws
.read_message_max(32);
432 doFailTest(w
, ws
, error::failed
);
435 // invalid inflate block
436 doTest(pmd
, [&](ws_type
& ws
)
438 auto const& s
= random_string();
440 ws
.next_layer().append(
441 "\xc2\x40" + s
.substr(0, 64));
447 catch(system_error
const& se
)
449 if(se
.code() == test::error::fail_error
)
451 BEAST_EXPECTS(se
.code().category() ==
452 zlib::detail::get_error_category(),
453 se
.code().message());
461 // no_context_takeover
462 pmd
.server_no_context_takeover
= true;
463 doTest(pmd
, [&](ws_type
& ws
)
465 auto const& s
= random_string();
467 w
.write(ws
, buffer(s
));
470 BEAST_EXPECT(to_string(b
.data()) == s
);
472 pmd
.client_no_context_takeover
= false;
478 permessage_deflate
const& pmd
,
481 using boost::asio::buffer
;
484 doTest(pmd
, [&](ws_type
& ws
)
486 std::string
const s
= "Hello, world!";
487 ws
.auto_fragment(false);
489 w
.write(ws
, buffer(s
));
492 BEAST_EXPECT(ws
.got_text());
493 BEAST_EXPECT(to_string(b
.data()) == s
);
497 doStreamLoop([&](test::stream
& ts
)
499 echo_server es
{log
, kind::async_client
};
501 ws
.next_layer().connect(es
.stream());
503 es
.async_handshake();
507 std::string
const s
= "Hello, world!";
508 ws
.auto_fragment(false);
510 w
.write(ws
, buffer(s
));
513 BEAST_EXPECT(ws
.got_text());
514 BEAST_EXPECT(to_string(b
.data()) == s
);
515 ws
.next_layer().close();
525 doTest(pmd
, [&](ws_type
& ws
)
527 std::string
const s
= "";
529 w
.write(ws
, buffer(s
));
532 BEAST_EXPECT(ws
.got_text());
533 BEAST_EXPECT(to_string(b
.data()) == s
);
537 doTest(pmd
, [&](ws_type
& ws
)
539 std::string
const s
= "Hello";
540 w
.write(ws
, buffer(s
));
542 auto const bytes_written
=
543 w
.read_some(ws
, buffer(buf
, sizeof(buf
)));
544 BEAST_EXPECT(bytes_written
> 0);
546 string_view(buf
, 3).substr(0, bytes_written
) ==
547 s
.substr(0, bytes_written
));
550 // partial message, dynamic buffer
551 doTest(pmd
, [&](ws_type
& ws
)
553 std::string
const s
= "Hello, world!";
554 w
.write(ws
, buffer(s
));
557 w
.read_some(ws
, 3, b
);
558 BEAST_EXPECT(bytes_written
> 0);
559 BEAST_EXPECT(to_string(b
.data()) ==
560 s
.substr(0, b
.size()));
561 w
.read_some(ws
, 256, b
);
562 BEAST_EXPECT(to_string(b
.data()) == s
);
566 doTest(pmd
, [&](ws_type
& ws
)
568 auto const& s
= random_string();
570 w
.write(ws
, buffer(s
));
573 BEAST_EXPECT(to_string(b
.data()) == s
);
577 doTest(pmd
, [&](ws_type
& ws
)
579 std::string
const s
= "\x03\xea\xf0\x28\x8c\xbc";
580 ws
.auto_fragment(false);
582 w
.write(ws
, buffer(s
));
583 doReadTest(w
, ws
, close_code::bad_payload
);
590 using boost::asio::buffer
;
592 doTestRead(SyncClient
{});
593 yield_to([&](yield_context yield
)
595 doTestRead(AsyncClient
{yield
});
598 permessage_deflate pmd
;
599 pmd
.client_enable
= false;
600 pmd
.server_enable
= false;
601 doTestRead(pmd
, SyncClient
{});
602 yield_to([&](yield_context yield
)
604 doTestRead(pmd
, AsyncClient
{yield
});
607 pmd
.client_enable
= true;
608 pmd
.server_enable
= true;
609 pmd
.client_max_window_bits
= 9;
610 pmd
.server_max_window_bits
= 9;
612 doTestRead(pmd
, SyncClient
{});
613 yield_to([&](yield_context yield
)
615 doTestRead(pmd
, AsyncClient
{yield
});
621 [&](error_code ev
, string_view s
)
624 stream
<test::stream
> ws
{ioc_
};
625 ws
.next_layer().connect(es
.stream());
626 ws
.handshake("localhost", "/");
627 ws
.next_layer().append(s
);
631 BEAST_EXPECTS(ec
== ev
, ec
.message());
632 ws
.next_layer().close();
639 // invalid close code 1005
645 "\x88\x06\xfc\x15\x0f\xd7\x73\x43");
649 "\x88\x06\xfc\x15utf8");
656 using boost::asio::buffer
;
658 // suspend on read block
659 doFailLoop([&](test::fail_counter
& fc
)
662 boost::asio::io_context ioc
;
663 stream
<test::stream
> ws
{ioc
, fc
};
664 ws
.next_layer().connect(es
.stream());
665 ws
.handshake("localhost", "/");
666 std::size_t count
= 0;
671 BOOST_THROW_EXCEPTION(
673 BEAST_EXPECT(++count
== 1);
675 while(! ws
.rd_block_
)
679 [&](error_code ec
, std::size_t)
681 if(ec
!= boost::asio::error::operation_aborted
)
682 BOOST_THROW_EXCEPTION(
684 BEAST_EXPECT(++count
== 2);
687 BEAST_EXPECT(count
== 2);
691 // suspend on release read block
692 doFailLoop([&](test::fail_counter
& fc
)
694 //log << "fc.count()==" << fc.count() << std::endl;
696 boost::asio::io_context ioc
;
697 stream
<test::stream
> ws
{ioc
, fc
};
698 ws
.next_layer().connect(es
.stream());
699 ws
.handshake("localhost", "/");
700 std::size_t count
= 0;
703 [&](error_code ec
, std::size_t)
705 if(ec
!= boost::asio::error::operation_aborted
)
706 BOOST_THROW_EXCEPTION(
708 BEAST_EXPECT(++count
== 2);
710 BOOST_ASSERT(ws
.rd_block_
);
715 BOOST_THROW_EXCEPTION(
717 BEAST_EXPECT(++count
== 1);
720 BEAST_EXPECT(count
== 2);
724 // suspend on write pong
725 doFailLoop([&](test::fail_counter
& fc
)
728 boost::asio::io_context ioc
;
729 stream
<test::stream
> ws
{ioc
, fc
};
730 ws
.next_layer().connect(es
.stream());
731 ws
.handshake("localhost", "/");
733 ws
.next_layer().append(string_view(
735 std::size_t count
= 0;
736 std::string
const s
= "Hello, world";
739 [&](error_code ec
, std::size_t)
742 BOOST_THROW_EXCEPTION(
744 BEAST_EXPECT(to_string(b
.data()) == s
);
747 BEAST_EXPECT(ws
.rd_block_
);
748 ws
.async_write(buffer(s
),
749 [&](error_code ec
, std::size_t n
)
752 BOOST_THROW_EXCEPTION(
754 BEAST_EXPECT(n
== s
.size());
757 BEAST_EXPECT(ws
.wr_block_
);
759 BEAST_EXPECT(count
== 2);
762 // Ignore ping when closing
763 doFailLoop([&](test::fail_counter
& fc
)
766 boost::asio::io_context ioc
;
767 stream
<test::stream
> ws
{ioc
, fc
};
768 ws
.next_layer().connect(es
.stream());
769 ws
.handshake("localhost", "/");
770 std::size_t count
= 0;
771 // insert fragmented message with
772 // a ping in between the frames.
773 ws
.next_layer().append(string_view(
779 [&](error_code ec
, std::size_t)
782 BOOST_THROW_EXCEPTION(
784 BEAST_EXPECT(to_string(b
.data()) == "**");
785 BEAST_EXPECT(++count
== 1);
788 [&](error_code ec
, std::size_t)
790 if(ec
!= boost::asio::error::operation_aborted
)
791 BOOST_THROW_EXCEPTION(
793 BEAST_EXPECT(++count
== 3);
796 BEAST_EXPECT(ws
.rd_block_
);
801 BOOST_THROW_EXCEPTION(
803 BEAST_EXPECT(++count
== 2);
805 BEAST_EXPECT(ws
.wr_block_
);
807 BEAST_EXPECT(count
== 3);
810 // See if we are already closing
811 doFailLoop([&](test::fail_counter
& fc
)
814 boost::asio::io_context ioc
;
815 stream
<test::stream
> ws
{ioc
, fc
};
816 ws
.next_layer().connect(es
.stream());
817 ws
.handshake("localhost", "/");
818 std::size_t count
= 0;
819 // insert fragmented message with
820 // a close in between the frames.
821 ws
.next_layer().append(string_view(
827 [&](error_code ec
, std::size_t)
829 if(ec
!= boost::asio::error::operation_aborted
)
830 BOOST_THROW_EXCEPTION(
832 BEAST_EXPECT(++count
== 2);
834 BEAST_EXPECT(ws
.rd_block_
);
839 BOOST_THROW_EXCEPTION(
841 BEAST_EXPECT(++count
== 1);
843 BEAST_EXPECT(ws
.wr_block_
);
845 BEAST_EXPECT(count
== 2);
857 boost::asio::io_context ioc
;
858 stream
<test::stream
> ws
{ioc
};
859 ws
.next_layer().connect(es
.stream());
860 ws
.handshake("localhost", "/");
861 ws
.next_layer().append(s
);
868 // chopped frame header
871 boost::asio::io_context ioc
;
872 stream
<test::stream
> ws
{ioc
};
873 ws
.next_layer().connect(es
.stream());
874 ws
.handshake("localhost", "/");
875 ws
.next_layer().append(
877 std::size_t count
= 0;
878 std::string
const s(257, '*');
882 [&](error_code ec
, std::size_t)
885 BEAST_EXPECTS(! ec
, ec
.message());
886 BEAST_EXPECT(to_string(b
.data()) == s
);
889 es
.stream().write_some(
890 boost::asio::buffer("\x01" + s
));
892 BEAST_EXPECT(count
== 1);
895 // new data frame when continuation expected
896 bad("\x01\x01*" "\x81\x01*");
898 // reserved bits not cleared
903 // continuation without an active message
906 // reserved bits not cleared (cont)
907 bad("\x01\x01*" "\xb0\x01*");
908 bad("\x01\x01*" "\xc0\x01*");
909 bad("\x01\x01*" "\xd0\x01*");
914 // fragmented control message
917 // invalid length for control message
918 bad("\x89\x7e\x01\x01");
920 // reserved bits not cleared (control)
925 // unmasked frame from client
927 echo_server es
{log
, kind::async_client
};
928 boost::asio::io_context ioc
;
929 stream
<test::stream
> ws
{ioc
};
930 ws
.next_layer().connect(es
.stream());
931 es
.async_handshake();
933 ws
.next_layer().append(
941 // masked frame from server
942 bad("\x81\x80\xff\xff\xff\xff");
944 // chopped control frame payload
947 boost::asio::io_context ioc
;
948 stream
<test::stream
> ws
{ioc
};
949 ws
.next_layer().connect(es
.stream());
950 ws
.handshake("localhost", "/");
951 ws
.next_layer().append(
953 std::size_t count
= 0;
957 [&](error_code ec
, std::size_t)
960 BEAST_EXPECTS(! ec
, ec
.message());
961 BEAST_EXPECT(to_string(b
.data()) == "**");
964 es
.stream().write_some(
968 BEAST_EXPECT(count
== 1);
971 // length not canonical
972 bad(string_view("\x81\x7e\x00\x7d", 4));
973 bad(string_view("\x81\x7f\x00\x00\x00\x00\x00\x00\xff\xff", 10));
982 void operator()(error_code
, std::size_t) {}
986 stream
<test::stream
> ws
{ioc_
};
987 stream
<test::stream
>::read_some_op
<
988 boost::asio::mutable_buffer
,
989 handler
> op
{handler
{}, ws
,
990 boost::asio::mutable_buffer
{
992 using boost::asio::asio_handler_is_continuation
;
993 asio_handler_is_continuation(&op
);
999 void operator()(error_code
, std::size_t) {}
1003 stream
<test::stream
> ws
{ioc_
};
1004 stream
<test::stream
>::read_op
<
1005 multi_buffer
, handler
> op
{
1006 handler
{}, ws
, b
, 32, true};
1007 using boost::asio::asio_handler_is_continuation
;
1008 asio_handler_is_continuation(&op
);
1016 for(std::size_t i
= 0; i
< 100; ++i
)
1018 echo_server es
{log
, kind::async
};
1019 boost::asio::io_context ioc
;
1020 stream
<test::stream
> ws
{ioc
};
1021 ws
.next_layer().connect(es
.stream());
1022 ws
.handshake("localhost", "/");
1023 // too-big message frame indicates payload of 2^64-1
1024 boost::asio::write(ws
.next_layer(), sbuf(
1025 "\x81\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"));
1029 BEAST_EXPECT(ec
== error::closed
);
1030 BEAST_EXPECT(ws
.reason().code
== 1009);
1037 echo_server es
{log
};
1038 boost::asio::io_context ioc
;
1039 stream
<test::stream
> ws
{ioc
};
1040 ws
.next_layer().connect(es
.stream());
1041 ws
.handshake("localhost", "/");
1042 ws
.write(sbuf("Hello, world!"));
1044 boost::asio::mutable_buffer b
{buf
, 0};
1045 auto const n
= ws
.read_some(b
);
1046 BEAST_EXPECT(n
== 0);
1049 /* Bishop Fox Hybrid Assessment issue 1
1051 Happens with permessage-deflate enabled and a
1052 compressed frame with the FIN bit set ends with an
1058 permessage_deflate pmd
;
1059 pmd
.client_enable
= true;
1060 pmd
.server_enable
= true;
1065 echo_server es
{log
};
1066 boost::asio::io_context ioc
;
1067 stream
<test::stream
> ws
{ioc
};
1069 ws
.next_layer().connect(es
.stream());
1070 ws
.handshake("localhost", "/");
1071 // invalid 1-byte deflate block in frame
1072 boost::asio::write(ws
.next_layer(), sbuf(
1073 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
1077 boost::asio::io_context ioc
;
1078 stream
<test::stream
> wsc
{ioc
};
1079 stream
<test::stream
> wss
{ioc
};
1080 wsc
.set_option(pmd
);
1081 wss
.set_option(pmd
);
1082 wsc
.next_layer().connect(wss
.next_layer());
1083 wsc
.async_handshake(
1084 "localhost", "/", [](error_code
){});
1085 wss
.async_accept([](error_code
){});
1088 BEAST_EXPECT(wsc
.is_open());
1089 BEAST_EXPECT(wss
.is_open());
1090 // invalid 1-byte deflate block in frame
1091 boost::asio::write(wsc
.next_layer(), sbuf(
1092 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
1096 BEAST_EXPECTS(ec
== zlib::error::end_of_stream
, ec
.message());
1102 echo_server es
{log
, kind::async
};
1103 boost::asio::io_context ioc
;
1104 stream
<test::stream
> ws
{ioc
};
1106 ws
.next_layer().connect(es
.stream());
1107 ws
.handshake("localhost", "/");
1108 // invalid 1-byte deflate block in frame
1109 boost::asio::write(ws
.next_layer(), sbuf(
1110 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
1114 boost::asio::io_context ioc
;
1115 stream
<test::stream
> wsc
{ioc
};
1116 stream
<test::stream
> wss
{ioc
};
1117 wsc
.set_option(pmd
);
1118 wss
.set_option(pmd
);
1119 wsc
.next_layer().connect(wss
.next_layer());
1120 wsc
.async_handshake(
1121 "localhost", "/", [](error_code
){});
1122 wss
.async_accept([](error_code
){});
1125 BEAST_EXPECT(wsc
.is_open());
1126 BEAST_EXPECT(wss
.is_open());
1127 // invalid 1-byte deflate block in frame
1128 boost::asio::write(wsc
.next_layer(), sbuf(
1129 "\xc1\x81\x3a\xa1\x74\x3b\x49"));
1133 [&ec
](error_code ec_
, std::size_t){ ec
= ec_
; });
1135 BEAST_EXPECTS(ec
== zlib::error::end_of_stream
, ec
.message());
1139 /* Bishop Fox Hybrid Assessment issue 2
1141 Happens with permessage-deflate enabled,
1142 and a deflate block with the BFINAL bit set
1143 is encountered in a compressed payload.
1148 permessage_deflate pmd
;
1149 pmd
.client_enable
= true;
1150 pmd
.server_enable
= true;
1154 boost::asio::io_context ioc
;
1155 stream
<test::stream
> wsc
{ioc
};
1156 stream
<test::stream
> wss
{ioc
};
1157 wsc
.set_option(pmd
);
1158 wss
.set_option(pmd
);
1159 wsc
.next_layer().connect(wss
.next_layer());
1160 wsc
.async_handshake(
1161 "localhost", "/", [](error_code
){});
1162 wss
.async_accept([](error_code
){});
1165 BEAST_EXPECT(wsc
.is_open());
1166 BEAST_EXPECT(wss
.is_open());
1167 // contains a deflate block with BFINAL set
1168 boost::asio::write(wsc
.next_layer(), sbuf(
1169 "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e"
1170 "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e"
1171 "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b"
1172 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1173 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
1174 "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4"
1175 "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e"
1176 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1177 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
1178 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1179 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e"
1180 "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1181 "\xcc\x3e\xd1\xe4\xcc\x3e"));
1185 BEAST_EXPECTS(ec
== zlib::error::end_of_stream
, ec
.message());
1190 boost::asio::io_context ioc
;
1191 stream
<test::stream
> wsc
{ioc
};
1192 stream
<test::stream
> wss
{ioc
};
1193 wsc
.set_option(pmd
);
1194 wss
.set_option(pmd
);
1195 wsc
.next_layer().connect(wss
.next_layer());
1196 wsc
.async_handshake(
1197 "localhost", "/", [](error_code
){});
1198 wss
.async_accept([](error_code
){});
1201 BEAST_EXPECT(wsc
.is_open());
1202 BEAST_EXPECT(wss
.is_open());
1203 // contains a deflate block with BFINAL set
1204 boost::asio::write(wsc
.next_layer(), sbuf(
1205 "\xc1\xf8\xd1\xe4\xcc\x3e\xda\xe4\xcc\x3e"
1206 "\x2b\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\x1e"
1207 "\x36\x3e\x35\xae\x4f\x54\x18\xae\x4f\x7b"
1208 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1209 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
1210 "\xd1\x1e\x36\xc4\x2b\x1e\x36\xc4\x2b\xe4"
1211 "\x28\x74\x52\x8e\x05\x74\x52\xa1\xcc\x3e"
1212 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1213 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e"
1214 "\xd1\xe4\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1215 "\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4\x36\x3e"
1216 "\xd1\xec\xcc\x3e\xd1\xe4\xcc\x3e\xd1\xe4"
1217 "\xcc\x3e\xd1\xe4\xcc\x3e"));
1221 [&ec
](error_code ec_
, std::size_t){ ec
= ec_
; });
1223 BEAST_EXPECTS(ec
== zlib::error::end_of_stream
, ec
.message());
1241 BEAST_DEFINE_TESTSUITE(beast
,websocket
,read
);