merged RC_1_1 into master
This commit is contained in:
commit
8b067310b1
|
@ -740,7 +740,11 @@ if(developer-options)
|
|||
ENABLED TORRENT_PROFILE_CALLS=1)
|
||||
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)
|
||||
|
||||
|
|
|
@ -47,6 +47,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_UTP_LOG_ENABLE
|
||||
#include "libtorrent/utp_stream.hpp"
|
||||
#endif
|
||||
|
||||
#include "libtorrent/torrent_info.hpp"
|
||||
#include "libtorrent/announce_entry.hpp"
|
||||
#include "libtorrent/entry.hpp"
|
||||
|
@ -1022,8 +1026,13 @@ CLIENT OPTIONS
|
|||
previous command line options, so be sure to specify this first
|
||||
-G Add torrents in seed-mode (i.e. assume all pieces
|
||||
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
|
||||
--<name-of-setting>=<value>
|
||||
set the libtorrent setting <name> to <value>
|
||||
|
@ -1190,6 +1199,11 @@ example alert_masks:
|
|||
case 'G': seed_mode = true; --i; break;
|
||||
case 's': save_path = make_absolute_path(arg); 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 'D': torrent_download_limit = atoi(arg) * 1000; break;
|
||||
case 'm': monitor_dir = make_absolute_path(arg); break;
|
||||
|
|
|
@ -78,8 +78,9 @@ namespace libtorrent {
|
|||
|
||||
packet_ptr insert(index_type idx, packet_ptr value);
|
||||
|
||||
int size() const
|
||||
{ return m_size; }
|
||||
int size() const { return m_size; }
|
||||
|
||||
bool empty() const { return m_size == 0; }
|
||||
|
||||
std::uint32_t capacity() const
|
||||
{ return m_capacity; }
|
||||
|
|
|
@ -1659,6 +1659,11 @@ namespace libtorrent {
|
|||
// systems.
|
||||
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
|
||||
// given time.
|
||||
max_web_seed_connections,
|
||||
|
|
|
@ -107,6 +107,7 @@ namespace libtorrent {
|
|||
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 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);
|
||||
int num_sockets() const { return int(m_utp_sockets.size()); }
|
||||
|
|
|
@ -285,7 +285,7 @@ struct sim_config : sim::default_config
|
|||
{
|
||||
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)
|
||||
result.push_back(address_v6::from_string("ff::dead:beef"));
|
||||
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::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"));
|
||||
|
||||
// listen on port 8080
|
||||
|
@ -370,7 +370,7 @@ void test_ipv6_support(char const* listen_interfaces
|
|||
for (int i = 0; i < num_interfaces; i++)
|
||||
{
|
||||
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));
|
||||
std::snprintf(ep, sizeof(ep), "ffff::1337:%d", i + 1);
|
||||
ips.push_back(address::from_string(ep));
|
||||
|
@ -428,7 +428,7 @@ void test_udpv6_support(char const* listen_interfaces
|
|||
sim_config 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"));
|
||||
|
||||
int v4_announces = 0;
|
||||
|
@ -442,7 +442,7 @@ void test_udpv6_support(char const* listen_interfaces
|
|||
for (int i = 0; i < num_interfaces; i++)
|
||||
{
|
||||
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));
|
||||
std::snprintf(ep, sizeof(ep), "ffff::1337:%d", i + 1);
|
||||
ips.push_back(address::from_string(ep));
|
||||
|
@ -555,7 +555,7 @@ TORRENT_TEST(ipv6_support_bind_v6_any)
|
|||
|
||||
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)
|
||||
|
@ -570,12 +570,12 @@ TORRENT_TEST(ipv6_support_bind_v6_3interfaces)
|
|||
|
||||
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)
|
||||
{
|
||||
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
|
||||
|
@ -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
|
||||
// wait until test2 is called.
|
||||
// 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.
|
||||
template <typename Setup, typename Announce, typename Test1, typename 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::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"));
|
||||
|
||||
// listen on port 8080
|
||||
|
@ -606,7 +606,7 @@ void tracker_test(Setup setup, Announce a, Test1 test1, Test2 test2
|
|||
|
||||
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") });
|
||||
lt::settings_pack sett = settings();
|
||||
std::unique_ptr<lt::session> ses(new lt::session(sett, ios));
|
||||
|
@ -976,7 +976,7 @@ TORRENT_TEST(tracker_ipv6_argument)
|
|||
{
|
||||
settings_pack pack;
|
||||
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);
|
||||
p.ti = make_torrent(true);
|
||||
return 60;
|
||||
|
@ -1000,7 +1000,7 @@ TORRENT_TEST(tracker_ipv6_argument)
|
|||
std::string::size_type const pos = req.find("&ipv4=");
|
||||
TEST_CHECK(pos != std::string::npos || stop_event);
|
||||
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";
|
||||
}
|
||||
|
|
|
@ -341,6 +341,7 @@ constexpr int CLOSE_FILE_INTERVAL = 0;
|
|||
SET(urlseed_max_request_bytes, 16 * 1024 * 1024, nullptr),
|
||||
SET(web_seed_name_lookup_retry, 1800, nullptr),
|
||||
SET(close_file_interval, CLOSE_FILE_INTERVAL, nullptr),
|
||||
SET(utp_cwnd_reduce_timer, 100, nullptr),
|
||||
SET(max_web_seed_connections, 3, nullptr),
|
||||
SET(resolver_cache_timeout, 1200, &session_impl::update_resolver_cache_timeout),
|
||||
}});
|
||||
|
|
|
@ -2832,9 +2832,15 @@ bool is_downloading_state(int const st)
|
|||
tcp::endpoint const ep = s.get_local_endpoint();
|
||||
if (is_any(ep.address())) return;
|
||||
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
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -289,7 +289,7 @@ struct utp_socket_impl
|
|||
bool consume_incoming_data(
|
||||
utp_header const* ph, std::uint8_t const* ptr, int payload_size, time_point now);
|
||||
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);
|
||||
|
||||
|
@ -394,6 +394,10 @@ struct utp_socket_impl
|
|||
// the last time we stepped the timestamp history
|
||||
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
|
||||
// value, to get the true number of bytes, shift right 16 bits
|
||||
// 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 (m_outbuf.empty()) m_duplicate_acks = 0;
|
||||
|
||||
// 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
|
||||
// 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);
|
||||
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);
|
||||
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))
|
||||
{
|
||||
m_duplicate_acks = 0;
|
||||
m_fast_resend_seq_nr = (pkt_seq + 1) & ACK_MASK;
|
||||
}
|
||||
experienced_loss(pkt_seq, now);
|
||||
cut_cwnd = false;
|
||||
}
|
||||
|
||||
if (cut_cwnd)
|
||||
if (resend_packet(p, true))
|
||||
{
|
||||
experienced_loss(pkt_seq);
|
||||
cut_cwnd = false;
|
||||
m_duplicate_acks = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -2271,11 +2278,17 @@ void utp_socket_impl::experienced_loss(std::uint32_t const seq_nr)
|
|||
// same packet again, ignore it.
|
||||
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
|
||||
m_cwnd = std::max(m_cwnd * m_sm.loss_multiplier() / 100
|
||||
, std::int64_t(m_mtu) * (1 << 16));
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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();
|
||||
if (m_outbuf.empty()) m_duplicate_acks = 0;
|
||||
}
|
||||
|
||||
// look for extended headers
|
||||
|
@ -2969,7 +2985,9 @@ bool utp_socket_impl::incoming_packet(span<std::uint8_t const> buf
|
|||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
TORRENT_ASSERT(!compare_less_wrap(m_seq_nr, m_acked_seq_nr, ACK_MASK));
|
||||
|
||||
#if TORRENT_UTP_LOG
|
||||
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()
|
||||
, int(total_milliseconds(m_timeout - receive_time))
|
||||
, int(total_microseconds(receive_time.time_since_epoch()))
|
||||
, (m_seq_nr - m_acked_seq_nr) & ACK_MASK
|
||||
, m_outbuf.size()
|
||||
, m_mtu
|
||||
, their_delay_base
|
||||
, std::uint32_t(m_reply_micro)
|
||||
|
@ -3532,7 +3552,20 @@ void utp_socket_impl::tick(time_point const now)
|
|||
if (now > m_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
|
||||
// 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.
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3567,52 +3602,45 @@ void utp_socket_impl::tick(time_point const now)
|
|||
return;
|
||||
}
|
||||
|
||||
if (((m_acked_seq_nr + 1) & ACK_MASK) == m_mtu_seq
|
||||
&& ((m_seq_nr - 1) & ACK_MASK) == m_mtu_seq
|
||||
&& m_mtu_seq != 0)
|
||||
if (!ignore_loss)
|
||||
{
|
||||
// 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();
|
||||
// set cwnd to 1 MSS
|
||||
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));
|
||||
|
||||
// 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
|
||||
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
|
||||
// where we just sent a SYN packet and then adjusted for
|
||||
// the uTorrent sequence number reuse
|
||||
|
|
|
@ -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::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::max_web_seed_connections, settings_pack::int_type_base + 130);
|
||||
TEST_EQUAL(settings_pack::resolver_cache_timeout, settings_pack::int_type_base + 131);
|
||||
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 + 132);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue