diff --git a/include/simulator/simulator.hpp b/include/simulator/simulator.hpp index 8e02fa7..f789ab2 100644 --- a/include/simulator/simulator.hpp +++ b/include/simulator/simulator.hpp @@ -208,6 +208,10 @@ namespace sim wait_read, wait_write, wait_error }; + // alias matching the name used by boost.asio's basic_socket::wait_type, + // for code that's written against both APIs + using wait_type = wait_type_t; + // io_control using reuse_address = boost::asio::socket_base::reuse_address; using executor_type = io_executor; @@ -767,7 +771,7 @@ namespace sim if (w == socket_base::wait_type_t::wait_write) { abort_send_handlers(); - assert(false && "not supported yet"); + async_wait_write_impl(std::move(handler)); } else if (w == socket_base::wait_type_t::wait_read) { @@ -841,6 +845,8 @@ namespace sim , aux::function handler); void async_wait_read_impl( aux::function handler); + void async_wait_write_impl( + aux::function handler); std::size_t write_some_impl(std::vector const& bufs , boost::system::error_code& ec); std::size_t read_some_impl(std::vector const& bufs diff --git a/src/tcp_socket.cpp b/src/tcp_socket.cpp index 918efc8..173de68 100644 --- a/src/tcp_socket.cpp +++ b/src/tcp_socket.cpp @@ -709,6 +709,37 @@ namespace ip { m_recv_null_buffers = true; } + void tcp::socket::async_wait_write_impl( + aux::function handler) + { + if (!m_open) + { + boost::system::error_code const ec(error::bad_descriptor); + post(m_io_service, aux::make_malloc(std::bind(std::move(handler), ec))); + return; + } + + if (!m_channel) + { + boost::system::error_code const ec(error::not_connected); + post(m_io_service, aux::make_malloc(std::bind(std::move(handler), ec))); + return; + } + + if (!m_connect_handler && m_bytes_in_flight + m_mss <= m_cwnd) + { + // the socket is writable right now. complete immediately without + // actually writing anything, this is the null_buffers equivalent + // for writes + boost::system::error_code const ec; + post(m_io_service, aux::make_malloc(std::bind(std::move(handler), ec))); + return; + } + + m_wait_send_handler = std::move(handler); + m_send_null_buffers = true; + } + // if there is an outstanding read operation, and this was the first incoming // operation since we last drained, wake up the reader void tcp::socket::maybe_wakeup_reader() @@ -731,12 +762,11 @@ namespace ip { void tcp::socket::maybe_wakeup_writer() { - if (!m_send_handler) return; + if (!m_send_handler && !m_wait_send_handler) return; if (m_send_null_buffers) { - assert(false && "not supported yet"); -// async_wait_write_impl(m_recv_handler); + async_wait_write_impl(std::move(m_wait_send_handler)); } else {