Boost logo

Boost Users :

From: Stephan Menzel (stephan.menzel_at_[hidden])
Date: 2019-09-06 11:35:22


Hi Vinnie,

Am Di., 3. Sept. 2019 um 16:23 Uhr schrieb Vinnie Falco <
vinnie.falco_at_[hidden]>:

> On Tue, Sep 3, 2019 at 7:22 AM Stephan Menzel via Boost-users
> <boost-users_at_[hidden]> wrote:
> > I'm trying to realize an old dream in asio. A function that will take a
> socket
> > and asynchronously...connect to the result while having a timeout around
> > the operation.
>
> Like this?
>
> <
> https://www.boost.org/doc/libs/1_71_0/libs/beast/doc/html/beast/ref/boost__beast__basic_stream/async_connect/overload1.html
> >
>

Well, not exactly. I wanted to do the resolve and connect in one go. This
one has a timeout though, which already is a huge step in the right
direction. Didn't know this existed.

Anyway, your implementation did bring me to beast::bind_handler, which
eventually led me to a working implementation:
https://github.com/MrMoose/moose_tools/blob/master/TimedConnect.hpp
as it enabled me to adopt the handler to async ops with different handler
requirements.

However, since I'm here ;-) may I ask a followup in this regard:

I have had success with beast::bind_handler using it in timed_connect like
this:

    template <typename Self>
    void operator()(Self &n_self, const boost::system::error_code &n_error
= boost::system::error_code(),
            boost::asio::ip::tcp::resolver::results_type n_results =
boost::asio::ip::tcp::resolver::results_type(),
            boost::asio::ip::tcp::endpoint n_connected_ep =
boost::asio::ip::tcp::endpoint()) {

    reenter(m_coro) {
        ....
        yield boost::asio::async_connect(m_socket, n_results,
            boost::beast::bind_handler(std::forward<Self>(n_self),
boost::placeholders::_1,
                boost::asio::ip::tcp::resolver::results_type(),
boost::placeholders::_2));
        ....
    }}

Now, this is great as it was key to have placeholders and therefore combine
async ops with incompatible handler types. However, I tried to adopt the
exact same thing in my next operation, which shall wrap up a socks4
handshake. Like this

      template <typename Self>
      void operator()(Self &n_self, boost::system::error_code n_error =
boost::system::error_code(),
          std::size_t = 0,
          boost::asio::ip::tcp::resolver::results_type n_results =
boost::asio::ip::tcp::resolver::results_type()) {

     reenter(m_coro) {
        ....
        yield m_resolver.async_resolve(tcp::v4(), *m_target_hostname,
*m_target_servicename,
                tcp::resolver::query::numeric_service,
                boost::beast::bind_handler(std::move(n_self),
boost::placeholders::_1, 0, boost::placeholders::_2));
        ....
    }}

and in this context, it fails. I have tried many different variations and
all I'm getting is crashes in the async_resolve operation that look like
moving the handler fails at runtime. Or strange errors at runtime when the
op returns with 995, which I suppose means a similar thing, e.g. m_resolver
being destroyed

Strangely it doesn't seem to matter which op I use the bind_handler with.
There is a reolve, a write and a read. Each one will fail weirdly at
runtime when I use the bind_handler to adapt the handler type. Of course, I
change the signature for operator() for those trials.

I strongly suspect it's got something to do with the moving that fails but
there's no difference between this object and the one I use in TimedConnect
which works great. Here's the data members:

    boost::asio::ip::tcp::socket &m_socket;
    boost::asio::ip::tcp::resolver m_resolver;
    std::unique_ptr<std::string> m_target_hostname;
    boost::uint16_t m_target_port;
    boost::asio::coroutine m_coro;

Nothing that can't be moved....

Anyway, maybe change move errors when using bind_handler rings a bell.

Thanks for your suggestions,
Stephan



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net