Skip to content

Commit

Permalink
prevent sending data on a uTP socket after closing it
Browse files Browse the repository at this point in the history
  • Loading branch information
arvidn committed Oct 21, 2022
1 parent 247b9f8 commit 40a2f6f
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 0 deletions.
18 changes: 18 additions & 0 deletions include/libtorrent/aux_/utp_stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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<void>(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)
Expand Down Expand Up @@ -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);
Expand Down
15 changes: 15 additions & 0 deletions src/utp_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 40a2f6f

Please sign in to comment.