diff --git a/include/libtorrent/aux_/utp_stream.hpp b/include/libtorrent/aux_/utp_stream.hpp index 894587b29db..a54992b469e 100644 --- a/include/libtorrent/aux_/utp_stream.hpp +++ b/include/libtorrent/aux_/utp_stream.hpp @@ -252,6 +252,7 @@ struct TORRENT_EXTRA_EXPORT utp_stream void add_read_buffer(void* buf, int len); void issue_read(); void add_write_buffer(void const* buf, int len); + bool check_fin_sent() const; void issue_write(); std::size_t read_some(bool clear_buffers); std::size_t write_some(bool clear_buffers); @@ -379,6 +380,13 @@ struct TORRENT_EXTRA_EXPORT utp_stream return 0; } + if (check_fin_sent()) + { + // we can't send more data after closing the socket + ec = boost::asio::error::broken_pipe; + return 0; + } + #if TORRENT_USE_ASSERTS size_t buf_size = 0; #endif @@ -441,6 +449,14 @@ struct TORRENT_EXTRA_EXPORT utp_stream return; } + if (check_fin_sent()) + { + // we can't send more data after closing the socket + post(m_io_service, std::bind(std::move(handler) + , boost::asio::error::broken_pipe, std::size_t(0))); + return; + } + std::size_t bytes_added = 0; for (auto i = buffer_sequence_begin(buffers) , end(buffer_sequence_end(buffers)); i != end; ++i) @@ -635,6 +651,8 @@ struct utp_socket_impl void issue_read(); void issue_write(); + bool check_fin_sent() const; + void do_connect(tcp::endpoint const& ep); std::size_t read_some(bool const clear_buffers); diff --git a/src/utp_stream.cpp b/src/utp_stream.cpp index c9ebe357a56..e2e07e6a5e4 100644 --- a/src/utp_stream.cpp +++ b/src/utp_stream.cpp @@ -474,6 +474,12 @@ void utp_stream::add_write_buffer(void const* buf, int const len) m_impl->add_write_buffer(buf, len); } +bool utp_stream::check_fin_sent() const +{ + TORRENT_ASSERT(m_impl); + return m_impl->check_fin_sent(); +} + // this is called when all user provided read buffers have been added // and it's time to execute the async operation. The first thing we // do is to copy any data stored in m_receive_buffer into the user @@ -684,6 +690,11 @@ void utp_socket_impl::issue_write() maybe_trigger_send_callback(); } +bool utp_socket_impl::check_fin_sent() const +{ + return state() == state_t::fin_sent; +} + std::size_t utp_socket_impl::write_some(bool const clear_buffers) { m_written = 0; @@ -1394,6 +1405,10 @@ bool utp_socket_impl::send_pkt(int const flags) + (sack ? sack + 2 : 0) + (close_reason ? 6 : 0); + // once we're in fin-sent mode, the write buffer should not be re-filled + // although, we may re-send packets, but those live in m_outbuf + TORRENT_ASSERT(state() != state_t::fin_sent || m_write_buffer_size == 0); + int payload_size = std::min(m_write_buffer_size , effective_mtu - header_size); TORRENT_ASSERT(payload_size >= 0);