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)
|
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)
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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; }
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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()); }
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
@ -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),
|
||||||
}});
|
}});
|
||||||
|
|
|
@ -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());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue