Add websocket service

This commit is contained in:
Vinnie Falco
2019-02-27 15:02:00 -08:00
parent 05b5843e19
commit 031e13c253
6 changed files with 133 additions and 15 deletions

View File

@ -1,6 +1,7 @@
Version 223:
* Add test::stream::service
* Add websocket service
--------------------------------------------------------------------------------

View File

@ -0,0 +1,91 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
// Official repository: https://github.com/boostorg/beast
//
#ifndef BOOST_BEAST_WEBSOCKET_DETAIL_SERVICE_HPP
#define BOOST_BEAST_WEBSOCKET_DETAIL_SERVICE_HPP
#include <boost/beast/core/detail/service_base.hpp>
#include <boost/asio/execution_context.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <mutex>
#include <vector>
namespace boost {
namespace beast {
namespace websocket {
namespace detail {
class service
: public beast::detail::service_base<service>
{
public:
class impl_type
: public boost::enable_shared_from_this<impl_type>
{
service& svc_;
std::size_t index_;
friend class service;
public:
virtual ~impl_type() = default;
explicit
impl_type(net::execution_context& ctx)
: svc_(net::use_service<service>(ctx))
{
std::lock_guard<std::mutex> g(svc_.m_);
index_ = svc_.v_.size();
svc_.v_.push_back(this);
}
BOOST_BEAST_DECL
void
remove()
{
std::lock_guard<std::mutex> g(svc_.m_);
auto& other = *svc_.v_.back();
other.index_ = index_;
svc_.v_[index_] = &other;
svc_.v_.pop_back();
}
};
private:
std::mutex m_;
std::vector<impl_type*> v_;
BOOST_BEAST_DECL
void
shutdown() override
{
std::vector<boost::weak_ptr<impl_type>> v;
{
std::lock_guard<std::mutex> g(m_);
v.reserve(v_.size());
for(auto p : v_)
v.emplace_back(p->weak_from_this());
}
}
public:
BOOST_BEAST_DECL
explicit
service(net::execution_context& ctx)
: beast::detail::service_base<service>(ctx)
{
}
};
} // detail
} // websocket
} // beast
} // boost
#endif

View File

@ -43,6 +43,14 @@ namespace boost {
namespace beast {
namespace websocket {
template<class NextLayer, bool deflateSupported>
stream<NextLayer, deflateSupported>::
~stream()
{
if(impl_)
impl_->remove();
}
template<class NextLayer, bool deflateSupported>
template<class... Args>
stream<NextLayer, deflateSupported>::

View File

@ -16,6 +16,7 @@
#include <boost/beast/websocket/detail/mask.hpp>
#include <boost/beast/websocket/detail/pmd_extension.hpp>
#include <boost/beast/websocket/detail/prng.hpp>
#include <boost/beast/websocket/detail/service.hpp>
#include <boost/beast/websocket/detail/soft_mutex.hpp>
#include <boost/beast/websocket/detail/utf8_checker.hpp>
#include <boost/beast/http/read.hpp>
@ -35,6 +36,7 @@
#include <boost/asio/steady_timer.hpp>
#include <boost/core/empty_value.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/optional.hpp>
namespace boost {
@ -44,13 +46,30 @@ namespace websocket {
template<
class NextLayer, bool deflateSupported>
struct stream<NextLayer, deflateSupported>::impl_type
: boost::enable_shared_from_this<impl_type>
: boost::empty_value<NextLayer>
, detail::service::impl_type
, detail::impl_base<deflateSupported>
, boost::empty_value<NextLayer>
{
NextLayer& stream() noexcept
{
return this->boost::empty_value<NextLayer>::get();
return this->boost::empty_value<
NextLayer>::get();
}
boost::weak_ptr<impl_type>
weak_from_this()
{
return boost::static_pointer_cast<
impl_type>(this->detail::service::
impl_type::shared_from_this());
}
boost::shared_ptr<impl_type>
shared_this()
{
return boost::static_pointer_cast<
impl_type>(this->detail::service::
impl_type::shared_from_this());
}
net::steady_timer timer; // used for timeouts
@ -110,6 +129,8 @@ struct stream<NextLayer, deflateSupported>::impl_type
: boost::empty_value<NextLayer>(
boost::empty_init_t{},
std::forward<Args>(args)...)
, detail::service::impl_type(
this->stream().get_executor().context())
, timer(this->stream().get_executor())
{
timeout_opt.handshake_timeout = none();

View File

@ -178,27 +178,20 @@ public:
@note A stream object must not be destroyed while there
are pending asynchronous operations associated with it.
*/
~stream() = default;
~stream();
/** Constructor
If `NextLayer` is move constructible, this function
will move-construct a new stream from the existing stream.
@note The behavior of move assignment on or from streams
with active or pending operations is undefined.
After the move, the only valid operation on the moved-from
object is destruction.
*/
stream(stream&&) = default;
/** Assignment
If `NextLayer` is move assignable, this function
will move-assign a new stream from the existing stream.
@note The behavior of move assignment on or from streams
with active or pending operations is undefined.
*/
stream& operator=(stream&&) = default;
/// Move assignment (deleted)
stream& operator=(stream&&) = delete;
/** Constructor

View File

@ -174,8 +174,10 @@ public:
BOOST_STATIC_ASSERT(std::is_move_constructible<
stream<test::stream>>::value);
#if 0
BOOST_STATIC_ASSERT(std::is_move_assignable<
stream<test::stream>>::value);
#endif
BOOST_STATIC_ASSERT(std::is_constructible<
stream<test::stream&>, test::stream&>::value);
@ -183,8 +185,10 @@ public:
// VFALCO Should these be allowed for NextLayer references?
BOOST_STATIC_ASSERT(std::is_move_constructible<
stream<test::stream&>>::value);
#if 0
BOOST_STATIC_ASSERT(std::is_move_assignable<
stream<test::stream&>>::value);
#endif
log << "sizeof(websocket::stream) == " <<
sizeof(websocket::stream<test::stream&>) << std::endl;