merged RC_1_1 into master

This commit is contained in:
arvidn 2019-01-11 12:22:47 +01:00
commit 8b067310b1
10 changed files with 138 additions and 78 deletions

View File

@ -740,7 +740,11 @@ if(developer-options)
ENABLED TORRENT_PROFILE_CALLS=1) ENABLED TORRENT_PROFILE_CALLS=1)
endif() endif()
generate_and_install_pkg_config_file(torrent-rasterbar libtorrent-rasterbar) # There is little to none support for using pkg-config with MSVC and most users won't bother with it.
# However, msys is a linux-like platform on Windows that do support/prefer using pkg-config.
if (NOT MSVC)
generate_and_install_pkg_config_file(torrent-rasterbar libtorrent-rasterbar)
endif()
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)

View File

@ -47,6 +47,10 @@ POSSIBILITY OF SUCH DAMAGE.
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#ifdef TORRENT_UTP_LOG_ENABLE
#include "libtorrent/utp_stream.hpp"
#endif
#include "libtorrent/torrent_info.hpp" #include "libtorrent/torrent_info.hpp"
#include "libtorrent/announce_entry.hpp" #include "libtorrent/announce_entry.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
@ -1022,8 +1026,13 @@ CLIENT OPTIONS
previous command line options, so be sure to specify this first previous command line options, so be sure to specify this first
-G Add torrents in seed-mode (i.e. assume all pieces -G Add torrents in seed-mode (i.e. assume all pieces
are present and check hashes on-demand) are present and check hashes on-demand)
-O print session stats counters to the log -O print session stats counters to the log)"
#ifdef TORRENT_UTP_LOG_ENABLE
R"(
-q Enable uTP transport-level verbose logging
)"
#endif
R"(
LIBTORRENT SETTINGS LIBTORRENT SETTINGS
--<name-of-setting>=<value> --<name-of-setting>=<value>
set the libtorrent setting <name> to <value> set the libtorrent setting <name> to <value>
@ -1190,6 +1199,11 @@ example alert_masks:
case 'G': seed_mode = true; --i; break; case 'G': seed_mode = true; --i; break;
case 's': save_path = make_absolute_path(arg); break; case 's': save_path = make_absolute_path(arg); break;
case 'O': stats_enabled = true; --i; break; case 'O': stats_enabled = true; --i; break;
#ifdef TORRENT_UTP_LOG_ENABLE
case 'q':
libtorrent::set_utp_stream_logging(true);
break;
#endif
case 'U': torrent_upload_limit = atoi(arg) * 1000; break; case 'U': torrent_upload_limit = atoi(arg) * 1000; break;
case 'D': torrent_download_limit = atoi(arg) * 1000; break; case 'D': torrent_download_limit = atoi(arg) * 1000; break;
case 'm': monitor_dir = make_absolute_path(arg); break; case 'm': monitor_dir = make_absolute_path(arg); break;

View File

