mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Add websocket service
This commit is contained in:
@ -1,6 +1,7 @@
|
|||||||
Version 223:
|
Version 223:
|
||||||
|
|
||||||
* Add test::stream::service
|
* Add test::stream::service
|
||||||
|
* Add websocket service
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
91
include/boost/beast/websocket/detail/service.hpp
Normal file
91
include/boost/beast/websocket/detail/service.hpp
Normal 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
|
@ -43,6 +43,14 @@ namespace boost {
|
|||||||
namespace beast {
|
namespace beast {
|
||||||
namespace websocket {
|
namespace websocket {
|
||||||
|
|
||||||
|
template<class NextLayer, bool deflateSupported>
|
||||||
|
stream<NextLayer, deflateSupported>::
|
||||||
|
~stream()
|
||||||
|
{
|
||||||
|
if(impl_)
|
||||||
|
impl_->remove();
|
||||||
|
}
|
||||||
|
|
||||||
template<class NextLayer, bool deflateSupported>
|
template<class NextLayer, bool deflateSupported>
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
stream<NextLayer, deflateSupported>::
|
stream<NextLayer, deflateSupported>::
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include <boost/beast/websocket/detail/mask.hpp>
|
#include <boost/beast/websocket/detail/mask.hpp>
|
||||||
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
#include <boost/beast/websocket/detail/pmd_extension.hpp>
|
||||||
#include <boost/beast/websocket/detail/prng.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/soft_mutex.hpp>
|
||||||
#include <boost/beast/websocket/detail/utf8_checker.hpp>
|
#include <boost/beast/websocket/detail/utf8_checker.hpp>
|
||||||
#include <boost/beast/http/read.hpp>
|
#include <boost/beast/http/read.hpp>
|
||||||
@ -35,6 +36,7 @@
|
|||||||
#include <boost/asio/steady_timer.hpp>
|
#include <boost/asio/steady_timer.hpp>
|
||||||
#include <boost/core/empty_value.hpp>
|
#include <boost/core/empty_value.hpp>
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -44,13 +46,30 @@ namespace websocket {
|
|||||||
template<
|
template<
|
||||||
class NextLayer, bool deflateSupported>
|
class NextLayer, bool deflateSupported>
|
||||||
struct stream<NextLayer, deflateSupported>::impl_type
|
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>
|
, detail::impl_base<deflateSupported>
|
||||||
, boost::empty_value<NextLayer>
|
|
||||||
{
|
{
|
||||||
NextLayer& stream() noexcept
|
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
|
net::steady_timer timer; // used for timeouts
|
||||||
@ -110,6 +129,8 @@ struct stream<NextLayer, deflateSupported>::impl_type
|
|||||||
: boost::empty_value<NextLayer>(
|
: boost::empty_value<NextLayer>(
|
||||||
boost::empty_init_t{},
|
boost::empty_init_t{},
|
||||||
std::forward<Args>(args)...)
|
std::forward<Args>(args)...)
|
||||||
|
, detail::service::impl_type(
|
||||||
|
this->stream().get_executor().context())
|
||||||
, timer(this->stream().get_executor())
|
, timer(this->stream().get_executor())
|
||||||
{
|
{
|
||||||
timeout_opt.handshake_timeout = none();
|
timeout_opt.handshake_timeout = none();
|
||||||
|
@ -178,27 +178,20 @@ public:
|
|||||||
@note A stream object must not be destroyed while there
|
@note A stream object must not be destroyed while there
|
||||||
are pending asynchronous operations associated with it.
|
are pending asynchronous operations associated with it.
|
||||||
*/
|
*/
|
||||||
~stream() = default;
|
~stream();
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
If `NextLayer` is move constructible, this function
|
If `NextLayer` is move constructible, this function
|
||||||
will move-construct a new stream from the existing stream.
|
will move-construct a new stream from the existing stream.
|
||||||
|
|
||||||
@note The behavior of move assignment on or from streams
|
After the move, the only valid operation on the moved-from
|
||||||
with active or pending operations is undefined.
|
object is destruction.
|
||||||
*/
|
*/
|
||||||
stream(stream&&) = default;
|
stream(stream&&) = default;
|
||||||
|
|
||||||
/** Assignment
|
/// Move assignment (deleted)
|
||||||
|
stream& operator=(stream&&) = delete;
|
||||||
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;
|
|
||||||
|
|
||||||
/** Constructor
|
/** Constructor
|
||||||
|
|
||||||
|
@ -174,8 +174,10 @@ public:
|
|||||||
BOOST_STATIC_ASSERT(std::is_move_constructible<
|
BOOST_STATIC_ASSERT(std::is_move_constructible<
|
||||||
stream<test::stream>>::value);
|
stream<test::stream>>::value);
|
||||||
|
|
||||||
|
#if 0
|
||||||
BOOST_STATIC_ASSERT(std::is_move_assignable<
|
BOOST_STATIC_ASSERT(std::is_move_assignable<
|
||||||
stream<test::stream>>::value);
|
stream<test::stream>>::value);
|
||||||
|
#endif
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(std::is_constructible<
|
BOOST_STATIC_ASSERT(std::is_constructible<
|
||||||
stream<test::stream&>, test::stream&>::value);
|
stream<test::stream&>, test::stream&>::value);
|
||||||
@ -183,8 +185,10 @@ public:
|
|||||||
// VFALCO Should these be allowed for NextLayer references?
|
// VFALCO Should these be allowed for NextLayer references?
|
||||||
BOOST_STATIC_ASSERT(std::is_move_constructible<
|
BOOST_STATIC_ASSERT(std::is_move_constructible<
|
||||||
stream<test::stream&>>::value);
|
stream<test::stream&>>::value);
|
||||||
|
#if 0
|
||||||
BOOST_STATIC_ASSERT(std::is_move_assignable<
|
BOOST_STATIC_ASSERT(std::is_move_assignable<
|
||||||
stream<test::stream&>>::value);
|
stream<test::stream&>>::value);
|
||||||
|
#endif
|
||||||
|
|
||||||
log << "sizeof(websocket::stream) == " <<
|
log << "sizeof(websocket::stream) == " <<
|
||||||
sizeof(websocket::stream<test::stream&>) << std::endl;
|
sizeof(websocket::stream<test::stream&>) << std::endl;
|
||||||
|
Reference in New Issue
Block a user