add invariant check to utp_socket_impl

This commit is contained in:
Arvid Norberg 2012-06-26 03:42:01 +00:00
parent aeea1cd2af
commit c6b368a763
1 changed files with 83 additions and 0 deletions

View File

@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/timestamp_history.hpp"
#include "libtorrent/error.hpp"
#include "libtorrent/random.hpp"
#include "libtorrent/invariant_check.hpp"
#include <boost/cstdint.hpp>
#define TORRENT_UTP_LOG 0
@ -320,6 +321,10 @@ struct utp_socket_impl
void check_receive_buffers() const;
#ifdef TORRENT_DEBUG
void check_invariant() const;
#endif
utp_socket_manager* m_sm;
// userdata pointer passed along
@ -690,6 +695,8 @@ void utp_send_ack(utp_socket_impl* s)
void utp_socket_impl::update_mtu_limits()
{
INVARIANT_CHECK;
TORRENT_ASSERT(m_mtu_floor <= m_mtu_ceiling);
m_mtu = (m_mtu_floor + m_mtu_ceiling) / 2;
@ -1051,6 +1058,8 @@ void utp_stream::do_connect(tcp::endpoint const& ep, utp_stream::connect_handler
utp_socket_impl::~utp_socket_impl()
{
INVARIANT_CHECK;
TORRENT_ASSERT(!m_attached);
TORRENT_ASSERT(!m_deferred_ack);
@ -1081,6 +1090,8 @@ utp_socket_impl::~utp_socket_impl()
bool utp_socket_impl::should_delete() const
{
INVARIANT_CHECK;
// if the socket state is not attached anymore we're free
// to delete it from the client's point of view. The other
// endpoint however might still need to be told that we're
@ -1100,6 +1111,8 @@ bool utp_socket_impl::should_delete() const
void utp_socket_impl::maybe_trigger_receive_callback(ptime now)
{
INVARIANT_CHECK;
// nothing has been read or there's no outstanding read operation
if (m_read == 0 || m_read_handler == 0) return;
@ -1116,6 +1129,8 @@ void utp_socket_impl::maybe_trigger_receive_callback(ptime now)
void utp_socket_impl::maybe_trigger_send_callback(ptime now)
{
INVARIANT_CHECK;
// nothing has been written or there's no outstanding write operation
if (m_written == 0 || m_write_handler == 0) return;
@ -1133,6 +1148,8 @@ void utp_socket_impl::maybe_trigger_send_callback(ptime now)
bool utp_socket_impl::destroy()
{
INVARIANT_CHECK;
#if TORRENT_UTP_LOG
UTP_LOGV("%8p: destroy state:%s\n", this, socket_state_names[m_state]);
#endif
@ -1169,12 +1186,16 @@ bool utp_socket_impl::destroy()
void utp_socket_impl::detach()
{
INVARIANT_CHECK;
UTP_LOGV("%8p: detach()\n", this);
m_attached = false;
}
void utp_socket_impl::send_syn()
{
INVARIANT_CHECK;
m_seq_nr = random();
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
m_loss_seq_nr = m_acked_seq_nr;
@ -1236,6 +1257,8 @@ void utp_socket_impl::send_syn()
void utp_socket_impl::send_fin()
{
INVARIANT_CHECK;
TORRENT_ASSERT(m_state != UTP_STATE_FIN_SENT);
// we need a heap allocated packet in order to stick it
@ -1307,6 +1330,8 @@ void utp_socket_impl::send_fin()
void utp_socket_impl::send_reset(utp_header* ph)
{
INVARIANT_CHECK;
utp_header h;
h.type_ver = (ST_RESET << 4) | 1;
h.extension = 0;
@ -1334,6 +1359,8 @@ std::size_t utp_socket_impl::available() const
void utp_socket_impl::parse_sack(boost::uint16_t packet_ack, boost::uint8_t const* ptr
, int size, int* acked_bytes, ptime const now, boost::uint32_t& min_rtt)
{
INVARIANT_CHECK;
if (size == 0) return;
// this is the sequence number the current bit represents
@ -1432,6 +1459,8 @@ void utp_socket_impl::parse_sack(boost::uint16_t packet_ack, boost::uint8_t cons
// pointed to by ptr
void utp_socket_impl::write_payload(boost::uint8_t* ptr, int size)
{
INVARIANT_CHECK;
#ifdef TORRENT_DEBUG
int write_buffer_size = 0;
for (std::vector<iovec_t>::iterator i = m_write_buffer.begin()
@ -1490,6 +1519,8 @@ void utp_socket_impl::write_payload(boost::uint8_t* ptr, int size)
void utp_socket_impl::defer_ack()
{
INVARIANT_CHECK;
if (m_deferred_ack) return;
UTP_LOGV("%8p: defer ack\n", this);
@ -1499,6 +1530,8 @@ void utp_socket_impl::defer_ack()
void utp_socket_impl::remove_sack_header(packet* p)
{
INVARIANT_CHECK;
// remove the sack header
boost::uint8_t* ptr = p->buf + sizeof(utp_header);
utp_header* h = (utp_header*)p->buf;
@ -1525,6 +1558,8 @@ void utp_socket_impl::remove_sack_header(packet* p)
// send_pkt() again)
bool utp_socket_impl::send_pkt(bool ack)
{
INVARIANT_CHECK;
// This assert is bad because we call this function to ack
// received FIN when we're in UTP_STATE_FIN_SENT.
//
@ -1836,6 +1871,8 @@ bool utp_socket_impl::send_pkt(bool ack)
// size is in bytes
void utp_socket_impl::write_sack(boost::uint8_t* buf, int size) const
{
INVARIANT_CHECK;
TORRENT_ASSERT(m_inbuf.size());
int ack_nr = (m_ack_nr + 2) & ACK_MASK;
boost::uint8_t* end = buf + size;
@ -1855,6 +1892,8 @@ void utp_socket_impl::write_sack(boost::uint8_t* buf, int size) const
bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
{
INVARIANT_CHECK;
// for fast re-sends the packet hasn't been marked as needing resending
TORRENT_ASSERT(p->need_resend || fast_resend);
@ -1945,6 +1984,8 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
void utp_socket_impl::experienced_loss(int seq_nr)
{
INVARIANT_CHECK;
// since loss often comes in bursts, we only cut the
// window in half once per RTT. This is implemented
// by limiting which packets can cause us to cut the
@ -1968,6 +2009,8 @@ void utp_socket_impl::experienced_loss(int seq_nr)
void utp_socket_impl::maybe_inc_acked_seq_nr()
{
INVARIANT_CHECK;
bool incremented = false;
// don't pass m_seq_nr, since we move into sequence
// numbers that haven't been sent yet, and aren't
@ -1998,6 +2041,8 @@ void utp_socket_impl::maybe_inc_acked_seq_nr()
void utp_socket_impl::ack_packet(packet* p, ptime const& receive_time
, boost::uint32_t& min_rtt, boost::uint16_t seq_nr)
{
INVARIANT_CHECK;
TORRENT_ASSERT(p);
// verify that the packet we're removing was in fact sent
@ -2041,6 +2086,8 @@ void utp_socket_impl::ack_packet(packet* p, ptime const& receive_time
void utp_socket_impl::incoming(boost::uint8_t const* buf, int size, packet* p, ptime now)
{
INVARIANT_CHECK;
while (!m_read_buffer.empty())
{
if (p)
@ -2101,6 +2148,8 @@ void utp_socket_impl::incoming(boost::uint8_t const* buf, int size, packet* p, p
bool utp_socket_impl::cancel_handlers(error_code const& ec, bool kill)
{
INVARIANT_CHECK;
TORRENT_ASSERT(ec);
bool ret = m_read_handler || m_write_handler || m_connect_handler;
@ -2120,6 +2169,8 @@ bool utp_socket_impl::consume_incoming_data(
utp_header const* ph, boost::uint8_t const* ptr, int payload_size
, ptime now)
{
INVARIANT_CHECK;
if (ph->get_type() != ST_DATA) return false;
if (m_eof && m_ack_nr == m_eof_seq_nr)
@ -2207,6 +2258,8 @@ bool utp_socket_impl::consume_incoming_data(
// returns true of the socket was closed
bool utp_socket_impl::test_socket_state()
{
INVARIANT_CHECK;
// if the socket is in a state where it's dead, just waiting to
// tell the client that it's closed. Do that and transition into
// the deleted state, where it will be deleted
@ -2234,6 +2287,8 @@ bool utp_socket_impl::test_socket_state()
void utp_socket_impl::init_mtu(int link_mtu, int utp_mtu)
{
INVARIANT_CHECK;
// if we're in a RAM constrained environment, don't increase
// the buffer size for interfaces with large MTUs. Just stick
// to ethernet frame sizes
@ -2269,6 +2324,8 @@ void utp_socket_impl::init_mtu(int link_mtu, int utp_mtu)
bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
, udp::endpoint const& ep, ptime receive_time)
{
INVARIANT_CHECK;
utp_header* ph = (utp_header*)buf;
if (ph->get_version() != 1)
@ -2916,6 +2973,8 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime const now)
{
INVARIANT_CHECK;
// the portion of the in-flight bytes that were acked. This is used to make
// the gain factor be scaled by the rtt. The formula is applied once per
// rtt, or on every ACK skaled by the number of ACKs per rtt
@ -3003,6 +3062,8 @@ void utp_stream::bind(endpoint_type const& ep, error_code& ec) { }
// into account
int utp_socket_impl::packet_timeout() const
{
INVARIANT_CHECK;
// SYN packets have a bit longer timeout, since we don't
// have an RTT estimate yet, make a conservative guess
if (m_state == UTP_STATE_NONE) return 3000;
@ -3017,6 +3078,8 @@ int utp_socket_impl::packet_timeout() const
void utp_socket_impl::tick(ptime const& now)
{
INVARIANT_CHECK;
#if TORRENT_UTP_LOG
UTP_LOGV("%8p: tick:%s r: %d (%s) w: %d (%s)\n"
, this, socket_state_names[m_state], m_read, m_read_handler ? "handler" : "no handler"
@ -3168,6 +3231,8 @@ void utp_socket_impl::tick(ptime const& now)
void utp_socket_impl::check_receive_buffers() const
{
INVARIANT_CHECK;
std::size_t size = 0;
for (std::vector<packet*>::const_iterator i = m_receive_buffer.begin()
@ -3180,5 +3245,23 @@ void utp_socket_impl::check_receive_buffers() const
TORRENT_ASSERT(int(size) == m_receive_buffer_size);
}
#ifdef TORRENT_DEBUG
void utp_socket_impl::check_invariant() const
{
for (int i = m_outbuf.cursor();
i != ((m_outbuf.cursor() + m_outbuf.span()) & ACK_MASK);
i = (i + 1) & ACK_MASK)
{
packet* p = (packet*)m_outbuf.at(i);
if (m_mtu_seq == i && m_mtu_seq != 0)
{
TORRENT_ASSERT(p);
if (p) TORRENT_ASSERT(p->mtu_probe);
}
if (!p) continue;
TORRENT_ASSERT(((utp_header*)p->buf)->seq_nr == i);
}
}
#endif
}