0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-12-30 17:34:04 +01:00

ircd::net: Fix bug where received data is stuck in SSL buffer.

This commit is contained in:
Jason Volk 2018-01-13 17:53:59 -08:00
parent fa3afc7ad7
commit f71a728225

View file

@ -1389,6 +1389,37 @@ ircd::net::socket::wait(const wait_opts &opts,
});
}
/// Asynchronous callback when the socket is ready
///
/// Overload for operator() without a timeout. see: operator()
///
void
ircd::net::socket::wait(const wait_opts &opts)
{
const scope_timeout timeout
{
*this, opts.timeout
};
switch(opts.type)
{
case ready::ERROR:
sd.async_wait(wait_type::wait_error, yield_context{to_asio{}});
break;
case ready::WRITE:
sd.async_wait(wait_type::wait_write, yield_context{to_asio{}});
break;
case ready::READ:
sd.async_wait(wait_type::wait_read, yield_context{to_asio{}});
break;
default:
throw ircd::not_implemented{};
}
}
/// Asynchronous callback when the socket is ready
///
/// This function calls back the handler when the socket is ready
@ -1421,13 +1452,26 @@ ircd::net::socket::wait(const wait_opts &opts,
case ready::READ:
{
static char buf[1] alignas(16);
static const ilist<mutable_buffer> bufs{buf};
__builtin_prefetch(buf, 1, 0); // 1 = write, 0 = no cache
// The problem here is that waiting on the sd doesn't account for bytes
// read into SSL that we didn't consume yet. If something is stuck in
// those userspace buffers, the socket won't know about it and perform
// the wait. ASIO should fix this by adding a ssl::stream.wait() method
// which will bail out immediately in this case before passing up to the
// real socket wait.
if(SSL_peek(ssl.native_handle(), buf, sizeof(buf)) > 0)
{
handle(error_code{});
break;
}
// The problem here is that the wait operation gives ec=success on both a
// socket error and when data is actually available. We then have to check
// using a non-blocking peek in the handler. By doing it this way here we
// just get the error in the handler's ec.
static char buf[16] alignas(16);
static const ilist<mutable_buffer> bufs{buf};
__builtin_prefetch(buf, 1, 0); // 1 = write, 0 = no cache
sd.async_receive(bufs, sd.message_peek, std::move(handle));
//sd.async_wait(wait_type::wait_read, std::move(handle));
break;
@ -1438,36 +1482,6 @@ ircd::net::socket::wait(const wait_opts &opts,
}
}
/// Asynchronous callback when the socket is ready
///
/// Overload for operator() without a timeout. see: operator()
///
void
ircd::net::socket::wait(const wait_opts &opts)
{
const scope_timeout timeout
{
*this, opts.timeout
};
switch(opts.type)
{
case ready::ERROR:
sd.async_wait(wait_type::wait_error, yield_context{to_asio{}});
break;
case ready::WRITE:
sd.async_wait(wait_type::wait_write, yield_context{to_asio{}});
break;
case ready::READ:
sd.async_wait(wait_type::wait_read, yield_context{to_asio{}});
default:
throw ircd::not_implemented{};
}
}
void
ircd::net::socket::handle_ready(const std::weak_ptr<socket> wp,
const net::ready type,