2016-04-30 13:00:33 -04:00
|
|
|
//
|
2017-08-21 14:45:58 -07:00
|
|
|
// Copyright (w) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
2016-04-30 13:00:33 -04:00
|
|
|
//
|
|
|
|
|
// Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
|
|
|
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
|
//
|
2017-07-20 13:40:34 -07:00
|
|
|
// Official repository: https://github.com/boostorg/beast
|
|
|
|
|
//
|
2016-04-30 13:00:33 -04:00
|
|
|
|
|
|
|
|
// Test that header file is self-contained.
|
2017-07-20 13:40:34 -07:00
|
|
|
#include <boost/beast/websocket/stream.hpp>
|
2016-04-30 13:00:33 -04:00
|
|
|
|
2017-08-24 06:21:30 -07:00
|
|
|
#include "test.hpp"
|
2016-04-30 13:00:33 -04:00
|
|
|
|
2017-07-20 13:40:34 -07:00
|
|
|
namespace boost {
|
2016-04-30 13:00:33 -04:00
|
|
|
namespace beast {
|
|
|
|
|
namespace websocket {
|
|
|
|
|
|
2017-08-24 06:21:30 -07:00
|
|
|
class stream_test : public websocket_test_suite
|
2016-04-30 13:00:33 -04:00
|
|
|
{
|
|
|
|
|
public:
|
2017-08-22 18:08:56 -07:00
|
|
|
void
|
|
|
|
|
testOptions()
|
|
|
|
|
{
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream> ws(ios_);
|
2017-08-22 18:08:56 -07:00
|
|
|
ws.auto_fragment(true);
|
|
|
|
|
ws.write_buffer_size(2048);
|
|
|
|
|
ws.binary(false);
|
|
|
|
|
ws.read_message_max(1 * 1024 * 1024);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
ws.write_buffer_size(7);
|
|
|
|
|
fail();
|
|
|
|
|
}
|
|
|
|
|
catch(std::exception const&)
|
|
|
|
|
{
|
|
|
|
|
pass();
|
2016-05-04 17:27:50 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-08-01 20:15:07 -07:00
|
|
|
//--------------------------------------------------------------------------
|
2016-10-24 18:41:25 -04:00
|
|
|
|
2017-08-21 14:45:58 -07:00
|
|
|
template<class Wrap>
|
2016-10-24 18:41:25 -04:00
|
|
|
void
|
2017-08-22 18:08:56 -07:00
|
|
|
doTestStream(Wrap const& w,
|
2017-08-21 14:45:58 -07:00
|
|
|
permessage_deflate const& pmd)
|
2016-10-24 18:41:25 -04:00
|
|
|
{
|
|
|
|
|
using boost::asio::buffer;
|
2017-08-01 20:15:07 -07:00
|
|
|
|
|
|
|
|
// send empty message
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2016-10-24 18:41:25 -04:00
|
|
|
{
|
2017-08-01 20:15:07 -07:00
|
|
|
ws.text(true);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, boost::asio::null_buffers{});
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(ws.got_text());
|
|
|
|
|
BEAST_EXPECT(b.size() == 0);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// send message
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
ws.auto_fragment(false);
|
|
|
|
|
ws.binary(false);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, sbuf("Hello"));
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(ws.got_text());
|
|
|
|
|
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// read_some
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, sbuf("Hello"));
|
2017-08-01 20:15:07 -07:00
|
|
|
char buf[10];
|
|
|
|
|
auto const bytes_written =
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read_some(ws, buffer(buf, sizeof(buf)));
|
2017-08-12 15:03:39 -07:00
|
|
|
BEAST_EXPECT(bytes_written > 0);
|
|
|
|
|
buf[bytes_written] = 0;
|
|
|
|
|
BEAST_EXPECT(
|
|
|
|
|
string_view(buf).substr(0, bytes_written) ==
|
|
|
|
|
string_view("Hello").substr(0, bytes_written));
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// close, no payload
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.close(ws, {});
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// close with code
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.close(ws, close_code::going_away);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// send ping and message
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
bool once = false;
|
|
|
|
|
auto cb =
|
|
|
|
|
[&](frame_type kind, string_view s)
|
2016-10-24 18:41:25 -04:00
|
|
|
{
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(kind == frame_type::pong);
|
|
|
|
|
BEAST_EXPECT(! once);
|
|
|
|
|
once = true;
|
|
|
|
|
BEAST_EXPECT(s == "");
|
2016-10-24 18:41:25 -04:00
|
|
|
};
|
2017-08-01 20:15:07 -07:00
|
|
|
ws.control_callback(cb);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.ping(ws, "");
|
2017-08-01 20:15:07 -07:00
|
|
|
ws.binary(true);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, sbuf("Hello"));
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(once);
|
|
|
|
|
BEAST_EXPECT(ws.got_binary());
|
|
|
|
|
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// send ping and fragmented message
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
bool once = false;
|
|
|
|
|
auto cb =
|
|
|
|
|
[&](frame_type kind, string_view s)
|
|
|
|
|
{
|
|
|
|
|
BEAST_EXPECT(kind == frame_type::pong);
|
|
|
|
|
BEAST_EXPECT(! once);
|
|
|
|
|
once = true;
|
|
|
|
|
BEAST_EXPECT(s == "payload");
|
|
|
|
|
};
|
|
|
|
|
ws.control_callback(cb);
|
|
|
|
|
ws.ping("payload");
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write_some(ws, false, sbuf("Hello, "));
|
|
|
|
|
w.write_some(ws, false, sbuf(""));
|
|
|
|
|
w.write_some(ws, true, sbuf("World!"));
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(once);
|
|
|
|
|
BEAST_EXPECT(to_string(b.data()) == "Hello, World!");
|
|
|
|
|
ws.control_callback();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// send pong
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.pong(ws, "");
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// send auto fragmented message
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
ws.auto_fragment(true);
|
|
|
|
|
ws.write_buffer_size(8);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, sbuf("Now is the time for all good men"));
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(to_string(b.data()) == "Now is the time for all good men");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// send message with write buffer limit
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
std::string s(2000, '*');
|
|
|
|
|
ws.write_buffer_size(1200);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, buffer(s.data(), s.size()));
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(to_string(b.data()) == s);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// unexpected cont
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write_raw(ws, cbuf(
|
2017-08-01 20:15:07 -07:00
|
|
|
0x80, 0x80, 0xff, 0xff, 0xff, 0xff));
|
2017-08-21 14:45:58 -07:00
|
|
|
doCloseTest(w, ws, close_code::protocol_error);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// invalid fixed frame header
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write_raw(ws, cbuf(
|
2017-08-01 20:15:07 -07:00
|
|
|
0x8f, 0x80, 0xff, 0xff, 0xff, 0xff));
|
2017-08-21 14:45:58 -07:00
|
|
|
doCloseTest(w, ws, close_code::protocol_error);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if(! pmd.client_enable)
|
|
|
|
|
{
|
|
|
|
|
// expected cont
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2016-10-24 18:41:25 -04:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write_some(ws, false, boost::asio::null_buffers{});
|
|
|
|
|
w.write_raw(ws, cbuf(
|
2017-08-01 20:15:07 -07:00
|
|
|
0x81, 0x80, 0xff, 0xff, 0xff, 0xff));
|
2017-08-21 14:45:58 -07:00
|
|
|
doCloseTest(w, ws, close_code::protocol_error);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
2016-10-24 18:41:25 -04:00
|
|
|
|
2017-08-01 20:15:07 -07:00
|
|
|
// message size above 2^64
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2016-10-24 18:41:25 -04:00
|
|
|
{
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write_some(ws, false, cbuf(0x00));
|
|
|
|
|
w.write_raw(ws, cbuf(
|
2017-08-01 20:15:07 -07:00
|
|
|
0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
|
|
|
|
|
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff));
|
2017-08-21 14:45:58 -07:00
|
|
|
doCloseTest(w, ws, close_code::too_big);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
// message size exceeds max
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
// VFALCO This was never implemented correctly
|
|
|
|
|
ws.read_message_max(1);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, cbuf(0x81, 0x02, '*', '*'));
|
|
|
|
|
doCloseTest(w, ws, close_code::too_big);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
*/
|
2016-10-24 18:41:25 -04:00
|
|
|
}
|
2017-08-01 20:15:07 -07:00
|
|
|
|
|
|
|
|
// receive ping
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
put(ws.next_layer().buffer(), cbuf(
|
|
|
|
|
0x89, 0x00));
|
|
|
|
|
bool invoked = false;
|
|
|
|
|
auto cb = [&](frame_type kind, string_view)
|
|
|
|
|
{
|
|
|
|
|
BEAST_EXPECT(! invoked);
|
|
|
|
|
BEAST_EXPECT(kind == frame_type::ping);
|
|
|
|
|
invoked = true;
|
|
|
|
|
};
|
|
|
|
|
ws.control_callback(cb);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, sbuf("Hello"));
|
2017-08-01 20:15:07 -07:00
|
|
|
multi_buffer b;
|
2017-08-21 14:45:58 -07:00
|
|
|
w.read(ws, b);
|
2017-08-01 20:15:07 -07:00
|
|
|
BEAST_EXPECT(invoked);
|
|
|
|
|
BEAST_EXPECT(ws.got_text());
|
|
|
|
|
BEAST_EXPECT(to_string(b.data()) == "Hello");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// receive ping
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
put(ws.next_layer().buffer(), cbuf(
|
|
|
|
|
0x88, 0x00));
|
|
|
|
|
bool invoked = false;
|
|
|
|
|
auto cb = [&](frame_type kind, string_view)
|
|
|
|
|
{
|
|
|
|
|
BEAST_EXPECT(! invoked);
|
|
|
|
|
BEAST_EXPECT(kind == frame_type::close);
|
|
|
|
|
invoked = true;
|
|
|
|
|
};
|
|
|
|
|
ws.control_callback(cb);
|
2017-08-21 14:45:58 -07:00
|
|
|
w.write(ws, sbuf("Hello"));
|
|
|
|
|
doCloseTest(w, ws, close_code::none);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// receive bad utf8
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
put(ws.next_layer().buffer(), cbuf(
|
|
|
|
|
0x81, 0x06, 0x03, 0xea, 0xf0, 0x28, 0x8c, 0xbc));
|
2017-08-21 14:45:58 -07:00
|
|
|
doFailTest(w, ws, error::failed);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// receive bad close
|
2017-08-21 14:45:58 -07:00
|
|
|
doTest(pmd, [&](ws_type& ws)
|
2017-08-01 20:15:07 -07:00
|
|
|
{
|
|
|
|
|
put(ws.next_layer().buffer(), cbuf(
|
|
|
|
|
0x88, 0x02, 0x03, 0xed));
|
2017-08-21 14:45:58 -07:00
|
|
|
doFailTest(w, ws, error::failed);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
2016-10-24 18:41:25 -04:00
|
|
|
}
|
|
|
|
|
|
2017-08-01 20:15:07 -07:00
|
|
|
//--------------------------------------------------------------------------
|
2017-07-29 17:47:04 -07:00
|
|
|
|
2017-06-07 17:41:27 -07:00
|
|
|
void
|
|
|
|
|
run() override
|
2016-04-30 13:00:33 -04:00
|
|
|
{
|
2017-05-23 12:33:31 -07:00
|
|
|
BOOST_STATIC_ASSERT(std::is_constructible<
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream>, boost::asio::io_service&>::value);
|
2016-05-07 17:06:46 -04:00
|
|
|
|
2017-05-23 12:33:31 -07:00
|
|
|
BOOST_STATIC_ASSERT(std::is_move_constructible<
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream>>::value);
|
2016-04-30 13:00:33 -04:00
|
|
|
|
2017-05-23 12:33:31 -07:00
|
|
|
BOOST_STATIC_ASSERT(std::is_move_assignable<
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream>>::value);
|
2016-04-30 13:00:33 -04:00
|
|
|
|
2017-05-23 12:33:31 -07:00
|
|
|
BOOST_STATIC_ASSERT(std::is_constructible<
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream&>, test::stream&>::value);
|
2016-05-15 16:22:25 -04:00
|
|
|
|
2017-05-23 12:33:31 -07:00
|
|
|
BOOST_STATIC_ASSERT(std::is_move_constructible<
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream&>>::value);
|
2016-05-15 16:22:25 -04:00
|
|
|
|
2017-05-23 12:33:31 -07:00
|
|
|
BOOST_STATIC_ASSERT(! std::is_move_assignable<
|
2017-08-24 06:21:30 -07:00
|
|
|
stream<test::stream&>>::value);
|
2016-04-30 13:00:33 -04:00
|
|
|
|
2016-06-10 15:48:39 -04:00
|
|
|
log << "sizeof(websocket::stream) == " <<
|
2017-08-16 19:25:02 -07:00
|
|
|
sizeof(websocket::stream<test::stream&>) << std::endl;
|
|
|
|
|
|
2016-10-24 18:41:25 -04:00
|
|
|
testOptions();
|
|
|
|
|
|
2017-08-22 18:08:56 -07:00
|
|
|
auto const testStream =
|
2017-08-01 20:15:07 -07:00
|
|
|
[this](permessage_deflate const& pmd)
|
2016-10-24 18:41:25 -04:00
|
|
|
{
|
2017-08-22 18:08:56 -07:00
|
|
|
doTestStream(SyncClient{}, pmd);
|
2017-08-21 14:45:58 -07:00
|
|
|
|
2017-08-12 15:03:39 -07:00
|
|
|
yield_to(
|
|
|
|
|
[&](yield_context yield)
|
|
|
|
|
{
|
2017-08-22 18:08:56 -07:00
|
|
|
doTestStream(AsyncClient{yield}, pmd);
|
2017-08-01 20:15:07 -07:00
|
|
|
});
|
2016-10-24 18:41:25 -04:00
|
|
|
};
|
|
|
|
|
|
2017-08-22 18:08:56 -07:00
|
|
|
permessage_deflate pmd;
|
|
|
|
|
|
2016-10-24 18:41:25 -04:00
|
|
|
pmd.client_enable = false;
|
|
|
|
|
pmd.server_enable = false;
|
2017-08-22 18:08:56 -07:00
|
|
|
testStream(pmd);
|
2016-10-24 18:41:25 -04:00
|
|
|
|
|
|
|
|
pmd.client_enable = true;
|
|
|
|
|
pmd.server_enable = true;
|
|
|
|
|
pmd.client_max_window_bits = 10;
|
|
|
|
|
pmd.client_no_context_takeover = false;
|
2017-07-31 18:48:22 -07:00
|
|
|
pmd.compLevel = 1;
|
|
|
|
|
pmd.memLevel = 1;
|
2017-08-22 18:08:56 -07:00
|
|
|
testStream(pmd);
|
2016-10-24 18:41:25 -04:00
|
|
|
|
|
|
|
|
pmd.client_enable = true;
|
|
|
|
|
pmd.server_enable = true;
|
|
|
|
|
pmd.client_max_window_bits = 10;
|
|
|
|
|
pmd.client_no_context_takeover = true;
|
2017-07-31 18:48:22 -07:00
|
|
|
pmd.compLevel = 1;
|
|
|
|
|
pmd.memLevel = 1;
|
2017-08-22 18:08:56 -07:00
|
|
|
testStream(pmd);
|
2016-04-30 13:00:33 -04:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2017-08-01 17:01:57 -07:00
|
|
|
BEAST_DEFINE_TESTSUITE(beast,websocket,stream);
|
2016-04-30 13:00:33 -04:00
|
|
|
|
|
|
|
|
} // websocket
|
|
|
|
|
} // beast
|
2017-07-20 13:40:34 -07:00
|
|
|
} // boost
|