Merge branch 'develop' into integration_tests_sleep
This commit is contained in:
commit
2819d364d9
10 files changed
+341
-124
No files matched your search
@@ -11,12 +11,28 @@ HEAD
|
||||
rather than connection `pre_init`. This allows setting of socket options prior
|
||||
to the bind/listen/accept system calls. Thank you ChristianRobl3D for
|
||||
reporting #530.
|
||||
- Improvement: Timers in transport integration tests should only fail if their
|
||||
own test times out, rather than any test. #643 Thank you Alex Korotkin for
|
||||
reporting and a patch.
|
||||
- Compatibility: Make sure the chrono library used by Boost/Asio is in sync
|
||||
with what the websocketpp is using. Thank you Flow86 for reporting and a
|
||||
patch.
|
||||
- Compatibility: Update `telemetry_client` to use a slightly more cross platform
|
||||
method of sleeping. Should work on windows now. Thank you Meir Yanovich for
|
||||
reporting.
|
||||
- Compatibility: Updated permessage-deflate support to reflect that the zlib
|
||||
library does not actually support a sliding window size of 256 bits.
|
||||
WebSocket++ will no longer negotiate 256 bit deflate windows. If the user
|
||||
of the library tries to request a 256 bit window a 512 bit window will be
|
||||
specified instead (This was the previous behavior). #596 #653 Thank you
|
||||
Vinnie Falco and Gianfranco Costamagna for reporting.
|
||||
- Compatibility: Better error handling and logging in cases where extension
|
||||
requests parse correctly but negotiation fails.
|
||||
- Compatibility: Removed custom handling of SSL_R_SHORT_READ error condition.
|
||||
This error code no longer exists in modern versions of OpenSSL and causes
|
||||
a build error. It wasn't being used for anything particularly important
|
||||
(slightly improving error reporting) and there isn't a great replacement.
|
||||
#599 Thank you Gianfranco Costamagna for reporting.
|
||||
- Bug: Store loggers in shared pointers to avoid crashes related to connections
|
||||
trying to write logs entries after their respective endpoint has been
|
||||
deallocated. Thank you Thalhammer for reporting and Jupp Müller for the
|
||||
@@ -29,6 +45,8 @@ HEAD
|
||||
- Bug/Documentation: Fix incorrect example code that used
|
||||
`websocketpp::lib::error_code` instead of `websocketpp::exception`. Thank you
|
||||
heretic13 for reporting
|
||||
- Bug: Fix uninitialized shared pointer in Asio transport test suite. #647
|
||||
Thank you Alex Korotkin for reporting and a patch.
|
||||
|
||||
0.7.0 - 2016-02-22
|
||||
- MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method
|
||||
|
||||
@@ -186,15 +186,22 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_invalid ) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_valid ) {
|
||||
ext_vars v;
|
||||
|
||||
// confirm that a request for a value of 8 is interpreted as 9
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
|
||||
v.attr["server_max_window_bits"] = "9";
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
|
||||
|
||||
v.attr["server_max_window_bits"] = "15";
|
||||
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
@@ -213,7 +220,7 @@ BOOST_AUTO_TEST_CASE( invalid_set_server_max_window_bits ) {
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_decline ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
v.attr["server_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::decline);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
@@ -223,7 +230,7 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_decline ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
@@ -232,10 +239,22 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::accept);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
@@ -244,10 +263,22 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::largest);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "8";
|
||||
|
||||
@@ -256,7 +287,19 @@ BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) {
|
||||
ext_vars v;
|
||||
v.attr["server_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_server_max_window_bits(15,pmd_mode::smallest);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=9");
|
||||
}
|
||||
|
||||
// Negotiate server_max_window_bits
|
||||
@@ -292,7 +335,13 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_valid ) {
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
|
||||
v.attr["client_max_window_bits"] = "9";
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
|
||||
v.attr["client_max_window_bits"] = "15";
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
@@ -311,7 +360,7 @@ BOOST_AUTO_TEST_CASE( invalid_set_client_max_window_bits ) {
|
||||
BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
@@ -323,7 +372,19 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_client_max_window_bits(9,pmd_mode::decline);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
@@ -332,10 +393,22 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_client_max_window_bits(15,pmd_mode::accept);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
@@ -344,10 +417,22 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_client_max_window_bits(15,pmd_mode::largest);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest_8 ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "8";
|
||||
|
||||
@@ -356,7 +441,19 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8");
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) {
|
||||
ext_vars v;
|
||||
v.attr["client_max_window_bits"] = "9";
|
||||
|
||||
v.ec = v.exts.set_client_max_window_bits(15,pmd_mode::smallest);
|
||||
v.esp = v.exts.negotiate(v.attr);
|
||||
BOOST_CHECK( v.exts.is_enabled() );
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() );
|
||||
BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=9");
|
||||
}
|
||||
|
||||
|
||||
@@ -507,7 +604,8 @@ BOOST_AUTO_TEST_CASE( compress_data ) {
|
||||
std::string compress_out;
|
||||
std::string decompress_out;
|
||||
|
||||
v.exts.init(true);
|
||||
v.ec = v.exts.init(true);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.compress(compress_in,compress_out);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
@@ -520,7 +618,8 @@ BOOST_AUTO_TEST_CASE( compress_data ) {
|
||||
BOOST_AUTO_TEST_CASE( compress_data_multiple ) {
|
||||
ext_vars v;
|
||||
|
||||
v.exts.init(true);
|
||||
v.ec = v.exts.init(true);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
std::string compress_in = "Hello";
|
||||
@@ -545,11 +644,12 @@ BOOST_AUTO_TEST_CASE( compress_data_large ) {
|
||||
|
||||
websocketpp::http::attribute_list alist;
|
||||
|
||||
alist["server_max_window_bits"] = "8";
|
||||
v.exts.set_server_max_window_bits(8,websocketpp::extensions::permessage_deflate::mode::smallest);
|
||||
alist["server_max_window_bits"] = "9";
|
||||
v.exts.set_server_max_window_bits(9,websocketpp::extensions::permessage_deflate::mode::smallest);
|
||||
|
||||
v.exts.negotiate(alist);
|
||||
v.exts.init(true);
|
||||
v.ec = v.exts.init(true);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.compress(compress_in,compress_out);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
@@ -573,7 +673,8 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) {
|
||||
v.exts.enable_server_no_context_takeover();
|
||||
|
||||
v.exts.negotiate(alist);
|
||||
v.exts.init(true);
|
||||
v.ec = v.exts.init(true);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.compress(compress_in,compress_out1);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
@@ -609,7 +710,8 @@ BOOST_AUTO_TEST_CASE( compress_empty ) {
|
||||
std::string compress_out;
|
||||
std::string decompress_out;
|
||||
|
||||
v.exts.init(true);
|
||||
v.ec = v.exts.init(true);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.compress(compress_in,compress_out);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
@@ -640,7 +742,8 @@ BOOST_AUTO_TEST_CASE( decompress_data ) {
|
||||
std::string out;
|
||||
std::string reference = "Hello";
|
||||
|
||||
v.exts.init(true);
|
||||
v.ec = v.exts.init(true);
|
||||
BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() );
|
||||
|
||||
v.ec = v.exts.decompress(in,11,out);
|
||||
|
||||
|
||||
@@ -140,7 +140,10 @@ typedef websocketpp::lib::shared_ptr<mock_con> connection_ptr;
|
||||
struct mock_endpoint : public websocketpp::transport::asio::endpoint<config> {
|
||||
typedef websocketpp::transport::asio::endpoint<config> base;
|
||||
|
||||
mock_endpoint() {
|
||||
mock_endpoint()
|
||||
: alog(websocketpp::lib::make_shared<config::alog_type>())
|
||||
, elog(websocketpp::lib::make_shared<config::elog_type>())
|
||||
{
|
||||
alog->set_channels(websocketpp::log::alevel::all);
|
||||
base::init_logging(alog,elog);
|
||||
init_asio();
|
||||
@@ -182,6 +185,8 @@ BOOST_AUTO_TEST_CASE( tls_handshake_timeout ) {
|
||||
dummy_server.detach();
|
||||
timer.detach();
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
mock_endpoint endpoint;
|
||||
endpoint.set_tls_init_handler(&on_tls_init);
|
||||
endpoint.connect("wss://localhost:9005");
|
||||
|
||||
@@ -354,11 +354,35 @@ void close(T * e, websocketpp::connection_hdl hdl) {
|
||||
e->get_con_from_hdl(hdl)->close(websocketpp::close::status::normal,"");
|
||||
}
|
||||
|
||||
// Wait for the specified time period then fail the test
|
||||
void run_test_timer(long value) {
|
||||
sleep(value);
|
||||
BOOST_FAIL( "Test timed out" );
|
||||
}
|
||||
class test_deadline_timer
|
||||
{
|
||||
public:
|
||||
test_deadline_timer(int seconds)
|
||||
: m_timer(m_io_service, boost::posix_time::seconds(seconds))
|
||||
{
|
||||
m_timer.async_wait(bind(&test_deadline_timer::expired, this, ::_1));
|
||||
std::size_t (boost::asio::io_service::*run)() = &boost::asio::io_service::run;
|
||||
m_timer_thread = websocketpp::lib::thread(websocketpp::lib::bind(run, &m_io_service));
|
||||
}
|
||||
~test_deadline_timer()
|
||||
{
|
||||
m_timer.cancel();
|
||||
m_timer_thread.join();
|
||||
}
|
||||
|
||||
private:
|
||||
void expired(const boost::system::error_code & ec)
|
||||
{
|
||||
if (ec == boost::asio::error::operation_aborted)
|
||||
return;
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_FAIL("Test timed out");
|
||||
}
|
||||
|
||||
boost::asio::io_service m_io_service;
|
||||
boost::asio::deadline_timer m_timer;
|
||||
websocketpp::lib::thread m_timer_thread;
|
||||
};
|
||||
|
||||
BOOST_AUTO_TEST_CASE( pong_no_timeout ) {
|
||||
server s;
|
||||
@@ -400,11 +424,10 @@ BOOST_AUTO_TEST_CASE( pong_timeout ) {
|
||||
websocketpp::lib::error_code(),::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
test_deadline_timer deadline(10);
|
||||
|
||||
run_client(c, "http://localhost:9005",false);
|
||||
|
||||
sthread.join();
|
||||
@@ -420,12 +443,12 @@ BOOST_AUTO_TEST_CASE( client_open_handshake_timeout ) {
|
||||
websocketpp::error::open_handshake_timeout,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_dummy_server,9005));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
sthread.detach();
|
||||
tthread.detach();
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
test_deadline_timer deadline(10);
|
||||
|
||||
run_client(c, "http://localhost:9005");
|
||||
}
|
||||
|
||||
@@ -439,8 +462,8 @@ BOOST_AUTO_TEST_CASE( server_open_handshake_timeout ) {
|
||||
websocketpp::error::open_handshake_timeout,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
test_deadline_timer deadline(10);
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
@@ -464,8 +487,8 @@ BOOST_AUTO_TEST_CASE( client_self_initiated_close_handshake_timeout ) {
|
||||
websocketpp::error::close_handshake_timeout,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
|
||||
test_deadline_timer deadline(10);
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
@@ -498,8 +521,7 @@ BOOST_AUTO_TEST_CASE( server_self_initiated_close_handshake_timeout ) {
|
||||
c.set_open_handler(bind(&delay,::_1,1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10));
|
||||
tthread.detach();
|
||||
test_deadline_timer deadline(10);
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
@@ -511,8 +533,7 @@ BOOST_AUTO_TEST_CASE( server_self_initiated_close_handshake_timeout ) {
|
||||
BOOST_AUTO_TEST_CASE( client_runs_out_of_work ) {
|
||||
client c;
|
||||
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,3));
|
||||
tthread.detach();
|
||||
test_deadline_timer deadline(3);
|
||||
|
||||
websocketpp::lib::error_code ec;
|
||||
c.init_asio(ec);
|
||||
@@ -578,8 +599,7 @@ BOOST_AUTO_TEST_CASE( stop_listening ) {
|
||||
c.set_open_handler(bind(&close<client>,&c,::_1));
|
||||
|
||||
websocketpp::lib::thread sthread(websocketpp::lib::bind(&run_server,&s,9005,false));
|
||||
websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,5));
|
||||
tthread.detach();
|
||||
test_deadline_timer deadline(5);
|
||||
|
||||
sleep(1); // give the server thread some time to start
|
||||
|
||||
|
||||
@@ -88,6 +88,9 @@ namespace lib {
|
||||
inline lib::chrono::milliseconds milliseconds(long duration) {
|
||||
return lib::chrono::milliseconds(duration);
|
||||
}
|
||||
|
||||
} // namespace error
|
||||
} // namespace ssl
|
||||
} // namespace asio
|
||||
|
||||
#else
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
namespace websocketpp {
|
||||
namespace extensions {
|
||||
|
||||
/// Implementation of the draft permessage-deflate WebSocket extension
|
||||
/// Implementation of RFC 7692, the permessage-deflate WebSocket extension
|
||||
/**
|
||||
* ### permessage-deflate interface
|
||||
*
|
||||
@@ -174,18 +174,30 @@ namespace websocketpp {
|
||||
namespace extensions {
|
||||
namespace permessage_deflate {
|
||||
|
||||
/// Default value for server_max_window_bits as defined by draft 17
|
||||
/// Default value for server_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const default_server_max_window_bits = 15;
|
||||
/// Minimum value for server_max_window_bits as defined by draft 17
|
||||
/// Minimum value for server_max_window_bits as defined by RFC 7692
|
||||
/**
|
||||
* NOTE: A value of 8 is not actually supported by zlib, the deflate
|
||||
* library that WebSocket++ uses. To preserve backwards compatibility
|
||||
* with RFC 7692 and previous versions of the library a value of 8
|
||||
* is accepted by the library but will always be negotiated as 9.
|
||||
*/
|
||||
static uint8_t const min_server_max_window_bits = 8;
|
||||
/// Maximum value for server_max_window_bits as defined by draft 17
|
||||
/// Maximum value for server_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const max_server_max_window_bits = 15;
|
||||
|
||||
/// Default value for client_max_window_bits as defined by draft 17
|
||||
/// Default value for client_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const default_client_max_window_bits = 15;
|
||||
/// Minimum value for client_max_window_bits as defined by draft 17
|
||||
/// Minimum value for client_max_window_bits as defined by RFC 7692
|
||||
/**
|
||||
* NOTE: A value of 8 is not actually supported by zlib, the deflate
|
||||
* library that WebSocket++ uses. To preserve backwards compatibility
|
||||
* with RFC 7692 and previous versions of the library a value of 8
|
||||
* is accepted by the library but will always be negotiated as 9.
|
||||
*/
|
||||
static uint8_t const min_client_max_window_bits = 8;
|
||||
/// Maximum value for client_max_window_bits as defined by draft 17
|
||||
/// Maximum value for client_max_window_bits as defined by RFC 7692
|
||||
static uint8_t const max_client_max_window_bits = 15;
|
||||
|
||||
namespace mode {
|
||||
@@ -372,7 +384,7 @@ public:
|
||||
/**
|
||||
* The bits setting is the base 2 logarithm of the maximum window size that
|
||||
* the server must use to compress outgoing messages. The permitted range
|
||||
* is 8 to 15 inclusive. 8 represents a 256 byte window and 15 a 32KiB
|
||||
* is 9 to 15 inclusive. 9 represents a 512 byte window and 15 a 32KiB
|
||||
* window. The default setting is 15.
|
||||
*
|
||||
* Mode Options:
|
||||
@@ -386,6 +398,14 @@ public:
|
||||
* adjusted by the server. A server may unilaterally set this value without
|
||||
* client support.
|
||||
*
|
||||
* NOTE: The permessage-deflate spec specifies that a value of 8 is allowed.
|
||||
* Prior to version 0.8.0 a value of 8 was also allowed by this library.
|
||||
* zlib, the deflate compression library that WebSocket++ uses has always
|
||||
* silently adjusted a value of 8 to 9. In recent versions of zlib (1.2.9
|
||||
* and greater) a value of 8 is now explicitly rejected. WebSocket++ 0.8.0
|
||||
* continues to perform the 8->9 conversion for backwards compatibility
|
||||
* purposes but this should be considered deprecated functionality.
|
||||
*
|
||||
* @param bits The size to request for the outgoing window size
|
||||
* @param mode The mode to use for negotiating this parameter
|
||||
* @return A status code
|
||||
@@ -394,6 +414,12 @@ public:
|
||||
if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) {
|
||||
return error::make_error_code(error::invalid_max_window_bits);
|
||||
}
|
||||
|
||||
// See note in doc comment above about what is happening here
|
||||
if (bits == 8) {
|
||||
bits = 9;
|
||||
}
|
||||
|
||||
m_server_max_window_bits = bits;
|
||||
m_server_max_window_bits_mode = mode;
|
||||
|
||||
@@ -403,8 +429,8 @@ public:
|
||||
/// Limit client LZ77 sliding window size
|
||||
/**
|
||||
* The bits setting is the base 2 logarithm of the window size that the
|
||||
* client must use to compress outgoing messages. The permitted range is 8
|
||||
* to 15 inclusive. 8 represents a 256 byte window and 15 a 32KiB window.
|
||||
* client must use to compress outgoing messages. The permitted range is 9
|
||||
* to 15 inclusive. 9 represents a 512 byte window and 15 a 32KiB window.
|
||||
* The default setting is 15.
|
||||
*
|
||||
* Mode Options:
|
||||
@@ -417,6 +443,14 @@ public:
|
||||
* outgoing window size unilaterally. A server may only limit the client's
|
||||
* window size if the remote client supports that feature.
|
||||
*
|
||||
* NOTE: The permessage-deflate spec specifies that a value of 8 is allowed.
|
||||
* Prior to version 0.8.0 a value of 8 was also allowed by this library.
|
||||
* zlib, the deflate compression library that WebSocket++ uses has always
|
||||
* silently adjusted a value of 8 to 9. In recent versions of zlib (1.2.9
|
||||
* and greater) a value of 8 is now explicitly rejected. WebSocket++ 0.8.0
|
||||
* continues to perform the 8->9 conversion for backwards compatibility
|
||||
* purposes but this should be considered deprecated functionality.
|
||||
*
|
||||
* @param bits The size to request for the outgoing window size
|
||||
* @param mode The mode to use for negotiating this parameter
|
||||
* @return A status code
|
||||
@@ -425,6 +459,12 @@ public:
|
||||
if (bits < min_client_max_window_bits || bits > max_client_max_window_bits) {
|
||||
return error::make_error_code(error::invalid_max_window_bits);
|
||||
}
|
||||
|
||||
// See note in doc comment above about what is happening here
|
||||
if (bits == 8) {
|
||||
bits = 9;
|
||||
}
|
||||
|
||||
m_client_max_window_bits = bits;
|
||||
m_client_max_window_bits_mode = mode;
|
||||
|
||||
@@ -642,11 +682,17 @@ private:
|
||||
* client requested that we use.
|
||||
*
|
||||
* options:
|
||||
* - decline (refuse to use the attribute)
|
||||
* - accept (use whatever the client says)
|
||||
* - largest (use largest possible value)
|
||||
* - decline (ignore value, offer our default instead)
|
||||
* - accept (use the value requested by the client)
|
||||
* - largest (use largest value acceptable to both)
|
||||
* - smallest (use smallest possible value)
|
||||
*
|
||||
* NOTE: As a value of 8 is no longer explicitly supported by zlib but might
|
||||
* be requested for negotiation by an older client/server, if the result of
|
||||
* the negotiation would be to send a value of 8, a value of 9 is offered
|
||||
* instead. This ensures that WebSocket++ will only ever negotiate connections
|
||||
* with compression settings explicitly supported by zlib.
|
||||
*
|
||||
* @param [in] value The value of the attribute from the offer
|
||||
* @param [out] ec A reference to the error code to return errors via
|
||||
*/
|
||||
@@ -678,6 +724,11 @@ private:
|
||||
ec = make_error_code(error::invalid_mode);
|
||||
m_server_max_window_bits = default_server_max_window_bits;
|
||||
}
|
||||
|
||||
// See note in doc comment
|
||||
if (m_server_max_window_bits == 8) {
|
||||
m_server_max_window_bits = 9;
|
||||
}
|
||||
}
|
||||
|
||||
/// Negotiate client_max_window_bits attribute
|
||||
@@ -687,11 +738,17 @@ private:
|
||||
* negotiation mode.
|
||||
*
|
||||
* options:
|
||||
* - decline (refuse to use the attribute)
|
||||
* - accept (use whatever the client says)
|
||||
* - largest (use largest possible value)
|
||||
* - decline (ignore value, offer our default instead)
|
||||
* - accept (use the value requested by the client)
|
||||
* - largest (use largest value acceptable to both)
|
||||
* - smallest (use smallest possible value)
|
||||
*
|
||||
* NOTE: As a value of 8 is no longer explicitly supported by zlib but might
|
||||
* be requested for negotiation by an older client/server, if the result of
|
||||
* the negotiation would be to send a value of 8, a value of 9 is offered
|
||||
* instead. This ensures that WebSocket++ will only ever negotiate connections
|
||||
* with compression settings explicitly supported by zlib.
|
||||
*
|
||||
* @param [in] value The value of the attribute from the offer
|
||||
* @param [out] ec A reference to the error code to return errors via
|
||||
*/
|
||||
@@ -727,6 +784,11 @@ private:
|
||||
ec = make_error_code(error::invalid_mode);
|
||||
m_client_max_window_bits = default_client_max_window_bits;
|
||||
}
|
||||
|
||||
// See note in doc comment
|
||||
if (m_client_max_window_bits == 8) {
|
||||
m_client_max_window_bits = 9;
|
||||
}
|
||||
}
|
||||
|
||||
bool m_enabled;
|
||||
|
||||
@@ -999,19 +999,16 @@ void connection<config>::handle_read_frame(lib::error_code const & ec,
|
||||
"handle_read_frame: got invalid istate in closed state");
|
||||
return;
|
||||
}
|
||||
} else if (ecm == transport::error::tls_short_read) {
|
||||
if (m_state == session::state::closed) {
|
||||
// We expect to get a TLS short read if we try to read after the
|
||||
// connection is closed. If this happens ignore and exit the
|
||||
// read frame path.
|
||||
terminate(lib::error_code());
|
||||
return;
|
||||
}
|
||||
echannel = log::elevel::rerror;
|
||||
} else if (ecm == transport::error::action_after_shutdown) {
|
||||
echannel = log::elevel::info;
|
||||
} else {
|
||||
// TODO: more generally should we do something different here in the
|
||||
// case that m_state is cosed? Are errors after the connection is
|
||||
// already closed really an rerror?
|
||||
}
|
||||
|
||||
|
||||
|
||||
log_err(echannel, "handle_read_frame", ecm);
|
||||
this->terminate(ecm);
|
||||
return;
|
||||
@@ -1222,12 +1219,18 @@ lib::error_code connection<config>::process_handshake_request() {
|
||||
std::pair<lib::error_code,std::string> neg_results;
|
||||
neg_results = m_processor->negotiate_extensions(m_request);
|
||||
|
||||
if (neg_results.first) {
|
||||
if (neg_results.first == processor::error::make_error_code(processor::error::extension_parse_error)) {
|
||||
// There was a fatal error in extension parsing that should result in
|
||||
// a failed connection attempt.
|
||||
m_alog->write(log::alevel::devel, "Bad request: " + neg_results.first.message());
|
||||
m_elog->write(log::elevel::info, "Bad request: " + neg_results.first.message());
|
||||
m_response.set_status(http::status_code::bad_request);
|
||||
return neg_results.first;
|
||||
} else if (neg_results.first) {
|
||||
// There was a fatal error in extension processing that is probably our
|
||||
// fault. Consider extension negotiation to have failed and continue as
|
||||
// if extensions were not supported
|
||||
m_elog->write(log::elevel::info,
|
||||
"Extension negotiation failed: " + neg_results.first.message());
|
||||
} else {
|
||||
// extension negotiation succeeded, set response header accordingly
|
||||
// we don't send an empty extensions header because it breaks many
|
||||
|
||||
@@ -125,38 +125,60 @@ public:
|
||||
|
||||
http::parameter_list::const_iterator it;
|
||||
|
||||
// look through the list of extension requests to find the first
|
||||
// one that we can accept.
|
||||
if (m_permessage_deflate.is_implemented()) {
|
||||
err_str_pair neg_ret;
|
||||
for (it = p.begin(); it != p.end(); ++it) {
|
||||
// look through each extension, if the key is permessage-deflate
|
||||
if (it->first == "permessage-deflate") {
|
||||
// if we have already successfully negotiated this extension
|
||||
// then skip any other requests to negotiate the same one
|
||||
// with different parameters
|
||||
if (m_permessage_deflate.is_enabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
neg_ret = m_permessage_deflate.negotiate(it->second);
|
||||
// not a permessage-deflate extension request, ignore
|
||||
if (it->first != "permessage-deflate") {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (neg_ret.first) {
|
||||
// Figure out if this is an error that should halt all
|
||||
// extension negotiations or simply cause negotiation of
|
||||
// this specific extension to fail.
|
||||
//std::cout << "permessage-compress negotiation failed: "
|
||||
// << neg_ret.first.message() << std::endl;
|
||||
} else {
|
||||
// Note: this list will need commas if WebSocket++ ever
|
||||
// supports more than one extension
|
||||
ret.second += neg_ret.second;
|
||||
m_permessage_deflate.init(base::m_server);
|
||||
continue;
|
||||
}
|
||||
// if we have already successfully negotiated this extension
|
||||
// then skip any other requests to negotiate the same one
|
||||
// with different parameters
|
||||
if (m_permessage_deflate.is_enabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// attempt to negotiate this offer
|
||||
neg_ret = m_permessage_deflate.negotiate(it->second);
|
||||
|
||||
if (neg_ret.first) {
|
||||
// negotiation offer failed. Do nothing. We will continue
|
||||
// searching for a permessage-deflate config that succeeds
|
||||
continue;
|
||||
}
|
||||
|
||||
// Negotiation tentatively succeeded
|
||||
|
||||
// Actually try to initialize the extension before we
|
||||
// deem negotiation complete
|
||||
lib::error_code ec = m_permessage_deflate.init(base::m_server);
|
||||
|
||||
if (ec) {
|
||||
// Negotiation succeeded but initialization failed this is
|
||||
// an error that should stop negotiation of permessage
|
||||
// deflate. Return the reason for the init failure
|
||||
|
||||
ret.first = ec;
|
||||
break;
|
||||
} else {
|
||||
// Successfully initialized, push the negotiated response into
|
||||
// the reply and stop looking for additional permessage-deflate
|
||||
// extensions
|
||||
ret.second += neg_ret.second;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// support for future extensions would go here. Should check the value of
|
||||
// ret.first before continuing. Might need to consider whether failure of
|
||||
// negotiation of an earlier extension should stop negotiation of subsequent
|
||||
// ones
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1116,17 +1116,10 @@ protected:
|
||||
tec = socket_con_type::translate_ec(ec);
|
||||
m_tec = ec;
|
||||
|
||||
if (tec == transport::error::tls_short_read) {
|
||||
// TLS short read at this point is somewhat expected if both
|
||||
// sides try and end the connection at the same time or if
|
||||
// SSLv2 is being used. In general there is nothing that can
|
||||
// be done here other than a low level development log.
|
||||
} else {
|
||||
// all other errors are effectively pass through errors of
|
||||
// some sort so print some detail on the info channel for
|
||||
// library users to look up if needed.
|
||||
log_err(log::elevel::info,"asio async_shutdown",ec);
|
||||
}
|
||||
// all other errors are effectively pass through errors of
|
||||
// some sort so print some detail on the info channel for
|
||||
// library users to look up if needed.
|
||||
log_err(log::elevel::info,"asio async_shutdown",ec);
|
||||
}
|
||||
} else {
|
||||
if (m_alog->static_test(log::alevel::devel)) {
|
||||
|
||||
@@ -355,13 +355,9 @@ protected:
|
||||
template <typename ErrorCodeType>
|
||||
lib::error_code translate_ec(ErrorCodeType ec) {
|
||||
if (ec.category() == lib::asio::error::get_ssl_category()) {
|
||||
if (ERR_GET_REASON(ec.value()) == SSL_R_SHORT_READ) {
|
||||
return make_error_code(transport::error::tls_short_read);
|
||||
} else {
|
||||
// We know it is a TLS related error, but otherwise don't know
|
||||
// more. Pass through as TLS generic.
|
||||
return make_error_code(transport::error::tls_error);
|
||||
}
|
||||
// We know it is a TLS related error, but otherwise don't know more.
|
||||
// Pass through as TLS generic.
|
||||
return make_error_code(transport::error::tls_error);
|
||||
} else {
|
||||
// We don't know any more information about this error so pass
|
||||
// through
|
||||
@@ -372,14 +368,6 @@ protected:
|
||||
/// Overload of translate_ec to catch cases where lib::error_code is the
|
||||
/// same type as lib::asio::error_code
|
||||
lib::error_code translate_ec(lib::error_code ec) {
|
||||
// Normalize the tls_short_read error as it is used by the library and
|
||||
// needs a consistent value. All other errors pass through natively.
|
||||
// TODO: how to get the SSL category from std::error?
|
||||
/*if (ec.category() == lib::asio::error::get_ssl_category()) {
|
||||
if (ERR_GET_REASON(ec.value()) == SSL_R_SHORT_READ) {
|
||||
return make_error_code(transport::error::tls_short_read);
|
||||
}
|
||||
}*/
|
||||
return ec;
|
||||
}
|
||||
private:
|
||||
|
||||
Reference in new issue
Block a user