merged RC_1_1 into master

This commit is contained in:
arvidn 2017-05-12 21:46:45 -04:00
commit e0fa1cd247
17 changed files with 108 additions and 48 deletions

View File

@ -73,6 +73,9 @@
* require C++11 to build libtorrent * require C++11 to build libtorrent
* bind upnp requests to correct local address
* save resume data when removing web seeds
* fix proxying of https connections
* fix race condition in disk I/O storage class * fix race condition in disk I/O storage class
* fix http connection timeout on multi-homed hosts * fix http connection timeout on multi-homed hosts
* removed depdendency on boost::uintptr_t for better compatibility * removed depdendency on boost::uintptr_t for better compatibility

View File

@ -100,7 +100,7 @@ struct TORRENT_EXTRA_EXPORT http_connection
std::string m_sendbuffer; std::string m_sendbuffer;
void get(std::string const& url, time_duration timeout = seconds(30) void get(std::string const& url, time_duration timeout = seconds(30)
, int prio = 0, aux::proxy_settings const* ps = 0, int handle_redirects = 5 , int prio = 0, aux::proxy_settings const* ps = NULL, int handle_redirects = 5
, std::string const& user_agent = std::string() , std::string const& user_agent = std::string()
, boost::optional<address> const& bind_addr = boost::optional<address>() , boost::optional<address> const& bind_addr = boost::optional<address>()
, int resolve_flags = 0, std::string const& auth_ = std::string() , int resolve_flags = 0, std::string const& auth_ = std::string()
@ -110,7 +110,7 @@ struct TORRENT_EXTRA_EXPORT http_connection
); );
void start(std::string const& hostname, int port void start(std::string const& hostname, int port
, time_duration timeout, int prio = 0, aux::proxy_settings const* ps = 0 , time_duration timeout, int prio = 0, aux::proxy_settings const* ps = NULL
, bool ssl = false, int handle_redirect = 5 , bool ssl = false, int handle_redirect = 5
, boost::optional<address> const& bind_addr = boost::optional<address>() , boost::optional<address> const& bind_addr = boost::optional<address>()
, int resolve_flags = 0 , int resolve_flags = 0

View File

@ -55,7 +55,7 @@ struct TORRENT_EXTRA_EXPORT natpmp
// maps the ports, if a port is set to 0 // maps the ports, if a port is set to 0
// it will not be mapped // it will not be mapped
int add_mapping(aux::portmap_protocol p, int external_port, int local_port); int add_mapping(aux::portmap_protocol p, int external_port, tcp::endpoint local_ep);
void delete_mapping(int mapping_index); void delete_mapping(int mapping_index);
bool get_mapping(int mapping_index, int& local_port, int& external_port bool get_mapping(int mapping_index, int& local_port, int& external_port
, aux::portmap_protocol& protocol) const; , aux::portmap_protocol& protocol) const;

View File

@ -249,8 +249,8 @@ protected:
bool handle_error(error_code const& e, handler_type const& h); bool handle_error(error_code const& e, handler_type const& h);
tcp::socket m_sock; tcp::socket m_sock;
std::string m_hostname; std::string m_hostname; // proxy host
int m_port; int m_port; // proxy port
endpoint_type m_remote_endpoint; endpoint_type m_remote_endpoint;

View File

@ -172,13 +172,13 @@ struct TORRENT_EXTRA_EXPORT upnp final
// portmap_alert_ respectively. If The mapping fails immediately, the return value // portmap_alert_ respectively. If The mapping fails immediately, the return value
// is -1, which means failure. There will not be any error alert notification for // is -1, which means failure. There will not be any error alert notification for
// mappings that fail with a -1 return value. // mappings that fail with a -1 return value.
int add_mapping(aux::portmap_protocol p, int external_port, int local_port); int add_mapping(aux::portmap_protocol p, int external_port, tcp::endpoint local_ep);
// This function removes a port mapping. ``mapping_index`` is the index that refers // This function removes a port mapping. ``mapping_index`` is the index that refers
// to the mapping you want to remove, which was returned from add_mapping(). // to the mapping you want to remove, which was returned from add_mapping().
void delete_mapping(int mapping_index); void delete_mapping(int mapping_index);
bool get_mapping(int mapping_index, int& local_port, int& external_port bool get_mapping(int mapping_index, tcp::endpoint& local_ep, int& external_port
, aux::portmap_protocol& protocol) const; , aux::portmap_protocol& protocol) const;
void discover_device(); void discover_device();
@ -249,7 +249,7 @@ private:
{ {
aux::portmap_protocol protocol = aux::portmap_protocol::none; aux::portmap_protocol protocol = aux::portmap_protocol::none;
int external_port = 0; int external_port = 0;
int local_port = 0; tcp::endpoint local_ep;
}; };
struct mapping_t struct mapping_t
@ -263,7 +263,7 @@ private:
// the local port for this mapping. If this is set // the local port for this mapping. If this is set
// to 0, the mapping is not in use // to 0, the mapping is not in use
int local_port = 0; tcp::endpoint local_ep;
// the external (on the NAT router) port // the external (on the NAT router) port
// for the mapping. This is the port we // for the mapping. This is the port we

@ -1 +1 @@
Subproject commit 0e8d74baf1f6d9db19857eaa87734faecd530f94 Subproject commit 70feadef80dc76ae6d5e7c2f92334377d698dd7d

View File

@ -602,6 +602,53 @@ TORRENT_TEST(http_connection_http_error)
test_proxy_failure(settings_pack::http); test_proxy_failure(settings_pack::http);
} }
// Requests a proxied SSL connection. This test just ensures that the correct CONNECT request
// is sent to the proxy server.
TORRENT_TEST(http_connection_ssl_proxy)
{
using sim::asio::ip::address_v4;
sim_config network_cfg;
sim::simulation sim{network_cfg};
sim::asio::io_service client_ios(sim, address_v4::from_string("10.0.0.1"));
sim::asio::io_service proxy_ios(sim, address_v4::from_string("50.50.50.50"));
lt::resolver res(client_ios);
sim::http_server http_proxy(proxy_ios, 4445);
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::http);
int client_counter = 0;
int proxy_counter = 0;
http_proxy.register_handler("10.0.0.2:8080"
, [&proxy_counter](std::string method, std::string req, std::map<std::string, std::string>& headers)
{
proxy_counter++;
TEST_EQUAL(method, "CONNECT");
return sim::send_response(403, "Not supported", 1337);
});
auto h = std::make_shared<http_connection>(client_ios
, res
, [&client_counter](error_code const& ec, http_parser const& parser
, char const* data, const int size, http_connection& c)
{
client_counter++;
TEST_EQUAL(ec, boost::asio::error::operation_not_supported);
});
h->start("10.0.0.2", 8080, seconds(1), 0, &ps, true /*ssl*/);
error_code e;
sim.run(e);
TEST_EQUAL(client_counter, 1);
TEST_EQUAL(proxy_counter, 1);
if (e) std::cerr << " run failed: " << e.message() << std::endl;
TEST_EQUAL(e, error_code());
}
// TODO: test http proxy with password // TODO: test http proxy with password
// TODO: test socks5 with password // TODO: test socks5 with password
// TODO: test SSL // TODO: test SSL

