WebSocket++  0.8.3-dev
C++ websocket client/server library
FAQ

General Library Usage

Can a handler be changed after a connection is established? Can one be removed?

Yes, but not globally.

Handlers assigned to endpoints will be automatically copied to the connections created by that endpoint. Changing a handler on an endpoint will only affect future connections.

Once a particular connection is created, it's handlers can be changed individually by calling the set_*_handler methods. Once changed, all future events of that type for that connection will use the new handler.

To remove a handler that was previously set, call the set method with nullptr or NULL.

Can I reject or conditionally accept a connection

Yes. The validate handler is called after the initial handshake has been recieved but before WebSocket++ has responded. This gives you the opportunity to inspect the incoming connection request, its headers, origin, subprotocols, and the remote endpoint IP. Return true from the validate handler to accept the connection and false to reject it.

To set a custom HTTP error message for your rejection, use websocketpp::connection::set_status and (optionally) websocketpp::connection::set_body() to set the HTTP status code and error message body text. If you do not set body text a message will be generated automatically based on the status code.

How do I negotiate subprotocols?

WebSocket connections may offer a particular subprotocol they want to use. The WebSocket protocol does not define the meaning or interpretation of the subprotocol. This interpretation is left up to the individual application endpoints.

WebSocket++ servers can read the requested subprotocols during the validate handler by calling websocketpp::connection::get_requested_subprotocols. The list is ordered by client priority. You may optionally choose one of these subprotocols with websocketpp::connection::select_subprotocol. The handshake will then complete and let the client know which one was chosen. If you do not choose any, the "blank"/empty/none subprotocol will be used.

WebSocket++ clients can add a subprotocol to an outgoing connection by calling websocketpp::connection::add_subprotocol before calling websocketpp::client::connect. The order of adding will be interpreted as the order of preference.

In both caases, after the connection has been established, the selected subprotocol is available via the websocketpp::connection::get_subprotocol method.

Note: some browsers will allow the connection to continue if they requested a subprotocol and your server doesn't select one. Others will reject the connection.

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:

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.

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.

Is there a way to check the validity of a <tt>connection_hdl</tt>?

Sometimes, not generally though, because there isn’t a way to check if a TCP connection is valid.

You can try upgrading your hdl to a full connection_ptr using websocketpp::endpoint::get_con_from_hdl. If this fails, the hdl is definitely invalid. If it succeeds it may or may not be. The only way to tell definitively is to try and send something (either a message or a ping).

If you handle errors from methods like send, ping, close, etc correctly then you shouldn’t have to worry about accidentally sending to dead connections. The send/ping/pong/close methods will set or throw a specific error in the case that you tried to send something but the connection was closed/gone/etc.

How do I fix the "address is in use" error when trying to restart my server?

Normally, for security purposes, operating systems prevent programs from listening on sockets created by other programs. When your program crashes and restarts, the new instance is a different program from the perspective of the operating system. As such it can’t listen on the socket address/port that the previous program was using until after a timeout occurs to make sure the old program was done with it.

The first step for handling this is to make sure that you provide a method (signal handler, admin websocket message, etc) to perform a clean server shutdown. There is a question elsewhere in this FAQ that describes the steps necessary for this.

The clean close strategy won't help in the case of crashes or other abnormal closures. An option to consider for these cases is the use of the SO_REUSEADDR socket option. This instructs the OS to not request an exclusive lock on the socket. This means that after your program crashes the replacement you start can immediately listen on that address/port combo again.

Please note: how this works exactly depends on your operating system. Additionally, not exclusively locking your listening socket could allow hijacking by other programs if you are running in a shared resource environment. For development this is generally no problem. For a production environment, think carefully about the security model. websocketpp::transport::asio::endpoint::set_reuse_addr is the method to do this. You must specify this setting before calling websocketpp::transport::asio::endpoint::listen.

How do I send and recieve binary messages?

When supported by the remote endpoint, WebSocket++ allows reading and sending messages in the two formats specified in RFC6455, UTF8 text and binary. WebSocket++ performs UTF8 validation on all outgoing text messages to ensure that they meet the specification. Binary messages do not have any additional processing and their interpretation is left entirely to the library user.

To determine the type of an incoming message, use websocketpp::message_buffer::message::get_opcode. The relevant return values are websocketpp::frame::opcode::text and websocketpp::frame::opcode::binary. There is no difference in how payloads are retrieved between these modes, only in how WebSocket++ validated the contents and how the library user is to interpret the data.

To specify the type of an outgoing message, use the frame opcode values listed above as the second op parameter for websocketpp::connection::send. There are two relevant overloads of send. One that takes a std::string and defaults to op=text. The other that takes a void const * and a size_t length and defaults to op=binary. Note: You can send binary messages via the string overload and text messages via the void * overload. In the case that you are manually building a message buffer rather than using the automatic send member functions, you can pass the opcode in as a parameter to the message buffer constructor or user the websocketpp::message_buffer::message::set_opcode member function to set or re-set it later.

Dependency Management

Can WebSocket++ be used without Boost?

Yes. WebSocket++ only uses Boost features as polyfills for C++11 language features and libraries. If you have a C++11 compiler and standard library you can use WebSocket++ without Boost. In most cases setting your build environment to use the C++11 (or later) language dialect is sufficient to enable this mode of use.

With less common compilers (and sometimes very recently release compilers) there may be specific issues with certain libraries that aren't automatically detected by the library. For these situations there are additional defines available to fine tune which C++11 libraries and features are used. TODO: more details about them.

For the iostream/raw transport the C++11 standard library is sufficient. For the Asio based transports, there is no C++11 library that provides the networking capabilaties that Asio does. As such even with a C++11 build system, you will need a standalone copy of Asio to use if Boost Asio is not available.

MinGW users who want to avoid Boost should also consult the nearby question about MinGW compatibility.

Can WebSocket++ be used with standalone Asio

Yes. The process is the same as used with standalone Asio itself. Define ASIO_STANDALONE before including Asio or WebSocket++ headers. You will need to download a copy of the Asio headers separately (http://www.think-async.com) and make sure they are in your build system's include path.

Can WebSocket++ be used without TLS or OpenSSL?

Yes. When using the iostream/raw transport, there are no TLS features and OpenSSL is not required. When using the Asio transport TLS features are optional. You only need OpenSSL if you want to use TLS. You can only make or recieve encrypted connections (https/wss) if you have enabled TLS features.

Whether an Asio endpoint uses TLS or not is determined by its config template parameter. The default bundled websocketpp::config::asio and websocketpp::config::asio_client configs do not support TLS, the websocketpp::config::asio_tls and websocketpp::config::asio_tls_client do.

The <websocketpp/config/asio.hpp> and <websocketpp/config/asio_client.hpp> headers will include both the TLS and non-TLS varients of their respective configs and require the presence of OpenSSL. The <websocketpp/config/asio_no_tls.hpp> and <websocketpp/config/asio_no_tls_client.hpp> headers will include only the non-TLS configs and do not require OpenSSL.

Build issues with TLS on recent versions of OS X

Mac OS X ships a severely outdated version of the OpenSSL library. To securely use TLS with WebSocket++ on OS X you will need to install a modern version of OpenSSL via homebrew or compiling from source.

Can WebSocket++ be used with MinGW

Generally, yes. Note that in C++11 mode MinGW does not currently support the C++11 STL <thread> library. WebSocket++ requires a thread/mutex library. Options include Boost thread (the default when a compatible C++11 <thread> can't be found) or mingw-std-threads (https://github.com/meganz/mingw-std-threads) by including those headers and defining _WEBSOCKETPP_MINGW_THREAD_.

Compression

How do I use permessage-deflate in version 0.6.0-permessagedeflate and 0.7.0?

These versions of the library require a custom config to use the permessage-deflate extension. Here is a minimal example of such a custom config. You can also integrate these lines into an existing custom config.

Note that in these versions there is no fine grained control over which connections are compressed or not. Clients will request compression with the default settings and use it if the server supports it. Servers will accept whatever parameters clients request.

Outgoing messages by default will be compressed if compression was auto-negotiated during the handshake. There is an option to force a specific message to be sent uncompressed even if compression was negotiated. This may be useful for sending data that you know to be compressed already (images, zip files, etc).

Server Example

#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
struct deflate_server_config : public websocketpp::config::asio {
// ... additional custom config if you need it for other things
struct permessage_deflate_config {};
<permessage_deflate_config> permessage_deflate_type;
};
typedef websocketpp::server<deflate_server_config> server_endpoint_type;

Client Example

#include <websocketpp/extensions/permessage_deflate/enabled.hpp>
struct deflate_client_config : public websocketpp::config::asio_client {
// ... additional custom config if you need it for other things
struct permessage_deflate_config {};
<permessage_deflate_config> permessage_deflate_type;
};
typedef websocketpp::client<deflate_client_config> client_endpoint_type;

Security

Is it possible to terminate a malicious connection quickly, without tying up resources performing clean close steps,

Yes. The library will automatically detect and terminate connections that violate the WebSocket protocol. In cases where the library believes the remote endpoint to be malicious or sufficiently broken to be unlikely to understand or process the closing handshake, it will be omited.

If your application detects conditions above the protocol level that you believe to be malicious, for example, if you recognize an IP from a known denial of service attack, you can close the connection with two different levels of urgency. Use the standard websocketpp::endpoint::close or websocketpp::connection::close methods with one of the following special close codes:

Please note that usage of these disconnect methods results in a violation of the WebSocket protocol and may have negative reprocusions for the remote endpoint with respect to network timeouts. Please use caution when using them.

Build Issues

Getting compile errors related to <tt>std::chrono</tt>, <tt>boost::chrono</tt>, <tt>waitable_timer</tt>, or <tt>steady_clock</tt>

Your build system may be confused about whether it is supposed to be using boost::chrono or std::chrono. Boost automatically detects this setup on some compilers but not others. Defining BOOST_ASIO_HAS_STD_CHRONO can help. See http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/overview/cpp2011/chrono.html for more details.

websocketpp::client
Client endpoint role based on the given config.
Definition: client_endpoint.hpp:47
websocketpp::config::asio
Server config with asio transport and TLS disabled.
Definition: asio_no_tls.hpp:38
websocketpp::extensions::permessage_deflate::enabled
Definition: enabled.hpp:218
websocketpp::server
Server endpoint role based on the given config.
Definition: server_endpoint.hpp:44
websocketpp::config::asio_client
Client config with asio transport and TLS disabled.
Definition: asio_no_tls_client.hpp:38