mirror of
https://github.com/twisterarmy/twister-core.git
synced 2025-01-09 22:37:55 +00:00
parent
cfa194b3f8
commit
187e052240
@ -1342,7 +1342,7 @@ namespace libtorrent
|
|||||||
, utp_min_timeout(500) // milliseconds
|
, utp_min_timeout(500) // milliseconds
|
||||||
, utp_syn_resends(2)
|
, utp_syn_resends(2)
|
||||||
, utp_fin_resends(2)
|
, utp_fin_resends(2)
|
||||||
, utp_num_resends(6)
|
, utp_num_resends(3)
|
||||||
, utp_connect_timeout(3000) // milliseconds
|
, utp_connect_timeout(3000) // milliseconds
|
||||||
#ifndef TORRENT_NO_DEPRECATE
|
#ifndef TORRENT_NO_DEPRECATE
|
||||||
, utp_delayed_ack(0) // milliseconds
|
, utp_delayed_ack(0) // milliseconds
|
||||||
|
@ -111,7 +111,12 @@ enum
|
|||||||
|
|
||||||
// the max number of packets to fast-resend per
|
// the max number of packets to fast-resend per
|
||||||
// selective ack message
|
// selective ack message
|
||||||
sack_resend_limit = 3,
|
// only re-sending a single packet per sack
|
||||||
|
// appears to improve performance by making it
|
||||||
|
// less likely to loose the re-sent packet. Because
|
||||||
|
// when that happens, we must time-out in order
|
||||||
|
// to continue, which takes a long time.
|
||||||
|
sack_resend_limit = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
// compare if lhs is less than rhs, taking wrapping
|
// compare if lhs is less than rhs, taking wrapping
|
||||||
@ -237,7 +242,7 @@ struct utp_socket_impl
|
|||||||
, m_written(0)
|
, m_written(0)
|
||||||
, m_receive_buffer_size(0)
|
, m_receive_buffer_size(0)
|
||||||
, m_read_buffer_size(0)
|
, m_read_buffer_size(0)
|
||||||
, m_in_buf_size(100 * 1024 * 1024)
|
, m_in_buf_size(1024 * 1024)
|
||||||
, m_in_packets(0)
|
, m_in_packets(0)
|
||||||
, m_out_packets(0)
|
, m_out_packets(0)
|
||||||
, m_send_delay(0)
|
, m_send_delay(0)
|
||||||
@ -267,6 +272,7 @@ struct utp_socket_impl
|
|||||||
, m_deferred_ack(false)
|
, m_deferred_ack(false)
|
||||||
, m_subscribe_drained(false)
|
, m_subscribe_drained(false)
|
||||||
, m_stalled(false)
|
, m_stalled(false)
|
||||||
|
, m_confirmed(false)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_userdata);
|
TORRENT_ASSERT(m_userdata);
|
||||||
for (int i = 0; i != num_delay_hist; ++i)
|
for (int i = 0; i != num_delay_hist; ++i)
|
||||||
@ -637,6 +643,11 @@ struct utp_socket_impl
|
|||||||
// of sockets in the utp_socket_manager to be notified of
|
// of sockets in the utp_socket_manager to be notified of
|
||||||
// the socket being writable again
|
// the socket being writable again
|
||||||
bool m_stalled:1;
|
bool m_stalled:1;
|
||||||
|
|
||||||
|
// this is false by default and set to true once we've received a non-SYN
|
||||||
|
// packet for this connection with a correct ack_nr, confirming that the
|
||||||
|
// other end is not spoofing its source IP
|
||||||
|
bool m_confirmed:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
|
||||||
@ -1227,7 +1238,7 @@ void utp_socket_impl::send_syn()
|
|||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
m_seq_nr = random();
|
m_seq_nr = random() & 0xffff;
|
||||||
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
||||||
m_loss_seq_nr = m_acked_seq_nr;
|
m_loss_seq_nr = m_acked_seq_nr;
|
||||||
m_ack_nr = 0;
|
m_ack_nr = 0;
|
||||||
@ -1447,9 +1458,10 @@ void utp_socket_impl::parse_sack(boost::uint16_t packet_ack, boost::uint8_t cons
|
|||||||
{
|
{
|
||||||
experienced_loss(m_fast_resend_seq_nr);
|
experienced_loss(m_fast_resend_seq_nr);
|
||||||
int num_resent = 0;
|
int num_resent = 0;
|
||||||
for (; m_fast_resend_seq_nr != last_ack; m_fast_resend_seq_nr = (m_fast_resend_seq_nr + 1) & ACK_MASK)
|
while (m_fast_resend_seq_nr != last_ack)
|
||||||
{
|
{
|
||||||
packet* p = (packet*)m_outbuf.at(m_fast_resend_seq_nr);
|
packet* p = (packet*)m_outbuf.at(m_fast_resend_seq_nr);
|
||||||
|
m_fast_resend_seq_nr = (m_fast_resend_seq_nr + 1) & ACK_MASK;
|
||||||
if (!p) continue;
|
if (!p) continue;
|
||||||
++num_resent;
|
++num_resent;
|
||||||
if (!resend_packet(p, true)) break;
|
if (!resend_packet(p, true)) break;
|
||||||
@ -1813,7 +1825,8 @@ bool utp_socket_impl::send_pkt(int flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
h->timestamp_difference_microseconds = m_reply_micro;
|
h->timestamp_difference_microseconds = m_reply_micro;
|
||||||
h->wnd_size = m_in_buf_size - m_buffered_incoming_bytes - m_receive_buffer_size;
|
h->wnd_size = (std::max)(m_in_buf_size - m_buffered_incoming_bytes
|
||||||
|
- m_receive_buffer_size, boost::int32_t(0));
|
||||||
h->ack_nr = m_ack_nr;
|
h->ack_nr = m_ack_nr;
|
||||||
|
|
||||||
// if this is a FIN packet, override the type
|
// if this is a FIN packet, override the type
|
||||||
@ -2079,8 +2092,10 @@ void utp_socket_impl::experienced_loss(int seq_nr)
|
|||||||
// window size. The first packet that's lost will
|
// window size. The first packet that's lost will
|
||||||
// update the limit to the last sequence number we sent.
|
// update the limit to the last sequence number we sent.
|
||||||
// i.e. only packet sent after this loss can cause another
|
// i.e. only packet sent after this loss can cause another
|
||||||
// window size cut
|
// window size cut. The +1 is to turn the comparison into
|
||||||
if (compare_less_wrap(seq_nr, m_loss_seq_nr, ACK_MASK)) return;
|
// less than or equal to. If we experience loss of the
|
||||||
|
// same packet again, ignore it.
|
||||||
|
if (compare_less_wrap(seq_nr, m_loss_seq_nr + 1, ACK_MASK)) return;
|
||||||
|
|
||||||
// cut window size in 2
|
// cut window size in 2
|
||||||
m_cwnd = (std::max)(m_cwnd * m_sm->loss_multiplier() / 100, boost::int64_t(m_mtu << 16));
|
m_cwnd = (std::max)(m_cwnd * m_sm->loss_multiplier() / 100, boost::int64_t(m_mtu << 16));
|
||||||
@ -2261,10 +2276,30 @@ bool utp_socket_impl::consume_incoming_data(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (m_read_buffer_size == 0
|
||||||
|
&& m_receive_buffer_size >= m_in_buf_size - m_buffered_incoming_bytes)
|
||||||
|
{
|
||||||
|
// if we don't have a buffer from the upper layer, and the
|
||||||
|
// number of queued up bytes, waiting for the upper layer,
|
||||||
|
// exceeds the advertized receive window, start ignoring
|
||||||
|
// more data packets
|
||||||
|
UTP_LOG("%8p: ERROR: our advertized window is not honored. "
|
||||||
|
"recv_buf: %d buffered_in: %d max_size: %d\n"
|
||||||
|
, static_cast<void*>(this), m_receive_buffer_size, m_buffered_incoming_bytes, m_in_buf_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (ph->seq_nr == ((m_ack_nr + 1) & ACK_MASK))
|
if (ph->seq_nr == ((m_ack_nr + 1) & ACK_MASK))
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_inbuf.at(m_ack_nr) == 0);
|
TORRENT_ASSERT(m_inbuf.at(m_ack_nr) == 0);
|
||||||
|
|
||||||
|
if (m_buffered_incoming_bytes + m_receive_buffer_size + payload_size > m_in_buf_size)
|
||||||
|
{
|
||||||
|
UTP_LOGV("%8p: other end is not honoring our advertised window, dropping packet\n"
|
||||||
|
, static_cast<void*>(this));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// we received a packet in order
|
// we received a packet in order
|
||||||
incoming(ptr, payload_size, 0, now);
|
incoming(ptr, payload_size, 0, now);
|
||||||
m_ack_nr = (m_ack_nr + 1) & ACK_MASK;
|
m_ack_nr = (m_ack_nr + 1) & ACK_MASK;
|
||||||
@ -2312,7 +2347,14 @@ bool utp_socket_impl::consume_incoming_data(
|
|||||||
if (m_inbuf.at(ph->seq_nr))
|
if (m_inbuf.at(ph->seq_nr))
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: already received seq_nr: %d\n"
|
UTP_LOGV("%8p: already received seq_nr: %d\n"
|
||||||
, this, int(ph->seq_nr));
|
, static_cast<void*>(this), int(ph->seq_nr));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_buffered_incoming_bytes + m_receive_buffer_size + payload_size > m_in_buf_size)
|
||||||
|
{
|
||||||
|
UTP_LOGV("%8p: other end is not honoring our advertised window, dropping packet %d\n"
|
||||||
|
, static_cast<void*>(this), int(ph->seq_nr));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2502,8 +2544,10 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
if (m_state == UTP_STATE_SYN_SENT && ph->get_type() == ST_STATE)
|
if (m_state == UTP_STATE_SYN_SENT && ph->get_type() == ST_STATE)
|
||||||
cmp_seq_nr = m_seq_nr;
|
cmp_seq_nr = m_seq_nr;
|
||||||
#endif
|
#endif
|
||||||
if (m_state != UTP_STATE_NONE
|
if ((m_state != UTP_STATE_NONE || ph->get_type() != ST_SYN)
|
||||||
&& compare_less_wrap(cmp_seq_nr, ph->ack_nr, ACK_MASK))
|
&& (compare_less_wrap(cmp_seq_nr, ph->ack_nr, ACK_MASK)
|
||||||
|
|| compare_less_wrap(ph->ack_nr, m_acked_seq_nr
|
||||||
|
- dup_ack_limit, ACK_MASK)))
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet ack_nr:%d our seq_nr:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet ack_nr:%d our seq_nr:%d (ignored)\n"
|
||||||
, this, int(ph->ack_nr), m_seq_nr);
|
, this, int(ph->ack_nr), m_seq_nr);
|
||||||
@ -2538,7 +2582,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
{
|
{
|
||||||
UTP_LOGV("%8p: incoming packet seq_nr:%d eof_seq_nr:%d (ignored)\n"
|
UTP_LOGV("%8p: incoming packet seq_nr:%d eof_seq_nr:%d (ignored)\n"
|
||||||
, this, int(ph->seq_nr), m_eof_seq_nr);
|
, this, int(ph->seq_nr), m_eof_seq_nr);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_state != UTP_STATE_NONE
|
if (m_state != UTP_STATE_NONE
|
||||||
@ -2643,7 +2687,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
, this, len, int(ptr - buf));
|
, this, len, int(ptr - buf));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ptr - buf + len > size_t(size))
|
if (ptr - buf + len > ptrdiff_t(size))
|
||||||
{
|
{
|
||||||
UTP_LOGV("%8p: invalid extension header size:%d packet:%d\n"
|
UTP_LOGV("%8p: invalid extension header size:%d packet:%d\n"
|
||||||
, this, len, int(ptr - buf));
|
, this, len, int(ptr - buf));
|
||||||
@ -2755,7 +2799,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
m_local_address = m_sm->local_endpoint(m_remote_address, ec).address();
|
m_local_address = m_sm->local_endpoint(m_remote_address, ec).address();
|
||||||
|
|
||||||
m_ack_nr = ph->seq_nr;
|
m_ack_nr = ph->seq_nr;
|
||||||
m_seq_nr = random();
|
m_seq_nr = random() & 0xffff;
|
||||||
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
m_acked_seq_nr = (m_seq_nr - 1) & ACK_MASK;
|
||||||
m_loss_seq_nr = m_acked_seq_nr;
|
m_loss_seq_nr = m_acked_seq_nr;
|
||||||
m_fast_resend_seq_nr = m_seq_nr;
|
m_fast_resend_seq_nr = m_seq_nr;
|
||||||
@ -2768,8 +2812,6 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
TORRENT_ASSERT(m_recv_id == ((m_send_id + 1) & 0xffff));
|
TORRENT_ASSERT(m_recv_id == ((m_send_id + 1) & 0xffff));
|
||||||
|
|
||||||
defer_ack();
|
defer_ack();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -2777,7 +2819,6 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
UTP_LOGV("%8p: type:%s state:%s (ignored)\n"
|
UTP_LOGV("%8p: type:%s state:%s (ignored)\n"
|
||||||
, this, packet_type_names[ph->get_type()], socket_state_names[m_state]);
|
, this, packet_type_names[ph->get_type()], socket_state_names[m_state]);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2790,7 +2831,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
UTP_LOGV("%8p: incorrect ack_nr (%d) waiting for %d\n"
|
UTP_LOGV("%8p: incorrect ack_nr (%d) waiting for %d\n"
|
||||||
, this, int(ph->ack_nr), (m_seq_nr - 1) & ACK_MASK);
|
, this, int(ph->ack_nr), (m_seq_nr - 1) & ACK_MASK);
|
||||||
#endif
|
#endif
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_ASSERT(!m_error);
|
TORRENT_ASSERT(!m_error);
|
||||||
@ -2845,7 +2886,11 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
// (i.e. ST_STATE) we're not ACKing anything. If we just
|
// (i.e. ST_STATE) we're not ACKing anything. If we just
|
||||||
// received a FIN packet, we need to ack that as well
|
// received a FIN packet, we need to ack that as well
|
||||||
bool has_ack = ph->get_type() == ST_DATA || ph->get_type() == ST_FIN || ph->get_type() == ST_SYN;
|
bool has_ack = ph->get_type() == ST_DATA || ph->get_type() == ST_FIN || ph->get_type() == ST_SYN;
|
||||||
int prev_out_packets = m_out_packets;
|
boost::uint32_t prev_out_packets = m_out_packets;
|
||||||
|
|
||||||
|
// the connection is connected and this packet made it past all the
|
||||||
|
// checks. We can now assume the other end is not spoofing it's IP.
|
||||||
|
if (ph->get_type() != ST_SYN) m_confirmed = true;
|
||||||
|
|
||||||
// try to send more data as long as we can
|
// try to send more data as long as we can
|
||||||
// if send_pkt returns true
|
// if send_pkt returns true
|
||||||
@ -2960,7 +3005,7 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
case UTP_STATE_FIN_SENT:
|
case UTP_STATE_FIN_SENT:
|
||||||
{
|
{
|
||||||
@ -3022,7 +3067,9 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
// data, and we can gracefully shut down.
|
// data, and we can gracefully shut down.
|
||||||
|
|
||||||
if (consume_incoming_data(ph, ptr, payload_size, receive_time))
|
if (consume_incoming_data(ph, ptr, payload_size, receive_time))
|
||||||
return true;
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_acked_seq_nr == ((m_seq_nr - 1) & ACK_MASK))
|
if (m_acked_seq_nr == ((m_seq_nr - 1) & ACK_MASK))
|
||||||
{
|
{
|
||||||
@ -3047,18 +3094,17 @@ bool utp_socket_impl::incoming_packet(boost::uint8_t const* buf, int size
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
case UTP_STATE_DELETE:
|
case UTP_STATE_DELETE:
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
// respond with a reset
|
// respond with a reset
|
||||||
send_reset(ph);
|
send_reset(ph);
|
||||||
return true;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime const now)
|
void utp_socket_impl::do_ledbat(int acked_bytes, int delay, int in_flight, ptime const now)
|
||||||
@ -3165,6 +3211,9 @@ int utp_socket_impl::packet_timeout() const
|
|||||||
|
|
||||||
int timeout = (std::max)(m_sm->min_timeout(), m_rtt.mean() + m_rtt.avg_deviation() * 2);
|
int timeout = (std::max)(m_sm->min_timeout(), m_rtt.mean() + m_rtt.avg_deviation() * 2);
|
||||||
if (m_num_timeouts > 0) timeout += (1 << (int(m_num_timeouts) - 1)) * 1000;
|
if (m_num_timeouts > 0) timeout += (1 << (int(m_num_timeouts) - 1)) * 1000;
|
||||||
|
|
||||||
|
// timeouts over 1 minute are capped
|
||||||
|
if (timeout > 60000) timeout = 60000;
|
||||||
return timeout;
|
return timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3192,7 +3241,11 @@ void utp_socket_impl::tick(ptime const& now)
|
|||||||
|
|
||||||
if (m_outbuf.size()) ++m_num_timeouts;
|
if (m_outbuf.size()) ++m_num_timeouts;
|
||||||
|
|
||||||
if (m_num_timeouts > m_sm->num_resends())
|
// a socket that has not been confirmed to actually have a live remote end
|
||||||
|
// (the IP may have been spoofed) fail on the first timeout. If we had
|
||||||
|
// heard anything from this peer, it would have been confirmed.
|
||||||
|
if (m_num_timeouts > m_sm->num_resends()
|
||||||
|
|| (m_num_timeouts > 0 && !m_confirmed))
|
||||||
{
|
{
|
||||||
// the connection is dead
|
// the connection is dead
|
||||||
m_error = asio::error::timed_out;
|
m_error = asio::error::timed_out;
|
||||||
|
Loading…
Reference in New Issue
Block a user