mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 04:47:29 +02:00
Add websocket service
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
Version 223:
|
||||
|
||||
* 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 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>::
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
Reference in New Issue
Block a user