@ -78,8 +78,9 @@ namespace libtorrent {
packet_ptr insert(index_type idx, packet_ptr value); packet_ptr insert(index_type idx, packet_ptr value);
int size() const int size() const { return m_size; }
{ return m_size; }
bool empty() const { return m_size == 0; }
std::uint32_t capacity() const std::uint32_t capacity() const
{ return m_capacity; } { return m_capacity; }

View File

@ -1659,6 +1659,11 @@ namespace libtorrent {
// systems. // systems.
close_file_interval, close_file_interval,
// When uTP experiences packet loss, it will reduce the congestion
// window, and not reduce it again for this many milliseconds, even if
// experiencing another lost packet.
utp_cwnd_reduce_timer,
// the max number of web seeds to have connected per torrent at any // the max number of web seeds to have connected per torrent at any
// given time. // given time.
max_web_seed_connections, max_web_seed_connections,

View File

@ -107,6 +107,7 @@ namespace libtorrent {
int connect_timeout() const { return m_sett.get_int(settings_pack::utp_connect_timeout); } int connect_timeout() const { return m_sett.get_int(settings_pack::utp_connect_timeout); }
int min_timeout() const { return m_sett.get_int(settings_pack::utp_min_timeout); } int min_timeout() const { return m_sett.get_int(settings_pack::utp_min_timeout); }
int loss_multiplier() const { return m_sett.get_int(settings_pack::utp_loss_multiplier); } int loss_multiplier() const { return m_sett.get_int(settings_pack::utp_loss_multiplier); }
int cwnd_reduce_timer() const { return m_sett.get_int(settings_pack::utp_cwnd_reduce_timer); }
std::pair<int, int> mtu_for_dest(address const& addr); std::pair<int, int> mtu_for_dest(address const& addr);
int num_sockets() const { return int(m_utp_sockets.size()); } int num_sockets() const { return int(m_utp_sockets.size()); }

View File

@ -285,7 +285,7 @@ struct sim_config : sim::default_config
{ {
if (hostname == "tracker.com") if (hostname == "tracker.com")
{ {
result.push_back(address_v4::from_string("10.0.0.2")); result.push_back(address_v4::from_string("123.0.0.2"));
if (ipv6) if (ipv6)
result.push_back(address_v6::from_string("ff::dead:beef")); result.push_back(address_v6::from_string("ff::dead:beef"));
return duration_cast<chrono::high_resolution_clock::duration>(chrono::milliseconds(100)); return duration_cast<chrono::high_resolution_clock::duration>(chrono::milliseconds(100));
@ -323,7 +323,7 @@ void test_ipv6_support(char const* listen_interfaces
sim_config network_cfg; sim_config network_cfg;
sim::simulation sim{network_cfg}; sim::simulation sim{network_cfg};
sim::asio::io_service web_server_v4(sim, address_v4::from_string("10.0.0.2")); sim::asio::io_service web_server_v4(sim, address_v4::from_string("123.0.0.2"));
sim::asio::io_service web_server_v6(sim, address_v6::from_string("ff::dead:beef")); sim::asio::io_service web_server_v6(sim, address_v6::from_string("ff::dead:beef"));
// listen on port 8080 // listen on port 8080
@ -370,7 +370,7 @@ void test_ipv6_support(char const* listen_interfaces
for (int i = 0; i < num_interfaces; i++) for (int i = 0; i < num_interfaces; i++)
{ {
char ep[30]; char ep[30];
std::snprintf(ep, sizeof(ep), "10.0.0.%d", i + 1); std::snprintf(ep, sizeof(ep), "123.0.0.%d", i + 1);
ips.push_back(address::from_string(ep)); ips.push_back(address::from_string(ep));
std::snprintf(ep, sizeof(ep), "ffff::1337:%d", i + 1); std::snprintf(ep, sizeof(ep), "ffff::1337:%d", i + 1);
ips.push_back(address::from_string(ep)); ips.push_back(address::from_string(ep));
@ -428,7 +428,7 @@ void test_udpv6_support(char const* listen_interfaces
sim_config network_cfg; sim_config network_cfg;
sim::simulation sim{network_cfg}; sim::simulation sim{network_cfg};
sim::asio::io_service web_server_v4(sim, address_v4::from_string("10.0.0.2")); sim::asio::io_service web_server_v4(sim, address_v4::from_string("123.0.0.2"));
sim::asio::io_service web_server_v6(sim, address_v6::from_string("ff::dead:beef")); sim::asio::io_service web_server_v6(sim, address_v6::from_string("ff::dead:beef"));
int v4_announces = 0; int v4_announces = 0;
@ -442,7 +442,7 @@ void test_udpv6_support(char const* listen_interfaces
for (int i = 0; i < num_interfaces; i++) for (int i = 0; i < num_interfaces; i++)
{ {
char ep[30]; char ep[30];
std::snprintf(ep, sizeof(ep), "10.0.0.%d", i + 1); std::snprintf(ep, sizeof(ep), "123.0.0.%d", i + 1);
ips.push_back(address::from_string(ep)); ips.push_back(address::from_string(ep));
std::snprintf(ep, sizeof(ep), "ffff::1337:%d", i + 1); std::snprintf(ep, sizeof(ep), "ffff::1337:%d", i + 1);
ips.push_back(address::from_string(ep)); ips.push_back(address::from_string(ep));
@ -555,7 +555,7 @@ TORRENT_TEST(ipv6_support_bind_v6_any)
TORRENT_TEST(ipv6_support_bind_v4) TORRENT_TEST(ipv6_support_bind_v4)
{ {
test_ipv6_support("10.0.0.3:6881", 2, 0); test_ipv6_support("123.0.0.3:6881", 2, 0);
} }
TORRENT_TEST(ipv6_support_bind_v6) TORRENT_TEST(ipv6_support_bind_v6)
@ -570,12 +570,12 @@ TORRENT_TEST(ipv6_support_bind_v6_3interfaces)
TORRENT_TEST(ipv6_support_bind_v4_v6) TORRENT_TEST(ipv6_support_bind_v4_v6)
{ {
test_ipv6_support("10.0.0.3:6881,[ffff::1337:1]:6881", 2, 2); test_ipv6_support("123.0.0.3:6881,[ffff::1337:1]:6881", 2, 2);
} }
TORRENT_TEST(ipv6_support_bind_v6_v4) TORRENT_TEST(ipv6_support_bind_v6_v4)
{ {
test_ipv6_support("[ffff::1337:1]:6881,10.0.0.3:6881", 2, 2); test_ipv6_support("[ffff::1337:1]:6881,123.0.0.3:6881", 2, 2);
} }
// this runs a simulation of a torrent with tracker(s), making sure the request // this runs a simulation of a torrent with tracker(s), making sure the request
@ -584,7 +584,7 @@ TORRENT_TEST(ipv6_support_bind_v6_v4)
// trackers to the torrent. It's expected to return the number of seconds to // trackers to the torrent. It's expected to return the number of seconds to
// wait until test2 is called. // wait until test2 is called.
// The Announce function is called on http requests. Test1 is run on the session // The Announce function is called on http requests. Test1 is run on the session
// 5 seconds after startup. The tracker is running at 10.0.0.2 (or tracker.com) // 5 seconds after startup. The tracker is running at 123.0.0.2 (or tracker.com)
// port 8080. // port 8080.
template <typename Setup, typename Announce, typename Test1, typename Test2> template <typename Setup, typename Announce, typename Test1, typename Test2>
void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2 void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2
@ -594,7 +594,7 @@ void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2
sim_config network_cfg; sim_config network_cfg;
sim::simulation sim{network_cfg}; sim::simulation sim{network_cfg};
sim::asio::io_service tracker_ios(sim, address_v4::from_string("10.0.0.2")); sim::asio::io_service tracker_ios(sim, address_v4::from_string("123.0.0.2"));
sim::asio::io_service tracker_ios6(sim, address_v6::from_string("ff::dead:beef")); sim::asio::io_service tracker_ios6(sim, address_v6::from_string("ff::dead:beef"));
// listen on port 8080 // listen on port 8080
@ -606,7 +606,7 @@ void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2
lt::session_proxy zombie; lt::session_proxy zombie;
asio::io_service ios(sim, { address_v4::from_string("10.0.0.3") asio::io_service ios(sim, { address_v4::from_string("123.0.0.3")
, address_v6::from_string("ffff::1337") }); , address_v6::from_string("ffff::1337") });
lt::settings_pack sett = settings(); lt::settings_pack sett = settings();
std::unique_ptr<lt::session> ses(new lt::session(sett, ios)); std::unique_ptr<lt::session> ses(new lt::session(sett, ios));
@ -976,7 +976,7 @@ TORRENT_TEST(tracker_ipv6_argument)
{ {
settings_pack pack; settings_pack pack;
pack.set_bool(settings_pack::anonymous_mode, false); pack.set_bool(settings_pack::anonymous_mode, false);
pack.set_str(settings_pack::listen_interfaces, "10.0.0.3:0,[ffff::1337]:0"); pack.set_str(settings_pack::listen_interfaces, "123.0.0.3:0,[ffff::1337]:0");
ses.apply_settings(pack); ses.apply_settings(pack);
p.ti = make_torrent(true); p.ti = make_torrent(true);
return 60; return 60;
@ -1000,7 +1000,7 @@ TORRENT_TEST(tracker_ipv6_argument)
std::string::size_type const pos = req.find("&ipv4="); std::string::size_type const pos = req.find("&ipv4=");
TEST_CHECK(pos != std::string::npos || stop_event); TEST_CHECK(pos != std::string::npos || stop_event);
got_ipv4 |= pos != std::string::npos; got_ipv4 |= pos != std::string::npos;
TEST_EQUAL(req.substr(pos + 6, req.substr(pos + 6).find_first_of('&')), "10.0.0.3"); TEST_EQUAL(req.substr(pos + 6, req.substr(pos + 6).find_first_of('&')), "123.0.0.3");
} }
return sim::send_response(200, "OK", 11) + "d5:peers0:e"; return sim::send_response(200, "OK", 11) + "d5:peers0:e";
} }

View File

@ -341,6 +341,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0;
SET(urlseed_max_request_bytes, 16 * 1024 * 1024, nullptr), SET(urlseed_max_request_bytes, 16 * 1024 * 1024, nullptr),
SET(web_seed_name_lookup_retry, 1800, nullptr), SET(web_seed_name_lookup_retry, 1800, nullptr),
SET(close_file_interval, CLOSE_FILE_INTERVAL, nullptr), SET(close_file_interval, CLOSE_FILE_INTERVAL, nullptr),
SET(utp_cwnd_reduce_timer, 100, nullptr),
SET(max_web_seed_connections, 3, nullptr), SET(max_web_seed_connections, 3, nullptr),
SET(resolver_cache_timeout, 1200, &session_impl::update_resolver_cache_timeout), SET(resolver_cache_timeout, 1200, &session_impl::update_resolver_cache_timeout),
}}); }});

View File

@ -2832,9 +2832,15 @@ bool is_downloading_state(int const st)
tcp::endpoint const ep = s.get_local_endpoint(); tcp::endpoint const ep = s.get_local_endpoint();
if (is_any(ep.address())) return; if (is_any(ep.address())) return;
if (is_v6(ep)) if (is_v6(ep))
req.ipv6.push_back(ep.address().to_v6()); {
if (!is_local(ep.address()) && !is_loopback(ep.address()))
req.ipv6.push_back(ep.address().to_v6());
}
else else
req.ipv4.push_back(ep.address().to_v4()); {
if (!is_local(ep.address()) && !is_loopback(ep.address()))
req.ipv4.push_back(ep.address().to_v4());
}
}); });
} }

View File

@ -289,7 +289,7 @@ struct utp_socket_impl
bool consume_incoming_data( bool consume_incoming_data(
utp_header const* ph, std::uint8_t const* ptr, int payload_size, time_point now); utp_header const* ph, std::uint8_t const* ptr, int payload_size, time_point now);
void update_mtu_limits(); void update_mtu_limits();
void experienced_loss(std::uint32_t seq_nr); void experienced_loss(std::uint32_t seq_nr, time_point now);
void set_state(int s); void set_state(int s);
@ -394,6 +394,10 @@ struct utp_socket_impl
// the last time we stepped the timestamp history // the last time we stepped the timestamp history
time_point m_last_history_step = clock_type::now(); time_point m_last_history_step = clock_type::now();
// the next time we allow a lost packet to halve cwnd. We only do this once every
// 100 ms
time_point m_next_loss;
// the max number of bytes in-flight. This is a fixed point // the max number of bytes in-flight. This is a fixed point
// value, to get the true number of bytes, shift right 16 bits // value, to get the true number of bytes, shift right 16 bits
// the value is always >= 0, but the calculations performed on // the value is always >= 0, but the calculations performed on
@ -1533,6 +1537,8 @@ std::pair<std::uint32_t, int> utp_socket_impl::parse_sack(std::uint16_t const pa
if (ack_nr == m_seq_nr) break; if (ack_nr == m_seq_nr) break;
} }
if (m_outbuf.empty()) m_duplicate_acks = 0;
// now, scan the bits in reverse, and count the number of ACKed packets. Only // now, scan the bits in reverse, and count the number of ACKed packets. Only
// lost packets followed by 'dup_ack_limit' packets may be resent // lost packets followed by 'dup_ack_limit' packets may be resent
// start with the sequence number represented by the last bit in the SACK // start with the sequence number represented by the last bit in the SACK
@ -1587,19 +1593,20 @@ std::pair<std::uint32_t, int> utp_socket_impl::parse_sack(std::uint16_t const pa
packet* p = m_outbuf.at(pkt_seq); packet* p = m_outbuf.at(pkt_seq);
UTP_LOGV("%8p: Packet %d lost. (fast_resend_seq_nr:%d trigger fast-resend)\n" UTP_LOGV("%8p: Packet %d lost. (fast_resend_seq_nr:%d trigger fast-resend)\n"
, static_cast<void*>(this), pkt_seq, m_fast_resend_seq_nr); , static_cast<void*>(this), pkt_seq, m_fast_resend_seq_nr);
if (p) if (!p) continue;
// don't cut cwnd if the packet we lost was the MTU probe
// the logic to handle a lost MTU probe is in resend_packet()
if (cut_cwnd && (pkt_seq != m_mtu_seq || m_mtu_seq == 0))
{ {
if (resend_packet(p, true)) experienced_loss(pkt_seq, now);
{ cut_cwnd = false;
m_duplicate_acks = 0;
m_fast_resend_seq_nr = (pkt_seq + 1) & ACK_MASK;
}
} }
if (cut_cwnd) if (resend_packet(p, true))
{ {
experienced_loss(pkt_seq); m_duplicate_acks = 0;
cut_cwnd = false; m_fast_resend_seq_nr = (pkt_seq + 1) & ACK_MASK;
} }
} }
@ -2251,7 +2258,7 @@ bool utp_socket_impl::resend_packet(packet* p, bool fast_resend)
return !m_stalled; return !m_stalled;
} }
void utp_socket_impl::experienced_loss(std::uint32_t const seq_nr) void utp_socket_impl::experienced_loss(std::uint32_t const seq_nr, time_point const now)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -2271,11 +2278,17 @@ void utp_socket_impl::experienced_loss(std::uint32_t const seq_nr)
// same packet again, ignore it. // same packet again, ignore it.
if (compare_less_wrap(seq_nr, m_loss_seq_nr + 1, ACK_MASK)) return; if (compare_less_wrap(seq_nr, m_loss_seq_nr + 1, ACK_MASK)) return;
// don't reduce cwnd more than once every 100ms
if (m_next_loss >= now) return;
m_next_loss = now + milliseconds(m_sm.cwnd_reduce_timer());
// cut window size in 2 // cut window size in 2
m_cwnd = std::max(m_cwnd * m_sm.loss_multiplier() / 100 m_cwnd = std::max(m_cwnd * m_sm.loss_multiplier() / 100
, std::int64_t(m_mtu) * (1 << 16)); , std::int64_t(m_mtu) * (1 << 16));
m_loss_seq_nr = m_seq_nr; m_loss_seq_nr = m_seq_nr;
UTP_LOGV("%8p: Lost packet %d caused cwnd cut\n", static_cast<void*>(this), seq_nr); UTP_LOGV("%8p: Lost packet %d caused cwnd cut. m_loss_seq_nr:%d\n"
, static_cast<void*>(this), seq_nr, m_seq_nr);
// if we happen to be in slow-start mode, we need to leave it // if we happen to be in slow-start mode, we need to leave it
// note that we set ssthres to the window size _after_ reducing it. Next slow // note that we set ssthres to the window size _after_ reducing it. Next slow
@ -2875,6 +2888,8 @@ bool utp_socket_impl::incoming_packet(span<std::uint8_t const> buf
++m_duplicate_acks; ++m_duplicate_acks;
} }
TORRENT_ASSERT_VAL(m_outbuf.size() > 0 || m_duplicate_acks == 0, m_duplicate_acks);
std::uint32_t min_rtt = std::numeric_limits<std::uint32_t>::max(); std::uint32_t min_rtt = std::numeric_limits<std::uint32_t>::max();
TORRENT_ASSERT(m_outbuf.at((m_acked_seq_nr + 1) & ACK_MASK) || ((m_seq_nr - m_acked_seq_nr) & ACK_MASK) <= 1); TORRENT_ASSERT(m_outbuf.at((m_acked_seq_nr + 1) & ACK_MASK) || ((m_seq_nr - m_acked_seq_nr) & ACK_MASK) <= 1);
@ -2904,6 +2919,7 @@ bool utp_socket_impl::incoming_packet(span<std::uint8_t const> buf
} }
maybe_inc_acked_seq_nr(); maybe_inc_acked_seq_nr();
if (m_outbuf.empty()) m_duplicate_acks = 0;
} }
// look for extended headers // look for extended headers
@ -2969,7 +2985,9 @@ bool utp_socket_impl::incoming_packet(span<std::uint8_t const> buf
if (p) if (p)
{ {
experienced_loss(m_fast_resend_seq_nr); // don't consider a lost probe as proper loss, it doesn't necessarily
// signal congestion
if (!p->mtu_probe) experienced_loss(m_fast_resend_seq_nr, receive_time);
resend_packet(p, true); resend_packet(p, true);
if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true; if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true;
} }
@ -3178,6 +3196,8 @@ bool utp_socket_impl::incoming_packet(span<std::uint8_t const> buf
if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true; if (m_state == UTP_STATE_ERROR_WAIT || m_state == UTP_STATE_DELETE) return true;
} }
TORRENT_ASSERT(!compare_less_wrap(m_seq_nr, m_acked_seq_nr, ACK_MASK));
#if TORRENT_UTP_LOG #if TORRENT_UTP_LOG
if (sample && acked_bytes && prev_bytes_in_flight) if (sample && acked_bytes && prev_bytes_in_flight)
{ {
@ -3246,7 +3266,7 @@ bool utp_socket_impl::incoming_packet(span<std::uint8_t const> buf
, packet_timeout() , packet_timeout()
, int(total_milliseconds(m_timeout - receive_time)) , int(total_milliseconds(m_timeout - receive_time))
, int(total_microseconds(receive_time.time_since_epoch())) , int(total_microseconds(receive_time.time_since_epoch()))
, (m_seq_nr - m_acked_seq_nr) & ACK_MASK , m_outbuf.size()
, m_mtu , m_mtu
, their_delay_base , their_delay_base
, std::uint32_t(m_reply_micro) , std::uint32_t(m_reply_micro)
@ -3532,7 +3552,20 @@ void utp_socket_impl::tick(time_point const now)
if (now > m_timeout) if (now > m_timeout)
{ {
// TIMEOUT! // TIMEOUT!
// set cwnd to 1 MSS
bool ignore_loss = false;
if (((m_acked_seq_nr + 1) & ACK_MASK) == m_mtu_seq
&& ((m_seq_nr - 1) & ACK_MASK) == m_mtu_seq
&& m_mtu_seq != 0)
{
// we timed out, and the only outstanding packet
// we had was the probe. Assume it was dropped
// because it was too big
m_mtu_ceiling = m_mtu - 1;
update_mtu_limits();
ignore_loss = true;
}
// the close_reason here is a bit of a hack. When it's set, it indicates // the close_reason here is a bit of a hack. When it's set, it indicates
// that the upper layer intends to close the socket. However, it has been // that the upper layer intends to close the socket. However, it has been
@ -3541,7 +3574,9 @@ void utp_socket_impl::tick(time_point const now)
// other end. This catches that case and let the socket time out. // other end. This catches that case and let the socket time out.
if (m_outbuf.size() || m_close_reason != close_reason_t::none) if (m_outbuf.size() || m_close_reason != close_reason_t::none)
{ {
++m_num_timeouts; // m_num_timeouts is used to update the connection timeout, and if we
// lose this packet because it's an MTU-probe, don't change the timeout
if (!ignore_loss) ++m_num_timeouts;
m_sm.inc_stats_counter(counters::utp_timeout); m_sm.inc_stats_counter(counters::utp_timeout);
} }
@ -3567,52 +3602,45 @@ void utp_socket_impl::tick(time_point const now)
return; return;
} }
if (((m_acked_seq_nr + 1) & ACK_MASK) == m_mtu_seq if (!ignore_loss)
&& ((m_seq_nr - 1) & ACK_MASK) == m_mtu_seq
&& m_mtu_seq != 0)
{ {
// we timed out, and the only outstanding packet // set cwnd to 1 MSS
// we had was the probe. Assume it was dropped if (m_bytes_in_flight == 0 && (m_cwnd >> 16) >= m_mtu)
// because it was too big {
m_mtu_ceiling = m_mtu - 1; // this is just a timeout because this direction of
update_mtu_limits(); // the stream is idle. Don't reset the cwnd, just decay it
m_cwnd = std::max(m_cwnd * 2 / 3, std::int64_t(m_mtu) * (1 << 16));
}
else
{
// we timed out because a packet was not ACKed or because
// the cwnd was made smaller than one packet
m_cwnd = std::int64_t(m_mtu) * (1 << 16);
}
TORRENT_ASSERT(m_cwnd >= 0);
m_timeout = now + milliseconds(packet_timeout());
UTP_LOGV("%8p: resetting cwnd:%d\n"
, static_cast<void*>(this), int(m_cwnd >> 16));
// since we've already timed out now, don't count
// loss that we might detect for packets that just
// timed out
m_loss_seq_nr = m_seq_nr;
// when we time out, the cwnd is reset to 1 MSS, which means we
// need to ramp it up quickly again. enter slow start mode. This time
// we're very likely to have an ssthres set, which will make us leave
// slow start before inducing more delay or loss.
m_slow_start = true;
UTP_LOGV("%8p: slow_start -> 1\n", static_cast<void*>(this));
} }
if (m_bytes_in_flight == 0 && (m_cwnd >> 16) >= m_mtu)
{
// this is just a timeout because this direction of
// the stream is idle. Don't reset the cwnd, just decay it
m_cwnd = std::max(m_cwnd * 2 / 3, std::int64_t(m_mtu) * (1 << 16));
}
else
{
// we timed out because a packet was not ACKed or because
// the cwnd was made smaller than one packet
m_cwnd = std::int64_t(m_mtu) * (1 << 16);
}
TORRENT_ASSERT(m_cwnd >= 0);
m_timeout = now + milliseconds(packet_timeout());
UTP_LOGV("%8p: resetting cwnd:%d\n"
, static_cast<void*>(this), int(m_cwnd >> 16));
// we dropped all packets, that includes the mtu probe // we dropped all packets, that includes the mtu probe
m_mtu_seq = 0; m_mtu_seq = 0;
// since we've already timed out now, don't count
// loss that we might detect for packets that just
// timed out
m_loss_seq_nr = m_seq_nr;
// when we time out, the cwnd is reset to 1 MSS, which means we
// need to ramp it up quickly again. enter slow start mode. This time
// we're very likely to have an ssthres set, which will make us leave
// slow start before inducing more delay or loss.
m_slow_start = true;
UTP_LOGV("%8p: slow_start -> 1\n", static_cast<void*>(this));
// we need to go one past m_seq_nr to cover the case // we need to go one past m_seq_nr to cover the case
// where we just sent a SYN packet and then adjusted for // where we just sent a SYN packet and then adjusted for
// the uTorrent sequence number reuse // the uTorrent sequence number reuse

View File

@ -257,6 +257,6 @@ TORRENT_TEST(settings_pack_abi)
TEST_EQUAL(settings_pack::max_http_recv_buffer_size, settings_pack::int_type_base + 115); TEST_EQUAL(settings_pack::max_http_recv_buffer_size, settings_pack::int_type_base + 115);
TEST_EQUAL(settings_pack::web_seed_name_lookup_retry, settings_pack::int_type_base + 128); TEST_EQUAL(settings_pack::web_seed_name_lookup_retry, settings_pack::int_type_base + 128);
TEST_EQUAL(settings_pack::close_file_interval, settings_pack::int_type_base + 129); TEST_EQUAL(settings_pack::close_file_interval, settings_pack::int_type_base + 129);
TEST_EQUAL(settings_pack::max_web_seed_connections, settings_pack::int_type_base + 130); TEST_EQUAL(settings_pack::max_web_seed_connections, settings_pack::int_type_base + 131);
TEST_EQUAL(settings_pack::resolver_cache_timeout, settings_pack::int_type_base + 131); TEST_EQUAL(settings_pack::resolver_cache_timeout, settings_pack::int_type_base + 132);
} }