From 6c6c6951e500464e625f0ef0ca8eaafccf963e52 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 5 Jul 2013 11:38:24 -0500 Subject: [PATCH 001/114] fix spelling error --- websocketpp/processors/hybi13.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index e3f2c459f..bfb2fb1b5 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -108,7 +108,7 @@ class hybi13 : public processor { return ret; } - http::parameter_list::const_iterator it; + http::parameter_list::const_iterator it; if (m_permessage_deflate.is_implemented()) { err_str_pair neg_ret; From c32bebba3ea6b6e48ee73269650d54ea4d1edd63 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 5 Jul 2013 11:39:02 -0500 Subject: [PATCH 002/114] take over print server example for testing --- examples/print_server/SConscript | 2 +- examples/print_server/print_server.cpp | 48 ++++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/examples/print_server/SConscript b/examples/print_server/SConscript index 725ed77e3..6d417a0f2 100644 --- a/examples/print_server/SConscript +++ b/examples/print_server/SConscript @@ -14,7 +14,7 @@ prgs = [] # if a C++11 environment is available build using that, otherwise use boost if env_cpp11.has_key('WSPP_CPP11_ENABLED'): - ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z'] prgs += env_cpp11.Program('print_server', ["print_server.cpp"], LIBS = ALL_LIBS) else: ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs] diff --git a/examples/print_server/print_server.cpp b/examples/print_server/print_server.cpp index 962ec45ae..e848c8b8a 100644 --- a/examples/print_server/print_server.cpp +++ b/examples/print_server/print_server.cpp @@ -1,18 +1,60 @@ #include -#include +#include #include -typedef websocketpp::server server; +#include + +struct deflate_config : public websocketpp::config::debug_core { + typedef deflate_config type; + typedef debug_core base; + + typedef base::concurrency_type concurrency_type; + + typedef base::request_type request_type; + typedef base::response_type response_type; + + typedef base::message_type message_type; + typedef base::con_msg_manager_type con_msg_manager_type; + typedef base::endpoint_msg_manager_type endpoint_msg_manager_type; + + typedef base::alog_type alog_type; + typedef base::elog_type elog_type; + + typedef base::rng_type rng_type; + + struct transport_config : public base::transport_config { + typedef type::concurrency_type concurrency_type; + typedef type::alog_type alog_type; + typedef type::elog_type elog_type; + typedef type::request_type request_type; + typedef type::response_type response_type; + typedef websocketpp::transport::asio::basic_socket::endpoint + socket_type; + }; + + typedef websocketpp::transport::asio::endpoint + transport_type; + + /// permessage_compress extension + struct permessage_deflate_config {}; + + typedef websocketpp::extensions::permessage_deflate::enabled + permessage_deflate_type; +}; + +typedef websocketpp::server server; void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg) { - std::cout << msg->get_payload() << std::endl; + std::cout << "on_message: " << msg->get_payload() << std::endl; } int main() { server print_server; print_server.set_message_handler(&on_message); + print_server.set_access_channels(websocketpp::log::alevel::all); + print_server.set_error_channels(websocketpp::log::elevel::all); print_server.init_asio(); print_server.listen(9002); From c103032e9c2018039cbf61387a61b724ce4128f0 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:34:07 -0500 Subject: [PATCH 003/114] add init to extension interface --- websocketpp/extensions/permessage_deflate/disabled.hpp | 5 +++++ websocketpp/extensions/permessage_deflate/enabled.hpp | 4 ++++ 2 files changed, 9 insertions(+) diff --git a/websocketpp/extensions/permessage_deflate/disabled.hpp b/websocketpp/extensions/permessage_deflate/disabled.hpp index 8b1e6cb57..809c9e0a6 100644 --- a/websocketpp/extensions/permessage_deflate/disabled.hpp +++ b/websocketpp/extensions/permessage_deflate/disabled.hpp @@ -57,6 +57,11 @@ class disabled { return make_pair(make_error_code(error::disabled),std::string()); } + /// Initialize state + lib::error_code init() { + return lib::error_code(); + } + /// Returns true if the extension is capable of providing /// permessage_deflate functionality bool is_implemented() const { diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 7fdaef541..fc1086023 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -48,6 +48,10 @@ namespace extensions { /** * ### permessage-deflate interface * + * **init**\n + * `lib::error_code init()`\n + * Performs initialization + * * **is_implimented**\n * `bool is_implimented()`\n * Returns whether or not the object impliments the extension or not From a90ccd83dd1e0adb213991b065370dd761e1b5b0 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:34:19 -0500 Subject: [PATCH 004/114] update error name to be more descriptive --- websocketpp/extensions/permessage_deflate/enabled.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index fc1086023..c790db827 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -138,7 +138,7 @@ class category : public lib::error_category { case zlib_error: return "A zlib function returned an error"; case uninitialized: - return "Object must be initialized before use"; + return "Deflate extension must be initialized before use"; default: return "Unknown permessage-compress error"; } From 631261c365c4ccc85d857dfddd0ac40e5f4fbd57 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:34:45 -0500 Subject: [PATCH 005/114] correctly set avail_in for compression --- websocketpp/extensions/permessage_deflate/enabled.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index c790db827..e76941130 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -493,14 +493,14 @@ class enabled { size_t output; int ret; - m_dstate.avail_out = m_compress_buffer_size; + m_dstate.avail_in = in.size(); m_dstate.next_in = (unsigned char *)(const_cast(in.data())); do { // Output to local buffer m_dstate.avail_out = m_compress_buffer_size; m_dstate.next_out = m_compress_buffer.get(); - + ret = deflate(&m_dstate, Z_SYNC_FLUSH); output = m_compress_buffer_size - m_dstate.avail_out; From 0501f77b57203f2b0b9ed20895c96f86602fb943 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:35:29 -0500 Subject: [PATCH 006/114] Add additional development logging of incoming data --- websocketpp/impl/connection_impl.hpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index ebd4fe7a5..7c9116e49 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -850,6 +850,12 @@ void connection::handle_read_frame(const lib::error_code& ec, lib::error_code ec; + if (m_alog.static_test(log::alevel::devel)) { + std::stringstream s; + s << "Processing Bytes: " << utility::to_hex(reinterpret_cast(m_buf)+p,bytes_transferred-p); + m_alog.write(log::alevel::devel,s.str()); + } + p += m_processor->consume( reinterpret_cast(m_buf)+p, bytes_transferred-p, From 4a52e548fd2ab0576ed344e432eb73fdf7878b32 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:35:43 -0500 Subject: [PATCH 007/114] compress outgoing messages by default if able --- websocketpp/impl/connection_impl.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index 7c9116e49..7c38e6544 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -77,6 +77,7 @@ lib::error_code connection::send(const std::string& payload, { message_ptr msg = m_msg_manager->get_message(op,payload.size()); msg->append_payload(payload); + msg->set_compressed(true); return send(msg); } From 359f03fb1e32041cac9edd4d909b39fba4c7ea36 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:36:00 -0500 Subject: [PATCH 008/114] Documentation --- websocketpp/message_buffer/message.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/websocketpp/message_buffer/message.hpp b/websocketpp/message_buffer/message.hpp index dde75798e..6d3c44ee2 100644 --- a/websocketpp/message_buffer/message.hpp +++ b/websocketpp/message_buffer/message.hpp @@ -147,6 +147,11 @@ class message { /// Set or clear the compression flag /** + * Setting the compression flag indicates that the data in this message + * would benefit from compression. If both endpoints negotiate a compression + * extension WebSocket++ will attempt to compress messages with this flag. + * Setting this flag does not guarantee that the message will be compressed. + * * @param value The value to set the compressed flag to */ void set_compressed(bool value) { From 4607150f82e4ead55c860c619787607e366148c3 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:36:52 -0500 Subject: [PATCH 009/114] add error checking to decompress method --- websocketpp/processors/hybi13.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index bfb2fb1b5..c98c94034 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -718,10 +718,13 @@ class hybi13 : public processor { // decompress message if needed. if (m_permessage_deflate.is_enabled() && frame::get_rsv1(m_basic_header)) - { + { // Decompress current buffer into the message buffer - m_permessage_deflate.decompress(buf,len,out); - + ec = m_permessage_deflate.decompress(buf,len,out); + if (ec) { + return 0; + } + // get the length of the newly uncompressed output offset = out.size() - offset; } else { From 14aa71091f1299a0da628bc7d7c28e03b147e42c Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:37:29 -0500 Subject: [PATCH 010/114] initialize deflate extension after it is negotiated --- websocketpp/processors/hybi13.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index c98c94034..0a05968ba 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -127,6 +127,7 @@ class hybi13 : public processor { // Note: this list will need commas if WebSocket++ ever // supports more than one extension ret.second += neg_ret.second; + m_permessage_deflate.init(); continue; } } From bd408944fdb975c892368cd34095367e13c1d14e Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:38:42 -0500 Subject: [PATCH 011/114] refactor message prep to determine payload size sooner --- websocketpp/processors/hybi13.hpp | 32 +++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 0a05968ba..8ff991ea5 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -524,25 +524,15 @@ class hybi13 : public processor { && in->get_compressed(); bool fin = in->get_fin(); - // generate header - frame::basic_header h(op,i.size(),fin,masked,compressed); - - if (masked) { - // Generate masking key. - key.i = m_rng(); - - frame::extended_header e(i.size(),key.i); - out->set_header(frame::prepare_header(h,e)); - } else { - frame::extended_header e(i.size()); - out->set_header(frame::prepare_header(h,e)); - } - // prepare payload if (compressed) { // compress and store in o after header. m_permessage_deflate.compress(i,o); + // Strip trailing 4 0x00 0x00 0xff 0xff bytes before writing to the + // wire + o.resize(o.size()-4); + // mask in place if necessary if (masked) { this->masked_copy(o,o,key); @@ -560,6 +550,20 @@ class hybi13 : public processor { std::copy(i.begin(),i.end(),o.begin()); } } + + // generate header + frame::basic_header h(op,o.size(),fin,masked,compressed); + + if (masked) { + // Generate masking key. + key.i = m_rng(); + + frame::extended_header e(o.size(),key.i); + out->set_header(frame::prepare_header(h,e)); + } else { + frame::extended_header e(o.size()); + out->set_header(frame::prepare_header(h,e)); + } out->set_prepared(true); From 25e8d522b2e79e2e88170fda1e03f51401777f68 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:42:12 -0500 Subject: [PATCH 012/114] refactor message finalization --- websocketpp/processors/hybi13.hpp | 32 +++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 8ff991ea5..ab250f90a 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -405,15 +405,10 @@ class hybi13 : public processor { // If this was the last frame in the message set the ready flag. // Otherwise, reset processor state to read additional frames. if (frame::get_fin(m_basic_header)) { - // ensure that text messages end on a valid UTF8 code point - if (frame::get_opcode(m_basic_header) == frame::opcode::TEXT) { - if (!m_current_msg->validator.complete()) { - ec = make_error_code(error::invalid_utf8); - break; - } + ec = finalize_message(); + if (ec) { + break; } - - m_state = READY; } else { this->reset_headers(); } @@ -427,6 +422,27 @@ class hybi13 : public processor { return p; } + /// Perform any finalization actions on an incoming message + /** + * Called after the full message is received. Provides the opportunity for + * extensions to complete any data post processing as well as final UTF8 + * validation checks for text messages. + * + * @return A code indicating errors, if any + */ + lib::error_code finalize_message() { + // ensure that text messages end on a valid UTF8 code point + if (frame::get_opcode(m_basic_header) == frame::opcode::TEXT) { + if (!m_current_msg->validator.complete()) { + return make_error_code(error::invalid_utf8); + } + } + + m_state = READY; + + return lib::error_code(); + } + void reset_headers() { m_state = HEADER_BASIC; m_bytes_needed = frame::BASIC_HEADER_LENGTH; From d0d97b860b90341ad2dd5b7bc7184b10c03ac7be Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:42:28 -0500 Subject: [PATCH 013/114] add permessage_deflate finalization code --- websocketpp/processors/hybi13.hpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index ab250f90a..7d627df35 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -431,6 +431,23 @@ class hybi13 : public processor { * @return A code indicating errors, if any */ lib::error_code finalize_message() { + std::string & out = m_current_msg->msg_ptr->get_raw_payload(); + + // if the frame is compressed, append the compression + // trailer and flush the compression buffer. + if (m_permessage_deflate.is_enabled() + && frame::get_rsv1(m_basic_header)) + { + uint8_t trailer[4] = {0x00, 0x00, 0xff, 0xff}; + + // Decompress current buffer into the message buffer + lib::error_code ec; + ec = m_permessage_deflate.decompress(trailer,4,out); + if (ec) { + return ec; + } + } + // ensure that text messages end on a valid UTF8 code point if (frame::get_opcode(m_basic_header) == frame::opcode::TEXT) { if (!m_current_msg->validator.complete()) { From 5323076007a07570c22f25a09437ec42c0e8e527 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:43:15 -0500 Subject: [PATCH 014/114] update permessage_deflate tests --- test/extension/permessage_deflate.cpp | 40 +++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index 67509fd20..af2d55995 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -500,44 +500,44 @@ BOOST_AUTO_TEST_CASE( negotiate_four_client_initiated ) { } // Compression -/* BOOST_AUTO_TEST_CASE( compress_data ) { ext_vars v; - std::string in = "Hello"; - std::string out; - std::string in2; - std::string out2; + std::string compress_in = "Hello"; + std::string compress_out; + std::string decompress_out; v.exts.init(); - v.ec = v.exts.compress(in,out); + v.ec = v.exts.compress(compress_in,compress_out); - std::cout << "in : " << websocketpp::utility::to_hex(in) << std::endl; BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); - std::cout << "out: " << websocketpp::utility::to_hex(out) << std::endl; - - in2 = out; - v.ec = v.exts.decompress(reinterpret_cast(in2.data()),in2.size(),out2); + v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); - std::cout << "out: " << websocketpp::utility::to_hex(out2) << std::endl; - BOOST_CHECK_EQUAL( out, out2 ); -} + BOOST_CHECK_EQUAL( compress_in, decompress_out ); +} +/// @todo: more compression tests +/** + * - compress two messages in a row + * - compress a message larger than the compression buffer + * - compress when no context takeover is enabled + * - compress at different compression levels + */ +// Decompression BOOST_AUTO_TEST_CASE( decompress_data ) { ext_vars v; - uint8_t in[12] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff}; - std::string out; + uint8_t in[11] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff}; + std::string out = ""; + std::string reference = "Hello"; v.exts.init(); - v.ec = v.exts.decompress(in,12,out); + v.ec = v.exts.decompress(in,11,out); BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); - std::cout << "out: " << websocketpp::utility::to_hex(out) << std::endl; - BOOST_CHECK( false ); + BOOST_CHECK_EQUAL( out, reference ); } -*/ \ No newline at end of file From 98a75b8cea3ee52704c4edcc334f2761c0e5c873 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:52:51 -0500 Subject: [PATCH 015/114] fix order of masking key initialization and use --- websocketpp/processors/hybi13.hpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 7d627df35..fd593e633 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -557,6 +557,11 @@ class hybi13 : public processor { && in->get_compressed(); bool fin = in->get_fin(); + if (masked) { + // Generate masking key. + key.i = m_rng(); + } + // prepare payload if (compressed) { // compress and store in o after header. @@ -586,11 +591,8 @@ class hybi13 : public processor { // generate header frame::basic_header h(op,o.size(),fin,masked,compressed); - + if (masked) { - // Generate masking key. - key.i = m_rng(); - frame::extended_header e(o.size(),key.i); out->set_header(frame::prepare_header(h,e)); } else { From 243cea16db84e818922d0de1817380b520689c98 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 11:58:43 -0500 Subject: [PATCH 016/114] update scratch examples --- SConstruct | 8 +- examples/print_server/SConscript | 2 +- examples/print_server/print_server.cpp | 44 +-------- .../SConscript | 6 +- .../scratch_client.cpp} | 0 examples/scratch_server/SConscript | 24 +++++ examples/scratch_server/scratch_server.cpp | 99 +++++++++++++++++++ 7 files changed, 135 insertions(+), 48 deletions(-) rename examples/{utility_client => scratch_client}/SConscript (78%) rename examples/{utility_client/utility_client.cpp => scratch_client/scratch_client.cpp} (100%) create mode 100644 examples/scratch_server/SConscript create mode 100644 examples/scratch_server/scratch_server.cpp diff --git a/SConstruct b/SConstruct index 3eee6f59a..69f2bd7fe 100644 --- a/SConstruct +++ b/SConstruct @@ -225,8 +225,12 @@ broadcast_server = SConscript('#/examples/broadcast_server/SConscript',variant_d # echo_client echo_client = SConscript('#/examples/echo_client/SConscript',variant_dir = builddir + 'echo_client',duplicate = 0) -# utility_client -utility_client = SConscript('#/examples/utility_client/SConscript',variant_dir = builddir + 'utility_client',duplicate = 0) +# scratch_client +scratch_client = SConscript('#/examples/scratch_client/SConscript',variant_dir = builddir + 'scratch_client',duplicate = 0) + +# scratch_server +scratch_server = SConscript('#/examples/scratch_server/SConscript',variant_dir = builddir + 'scratch_server',duplicate = 0) + # subprotocol_server subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',variant_dir = builddir + 'subprotocol_server',duplicate = 0) diff --git a/examples/print_server/SConscript b/examples/print_server/SConscript index 6d417a0f2..725ed77e3 100644 --- a/examples/print_server/SConscript +++ b/examples/print_server/SConscript @@ -14,7 +14,7 @@ prgs = [] # if a C++11 environment is available build using that, otherwise use boost if env_cpp11.has_key('WSPP_CPP11_ENABLED'): - ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z'] + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] prgs += env_cpp11.Program('print_server', ["print_server.cpp"], LIBS = ALL_LIBS) else: ALL_LIBS = boostlibs(['system','regex'],env) + [platform_libs] + [polyfill_libs] diff --git a/examples/print_server/print_server.cpp b/examples/print_server/print_server.cpp index e848c8b8a..4f47cae4f 100644 --- a/examples/print_server/print_server.cpp +++ b/examples/print_server/print_server.cpp @@ -1,49 +1,9 @@ #include -#include +#include #include -#include - -struct deflate_config : public websocketpp::config::debug_core { - typedef deflate_config type; - typedef debug_core base; - - typedef base::concurrency_type concurrency_type; - - typedef base::request_type request_type; - typedef base::response_type response_type; - - typedef base::message_type message_type; - typedef base::con_msg_manager_type con_msg_manager_type; - typedef base::endpoint_msg_manager_type endpoint_msg_manager_type; - - typedef base::alog_type alog_type; - typedef base::elog_type elog_type; - - typedef base::rng_type rng_type; - - struct transport_config : public base::transport_config { - typedef type::concurrency_type concurrency_type; - typedef type::alog_type alog_type; - typedef type::elog_type elog_type; - typedef type::request_type request_type; - typedef type::response_type response_type; - typedef websocketpp::transport::asio::basic_socket::endpoint - socket_type; - }; - - typedef websocketpp::transport::asio::endpoint - transport_type; - - /// permessage_compress extension - struct permessage_deflate_config {}; - - typedef websocketpp::extensions::permessage_deflate::enabled - permessage_deflate_type; -}; - -typedef websocketpp::server server; +typedef websocketpp::server server; void on_message(websocketpp::connection_hdl hdl, server::message_ptr msg) { std::cout << "on_message: " << msg->get_payload() << std::endl; diff --git a/examples/utility_client/SConscript b/examples/scratch_client/SConscript similarity index 78% rename from examples/utility_client/SConscript rename to examples/scratch_client/SConscript index 82625876a..dcb1a5369 100644 --- a/examples/utility_client/SConscript +++ b/examples/scratch_client/SConscript @@ -1,4 +1,4 @@ -## Utility client example +## Scratch client example ## Import('env') @@ -16,9 +16,9 @@ prgs = [] # if a C++11 environment is available build using that, otherwise use boost if env_cpp11.has_key('WSPP_CPP11_ENABLED'): ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs] - prgs += env_cpp11.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS) + prgs += env_cpp11.Program('scratch_client', ["scratch_client.cpp"], LIBS = ALL_LIBS) else: ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs] - prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS) + prgs += env.Program('scratch_client', ["scratch_client.cpp"], LIBS = ALL_LIBS) Return('prgs') diff --git a/examples/utility_client/utility_client.cpp b/examples/scratch_client/scratch_client.cpp similarity index 100% rename from examples/utility_client/utility_client.cpp rename to examples/scratch_client/scratch_client.cpp diff --git a/examples/scratch_server/SConscript b/examples/scratch_server/SConscript new file mode 100644 index 000000000..bf90f7433 --- /dev/null +++ b/examples/scratch_server/SConscript @@ -0,0 +1,24 @@ +## Scratch server example +## + +Import('env') +Import('env_cpp11') +Import('boostlibs') +Import('platform_libs') +Import('polyfill_libs') +Import('tls_libs') + +env = env.Clone () +env_cpp11 = env_cpp11.Clone () + +prgs = [] + +# if a C++11 environment is available build using that, otherwise use boost +if env_cpp11.has_key('WSPP_CPP11_ENABLED'): + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs] + ['z'] + prgs += env_cpp11.Program('scratch_server', ["scratch_server.cpp"], LIBS = ALL_LIBS) +else: + ALL_LIBS = boostlibs(['system','regex','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs] + ['z'] + prgs += env.Program('scratch_server', ["scratch_server.cpp"], LIBS = ALL_LIBS) + +Return('prgs') diff --git a/examples/scratch_server/scratch_server.cpp b/examples/scratch_server/scratch_server.cpp new file mode 100644 index 000000000..708719c77 --- /dev/null +++ b/examples/scratch_server/scratch_server.cpp @@ -0,0 +1,99 @@ +/** + * This example is presently used as a scratch space. It may or may not be broken + * at any given time. + */ + +#include + +#include +#include + +#include + +struct deflate_config : public websocketpp::config::debug_core { + typedef deflate_config type; + typedef debug_core base; + + typedef base::concurrency_type concurrency_type; + + typedef base::request_type request_type; + typedef base::response_type response_type; + + typedef base::message_type message_type; + typedef base::con_msg_manager_type con_msg_manager_type; + typedef base::endpoint_msg_manager_type endpoint_msg_manager_type; + + typedef base::alog_type alog_type; + typedef base::elog_type elog_type; + + typedef base::rng_type rng_type; + + struct transport_config : public base::transport_config { + typedef type::concurrency_type concurrency_type; + typedef type::alog_type alog_type; + typedef type::elog_type elog_type; + typedef type::request_type request_type; + typedef type::response_type response_type; + typedef websocketpp::transport::asio::basic_socket::endpoint + socket_type; + }; + + typedef websocketpp::transport::asio::endpoint + transport_type; + + /// permessage_compress extension + struct permessage_deflate_config {}; + + typedef websocketpp::extensions::permessage_deflate::enabled + permessage_deflate_type; +}; + +typedef websocketpp::server server; + +typedef server::message_ptr message_ptr; + +// Define a callback to handle incoming messages +void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) { + std::cout << "on_message called with hdl: " << hdl.lock().get() + << " and message: " << msg->get_payload() + << std::endl; + + try { + s->send(hdl, msg->get_payload(), msg->get_opcode()); + } catch (const websocketpp::lib::error_code& e) { + std::cout << "Echo failed because: " << e + << "(" << e.message() << ")" << std::endl; + } +} + +int main() { + // Create a server endpoint + server echo_server; + + try { + // Set logging settings + echo_server.set_access_channels(websocketpp::log::alevel::all); + echo_server.set_error_channels(websocketpp::log::elevel::all); + + // Initialize ASIO + echo_server.init_asio(); + + // Register our message handler + echo_server.set_message_handler(bind(&on_message,&echo_server,::_1,::_2)); + + // Listen on port 9002 + echo_server.listen(9002); + + // Start the server accept loop + echo_server.start_accept(); + + // Start the ASIO io_service run loop + echo_server.run(); + } catch (const std::exception & e) { + std::cout << e.what() << std::endl; + } catch (websocketpp::lib::error_code e) { + std::cout << e.message() << std::endl; + } catch (...) { + std::cout << "other exception" << std::endl; + } +} From f7376ccf46ee6e86178a31db905c5b9bd522661f Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 12:00:21 -0500 Subject: [PATCH 017/114] fix missing return value --- websocketpp/extensions/permessage_deflate/enabled.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index e76941130..6f71fd41a 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -437,7 +437,7 @@ class enabled { * @return Validation error or 0 on success */ lib::error_code validate_offer(http::attribute_list const & response) { - + return lib::error_code(); } /// Negotiate extension From 6920b39aa28be06b4ba4fb854b199fa291acb3b3 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 12:00:29 -0500 Subject: [PATCH 018/114] fix unused variable --- websocketpp/extensions/permessage_deflate/enabled.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 6f71fd41a..f5ba0c204 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -491,7 +491,6 @@ class enabled { } size_t output; - int ret; m_dstate.avail_in = in.size(); m_dstate.next_in = (unsigned char *)(const_cast(in.data())); @@ -501,7 +500,7 @@ class enabled { m_dstate.avail_out = m_compress_buffer_size; m_dstate.next_out = m_compress_buffer.get(); - ret = deflate(&m_dstate, Z_SYNC_FLUSH); + deflate(&m_dstate, Z_SYNC_FLUSH); output = m_compress_buffer_size - m_dstate.avail_out; From b809bf37061eb9398de9339d32440c8edd223a5a Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 12:08:16 -0500 Subject: [PATCH 019/114] ensure that the masking key is initialized --- websocketpp/processors/hybi13.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index fd593e633..680d83460 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -560,6 +560,8 @@ class hybi13 : public processor { if (masked) { // Generate masking key. key.i = m_rng(); + } else { + key.i = 0; } // prepare payload From c60e0895537445708fb4b5cbffc291d83c9839d1 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 16:10:03 -0500 Subject: [PATCH 020/114] add back to back message compression test --- test/extension/permessage_deflate.cpp | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index af2d55995..656afa0e3 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -510,17 +510,33 @@ BOOST_AUTO_TEST_CASE( compress_data ) { v.exts.init(); v.ec = v.exts.compress(compress_in,compress_out); - BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); - BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); BOOST_CHECK_EQUAL( compress_in, decompress_out ); } + +BOOST_AUTO_TEST_CASE( compress_data_multiple ) { + ext_vars v; + + v.exts.init(); + + for (int i = 0; i < 2; i++) { + std::string compress_in = "Hello"; + std::string compress_out; + std::string decompress_out; + + v.ec = v.exts.compress(compress_in,compress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + + v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + BOOST_CHECK_EQUAL( compress_in, decompress_out ); + } +} /// @todo: more compression tests /** - * - compress two messages in a row * - compress a message larger than the compression buffer * - compress when no context takeover is enabled * - compress at different compression levels From 11906dc2ceee979c70f2825c90b672aefdfde8d5 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 8 Jul 2013 16:15:45 -0500 Subject: [PATCH 021/114] Adds is_server detection flag to deflate extension init --- test/extension/permessage_deflate.cpp | 6 +++--- .../extensions/permessage_deflate/disabled.hpp | 2 +- .../extensions/permessage_deflate/enabled.hpp | 13 +++++++++---- websocketpp/processors/hybi13.hpp | 2 +- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index 656afa0e3..aafe3d1f1 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -507,7 +507,7 @@ BOOST_AUTO_TEST_CASE( compress_data ) { std::string compress_out; std::string decompress_out; - v.exts.init(); + v.exts.init(true); v.ec = v.exts.compress(compress_in,compress_out); BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); @@ -520,7 +520,7 @@ BOOST_AUTO_TEST_CASE( compress_data ) { BOOST_AUTO_TEST_CASE( compress_data_multiple ) { ext_vars v; - v.exts.init(); + v.exts.init(true); for (int i = 0; i < 2; i++) { std::string compress_in = "Hello"; @@ -550,7 +550,7 @@ BOOST_AUTO_TEST_CASE( decompress_data ) { std::string out = ""; std::string reference = "Hello"; - v.exts.init(); + v.exts.init(true); v.ec = v.exts.decompress(in,11,out); diff --git a/websocketpp/extensions/permessage_deflate/disabled.hpp b/websocketpp/extensions/permessage_deflate/disabled.hpp index 809c9e0a6..c87f00d45 100644 --- a/websocketpp/extensions/permessage_deflate/disabled.hpp +++ b/websocketpp/extensions/permessage_deflate/disabled.hpp @@ -58,7 +58,7 @@ class disabled { } /// Initialize state - lib::error_code init() { + lib::error_code init(bool is_server) { return lib::error_code(); } diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index f5ba0c204..5b5e022ce 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -49,7 +49,7 @@ namespace extensions { * ### permessage-deflate interface * * **init**\n - * `lib::error_code init()`\n + * `lib::error_code init(bool is_server)`\n * Performs initialization * * **is_implimented**\n @@ -246,15 +246,20 @@ class enabled { /// Initialize zlib state /** + * Note: this should be called *after* the negotiation methods. It will use + * information from the negotiation to determine how to initialize the zlib + * data structures. * * @todo memory level, strategy, etc are hardcoded - * @todo server detection is hardcoded + * + * @param is_server Whether or not to initialize as a server or client. + * @return A code representing the error that occurred, if any */ - lib::error_code init() { + lib::error_code init(bool is_server) { uint8_t deflate_bits; uint8_t inflate_bits; - if (true /*is_server*/) { + if (is_server) { deflate_bits = m_s2c_max_window_bits; inflate_bits = m_c2s_max_window_bits; } else { diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 680d83460..fcab6863b 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -127,7 +127,7 @@ class hybi13 : public processor { // Note: this list will need commas if WebSocket++ ever // supports more than one extension ret.second += neg_ret.second; - m_permessage_deflate.init(); + m_permessage_deflate.init(base::m_server); continue; } } From 4d63c10be7e1ebc69031c1d8590a11e9e555027d Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 9 Jul 2013 07:14:00 -0500 Subject: [PATCH 022/114] remove debug printing --- test/processors/hybi13.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/processors/hybi13.cpp b/test/processors/hybi13.cpp index fef93c350..d6c8eef63 100644 --- a/test/processors/hybi13.cpp +++ b/test/processors/hybi13.cpp @@ -655,8 +655,6 @@ BOOST_AUTO_TEST_CASE( extension_negotiation_permessage_deflate ) { std::pair neg_results; neg_results = env.p.negotiate_extensions(env.req); - std::cout << neg_results.first.message() << neg_results.second << std::endl; - BOOST_CHECK( !neg_results.first ); BOOST_CHECK_EQUAL( neg_results.second, "permessage-deflate" ); } From eb362007abaa383f9f12fb14aa5cff48eabf0841 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 9 Jul 2013 07:14:14 -0500 Subject: [PATCH 023/114] permessage_deflate tests --- test/extension/permessage_deflate.cpp | 69 ++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index aafe3d1f1..070a520b5 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Peter Thorson. All rights reserved. + * Copyright (c) 2013, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -535,9 +535,74 @@ BOOST_AUTO_TEST_CASE( compress_data_multiple ) { BOOST_CHECK_EQUAL( compress_in, decompress_out ); } } + +BOOST_AUTO_TEST_CASE( compress_data_large ) { + ext_vars v; + + std::string compress_in(600,'*'); + std::string compress_out; + std::string decompress_out; + + websocketpp::http::attribute_list alist; + + alist["s2c_max_window_bits"] = "8"; + v.exts.set_s2c_max_window_bits(8,websocketpp::extensions::permessage_deflate::mode::smallest); + + v.exts.negotiate(alist); + v.exts.init(true); + + v.ec = v.exts.compress(compress_in,compress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + + v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + BOOST_CHECK_EQUAL( compress_in, decompress_out ); +} + +BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { + ext_vars v; + + std::string compress_in = "Hello"; + std::string compress_out1; + std::string compress_out2; + std::string decompress_out; + + websocketpp::http::attribute_list alist; + + alist["s2c_no_context_takeover"] = ""; + v.exts.enable_s2c_no_context_takeover(); + + v.exts.negotiate(alist); + v.exts.init(true); + + v.ec = v.exts.compress(compress_in,compress_out1); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + + v.ec = v.exts.decompress( + reinterpret_cast(compress_out1.data()), + compress_out1.size(), + decompress_out + ); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + BOOST_CHECK_EQUAL( compress_in, decompress_out ); + + decompress_out = ""; + + v.ec = v.exts.compress(compress_in,compress_out2); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + + v.ec = v.exts.decompress( + reinterpret_cast(compress_out2.data()), + compress_out2.size(), + decompress_out + ); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + BOOST_CHECK_EQUAL( compress_in, decompress_out ); + + BOOST_CHECK_NE( compress_out1, compress_out2 ); +} /// @todo: more compression tests /** - * - compress a message larger than the compression buffer * - compress when no context takeover is enabled * - compress at different compression levels */ From b8d962950fdd7b848e6cd522700055e66167beb3 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 10 Jul 2013 20:16:19 -0500 Subject: [PATCH 024/114] impliment no_context_takeover options --- test/extension/permessage_deflate.cpp | 3 +-- .../extensions/permessage_deflate/enabled.hpp | 13 ++++++++++--- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index 070a520b5..d06a4a7bf 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -599,11 +599,10 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); BOOST_CHECK_EQUAL( compress_in, decompress_out ); - BOOST_CHECK_NE( compress_out1, compress_out2 ); + BOOST_CHECK_EQUAL( compress_out1, compress_out2 ); } /// @todo: more compression tests /** - * - compress when no context takeover is enabled * - compress at different compression levels */ diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 5b5e022ce..91439701b 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -290,6 +290,13 @@ class enabled { } m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]); + if ((m_s2c_no_context_takeover && is_server) || + (m_c2s_no_context_takeover && !is_server)) + { + m_flush = Z_FULL_FLUSH; + } else { + m_flush = Z_SYNC_FLUSH; + } m_initialized = true; return lib::error_code(); } @@ -504,9 +511,8 @@ class enabled { // Output to local buffer m_dstate.avail_out = m_compress_buffer_size; m_dstate.next_out = m_compress_buffer.get(); - - deflate(&m_dstate, Z_SYNC_FLUSH); - + + deflate(&m_dstate, m_flush); output = m_compress_buffer_size - m_dstate.avail_out; out.append((char *)(m_compress_buffer.get()),output); @@ -719,6 +725,7 @@ class enabled { mode::value m_c2s_max_window_bits_mode; bool m_initialized; + int m_flush; size_t m_compress_buffer_size; lib::unique_ptr_uchar_array m_compress_buffer; z_stream m_dstate; From 475c478a2e30f82f84493ef5d086476402c9558b Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 12 Jul 2013 08:29:34 -0500 Subject: [PATCH 025/114] protect against compress returning nothing --- websocketpp/processors/hybi13.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index fcab6863b..5aecb4352 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -569,6 +569,10 @@ class hybi13 : public processor { // compress and store in o after header. m_permessage_deflate.compress(i,o); + if (o.size() < 4) { + return make_error_code(error::general); + } + // Strip trailing 4 0x00 0x00 0xff 0xff bytes before writing to the // wire o.resize(o.size()-4); From e967ffc74da382d35dd18590e90f0f5386047cfd Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 12 Jul 2013 08:30:51 -0500 Subject: [PATCH 026/114] silence stratch server --- examples/scratch_server/scratch_server.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/scratch_server/scratch_server.cpp b/examples/scratch_server/scratch_server.cpp index 708719c77..d9f8e982d 100644 --- a/examples/scratch_server/scratch_server.cpp +++ b/examples/scratch_server/scratch_server.cpp @@ -54,10 +54,10 @@ typedef server::message_ptr message_ptr; // Define a callback to handle incoming messages void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) { - std::cout << "on_message called with hdl: " << hdl.lock().get() - << " and message: " << msg->get_payload() + /*std::cout << "on_message called with hdl: " << hdl.lock().get() + << " and message (" << msg->get_payload().size() << "): " << msg->get_payload() << std::endl; - +*/ try { s->send(hdl, msg->get_payload(), msg->get_opcode()); } catch (const websocketpp::lib::error_code& e) { @@ -72,8 +72,8 @@ int main() { try { // Set logging settings - echo_server.set_access_channels(websocketpp::log::alevel::all); - echo_server.set_error_channels(websocketpp::log::elevel::all); + echo_server.set_access_channels(websocketpp::log::alevel::none); + echo_server.set_error_channels(websocketpp::log::elevel::none); // Initialize ASIO echo_server.init_asio(); From 48add58dc2f2635137176ab3cdaa5248ccc992e4 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 12 Jul 2013 08:35:49 -0500 Subject: [PATCH 027/114] update compression tests --- test/extension/permessage_deflate.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index d06a4a7bf..7bcb24487 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -601,6 +601,32 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { BOOST_CHECK_EQUAL( compress_out1, compress_out2 ); } + +BOOST_AUTO_TEST_CASE( compress_empty ) { + ext_vars v; + + std::string compress_in = ""; + std::string compress_out; + std::string decompress_out; + + v.exts.init(true); + + v.ec = v.exts.compress(compress_in,compress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + + v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); + + compress_out = ""; + decompress_out = ""; + + v.ec = v.exts.compress(compress_in,compress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + + v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); + BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); + BOOST_CHECK_EQUAL( compress_in, decompress_out ); +} + /// @todo: more compression tests /** * - compress at different compression levels From 9a73b74a37b2d7c551868701c4216bb97927e209 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 12 Jul 2013 08:37:08 -0500 Subject: [PATCH 028/114] fix to ensure empty messages are handled correctly --- websocketpp/extensions/permessage_deflate/enabled.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 91439701b..37c6914af 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -493,6 +493,9 @@ class enabled { /// Compress bytes /** + * @todo: avail_in/out is 32 bit, need to fix for cases of >32 bit frames + * on 64 bit machines. + * * @param [in] in String to compress * @param [out] out String to append compressed bytes to * @return Error or status code @@ -503,6 +506,12 @@ class enabled { } size_t output; + + if (in.empty()) { + uint8_t buf[6] = {0x02, 0x00, 0x00, 0x00, 0xff, 0xff}; + out.append((char *)(buf),6); + return lib::error_code(); + } m_dstate.avail_in = in.size(); m_dstate.next_in = (unsigned char *)(const_cast(in.data())); From ccbd93f7256c9171e75875962dafcb84eb94ebd0 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 12 Jul 2013 15:53:40 -0500 Subject: [PATCH 029/114] add a debug mode switch --- examples/scratch_server/scratch_server.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/scratch_server/scratch_server.cpp b/examples/scratch_server/scratch_server.cpp index d9f8e982d..a547f0c70 100644 --- a/examples/scratch_server/scratch_server.cpp +++ b/examples/scratch_server/scratch_server.cpp @@ -66,14 +66,19 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) { } } -int main() { +int main(int argc, char * argv[]) { // Create a server endpoint server echo_server; try { - // Set logging settings - echo_server.set_access_channels(websocketpp::log::alevel::none); - echo_server.set_error_channels(websocketpp::log::elevel::none); + // Set logging settings + if (argc > 1 && std::string(argv[1]) == "-d") { + echo_server.set_access_channels(websocketpp::log::alevel::all); + echo_server.set_error_channels(websocketpp::log::elevel::all); + } else { + echo_server.set_access_channels(websocketpp::log::alevel::none); + echo_server.set_error_channels(websocketpp::log::elevel::none); + } // Initialize ASIO echo_server.init_asio(); From eb314e55de7ca56b68709d1f66630ededae89fe5 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Mon, 15 Jul 2013 11:08:05 -0500 Subject: [PATCH 030/114] retry build --- examples/scratch_server/scratch_server.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/scratch_server/scratch_server.cpp b/examples/scratch_server/scratch_server.cpp index a547f0c70..32c395f16 100644 --- a/examples/scratch_server/scratch_server.cpp +++ b/examples/scratch_server/scratch_server.cpp @@ -57,7 +57,7 @@ void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg) { /*std::cout << "on_message called with hdl: " << hdl.lock().get() << " and message (" << msg->get_payload().size() << "): " << msg->get_payload() << std::endl; -*/ + */ try { s->send(hdl, msg->get_payload(), msg->get_opcode()); } catch (const websocketpp::lib::error_code& e) { From e62823a0af12b4b6e4e8d7856149799fde55be43 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 16 Oct 2013 06:29:46 -0500 Subject: [PATCH 031/114] update deflate constants --- websocketpp/extensions/permessage_deflate/enabled.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 278261b1c..d8011a98c 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -272,8 +272,8 @@ class enabled { Z_DEFAULT_COMPRESSION, Z_DEFLATED, -1*deflate_bits, - 8, // memory level 1-9 - /*Z_DEFAULT_STRATEGY*/Z_FIXED + 4, // memory level 1-9 + Z_DEFAULT_STRATEGY ); if (ret != Z_OK) { From aabf87b6b1c12d6bb5f50673df7482353020819e Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 25 Mar 2014 19:35:07 -0500 Subject: [PATCH 032/114] add missing tls libraries --- examples/scratch_client/SConscript | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/scratch_client/SConscript b/examples/scratch_client/SConscript index 4c6c6a811..6e7b2ef07 100644 --- a/examples/scratch_client/SConscript +++ b/examples/scratch_client/SConscript @@ -6,6 +6,7 @@ Import('env_cpp11') Import('boostlibs') Import('platform_libs') Import('polyfill_libs') +Import('tls_libs') env = env.Clone () env_cpp11 = env_cpp11.Clone () From 2ee496c08d5d440a865c8cdd35a56f36c7d5d34f Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 25 Mar 2014 19:35:24 -0500 Subject: [PATCH 033/114] update parameter fields to latest draft --- .../extensions/permessage_deflate/enabled.hpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 9e5de6ae6..e6ce30196 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -468,13 +468,13 @@ class enabled { http::attribute_list::const_iterator it; for (it = offer.begin(); it != offer.end(); ++it) { - if (it->first == "s2c_no_context_takeover") { + if (it->first == "server_no_context_takeover") { negotiate_s2c_no_context_takeover(it->second,ret.first); - } else if (it->first == "c2s_no_context_takeover") { + } else if (it->first == "client_no_context_takeover") { negotiate_c2s_no_context_takeover(it->second,ret.first); - } else if (it->first == "s2c_max_window_bits") { + } else if (it->first == "server_max_window_bits") { negotiate_s2c_max_window_bits(it->second,ret.first); - } else if (it->first == "c2s_max_window_bits") { + } else if (it->first == "client_max_window_bits") { negotiate_c2s_max_window_bits(it->second,ret.first); } else { ret.first = make_error_code(error::invalid_attributes); @@ -579,23 +579,23 @@ class enabled { std::string ret = "permessage-deflate"; if (m_s2c_no_context_takeover) { - ret += "; s2c_no_context_takeover"; + ret += "; server_no_context_takeover"; } if (m_c2s_no_context_takeover) { - ret += "; c2s_no_context_takeover"; + ret += "; client_no_context_takeover"; } if (m_s2c_max_window_bits < default_s2c_max_window_bits) { std::stringstream s; s << int(m_s2c_max_window_bits); - ret += "; s2c_max_window_bits="+s.str(); + ret += "; server_max_window_bits="+s.str(); } if (m_c2s_max_window_bits < default_c2s_max_window_bits) { std::stringstream s; s << int(m_c2s_max_window_bits); - ret += "; c2s_max_window_bits="+s.str(); + ret += "; client_max_window_bits="+s.str(); } return ret; From 75dd6f3ba525b3d022c65df00e1c9a31b56e7417 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 25 Mar 2014 19:43:11 -0500 Subject: [PATCH 034/114] fix negotiating multiple copies of the same extension --- websocketpp/processors/hybi13.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 5df9f1a97..44612db66 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -115,6 +115,14 @@ class hybi13 : public processor { 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); if (neg_ret.first) { From 884e7d210c081513d783a08065b59ee6c1ce3ec6 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 26 Mar 2014 06:47:28 -0500 Subject: [PATCH 035/114] this is just wrong, removing --- websocketpp/processors/hybi13.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 44612db66..bd5d4e68b 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -777,9 +777,6 @@ class hybi13 : public processor { if (ec) { return 0; } - - // get the length of the newly uncompressed output - offset = out.size() - offset; } else { // No compression, straight copy out.append(reinterpret_cast(buf),len); From 99ae2f768c805acc39e295ea07b361d84b056aa0 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 26 Mar 2014 06:48:26 -0500 Subject: [PATCH 036/114] fix issue where fragmented messages weren't getting decompressed correctly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit the rsv1 bit is only set for the first fragment. check it then and store the result in the message’s compressed flag instead. --- websocketpp/processors/hybi13.hpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index bd5d4e68b..247dd35ce 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -387,6 +387,10 @@ class hybi13 : public processor { m_msg_manager->get_message(op,m_bytes_needed), frame::get_masking_key(m_basic_header,m_extended_header) ); + + if (m_permessage_deflate.is_enabled()) { + m_data_msg.msg_ptr->set_compressed(frame::get_rsv1(m_basic_header)); + } } else { // Fetch the underlying payload buffer from the data message we // are writing into. @@ -459,7 +463,7 @@ class hybi13 : public processor { // if the frame is compressed, append the compression // trailer and flush the compression buffer. if (m_permessage_deflate.is_enabled() - && frame::get_rsv1(m_basic_header)) + && m_current_msg->msg_ptr->get_compressed()) { uint8_t trailer[4] = {0x00, 0x00, 0xff, 0xff}; @@ -770,7 +774,7 @@ class hybi13 : public processor { // decompress message if needed. if (m_permessage_deflate.is_enabled() - && frame::get_rsv1(m_basic_header)) + && m_current_msg->msg_ptr->get_compressed()) { // Decompress current buffer into the message buffer ec = m_permessage_deflate.decompress(buf,len,out); From 70923eea230ebd6fa50d328497cda790f64882aa Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 26 Mar 2014 06:48:36 -0500 Subject: [PATCH 037/114] remove raw cout debug code --- websocketpp/processors/hybi13.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 247dd35ce..b3615fcc9 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -129,8 +129,8 @@ class hybi13 : public processor { // 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; + //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 From 7f7e9d2c2c783faf78824d467bc7f8e83ed375b2 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 26 Mar 2014 07:19:35 -0500 Subject: [PATCH 038/114] update interface and unit tests for new permessage-deflate parameter names --- test/extension/permessage_deflate.cpp | 224 +++++++++--------- test/processors/hybi13.cpp | 2 +- .../extensions/permessage_deflate/enabled.hpp | 168 ++++++------- 3 files changed, 197 insertions(+), 197 deletions(-) diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index 881396c9d..06ace5e2c 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -100,10 +100,10 @@ BOOST_AUTO_TEST_CASE( negotiation_invalid_attr ) { BOOST_CHECK_EQUAL( v.esp.second, ""); } -// Negotiate s2c_no_context_takeover -BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover_invalid ) { +// Negotiate server_no_context_takeover +BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover_invalid ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = "foo"; + v.attr["server_no_context_takeover"] = "foo"; v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( !v.exts.is_enabled() ); @@ -111,30 +111,30 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover_invalid ) { BOOST_CHECK_EQUAL( v.esp.second, ""); } -BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover ) { +BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"] = ""; 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; s2c_no_context_takeover"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover"); } -BOOST_AUTO_TEST_CASE( negotiate_s2c_no_context_takeover_server_initiated ) { +BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover_server_initiated ) { ext_vars v; - v.exts.enable_s2c_no_context_takeover(); + v.exts.enable_server_no_context_takeover(); 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; s2c_no_context_takeover"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover"); } -// Negotiate c2s_no_context_takeover -BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover_invalid ) { +// Negotiate client_no_context_takeover +BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover_invalid ) { ext_vars v; - v.attr["c2s_no_context_takeover"] = "foo"; + v.attr["client_no_context_takeover"] = "foo"; v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( !v.exts.is_enabled() ); @@ -142,29 +142,29 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover_invalid ) { BOOST_CHECK_EQUAL( v.esp.second, ""); } -BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover ) { +BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover ) { ext_vars v; - v.attr["c2s_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"] = ""; 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; c2s_no_context_takeover"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover"); } -BOOST_AUTO_TEST_CASE( negotiate_c2s_no_context_takeover_server_initiated ) { +BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover_server_initiated ) { ext_vars v; - v.exts.enable_c2s_no_context_takeover(); + v.exts.enable_client_no_context_takeover(); 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; c2s_no_context_takeover"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover"); } -// Negotiate s2c_max_window_bits -BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_invalid ) { +// Negotiate server_max_window_bits +BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_invalid ) { ext_vars v; std::vector values; @@ -175,7 +175,7 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_invalid ) { std::vector::const_iterator it; for (it = values.begin(); it != values.end(); ++it) { - v.attr["s2c_max_window_bits"] = *it; + v.attr["server_max_window_bits"] = *it; v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( !v.exts.is_enabled() ); @@ -184,16 +184,16 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_invalid ) { } } -BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_valid ) { +BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_valid ) { ext_vars v; - v.attr["s2c_max_window_bits"] = "8"; + 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; s2c_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8"); - v.attr["s2c_max_window_bits"] = "15"; + v.attr["server_max_window_bits"] = "15"; v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( v.exts.is_enabled() ); @@ -201,21 +201,21 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_valid ) { BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate"); } -BOOST_AUTO_TEST_CASE( invalid_set_s2c_max_window_bits ) { +BOOST_AUTO_TEST_CASE( invalid_set_server_max_window_bits ) { ext_vars v; - v.ec = v.exts.set_s2c_max_window_bits(7,pmd_mode::decline); + v.ec = v.exts.set_server_max_window_bits(7,pmd_mode::decline); BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits)); - v.ec = v.exts.set_s2c_max_window_bits(16,pmd_mode::decline); + v.ec = v.exts.set_server_max_window_bits(16,pmd_mode::decline); BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits)); } -BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_decline ) { +BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_decline ) { ext_vars v; - v.attr["s2c_max_window_bits"] = "8"; + v.attr["server_max_window_bits"] = "8"; - v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::decline); + v.ec = v.exts.set_server_max_window_bits(15,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() ); @@ -223,44 +223,44 @@ BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_decline ) { BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate"); } -BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_accept ) { +BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_accept ) { ext_vars v; - v.attr["s2c_max_window_bits"] = "8"; + v.attr["server_max_window_bits"] = "8"; - v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::accept); + 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; s2c_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8"); } -BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_largest ) { +BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_largest ) { ext_vars v; - v.attr["s2c_max_window_bits"] = "8"; + v.attr["server_max_window_bits"] = "8"; - v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::largest); + 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; s2c_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8"); } -BOOST_AUTO_TEST_CASE( negotiate_s2c_max_window_bits_smallest ) { +BOOST_AUTO_TEST_CASE( negotiate_server_max_window_bits_smallest ) { ext_vars v; - v.attr["s2c_max_window_bits"] = "8"; + v.attr["server_max_window_bits"] = "8"; - v.ec = v.exts.set_s2c_max_window_bits(15,pmd_mode::smallest); + 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; s2c_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=8"); } -// Negotiate s2c_max_window_bits -BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_invalid ) { +// Negotiate server_max_window_bits +BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_invalid ) { ext_vars v; std::vector values; @@ -270,7 +270,7 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_invalid ) { std::vector::const_iterator it; for (it = values.begin(); it != values.end(); ++it) { - v.attr["c2s_max_window_bits"] = *it; + v.attr["client_max_window_bits"] = *it; v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( !v.exts.is_enabled() ); @@ -279,43 +279,43 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_invalid ) { } } -BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_valid ) { +BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_valid ) { ext_vars v; - v.attr["c2s_max_window_bits"] = ""; + v.attr["client_max_window_bits"] = ""; 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"); - v.attr["c2s_max_window_bits"] = "8"; + v.attr["client_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; c2s_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8"); - v.attr["c2s_max_window_bits"] = "15"; + v.attr["client_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() ); BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate"); } -BOOST_AUTO_TEST_CASE( invalid_set_c2s_max_window_bits ) { +BOOST_AUTO_TEST_CASE( invalid_set_client_max_window_bits ) { ext_vars v; - v.ec = v.exts.set_c2s_max_window_bits(7,pmd_mode::decline); + v.ec = v.exts.set_client_max_window_bits(7,pmd_mode::decline); BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits)); - v.ec = v.exts.set_c2s_max_window_bits(16,pmd_mode::decline); + v.ec = v.exts.set_client_max_window_bits(16,pmd_mode::decline); BOOST_CHECK_EQUAL(v.ec,pmde::make_error_code(pmde::invalid_max_window_bits)); } -BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_decline ) { +BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_decline ) { ext_vars v; - v.attr["c2s_max_window_bits"] = "8"; + v.attr["client_max_window_bits"] = "8"; - v.ec = v.exts.set_c2s_max_window_bits(8,pmd_mode::decline); + v.ec = v.exts.set_client_max_window_bits(8,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() ); @@ -323,40 +323,40 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_decline ) { BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate"); } -BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_accept ) { +BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_accept ) { ext_vars v; - v.attr["c2s_max_window_bits"] = "8"; + v.attr["client_max_window_bits"] = "8"; - v.ec = v.exts.set_c2s_max_window_bits(15,pmd_mode::accept); + 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; c2s_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8"); } -BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_largest ) { +BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_largest ) { ext_vars v; - v.attr["c2s_max_window_bits"] = "8"; + v.attr["client_max_window_bits"] = "8"; - v.ec = v.exts.set_c2s_max_window_bits(15,pmd_mode::largest); + 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; c2s_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8"); } -BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_smallest ) { +BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) { ext_vars v; - v.attr["c2s_max_window_bits"] = "8"; + v.attr["client_max_window_bits"] = "8"; - v.ec = v.exts.set_c2s_max_window_bits(15,pmd_mode::smallest); + 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; c2s_max_window_bits=8"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_max_window_bits=8"); } @@ -364,139 +364,139 @@ BOOST_AUTO_TEST_CASE( negotiate_c2s_max_window_bits_smallest ) { BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated1 ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["c2s_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"] = ""; 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; s2c_no_context_takeover; c2s_no_context_takeover"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover"); } BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated2 ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["s2c_max_window_bits"] = "10"; + v.attr["server_no_context_takeover"] = ""; + v.attr["server_max_window_bits"] = "10"; 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; s2c_no_context_takeover; s2c_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; server_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated3 ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["server_no_context_takeover"] = ""; + v.attr["client_max_window_bits"] = "10"; 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; s2c_no_context_takeover; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated4 ) { ext_vars v; - v.attr["c2s_no_context_takeover"] = ""; - v.attr["s2c_max_window_bits"] = "10"; + v.attr["client_no_context_takeover"] = ""; + v.attr["server_max_window_bits"] = "10"; 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; c2s_no_context_takeover; s2c_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover; server_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated5 ) { ext_vars v; - v.attr["c2s_no_context_takeover"] = ""; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["client_no_context_takeover"] = ""; + v.attr["client_max_window_bits"] = "10"; 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; c2s_no_context_takeover; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover; client_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated6 ) { ext_vars v; - v.attr["s2c_max_window_bits"] = "10"; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["server_max_window_bits"] = "10"; + v.attr["client_max_window_bits"] = "10"; 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; s2c_max_window_bits=10; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_max_window_bits=10; client_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated1 ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["c2s_no_context_takeover"] = ""; - v.attr["s2c_max_window_bits"] = "10"; + v.attr["server_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"] = ""; + v.attr["server_max_window_bits"] = "10"; 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; s2c_no_context_takeover; c2s_no_context_takeover; s2c_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover; server_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated2 ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["c2s_no_context_takeover"] = ""; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["server_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"] = ""; + v.attr["client_max_window_bits"] = "10"; 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; s2c_no_context_takeover; c2s_no_context_takeover; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover; client_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated3 ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["s2c_max_window_bits"] = "10"; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["server_no_context_takeover"] = ""; + v.attr["server_max_window_bits"] = "10"; + v.attr["client_max_window_bits"] = "10"; 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; s2c_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; server_max_window_bits=10; client_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated4 ) { ext_vars v; - v.attr["c2s_no_context_takeover"] = ""; - v.attr["s2c_max_window_bits"] = "10"; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["client_no_context_takeover"] = ""; + v.attr["server_max_window_bits"] = "10"; + v.attr["client_max_window_bits"] = "10"; 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; c2s_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; client_no_context_takeover; server_max_window_bits=10; client_max_window_bits=10"); } BOOST_AUTO_TEST_CASE( negotiate_four_client_initiated ) { ext_vars v; - v.attr["s2c_no_context_takeover"] = ""; - v.attr["c2s_no_context_takeover"] = ""; - v.attr["s2c_max_window_bits"] = "10"; - v.attr["c2s_max_window_bits"] = "10"; + v.attr["server_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"] = ""; + v.attr["server_max_window_bits"] = "10"; + v.attr["client_max_window_bits"] = "10"; 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; s2c_no_context_takeover; c2s_no_context_takeover; s2c_max_window_bits=10; c2s_max_window_bits=10"); + BOOST_CHECK_EQUAL( v.esp.second, "permessage-deflate; server_no_context_takeover; client_no_context_takeover; server_max_window_bits=10; client_max_window_bits=10"); } // Compression @@ -545,8 +545,8 @@ BOOST_AUTO_TEST_CASE( compress_data_large ) { websocketpp::http::attribute_list alist; - alist["s2c_max_window_bits"] = "8"; - v.exts.set_s2c_max_window_bits(8,websocketpp::extensions::permessage_deflate::mode::smallest); + alist["server_max_window_bits"] = "8"; + v.exts.set_server_max_window_bits(8,websocketpp::extensions::permessage_deflate::mode::smallest); v.exts.negotiate(alist); v.exts.init(true); @@ -569,8 +569,8 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { websocketpp::http::attribute_list alist; - alist["s2c_no_context_takeover"] = ""; - v.exts.enable_s2c_no_context_takeover(); + alist["server_no_context_takeover"] = ""; + v.exts.enable_server_no_context_takeover(); v.exts.negotiate(alist); v.exts.init(true); diff --git a/test/processors/hybi13.cpp b/test/processors/hybi13.cpp index e4c1bff2f..18fdf83f9 100644 --- a/test/processors/hybi13.cpp +++ b/test/processors/hybi13.cpp @@ -682,7 +682,7 @@ BOOST_AUTO_TEST_CASE( extension_negotiation_permessage_deflate ) { processor_setup_ext env(true); env.req.replace_header("Sec-WebSocket-Extensions", - "permessage-deflate; c2s_max_window_bits"); + "permessage-deflate; client_max_window_bits"); std::pair neg_results; neg_results = env.p.negotiate_extensions(env.req); diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index e6ce30196..dc6352a5f 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -174,19 +174,19 @@ namespace websocketpp { namespace extensions { namespace permessage_deflate { -/// Default value for s2c_max_window_bits as defined by RFC6455 -static uint8_t const default_s2c_max_window_bits = 15; -/// Minimum value for s2c_max_window_bits as defined by RFC6455 -static uint8_t const min_s2c_max_window_bits = 8; -/// Maximum value for s2c_max_window_bits as defined by RFC6455 -static uint8_t const max_s2c_max_window_bits = 15; - -/// Default value for c2s_max_window_bits as defined by RFC6455 -static uint8_t const default_c2s_max_window_bits = 15; -/// Minimum value for c2s_max_window_bits as defined by RFC6455 -static uint8_t const min_c2s_max_window_bits = 8; -/// Maximum value for c2s_max_window_bits as defined by RFC6455 -static uint8_t const max_c2s_max_window_bits = 15; +/// Default value for server_max_window_bits as defined by RFC6455 +static uint8_t const default_server_max_window_bits = 15; +/// Minimum value for server_max_window_bits as defined by RFC6455 +static uint8_t const min_server_max_window_bits = 8; +/// Maximum value for server_max_window_bits as defined by RFC6455 +static uint8_t const max_server_max_window_bits = 15; + +/// Default value for client_max_window_bits as defined by RFC6455 +static uint8_t const default_client_max_window_bits = 15; +/// Minimum value for client_max_window_bits as defined by RFC6455 +static uint8_t const min_client_max_window_bits = 8; +/// Maximum value for client_max_window_bits as defined by RFC6455 +static uint8_t const max_client_max_window_bits = 15; namespace mode { enum value { @@ -206,12 +206,12 @@ class enabled { public: enabled() : m_enabled(false) - , m_s2c_no_context_takeover(false) - , m_c2s_no_context_takeover(false) - , m_s2c_max_window_bits(15) - , m_c2s_max_window_bits(15) - , m_s2c_max_window_bits_mode(mode::accept) - , m_c2s_max_window_bits_mode(mode::accept) + , m_server_no_context_takeover(false) + , m_client_no_context_takeover(false) + , m_server_max_window_bits(15) + , m_client_max_window_bits(15) + , m_server_max_window_bits_mode(mode::accept) + , m_client_max_window_bits_mode(mode::accept) , m_initialized(false) , m_compress_buffer_size(16384) { @@ -262,11 +262,11 @@ class enabled { uint8_t inflate_bits; if (is_server) { - deflate_bits = m_s2c_max_window_bits; - inflate_bits = m_c2s_max_window_bits; + deflate_bits = m_server_max_window_bits; + inflate_bits = m_client_max_window_bits; } else { - deflate_bits = m_c2s_max_window_bits; - inflate_bits = m_s2c_max_window_bits; + deflate_bits = m_client_max_window_bits; + inflate_bits = m_server_max_window_bits; } int ret = deflateInit2( @@ -292,8 +292,8 @@ class enabled { } m_compress_buffer.reset(new unsigned char[m_compress_buffer_size]); - if ((m_s2c_no_context_takeover && is_server) || - (m_c2s_no_context_takeover && !is_server)) + if ((m_server_no_context_takeover && is_server) || + (m_client_no_context_takeover && !is_server)) { m_flush = Z_FULL_FLUSH; } else { @@ -345,8 +345,8 @@ class enabled { * the option will be in use so they can optimize resource usage if they * are able. */ - void enable_s2c_no_context_takeover() { - m_s2c_no_context_takeover = true; + void enable_server_no_context_takeover() { + m_server_no_context_takeover = true; } /// Reset client's outgoing LZ77 sliding window for each new message @@ -364,8 +364,8 @@ class enabled { * This option is supported by all compliant clients and servers. Enabling * it via either endpoint should be sufficient to ensure it is used. */ - void enable_c2s_no_context_takeover() { - m_c2s_no_context_takeover = true; + void enable_client_no_context_takeover() { + m_client_no_context_takeover = true; } /// Limit server LZ77 sliding window size @@ -390,12 +390,12 @@ class enabled { * @param mode The mode to use for negotiating this parameter * @return A status code */ - lib::error_code set_s2c_max_window_bits(uint8_t bits, mode::value mode) { - if (bits < min_s2c_max_window_bits || bits > max_s2c_max_window_bits) { + lib::error_code set_server_max_window_bits(uint8_t bits, mode::value mode) { + if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) { return error::make_error_code(error::invalid_max_window_bits); } - m_s2c_max_window_bits = bits; - m_s2c_max_window_bits_mode = mode; + m_server_max_window_bits = bits; + m_server_max_window_bits_mode = mode; return lib::error_code(); } @@ -421,12 +421,12 @@ class enabled { * @param mode The mode to use for negotiating this parameter * @return A status code */ - lib::error_code set_c2s_max_window_bits(uint8_t bits, mode::value mode) { - if (bits < min_c2s_max_window_bits || bits > max_c2s_max_window_bits) { + lib::error_code set_client_max_window_bits(uint8_t bits, mode::value mode) { + if (bits < min_client_max_window_bits || bits > max_client_max_window_bits) { return error::make_error_code(error::invalid_max_window_bits); } - m_c2s_max_window_bits = bits; - m_c2s_max_window_bits_mode = mode; + m_client_max_window_bits = bits; + m_client_max_window_bits_mode = mode; return lib::error_code(); } @@ -469,13 +469,13 @@ class enabled { http::attribute_list::const_iterator it; for (it = offer.begin(); it != offer.end(); ++it) { if (it->first == "server_no_context_takeover") { - negotiate_s2c_no_context_takeover(it->second,ret.first); + negotiate_server_no_context_takeover(it->second,ret.first); } else if (it->first == "client_no_context_takeover") { - negotiate_c2s_no_context_takeover(it->second,ret.first); + negotiate_client_no_context_takeover(it->second,ret.first); } else if (it->first == "server_max_window_bits") { - negotiate_s2c_max_window_bits(it->second,ret.first); + negotiate_server_max_window_bits(it->second,ret.first); } else if (it->first == "client_max_window_bits") { - negotiate_c2s_max_window_bits(it->second,ret.first); + negotiate_client_max_window_bits(it->second,ret.first); } else { ret.first = make_error_code(error::invalid_attributes); } @@ -578,35 +578,35 @@ class enabled { std::string generate_response() { std::string ret = "permessage-deflate"; - if (m_s2c_no_context_takeover) { + if (m_server_no_context_takeover) { ret += "; server_no_context_takeover"; } - if (m_c2s_no_context_takeover) { + if (m_client_no_context_takeover) { ret += "; client_no_context_takeover"; } - if (m_s2c_max_window_bits < default_s2c_max_window_bits) { + if (m_server_max_window_bits < default_server_max_window_bits) { std::stringstream s; - s << int(m_s2c_max_window_bits); + s << int(m_server_max_window_bits); ret += "; server_max_window_bits="+s.str(); } - if (m_c2s_max_window_bits < default_c2s_max_window_bits) { + if (m_client_max_window_bits < default_client_max_window_bits) { std::stringstream s; - s << int(m_c2s_max_window_bits); + s << int(m_client_max_window_bits); ret += "; client_max_window_bits="+s.str(); } return ret; } - /// Negotiate s2c_no_context_takeover attribute + /// Negotiate server_no_context_takeover attribute /** * @param [in] value The value of the attribute from the offer * @param [out] ec A reference to the error code to return errors via */ - void negotiate_s2c_no_context_takeover(std::string const & value, + void negotiate_server_no_context_takeover(std::string const & value, lib::error_code & ec) { if (!value.empty()) { @@ -614,15 +614,15 @@ class enabled { return; } - m_s2c_no_context_takeover = true; + m_server_no_context_takeover = true; } - /// Negotiate c2s_no_context_takeover attribute + /// Negotiate client_no_context_takeover attribute /** * @param [in] value The value of the attribute from the offer * @param [out] ec A reference to the error code to return errors via */ - void negotiate_c2s_no_context_takeover(std::string const & value, + void negotiate_client_no_context_takeover(std::string const & value, lib::error_code & ec) { if (!value.empty()) { @@ -630,13 +630,13 @@ class enabled { return; } - m_c2s_no_context_takeover = true; + m_client_no_context_takeover = true; } - /// Negotiate s2c_max_window_bits attribute + /// Negotiate server_max_window_bits attribute /** - * When this method starts, m_s2c_max_window_bits will contain the server's - * preferred value and m_s2c_max_window_bits_mode will contain the mode the + * When this method starts, m_server_max_window_bits will contain the server's + * preferred value and m_server_max_window_bits_mode will contain the mode the * server wants to use to for negotiation. `value` contains the value the * client requested that we use. * @@ -649,39 +649,39 @@ class enabled { * @param [in] value The value of the attribute from the offer * @param [out] ec A reference to the error code to return errors via */ - void negotiate_s2c_max_window_bits(std::string const & value, + void negotiate_server_max_window_bits(std::string const & value, lib::error_code & ec) { uint8_t bits = uint8_t(atoi(value.c_str())); - if (bits < min_s2c_max_window_bits || bits > max_s2c_max_window_bits) { + if (bits < min_server_max_window_bits || bits > max_server_max_window_bits) { ec = make_error_code(error::invalid_attribute_value); - m_s2c_max_window_bits = default_s2c_max_window_bits; + m_server_max_window_bits = default_server_max_window_bits; return; } - switch (m_s2c_max_window_bits_mode) { + switch (m_server_max_window_bits_mode) { case mode::decline: - m_s2c_max_window_bits = default_s2c_max_window_bits; + m_server_max_window_bits = default_server_max_window_bits; break; case mode::accept: - m_s2c_max_window_bits = bits; + m_server_max_window_bits = bits; break; case mode::largest: - m_s2c_max_window_bits = std::min(bits,m_s2c_max_window_bits); + m_server_max_window_bits = std::min(bits,m_server_max_window_bits); break; case mode::smallest: - m_s2c_max_window_bits = min_s2c_max_window_bits; + m_server_max_window_bits = min_server_max_window_bits; break; default: ec = make_error_code(error::invalid_mode); - m_s2c_max_window_bits = default_s2c_max_window_bits; + m_server_max_window_bits = default_server_max_window_bits; } } - /// Negotiate c2s_max_window_bits attribute + /// Negotiate client_max_window_bits attribute /** - * When this method starts, m_c2s_max_window_bits and m_c2s_max_window_mode + * When this method starts, m_client_max_window_bits and m_c2s_max_window_mode * will contain the server's preferred values for window size and * negotiation mode. * @@ -694,47 +694,47 @@ class enabled { * @param [in] value The value of the attribute from the offer * @param [out] ec A reference to the error code to return errors via */ - void negotiate_c2s_max_window_bits(std::string const & value, + void negotiate_client_max_window_bits(std::string const & value, lib::error_code & ec) { uint8_t bits = uint8_t(atoi(value.c_str())); if (value.empty()) { - bits = default_c2s_max_window_bits; - } else if (bits < min_c2s_max_window_bits || - bits > max_c2s_max_window_bits) + bits = default_client_max_window_bits; + } else if (bits < min_client_max_window_bits || + bits > max_client_max_window_bits) { ec = make_error_code(error::invalid_attribute_value); - m_c2s_max_window_bits = default_c2s_max_window_bits; + m_client_max_window_bits = default_client_max_window_bits; return; } - switch (m_c2s_max_window_bits_mode) { + switch (m_client_max_window_bits_mode) { case mode::decline: - m_c2s_max_window_bits = default_c2s_max_window_bits; + m_client_max_window_bits = default_client_max_window_bits; break; case mode::accept: - m_c2s_max_window_bits = bits; + m_client_max_window_bits = bits; break; case mode::largest: - m_c2s_max_window_bits = std::min(bits,m_c2s_max_window_bits); + m_client_max_window_bits = std::min(bits,m_client_max_window_bits); break; case mode::smallest: - m_c2s_max_window_bits = min_c2s_max_window_bits; + m_client_max_window_bits = min_client_max_window_bits; break; default: ec = make_error_code(error::invalid_mode); - m_c2s_max_window_bits = default_c2s_max_window_bits; + m_client_max_window_bits = default_client_max_window_bits; } } bool m_enabled; - bool m_s2c_no_context_takeover; - bool m_c2s_no_context_takeover; - uint8_t m_s2c_max_window_bits; - uint8_t m_c2s_max_window_bits; - mode::value m_s2c_max_window_bits_mode; - mode::value m_c2s_max_window_bits_mode; + bool m_server_no_context_takeover; + bool m_client_no_context_takeover; + uint8_t m_server_max_window_bits; + uint8_t m_client_max_window_bits; + mode::value m_server_max_window_bits_mode; + mode::value m_client_max_window_bits_mode; bool m_initialized; int m_flush; From c021766592437cc66cdfdca617b0bbbc38495fb0 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 26 Mar 2014 07:29:27 -0500 Subject: [PATCH 039/114] these are not defined in RFC6455 --- .../extensions/permessage_deflate/enabled.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index dc6352a5f..1117bb21a 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -174,18 +174,18 @@ namespace websocketpp { namespace extensions { namespace permessage_deflate { -/// Default value for server_max_window_bits as defined by RFC6455 +/// Default value for server_max_window_bits as defined by draft 17 static uint8_t const default_server_max_window_bits = 15; -/// Minimum value for server_max_window_bits as defined by RFC6455 +/// Minimum value for server_max_window_bits as defined by draft 17 static uint8_t const min_server_max_window_bits = 8; -/// Maximum value for server_max_window_bits as defined by RFC6455 +/// Maximum value for server_max_window_bits as defined by draft 17 static uint8_t const max_server_max_window_bits = 15; -/// Default value for client_max_window_bits as defined by RFC6455 +/// Default value for client_max_window_bits as defined by draft 17 static uint8_t const default_client_max_window_bits = 15; -/// Minimum value for client_max_window_bits as defined by RFC6455 +/// Minimum value for client_max_window_bits as defined by draft 17 static uint8_t const min_client_max_window_bits = 8; -/// Maximum value for client_max_window_bits as defined by RFC6455 +/// Maximum value for client_max_window_bits as defined by draft 17 static uint8_t const max_client_max_window_bits = 15; namespace mode { From 17544d4d62aa985101c5519c02e9cd8197c8dcea Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 20 Jan 2015 07:00:43 -0500 Subject: [PATCH 040/114] correct some documentation & fix warnings --- websocketpp/extensions/permessage_deflate/disabled.hpp | 10 ++++++++-- websocketpp/extensions/permessage_deflate/enabled.hpp | 4 ++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/disabled.hpp b/websocketpp/extensions/permessage_deflate/disabled.hpp index 5c6902ef1..5d2dd5468 100644 --- a/websocketpp/extensions/permessage_deflate/disabled.hpp +++ b/websocketpp/extensions/permessage_deflate/disabled.hpp @@ -55,7 +55,7 @@ class disabled { public: /// Negotiate extension /** - * The disabled extension always fails the negotiation with a disabled + * The disabled extension always fails the negotiation with a disabled * error. * * @param offer Attribute from client's offer @@ -66,7 +66,13 @@ class disabled { } /// Initialize state - lib::error_code init(bool is_server) { + /** + * For the disabled extension state initialization is a no-op. + * + * @param is_server True to initialize as a server, false for a client. + * @return A code representing the error that occurred, if any + */ + lib::error_code init(bool) { return lib::error_code(); } diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index b098d9b28..051627f73 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -254,7 +254,7 @@ class enabled { * * @todo memory level, strategy, etc are hardcoded * - * @param is_server Whether or not to initialize as a server or client. + * @param is_server True to initialize as a server, false for a client. * @return A code representing the error that occurred, if any */ lib::error_code init(bool is_server) { @@ -450,7 +450,7 @@ class enabled { * @param response The server response attribute list to validate * @return Validation error or 0 on success */ - lib::error_code validate_offer(http::attribute_list const & response) { + lib::error_code validate_offer(http::attribute_list const &) { return lib::error_code(); } From 3017a9c5e4224a6126818608e8f1ed40a5655108 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 20 Jan 2015 07:55:42 -0500 Subject: [PATCH 041/114] increase test timeouts --- test/transport/integration.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/test/transport/integration.cpp b/test/transport/integration.cpp index 2aee269df..8d087c425 100644 --- a/test/transport/integration.cpp +++ b/test/transport/integration.cpp @@ -395,7 +395,7 @@ 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,6)); + websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10)); tthread.detach(); run_client(c, "http://localhost:9005",false); @@ -413,7 +413,7 @@ 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,6)); + websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10)); sthread.detach(); tthread.detach(); @@ -430,7 +430,7 @@ 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,6)); + websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10)); tthread.detach(); run_dummy_client("9005"); @@ -453,7 +453,7 @@ 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,6)); + websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10)); tthread.detach(); run_client(c, "http://localhost:9005", false); @@ -485,7 +485,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,6)); + websocketpp::lib::thread tthread(websocketpp::lib::bind(&run_test_timer,10)); tthread.detach(); run_client(c, "http://localhost:9005",false); @@ -575,17 +575,17 @@ BOOST_AUTO_TEST_CASE( pause_reading ) { iostream_server s; std::string handshake = "GET / HTTP/1.1\r\nHost: www.example.com\r\nConnection: upgrade\r\nUpgrade: websocket\r\nSec-WebSocket-Version: 13\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\n\r\n"; char buffer[2] = { char(0x81), char(0x80) }; - + // suppress output (it needs a place to go to avoid error but we don't care what it is) std::stringstream null_output; s.register_ostream(&null_output); - + iostream_server::connection_ptr con = s.get_connection(); con->start(); // read handshake, should work BOOST_CHECK_EQUAL( con->read_some(handshake.data(), handshake.length()), handshake.length()); - + // pause reading and try again. The first read should work, the second should return 0 // the first read was queued already after the handshake so it will go through because // reading wasn't paused when it was queued. The byte it reads wont be enough to @@ -603,4 +603,4 @@ BOOST_AUTO_TEST_CASE( pause_reading ) { BOOST_AUTO_TEST_CASE( server_connection_cleanup ) { server_tls s; -} \ No newline at end of file +} From fccc78479eb5d716bc58889156da900821d4a8d5 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 20 Jan 2015 08:29:02 -0500 Subject: [PATCH 042/114] retest --- SConstruct | 1 + 1 file changed, 1 insertion(+) diff --git a/SConstruct b/SConstruct index 7c8d880c3..a067618c8 100644 --- a/SConstruct +++ b/SConstruct @@ -112,6 +112,7 @@ elif env['CXX'].startswith('clang++'): # Wpadded # Wsign-conversion + # platform_libs = [] tls_libs = [] From 349717ad4608a2b4b29224412e31f056a40bb956 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 27 Feb 2015 07:45:39 -0500 Subject: [PATCH 043/114] set default extension offer string Currently the offer is for default settings and advertises the ability to accept any counteroffer. --- .../extensions/permessage_deflate/disabled.hpp | 11 +++++++++++ websocketpp/extensions/permessage_deflate/enabled.hpp | 3 ++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/websocketpp/extensions/permessage_deflate/disabled.hpp b/websocketpp/extensions/permessage_deflate/disabled.hpp index 5d2dd5468..49c0e1dcf 100644 --- a/websocketpp/extensions/permessage_deflate/disabled.hpp +++ b/websocketpp/extensions/permessage_deflate/disabled.hpp @@ -88,6 +88,17 @@ class disabled { return false; } + /// Generate extension offer + /** + * Creates an offer string to include in the Sec-WebSocket-Extensions + * header of outgoing client requests. + * + * @return A WebSocket extension offer string for this extension + */ + std::string generate_offer() const { + return ""; + } + /// Compress bytes /** * @param [in] in String to compress diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 8e9299042..9afbb5c41 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -439,7 +439,8 @@ class enabled { * @return A WebSocket extension offer string for this extension */ std::string generate_offer() const { - return ""; + // TODO: this should be dynamically generated based on user settings + return "permessage-deflate; client_no_context_takeover; client_max_window_bits"; } /// Validate extension response From 643e7a0ce163d8d6a1af54e6de923d0ebb1f8bd1 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 27 Feb 2015 07:46:57 -0500 Subject: [PATCH 044/114] Update processor to allow client side extension negotiation Existing code worked for both client and server but the type signatures needed some adjustment --- websocketpp/processors/hybi13.hpp | 29 +++++++++++++++++++++++++--- websocketpp/processors/processor.hpp | 21 +++++++++++++++++--- 2 files changed, 44 insertions(+), 6 deletions(-) diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index 730cd2505..7238377a4 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -85,7 +85,21 @@ class hybi13 : public processor { return m_permessage_deflate.is_implemented(); } - err_str_pair negotiate_extensions(request_type const & req) { + err_str_pair negotiate_extensions(request_type const & request) { + return negotiate_extensions_helper(request); + } + + err_str_pair negotiate_extensions(response_type const & response) { + return negotiate_extensions_helper(response); + } + + /// Extension negotiation helper function + /** + * This exists mostly because the code for requests and responses is + * identical and I can't have virtual template methods. + */ + template + err_str_pair negotiate_extensions_helper(header_type const & header) { err_str_pair ret; // Respect blanket disabling of all extensions and don't even parse @@ -97,7 +111,7 @@ class hybi13 : public processor { http::parameter_list p; - bool error = req.get_header_as_plist("Sec-WebSocket-Extensions",p); + bool error = header.get_header_as_plist("Sec-WebSocket-Extensions",p); if (error) { ret.first = make_error_code(error::extension_parse_error); @@ -232,6 +246,13 @@ class hybi13 : public processor { req.replace_header("Sec-WebSocket-Key",base64_encode(raw_key, 16)); + if (m_permessage_deflate.is_implemented()) { + std::string offer = m_permessage_deflate.generate_offer(); + if (!offer.empty()) { + req.replace_header("Sec-WebSocket-Extensions",offer); + } + } + return lib::error_code(); } @@ -273,6 +294,8 @@ class hybi13 : public processor { return error::make_error_code(error::missing_required_header); } + // check extensions + return lib::error_code(); } diff --git a/websocketpp/processors/processor.hpp b/websocketpp/processors/processor.hpp index 99b64cae8..ff3cbb2e7 100644 --- a/websocketpp/processors/processor.hpp +++ b/websocketpp/processors/processor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -217,13 +217,28 @@ class processor { /** * Reads the Sec-WebSocket-Extensions header and determines if any of the * requested extensions are supported by this processor. If they are their - * settings data is initialized. + * settings data is initialized and an extension string to send to the + * is returned. * - * @param request The request headers to look at. + * @param request The request or response headers to look at. */ virtual err_str_pair negotiate_extensions(request_type const &) { return err_str_pair(); } + + /// Initializes extensions based on the Sec-WebSocket-Extensions header + /** + * Reads the Sec-WebSocket-Extensions header and determines if any of the + * requested extensions were accepted by the server. If they are their + * settings data is initialized. If they are not a list of required + * extensions (if any) is returned. This list may be sent back to the server + * as a part of the 1010/Extension required close code. + * + * @param response The request or response headers to look at. + */ + virtual err_str_pair negotiate_extensions(response_type const &) { + return err_str_pair(); + } /// validate a WebSocket handshake request for this version /** From c39412ee385a4a58980bb1c7352ab03835045047 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 27 Feb 2015 07:47:31 -0500 Subject: [PATCH 045/114] Update connection to negotiate extensions for clients --- websocketpp/error.hpp | 7 ++++++- websocketpp/impl/connection_impl.hpp | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/websocketpp/error.hpp b/websocketpp/error.hpp index 81fff8733..c9327201d 100644 --- a/websocketpp/error.hpp +++ b/websocketpp/error.hpp @@ -140,7 +140,10 @@ enum value { unsupported_version, /// HTTP parse error - http_parse_error + http_parse_error, + + /// Extension negotiation failed + extension_neg_failed }; // enum value @@ -216,6 +219,8 @@ class category : public lib::error_category { return "Unsupported version"; case error::http_parse_error: return "HTTP parse error"; + case error::extension_neg_failed: + return "Extension negotiation failed"; default: return "Unknown"; } diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index ac7eb285a..5648a5517 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -1532,6 +1532,25 @@ void connection::handle_read_http_response(lib::error_code const & ec, return; } + // Read extension parameters and set up values necessary for the end + // user to complete extension negotiation. + std::pair neg_results; + neg_results = m_processor->negotiate_extensions(m_response); + + if (neg_results.first) { + // There was a fatal error in extension negotiation. For the moment + // kill all connections that fail extension negotiation. + + // TODO: deal with cases where the response is well formed but + // doesn't match the options requested by the client. Its possible + // that the best behavior in this cases is to log and continue with + // an unextended connection. + m_alog.write(log::alevel::devel, "Extension negotiation failed: " + + neg_results.first.message()); + this->terminate(make_error_code(error::extension_neg_failed)); + // TODO: close connection with reason 1010 (and list extensions) + } + // response is valid, connection can now be assumed to be open m_internal_state = istate::PROCESS_CONNECTION; m_state = session::state::open; From 214cedf9491432234cc26f66ff48e8dd135d3144 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 27 Feb 2015 07:48:08 -0500 Subject: [PATCH 046/114] Update version info for permessage deflate branch --- websocketpp/version.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/websocketpp/version.hpp b/websocketpp/version.hpp index 519fa681a..88f5015c9 100644 --- a/websocketpp/version.hpp +++ b/websocketpp/version.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -50,10 +50,10 @@ static int const patch_version = 0; * This is a textual flag indicating the type and number for pre-release * versions (dev, alpha, beta, rc). This will be blank for release versions. */ -static char const prerelease_flag[] = ""; +static char const prerelease_flag[] = "permessagedeflate"; /// Default user agent string -static char const user_agent[] = "WebSocket++/0.5.0"; +static char const user_agent[] = "WebSocket++/0.5.0-permessagedeflate"; } // namespace websocketpp From 174698f1df2ef70719caba0474888018147c95fa Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 27 Feb 2015 07:48:45 -0500 Subject: [PATCH 047/114] update testee_server and testee_client Autobahn test examples to support permessage deflate --- examples/testee_client/SConscript | 4 +- examples/testee_client/testee_client.cpp | 69 +++++++++++++++++++++++- examples/testee_server/SConscript | 4 +- examples/testee_server/testee_server.cpp | 9 +++- 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/examples/testee_client/SConscript b/examples/testee_client/SConscript index 9547f3fc4..64f0ef1f3 100644 --- a/examples/testee_client/SConscript +++ b/examples/testee_client/SConscript @@ -14,10 +14,10 @@ prgs = [] # if a C++11 environment is available build using that, otherwise use boost if env_cpp11.has_key('WSPP_CPP11_ENABLED'): - ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z'] prgs += env_cpp11.Program('testee_client', ["testee_client.cpp"], LIBS = ALL_LIBS) else: - ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + ['z'] prgs += env.Program('testee_client', ["testee_client.cpp"], LIBS = ALL_LIBS) Return('prgs') diff --git a/examples/testee_client/testee_client.cpp b/examples/testee_client/testee_client.cpp index d191df579..b66e63353 100644 --- a/examples/testee_client/testee_client.cpp +++ b/examples/testee_client/testee_client.cpp @@ -1,10 +1,75 @@ -#include +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +#include #include +#include #include -typedef websocketpp::client client; +struct deflate_config : public websocketpp::config::asio_client { + typedef deflate_config type; + typedef asio_client base; + + typedef base::concurrency_type concurrency_type; + + typedef base::request_type request_type; + typedef base::response_type response_type; + + typedef base::message_type message_type; + typedef base::con_msg_manager_type con_msg_manager_type; + typedef base::endpoint_msg_manager_type endpoint_msg_manager_type; + + typedef base::alog_type alog_type; + typedef base::elog_type elog_type; + + typedef base::rng_type rng_type; + + struct transport_config : public base::transport_config { + typedef type::concurrency_type concurrency_type; + typedef type::alog_type alog_type; + typedef type::elog_type elog_type; + typedef type::request_type request_type; + typedef type::response_type response_type; + typedef websocketpp::transport::asio::basic_socket::endpoint + socket_type; + }; + + typedef websocketpp::transport::asio::endpoint + transport_type; + + /// permessage_compress extension + struct permessage_deflate_config {}; + + typedef websocketpp::extensions::permessage_deflate::enabled + permessage_deflate_type; +}; + +typedef websocketpp::client client; using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; diff --git a/examples/testee_server/SConscript b/examples/testee_server/SConscript index 526886f68..3c75f4ff2 100644 --- a/examples/testee_server/SConscript +++ b/examples/testee_server/SConscript @@ -14,10 +14,10 @@ prgs = [] # if a C++11 environment is available build using that, otherwise use boost if env_cpp11.has_key('WSPP_CPP11_ENABLED'): - ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z'] prgs += env_cpp11.Program('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS) else: - ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + ['z'] prgs += env.Program('testee_server', ["testee_server.cpp"], LIBS = ALL_LIBS) Return('prgs') diff --git a/examples/testee_server/testee_server.cpp b/examples/testee_server/testee_server.cpp index d44368c88..9ac9a7d4c 100644 --- a/examples/testee_server/testee_server.cpp +++ b/examples/testee_server/testee_server.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -27,6 +27,7 @@ #include #include +#include #include struct testee_config : public websocketpp::config::asio { @@ -64,6 +65,12 @@ struct testee_config : public websocketpp::config::asio { websocketpp::log::elevel::none; static const websocketpp::log::level alog_level = websocketpp::log::alevel::none; + + /// permessage_compress extension + struct permessage_deflate_config {}; + + typedef websocketpp::extensions::permessage_deflate::enabled + permessage_deflate_type; }; typedef websocketpp::server server; From e161ffde693bdc6cd8702f238296561bbd9b545f Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 2 Apr 2015 09:39:03 -0400 Subject: [PATCH 048/114] permessage deflate error category utility methods should be inline --- websocketpp/extensions/permessage_deflate/enabled.hpp | 4 ++-- websocketpp/version.hpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 9afbb5c41..0340303d7 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -148,13 +148,13 @@ class category : public lib::error_category { }; /// Get a reference to a static copy of the permessage-deflate error category -lib::error_category const & get_category() { +inline lib::error_category const & get_category() { static category instance; return instance; } /// Create an error code in the permessage-deflate category -lib::error_code make_error_code(error::value e) { +inline lib::error_code make_error_code(error::value e) { return lib::error_code(static_cast(e), get_category()); } diff --git a/websocketpp/version.hpp b/websocketpp/version.hpp index ee128f95b..6f9397bad 100644 --- a/websocketpp/version.hpp +++ b/websocketpp/version.hpp @@ -53,7 +53,7 @@ static int const patch_version = 1; static char const prerelease_flag[] = "permessagedeflate"; /// Default user agent string -static char const user_agent[] = "WebSocket++/0.5.0-permessagedeflate"; +static char const user_agent[] = "WebSocketpp/0.5.1-permessagedeflate"; } // namespace websocketpp From d68fd03e4092683c8bd39a7cafc67fb6c53328c3 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 2 Apr 2015 09:56:22 -0400 Subject: [PATCH 049/114] date fix --- websocketpp/extensions/permessage_deflate/enabled.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocketpp/extensions/permessage_deflate/enabled.hpp b/websocketpp/extensions/permessage_deflate/enabled.hpp index 0340303d7..1581f14cb 100644 --- a/websocketpp/extensions/permessage_deflate/enabled.hpp +++ b/websocketpp/extensions/permessage_deflate/enabled.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: From 39497aaa610b079f65bc1154ad6f24ce6f135531 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 2 Jun 2015 08:59:10 -0400 Subject: [PATCH 050/114] reset dev branch for work on next version --- CMakeLists.txt | 2 +- Doxyfile | 2 +- readme.md | 2 +- websocketpp/version.hpp | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0874b4eed..44e58f9dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ project (websocketpp) cmake_minimum_required (VERSION 2.6) set (WEBSOCKETPP_MAJOR_VERSION 0) -set (WEBSOCKETPP_MINOR_VERSION 6) +set (WEBSOCKETPP_MINOR_VERSION 7) set (WEBSOCKETPP_PATCH_VERSION 0) set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION}) diff --git a/Doxyfile b/Doxyfile index cb725d564..7d8a81355 100644 --- a/Doxyfile +++ b/Doxyfile @@ -33,7 +33,7 @@ PROJECT_NAME = "websocketpp" # if some version control system is used. -PROJECT_NUMBER = "0.6.0" +PROJECT_NUMBER = "0.7.x-dev" # Using the PROJECT_BRIEF tag one can provide an optional one line description diff --git a/readme.md b/readme.md index 18716d4fa..907201468 100644 --- a/readme.md +++ b/readme.md @@ -1,4 +1,4 @@ -WebSocket++ (0.6.0) +WebSocket++ (0.7.x-dev) ========================== WebSocket++ is a header only C++ library that implements RFC6455 The WebSocket diff --git a/websocketpp/version.hpp b/websocketpp/version.hpp index 7c2d0f495..2e0a0245a 100644 --- a/websocketpp/version.hpp +++ b/websocketpp/version.hpp @@ -42,7 +42,7 @@ namespace websocketpp { /// Library major version number static int const major_version = 0; /// Library minor version number -static int const minor_version = 6; +static int const minor_version = 7; /// Library patch version number static int const patch_version = 0; /// Library pre-release flag @@ -50,10 +50,10 @@ static int const patch_version = 0; * This is a textual flag indicating the type and number for pre-release * versions (dev, alpha, beta, rc). This will be blank for release versions. */ -static char const prerelease_flag[] = ""; +static char const prerelease_flag[] = "dev"; /// Default user agent string -static char const user_agent[] = "WebSocket++/0.6.0"; +static char const user_agent[] = "WebSocket++/0.7.x-dev"; } // namespace websocketpp From dabf32a668e53788e49199dd198b048cd82c23f4 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 5 Jun 2015 08:49:07 -0400 Subject: [PATCH 051/114] Better std::chrono autodetection for Visual Studio --- changelog.md | 1 + websocketpp/common/chrono.hpp | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 986245bf8..8c63cbc87 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,5 @@ HEAD +- Improvement: Better automatic std::chrono feature detection for Visual Studio 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/websocketpp/common/chrono.hpp b/websocketpp/common/chrono.hpp index d50dd1209..975ee043d 100644 --- a/websocketpp/common/chrono.hpp +++ b/websocketpp/common/chrono.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -39,6 +39,14 @@ #endif #endif +// If we're on Visual Studio 2012 or higher and haven't explicitly disabled +// the use of C++11 chrono header then prefer it to boost. +#if defined(_MSC_VER) && _MSC_VER >= 1700 && !defined _WEBSOCKETPP_NO_CPP11_CHRONO_ + #ifndef _WEBSOCKETPP_CPP11_CHRONO_ + #define _WEBSOCKETPP_CPP11_CHRONO_ + #endif +#endif + #ifdef _WEBSOCKETPP_CPP11_CHRONO_ #include #else From 7514c82c92f4a8be8e3c17979ae0e00c7b6b28cd Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 16 Jul 2015 11:38:38 +0200 Subject: [PATCH 052/114] CMake: properly include examples and tests with macro (added unit_test_framework dependency for unit tests) --- CMakeLists.txt | 8 ++++++-- cmake/CMakeHelpers.cmake | 9 +++++++++ examples/CMakeLists.txt | 6 ------ 3 files changed, 15 insertions(+), 8 deletions(-) delete mode 100644 examples/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 44e58f9dd..ad8275260 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,10 @@ if (BUILD_TESTS OR BUILD_EXAMPLES) list (APPEND WEBSOCKETPP_BOOST_LIBS random) endif() + if (BUILD_TESTS) + list (APPEND WEBSOCKETPP_BOOST_LIBS unit_test_framework) + endif() + ############ Dependencies # Set BOOST_ROOT env variable or pass with cmake -DBOOST_ROOT=path. @@ -221,12 +225,12 @@ add_subdirectory (websocketpp) # Add examples if (BUILD_EXAMPLES) - add_subdirectory (examples) + include_subdirs ("examples") endif () # Add tests if (BUILD_TESTS) - add_subdirectory (test) + include_subdirs ("test") endif () print_used_build_config() diff --git a/cmake/CMakeHelpers.cmake b/cmake/CMakeHelpers.cmake index 0a23905e8..ab4bc995f 100644 --- a/cmake/CMakeHelpers.cmake +++ b/cmake/CMakeHelpers.cmake @@ -76,3 +76,12 @@ endmacro () macro (link_openssl) target_link_libraries (${TARGET_NAME} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) endmacro () + +macro (include_subdirs PARENT) + file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PARENT}/*") + foreach (SUBDIR ${SDIRS}) + if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt") + add_subdirectory ("${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}") + endif () + endforeach () +endmacro() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt deleted file mode 100644 index cb746662a..000000000 --- a/examples/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} *) -foreach (SUBDIR ${SDIRS}) - if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUBDIR}/CMakeLists.txt") - add_subdirectory (${SUBDIR}) - endif () -endforeach () From d3fe51fa39bca53403972517da2ea1aa0a93a908 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 16 Jul 2015 12:17:59 +0200 Subject: [PATCH 053/114] Added missing CMake files, organized the CMake structure between test and example directories using the global variable USE_FOLDERS --- CMakeLists.txt | 2 ++ examples/associative_storage/CMakeLists.txt | 12 ++++++++++++ examples/broadcast_server/CMakeLists.txt | 12 ++++++++++++ examples/debug_client/CMakeLists.txt | 12 ++++++++++++ examples/debug_server/CMakeLists.txt | 2 ++ examples/dev/CMakeLists.txt | 12 ++++++++++++ examples/echo_server/CMakeLists.txt | 2 ++ examples/echo_server_both/CMakeLists.txt | 3 +++ examples/echo_server_tls/CMakeLists.txt | 3 +++ examples/enriched_storage/CMakeLists.txt | 12 ++++++++++++ examples/handler_switch/CMakeLists.txt | 12 ++++++++++++ examples/iostream_server/CMakeLists.txt | 12 ++++++++++++ examples/print_server/CMakeLists.txt | 2 ++ examples/simple_broadcast_server/CMakeLists.txt | 12 ++++++++++++ examples/sip_client/CMakeLists.txt | 1 + examples/subprotocol_server/CMakeLists.txt | 12 ++++++++++++ examples/telemetry_client/CMakeLists.txt | 2 ++ examples/telemetry_server/CMakeLists.txt | 2 ++ examples/testee_client/CMakeLists.txt | 1 + examples/testee_server/CMakeLists.txt | 12 ++++++++++++ examples/utility_client/CMakeLists.txt | 1 + test/connection/CMakeLists.txt | 12 ++++++++++++ test/endpoint/CMakeLists.txt | 12 ++++++++++++ test/extension/CMakeLists.txt | 12 ++++++++++++ test/http/CMakeLists.txt | 12 ++++++++++++ test/logger/CMakeLists.txt | 12 ++++++++++++ test/message_buffer/CMakeLists.txt | 12 ++++++++++++ test/processors/CMakeLists.txt | 12 ++++++++++++ test/random/CMakeLists.txt | 12 ++++++++++++ test/roles/CMakeLists.txt | 12 ++++++++++++ test/transport/CMakeLists.txt | 12 ++++++++++++ test/utility/CMakeLists.txt | 12 ++++++++++++ 32 files changed, 273 insertions(+) create mode 100644 examples/associative_storage/CMakeLists.txt create mode 100644 examples/broadcast_server/CMakeLists.txt create mode 100644 examples/debug_client/CMakeLists.txt create mode 100644 examples/dev/CMakeLists.txt create mode 100644 examples/enriched_storage/CMakeLists.txt create mode 100644 examples/handler_switch/CMakeLists.txt create mode 100644 examples/iostream_server/CMakeLists.txt create mode 100644 examples/simple_broadcast_server/CMakeLists.txt create mode 100644 examples/subprotocol_server/CMakeLists.txt create mode 100644 examples/testee_server/CMakeLists.txt create mode 100644 test/connection/CMakeLists.txt create mode 100644 test/endpoint/CMakeLists.txt create mode 100644 test/extension/CMakeLists.txt create mode 100644 test/http/CMakeLists.txt create mode 100644 test/logger/CMakeLists.txt create mode 100644 test/message_buffer/CMakeLists.txt create mode 100644 test/processors/CMakeLists.txt create mode 100644 test/random/CMakeLists.txt create mode 100644 test/roles/CMakeLists.txt create mode 100644 test/transport/CMakeLists.txt create mode 100644 test/utility/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index ad8275260..d11f40c5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ set (WEBSOCKETPP_MINOR_VERSION 7) set (WEBSOCKETPP_PATCH_VERSION 0) set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION}) +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + set(INSTALL_INCLUDE_DIR include CACHE PATH "Installation directory for header files") if (WIN32 AND NOT CYGWIN) set (DEF_INSTALL_CMAKE_DIR cmake) diff --git a/examples/associative_storage/CMakeLists.txt b/examples/associative_storage/CMakeLists.txt new file mode 100644 index 000000000..2f77e7bbc --- /dev/null +++ b/examples/associative_storage/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (associative_storage) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/broadcast_server/CMakeLists.txt b/examples/broadcast_server/CMakeLists.txt new file mode 100644 index 000000000..5fb5fe3b5 --- /dev/null +++ b/examples/broadcast_server/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (broadcast_server) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/debug_client/CMakeLists.txt b/examples/debug_client/CMakeLists.txt new file mode 100644 index 000000000..5f3110842 --- /dev/null +++ b/examples/debug_client/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (debug_client) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/debug_server/CMakeLists.txt b/examples/debug_server/CMakeLists.txt index 02f6dcf72..d134d318e 100644 --- a/examples/debug_server/CMakeLists.txt +++ b/examples/debug_server/CMakeLists.txt @@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/dev/CMakeLists.txt b/examples/dev/CMakeLists.txt new file mode 100644 index 000000000..810da8b30 --- /dev/null +++ b/examples/dev/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (dev) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/echo_server/CMakeLists.txt b/examples/echo_server/CMakeLists.txt index a82dfa792..a48be5244 100644 --- a/examples/echo_server/CMakeLists.txt +++ b/examples/echo_server/CMakeLists.txt @@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/echo_server_both/CMakeLists.txt b/examples/echo_server_both/CMakeLists.txt index 1bb194db2..83c50dc12 100644 --- a/examples/echo_server_both/CMakeLists.txt +++ b/examples/echo_server_both/CMakeLists.txt @@ -12,4 +12,7 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () link_openssl() final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") + endif() diff --git a/examples/echo_server_tls/CMakeLists.txt b/examples/echo_server_tls/CMakeLists.txt index b87cbb1f0..99f0c1428 100644 --- a/examples/echo_server_tls/CMakeLists.txt +++ b/examples/echo_server_tls/CMakeLists.txt @@ -12,4 +12,7 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () link_openssl() final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") + endif() diff --git a/examples/enriched_storage/CMakeLists.txt b/examples/enriched_storage/CMakeLists.txt new file mode 100644 index 000000000..78fa7d253 --- /dev/null +++ b/examples/enriched_storage/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (enriched_storage) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/handler_switch/CMakeLists.txt b/examples/handler_switch/CMakeLists.txt new file mode 100644 index 000000000..45917d51a --- /dev/null +++ b/examples/handler_switch/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (handler_switch) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/iostream_server/CMakeLists.txt b/examples/iostream_server/CMakeLists.txt new file mode 100644 index 000000000..962d90978 --- /dev/null +++ b/examples/iostream_server/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (iostream_server) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/print_server/CMakeLists.txt b/examples/print_server/CMakeLists.txt index dc34879b6..32c6e0fa8 100644 --- a/examples/print_server/CMakeLists.txt +++ b/examples/print_server/CMakeLists.txt @@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/simple_broadcast_server/CMakeLists.txt b/examples/simple_broadcast_server/CMakeLists.txt new file mode 100644 index 000000000..5828edb2e --- /dev/null +++ b/examples/simple_broadcast_server/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (simple_broadcast_server) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/sip_client/CMakeLists.txt b/examples/sip_client/CMakeLists.txt index 65a90b01c..439fdf1fb 100644 --- a/examples/sip_client/CMakeLists.txt +++ b/examples/sip_client/CMakeLists.txt @@ -9,3 +9,4 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/subprotocol_server/CMakeLists.txt b/examples/subprotocol_server/CMakeLists.txt new file mode 100644 index 000000000..fa911eba3 --- /dev/null +++ b/examples/subprotocol_server/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (subprotocol_server) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/telemetry_client/CMakeLists.txt b/examples/telemetry_client/CMakeLists.txt index 5cf4964e9..04462e986 100644 --- a/examples/telemetry_client/CMakeLists.txt +++ b/examples/telemetry_client/CMakeLists.txt @@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/telemetry_server/CMakeLists.txt b/examples/telemetry_server/CMakeLists.txt index 7ee569b07..845fe863c 100644 --- a/examples/telemetry_server/CMakeLists.txt +++ b/examples/telemetry_server/CMakeLists.txt @@ -8,3 +8,5 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/testee_client/CMakeLists.txt b/examples/testee_client/CMakeLists.txt index a6ca6dd35..69ddd4792 100644 --- a/examples/testee_client/CMakeLists.txt +++ b/examples/testee_client/CMakeLists.txt @@ -9,3 +9,4 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/testee_server/CMakeLists.txt b/examples/testee_server/CMakeLists.txt new file mode 100644 index 000000000..b394d1a0e --- /dev/null +++ b/examples/testee_server/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (testee_server) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/utility_client/CMakeLists.txt b/examples/utility_client/CMakeLists.txt index 865a4c783..8ff4dedd3 100644 --- a/examples/utility_client/CMakeLists.txt +++ b/examples/utility_client/CMakeLists.txt @@ -9,3 +9,4 @@ build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/test/connection/CMakeLists.txt b/test/connection/CMakeLists.txt new file mode 100644 index 000000000..b151ff474 --- /dev/null +++ b/test/connection/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_connection) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/endpoint/CMakeLists.txt b/test/endpoint/CMakeLists.txt new file mode 100644 index 000000000..22de20f04 --- /dev/null +++ b/test/endpoint/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_endpoint) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/extension/CMakeLists.txt b/test/extension/CMakeLists.txt new file mode 100644 index 000000000..f4e36d7b2 --- /dev/null +++ b/test/extension/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_extension) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/http/CMakeLists.txt b/test/http/CMakeLists.txt new file mode 100644 index 000000000..c1f011ea6 --- /dev/null +++ b/test/http/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_http) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/logger/CMakeLists.txt b/test/logger/CMakeLists.txt new file mode 100644 index 000000000..34f25bc50 --- /dev/null +++ b/test/logger/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_logger) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/message_buffer/CMakeLists.txt b/test/message_buffer/CMakeLists.txt new file mode 100644 index 000000000..e16920409 --- /dev/null +++ b/test/message_buffer/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_message_buffer) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/processors/CMakeLists.txt b/test/processors/CMakeLists.txt new file mode 100644 index 000000000..de24a8eb7 --- /dev/null +++ b/test/processors/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_processors) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/random/CMakeLists.txt b/test/random/CMakeLists.txt new file mode 100644 index 000000000..1d6f1cddb --- /dev/null +++ b/test/random/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_random) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/roles/CMakeLists.txt b/test/roles/CMakeLists.txt new file mode 100644 index 000000000..b4100c2e2 --- /dev/null +++ b/test/roles/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_roles) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/transport/CMakeLists.txt b/test/transport/CMakeLists.txt new file mode 100644 index 000000000..4fe703743 --- /dev/null +++ b/test/transport/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_transport) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/utility/CMakeLists.txt b/test/utility/CMakeLists.txt new file mode 100644 index 000000000..30a1d9670 --- /dev/null +++ b/test/utility/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (test_utility) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") From bc7ad6550e63ec424733540f4d277ec15683b245 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Thu, 16 Jul 2015 12:18:32 +0200 Subject: [PATCH 054/114] fixed typo --- examples/sip_client/SConscript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/sip_client/SConscript b/examples/sip_client/SConscript index 59b62d091..fafe7b4ff 100644 --- a/examples/sip_client/SConscript +++ b/examples/sip_client/SConscript @@ -12,7 +12,7 @@ env_cpp11 = env_cpp11.Clone () prgs = [] -# if a C++11 environment is avaliable build using that, otherwise use boost +# if a C++11 environment is available build using that, otherwise use boost if env_cpp11.has_key('WSPP_CPP11_ENABLED'): ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] prgs += env_cpp11.Program('sip_client', ["sip_client.cpp"], LIBS = ALL_LIBS) From 35805309025ba145248ae5efcb7f9df7a16697d7 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 23 Jul 2015 07:53:31 -0400 Subject: [PATCH 055/114] Miscellaneous changes - Updates code style - Adds some tags for future exception free work - Fix utility client build scripts --- examples/utility_client/CMakeLists.txt | 25 ++++++------------------- examples/utility_client/SConscript | 11 ----------- websocketpp/extensions/extension.hpp | 2 +- websocketpp/impl/connection_impl.hpp | 10 ++++++++++ 4 files changed, 17 insertions(+), 31 deletions(-) delete mode 100644 examples/utility_client/SConscript diff --git a/examples/utility_client/CMakeLists.txt b/examples/utility_client/CMakeLists.txt index 6e6cd8c9d..7cb839b15 100644 --- a/examples/utility_client/CMakeLists.txt +++ b/examples/utility_client/CMakeLists.txt @@ -1,23 +1,10 @@ -## Utility client example -## -Import('env') -Import('env_cpp11') -Import('boostlibs') -Import('platform_libs') -Import('polyfill_libs') +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) -env = env.Clone () -env_cpp11 = env_cpp11.Clone () +init_target (utility_client) -prgs = [] +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) -# if a C++11 environment is available build using that, otherwise use boost -if env_cpp11.has_key('WSPP_CPP11_ENABLED'): - ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] - prgs += env_cpp11.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS) -else: - ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] - prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS) - -Return('prgs') \ No newline at end of file +link_boost () +final_target () diff --git a/examples/utility_client/SConscript b/examples/utility_client/SConscript deleted file mode 100644 index 865a4c783..000000000 --- a/examples/utility_client/SConscript +++ /dev/null @@ -1,11 +0,0 @@ - -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) - -init_target (utility_client) - -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) - -link_boost () -final_target () - diff --git a/websocketpp/extensions/extension.hpp b/websocketpp/extensions/extension.hpp index 4d2ba745d..f5fbd9f7b 100644 --- a/websocketpp/extensions/extension.hpp +++ b/websocketpp/extensions/extension.hpp @@ -78,7 +78,7 @@ class category : public lib::error_category { } }; -inline const lib::error_category& get_category() { +inline lib::error_category const & get_category() { static category instance; return instance; } diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index b191756d7..ad6df9460 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -540,6 +540,7 @@ connection::get_response_header(std::string const & key) const { return m_response.get_header(key); } +// TODO: EXCEPTION_FREE template void connection::set_status(http::status_code::value code) { @@ -549,6 +550,8 @@ void connection::set_status(http::status_code::value code) } m_response.set_status(code); } + +// TODO: EXCEPTION_FREE template void connection::set_status(http::status_code::value code, std::string const & msg) @@ -560,6 +563,8 @@ void connection::set_status(http::status_code::value code, m_response.set_status(code,msg); } + +// TODO: EXCEPTION_FREE template void connection::set_body(std::string const & value) { if (m_internal_state != istate::PROCESS_HTTP_REQUEST) { @@ -570,6 +575,7 @@ void connection::set_body(std::string const & value) { m_response.set_body(value); } +// TODO: EXCEPTION_FREE template void connection::append_header(std::string const & key, std::string const & val) @@ -592,6 +598,8 @@ void connection::append_header(std::string const & key, } } } + +// TODO: EXCEPTION_FREE template void connection::replace_header(std::string const & key, std::string const & val) @@ -614,6 +622,8 @@ void connection::replace_header(std::string const & key, } } } + +// TODO: EXCEPTION_FREE template void connection::remove_header(std::string const & key) { From c54f2abaab3e919fb0f62801e599c8068c0e5d4e Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 23 Jul 2015 07:53:51 -0400 Subject: [PATCH 056/114] utility client build scripts --- examples/utility_client/SConscript | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 examples/utility_client/SConscript diff --git a/examples/utility_client/SConscript b/examples/utility_client/SConscript new file mode 100644 index 000000000..6e6cd8c9d --- /dev/null +++ b/examples/utility_client/SConscript @@ -0,0 +1,23 @@ +## Utility client example +## + +Import('env') +Import('env_cpp11') +Import('boostlibs') +Import('platform_libs') +Import('polyfill_libs') + +env = env.Clone () +env_cpp11 = env_cpp11.Clone () + +prgs = [] + +# if a C++11 environment is available build using that, otherwise use boost +if env_cpp11.has_key('WSPP_CPP11_ENABLED'): + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + prgs += env_cpp11.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS) +else: + ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + prgs += env.Program('utility_client', ["utility_client.cpp"], LIBS = ALL_LIBS) + +Return('prgs') \ No newline at end of file From 1f504001d2b2401ad68adda456ed25bf7eb64548 Mon Sep 17 00:00:00 2001 From: Mark Grimes Date: Sun, 26 Jul 2015 12:15:06 +0100 Subject: [PATCH 057/114] Use smart pointer to hold new io_service temporarily in case of errors --- websocketpp/common/memory.hpp | 2 ++ websocketpp/transport/asio/endpoint.hpp | 11 +++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/websocketpp/common/memory.hpp b/websocketpp/common/memory.hpp index 52cd85b57..4187e1ab9 100644 --- a/websocketpp/common/memory.hpp +++ b/websocketpp/common/memory.hpp @@ -65,6 +65,7 @@ namespace lib { #ifdef _WEBSOCKETPP_CPP11_MEMORY_ using std::shared_ptr; using std::weak_ptr; + using std::auto_ptr; using std::enable_shared_from_this; using std::static_pointer_cast; using std::make_shared; @@ -73,6 +74,7 @@ namespace lib { #else using boost::shared_ptr; using boost::weak_ptr; + using std::auto_ptr; using boost::enable_shared_from_this; using boost::static_pointer_cast; using boost::make_shared; diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp index 4e278d41c..ba38d96d2 100644 --- a/websocketpp/transport/asio/endpoint.hpp +++ b/websocketpp/transport/asio/endpoint.hpp @@ -218,7 +218,10 @@ class endpoint : public config::socket_type { * @param ec Set to indicate what error occurred, if any. */ void init_asio(lib::error_code & ec) { - init_asio(new lib::asio::io_service(), ec); + // Use a smart pointer until the call is successful and ownership has successfully been taken + lib::auto_ptr pService(new lib::asio::io_service()); + init_asio(pService.get(), ec); + if( !ec ) pService.release(); // Call was successful, transfer ownership m_external_io_service = false; } @@ -230,7 +233,11 @@ class endpoint : public config::socket_type { * @see init_asio(io_service_ptr ptr) */ void init_asio() { - init_asio(new lib::asio::io_service()); + // Use a smart pointer until the call is successful and ownership transferred + lib::auto_ptr pService(new lib::asio::io_service()); + init_asio( pService.get() ); + // If control got this far without an exception, then ownership has successfully been taken + pService.release(); m_external_io_service = false; } From ef380f7fff2c50b5f5c8bd332855d7d404787f3b Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 29 Jul 2015 08:57:56 -0400 Subject: [PATCH 058/114] Add CMake build support for examples and tests, zlib dependencies --- .gitignore | 2 + CMakeLists.txt | 5 +++ changelog.md | 3 ++ cmake/CMakeHelpers.cmake | 6 ++- examples/debug_client/CMakeLists.txt | 5 +++ examples/dev/CMakeLists.txt | 10 ++--- test/endpoint/CMakeLists.txt | 5 +++ test/extension/CMakeLists.txt | 20 +++++++--- test/http/CMakeLists.txt | 5 +-- test/message_buffer/CMakeLists.txt | 17 ++++++--- test/processors/CMakeLists.txt | 55 ++++++++++++++++++++++++++-- test/random/CMakeLists.txt | 17 ++++++--- test/roles/CMakeLists.txt | 17 ++++++--- test/transport/CMakeLists.txt | 55 ++++++++++++++++++++++++++-- test/utility/CMakeLists.txt | 49 +++++++++++++++++++++++-- 15 files changed, 228 insertions(+), 43 deletions(-) diff --git a/.gitignore b/.gitignore index 558a1b3d7..a7ec1f5f2 100644 --- a/.gitignore +++ b/.gitignore @@ -88,3 +88,5 @@ examples/wsperf/wsperf_client *.vcxproj.filters *.user install +Makefile +bin diff --git a/CMakeLists.txt b/CMakeLists.txt index d11f40c5b..4f3273803 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -186,6 +186,10 @@ if (BUILD_TESTS OR BUILD_EXAMPLES) set (Boost_USE_STATIC_LIBS FALSE) endif () + if (BOOST_STATIC) + set (Boost_USE_STATIC_LIBS TRUE) + endif () + set (Boost_FIND_REQUIRED TRUE) set (Boost_FIND_QUIETLY TRUE) set (Boost_DEBUG FALSE) @@ -218,6 +222,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES) endif () find_package(OpenSSL) + find_package(ZLIB) endif() ############ Add projects diff --git a/changelog.md b/changelog.md index 8c63cbc87..2b57a7732 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,8 @@ HEAD - Improvement: Better automatic std::chrono feature detection for Visual Studio +- Improvement: Major refactoring to bundled CMake build system. CMake can now be used to + build all of the examples and the test suite. Thank you Thijs Wenker for a significant + portion of this code. #378, #435, #449 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/cmake/CMakeHelpers.cmake b/cmake/CMakeHelpers.cmake index ab4bc995f..a3e4973de 100644 --- a/cmake/CMakeHelpers.cmake +++ b/cmake/CMakeHelpers.cmake @@ -13,7 +13,7 @@ macro (print_used_build_config) message ("") message (STATUS "WEBSOCKETPP_BOOST_LIBS = ${WEBSOCKETPP_BOOST_LIBS}") message (STATUS "WEBSOCKETPP_PLATFORM_LIBS = ${WEBSOCKETPP_PLATFORM_LIBS}") - message (STATUS "WEBSOCKETPP_PLATFORM_TSL_LIBS = ${WEBSOCKETPP_PLATFORM_TSL_LIBS}") + message (STATUS "WEBSOCKETPP_PLATFORM_TLS_LIBS = ${WEBSOCKETPP_PLATFORM_TLS_LIBS}") message ("") endmacro () @@ -77,6 +77,10 @@ macro (link_openssl) target_link_libraries (${TARGET_NAME} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) endmacro () +macro (link_zlib) + target_link_libraries (${TARGET_NAME} ${ZLIB_LIBRARIES}) +endmacro () + macro (include_subdirs PARENT) file (GLOB SDIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "${PARENT}/*") foreach (SUBDIR ${SDIRS}) diff --git a/examples/debug_client/CMakeLists.txt b/examples/debug_client/CMakeLists.txt index 5f3110842..651208a37 100644 --- a/examples/debug_client/CMakeLists.txt +++ b/examples/debug_client/CMakeLists.txt @@ -2,11 +2,16 @@ file (GLOB SOURCE_FILES *.cpp) file (GLOB HEADER_FILES *.hpp) +if (OPENSSL_FOUND) + init_target (debug_client) build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () +link_openssl() final_target () set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") + +endif() \ No newline at end of file diff --git a/examples/dev/CMakeLists.txt b/examples/dev/CMakeLists.txt index 810da8b30..f820c6b53 100644 --- a/examples/dev/CMakeLists.txt +++ b/examples/dev/CMakeLists.txt @@ -2,11 +2,11 @@ file (GLOB SOURCE_FILES *.cpp) file (GLOB HEADER_FILES *.hpp) -init_target (dev) +#init_target (dev) -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +#build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) -link_boost () -final_target () +#link_boost () +#final_target () -set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") +#set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/test/endpoint/CMakeLists.txt b/test/endpoint/CMakeLists.txt index 22de20f04..5e6cb4c02 100644 --- a/test/endpoint/CMakeLists.txt +++ b/test/endpoint/CMakeLists.txt @@ -2,11 +2,16 @@ file (GLOB SOURCE_FILES *.cpp) file (GLOB HEADER_FILES *.hpp) +if (OPENSSL_FOUND) + init_target (test_endpoint) build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) link_boost () +link_openssl () final_target () set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +endif() \ No newline at end of file diff --git a/test/extension/CMakeLists.txt b/test/extension/CMakeLists.txt index f4e36d7b2..df4acbeba 100644 --- a/test/extension/CMakeLists.txt +++ b/test/extension/CMakeLists.txt @@ -1,12 +1,22 @@ - -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) +# Extension Tests +file (GLOB SOURCE extension.cpp) init_target (test_extension) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +if ( ZLIB_FOUND ) +# Permessage-deflate tests +file (GLOB SOURCE permessage_deflate.cpp) + +init_target (test_permessage_deflate) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () +link_zlib() final_target () - set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +endif ( ZLIB_FOUND ) \ No newline at end of file diff --git a/test/http/CMakeLists.txt b/test/http/CMakeLists.txt index c1f011ea6..dd9a4ce98 100644 --- a/test/http/CMakeLists.txt +++ b/test/http/CMakeLists.txt @@ -1,10 +1,9 @@ -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) +file (GLOB SOURCE_FILES parser.cpp) init_target (test_http) -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +build_executable (${TARGET_NAME} ${SOURCE_FILES}) link_boost () final_target () diff --git a/test/message_buffer/CMakeLists.txt b/test/message_buffer/CMakeLists.txt index e16920409..7191989db 100644 --- a/test/message_buffer/CMakeLists.txt +++ b/test/message_buffer/CMakeLists.txt @@ -1,12 +1,17 @@ +# Test alloc message buffer strategy +file (GLOB SOURCE alloc.cpp) -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) - -init_target (test_message_buffer) +init_target (test_message_alloc) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +# Test message buffers +file (GLOB SOURCE message.cpp) +init_target (test_message_buffer) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () final_target () - set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/processors/CMakeLists.txt b/test/processors/CMakeLists.txt index de24a8eb7..744108937 100644 --- a/test/processors/CMakeLists.txt +++ b/test/processors/CMakeLists.txt @@ -1,12 +1,59 @@ +# Generic processor tests +file (GLOB SOURCE processor.cpp) -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) +init_target (test_processor) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -init_target (test_processors) +# Hybi00 processor tests +file (GLOB SOURCE hybi00.cpp) + +init_target (test_processor_hybi00) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +# Hybi07 processor tests +file (GLOB SOURCE hybi07.cpp) +init_target (test_processor_hybi07) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Hybi08 processor tests +file (GLOB SOURCE hybi08.cpp) +init_target (test_processor_hybi08) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +if (ZLIB_FOUND) + +# Hybi13 processor tests +file (GLOB SOURCE hybi13.cpp) + +init_target (test_processor_hybi13) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +link_zlib() +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Permessage compression extension processor tests +file (GLOB SOURCE extension_permessage_compress.cpp) + +init_target (test_processor_extension_permessage_compress) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +link_zlib() +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +endif ( ZLIB_FOUND ) \ No newline at end of file diff --git a/test/random/CMakeLists.txt b/test/random/CMakeLists.txt index 1d6f1cddb..d375f4bc0 100644 --- a/test/random/CMakeLists.txt +++ b/test/random/CMakeLists.txt @@ -1,12 +1,17 @@ +# Test RNG policy none +file (GLOB SOURCE none.cpp) -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) - -init_target (test_random) +init_target (test_random_none) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +# Test RNG policy random_device +file (GLOB SOURCE random_device.cpp) +init_target (test_random_random_device) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () final_target () - set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/roles/CMakeLists.txt b/test/roles/CMakeLists.txt index b4100c2e2..0d6771f47 100644 --- a/test/roles/CMakeLists.txt +++ b/test/roles/CMakeLists.txt @@ -1,12 +1,17 @@ +# Test client role +file (GLOB SOURCE client.cpp) -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) - -init_target (test_roles) +init_target (test_roles_client) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +# Test server role +file (GLOB SOURCE server.cpp) +init_target (test_roles_server) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () final_target () - set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") diff --git a/test/transport/CMakeLists.txt b/test/transport/CMakeLists.txt index 4fe703743..d1365cf7a 100644 --- a/test/transport/CMakeLists.txt +++ b/test/transport/CMakeLists.txt @@ -1,12 +1,61 @@ +if (OPENSSL_FOUND) -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) +# Test transport integration +file (GLOB SOURCE integration.cpp) init_target (test_transport) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +link_openssl() +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +# Test transport asio timers +file (GLOB SOURCE asio/timers.cpp) +init_target (test_transport_asio_timers) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () +link_openssl() final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") +endif() + +# Test transport iostream base +file (GLOB SOURCE iostream/base.cpp) + +init_target (test_transport_iostream_base) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Test transport iostream endpoint +file (GLOB SOURCE iostream/endpoint.cpp) + +init_target (test_transport_iostream_endpoint) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Test transport iostream connection +file (GLOB SOURCE iostream/connection.cpp) + +init_target (test_transport_iostream_connection) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Test transport asio base +file (GLOB SOURCE asio/base.cpp) + +init_target (test_transport_asio_base) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + + diff --git a/test/utility/CMakeLists.txt b/test/utility/CMakeLists.txt index 30a1d9670..8db99e3b0 100644 --- a/test/utility/CMakeLists.txt +++ b/test/utility/CMakeLists.txt @@ -1,12 +1,53 @@ +# Test close utilities +file (GLOB SOURCE close.cpp) -file (GLOB SOURCE_FILES *.cpp) -file (GLOB HEADER_FILES *.hpp) +init_target (test_close) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") -init_target (test_utility) +# Test error utilities +file (GLOB SOURCE error.cpp) -build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) +init_target (test_error) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") +# Test frame utilities +file (GLOB SOURCE frame.cpp) + +init_target (test_frame) +build_executable (${TARGET_NAME} ${SOURCE}) link_boost () final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Test sha1 utilities +file (GLOB SOURCE sha1.cpp) +init_target (test_sha1) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Test uri utilities +file (GLOB SOURCE uri.cpp) + +init_target (test_uri) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + +# Test misc utilities +file (GLOB SOURCE utilities.cpp) + +init_target (test_utilities) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +final_target () set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") From 95551e7e94cebfcec559527d5fc92d24f95a80cd Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 29 Jul 2015 09:28:22 -0400 Subject: [PATCH 059/114] code style & change log update for PR --- changelog.md | 2 ++ websocketpp/transport/asio/endpoint.hpp | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index 8c63cbc87..6e1dd8109 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,7 @@ HEAD - Improvement: Better automatic std::chrono feature detection for Visual Studio +- Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for + reporting and fixing. 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp index ba38d96d2..6b348f985 100644 --- a/websocketpp/transport/asio/endpoint.hpp +++ b/websocketpp/transport/asio/endpoint.hpp @@ -219,9 +219,9 @@ class endpoint : public config::socket_type { */ void init_asio(lib::error_code & ec) { // Use a smart pointer until the call is successful and ownership has successfully been taken - lib::auto_ptr pService(new lib::asio::io_service()); - init_asio(pService.get(), ec); - if( !ec ) pService.release(); // Call was successful, transfer ownership + lib::auto_ptr service(new lib::asio::io_service()); + init_asio(service.get(), ec); + if( !ec ) service.release(); // Call was successful, transfer ownership m_external_io_service = false; } @@ -234,10 +234,10 @@ class endpoint : public config::socket_type { */ void init_asio() { // Use a smart pointer until the call is successful and ownership transferred - lib::auto_ptr pService(new lib::asio::io_service()); - init_asio( pService.get() ); + lib::auto_ptr service(new lib::asio::io_service()); + init_asio( service.get() ); // If control got this far without an exception, then ownership has successfully been taken - pService.release(); + service.release(); m_external_io_service = false; } From 4b18214eda16186ab8766d0186bc6c49744915ed Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Sat, 1 Aug 2015 12:38:18 -0400 Subject: [PATCH 060/114] Add preliminary support for C++11 features in Visual Studio 2015 --- websocketpp/common/cpp11.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/websocketpp/common/cpp11.hpp b/websocketpp/common/cpp11.hpp index a150de363..492a3b8ff 100644 --- a/websocketpp/common/cpp11.hpp +++ b/websocketpp/common/cpp11.hpp @@ -105,6 +105,9 @@ #if __has_feature(cxx_noexcept) // clang feature detect says we have noexcept #define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept + #elif defined(_MSC_VER) && _MSC_VER >= 1900 + // Visual Studio 2015+ has noexcept + #define _WEBSOCKETPP_NOEXCEPT_TOKEN_ noexcept #else // assume we don't have noexcept #define _WEBSOCKETPP_NOEXCEPT_TOKEN_ @@ -121,6 +124,9 @@ #if __has_feature(cxx_constexpr) // clang feature detect says we have constexpr #define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr + #elif defined(_MSC_VER) && _MSC_VER >= 1900 + // Visual Studio 2015+ has constexpr + #define _WEBSOCKETPP_CONSTEXPR_TOKEN_ constexpr #else // assume we don't have constexpr #define _WEBSOCKETPP_CONSTEXPR_TOKEN_ @@ -142,7 +148,7 @@ #if __has_feature(cxx_nullptr) // clang feature detect says we have nullptr #define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr - #elif _MSC_VER >= 1600 + #elif defined(_MSC_VER) &&_MSC_VER >= 1600 // Visual Studio version that has nullptr #define _WEBSOCKETPP_NULLPTR_TOKEN_ nullptr #else From 15c78afbf447e567c30a1c8c226fda427fd69add Mon Sep 17 00:00:00 2001 From: Eli Fidler Date: Tue, 4 Aug 2015 11:52:45 -0400 Subject: [PATCH 061/114] fix crash in strip_lws() Before this fix, a malicious client could cause a websocketpp server to create an invalid std::string. --- test/http/parser.cpp | 2 ++ websocketpp/http/parser.hpp | 8 ++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/http/parser.cpp b/test/http/parser.cpp index dc7cf56eb..e0fb3e0ef 100644 --- a/test/http/parser.cpp +++ b/test/http/parser.cpp @@ -365,6 +365,7 @@ BOOST_AUTO_TEST_CASE( strip_lws ) { std::string test6 = " \r\n foo "; std::string test7 = " \t foo "; std::string test8 = " \t "; + std::string test9 = " \n\r"; BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test1), "foo" ); BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test2), "foo" ); @@ -374,6 +375,7 @@ BOOST_AUTO_TEST_CASE( strip_lws ) { BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test6), "foo" ); BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test7), "foo" ); BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test8), "" ); + BOOST_CHECK_EQUAL( websocketpp::http::parser::strip_lws(test9), "" ); } BOOST_AUTO_TEST_CASE( case_insensitive_headers ) { diff --git a/websocketpp/http/parser.hpp b/websocketpp/http/parser.hpp index c66da6cee..ade86e415 100644 --- a/websocketpp/http/parser.hpp +++ b/websocketpp/http/parser.hpp @@ -381,9 +381,13 @@ inline std::string strip_lws(std::string const & input) { if (begin == input.end()) { return std::string(); } - std::string::const_reverse_iterator end = extract_all_lws(input.rbegin(),input.rend()); - return std::string(begin,end.base()); + std::string::const_reverse_iterator rbegin = extract_all_lws(input.rbegin(),input.rend()); + if (rbegin == input.rend()) { + return std::string(); + } + + return std::string(begin,rbegin.base()); } /// Base HTTP parser From 0b2b77e4ad183d74e6681d5b03c716c0e788eb92 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 6 Aug 2015 09:11:50 -0400 Subject: [PATCH 062/114] update changelog --- changelog.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/changelog.md b/changelog.md index bdf140d13..0aa85052a 100644 --- a/changelog.md +++ b/changelog.md @@ -6,6 +6,8 @@ HEAD portion of this code. #378, #435, #449 - Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for reporting and fixing. +- Bug: Fix crash when processing a specially crafted HTTP header. Thank you Eli Fidler for + reporting, test cases, and a patch. #456 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be From fb829e08958827b4ce846937aadf8f5b5085cc17 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 20 Aug 2015 10:14:55 -0400 Subject: [PATCH 063/114] Misc changes related to translation of asio transport errors #448 --- changelog.md | 23 +++++-- test/transport/CMakeLists.txt | 10 +++ test/transport/asio/SConscript | 4 ++ test/transport/asio/security.cpp | 69 ++++++++++++++++++++ websocketpp/common/type_traits.hpp | 2 + websocketpp/transport/asio/base.hpp | 3 - websocketpp/transport/asio/connection.hpp | 28 ++++++++ websocketpp/transport/asio/security/base.hpp | 5 +- websocketpp/transport/asio/security/none.hpp | 29 ++++++-- websocketpp/transport/asio/security/tls.hpp | 37 ++++++++--- 10 files changed, 184 insertions(+), 26 deletions(-) create mode 100644 test/transport/asio/security.cpp diff --git a/changelog.md b/changelog.md index 0aa85052a..2c95dff92 100644 --- a/changelog.md +++ b/changelog.md @@ -1,13 +1,22 @@ HEAD - Feature: Basic support for the permessage-deflate extension. #344 - Improvement: Better automatic std::chrono feature detection for Visual Studio -- Improvement: Major refactoring to bundled CMake build system. CMake can now be used to - build all of the examples and the test suite. Thank you Thijs Wenker for a significant - portion of this code. #378, #435, #449 -- Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for - reporting and fixing. -- Bug: Fix crash when processing a specially crafted HTTP header. Thank you Eli Fidler for - reporting, test cases, and a patch. #456 +- Improvement: Major refactoring to bundled CMake build system. CMake can now be + used to build all of the examples and the test suite. Thank you Thijs Wenker + for a significant portion of this code. #378, #435, #449 +- Improvement: In build environments where `lib::error_code` and + `lib::asio::error_code` match (such as using `boost::asio` with + `boost::system_error` or standalone asio with `std::system_error`, transport + errors are passed through natively rather than being reported as a translated + `pass_through` error type. +- Improvement: Add a `get_transport_error` method to Asio transport connections + to allow retrieving a machine readable native transport error. +- Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark + Grimes for reporting and fixing. +- Bug: Fix crash when processing a specially crafted HTTP header. Thank you Eli + Fidler for reporting, test cases, and a patch. #456 +- Bug: Fix an issue where standalone Asio builds that use TLS would not compile + due to lingering boost code. #448 Thank you mjsp for reporting 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/test/transport/CMakeLists.txt b/test/transport/CMakeLists.txt index d1365cf7a..8e9564896 100644 --- a/test/transport/CMakeLists.txt +++ b/test/transport/CMakeLists.txt @@ -20,6 +20,16 @@ link_openssl() final_target () set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") +# Test transport asio security +file (GLOB SOURCE asio/security.cpp) + +init_target (test_transport_asio_security) +build_executable (${TARGET_NAME} ${SOURCE}) +link_boost () +link_openssl() +final_target () +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "test") + endif() # Test transport iostream base diff --git a/test/transport/asio/SConscript b/test/transport/asio/SConscript index ea0526b3a..f8185e57e 100644 --- a/test/transport/asio/SConscript +++ b/test/transport/asio/SConscript @@ -15,14 +15,18 @@ BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','chrono'],env) + objs = env.Object('base_boost.o', ["base.cpp"], LIBS = BOOST_LIBS) objs += env.Object('timers_boost.o', ["timers.cpp"], LIBS = BOOST_LIBS) +objs += env.Object('security_boost.o', ["security.cpp"], LIBS = BOOST_LIBS) prgs = env.Program('test_base_boost', ["base_boost.o"], LIBS = BOOST_LIBS) prgs += env.Program('test_timers_boost', ["timers_boost.o"], LIBS = BOOST_LIBS) +prgs += env.Program('test_security_boost', ["security_boost.o"], LIBS = BOOST_LIBS) if env_cpp11.has_key('WSPP_CPP11_ENABLED'): BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs] objs += env_cpp11.Object('base_stl.o', ["base.cpp"], LIBS = BOOST_LIBS_CPP11) objs += env_cpp11.Object('timers_stl.o', ["timers.cpp"], LIBS = BOOST_LIBS_CPP11) + objs += env_cpp11.Object('security_stl.o', ["security.cpp"], LIBS = BOOST_LIBS_CPP11) prgs += env_cpp11.Program('test_base_stl', ["base_stl.o"], LIBS = BOOST_LIBS_CPP11) prgs += env_cpp11.Program('test_timers_stl', ["timers_stl.o"], LIBS = BOOST_LIBS_CPP11) + prgs += env_cpp11.Program('test_security_stl', ["security_stl.o"], LIBS = BOOST_LIBS_CPP11) Return('prgs') diff --git a/test/transport/asio/security.cpp b/test/transport/asio/security.cpp new file mode 100644 index 000000000..a75e2a881 --- /dev/null +++ b/test/transport/asio/security.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ +//#define BOOST_TEST_DYN_LINK +#define BOOST_TEST_MODULE transport_asio_base +#include + +#include + +#include + +#include +#include + +template +struct dummy_con : public base { + websocketpp::lib::error_code test() { + return this->translate_ec(websocketpp::lib::asio::error_code()); + } +}; + +BOOST_AUTO_TEST_CASE( translated_ec_none ) { + dummy_con tscon; + + // If the current configuration settings result in the library error type and the asio + // error type being the same, then the code should pass through natively. Otherwise + // we should get a generic pass through error. + if(websocketpp::lib::is_same::value) { + BOOST_CHECK_EQUAL( tscon.test(), websocketpp::lib::error_code() ); + } else { + BOOST_CHECK_EQUAL( tscon.test(), websocketpp::transport::error::make_error_code(websocketpp::transport::error::pass_through) ); + } +} + +BOOST_AUTO_TEST_CASE( translated_ec_tls ) { + dummy_con tscon; + + // If the current configuration settings result in the library error type and the asio + // error type being the same, then the code should pass through natively. Otherwise + // we should get a generic pass through error. + if(websocketpp::lib::is_same::value) { + BOOST_CHECK_EQUAL( tscon.test(), websocketpp::lib::error_code() ); + } else { + BOOST_CHECK_EQUAL( tscon.test(), websocketpp::transport::error::make_error_code(websocketpp::transport::error::pass_through) ); + } +} diff --git a/websocketpp/common/type_traits.hpp b/websocketpp/common/type_traits.hpp index 72cc2e1e4..c89b82b31 100644 --- a/websocketpp/common/type_traits.hpp +++ b/websocketpp/common/type_traits.hpp @@ -53,8 +53,10 @@ namespace lib { #ifdef _WEBSOCKETPP_CPP11_TYPE_TRAITS_ using std::aligned_storage; + using std::is_same; #else using boost::aligned_storage; + using boost::is_same; #endif } // namespace lib diff --git a/websocketpp/transport/asio/base.hpp b/websocketpp/transport/asio/base.hpp index 6ee881ab8..b945fe11f 100644 --- a/websocketpp/transport/asio/base.hpp +++ b/websocketpp/transport/asio/base.hpp @@ -142,9 +142,6 @@ inline custom_alloc_handler make_custom_alloc_handler( template class endpoint; -typedef lib::function - socket_shutdown_handler; - typedef lib::function async_read_handler; diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index 635a0f3a1..7e97c0c62 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -366,6 +366,29 @@ class connection : public config::socket_type::socket_con_type { return m_strand; } + /// Get the internal transport error code for a closed/failed connection + /** + * Retrieves a machine readable detailed error code indicating the reason + * that the connection was closed or failed. Valid only after the close or + * fail handler is called. + * + * Primarily used if you are using mismatched asio / system_error + * implementations such as `boost::asio` with `std::system_error`. In these + * cases the transport error type is different than the library error type + * and some WebSocket++ functions that return transport errors via the + * library error code type will be coerced into a catch all `pass_through` + * or `tls_error` error. This method will return the original machine + * readable transport error in the native type. + * + * @since 0.7.0 + * + * @return Error code indicating the reason the connection was closed or + * failed + */ + lib::asio::error_code get_transport_ec() const { + return m_tec; + } + /// Initialize transport for reading /** * init_asio is called once immediately after construction to initialize @@ -877,6 +900,7 @@ class connection : public config::socket_type::socket_con_type { // We don't know much more about the error at this point. As our // socket/security policy if it knows more: tec = socket_con_type::translate_ec(ec); + m_tec = ec; if (tec == transport::error::tls_error || tec == transport::error::pass_through) @@ -1100,6 +1124,7 @@ class connection : public config::socket_type::socket_con_type { // We don't know anything more about this error, give our // socket/security policy a crack at it. 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 @@ -1156,6 +1181,9 @@ class connection : public config::socket_type::socket_con_type { std::vector m_bufs; + /// Detailed internal error code + lib::asio::error_code m_tec; + // Handlers tcp_init_handler m_tcp_pre_init_handler; tcp_init_handler m_tcp_post_init_handler; diff --git a/websocketpp/transport/asio/security/base.hpp b/websocketpp/transport/asio/security/base.hpp index dff14508b..0f08f4046 100644 --- a/websocketpp/transport/asio/security/base.hpp +++ b/websocketpp/transport/asio/security/base.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Peter Thorson. All rights reserved. + * Copyright (c) 2015, Peter Thorson. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -28,6 +28,7 @@ #ifndef WEBSOCKETPP_TRANSPORT_ASIO_SOCKET_BASE_HPP #define WEBSOCKETPP_TRANSPORT_ASIO_SOCKET_BASE_HPP +#include #include #include #include @@ -63,6 +64,8 @@ namespace transport { namespace asio { namespace socket { +typedef lib::function shutdown_handler; + /** * The transport::asio::socket::* classes are a set of security/socket related * policies and support code for the ASIO transport types. diff --git a/websocketpp/transport/asio/security/none.hpp b/websocketpp/transport/asio/security/none.hpp index 138ea403a..41634b008 100644 --- a/websocketpp/transport/asio/security/none.hpp +++ b/websocketpp/transport/asio/security/none.hpp @@ -30,6 +30,7 @@ #include +#include #include #include @@ -240,7 +241,7 @@ class connection : public lib::enable_shared_from_this { m_socket->cancel(); } - void async_shutdown(socket_shutdown_handler h) { + void async_shutdown(socket::shutdown_handler h) { lib::asio::error_code ec; m_socket->shutdown(lib::asio::ip::tcp::socket::shutdown_both, ec); h(ec); @@ -252,20 +253,36 @@ class connection : public lib::enable_shared_from_this { /// Translate any security policy specific information about an error code /** - * Translate_ec takes a boost error code and attempts to convert its value - * to an appropriate websocketpp error code. The plain socket policy does - * not presently provide any additional information so all errors will be - * reported as the generic transport pass_through error. + * Translate_ec takes an Asio error code and attempts to convert its value + * to an appropriate websocketpp error code. In the case that the Asio and + * Websocketpp error types are the same (such as using boost::asio and + * boost::system_error or using standalone asio and std::system_error the + * code will be passed through natively. + * + * In the case of a mismatch (boost::asio with std::system_error) a + * translated code will be returned. The plain socket policy does not have + * any additional information so all such errors will be reported as the + * generic transport pass_through error. * * @since 0.3.0 * * @param ec The error code to translate_ec * @return The translated error code */ - lib::error_code translate_ec(lib::asio::error_code) { + template + lib::error_code translate_ec(ErrorCodeType) { // We don't know any more information about this error so pass through return make_error_code(transport::error::pass_through); } + + /// 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) { + // We don't know any more information about this error, but the error is + // the same type as the one we are translating to, so pass through + // untranslated. + return ec; + } private: enum state { UNINITIALIZED = 0, diff --git a/websocketpp/transport/asio/security/tls.hpp b/websocketpp/transport/asio/security/tls.hpp index 350a49fab..6be3afe7a 100644 --- a/websocketpp/transport/asio/security/tls.hpp +++ b/websocketpp/transport/asio/security/tls.hpp @@ -55,7 +55,7 @@ typedef lib::function(connection_hdl)> tls_init_handler; -/// TLS enabled Boost ASIO connection socket component +/// TLS enabled Asio connection socket component /** * transport::asio::tls_socket::connection implements a secure connection socket * component that uses Asio's ssl::stream to wrap an ip::tcp::socket. @@ -315,26 +315,31 @@ class connection : public lib::enable_shared_from_this { get_raw_socket().cancel(); } - void async_shutdown(socket_shutdown_handler callback) { + void async_shutdown(socket::shutdown_handler callback) { m_socket->async_shutdown(callback); } /// Translate any security policy specific information about an error code /** - * Translate_ec takes a boost error code and attempts to convert its value - * to an appropriate websocketpp error code. Any error that is determined to - * be related to TLS but does not have a more specific websocketpp error - * code is returned under the catch all error "tls_error". + * Translate_ec takes an Asio error code and attempts to convert its value + * to an appropriate websocketpp error code. In the case that the Asio and + * Websocketpp error types are the same (such as using boost::asio and + * boost::system_error or using standalone asio and std::system_error the + * code will be passed through natively. * - * Non-TLS related errors are returned as the transport generic pass_through - * error. + * In the case of a mismatch (boost::asio with std::system_error) a + * translated code will be returned. Any error that is determined to be + * related to TLS but does not have a more specific websocketpp error code + * is returned under the catch all error `tls_error`. Non-TLS related errors + * are returned as the transport generic error `pass_through` * * @since 0.3.0 * * @param ec The error code to translate_ec * @return The translated error code */ - lib::error_code translate_ec(boost::system::error_code ec) { + template + 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); @@ -349,6 +354,20 @@ class connection : public lib::enable_shared_from_this { return make_error_code(transport::error::pass_through); } } + + /// 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: socket_type::handshake_type get_handshake_type() { if (m_is_server) { From e0bd3f7e95a4fc63a4293fe9241278fc88c1b3d3 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 25 Aug 2015 09:03:00 -0400 Subject: [PATCH 064/114] Address an issue where an exception could be thrown when a socket gets canceled on Windows XP #460 This fix switches to using the non-exception variant of socket::cancel and logging the error instead of throwing it. There is a chance that something else will need to be addressed as a result of this change as some async operations might not be cancelled? I believe everything in question has timeouts that will trigger operation cancellation at some point anyways. --- changelog.md | 7 +++++++ websocketpp/transport/asio/connection.hpp | 12 ++++++++++-- websocketpp/transport/asio/security/none.hpp | 14 ++++++++++++-- websocketpp/transport/asio/security/tls.hpp | 14 ++++++++++++-- 4 files changed, 41 insertions(+), 6 deletions(-) diff --git a/changelog.md b/changelog.md index 2c95dff92..9cea1e1ab 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,8 @@ HEAD +- MINOR BREAKING SOCKET POLICY CHANGE: Asio transport socket policy method + `cancel_socket` will now return `lib::asio::error_code` instead of `void`. + Custom Asio transport socket policies will need to be updated accordingly. + This does not affect anyone using the bundled socket policies. - Feature: Basic support for the permessage-deflate extension. #344 - Improvement: Better automatic std::chrono feature detection for Visual Studio - Improvement: Major refactoring to bundled CMake build system. CMake can now be @@ -17,6 +21,9 @@ HEAD Fidler for reporting, test cases, and a patch. #456 - Bug: Fix an issue where standalone Asio builds that use TLS would not compile due to lingering boost code. #448 Thank you mjsp for reporting +- Bug: Fix an issue where canceling a socket could throw an exception on some + older Windows XP platforms. It now prints an appropriate set of log messages + instead. Thank you Thijs Wenker for reporting and researching solutions. #460 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index 7e97c0c62..eee01cb3c 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -577,8 +577,16 @@ class connection : public config::socket_type::socket_con_type { } } - m_alog.write(log::alevel::devel,"Asio transport post-init timed out"); - socket_con_type::cancel_socket(); + m_alog.write(log::alevel::devel, "Asio transport post-init timed out"); + lib::asio::error_code cec = socket_con_type::cancel_socket(); + if (cec) { + if (cec == lib::asio::error::operation_not_supported) { + // cancel not supported on this OS, ignore and log at dev level + m_alog.write(log::alevel::devel, "socket cancel not supported"); + } else { + m_alog.write(log::elevel::warn, "socket cancel failed"); + } + } callback(ret_ec); } diff --git a/websocketpp/transport/asio/security/none.hpp b/websocketpp/transport/asio/security/none.hpp index 41634b008..f7db66b06 100644 --- a/websocketpp/transport/asio/security/none.hpp +++ b/websocketpp/transport/asio/security/none.hpp @@ -237,8 +237,18 @@ class connection : public lib::enable_shared_from_this { } /// Cancel all async operations on this socket - void cancel_socket() { - m_socket->cancel(); + /** + * Attempts to cancel all async operations on this socket and reports any + * failures. + * + * NOTE: Windows XP and earlier do not support socket cancellation. + * + * @return The error that occurred, if any. + */ + lib::asio::error_code cancel_socket() { + lib::asio::error_code ec; + m_socket->cancel(ec); + return ec; } void async_shutdown(socket::shutdown_handler h) { diff --git a/websocketpp/transport/asio/security/tls.hpp b/websocketpp/transport/asio/security/tls.hpp index 6be3afe7a..ad3ae76f6 100644 --- a/websocketpp/transport/asio/security/tls.hpp +++ b/websocketpp/transport/asio/security/tls.hpp @@ -311,8 +311,18 @@ class connection : public lib::enable_shared_from_this { } /// Cancel all async operations on this socket - void cancel_socket() { - get_raw_socket().cancel(); + /** + * Attempts to cancel all async operations on this socket and reports any + * failures. + * + * NOTE: Windows XP and earlier do not support socket cancellation. + * + * @return The error that occurred, if any. + */ + lib::asio::error_code cancel_socket() { + lib::asio::error_code ec; + get_raw_socket().cancel(ec); + return ec; } void async_shutdown(socket::shutdown_handler callback) { From 54ce641d02087c1a68399a20603bcc6c0aa19c25 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 25 Aug 2015 09:30:00 -0400 Subject: [PATCH 065/114] remove tabs --- websocketpp/transport/asio/connection.hpp | 16 ++++++++-------- websocketpp/transport/asio/security/none.hpp | 2 +- websocketpp/transport/asio/security/tls.hpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index eee01cb3c..1f1741e68 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -366,7 +366,7 @@ class connection : public config::socket_type::socket_con_type { return m_strand; } - /// Get the internal transport error code for a closed/failed connection + /// Get the internal transport error code for a closed/failed connection /** * Retrieves a machine readable detailed error code indicating the reason * that the connection was closed or failed. Valid only after the close or @@ -580,12 +580,12 @@ class connection : public config::socket_type::socket_con_type { m_alog.write(log::alevel::devel, "Asio transport post-init timed out"); lib::asio::error_code cec = socket_con_type::cancel_socket(); if (cec) { - if (cec == lib::asio::error::operation_not_supported) { - // cancel not supported on this OS, ignore and log at dev level - m_alog.write(log::alevel::devel, "socket cancel not supported"); - } else { - m_alog.write(log::elevel::warn, "socket cancel failed"); - } + if (cec == lib::asio::error::operation_not_supported) { + // cancel not supported on this OS, ignore and log at dev level + m_alog.write(log::alevel::devel, "socket cancel not supported"); + } else { + m_alog.write(log::elevel::warn, "socket cancel failed"); + } } callback(ret_ec); } @@ -1189,7 +1189,7 @@ class connection : public config::socket_type::socket_con_type { std::vector m_bufs; - /// Detailed internal error code + /// Detailed internal error code lib::asio::error_code m_tec; // Handlers diff --git a/websocketpp/transport/asio/security/none.hpp b/websocketpp/transport/asio/security/none.hpp index f7db66b06..0e68a65c8 100644 --- a/websocketpp/transport/asio/security/none.hpp +++ b/websocketpp/transport/asio/security/none.hpp @@ -246,7 +246,7 @@ class connection : public lib::enable_shared_from_this { * @return The error that occurred, if any. */ lib::asio::error_code cancel_socket() { - lib::asio::error_code ec; + lib::asio::error_code ec; m_socket->cancel(ec); return ec; } diff --git a/websocketpp/transport/asio/security/tls.hpp b/websocketpp/transport/asio/security/tls.hpp index ad3ae76f6..7c236eccb 100644 --- a/websocketpp/transport/asio/security/tls.hpp +++ b/websocketpp/transport/asio/security/tls.hpp @@ -320,7 +320,7 @@ class connection : public lib::enable_shared_from_this { * @return The error that occurred, if any. */ lib::asio::error_code cancel_socket() { - lib::asio::error_code ec; + lib::asio::error_code ec; get_raw_socket().cancel(ec); return ec; } From 3c77ce3cc7eb189ce113e495a1534ff9f1f7ea48 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 9 Sep 2015 10:14:37 -0400 Subject: [PATCH 066/114] Fix race condition resulting in corruption of responses sent from non-blocking HTTP handers The HTTP request processing code was expecting that the http response state would be `deferred` after a call to an HTTP handler that deferred the response. If, in addition to deferring, you also sent the response the HTTP state advanced past `deferred` to `response_written`. This doesn't easily show up in unit tests because the bug requires that the async write still be in flight and the connection still be open when the HTTP handler returns. An asynchronous network transport (like Asio) combined with a sufficiently large message that Asio yields control back to WebSocket++ before the response is fully written will trigger a second write on the same connection while the first is in flight. This is not allowed per the Asio spec and results in undefined behavior. The HTTP request processing code now checks if the http state is init, i.e. not deferred and no response has been started rather than just if it was deferred. --- changelog.md | 4 ++++ examples/echo_server/echo_server.cpp | 2 +- websocketpp/impl/connection_impl.hpp | 6 +++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index 9cea1e1ab..30cc5b2b3 100644 --- a/changelog.md +++ b/changelog.md @@ -24,6 +24,10 @@ HEAD - Bug: Fix an issue where canceling a socket could throw an exception on some older Windows XP platforms. It now prints an appropriate set of log messages instead. Thank you Thijs Wenker for reporting and researching solutions. #460 +- Bug: Fix an issue where deferred HTTP connections that start sending a very + long response before their HTTP handler ends would result in a second set of + HTTP headers being injected into the output. Thank you Kevin Smith for + reporting and providing test case details. #443 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/examples/echo_server/echo_server.cpp b/examples/echo_server/echo_server.cpp index 5ae78ad39..166040f68 100644 --- a/examples/echo_server/echo_server.cpp +++ b/examples/echo_server/echo_server.cpp @@ -43,7 +43,7 @@ int main() { echo_server.set_access_channels(websocketpp::log::alevel::all); echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload); - // Initialize ASIO + // Initialize Asio echo_server.init_asio(); // Register our message handler diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index ad6df9460..579529403 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -917,7 +917,11 @@ void connection::handle_read_handshake(lib::error_code const & ec, // We have the complete request. Process it. lib::error_code handshake_ec = this->process_handshake_request(); - if (!m_is_http || m_http_state != session::http_state::deferred) { + + // Write a response if this is a websocket connection or if it is an + // HTTP connection for which the response has not been deferred or + // started yet by a different system (i.e. still in init state). + if (!m_is_http || m_http_state == session::http_state::init) { this->write_http_response(handshake_ec); } } else { From 3e8dbf767da7e4e0bd6c36a5876fb9dcfd94de2e Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 17 Sep 2015 08:11:48 -0400 Subject: [PATCH 067/114] Add example demonstrating external io_service --- SConstruct | 11 ++- changelog.md | 1 + examples/external_io_service/CMakeLists.txt | 12 +++ examples/external_io_service/SConscript | 23 +++++ .../external_io_service.cpp | 85 ++++++++++++++++ .../external_io_service/tcp_echo_server.hpp | 98 +++++++++++++++++++ 6 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 examples/external_io_service/CMakeLists.txt create mode 100644 examples/external_io_service/SConscript create mode 100644 examples/external_io_service/external_io_service.cpp create mode 100644 examples/external_io_service/tcp_echo_server.hpp diff --git a/SConstruct b/SConstruct index b064417f4..8761ee916 100644 --- a/SConstruct +++ b/SConstruct @@ -34,6 +34,11 @@ elif os.environ.has_key('BOOST_INCLUDES') and os.environ.has_key('BOOST_LIBS'): else: raise SCons.Errors.UserError, "Neither BOOST_ROOT, nor BOOST_INCLUDES + BOOST_LIBS was set!" +## Custom OpenSSL +if os.environ.has_key('OPENSSL_PATH'): + env.Append(CPPPATH = os.path.join(os.environ['OPENSSL_PATH'], 'include')) + env.Append(LIBPATH = os.environ['OPENSSL_PATH']) + if os.environ.has_key('WSPP_ENABLE_CPP11'): env['WSPP_ENABLE_CPP11'] = True else: @@ -93,8 +98,7 @@ if env['PLATFORM'].startswith('win'): #env['LIBPATH'] = env['BOOST_LIBS'] pass else: - env['LIBPATH'] = ['/usr/lib', - '/usr/local/lib'] #, env['BOOST_LIBS'] + env.Append(LIBPATH = ['/usr/lib', '/usr/local/lib']) # Compiler specific warning flags if env['CXX'].startswith('g++'): @@ -260,6 +264,9 @@ subprotocol_server = SConscript('#/examples/subprotocol_server/SConscript',varia # telemetry_server telemetry_server = SConscript('#/examples/telemetry_server/SConscript',variant_dir = builddir + 'telemetry_server',duplicate = 0) +# external_io_service +external_io_service = SConscript('#/examples/external_io_service/SConscript',variant_dir = builddir + 'external_io_service',duplicate = 0) + if not env['PLATFORM'].startswith('win'): # iostream_server iostream_server = SConscript('#/examples/iostream_server/SConscript',variant_dir = builddir + 'iostream_server',duplicate = 0) diff --git a/changelog.md b/changelog.md index 30cc5b2b3..75029c2b9 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,7 @@ HEAD `pass_through` error type. - Improvement: Add a `get_transport_error` method to Asio transport connections to allow retrieving a machine readable native transport error. +- Documentation: Adds an example demonstrating the use of external `io_service` - Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for reporting and fixing. - Bug: Fix crash when processing a specially crafted HTTP header. Thank you Eli diff --git a/examples/external_io_service/CMakeLists.txt b/examples/external_io_service/CMakeLists.txt new file mode 100644 index 000000000..5223da1be --- /dev/null +++ b/examples/external_io_service/CMakeLists.txt @@ -0,0 +1,12 @@ + +file (GLOB SOURCE_FILES *.cpp) +file (GLOB HEADER_FILES *.hpp) + +init_target (external_io_service) + +build_executable (${TARGET_NAME} ${SOURCE_FILES} ${HEADER_FILES}) + +link_boost () +final_target () + +set_target_properties(${TARGET_NAME} PROPERTIES FOLDER "examples") diff --git a/examples/external_io_service/SConscript b/examples/external_io_service/SConscript new file mode 100644 index 000000000..beb7c1c42 --- /dev/null +++ b/examples/external_io_service/SConscript @@ -0,0 +1,23 @@ +## Main development example +## + +Import('env') +Import('env_cpp11') +Import('boostlibs') +Import('platform_libs') +Import('polyfill_libs') + +env = env.Clone () +env_cpp11 = env_cpp11.Clone () + +prgs = [] + +# if a C++11 environment is available build using that, otherwise use boost +if env_cpp11.has_key('WSPP_CPP11_ENABLED'): + ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + prgs += env_cpp11.Program('external_io_service', ["external_io_service.cpp"], LIBS = ALL_LIBS) +else: + ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + prgs += env.Program('external_io_service', ["external_io_service.cpp"], LIBS = ALL_LIBS) + +Return('prgs') diff --git a/examples/external_io_service/external_io_service.cpp b/examples/external_io_service/external_io_service.cpp new file mode 100644 index 000000000..b6ce3b186 --- /dev/null +++ b/examples/external_io_service/external_io_service.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "tcp_echo_server.hpp" + +#include +#include + +#include + +using websocketpp::lib::placeholders::_1; +using websocketpp::lib::placeholders::_2; +using websocketpp::lib::bind; + +typedef websocketpp::server ws_echo_server; + +// Define a callback to handle incoming messages +void on_message(ws_echo_server* s, websocketpp::connection_hdl hdl, ws_echo_server::message_ptr msg) { + std::cout << "on_message called with hdl: " << hdl.lock().get() + << " and message: " << msg->get_payload() + << std::endl; + + // check for a special command to instruct the server to stop listening so + // it can be cleanly exited. + if (msg->get_payload() == "stop-listening") { + s->stop_listening(); + return; + } + + try { + s->send(hdl, msg->get_payload(), msg->get_opcode()); + } catch (websocketpp::lib::error_code const & e) { + std::cout << "Echo failed because: " << e + << "(" << e.message() << ")" << std::endl; + } +} + +int main() { + asio::io_service service; + + // Add a TCP echo server on port 9003 + tcp_echo_server custom_http_server(service, 9003); + + // Add a WebSocket echo server on port 9002 + ws_echo_server ws_server; + ws_server.set_access_channels(websocketpp::log::alevel::all); + ws_server.clear_access_channels(websocketpp::log::alevel::frame_payload); + + // The only difference in this code between an internal and external + // io_service is the different constructor to init_asio + ws_server.init_asio(&service); + + // Register our message handler + ws_server.set_message_handler(bind(&on_message,&ws_server,::_1,::_2)); + ws_server.listen(9002); + ws_server.start_accept(); + + // TODO: add a timer? + + // Start the Asio io_service run loop for all + service.run(); +} \ No newline at end of file diff --git a/examples/external_io_service/tcp_echo_server.hpp b/examples/external_io_service/tcp_echo_server.hpp new file mode 100644 index 000000000..f6cd61826 --- /dev/null +++ b/examples/external_io_service/tcp_echo_server.hpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015, Peter Thorson. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the WebSocket++ Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PETER THORSON BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * TCP Echo Server + * + * This file defines a simple TCP Echo Server. It is adapted from the Asio + * example: cpp03/echo/async_tcp_echo_server.cpp + */ + +#include +#include +#include + +using websocketpp::lib::placeholders::_1; +using websocketpp::lib::placeholders::_2; +using websocketpp::lib::bind; + +namespace asio = websocketpp::lib::asio; +using tcp = asio::ip::tcp; + +struct tcp_echo_session : websocketpp::lib::enable_shared_from_this { + typedef websocketpp::lib::shared_ptr ptr; + + tcp_echo_session(asio::io_service & service) : m_socket(service) {} + + void start() { + m_socket.async_read_some(asio::buffer(m_buffer, sizeof(m_buffer)), + websocketpp::lib::bind( + &tcp_echo_session::handle_read, shared_from_this(), _1, _2)); + } + + void handle_read(const asio::error_code & ec, size_t transferred) { + if (!ec) { + asio::async_write(m_socket, + asio::buffer(m_buffer, transferred), + bind(&tcp_echo_session::handle_write, shared_from_this(), _1)); + } + } + + void handle_write(const asio::error_code & ec) { + if (!ec) { + m_socket.async_read_some(asio::buffer(m_buffer, sizeof(m_buffer)), + bind(&tcp_echo_session::handle_read, shared_from_this(), _1, _2)); + } + } + + tcp::socket m_socket; + char m_buffer[1024]; +}; + +struct tcp_echo_server { + tcp_echo_server(asio::io_service & service, short port) + : m_service(service) + , m_acceptor(service, tcp::endpoint(tcp::v6(), port)) + { + this->start_accept(); + } + + void start_accept() { + tcp_echo_session::ptr new_session(new tcp_echo_session(m_service)); + m_acceptor.async_accept(new_session->m_socket, + bind(&tcp_echo_server::handle_accept, this, new_session, _1)); + } + + void handle_accept(tcp_echo_session::ptr new_session, const asio::error_code & ec) { + if (!ec) { + new_session->start(); + } + start_accept(); + } + + asio::io_service & m_service; + tcp::acceptor m_acceptor; +}; From 93b75ccc7ddc5345c4a3a021eb08f7f10b21c05d Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 17 Sep 2015 10:09:07 -0400 Subject: [PATCH 068/114] Add get_status and get_response methods to connection fixes #465 --- changelog.md | 3 +++ websocketpp/connection.hpp | 31 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/changelog.md b/changelog.md index 75029c2b9..2b7b4d461 100644 --- a/changelog.md +++ b/changelog.md @@ -15,6 +15,9 @@ HEAD `pass_through` error type. - Improvement: Add a `get_transport_error` method to Asio transport connections to allow retrieving a machine readable native transport error. +- Improvement: Add `connection::get_status` and `connection::get_response` + methods to allow accessing additional information about the HTTP responses + that WebSocket++ sends. #465 Thank you Flow86 for reporting. - Documentation: Adds an example demonstrating the use of external `io_service` - Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for reporting and fixing. diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp index 203de6f66..0d5bb754d 100644 --- a/websocketpp/connection.hpp +++ b/websocketpp/connection.hpp @@ -969,6 +969,18 @@ class connection */ std::string const & get_response_header(std::string const & key) const; + /// Get response status code and message + /** + * Gets the response status code + * + * @since 0.7.0 + * + * @return The response status code sent + */ + http::status_code::value get_status() const { + return m_response->get_status(); + } + /// Set response status code and message /** * Sets the response status code to `code` and looks up the corresponding @@ -1076,6 +1088,25 @@ class connection return m_request; } + /// Get response object + /** + * Direct access to the HTTP response sent or received as a part of the + * opening handshake. This can be used to call methods of the response + * object that are not part of the standard request API that connection + * wraps. + * + * Note use of this method involves using behavior specific to the + * configured HTTP policy. Such behavior may not work with alternate HTTP + * policies. + * + * @since 0.7.0 + * + * @return A const reference to the raw response object + */ + response_type const & get_response() const { + return m_response; + } + /// Defer HTTP Response until later (Exception free) /** * Used in the http handler to defer the HTTP response for this connection From 72e55a76b5f1728ce61c6ef2abe27e151f93e6f4 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 17 Sep 2015 10:09:28 -0400 Subject: [PATCH 069/114] remove alias for better compatibility with older compilers --- examples/external_io_service/tcp_echo_server.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/examples/external_io_service/tcp_echo_server.hpp b/examples/external_io_service/tcp_echo_server.hpp index f6cd61826..ef4ce1855 100644 --- a/examples/external_io_service/tcp_echo_server.hpp +++ b/examples/external_io_service/tcp_echo_server.hpp @@ -40,7 +40,6 @@ using websocketpp::lib::placeholders::_2; using websocketpp::lib::bind; namespace asio = websocketpp::lib::asio; -using tcp = asio::ip::tcp; struct tcp_echo_session : websocketpp::lib::enable_shared_from_this { typedef websocketpp::lib::shared_ptr ptr; @@ -68,14 +67,14 @@ struct tcp_echo_session : websocketpp::lib::enable_shared_from_thisstart_accept(); } @@ -94,5 +93,5 @@ struct tcp_echo_server { } asio::io_service & m_service; - tcp::acceptor m_acceptor; + asio::ip::tcp::acceptor m_acceptor; }; From b6817e4c7e8e6344d749686a14211ca883b68b5f Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Sat, 19 Sep 2015 10:54:50 -0400 Subject: [PATCH 070/114] Actually have the response status getters work; also tests --- changelog.md | 7 ++++--- test/connection/connection.cpp | 7 ++++++- websocketpp/connection.hpp | 18 +++++++++++++++--- 3 files changed, 25 insertions(+), 7 deletions(-) diff --git a/changelog.md b/changelog.md index 2b7b4d461..aca4bae50 100644 --- a/changelog.md +++ b/changelog.md @@ -15,9 +15,10 @@ HEAD `pass_through` error type. - Improvement: Add a `get_transport_error` method to Asio transport connections to allow retrieving a machine readable native transport error. -- Improvement: Add `connection::get_status` and `connection::get_response` - methods to allow accessing additional information about the HTTP responses - that WebSocket++ sends. #465 Thank you Flow86 for reporting. +- Improvement: Add `connection::get_response`, `connection::get_response_code`, + and `connection::get_response_msg` methods to allow accessing additional + information about the HTTP responses that WebSocket++ sends. #465 Thank you + Flow86 for reporting. - Documentation: Adds an example demonstrating the use of external `io_service` - Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for reporting and fixing. diff --git a/test/connection/connection.cpp b/test/connection/connection.cpp index 5491ab1d0..8f2781ea0 100644 --- a/test/connection/connection.cpp +++ b/test/connection/connection.cpp @@ -159,12 +159,17 @@ bool validate_set_ua(server* s, websocketpp::connection_hdl hdl) { } void http_func(server* s, websocketpp::connection_hdl hdl) { + using namespace websocketpp::http; + server::connection_ptr con = s->get_con_from_hdl(hdl); std::string res = con->get_resource(); con->set_body(res); - con->set_status(websocketpp::http::status_code::ok); + con->set_status(status_code::ok); + + BOOST_CHECK_EQUAL(con->get_response_code(), status_code::ok); + BOOST_CHECK_EQUAL(con->get_response_msg(), status_code::get_string(status_code::ok)); } void defer_http_func(server* s, bool * deferred, websocketpp::connection_hdl hdl) { diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp index 0d5bb754d..a38608d0f 100644 --- a/websocketpp/connection.hpp +++ b/websocketpp/connection.hpp @@ -969,7 +969,7 @@ class connection */ std::string const & get_response_header(std::string const & key) const; - /// Get response status code and message + /// Get response HTTP status code /** * Gets the response status code * @@ -977,10 +977,22 @@ class connection * * @return The response status code sent */ - http::status_code::value get_status() const { - return m_response->get_status(); + http::status_code::value get_response_code() const { + return m_response.get_status_code(); } + /// Get response HTTP status message + /** + * Gets the response status message + * + * @since 0.7.0 + * + * @return The response status message sent + */ + std::string const & get_response_msg() const { + return m_response.get_status_msg(); + } + /// Set response status code and message /** * Sets the response status code to `code` and looks up the corresponding From cd4af122c0872f4707212bf63b817a56d67c0226 Mon Sep 17 00:00:00 2001 From: vladon Date: Tue, 29 Sep 2015 21:36:41 +0300 Subject: [PATCH 071/114] avoid unnecessary empty strings ("") in favor of clear() and empty() (performance) --- .../associative_storage.cpp | 4 +- .../enriched_storage/enriched_storage.cpp | 2 +- examples/scratch_client/scratch_client.cpp | 2 +- examples/utility_client/utility_client.cpp | 4 +- test/extension/permessage_deflate.cpp | 46 +++++++++---------- test/http/parser.cpp | 14 +++--- .../extension_permessage_compress.cpp | 6 +-- test/roles/server.cpp | 2 +- test/utility/close.cpp | 8 ++-- tutorials/utility_client/step5.cpp | 2 +- tutorials/utility_client/step6.cpp | 4 +- tutorials/utility_client/utility_client.md | 2 +- websocketpp/close.hpp | 2 +- websocketpp/connection.hpp | 4 +- websocketpp/http/constants.hpp | 6 +-- websocketpp/http/impl/parser.hpp | 6 +-- websocketpp/http/impl/request.hpp | 2 +- websocketpp/http/impl/response.hpp | 2 +- websocketpp/http/parser.hpp | 8 ++-- websocketpp/impl/connection_impl.hpp | 28 +++++------ websocketpp/processors/hybi00.hpp | 14 +++--- websocketpp/processors/hybi13.hpp | 2 +- websocketpp/processors/processor.hpp | 2 +- websocketpp/uri.hpp | 16 +++---- 24 files changed, 94 insertions(+), 94 deletions(-) diff --git a/examples/associative_storage/associative_storage.cpp b/examples/associative_storage/associative_storage.cpp index e2245e4e4..2ac849410 100644 --- a/examples/associative_storage/associative_storage.cpp +++ b/examples/associative_storage/associative_storage.cpp @@ -30,7 +30,7 @@ class print_server { connection_data data; data.sessionid = m_next_sessionid++; - data.name = ""; + data.name.clear(); m_connections[hdl] = data; } @@ -47,7 +47,7 @@ class print_server { void on_message(connection_hdl hdl, server::message_ptr msg) { connection_data& data = get_data_from_hdl(hdl); - if (data.name == "") { + if (data.name.empty()) { data.name = msg->get_payload(); std::cout << "Setting name of connection with sessionid " << data.sessionid << " to " << data.name << std::endl; diff --git a/examples/enriched_storage/enriched_storage.cpp b/examples/enriched_storage/enriched_storage.cpp index fbedc8ee2..fb233198a 100644 --- a/examples/enriched_storage/enriched_storage.cpp +++ b/examples/enriched_storage/enriched_storage.cpp @@ -61,7 +61,7 @@ class print_server { void on_message(connection_hdl hdl, server::message_ptr msg) { connection_ptr con = m_server.get_con_from_hdl(hdl); - if (con->name == "") { + if (con->name.empty()) { con->name = msg->get_payload(); std::cout << "Setting name of connection with sessionid " << con->sessionid << " to " << con->name << std::endl; diff --git a/examples/scratch_client/scratch_client.cpp b/examples/scratch_client/scratch_client.cpp index 9b5a25c0d..a6a1fbcfe 100644 --- a/examples/scratch_client/scratch_client.cpp +++ b/examples/scratch_client/scratch_client.cpp @@ -246,7 +246,7 @@ int main() { std::string cmd; int id; int close_code = websocketpp::close::status::normal; - std::string reason = ""; + std::string reason; ss >> cmd >> id >> close_code; std::getline(ss,reason); diff --git a/examples/utility_client/utility_client.cpp b/examples/utility_client/utility_client.cpp index e9108dc01..aa43b8e39 100644 --- a/examples/utility_client/utility_client.cpp +++ b/examples/utility_client/utility_client.cpp @@ -289,7 +289,7 @@ int main() { std::string cmd; int id; - std::string message = ""; + std::string message; ss >> cmd >> id; std::getline(ss,message); @@ -301,7 +301,7 @@ int main() { std::string cmd; int id; int close_code = websocketpp::close::status::normal; - std::string reason = ""; + std::string reason; ss >> cmd >> id >> close_code; std::getline(ss,reason); diff --git a/test/extension/permessage_deflate.cpp b/test/extension/permessage_deflate.cpp index 06ace5e2c..4cd3e7b63 100644 --- a/test/extension/permessage_deflate.cpp +++ b/test/extension/permessage_deflate.cpp @@ -113,7 +113,7 @@ BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover_invalid ) { BOOST_AUTO_TEST_CASE( negotiate_server_no_context_takeover ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( v.exts.is_enabled() ); @@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover_invalid ) { BOOST_AUTO_TEST_CASE( negotiate_client_no_context_takeover ) { ext_vars v; - v.attr["client_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"].clear(); v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( v.exts.is_enabled() ); @@ -282,7 +282,7 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_invalid ) { BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_valid ) { ext_vars v; - v.attr["client_max_window_bits"] = ""; + v.attr["client_max_window_bits"].clear(); v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( v.exts.is_enabled() ); BOOST_CHECK_EQUAL( v.esp.first, websocketpp::lib::error_code() ); @@ -364,8 +364,8 @@ BOOST_AUTO_TEST_CASE( negotiate_client_max_window_bits_smallest ) { BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated1 ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; - v.attr["client_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); + v.attr["client_no_context_takeover"].clear(); v.esp = v.exts.negotiate(v.attr); BOOST_CHECK( v.exts.is_enabled() ); @@ -376,7 +376,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated1 ) { BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated2 ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); v.attr["server_max_window_bits"] = "10"; v.esp = v.exts.negotiate(v.attr); @@ -388,7 +388,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated2 ) { BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated3 ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); v.attr["client_max_window_bits"] = "10"; v.esp = v.exts.negotiate(v.attr); @@ -400,7 +400,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated3 ) { BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated4 ) { ext_vars v; - v.attr["client_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"].clear(); v.attr["server_max_window_bits"] = "10"; v.esp = v.exts.negotiate(v.attr); @@ -412,7 +412,7 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated4 ) { BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated5 ) { ext_vars v; - v.attr["client_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"].clear(); v.attr["client_max_window_bits"] = "10"; v.esp = v.exts.negotiate(v.attr); @@ -436,8 +436,8 @@ BOOST_AUTO_TEST_CASE( negotiate_two_client_initiated6 ) { BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated1 ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; - v.attr["client_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); + v.attr["client_no_context_takeover"].clear(); v.attr["server_max_window_bits"] = "10"; v.esp = v.exts.negotiate(v.attr); @@ -449,8 +449,8 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated1 ) { BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated2 ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; - v.attr["client_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); + v.attr["client_no_context_takeover"].clear(); v.attr["client_max_window_bits"] = "10"; v.esp = v.exts.negotiate(v.attr); @@ -462,7 +462,7 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated2 ) { BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated3 ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); v.attr["server_max_window_bits"] = "10"; v.attr["client_max_window_bits"] = "10"; @@ -475,7 +475,7 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated3 ) { BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated4 ) { ext_vars v; - v.attr["client_no_context_takeover"] = ""; + v.attr["client_no_context_takeover"].clear(); v.attr["server_max_window_bits"] = "10"; v.attr["client_max_window_bits"] = "10"; @@ -488,8 +488,8 @@ BOOST_AUTO_TEST_CASE( negotiate_three_client_initiated4 ) { BOOST_AUTO_TEST_CASE( negotiate_four_client_initiated ) { ext_vars v; - v.attr["server_no_context_takeover"] = ""; - v.attr["client_no_context_takeover"] = ""; + v.attr["server_no_context_takeover"].clear(); + v.attr["client_no_context_takeover"].clear(); v.attr["server_max_window_bits"] = "10"; v.attr["client_max_window_bits"] = "10"; @@ -569,7 +569,7 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { websocketpp::http::attribute_list alist; - alist["server_no_context_takeover"] = ""; + alist["server_no_context_takeover"].clear(); v.exts.enable_server_no_context_takeover(); v.exts.negotiate(alist); @@ -586,7 +586,7 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); BOOST_CHECK_EQUAL( compress_in, decompress_out ); - decompress_out = ""; + decompress_out.clear(); v.ec = v.exts.compress(compress_in,compress_out2); BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); @@ -605,7 +605,7 @@ BOOST_AUTO_TEST_CASE( compress_data_no_context_takeover ) { BOOST_AUTO_TEST_CASE( compress_empty ) { ext_vars v; - std::string compress_in = ""; + std::string compress_in; std::string compress_out; std::string decompress_out; @@ -616,8 +616,8 @@ BOOST_AUTO_TEST_CASE( compress_empty ) { v.ec = v.exts.decompress(reinterpret_cast(compress_out.data()),compress_out.size(),decompress_out); - compress_out = ""; - decompress_out = ""; + compress_out.clear(); + decompress_out.clear(); v.ec = v.exts.compress(compress_in,compress_out); BOOST_CHECK_EQUAL( v.ec, websocketpp::lib::error_code() ); @@ -637,7 +637,7 @@ BOOST_AUTO_TEST_CASE( decompress_data ) { ext_vars v; uint8_t in[11] = {0xf2, 0x48, 0xcd, 0xc9, 0xc9, 0x07, 0x00, 0x00, 0x00, 0xff, 0xff}; - std::string out = ""; + std::string out; std::string reference = "Hello"; v.exts.init(true); diff --git a/test/http/parser.cpp b/test/http/parser.cpp index e0fb3e0ef..1d71ec874 100644 --- a/test/http/parser.cpp +++ b/test/http/parser.cpp @@ -115,7 +115,7 @@ BOOST_AUTO_TEST_CASE( extract_token ) { BOOST_CHECK( ret.second == d1.begin()+3 ); ret = websocketpp::http::parser::extract_token(d2.begin(),d2.end()); - BOOST_CHECK( ret.first == "" ); + BOOST_CHECK( ret.first.empty() ); BOOST_CHECK( ret.second == d2.begin()+0 ); ret = websocketpp::http::parser::extract_token(d2.begin()+1,d2.end()); @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE( extract_quoted_string ) { std::string d1 = "\"foo\""; std::string d2 = "\"foo\\\"bar\\\"baz\""; std::string d3 = "\"foo\" "; - std::string d4 = ""; + std::string d4; std::string d5 = "foo"; std::pair ret; @@ -147,11 +147,11 @@ BOOST_AUTO_TEST_CASE( extract_quoted_string ) { BOOST_CHECK( ret.second == d3.begin()+5 ); ret = extract_quoted_string(d4.begin(),d4.end()); - BOOST_CHECK( ret.first == "" ); + BOOST_CHECK( ret.first.empty() ); BOOST_CHECK( ret.second == d4.begin() ); ret = extract_quoted_string(d5.begin(),d5.end()); - BOOST_CHECK( ret.first == "" ); + BOOST_CHECK( ret.first.empty() ); BOOST_CHECK( ret.second == d5.begin() ); } @@ -185,7 +185,7 @@ BOOST_AUTO_TEST_CASE( extract_all_lws ) { } BOOST_AUTO_TEST_CASE( extract_attributes_blank ) { - std::string s = ""; + std::string s; websocketpp::http::attribute_list a; std::string::const_iterator it; @@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE( extract_attributes_simple ) { } BOOST_AUTO_TEST_CASE( extract_parameters ) { - std::string s1 = ""; + std::string s1; std::string s2 = "foo"; std::string s3 = " foo \r\nAbc"; std::string s4 = " \r\n foo "; @@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE( case_insensitive_headers_overwrite ) { BOOST_AUTO_TEST_CASE( blank_consume ) { websocketpp::http::parser::request r; - std::string raw = ""; + std::string raw; bool exception = false; diff --git a/test/processors/extension_permessage_compress.cpp b/test/processors/extension_permessage_compress.cpp index 9b84c995a..7f26a9dd5 100644 --- a/test/processors/extension_permessage_compress.cpp +++ b/test/processors/extension_permessage_compress.cpp @@ -165,7 +165,7 @@ BOOST_AUTO_TEST_CASE( deflate_init ) { << websocketpp::utility::to_hex(test_out,test_out_size) << std::endl; std::string input = "Hello"; - std::string output = ""; + std::string output; ec = de.compress(input,output); BOOST_CHECK( ec == processor::extensions::error::uninitialized ); @@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE( deflate_init ) { << websocketpp::utility::to_hex(input) << std::endl << websocketpp::utility::to_hex(output) << std::endl; - output = ""; + output.clear(); ec = de.compress(input,output); std::cout << ec.message() << std::endl @@ -189,7 +189,7 @@ BOOST_AUTO_TEST_CASE( deflate_init ) { << websocketpp::utility::to_hex(output) << std::endl; input = output; - output = ""; + output.clear(); ec = de.decompress(input,output); std::cout << ec.message() << std::endl << websocketpp::utility::to_hex(input) << std::endl diff --git a/test/roles/server.cpp b/test/roles/server.cpp index cbe860737..ef24bfcd4 100644 --- a/test/roles/server.cpp +++ b/test/roles/server.cpp @@ -103,7 +103,7 @@ bool validate_func_subprotocol(server* s, std::string* out, std::string accept, *out = o.str(); - if (accept != "") { + if (!accept.empty()) { con->select_subprotocol(accept); } diff --git a/test/utility/close.cpp b/test/utility/close.cpp index 191f2632d..81d7188e5 100644 --- a/test/utility/close.cpp +++ b/test/utility/close.cpp @@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE( value_extraction ) { BOOST_AUTO_TEST_CASE( extract_empty ) { lib::error_code ec; - std::string payload = ""; + std::string payload; BOOST_CHECK( close::extract_code(payload,ec) == close::status::no_status ); BOOST_CHECK( !ec ); @@ -109,12 +109,12 @@ BOOST_AUTO_TEST_CASE( extract_reason ) { BOOST_CHECK( close::extract_reason(payload,ec) == "Foo" ); BOOST_CHECK( !ec ); - payload = ""; - BOOST_CHECK( close::extract_reason(payload,ec) == "" ); + payload.clear(); + BOOST_CHECK( close::extract_reason(payload,ec).empty() ); BOOST_CHECK( !ec ); payload = "00"; - BOOST_CHECK( close::extract_reason(payload,ec) == "" ); + BOOST_CHECK( close::extract_reason(payload,ec).empty() ); BOOST_CHECK( !ec ); payload = "000"; diff --git a/tutorials/utility_client/step5.cpp b/tutorials/utility_client/step5.cpp index dd9136a83..3e57b3c24 100644 --- a/tutorials/utility_client/step5.cpp +++ b/tutorials/utility_client/step5.cpp @@ -246,7 +246,7 @@ int main() { std::string cmd; int id; int close_code = websocketpp::close::status::normal; - std::string reason = ""; + std::string reason; ss >> cmd >> id >> close_code; std::getline(ss,reason); diff --git a/tutorials/utility_client/step6.cpp b/tutorials/utility_client/step6.cpp index 6cd3ef50b..208b95db6 100644 --- a/tutorials/utility_client/step6.cpp +++ b/tutorials/utility_client/step6.cpp @@ -289,7 +289,7 @@ int main() { std::string cmd; int id; - std::string message = ""; + std::string message; ss >> cmd >> id; std::getline(ss,message); @@ -301,7 +301,7 @@ int main() { std::string cmd; int id; int close_code = websocketpp::close::status::normal; - std::string reason = ""; + std::string reason; ss >> cmd >> id >> close_code; std::getline(ss,reason); diff --git a/tutorials/utility_client/utility_client.md b/tutorials/utility_client/utility_client.md index 85cc92817..3fac2ee85 100644 --- a/tutorials/utility_client/utility_client.md +++ b/tutorials/utility_client/utility_client.md @@ -602,7 +602,7 @@ else if (input.substr(0,5) == "close") { std::string cmd; int id; int close_code = websocketpp::close::status::normal; - std::string reason = ""; + std::string reason; ss >> cmd >> id >> close_code; std::getline(ss,reason); diff --git a/websocketpp/close.hpp b/websocketpp/close.hpp index f8e769436..ded776575 100644 --- a/websocketpp/close.hpp +++ b/websocketpp/close.hpp @@ -322,7 +322,7 @@ inline status::value extract_code(std::string const & payload, lib::error_code inline std::string extract_reason(std::string const & payload, lib::error_code & ec) { - std::string reason = ""; + std::string reason; ec = lib::error_code(); if (payload.size() > 2) { diff --git a/websocketpp/connection.hpp b/websocketpp/connection.hpp index a38608d0f..39c9b16bd 100644 --- a/websocketpp/connection.hpp +++ b/websocketpp/connection.hpp @@ -1385,7 +1385,7 @@ class connection * @return A status code, zero on success, non-zero otherwise */ lib::error_code send_close_ack(close::status::value code = - close::status::blank, std::string const & reason = ""); + close::status::blank, std::string const & reason = std::string()); /// Send close frame /** @@ -1403,7 +1403,7 @@ class connection * @return A status code, zero on success, non-zero otherwise */ lib::error_code send_close_frame(close::status::value code = - close::status::blank, std::string const & reason = "", bool ack = false, + close::status::blank, std::string const & reason = std::string(), bool ack = false, bool terminal = false); /// Get a pointer to a new WebSocket protocol processor for a given version diff --git a/websocketpp/http/constants.hpp b/websocketpp/http/constants.hpp index 10e726d0b..f946cb317 100644 --- a/websocketpp/http/constants.hpp +++ b/websocketpp/http/constants.hpp @@ -59,7 +59,7 @@ namespace http { static char const header_separator[] = ":"; /// Literal value of an empty header - static std::string const empty_header = ""; + static std::string const empty_header; /// Maximum size in bytes before rejecting an HTTP header as too big. size_t const max_header_size = 16000; @@ -284,8 +284,8 @@ namespace http { public: exception(const std::string& log_msg, status_code::value error_code, - const std::string& error_msg = "", - const std::string& body = "") + const std::string& error_msg = std::string(), + const std::string& body = std::string()) : m_msg(log_msg) , m_error_msg(error_msg) , m_body(body) diff --git a/websocketpp/http/impl/parser.hpp b/websocketpp/http/impl/parser.hpp index 92799a406..1d59b938e 100644 --- a/websocketpp/http/impl/parser.hpp +++ b/websocketpp/http/impl/parser.hpp @@ -71,7 +71,7 @@ inline void parser::append_header(std::string const & key, std::string const & throw exception("Invalid header name",status_code::bad_request); } - if (this->get_header(key) == "") { + if (this->get_header(key).empty()) { m_headers[key] = val; } else { m_headers[key] += ", " + val; @@ -91,7 +91,7 @@ inline void parser::remove_header(std::string const & key) { inline void parser::set_body(std::string const & value) { if (value.size() == 0) { remove_header("Content-Length"); - m_body = ""; + m_body.clear(); return; } @@ -117,7 +117,7 @@ inline bool parser::parse_parameter_list(std::string const & in, } inline bool parser::prepare_body() { - if (get_header("Content-Length") != "") { + if (!get_header("Content-Length").empty()) { std::string const & cl_header = get_header("Content-Length"); char * end; diff --git a/websocketpp/http/impl/request.hpp b/websocketpp/http/impl/request.hpp index 5da936f04..311a620f6 100644 --- a/websocketpp/http/impl/request.hpp +++ b/websocketpp/http/impl/request.hpp @@ -88,7 +88,7 @@ inline size_t request::consume(char const * buf, size_t len) { //the range [begin,end) now represents a line to be processed. if (end-begin == 0) { // we got a blank line - if (m_method.empty() || get_header("Host") == "") { + if (m_method.empty() || get_header("Host").empty()) { throw exception("Incomplete Request",status_code::bad_request); } diff --git a/websocketpp/http/impl/response.hpp b/websocketpp/http/impl/response.hpp index 653d1be36..4400cda5c 100644 --- a/websocketpp/http/impl/response.hpp +++ b/websocketpp/http/impl/response.hpp @@ -94,7 +94,7 @@ inline size_t response::consume(char const * buf, size_t len) { // TODO: grab content-length std::string length = get_header("Content-Length"); - if (length == "") { + if (length.empty()) { // no content length found, read indefinitely m_read = 0; } else { diff --git a/websocketpp/http/parser.hpp b/websocketpp/http/parser.hpp index ade86e415..90f49ebe5 100644 --- a/websocketpp/http/parser.hpp +++ b/websocketpp/http/parser.hpp @@ -230,7 +230,7 @@ InputIterator extract_attributes(InputIterator begin, InputIterator end, cursor = http::parser::extract_all_lws(cursor,end); ret = http::parser::extract_token(cursor,end); - if (ret.first == "") { + if (ret.first.empty()) { // error: expected a token return begin; } else { @@ -242,7 +242,7 @@ InputIterator extract_attributes(InputIterator begin, InputIterator end, if (cursor == end || *cursor != '=') { // if there is an equals sign, read the attribute value. Otherwise // record a blank value and continue - attributes[name] = ""; + attributes[name].clear(); continue; } @@ -263,7 +263,7 @@ InputIterator extract_attributes(InputIterator begin, InputIterator end, } ret = http::parser::extract_token(cursor,end); - if (ret.first == "") { + if (ret.first.empty()) { // error : expected token or quoted string return begin; } else { @@ -321,7 +321,7 @@ InputIterator extract_parameters(InputIterator begin, InputIterator end, ret = http::parser::extract_token(cursor,end); - if (ret.first == "") { + if (ret.first.empty()) { // error: expected a token return begin; } else { diff --git a/websocketpp/impl/connection_impl.hpp b/websocketpp/impl/connection_impl.hpp index 579529403..d29f70071 100644 --- a/websocketpp/impl/connection_impl.hpp +++ b/websocketpp/impl/connection_impl.hpp @@ -900,7 +900,7 @@ void connection::handle_read_handshake(lib::error_code const & ec, if (m_alog.static_test(log::alevel::devel)) { m_alog.write(log::alevel::devel,m_request.raw()); - if (m_request.get_header("Sec-WebSocket-Key3") != "") { + if (!m_request.get_header("Sec-WebSocket-Key3").empty()) { m_alog.write(log::alevel::devel, utility::to_hex(m_request.get_header("Sec-WebSocket-Key3"))); } @@ -1160,7 +1160,7 @@ lib::error_code connection::initialize_processor() { m_response.set_status(http::status_code::bad_request); std::stringstream ss; - std::string sep = ""; + std::string sep; std::vector::const_iterator it; for (it = versions_supported.begin(); it != versions_supported.end(); it++) { @@ -1308,7 +1308,7 @@ void connection::write_http_response(lib::error_code const & ec) { m_response.set_version("HTTP/1.1"); // Set server header based on the user agent settings - if (m_response.get_header("Server") == "") { + if (m_response.get_header("Server").empty()) { if (!m_user_agent.empty()) { m_response.replace_header("Server",m_user_agent); } else { @@ -1326,7 +1326,7 @@ void connection::write_http_response(lib::error_code const & ec) { if (m_alog.static_test(log::alevel::devel)) { m_alog.write(log::alevel::devel,"Raw Handshake response:\n"+m_handshake_buffer); - if (m_response.get_header("Sec-WebSocket-Key3") != "") { + if (!m_response.get_header("Sec-WebSocket-Key3").empty()) { m_alog.write(log::alevel::devel, utility::to_hex(m_response.get_header("Sec-WebSocket-Key3"))); } @@ -1450,7 +1450,7 @@ void connection::send_http_request() { } // Unless the user has overridden the user agent, send generic WS++ UA. - if (m_request.get_header("User-Agent") == "") { + if (m_request.get_header("User-Agent").empty()) { if (!m_user_agent.empty()) { m_request.replace_header("User-Agent",m_user_agent); } else { @@ -2075,7 +2075,7 @@ lib::error_code connection::send_close_frame(close::status::value code, if (config::silent_close) { m_alog.write(log::alevel::devel,"closing silently"); m_local_close_code = close::status::no_status; - m_local_close_reason = ""; + m_local_close_reason.clear(); } else if (code != close::status::blank) { m_alog.write(log::alevel::devel,"closing with specified codes"); m_local_close_code = code; @@ -2083,12 +2083,12 @@ lib::error_code connection::send_close_frame(close::status::value code, } else if (!ack) { m_alog.write(log::alevel::devel,"closing with no status code"); m_local_close_code = close::status::no_status; - m_local_close_reason = ""; + m_local_close_reason.clear(); } else if (m_remote_close_code == close::status::no_status) { m_alog.write(log::alevel::devel, "acknowledging a no-status close with normal code"); m_local_close_code = close::status::normal; - m_local_close_reason = ""; + m_local_close_reason.clear(); } else { m_alog.write(log::alevel::devel,"acknowledging with remote codes"); m_local_close_code = m_remote_close_code; @@ -2269,7 +2269,7 @@ void connection::log_open_result() // User Agent std::string ua = m_request.get_header("User-Agent"); - if (ua == "") { + if (ua.empty()) { s << "\"\" "; } else { // check if there are any quotes in the user agent @@ -2292,9 +2292,9 @@ void connection::log_close_result() s << "Disconnect " << "close local:[" << m_local_close_code - << (m_local_close_reason == "" ? "" : ","+m_local_close_reason) + << (m_local_close_reason.empty() ? "" : ","+m_local_close_reason) << "] remote:[" << m_remote_close_code - << (m_remote_close_reason == "" ? "" : ","+m_remote_close_reason) << "]"; + << (m_remote_close_reason.empty() ? "" : ","+m_remote_close_reason) << "]"; m_alog.write(log::alevel::disconnect,s.str()); } @@ -2319,7 +2319,7 @@ void connection::log_fail_result() // User Agent std::string ua = m_request.get_header("User-Agent"); - if (ua == "") { + if (ua.empty()) { s << " \"\" "; } else { // check if there are any quotes in the user agent @@ -2348,7 +2348,7 @@ void connection::log_http_result() { } // Connection Type - s << (m_request.get_header("host") == "" ? "-" : m_request.get_header("host")) + s << (m_request.get_header("host").empty() ? "-" : m_request.get_header("host")) << " " << transport_con_type::get_remote_endpoint() << " \"" << m_request.get_method() << " " << (m_uri ? m_uri->get_resource() : "-") @@ -2357,7 +2357,7 @@ void connection::log_http_result() { // User Agent std::string ua = m_request.get_header("User-Agent"); - if (ua == "") { + if (ua.empty()) { s << " \"\" "; } else { // check if there are any quotes in the user agent diff --git a/websocketpp/processors/hybi00.hpp b/websocketpp/processors/hybi00.hpp index 991813922..43d8e4fdd 100644 --- a/websocketpp/processors/hybi00.hpp +++ b/websocketpp/processors/hybi00.hpp @@ -85,9 +85,9 @@ class hybi00 : public processor { // Host is required by HTTP/1.1 // Connection is required by is_websocket_handshake // Upgrade is required by is_websocket_handshake - if (r.get_header("Sec-WebSocket-Key1") == "" || - r.get_header("Sec-WebSocket-Key2") == "" || - r.get_header("Sec-WebSocket-Key3") == "") + if (r.get_header("Sec-WebSocket-Key1").empty() || + r.get_header("Sec-WebSocket-Key2").empty() || + r.get_header("Sec-WebSocket-Key3").empty()) { return make_error_code(error::missing_required_header); } @@ -126,18 +126,18 @@ class hybi00 : public processor { // Echo back client's origin unless our local application set a // more restrictive one. - if (res.get_header("Sec-WebSocket-Origin") == "") { + if (res.get_header("Sec-WebSocket-Origin").empty()) { res.append_header("Sec-WebSocket-Origin",req.get_header("Origin")); } // Echo back the client's request host unless our local application // set a different one. - if (res.get_header("Sec-WebSocket-Location") == "") { + if (res.get_header("Sec-WebSocket-Location").empty()) { uri_ptr uri = get_uri(req); res.append_header("Sec-WebSocket-Location",uri->str()); } - if (subprotocol != "") { + if (!subprotocol.empty()) { res.replace_header("Sec-WebSocket-Protocol",subprotocol); } @@ -400,7 +400,7 @@ class hybi00 : public processor { private: void decode_client_key(std::string const & key, char * result) const { unsigned int spaces = 0; - std::string digits = ""; + std::string digits; uint32_t num; // key2 diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index b46593f65..b18dd153d 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -173,7 +173,7 @@ class hybi13 : public processor { // Host is required by HTTP/1.1 // Connection is required by is_websocket_handshake // Upgrade is required by is_websocket_handshake - if (r.get_header("Sec-WebSocket-Key") == "") { + if (r.get_header("Sec-WebSocket-Key").empty()) { return make_error_code(error::missing_required_header); } diff --git a/websocketpp/processors/processor.hpp b/websocketpp/processors/processor.hpp index ff3cbb2e7..5131cc45e 100644 --- a/websocketpp/processors/processor.hpp +++ b/websocketpp/processors/processor.hpp @@ -109,7 +109,7 @@ int get_websocket_version(request_type& r) { return -2; } - if (r.get_header("Sec-WebSocket-Version") == "") { + if (r.get_header("Sec-WebSocket-Version").empty()) { return 0; } diff --git a/websocketpp/uri.hpp b/websocketpp/uri.hpp index e2cd8c837..44a79cf31 100644 --- a/websocketpp/uri.hpp +++ b/websocketpp/uri.hpp @@ -135,7 +135,7 @@ class uri { } // parse port - std::string port = ""; + std::string port; while (state == 1) { if (it == uri_string.end()) { // state is not used after this point presently. @@ -169,7 +169,7 @@ class uri { std::string const & resource) : m_scheme(secure ? "wss" : "ws") , m_host(host) - , m_resource(resource == "" ? "/" : resource) + , m_resource(resource.empty() ? "/" : resource) , m_port(port) , m_secure(secure) , m_valid(true) {} @@ -177,7 +177,7 @@ class uri { uri(bool secure, std::string const & host, std::string const & resource) : m_scheme(secure ? "wss" : "ws") , m_host(host) - , m_resource(resource == "" ? "/" : resource) + , m_resource(resource.empty() ? "/" : resource) , m_port(secure ? uri_default_secure_port : uri_default_port) , m_secure(secure) , m_valid(true) {} @@ -186,7 +186,7 @@ class uri { std::string const & resource) : m_scheme(secure ? "wss" : "ws") , m_host(host) - , m_resource(resource == "" ? "/" : resource) + , m_resource(resource.empty() ? "/" : resource) , m_secure(secure) { lib::error_code ec; @@ -198,7 +198,7 @@ class uri { std::string const & resource) : m_scheme(scheme) , m_host(host) - , m_resource(resource == "" ? "/" : resource) + , m_resource(resource.empty() ? "/" : resource) , m_port(port) , m_secure(scheme == "wss" || scheme == "https") , m_valid(true) {} @@ -206,7 +206,7 @@ class uri { uri(std::string scheme, std::string const & host, std::string const & resource) : m_scheme(scheme) , m_host(host) - , m_resource(resource == "" ? "/" : resource) + , m_resource(resource.empty() ? "/" : resource) , m_port((scheme == "wss" || scheme == "https") ? uri_default_secure_port : uri_default_port) , m_secure(scheme == "wss" || scheme == "https") , m_valid(true) {} @@ -215,7 +215,7 @@ class uri { std::string const & port, std::string const & resource) : m_scheme(scheme) , m_host(host) - , m_resource(resource == "" ? "/" : resource) + , m_resource(resource.empty() ? "/" : resource) , m_secure(scheme == "wss" || scheme == "https") { lib::error_code ec; @@ -321,7 +321,7 @@ class uri { { ec = lib::error_code(); - if (port == "") { + if (port.empty()) { return (m_secure ? uri_default_secure_port : uri_default_port); } From 39c5f3ae3d90407d9002c713cdfedb96f15a11b2 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 30 Sep 2015 09:56:57 -0400 Subject: [PATCH 072/114] Update changelog --- changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index aca4bae50..067fe3313 100644 --- a/changelog.md +++ b/changelog.md @@ -19,6 +19,9 @@ HEAD and `connection::get_response_msg` methods to allow accessing additional information about the HTTP responses that WebSocket++ sends. #465 Thank you Flow86 for reporting. +- Improvement: Removes use of empty strings ("") in favor of `string::clear()` + and `string::empty()`. This avoids generating unnecessary temporary objects. + #468 Thank you Vladislav Yaroslavlev for reporting and a patch. - Documentation: Adds an example demonstrating the use of external `io_service` - Bug: Fix memory leak when init_asio produces an error. #454 Thank you Mark Grimes for reporting and fixing. From 6a941622646cf633c28835c208f47531a0d71735 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 30 Oct 2015 08:45:32 -0400 Subject: [PATCH 073/114] Fix error handling in debug_client fixes #473 --- examples/debug_client/debug_client.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/debug_client/debug_client.cpp b/examples/debug_client/debug_client.cpp index c6be2c111..5f4a1b7bc 100644 --- a/examples/debug_client/debug_client.cpp +++ b/examples/debug_client/debug_client.cpp @@ -76,6 +76,7 @@ class perftest { if (ec) { m_endpoint.get_alog().write(websocketpp::log::alevel::app,ec.message()); + return; } //con->set_proxy("http://humupdates.uchicago.edu:8443"); From 4e2fb75d07d903554ae4d729deb00c4ce79a53fc Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Fri, 30 Oct 2015 09:26:28 -0400 Subject: [PATCH 074/114] Removes non-standards compliant masking behavior. fixes #469, fixes #395 --- changelog.md | 2 ++ websocketpp/processors/hybi13.hpp | 41 ++++--------------------------- 2 files changed, 7 insertions(+), 36 deletions(-) diff --git a/changelog.md b/changelog.md index 067fe3313..f2d420ca3 100644 --- a/changelog.md +++ b/changelog.md @@ -36,6 +36,8 @@ HEAD long response before their HTTP handler ends would result in a second set of HTTP headers being injected into the output. Thank you Kevin Smith for reporting and providing test case details. #443 +- Compatibility: Removes non-standards compliant masking behavior. Fixes #469, + Fixes #395 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/websocketpp/processors/hybi13.hpp b/websocketpp/processors/hybi13.hpp index b18dd153d..79486654a 100644 --- a/websocketpp/processors/hybi13.hpp +++ b/websocketpp/processors/hybi13.hpp @@ -574,19 +574,6 @@ class hybi13 : public processor { * Performs validation, masking, compression, etc. will return an error if * there was an error, otherwise msg will be ready to be written * - * By default WebSocket++ performs block masking/unmasking in a manner that - * makes assumptions about the nature of the machine and STL library used. - * In particular the assumption is either a 32 or 64 bit word size and an - * STL with std::string::data returning a contiguous char array. - * - * This method improves masking performance by 3-8x depending on the ratio - * of small to large messages and the availability of a 64 bit processor. - * - * To disable this optimization (for use with alternative STL - * implementations or processors) define WEBSOCKETPP_STRICT_MASKING when - * compiling the library. This will force the library to perform masking in - * single byte chunks. - * * TODO: tests * * @param in An unprepared message to prepare @@ -791,19 +778,9 @@ class hybi13 : public processor { { // unmask if masked if (frame::get_masked(m_basic_header)) { - #ifdef WEBSOCKETPP_STRICT_MASKING - m_current_msg->prepared_key = frame::byte_mask_circ( - buf, - len, - m_current_msg->prepared_key - ); - #else - m_current_msg->prepared_key = frame::word_mask_circ( - buf, - len, - m_current_msg->prepared_key - ); - #endif + m_current_msg->prepared_key = frame::byte_mask_circ( + buf, len, m_current_msg->prepared_key); + // TODO: SIMD masking } std::string & out = m_current_msg->msg_ptr->get_raw_payload(); @@ -962,16 +939,8 @@ class hybi13 : public processor { void masked_copy (std::string const & i, std::string & o, frame::masking_key_type key) const { - #ifdef WEBSOCKETPP_STRICT_MASKING - frame::byte_mask(i.begin(),i.end(),o.begin(),key); - #else - websocketpp::frame::word_mask_exact( - reinterpret_cast(const_cast(i.data())), - reinterpret_cast(const_cast(o.data())), - i.size(), - key - ); - #endif + frame::byte_mask(i.begin(),i.end(),o.begin(),key); + // TODO: SIMD masking } /// Generic prepare control frame with opcode and payload. From 5500aef4ce0ec14d4e93a4c5f7f6072304eb3c25 Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 5 Nov 2015 06:33:15 -0500 Subject: [PATCH 075/114] Allow accessing the local endpoint when using the Asio transport. fixes #458 --- changelog.md | 7 +++++-- websocketpp/transport/asio/endpoint.hpp | 22 ++++++++++++++++++++++ 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/changelog.md b/changelog.md index f2d420ca3..e31525c3f 100644 --- a/changelog.md +++ b/changelog.md @@ -4,6 +4,10 @@ HEAD Custom Asio transport socket policies will need to be updated accordingly. This does not affect anyone using the bundled socket policies. - Feature: Basic support for the permessage-deflate extension. #344 +- Feature: Allow accessing the local endpoint when using the Asio transport. + This allows inspection of the address and port in cases where they are chosen + by the operating system rather than the user. Thank you Andreas Weis and + Muzahid Hussain for reporting and related code. #458 - Improvement: Better automatic std::chrono feature detection for Visual Studio - Improvement: Major refactoring to bundled CMake build system. CMake can now be used to build all of the examples and the test suite. Thank you Thijs Wenker @@ -36,8 +40,7 @@ HEAD long response before their HTTP handler ends would result in a second set of HTTP headers being injected into the output. Thank you Kevin Smith for reporting and providing test case details. #443 -- Compatibility: Removes non-standards compliant masking behavior. Fixes #469, - Fixes #395 +- Compatibility: Removes non-standards compliant masking behavior. #395, #469 0.6.0 - MINOR BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp index 6b348f985..1dd23787e 100644 --- a/websocketpp/transport/asio/endpoint.hpp +++ b/websocketpp/transport/asio/endpoint.hpp @@ -339,6 +339,28 @@ class endpoint : public config::socket_type { lib::asio::io_service & get_io_service() { return *m_io_service; } + + /// Get local TCP endpoint + /** + * Extracts the local endpoint from the acceptor. This represents the + * address that WebSocket++ is listening on. + * + * Sets a bad_descriptor error if the acceptor is not currently listening + * or otherwise unavailable. + * + * @since 0.7.0 + * + * @param ec Set to indicate what error occurred, if any. + * @return The local endpoint + */ + lib::asio::ip::tcp::endpoint get_local_endpoint(lib::asio::error_code & ec) { + if (m_acceptor) { + return m_acceptor->local_endpoint(ec); + } else { + ec = lib::asio::error::make_error_code(lib::asio::error::bad_descriptor); + return lib::asio::ip::tcp::endpoint(); + } + } /// Set up endpoint for listening manually (exception free) /** From b85affddf4b4aa422cd2a8a6c1f70364a01d583d Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Thu, 5 Nov 2015 08:29:04 -0500 Subject: [PATCH 076/114] Test how some doxygen compatible markup behaves on github --- tutorials/utility_client/utility_client.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tutorials/utility_client/utility_client.md b/tutorials/utility_client/utility_client.md index 3fac2ee85..1a25afb72 100644 --- a/tutorials/utility_client/utility_client.md +++ b/tutorials/utility_client/utility_client.md @@ -1,5 +1,5 @@ -Utility Client Example Application -================================== +Utility Client Example Application Tutorial +=========================================== Chapter 1: Initial Setup & Basics --------------------------------- @@ -17,7 +17,7 @@ A basic program loop that prompts the user for a command and then processes it. *note* A code snapshot for each step is present next to this tutorial file in the git repository. -```cpp +~~~{.cpp} #include #include @@ -44,7 +44,7 @@ int main() { return 0; } -``` +~~~ ### Step 2 From ed45dcc6171ce1a64f4d38102fa9db890c0486ad Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 24 Nov 2015 10:22:54 -0500 Subject: [PATCH 077/114] Fix an issue where the wrong type of strand was being created. --- changelog.md | 2 ++ websocketpp/transport/asio/connection.hpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index e31525c3f..fb66a1030 100644 --- a/changelog.md +++ b/changelog.md @@ -40,6 +40,8 @@ HEAD long response before their HTTP handler ends would result in a second set of HTTP headers being injected into the output. Thank you Kevin Smith for reporting and providing test case details. #443 +- Bug: Fix an issue where the wrong type of strand was being created. Thank you + Bastien Brunnenstein for reporting and a patch. #462 - Compatibility: Removes non-standards compliant masking behavior. #395, #469 0.6.0 diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index 1f1741e68..cfb57779c 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -462,7 +462,7 @@ class connection : public config::socket_type::socket_con_type { m_io_service = io_service; if (config::enable_multithreading) { - m_strand = lib::make_shared( + m_strand = lib::make_shared( lib::ref(*io_service)); m_async_read_handler = m_strand->wrap(lib::bind( From f7448bb1b00b5a6f2cad658b9f240bbac5839efd Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Tue, 15 Dec 2015 11:00:42 -0800 Subject: [PATCH 078/114] Write to the error log for socket cancel failures Previously an elevel entry was being written to an alog (possible copy-paste error?). --- websocketpp/transport/asio/connection.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index cfb57779c..325a53bd3 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -584,7 +584,7 @@ class connection : public config::socket_type::socket_con_type { // cancel not supported on this OS, ignore and log at dev level m_alog.write(log::alevel::devel, "socket cancel not supported"); } else { - m_alog.write(log::elevel::warn, "socket cancel failed"); + m_elog.write(log::elevel::warn, "socket cancel failed"); } } callback(ret_ec); From 999add0c4b9c0b72c427b513ccfa6691e605e338 Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Tue, 15 Dec 2015 11:26:59 -0800 Subject: [PATCH 079/114] Improve socket cancellation error messages log_err() includes information about the error code. --- websocketpp/transport/asio/connection.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index 325a53bd3..2aaa8a233 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -584,7 +584,7 @@ class connection : public config::socket_type::socket_con_type { // cancel not supported on this OS, ignore and log at dev level m_alog.write(log::alevel::devel, "socket cancel not supported"); } else { - m_elog.write(log::elevel::warn, "socket cancel failed"); + log_err(log::elevel::warn, "socket cancel failed", cec); } } callback(ret_ec); From 5f52127cf76f74e8c4021594c069fbb07cc0e8bb Mon Sep 17 00:00:00 2001 From: Jacob Champion Date: Tue, 15 Dec 2015 11:24:04 -0800 Subject: [PATCH 080/114] Always log errors during socket cancel cancel_socket_checked(), which logs any received errors, is now called consistently instead of the lower-level cancel_socket(). --- websocketpp/transport/asio/connection.hpp | 28 ++++++++++++++--------- websocketpp/transport/asio/endpoint.hpp | 2 +- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/websocketpp/transport/asio/connection.hpp b/websocketpp/transport/asio/connection.hpp index 2aaa8a233..b9f92ef3f 100644 --- a/websocketpp/transport/asio/connection.hpp +++ b/websocketpp/transport/asio/connection.hpp @@ -578,15 +578,7 @@ class connection : public config::socket_type::socket_con_type { } m_alog.write(log::alevel::devel, "Asio transport post-init timed out"); - lib::asio::error_code cec = socket_con_type::cancel_socket(); - if (cec) { - if (cec == lib::asio::error::operation_not_supported) { - // cancel not supported on this OS, ignore and log at dev level - m_alog.write(log::alevel::devel, "socket cancel not supported"); - } else { - log_err(log::elevel::warn, "socket cancel failed", cec); - } - } + cancel_socket_checked(); callback(ret_ec); } @@ -690,7 +682,7 @@ class connection : public config::socket_type::socket_con_type { } else { m_alog.write(log::alevel::devel, "asio handle_proxy_write timer expired"); - socket_con_type::cancel_socket(); + cancel_socket_checked(); callback(make_error_code(transport::error::timeout)); } } @@ -1105,7 +1097,7 @@ class connection : public config::socket_type::socket_con_type { m_alog.write(log::alevel::devel, "Asio transport socket shutdown timed out"); - socket_con_type::cancel_socket(); + cancel_socket_checked(); callback(ret_ec); } @@ -1154,6 +1146,20 @@ class connection : public config::socket_type::socket_con_type { } callback(tec); } + + /// Cancel the underlying socket and log any errors + void cancel_socket_checked() { + lib::asio::error_code cec = socket_con_type::cancel_socket(); + if (cec) { + if (cec == lib::asio::error::operation_not_supported) { + // cancel not supported on this OS, ignore and log at dev level + m_alog.write(log::alevel::devel, "socket cancel not supported"); + } else { + log_err(log::elevel::warn, "socket cancel failed", cec); + } + } + } + private: /// Convenience method for logging the code and message for an error_code template diff --git a/websocketpp/transport/asio/endpoint.hpp b/websocketpp/transport/asio/endpoint.hpp index 1dd23787e..d0af21579 100644 --- a/websocketpp/transport/asio/endpoint.hpp +++ b/websocketpp/transport/asio/endpoint.hpp @@ -1027,7 +1027,7 @@ class endpoint : public config::socket_type { } m_alog->write(log::alevel::devel,"TCP connect timed out"); - tcon->cancel_socket(); + tcon->cancel_socket_checked(); callback(ret_ec); } From bda1bd14cb067276cf9935aaffc7b799d51f698a Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 15 Dec 2015 19:13:37 -0500 Subject: [PATCH 081/114] use c++11 thread support on recent visual studio versions --- websocketpp/common/thread.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/websocketpp/common/thread.hpp b/websocketpp/common/thread.hpp index fa87396f9..c0ce43196 100644 --- a/websocketpp/common/thread.hpp +++ b/websocketpp/common/thread.hpp @@ -43,6 +43,14 @@ #endif #endif +// If we're on Visual Studio 2013 or higher and haven't explicitly disabled +// the use of C++11 thread header then prefer it to boost. +#if defined(_MSC_VER) && _MSC_VER >= 1800 && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_ + #ifndef _WEBSOCKETPP_CPP11_MEMORY_ + #define _WEBSOCKETPP_CPP11_MEMORY_ + #endif +#endif + #ifdef _WEBSOCKETPP_CPP11_THREAD_ #include #include From 1e12e7aff8c3359970363bbdf79c9cffdc1e979b Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Tue, 15 Dec 2015 19:17:11 -0500 Subject: [PATCH 082/114] use c++11 thread support on recent visual studio versions (really) --- websocketpp/common/thread.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/websocketpp/common/thread.hpp b/websocketpp/common/thread.hpp index c0ce43196..09f6b3c51 100644 --- a/websocketpp/common/thread.hpp +++ b/websocketpp/common/thread.hpp @@ -45,9 +45,9 @@ // If we're on Visual Studio 2013 or higher and haven't explicitly disabled // the use of C++11 thread header then prefer it to boost. -#if defined(_MSC_VER) && _MSC_VER >= 1800 && !defined _WEBSOCKETPP_NO_CPP11_MEMORY_ - #ifndef _WEBSOCKETPP_CPP11_MEMORY_ - #define _WEBSOCKETPP_CPP11_MEMORY_ +#if defined(_MSC_VER) && _MSC_VER >= 1800 && !defined _WEBSOCKETPP_NO_CPP11_THREAD_ + #ifndef _WEBSOCKETPP_CPP11_THREAD_ + #define _WEBSOCKETPP_CPP11_THREAD_ #endif #endif From 935c8a3264eabcf8c5b72bafc2f0c94ef7c3cedf Mon Sep 17 00:00:00 2001 From: Peter Thorson Date: Wed, 16 Dec 2015 10:03:14 -0500 Subject: [PATCH 083/114] Begin update to migrate manual content into the git repository The goal here is to get all the documentation in one place including the class reference, text based manual, tutorials, etc. --- Doxyfile | 2552 ++++++++++++++++++++++---------------- docs/faq.dox | 22 + docs/getting_started.dox | 27 + docs/handlers.dox | 165 +++ docs/manual.css | 22 + docs/manual.dox | 18 + 6 files changed, 1771 insertions(+), 1035 deletions(-) create mode 100644 docs/faq.dox create mode 100644 docs/getting_started.dox create mode 100644 docs/handlers.dox create mode 100644 docs/manual.css create mode 100644 docs/manual.dox diff --git a/Doxyfile b/Doxyfile index 3e7d4a049..88a37bd6d 100644 --- a/Doxyfile +++ b/Doxyfile @@ -1,111 +1,129 @@ -# Doxyfile 1.8.3.1 +# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored. +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. - -PROJECT_NAME = "websocketpp" +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +PROJECT_NAME = WebSocket++ +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. -PROJECT_NUMBER = "0.7.x-dev" +PROJECT_NUMBER = 0.7.x-dev # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "C++/Boost Asio based websocket client/server library" +PROJECT_BRIEF = "C++ websocket client/server library" -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. -PROJECT_LOGO = +PROJECT_LOGO = -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. -OUTPUT_DIRECTORY = "doxygen" +OUTPUT_DIRECTORY = doxygen -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. -ABBREVIATE_BRIEF = +ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -113,179 +131,207 @@ ALWAYS_DETAILED_SEC = NO # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. Note that you specify absolute paths here, but also -# relative paths, which will be relative from the directory where doxygen is -# started. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = NO -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = NO -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. -ALIASES = +ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. -TCL_SUBST = +TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it -# using this tag. The format is ext=language, where ext is a file extension, -# and language is one of the parsers supported by doxygen: IDL, Java, -# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, -# C++. For instance to make doxygen treat .inc files as Fortran files (default -# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note -# that for custom extensions you also need to set FILE_PATTERNS otherwise the -# files are not read by doxygen. - -EXTENSION_MAPPING = - -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. MARKDOWN_SUPPORT = YES -# When enabled doxygen tries to link words that correspond to documented classes, -# or namespaces to their corresponding documentation. Such a link can be -# prevented in individual cases by by putting a % sign in front of the word or -# globally by setting AUTOLINK_SUPPORT to NO. +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate -# getter and setter methods for a property. Setting this option to YES (the -# default) will make doxygen replace the get and set methods by a property in -# the documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES @@ -293,67 +339,61 @@ IDL_PROPERTY_SUPPORT = YES # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. INLINE_GROUPED_CLASSES = NO -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. INLINE_SIMPLE_STRUCTS = NO -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 @@ -362,345 +402,394 @@ LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. +# The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = YES -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = NO -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = NO -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = NO -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. FORCE_LOCAL_INCLUDES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= YES -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if section-label ... \endif -# and \cond section-label ... \endcond blocks. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. -ENABLED_SECTIONS = +ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = YES -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. -FILE_VERSION_FILTER = +FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. -LAYOUT_FILE = +LAYOUT_FILE = -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. Do not use -# file names with spaces, bibtex cannot handle them. +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. -CITE_BIB_FILES = +CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = YES -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. -INPUT = websocketpp \ - readme.md \ +INPUT = readme.md \ changelog.md \ - roadmap.md + roadmap.md \ + websocketpp \ + tutorials \ + docs # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. -FILE_PATTERNS = +FILE_PATTERNS = -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# # Note that relative paths are relative to the directory from which doxygen is # run. @@ -709,942 +798,1255 @@ EXCLUDE = build # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). -EXAMPLE_PATH = +EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. -EXAMPLE_PATTERNS = +EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). -IMAGE_PATH = +IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. -INPUT_FILTER = +INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. -FILTER_PATTERNS = +FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. -FILTER_SOURCE_PATTERNS = +FILTER_SOURCE_PATTERNS = -# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that -# is part of the input, its contents will be placed on the main page (index.html). -# This can be useful if you have a project on for instance GitHub and want reuse -# the introduction page also for the doxygen output. +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = YES -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = NO -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = NO -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES, then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# compiled with the --with-libclang option. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = YES + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! - -HTML_HEADER = - -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. - -HTML_FOOTER = - -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If left blank doxygen will -# generate a default style sheet. Note that it is recommended to use -# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this -# tag will in the future become obsolete. - -HTML_STYLESHEET = - -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional -# user-defined cascading style sheet that is included after the standard -# style sheets created by doxygen. Using this option one can overrule -# certain style aspects. This is preferred over using HTML_STYLESHEET -# since it does not replace the standard style sheet and is therefor more -# robust against future updates. Doxygen will copy the style sheet file to -# the output directory. - -HTML_EXTRA_STYLESHEET = +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = docs/manual.css # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. - -HTML_EXTRA_FILES = - -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 236 -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 0 -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 148 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = NO # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely -# identify the documentation publisher. This should be a reverse domain-name -# style string, e.g. com.mycompany.MyDocSet.documentation. +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_FILE = +CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -HHC_LOCATION = +HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_INDEX_ENCODING = +CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. -QCH_FILE = +QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_ATTRS = +QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. -QHP_SECT_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. -QHG_LOCATION = +QHG_LOCATION = -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for -# thA MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and -# SVG. The default value is HTML-CSS, which is slower, but has the best -# compatibility. +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. - -MATHJAX_EXTENSIONS = - -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /