Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
############ Setup project and cmake
# Minimum cmake requirement. We should require a quite recent
# cmake for the dependency find macros etc. to be up to date.
cmake_minimum_required (VERSION 2.8.8)
cmake_minimum_required (VERSION 3.10)

############ Paths

Expand Down Expand Up @@ -77,6 +77,7 @@ include (CMakeHelpers)
option (ENABLE_CPP11 "Build websocketpp with CPP11 features enabled." TRUE)
option (BUILD_EXAMPLES "Build websocketpp examples." FALSE)
option (BUILD_TESTS "Build websocketpp tests." FALSE)
option (USE_ASIO_STANDALONE "Build websocketpp examples and tests using the standalone ASIO library." FALSE)

if (BUILD_TESTS OR BUILD_EXAMPLES)

Expand Down Expand Up @@ -114,7 +115,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)

# Visual studio
if (MSVC)
set (WEBSOCKETPP_BOOST_LIBS system thread)
set (WEBSOCKETPP_BOOST_LIBS thread)
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL /Gy /GF /Ox /Ob2 /Ot /Oi /MP /arch:SSE2 /fp:fast")
set (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG /INCREMENTAL:NO /OPT:REF /OPT:ICF")
add_definitions (/W3 /wd4996 /wd4995 /wd4355)
Expand All @@ -135,7 +136,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
endif()
endif()
set (WEBSOCKETPP_PLATFORM_TLS_LIBS ssl crypto)
set (WEBSOCKETPP_BOOST_LIBS system thread)
set (WEBSOCKETPP_BOOST_LIBS thread)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
if (NOT APPLE)
add_definitions (-DNDEBUG -Wall -Wcast-align) # todo: should we use CMAKE_C_FLAGS for these?
Expand All @@ -145,7 +146,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
execute_process (COMMAND ${CMAKE_CXX_COMPILER} "-dumpversion" OUTPUT_VARIABLE GCC_VERSION)
if ("${GCC_VERSION}" STRGREATER "4.4.0")
message("* C++11 support partially enabled due to GCC version ${GCC_VERSION}")
set (WEBSOCKETPP_BOOST_LIBS system thread)
set (WEBSOCKETPP_BOOST_LIBS thread)
endif ()
endif ()

Expand All @@ -159,7 +160,7 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
set (WEBSOCKETPP_PLATFORM_LIBS pthread rt)
endif()
set (WEBSOCKETPP_PLATFORM_TLS_LIBS ssl crypto)
set (WEBSOCKETPP_BOOST_LIBS system thread)
set (WEBSOCKETPP_BOOST_LIBS thread)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
if (NOT APPLE)
add_definitions (-DNDEBUG -Wall -Wno-padded) # todo: should we use CMAKE_C_FLAGS for these?
Expand Down Expand Up @@ -221,9 +222,8 @@ if (BUILD_TESTS OR BUILD_EXAMPLES)
set (Boost_FIND_QUIETLY TRUE)
set (Boost_DEBUG FALSE)
set (Boost_USE_MULTITHREADED TRUE)
set (Boost_ADDITIONAL_VERSIONS "1.39.0" "1.40.0" "1.41.0" "1.42.0" "1.43.0" "1.44.0" "1.46.1") # todo: someone who knows better spesify these!

find_package (Boost 1.39.0 COMPONENTS ${WEBSOCKETPP_BOOST_LIBS})
find_package (Boost 1.70.0 CONFIG COMPONENTS ${WEBSOCKETPP_BOOST_LIBS})

if (Boost_FOUND)
# Boost is a project wide global dependency.
Expand Down Expand Up @@ -254,6 +254,10 @@ endif()

############ Add projects

if (USE_ASIO_STANDALONE)
add_definitions("-DASIO_STANDALONE -DASIO_HAS_BOOST_DATE_TIME")
endif ()

# Add main library
add_subdirectory (websocketpp)

Expand Down
4 changes: 2 additions & 2 deletions SConstruct
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ 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)
# external_io_context
external_io_context = SConscript('#/examples/external_io_context/SConscript',variant_dir = builddir + 'external_io_context',duplicate = 0)

if not env['PLATFORM'].startswith('win'):
# iostream_server
Expand Down
12 changes: 6 additions & 6 deletions docs/faq.dox
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@ Note: some browsers will allow the connection to continue if they requested a su

### How do I cleanly exit an Asio transport based program

The Asio transport based clients and servers use the Asio library's underlying `io_service` to handle asyncronous networking operations. The standard behavior of the io_service is to run until there are no async operations left and then return. WebSocket++, when using the Asio transport, behaves like a standard Asio application. If you want your WebSocket++/Asio based program to stop network operations and cleanly close all sockets you will want to do the following:
The Asio transport based clients and servers use the Asio library's underlying `io_context` to handle asyncronous networking operations. The standard behavior of the io_context is to run until there are no async operations left and then return. WebSocket++, when using the Asio transport, behaves like a standard Asio application. If you want your WebSocket++/Asio based program to stop network operations and cleanly close all sockets you will want to do the following:

- For servers, call `websocketpp::transport::asio::endpoint::stop_listening` to initiate the closing of the server listening socket.
- For clients, if you have engaged perpetual mode with `websocketpp::transport::asio::endpoint::start_perpetual`, disable it with `websocketpp::transport::asio::endpoint::stop_perpetual`.
- For both, run `websocketpp::endpoint::close` or `websocketpp::connection::close` on all currently outstanding connections. This will initiate the WebSocket closing handshake for these connections
- Wait. Asio is asyncronous. When the calls to the above methods (stop_listening, close, etc) complete the server *will still be listening*, the connections *will still be active* until the io_service gets around to asyncronously processing the socket and WebSocket protocol closing handshakes. The `io_service::run` method will exit cleanly and automatically when all operations are complete.
- Wait. Asio is asyncronous. When the calls to the above methods (stop_listening, close, etc) complete the server *will still be listening*, the connections *will still be active* until the io_context gets around to asyncronously processing the socket and WebSocket protocol closing handshakes. The `io_context::run` method will exit cleanly and automatically when all operations are complete.

__WARNING__: Asio's `io_service` has a method called `stop`. WebSocket++ wraps this method as `websocketpp::transport::asio::endpoint::stop`. While this operation has a benign sounding name, it is a powerful and destructive operation that should only be used in special cases. If you are using `io_service::stop` or `endpoint::stop` without a very good reason your program is likely broken and may exhibit erratic behavior. Specifically, `io_service::stop` stops the processing of events entirely. This does not give current operations (such as socket closing handshakes) the opportunity to finish. It will leave your sockets in a dangling state that may invoke operating system level timeouts or other errors.
__WARNING__: Asio's `io_context` has a method called `stop`. WebSocket++ wraps this method as `websocketpp::transport::asio::endpoint::stop`. While this operation has a benign sounding name, it is a powerful and destructive operation that should only be used in special cases. If you are using `io_context::stop` or `endpoint::stop` without a very good reason your program is likely broken and may exhibit erratic behavior. Specifically, `io_context::stop` stops the processing of events entirely. This does not give current operations (such as socket closing handshakes) the opportunity to finish. It will leave your sockets in a dangling state that may invoke operating system level timeouts or other errors.

__Special cases__:
- If your client uses the `start_perpetual` method it will prevent the io_service from exiting even if it has nothing to do. This is useful if you want a client endpoint to idle in the background to allow new connections to be formed on demand rather than generating a new endpoint for each.
- If you are using an external io_service and/or are placing non-WebSocket++ operations on the `io_service` those operations may keep the `io_service` open even after all WebSocket++ operations have completed.
- If you are using `poll`/`poll_one`/`run_one` or otherwise manually driving the `io_service` event loop you may need to adjust usage to make sure you are correctly recognizing the "done with work" and "not done but idling / `io_service::work`" cases.
- If your client uses the `start_perpetual` method it will prevent the io_context from exiting even if it has nothing to do. This is useful if you want a client endpoint to idle in the background to allow new connections to be formed on demand rather than generating a new endpoint for each.
- If you are using an external io_context and/or are placing non-WebSocket++ operations on the `io_context` those operations may keep the `io_context` open even after all WebSocket++ operations have completed.
- If you are using `poll`/`poll_one`/`run_one` or otherwise manually driving the `io_context` event loop you may need to adjust usage to make sure you are correctly recognizing the "done with work" and "not done but idling / `io_context::work`" cases.

### Is there a way to check the validity of a `connection_hdl`?

Expand Down
4 changes: 2 additions & 2 deletions examples/broadcast_server/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ prgs = []

# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','thread'],env) + [platform_libs] + [polyfill_libs]
ALL_LIBS = boostlibs(['thread'],env) + [platform_libs] + [polyfill_libs]
prgs += env.Program('broadcast_server', ["broadcast_server.cpp"], LIBS = ALL_LIBS)

Return('prgs')
2 changes: 1 addition & 1 deletion examples/broadcast_server/broadcast_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ class broadcast_server {
return;
}

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
//try {
m_server.run();
//} catch (const std::exception & e) {
Expand Down
4 changes: 2 additions & 2 deletions examples/debug_client/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ prgs = []

# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs] + [tls_libs]
prgs += env_cpp11.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
ALL_LIBS = boostlibs(['random'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
prgs += env.Program('debug_client', ["debug_client.cpp"], LIBS = ALL_LIBS)

Return('prgs')
14 changes: 7 additions & 7 deletions examples/debug_client/debug_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ using websocketpp::lib::bind;

// pull out the type of messages sent by our config
typedef websocketpp::config::asio_tls_client::message_type::ptr message_ptr;
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;
typedef client::connection_ptr connection_ptr;


Expand Down Expand Up @@ -82,7 +82,7 @@ class perftest {

m_endpoint.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
m_start = std::chrono::high_resolution_clock::now();
m_endpoint.run();
}
Expand All @@ -93,13 +93,13 @@ class perftest {

context_ptr on_tls_init(websocketpp::connection_hdl) {
m_tls_init = std::chrono::high_resolution_clock::now();
context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv1);
context_ptr ctx = websocketpp::lib::make_shared<websocketpp::lib::asio::ssl::context>(websocketpp::lib::asio::ssl::context::tlsv1);

try {
ctx->set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3 |
boost::asio::ssl::context::single_dh_use);
ctx->set_options(websocketpp::lib::asio::ssl::context::default_workarounds |
websocketpp::lib::asio::ssl::context::no_sslv2 |
websocketpp::lib::asio::ssl::context::no_sslv3 |
websocketpp::lib::asio::ssl::context::single_dh_use);
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
Expand Down
4 changes: 2 additions & 2 deletions examples/debug_server/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ prgs = []

# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs]
prgs += env.Program('debug_server', ["debug_server.cpp"], LIBS = ALL_LIBS)

Return('prgs')
2 changes: 1 addition & 1 deletion examples/debug_server/debug_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ int main() {
// Start the server accept loop
echo_server.start_accept();

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
echo_server.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
Expand Down
2 changes: 1 addition & 1 deletion examples/dev/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ env_cpp11 = env_cpp11.Clone ()
prgs = []

if 'WSPP_CPP11_ENABLED' in env_cpp11:
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','system','timer','chrono'],env_cpp11) + [platform_libs] + [polyfill_libs]
BOOST_LIBS_CPP11 = boostlibs(['unit_test_framework','timer','chrono'],env_cpp11) + [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('main', ["main.cpp"], LIBS = BOOST_LIBS_CPP11)

Return('prgs')
4 changes: 2 additions & 2 deletions examples/echo_client/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ prgs = []

# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + ['z']
ALL_LIBS = [platform_libs] + [polyfill_libs] + ['z']
prgs += env_cpp11.Program('echo_client', ["echo_client.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system','random'],env) + [platform_libs] + [polyfill_libs] + ['z']
ALL_LIBS = boostlibs(['random'],env) + [platform_libs] + [polyfill_libs] + ['z']
prgs += env.Program('echo_client', ["echo_client.cpp"], LIBS = ALL_LIBS)

Return('prgs')
2 changes: 1 addition & 1 deletion examples/echo_client/echo_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ int main(int argc, char* argv[]) {
// exchanged until the event loop starts running in the next line.
c.connect(con);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
// this will cause a single connection to be made to the server. c.run()
// will exit when this connection is closed.
c.run();
Expand Down
4 changes: 2 additions & 2 deletions examples/echo_server/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ prgs = []

# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs]
prgs += env_cpp11.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs]
prgs += env.Program('echo_server', ["echo_server.cpp"], LIBS = ALL_LIBS)

Return('prgs')
2 changes: 1 addition & 1 deletion examples/echo_server/echo_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ int main() {
// Start the server accept loop
echo_server.start_accept(&on_end_accept);

// Start the ASIO io_service run loop
// Start the ASIO io_context run loop
echo_server.run();
} catch (websocketpp::exception const & e) {
std::cout << e.what() << std::endl;
Expand Down
4 changes: 2 additions & 2 deletions examples/echo_server_both/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ prgs = []

# if a C++11 environment is available build using that, otherwise use boost
if 'WSPP_CPP11_ENABLED' in env_cpp11:
ALL_LIBS = boostlibs(['system'],env_cpp11) + [platform_libs] + [polyfill_libs] + [tls_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs] + [tls_libs]
prgs += env_cpp11.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)
else:
ALL_LIBS = boostlibs(['system'],env) + [platform_libs] + [polyfill_libs] + [tls_libs]
ALL_LIBS = [platform_libs] + [polyfill_libs] + [tls_libs]
prgs += env.Program('echo_server_both', ["echo_server_both.cpp"], LIBS = ALL_LIBS)

Return('prgs')
28 changes: 14 additions & 14 deletions examples/echo_server_both/echo_server_both.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ using websocketpp::lib::bind;
using websocketpp::lib::error_code;

// type of the ssl context pointer is long so alias it
typedef websocketpp::lib::shared_ptr<boost::asio::ssl::context> context_ptr;
typedef websocketpp::lib::shared_ptr<websocketpp::lib::asio::ssl::context> context_ptr;

// The shared on_message handler takes a template parameter so the function can
// resolve any endpoint dependent types like message_ptr or connection_ptr
Expand Down Expand Up @@ -48,39 +48,39 @@ std::string get_password() {

context_ptr on_tls_init(websocketpp::connection_hdl hdl) {
std::cout << "on_tls_init called with hdl: " << hdl.lock().get() << std::endl;
context_ptr ctx(new boost::asio::ssl::context(boost::asio::ssl::context::tlsv1));
context_ptr ctx(new websocketpp::lib::asio::ssl::context(websocketpp::lib::asio::ssl::context::tlsv1));

try {
ctx->set_options(boost::asio::ssl::context::default_workarounds |
boost::asio::ssl::context::no_sslv2 |
boost::asio::ssl::context::no_sslv3 |
boost::asio::ssl::context::single_dh_use);
ctx->set_options(websocketpp::lib::asio::ssl::context::default_workarounds |
websocketpp::lib::asio::ssl::context::no_sslv2 |
websocketpp::lib::asio::ssl::context::no_sslv3 |
websocketpp::lib::asio::ssl::context::single_dh_use);
ctx->set_password_callback(bind(&get_password));
ctx->use_certificate_chain_file("server.pem");
ctx->use_private_key_file("server.pem", boost::asio::ssl::context::pem);
ctx->use_private_key_file("server.pem", websocketpp::lib::asio::ssl::context::pem);
} catch (std::exception& e) {
std::cout << e.what() << std::endl;
}
return ctx;
}

int main() {
// set up an external io_service to run both endpoints on. This is not
// set up an external io_context to run both endpoints on. This is not
// strictly necessary, but simplifies thread management a bit.
boost::asio::io_service ios;
websocketpp::lib::asio::io_context ctx;

// set up plain endpoint
server_plain endpoint_plain;
// initialize asio with our external io_service rather than an internal one
endpoint_plain.init_asio(&ios);
// initialize asio with our external io_context rather than an internal one
endpoint_plain.init_asio(&ctx);
endpoint_plain.set_message_handler(
bind(&on_message<server_plain>,&endpoint_plain,::_1,::_2));
endpoint_plain.listen(80);
endpoint_plain.start_accept(&on_end_accept);

// set up tls endpoint
server_tls endpoint_tls;
endpoint_tls.init_asio(&ios);
endpoint_tls.init_asio(&ctx);
endpoint_tls.set_message_handler(
bind(&on_message<server_tls>,&endpoint_tls,::_1,::_2));
// TLS endpoint has an extra handler for the tls init
Expand All @@ -89,6 +89,6 @@ int main() {
endpoint_tls.listen(443);
endpoint_tls.start_accept(&on_end_accept);

// Start the ASIO io_service run loop running both endpoints
ios.run();
// Start the ASIO io_context run loop running both endpoints
ctx.run();
}
Loading