Skip to content

Commit

Permalink
Major refactor to support standalone Asio and remove Boost dependencies
Browse files Browse the repository at this point in the history
It is now possible to use WebSocket++’s asio transport using only
standalone asio by defining ASIO_STANDALONE before including any
WebSocket++ headers.
  • Loading branch information
Peter Thorson committed Apr 25, 2015
1 parent d670d69 commit 769fe89
Show file tree
Hide file tree
Showing 19 changed files with 370 additions and 195 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ project (websocketpp)
cmake_minimum_required (VERSION 2.6)

set (WEBSOCKETPP_MAJOR_VERSION 0)
set (WEBSOCKETPP_MINOR_VERSION 5)
set (WEBSOCKETPP_MINOR_VERSION 6)
set (WEBSOCKETPP_PATCH_VERSION 0)
set (WEBSOCKETPP_VERSION ${WEBSOCKETPP_MAJOR_VERSION}.${WEBSOCKETPP_MINOR_VERSION}.${WEBSOCKETPP_PATCH_VERSION})

Expand Down
2 changes: 1 addition & 1 deletion Doxyfile
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ PROJECT_NAME = "websocketpp"
# if some version control system is used.


PROJECT_NUMBER = "0.5.x-dev"
PROJECT_NUMBER = "0.6.x-dev"


# Using the PROJECT_BRIEF tag one can provide an optional one line description
Expand Down
26 changes: 23 additions & 3 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,37 @@ HEAD
- BREAKING TRANSPORT POLICY CHANGE: Custom transport policies will now be
required to include a new method `void set_uri(uri_ptr u)`. An implementation
is not required. The stub transport policy includes an example stub method
that can be pasted into any existing custom transport policy to fulfill this
that can be added to any existing custom transport policy to fulfill this
requirement. This does not affect anyone using the bundled transports or
configs.
- BREAKING SOCKET POLICY CHANGE: Custom asio transport socket policies will now
be required to include a new method `void set_uri(uri_ptr u)`. Like with the
transport layer, an implementation is not required. This does not affect
anyone using the bundled socket policies.
- Improvement: Outgoing TLS connections to servers using the SNI extension to
choose a certificate will now work.
- Feature: WebSocket++ Asio transport policy can now be used with the standalone
version of Asio (1.8.0+) when a C++11 compiler and standard library are
present. This means that it is possible now to use WebSocket++'s Asio
transport entirely without Boost.
- Feature: Adds a vectored/scatter-gather write handler to the iostream
transport.
- Improvement: `endpoint::set_timer` now uses a steady clock provided by
`boost::chrono` or `std::chrono` where available instead of the non-monotonic
system clock. Thank you breyed for reporting. fixes #241
- Improvement: Outgoing TLS connections to servers using the SNI extension to
choose a certificate will now work.
- Cleanup: Asio transport policy has been refactored to remove many Boost
dependencies. On C++03 compilers the `boost::noncopyable` dependency has been
removed and the `boost::date_time` dependency has been replaced with the newer
`boost::chrono` when possible. On C++11 compilers the `boost::aligned_storage`
and `boost::date_time` dependencies are gone, replaced with equivalent C++11
standard library features.

0.5.1 - 2015-02-27
- Bug: Fixes an issue where some frame data was counted against the max header
size limit, resulting in connections that included a lot of frame data
immediately after the opening handshake to fail.
- Bug: Fix a typo in the name of the set method for `max_http_body_size`. #406
Thank you jplatte for reporting.

0.5.0 - 2015-01-22
- BREAKING UTILITY CHANGE: Deprecated methods `http::parser::parse_headers`,
Expand Down
6 changes: 3 additions & 3 deletions examples/telemetry_client/telemetry_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@ class telemetry_client {
// Bind the handlers we are using
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::bind;
m_client.set_open_handler(bind(&telemetry_client::on_open,this,::_1));
m_client.set_close_handler(bind(&telemetry_client::on_close,this,::_1));
m_client.set_fail_handler(bind(&telemetry_client::on_fail,this,::_1));
m_client.set_open_handler(bind(&telemetry_client::on_open,this,_1));
m_client.set_close_handler(bind(&telemetry_client::on_close,this,_1));
m_client.set_fail_handler(bind(&telemetry_client::on_fail,this,_1));
}

// This method will block until the connection is complete
Expand Down
6 changes: 3 additions & 3 deletions examples/telemetry_server/telemetry_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class telemetry_server {
// Bind the handlers we are using
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::bind;
m_endpoint.set_open_handler(bind(&telemetry_server::on_open,this,::_1));
m_endpoint.set_close_handler(bind(&telemetry_server::on_close,this,::_1));
m_endpoint.set_http_handler(bind(&telemetry_server::on_http,this,::_1));
m_endpoint.set_open_handler(bind(&telemetry_server::on_open,this,_1));
m_endpoint.set_close_handler(bind(&telemetry_server::on_close,this,_1));
m_endpoint.set_http_handler(bind(&telemetry_server::on_http,this,_1));
}