View File

@ -64,15 +64,7 @@ namespace libtorrent {
// send CONNECT // send CONNECT
std::back_insert_iterator<std::vector<char>> p(m_buffer); std::back_insert_iterator<std::vector<char>> p(m_buffer);
std::string endpoint; std::string const endpoint = print_endpoint(m_remote_endpoint);
if (!m_hostname.empty())
{
endpoint = m_hostname + ':' + to_string(m_remote_endpoint.port()).data();
}
else
{
endpoint = print_endpoint(m_remote_endpoint);
}
write_string("CONNECT " + endpoint + " HTTP/1.0\r\n", p); write_string("CONNECT " + endpoint + " HTTP/1.0\r\n", p);
if (!m_user.empty()) if (!m_user.empty())
{ {

View File

@ -229,7 +229,7 @@ void natpmp::delete_mapping(int const index)
} }
int natpmp::add_mapping(portmap_protocol const p, int const external_port int natpmp::add_mapping(portmap_protocol const p, int const external_port
, int const local_port) , tcp::endpoint const local_ep)
{ {
TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(is_single_thread());
@ -244,7 +244,7 @@ int natpmp::add_mapping(portmap_protocol const p, int const external_port
} }
i->protocol = p; i->protocol = p;
i->external_port = external_port; i->external_port = external_port;
i->local_port = local_port; i->local_port = local_ep.port();
i->act = mapping_t::action::add; i->act = mapping_t::action::add;
int const mapping_index = int(i - m_mappings.begin()); int const mapping_index = int(i - m_mappings.begin());

View File

@ -1528,7 +1528,7 @@ namespace {
} }
#endif // TORRENT_DISABLE_LOGGING #endif // TORRENT_DISABLE_LOGGING
} }
#endif // TORRENT_WINDOWS #else
{ {
// this is best-effort. ignore errors // this is best-effort. ignore errors
@ -1542,6 +1542,7 @@ namespace {
} }
#endif // TORRENT_DISABLE_LOGGING #endif // TORRENT_DISABLE_LOGGING
} }
#endif // TORRENT_WINDOWS
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
if (bind_ep.address().is_v6()) if (bind_ep.address().is_v6())
@ -2200,7 +2201,12 @@ namespace {
// only update this mapping if we actually have a socket listening // only update this mapping if we actually have a socket listening
if (ep != EndpointType()) if (ep != EndpointType())
map_handle = m.add_mapping(protocol, ep.port(), ep.port()); map_handle = m.add_mapping(protocol, ep.port(), ep);
}
tcp::endpoint to_tcp(udp::endpoint const ep)
{
return tcp::endpoint(ep.address(), ep.port());
} }
} }
@ -2213,12 +2219,12 @@ namespace {
if ((mask & remap_natpmp) && m_natpmp) if ((mask & remap_natpmp) && m_natpmp)
{ {
map_port(*m_natpmp, portmap_protocol::tcp, tcp_ep, s.tcp_port_mapping[0]); map_port(*m_natpmp, portmap_protocol::tcp, tcp_ep, s.tcp_port_mapping[0]);
map_port(*m_natpmp, portmap_protocol::udp, udp_ep, s.udp_port_mapping[0]); map_port(*m_natpmp, portmap_protocol::udp, to_tcp(udp_ep), s.udp_port_mapping[0]);
} }
if ((mask & remap_upnp) && m_upnp) if ((mask & remap_upnp) && m_upnp)
{ {
map_port(*m_upnp, portmap_protocol::tcp, tcp_ep, s.tcp_port_mapping[1]); map_port(*m_upnp, portmap_protocol::tcp, tcp_ep, s.tcp_port_mapping[1]);
map_port(*m_upnp, portmap_protocol::udp, udp_ep, s.udp_port_mapping[1]); map_port(*m_upnp, portmap_protocol::udp, to_tcp(udp_ep), s.udp_port_mapping[1]);
} }
} }
@ -5011,8 +5017,9 @@ namespace {
{ {
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
s.set_option(exclusive_address_use(true), ec); s.set_option(exclusive_address_use(true), ec);
#endif #else
s.set_option(tcp::acceptor::reuse_address(true), ec); s.set_option(tcp::acceptor::reuse_address(true), ec);
#endif
// ignore errors because the underlying socket may not // ignore errors because the underlying socket may not
// be opened yet. This happens when we're routing through // be opened yet. This happens when we're routing through
// a proxy. In that case, we don't yet know the address of // a proxy. In that case, we don't yet know the address of
@ -6613,9 +6620,9 @@ namespace {
{ {
int ret = 0; int ret = 0;
if (m_upnp) ret = m_upnp->add_mapping(static_cast<portmap_protocol>(t), external_port if (m_upnp) ret = m_upnp->add_mapping(static_cast<portmap_protocol>(t), external_port
, local_port); , tcp::endpoint({}, static_cast<std::uint16_t>(local_port)));
if (m_natpmp) ret = m_natpmp->add_mapping(static_cast<portmap_protocol>(t), external_port if (m_natpmp) ret = m_natpmp->add_mapping(static_cast<portmap_protocol>(t), external_port
, local_port); , tcp::endpoint({}, static_cast<std::uint16_t>(local_port)));
return ret; return ret;
} }

View File

@ -9776,7 +9776,11 @@ namespace libtorrent {
auto const i = std::find_if(m_web_seeds.begin(), m_web_seeds.end() auto const i = std::find_if(m_web_seeds.begin(), m_web_seeds.end()
, [&] (web_seed_t const& w) { return w.url == url && w.type == type; }); , [&] (web_seed_t const& w) { return w.url == url && w.type == type; });
if (i != m_web_seeds.end()) remove_web_seed_iter(i); if (i != m_web_seeds.end())
{
remove_web_seed_iter(i);
set_need_save_resume();
}
} }
void torrent::disconnect_web_seed(peer_connection* p) void torrent::disconnect_web_seed(peer_connection* p)

View File

@ -433,8 +433,9 @@ void udp_socket::open(udp const& protocol, error_code& ec)
error_code err; error_code err;
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
m_socket.set_option(exclusive_address_use(true), err); m_socket.set_option(exclusive_address_use(true), err);
#endif #else
m_socket.set_option(boost::asio::socket_base::reuse_address(true), err); m_socket.set_option(boost::asio::socket_base::reuse_address(true), err);
#endif
} }
void udp_socket::bind(udp::endpoint const& ep, error_code& ec) void udp_socket::bind(udp::endpoint const& ep, error_code& ec)

View File

@ -182,7 +182,7 @@ void upnp::discover_device_impl()
// returns a reference to a mapping or -1 on failure // returns a reference to a mapping or -1 on failure
int upnp::add_mapping(portmap_protocol const p, int const external_port int upnp::add_mapping(portmap_protocol const p, int const external_port
, int const local_port) , tcp::endpoint const local_ep)
{ {
TORRENT_ASSERT(is_single_thread()); TORRENT_ASSERT(is_single_thread());
// external port 0 means _every_ port // external port 0 means _every_ port
@ -190,9 +190,9 @@ int upnp::add_mapping(portmap_protocol const p, int const external_port
#ifndef TORRENT_DISABLE_LOGGING #ifndef TORRENT_DISABLE_LOGGING
log("adding port map: [ protocol: %s ext_port: %u " log("adding port map: [ protocol: %s ext_port: %u "
"local_port: %u ] %s", (p == portmap_protocol::tcp?"tcp":"udp") "local_ep: %s ] %s", (p == portmap_protocol::tcp?"tcp":"udp")
, external_port , external_port
, local_port, m_disabled ? "DISABLED": ""); , print_endpoint(local_ep).c_str(), m_disabled ? "DISABLED": "");
#endif #endif
if (m_disabled) return -1; if (m_disabled) return -1;
@ -208,7 +208,7 @@ int upnp::add_mapping(portmap_protocol const p, int const external_port
mapping_it->protocol = p; mapping_it->protocol = p;
mapping_it->external_port = external_port; mapping_it->external_port = external_port;
mapping_it->local_port = local_port; mapping_it->local_ep = local_ep;
int const mapping_index = int(mapping_it - m_mappings.begin()); int const mapping_index = int(mapping_it - m_mappings.begin());
@ -224,7 +224,7 @@ int upnp::add_mapping(portmap_protocol const p, int const external_port
m.act = mapping_t::action::add; m.act = mapping_t::action::add;
m.protocol = p; m.protocol = p;
m.external_port = external_port; m.external_port = external_port;
m.local_port = local_port; m.local_ep = local_ep;
if (!d.service_namespace.empty()) update_map(d, mapping_index); if (!d.service_namespace.empty()) update_map(d, mapping_index);
} }
@ -242,8 +242,8 @@ void upnp::delete_mapping(int const mapping)
#ifndef TORRENT_DISABLE_LOGGING #ifndef TORRENT_DISABLE_LOGGING
log("deleting port map: [ protocol: %s ext_port: %u " log("deleting port map: [ protocol: %s ext_port: %u "
"local_port: %u ]", (m.protocol == portmap_protocol::tcp?"tcp":"udp"), m.external_port "local_ep: %s ]", (m.protocol == portmap_protocol::tcp?"tcp":"udp"), m.external_port
, m.local_port); , print_endpoint(m.local_ep).c_str());
#endif #endif
if (m.protocol == portmap_protocol::none) return; if (m.protocol == portmap_protocol::none) return;
@ -261,7 +261,7 @@ void upnp::delete_mapping(int const mapping)
} }
bool upnp::get_mapping(int const index bool upnp::get_mapping(int const index
, int& local_port , tcp::endpoint& local_ep
, int& external_port , int& external_port
, portmap_protocol& protocol) const , portmap_protocol& protocol) const
{ {
@ -270,7 +270,7 @@ bool upnp::get_mapping(int const index
if (index >= int(m_mappings.size()) || index < 0) return false; if (index >= int(m_mappings.size()) || index < 0) return false;
global_mapping_t const& m = m_mappings[index]; global_mapping_t const& m = m_mappings[index];
if (m.protocol == portmap_protocol::none) return false; if (m.protocol == portmap_protocol::none) return false;
local_port = m.local_port; local_ep = m.local_ep;
external_port = m.external_port; external_port = m.external_port;
protocol = m.protocol; protocol = m.protocol;
return true; return true;
@ -586,7 +586,7 @@ void upnp::on_reply(udp::endpoint const& from, char* buffer
{ {
mapping_t m; mapping_t m;
m.act = mapping_t::action::add; m.act = mapping_t::action::add;
m.local_port = j.local_port; m.local_ep = j.local_ep;
m.external_port = j.external_port; m.external_port = j.external_port;
m.protocol = j.protocol; m.protocol = j.protocol;
d.mapping.push_back(m); d.mapping.push_back(m);
@ -744,9 +744,9 @@ void upnp::create_port_mapping(http_connection& c, rootdevice& d, int const i)
"</u:%s></s:Body></s:Envelope>" "</u:%s></s:Body></s:Envelope>"
, soap_action, d.service_namespace.c_str(), d.mapping[i].external_port , soap_action, d.service_namespace.c_str(), d.mapping[i].external_port
, (d.mapping[i].protocol == portmap_protocol::udp ? "UDP" : "TCP") , (d.mapping[i].protocol == portmap_protocol::udp ? "UDP" : "TCP")
, d.mapping[i].local_port , d.mapping[i].local_ep.port()
, local_endpoint.c_str() , local_endpoint.c_str()
, m_user_agent.c_str(), local_endpoint.c_str(), d.mapping[i].local_port , m_user_agent.c_str(), local_endpoint.c_str(), d.mapping[i].local_ep.port()
, d.lease_duration, soap_action); , d.lease_duration, soap_action);
post(d, soap, soap_action); post(d, soap, soap_action);
@ -817,7 +817,7 @@ void upnp::update_map(rootdevice& d, int const i)
, std::bind(&upnp::create_port_mapping, self(), _1, std::ref(d), i)); , std::bind(&upnp::create_port_mapping, self(), _1, std::ref(d), i));
d.upnp_connection->start(d.hostname, d.port d.upnp_connection->start(d.hostname, d.port
, seconds(10), 1); , seconds(10), 1, NULL, false, 5, m.local_ep.address());
} }
else if (m.act == mapping_t::action::del) else if (m.act == mapping_t::action::del)
{ {
@ -828,7 +828,7 @@ void upnp::update_map(rootdevice& d, int const i)
, std::ref(d), i, _5), true, default_max_bottled_buffer_size , std::ref(d), i, _5), true, default_max_bottled_buffer_size
, std::bind(&upnp::delete_port_mapping, self(), std::ref(d), i)); , std::bind(&upnp::delete_port_mapping, self(), std::ref(d), i));
d.upnp_connection->start(d.hostname, d.port d.upnp_connection->start(d.hostname, d.port
, seconds(10), 1); , seconds(10), 1, NULL, false, 5, m.local_ep.address());
} }
m.act = mapping_t::action::none; m.act = mapping_t::action::none;

