Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions include/boost/beast2/impl/read.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2025 Mohammad Nejati
//
// 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)
Expand Down Expand Up @@ -62,7 +63,15 @@ class read_until_op
{
pr_.parse(ec);
if(ec == http_proto::condition::need_more_input)
{
// specific to http_io::async_read_some
if(total_bytes_ != 0 && condition_(pr_))
{
ec = {};
goto upcall;
}
break;
}
if(ec.failed() || condition_(pr_))
{
if(total_bytes_ == 0)
Expand Down
1 change: 1 addition & 0 deletions include/boost/beast2/read.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2025 Mohammad Nejati
//
// 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)
Expand Down
40 changes: 40 additions & 0 deletions include/boost/beast2/test/detail/service_base.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// 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/cppaliance/beast2
//

#ifndef BOOST_BEAST2_TEST_DETAIL_SERVICE_BASE_HPP
#define BOOST_BEAST2_TEST_DETAIL_SERVICE_BASE_HPP

#include <boost/asio/execution_context.hpp>

namespace boost {
namespace beast2 {
namespace test {
namespace detail {

template<class T>
struct service_base : asio::execution_context::service
{
static asio::execution_context::id const id;

explicit
service_base(asio::execution_context& ctx)
: asio::execution_context::service(ctx)
{
}
};

template<class T>
asio::execution_context::id const service_base<T>::id;

} // detail
} // test
} // beast2
} // boost

#endif
260 changes: 260 additions & 0 deletions include/boost/beast2/test/detail/stream_state.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,260 @@
//
// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2020 Richard Hodges ([email protected])
//
// 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/cppaliance/beast2
//

#ifndef BOOST_BEAST2_TEST_DETAIL_STREAM_STATE_HPP
#define BOOST_BEAST2_TEST_DETAIL_STREAM_STATE_HPP

#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/error.hpp>
#include <boost/buffers/string_buffer.hpp>
#include <boost/beast2/detail/config.hpp>
#include <boost/beast2/test/detail/service_base.hpp>
#include <boost/beast2/test/error.hpp>
#include <boost/beast2/test/fail_count.hpp>
#include <boost/make_shared.hpp>
#include <boost/smart_ptr/weak_ptr.hpp>

#include <condition_variable>
#include <memory>
#include <mutex>
#include <vector>

namespace boost {
namespace beast2 {
namespace test {
namespace detail {

struct stream_state;

struct stream_service_impl
{
std::mutex m_;
std::vector<stream_state*> v_;

void
remove(stream_state& impl);
};

//------------------------------------------------------------------------------

class stream_service
: public beast2::test::detail::service_base<stream_service>
{
boost::shared_ptr<detail::stream_service_impl> sp_;

void
shutdown() override;

public:
explicit
stream_service(asio::execution_context& ctx);

static
auto
make_impl(
asio::any_io_executor exec,
test::fail_count* fc) ->
boost::shared_ptr<detail::stream_state>;
};

//------------------------------------------------------------------------------

struct stream_read_op_base
{
virtual ~stream_read_op_base() = default;
virtual void operator()(system::error_code ec) = 0;
};

//------------------------------------------------------------------------------

enum class stream_status
{
ok,
eof,
};

//------------------------------------------------------------------------------

struct stream_state
{
asio::any_io_executor exec;
boost::weak_ptr<stream_service_impl> wp;
std::mutex m;
std::string storage;
buffers::string_buffer b;
std::condition_variable cv;
std::unique_ptr<stream_read_op_base> op;
stream_status code = stream_status::ok;
fail_count* fc = nullptr;
std::size_t nread = 0;
std::size_t nread_bytes = 0;
std::size_t nwrite = 0;
std::size_t nwrite_bytes = 0;
std::size_t read_max =
(std::numeric_limits<std::size_t>::max)();
std::size_t write_max =
(std::numeric_limits<std::size_t>::max)();

stream_state(
asio::any_io_executor exec_,
boost::weak_ptr<stream_service_impl> wp_,
fail_count* fc_);

stream_state(stream_state&&) = delete;

~stream_state();

void
remove() noexcept;

void
notify_read();

void
cancel_read();
};

//------------------------------------------------------------------------------

inline
stream_service::
stream_service(asio::execution_context& ctx)
: beast2::test::detail::service_base<stream_service>(ctx)
, sp_(boost::make_shared<stream_service_impl>())
{
}

inline
void
stream_service::
shutdown()
{
std::vector<std::unique_ptr<detail::stream_read_op_base>> v;
std::lock_guard<std::mutex> g1(sp_->m_);
v.reserve(sp_->v_.size());
for(auto p : sp_->v_)
{
std::lock_guard<std::mutex> g2(p->m);
v.emplace_back(std::move(p->op));
p->code = detail::stream_status::eof;
}
}

inline
auto
stream_service::
make_impl(
asio::any_io_executor exec,
test::fail_count* fc) ->
boost::shared_ptr<detail::stream_state>
{
#if defined(BOOST_ASIO_USE_TS_EXECUTOR_AS_DEFAULT)
auto& ctx = exec.context();
#else
auto& ctx = asio::query(
exec,
asio::execution::context);
#endif
auto& svc = asio::use_service<stream_service>(ctx);
auto sp = boost::make_shared<detail::stream_state>(exec, svc.sp_, fc);
std::lock_guard<std::mutex> g(svc.sp_->m_);
svc.sp_->v_.push_back(sp.get());
return sp;
}

//------------------------------------------------------------------------------

inline
void
stream_service_impl::
remove(stream_state& impl)
{
std::lock_guard<std::mutex> g(m_);
*std::find(
v_.begin(), v_.end(),
&impl) = std::move(v_.back());
v_.pop_back();
}

//------------------------------------------------------------------------------

inline
stream_state::
stream_state(
asio::any_io_executor exec_,
boost::weak_ptr<stream_service_impl> wp_,
fail_count* fc_)
: exec(std::move(exec_))
, wp(std::move(wp_))
, b(&storage)
, fc(fc_)
{
}

inline
stream_state::
~stream_state()
{
// cancel outstanding read
if(op != nullptr)
(*op)(asio::error::operation_aborted);
}

inline
void
stream_state::
remove() noexcept
{
auto sp = wp.lock();

// If this goes off, it means the lifetime of a test::stream object
// extended beyond the lifetime of the associated execution context.
BOOST_ASSERT(sp);

sp->remove(*this);
}

inline
void
stream_state::
notify_read()
{
if(op)
{
auto op_ = std::move(op);
op_->operator()(system::error_code{});
}
else
{
cv.notify_all();
}
}

inline
void
stream_state::
cancel_read()
{
std::unique_ptr<stream_read_op_base> p;
{
std::lock_guard<std::mutex> lock(m);
code = stream_status::eof;
p = std::move(op);
}
if(p != nullptr)
(*p)(asio::error::operation_aborted);
}

} // detail
} // test
} // beast2
} // boost

#endif
34 changes: 34 additions & 0 deletions include/boost/beast2/test/error.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//
// 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/cppaliance/beast2
//

#ifndef BOOST_BEAST2_TEST_ERROR_HPP
#define BOOST_BEAST2_TEST_ERROR_HPP

namespace boost {
namespace beast2 {
namespace test {

/// Error codes returned from unit testing algorithms
enum class error
{
/** The test stream generated a simulated testing error

This error is returned by a @ref fail_count object
when it generates a simulated error.
*/
test_failure = 1
};

} // test
} // beast2
} // boost

#include <boost/beast2/test/impl/error.hpp>

#endif
Loading
Loading