void run(std::string docroot, uint16_t port) {
Expand Down
8 changes: 5 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
WebSocket++ (0.5.x-dev)
WebSocket++ (0.6.x-dev)
==========================

WebSocket++ is a header only C++ library that implements RFC6455 The WebSocket
Protocol. It allows integrating WebSocket client and server functionality into
C++ programs. It uses interchangeable network transport modules including one
based on C++ iostreams and one based on Boost Asio.
based on raw char buffers, one based on C++ iostreams, and one based on Asio
(either via Boost or standalone). End users can write additional transport
policies to support other networking or event libraries as needed.

Major Features
==============
Expand All @@ -13,7 +15,7 @@ Major Features
* Message/event based interface
* Supports secure WebSockets (TLS), IPv6, and explicit proxies.
* Flexible dependency management (C++11 Standard Library or Boost)
* Interchangeable network transport modules (iostream and Boost Asio)
* Interchangeable network transport modules (raw, iostream, Asio, or custom)
* Portable/cross platform (Posix/Windows, 32/64bit, Intel/ARM/PPC)
* Thread-safe

Expand Down
2 changes: 1 addition & 1 deletion test/transport/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Import('tls_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()

BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','random'],env) + [platform_libs] + [tls_libs]
BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','random','chrono'],env) + [platform_libs] + [tls_libs]

objs = env.Object('boost_integration.o', ["integration.cpp"], LIBS = BOOST_LIBS)
prgs = env.Program('test_boost_integration', ["boost_integration.o"], LIBS = BOOST_LIBS)
Expand Down
2 changes: 1 addition & 1 deletion test/transport/asio/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Import('tls_libs')
env = env.Clone ()
env_cpp11 = env_cpp11.Clone ()

BOOST_LIBS = boostlibs(['unit_test_framework','system','thread'],env) + [platform_libs] + [tls_libs]
BOOST_LIBS = boostlibs(['unit_test_framework','system','thread','chrono'],env) + [platform_libs] + [tls_libs]

objs = env.Object('base_boost.o', ["base.cpp"], LIBS = BOOST_LIBS)
objs += env.Object('timers_boost.o', ["timers.cpp"], LIBS = BOOST_LIBS)
Expand Down
130 changes: 130 additions & 0 deletions websocketpp/common/asio.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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.
*
*/

#ifndef WEBSOCKETPP_COMMON_ASIO_HPP
#define WEBSOCKETPP_COMMON_ASIO_HPP

// This file goes to some length to preserve compatibility with versions of
// boost older than 1.49 (where the first modern steady_timer timer based on
// boost/std chrono was introduced.
//
// For the versions older than 1.49, the deadline_timer is used instead. this
// brings in dependencies on boost date_time and it has a different interface
// that is normalized by the `lib::asio::is_neg` and `lib::asio::milliseconds`
// wrappers provided by this file.
//
// The primary reason for this continued support is that boost 1.48 is the
// default and not easily changeable version of boost supplied by the package
// manager of popular Linux distributions like Ubuntu 12.04 LTS. Once the need
// for this has passed this should be cleaned up and simplified.

#ifdef ASIO_STANDALONE
#include <asio/version.hpp>

#if (ASIO_VERSION/100000) == 1 && ((ASIO_VERSION/100)%1000) < 8
static_assert(false, "The minimum version of standalone Asio is 1.8.0");
#endif

#include <asio.hpp>
#include <asio/steady_timer.hpp>
#include <websocketpp/common/chrono.hpp>
#else
#include <boost/asio.hpp>

// See note above about boost <1.49 compatibility. If we are running on
// boost > 1.48 pull in the steady timer and chrono library
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48
#include <boost/asio/steady_timer.hpp>
#include <websocketpp/common/chrono.hpp>
#endif

#include <boost/system/error_code.hpp>
#endif

namespace websocketpp {
namespace lib {

#ifdef ASIO_STANDALONE
namespace asio {
using namespace ::asio;
// Here we assume that we will be using std::error_code with standalone
// Asio. This is probably a good assumption, but it is possible in rare
// cases that local Asio versions would be used.
using std::errc;

// See note above about boost <1.49 compatibility. Because we require
// a standalone Asio version of 1.8+ we are guaranteed to have
// steady_timer available. By convention we require the chrono library
// (either boost or std) for use with standalone Asio.
template <typename T>
bool is_neg(T duration) {
return duration.count() < 0;
}
inline lib::chrono::milliseconds milliseconds(long duration) {
return lib::chrono::milliseconds(duration);
}
} // namespace asio

#else
namespace asio {
using namespace boost::asio;

// See note above about boost <1.49 compatibility
#if (BOOST_VERSION/100000) == 1 && ((BOOST_VERSION/100)%1000) > 48
// Using boost::asio >=1.49 so we use chrono and steady_timer
template <typename T>
bool is_neg(T duration) {
return duration.count() < 0;
}
inline lib::chrono::milliseconds milliseconds(long duration) {
return lib::chrono::milliseconds(duration);
}
#else
// Using boost::asio <1.49 we pretend a deadline timer is a steady
// timer and wrap the negative detection and duration conversion
// appropriately.
typedef boost::asio::deadline_timer steady_timer;

template <typename T>
bool is_neg(T duration) {
return duration.is_negative();
}
inline boost::posix_time::time_duration milliseconds(long duration) {
return boost::posix_time::milliseconds(duration);
}
#endif

using boost::system::error_code;
namespace errc = boost::system::errc;
} // namespace asio
#endif


} // namespace lib
} // namespace websocketpp

#endif // WEBSOCKETPP_COMMON_ASIO_HPP
37 changes: 37 additions & 0 deletions websocketpp/common/asio_ssl.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/*
* 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.
*
*/

#ifndef WEBSOCKETPP_COMMON_ASIO_SSL_HPP
#define WEBSOCKETPP_COMMON_ASIO_SSL_HPP

#ifdef ASIO_STANDALONE
#include <asio/asio/ssl.hpp>
#else
#include <boost/asio/ssl.hpp>
#endif

#endif // WEBSOCKETPP_COMMON_ASIO_SSL_HPP
4 changes: 2 additions & 2 deletions websocketpp/common/chrono.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ namespace websocketpp {
namespace lib {

#ifdef _WEBSOCKETPP_CPP11_CHRONO_
using std::chrono::system_clock;
namespace chrono = std::chrono;
#else
using boost::chrono::system_clock;
namespace chrono = boost::chrono;
#endif

} // namespace lib
Expand Down
2 changes: 2 additions & 0 deletions websocketpp/common/system_error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,15 @@ namespace websocketpp {
namespace lib {

#ifdef _WEBSOCKETPP_CPP11_SYSTEM_ERROR_
using std::errc;
using std::error_code;
using std::error_category;
using std::error_condition;
using std::system_error;
#define _WEBSOCKETPP_ERROR_CODE_ENUM_NS_START_ namespace std {
#define _WEBSOCKETPP_ERROR_CODE_ENUM_NS_END_ }
#else
namespace errc = boost::system::errc;
using boost::system::error_code;
using boost::system::error_category;
using boost::system::error_condition;
Expand Down
17 changes: 7 additions & 10 deletions websocketpp/transport/asio/base.hpp
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -28,26 +28,23 @@
#ifndef WEBSOCKETPP_TRANSPORT_ASIO_BASE_HPP
#define WEBSOCKETPP_TRANSPORT_ASIO_BASE_HPP

#include <websocketpp/common/asio.hpp>
#include <websocketpp/common/cpp11.hpp>
#include <websocketpp/common/functional.hpp>
#include <websocketpp/common/system_error.hpp>
#include <websocketpp/common/type_traits.hpp>

#include <boost/system/error_code.hpp>

#include <string>

namespace websocketpp {
namespace transport {
/// Transport policy that uses boost::asio
/// Transport policy that uses asio
/**
* This policy uses a single boost::asio io_service to provide transport
* This policy uses a single asio io_service to provide transport
* services to a WebSocket++ endpoint.
*/
namespace asio {

//

// Class to manage the memory to be used for handler-based custom allocation.
// It contains a single block of memory which may be returned for allocation
// requests. If the memory is in use when an allocation request is made, the
Expand Down Expand Up @@ -145,13 +142,13 @@ inline custom_alloc_handler<Handler> make_custom_alloc_handler(
template <typename config>
class endpoint;

typedef lib::function<void(boost::system::error_code const &)>
typedef lib::function<void(lib::asio::error_code const &)>
socket_shutdown_handler;

typedef lib::function<void (boost::system::error_code const & ec,
typedef lib::function<void (lib::asio::error_code const & ec,
size_t bytes_transferred)> async_read_handler;

typedef lib::function<void (boost::system::error_code const & ec,
typedef lib::function<void (lib::asio::error_code const & ec,
size_t bytes_transferred)> async_write_handler;

typedef lib::function<void (lib::error_code const & ec)> pre_init_handler;
Expand Down
Loading

0 comments on commit 769fe89

Please sign in to comment.