View File

@ -135,6 +135,7 @@ struct mock_dht_socket final : aux::session_listen_socket
tcp::endpoint m_local_endpoint; tcp::endpoint m_local_endpoint;
}; };
#if TORRENT_USE_IPV6
struct mock_dht_socket6 final : aux::session_listen_socket struct mock_dht_socket6 final : aux::session_listen_socket
{ {
address get_external_address() override { return m_external_address; } address get_external_address() override { return m_external_address; }
@ -143,6 +144,7 @@ struct mock_dht_socket6 final : aux::session_listen_socket
address m_external_address = addr6("2002::1"); address m_external_address = addr6("2002::1");
tcp::endpoint m_local_endpoint = tcp::endpoint(addr6("2002::1"), 6881); tcp::endpoint m_local_endpoint = tcp::endpoint(addr6("2002::1"), 6881);
}; };
#endif
node* get_foreign_node_stub(node_id const&, std::string const&) node* get_foreign_node_stub(node_id const&, std::string const&)
{ {

View File

@ -87,8 +87,9 @@ int main(int argc, char* argv[])
deadline_timer timer(ios); deadline_timer timer(ios);
int const tcp_map = natpmp_handler->add_mapping(portmap_protocol::tcp int const tcp_map = natpmp_handler->add_mapping(portmap_protocol::tcp
, atoi(argv[1]), atoi(argv[1])); , atoi(argv[1]), tcp::endpoint({}, atoi(argv[1])));
natpmp_handler->add_mapping(portmap_protocol::udp, atoi(argv[2]), atoi(argv[2])); natpmp_handler->add_mapping(portmap_protocol::udp, atoi(argv[2])
, tcp::endpoint({}, atoi(argv[2])));
error_code ec; error_code ec;
timer.expires_from_now(seconds(2), ec); timer.expires_from_now(seconds(2), ec);

View File

@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/bencode.hpp" #include "libtorrent/bencode.hpp"
#include "libtorrent/bdecode.hpp" #include "libtorrent/bdecode.hpp"
#include "libtorrent/hex.hpp" #include "libtorrent/hex.hpp"
#include "setup_transfer.hpp" // for addr6
#include "settings.hpp" #include "settings.hpp"
#include "test.hpp" #include "test.hpp"
@ -112,8 +113,10 @@ TORRENT_TEST(dht_state)
s.nids.emplace_back(addr4("0.0.0.0"), to_hash("0000000000000000000000000000000000000001")); s.nids.emplace_back(addr4("0.0.0.0"), to_hash("0000000000000000000000000000000000000001"));
s.nodes.push_back(uep("1.1.1.1", 1)); s.nodes.push_back(uep("1.1.1.1", 1));
s.nodes.push_back(uep("2.2.2.2", 2)); s.nodes.push_back(uep("2.2.2.2", 2));
#if TORRENT_USE_IPV6
// not important that IPv6 is disabled here // not important that IPv6 is disabled here
s.nids.emplace_back(addr6("::"), to_hash("0000000000000000000000000000000000000002")); s.nids.emplace_back(addr6("::"), to_hash("0000000000000000000000000000000000000002"));
#endif
session_params params(p); session_params params(p);
params.dht_settings = sett; params.dht_settings = sett;

View File

@ -198,8 +198,8 @@ void run_upnp_test(char const* root_filename, char const* router_model, char con
std::cout << "router: " << upnp_handler->router_model() << std::endl; std::cout << "router: " << upnp_handler->router_model() << std::endl;
TEST_EQUAL(upnp_handler->router_model(), router_model); TEST_EQUAL(upnp_handler->router_model(), router_model);
int mapping1 = upnp_handler->add_mapping(portmap_protocol::tcp, 500, 500); int const mapping1 = upnp_handler->add_mapping(portmap_protocol::tcp, 500, ep("127.0.0.1", 500));
int mapping2 = upnp_handler->add_mapping(portmap_protocol::udp, 501, 501); int const mapping2 = upnp_handler->add_mapping(portmap_protocol::udp, 501, ep("127.0.0.1", 501));
for (int i = 0; i < 40; ++i) for (int i = 0; i < 40; ++i)
{ {