fix an old use of posix_category. make http_connection translate IPs into proper endpoints when connecting over socks (instead of passing the IP on as a hostname string). add test coverage
This commit is contained in:
parent
92236a9923
commit
e3dad98fbe
|
@ -111,6 +111,17 @@ public:
|
||||||
|
|
||||||
void set_dst_name(std::string const& host)
|
void set_dst_name(std::string const& host)
|
||||||
{
|
{
|
||||||
|
// TODO: 3 enable this assert and fix remaining causes of it triggering
|
||||||
|
/*
|
||||||
|
#if TORRENT_USE_ASSERTS
|
||||||
|
error_code ec;
|
||||||
|
address::from_string(host, ec);
|
||||||
|
// if this assert trips, set_dst_name() is called wth an IP address rather
|
||||||
|
// than a hostname. Instead, resolve the IP into an address and pass it to
|
||||||
|
// async_connect instead
|
||||||
|
TORRENT_ASSERT(ec);
|
||||||
|
#endif
|
||||||
|
*/
|
||||||
m_dst_name = host;
|
m_dst_name = host;
|
||||||
if (m_dst_name.size() > 255)
|
if (m_dst_name.size() > 255)
|
||||||
m_dst_name.resize(255);
|
m_dst_name.resize(255);
|
||||||
|
|
|
@ -167,7 +167,7 @@ void print_http_header(std::map<std::string, std::string> const& headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_test(settings_pack::proxy_type_t proxy_type, std::string url, int expect_size, int expect_status
|
void run_test(lt::aux::proxy_settings ps, std::string url, int expect_size, int expect_status
|
||||||
, boost::system::error_condition expect_error, std::vector<int> expect_counters);
|
, boost::system::error_condition expect_error, std::vector<int> expect_counters);
|
||||||
|
|
||||||
enum expect_counters
|
enum expect_counters
|
||||||
|
@ -184,58 +184,79 @@ enum expect_counters
|
||||||
num_counters
|
num_counters
|
||||||
};
|
};
|
||||||
|
|
||||||
void run_suite(settings_pack::proxy_type_t proxy_type)
|
void run_suite(lt::aux::proxy_settings ps)
|
||||||
{
|
{
|
||||||
std::string url_base = "http://10.0.0.2:8080";
|
std::string url_base = "http://10.0.0.2:8080";
|
||||||
|
|
||||||
run_test(proxy_type, url_base + "/test_file", 1337, 200, error_condition(), { 1, 1, 1});
|
run_test(ps, url_base + "/test_file", 1337, 200, error_condition(), { 1, 1, 1});
|
||||||
|
|
||||||
run_test(proxy_type, url_base + "/non-existent", 0, 404, error_condition(), { 1, 1 });
|
run_test(ps, url_base + "/non-existent", 0, 404, error_condition(), { 1, 1 });
|
||||||
run_test(proxy_type, url_base + "/redirect", 1337, 200, error_condition(), { 2, 1, 1, 1 });
|
run_test(ps, url_base + "/redirect", 1337, 200, error_condition(), { 2, 1, 1, 1 });
|
||||||
run_test(proxy_type, url_base + "/relative/redirect", 1337, 200, error_condition(), {2, 1, 1, 0, 1});
|
run_test(ps, url_base + "/relative/redirect", 1337, 200, error_condition(), {2, 1, 1, 0, 1});
|
||||||
|
|
||||||
run_test(proxy_type, url_base + "/infinite/redirect", 0, 301
|
run_test(ps, url_base + "/infinite/redirect", 0, 301
|
||||||
, error_condition(asio::error::eof, asio::error::get_misc_category()), {6, 1, 0, 0, 0, 6});
|
, error_condition(asio::error::eof, asio::error::get_misc_category()), {6, 1, 0, 0, 0, 6});
|
||||||
|
|
||||||
run_test(proxy_type, url_base + "/chunked_encoding", 1337, 200, error_condition(), { 1, 1, 0, 0, 0, 0, 1});
|
run_test(ps, url_base + "/chunked_encoding", 1337, 200, error_condition(), { 1, 1, 0, 0, 0, 0, 1});
|
||||||
|
|
||||||
// we are on an IPv4 host, we can't connect to IPv6 addresses, make sure that
|
// we are on an IPv4 host, we can't connect to IPv6 addresses, make sure that
|
||||||
// error is correctly propagated
|
// error is correctly propagated
|
||||||
// with socks5 we would be able to do this, assuming the socks server
|
// with socks5 we would be able to do this, assuming the socks server
|
||||||
// supported it, but the current socks implementation in libsimulator does
|
// supported it, but the current socks implementation in libsimulator does
|
||||||
// not support IPv6
|
// not support IPv6
|
||||||
if (proxy_type != settings_pack::socks5)
|
if (ps.type != settings_pack::socks5)
|
||||||
{
|
{
|
||||||
run_test(proxy_type, "http://[ff::dead:beef]:8080/test_file", 0, -1
|
run_test(ps, "http://[ff::dead:beef]:8080/test_file", 0, -1
|
||||||
, error_condition(boost::system::errc::address_family_not_supported, generic_category())
|
, error_condition(boost::system::errc::address_family_not_supported, generic_category())
|
||||||
, {0,1});
|
, {0,1});
|
||||||
}
|
}
|
||||||
|
|
||||||
// there is no node at 10.0.0.10, this should fail with connection refused
|
// there is no node at 10.0.0.10, this should fail with connection refused
|
||||||
run_test(proxy_type, "http://10.0.0.10:8080/test_file", 0, -1,
|
run_test(ps, "http://10.0.0.10:8080/test_file", 0, -1,
|
||||||
error_condition(boost::system::errc::connection_refused, generic_category())
|
error_condition(boost::system::errc::connection_refused, generic_category())
|
||||||
, {0,1});
|
, {0,1});
|
||||||
|
|
||||||
// this hostname will resolve to multiple IPs, all but one that we cannot
|
// TODO: 3 add support for "domain name" address type in libsimulator's socks
|
||||||
// connect to and the second one where we'll get the test file response. Make
|
// proxy. Also, make sure we can assert that raw IPs still are passed on to
|
||||||
// sure the http_connection correcly tries the second IP if the first one
|
// the proxy server as IPs, and not as hostnames
|
||||||
// fails.
|
if (ps.proxy_hostnames == false)
|
||||||
run_test(proxy_type, "http://try-next.com:8080/test_file", 1337, 200
|
{
|
||||||
, error_condition(), { 1, 1, 1});
|
// this hostname will resolve to multiple IPs, all but one that we cannot
|
||||||
|
// connect to and the second one where we'll get the test file response. Make
|
||||||
|
// sure the http_connection correcly tries the second IP if the first one
|
||||||
|
// fails.
|
||||||
|
run_test(ps, "http://try-next.com:8080/test_file", 1337, 200
|
||||||
|
, error_condition(), { 1, 1, 1});
|
||||||
|
|
||||||
// make sure hostname lookup failures are passed through correctly
|
// make sure hostname lookup failures are passed through correctly
|
||||||
run_test(proxy_type, "http://non-existent.com/test_file", 0, -1
|
run_test(ps, "http://non-existent.com/test_file", 0, -1
|
||||||
, error_condition(asio::error::host_not_found, boost::asio::error::get_netdb_category()), { 0, 1});
|
, error_condition(asio::error::host_not_found, boost::asio::error::get_netdb_category()), { 0, 1});
|
||||||
|
}
|
||||||
|
|
||||||
// make sure we handle gzipped content correctly
|
// make sure we handle gzipped content correctly
|
||||||
run_test(proxy_type, url_base + "/test_file.gz", 1337, 200, error_condition(), { 1, 1, 0, 0, 0, 0, 0, 1});
|
run_test(ps, url_base + "/test_file.gz", 1337, 200, error_condition(), { 1, 1, 0, 0, 0, 0, 0, 1});
|
||||||
|
|
||||||
// TODO: 2 test basic-auth
|
// TODO: 2 test basic-auth
|
||||||
// TODO: 2 test https
|
// TODO: 2 test https
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_test(settings_pack::proxy_type_t proxy_type, std::string url, int expect_size, int expect_status
|
lt::aux::proxy_settings make_proxy_settings(lt::settings_pack::proxy_type_t proxy_type)
|
||||||
|
{
|
||||||
|
lt::aux::proxy_settings ps;
|
||||||
|
ps.type = proxy_type;
|
||||||
|
if (proxy_type != settings_pack::none)
|
||||||
|
{
|
||||||
|
ps.hostname = "50.50.50.50";
|
||||||
|
ps.port = 4444;
|
||||||
|
ps.username = "testuser";
|
||||||
|
ps.password = "testpass";
|
||||||
|
ps.proxy_hostnames = false;
|
||||||
|
}
|
||||||
|
return ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_test(lt::aux::proxy_settings ps, std::string url, int expect_size, int expect_status
|
||||||
, boost::system::error_condition expect_error, std::vector<int> expect_counters)
|
, boost::system::error_condition expect_error, std::vector<int> expect_counters)
|
||||||
{
|
{
|
||||||
using sim::asio::ip::address_v4;
|
using sim::asio::ip::address_v4;
|
||||||
|
@ -251,19 +272,7 @@ void run_test(settings_pack::proxy_type_t proxy_type, std::string url, int expec
|
||||||
lt::resolver res(ios);
|
lt::resolver res(ios);
|
||||||
|
|
||||||
sim::http_server http(web_server, 8080);
|
sim::http_server http(web_server, 8080);
|
||||||
sim::socks_server socks(proxy_ios, 4444, proxy_type == settings_pack::socks4 ? 4 : 5);
|
sim::socks_server socks(proxy_ios, 4444, ps.type == settings_pack::socks4 ? 4 : 5);
|
||||||
|
|
||||||
lt::aux::proxy_settings ps;
|
|
||||||
if (proxy_type != settings_pack::none)
|
|
||||||
{
|
|
||||||
ps.hostname = "50.50.50.50";
|
|
||||||
ps.port = 4444;
|
|
||||||
ps.username = "testuser";
|
|
||||||
ps.password = "testpass";
|
|
||||||
ps.type = proxy_type;
|
|
||||||
ps.proxy_hostnames = false;
|
|
||||||
// TODO: 2 also test proxying host names, and verify they are in fact proxied
|
|
||||||
}
|
|
||||||
|
|
||||||
char data_buffer[4000];
|
char data_buffer[4000];
|
||||||
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
|
||||||
|
@ -379,17 +388,27 @@ void run_test(settings_pack::proxy_type_t proxy_type, std::string url, int expec
|
||||||
|
|
||||||
TORRENT_TEST(http_connection)
|
TORRENT_TEST(http_connection)
|
||||||
{
|
{
|
||||||
run_suite(settings_pack::none);
|
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::none);
|
||||||
|
run_suite(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(http_connection_socks4)
|
TORRENT_TEST(http_connection_socks4)
|
||||||
{
|
{
|
||||||
run_suite(settings_pack::socks4);
|
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::socks4);
|
||||||
|
run_suite(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(http_connection_socks5)
|
TORRENT_TEST(http_connection_socks5)
|
||||||
{
|
{
|
||||||
run_suite(settings_pack::socks5);
|
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::socks5);
|
||||||
|
run_suite(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
TORRENT_TEST(http_connection_socks5_proxy_names)
|
||||||
|
{
|
||||||
|
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::socks5);
|
||||||
|
ps.proxy_hostnames = true;
|
||||||
|
run_suite(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
TORRENT_TEST(http_connection_socks_error)
|
TORRENT_TEST(http_connection_socks_error)
|
||||||
|
|
|
@ -379,6 +379,9 @@ void http_connection::start(std::string const& hostname, int port
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_endpoints.clear();
|
||||||
|
m_next_ep = 0;
|
||||||
|
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
if (is_i2p)
|
if (is_i2p)
|
||||||
{
|
{
|
||||||
|
@ -395,9 +398,6 @@ void http_connection::start(std::string const& hostname, int port
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// TODO: 3 if hostname is in fact an IP address (v4 or v6), we should go
|
|
||||||
// straight to connecting, regardless of proxy_hostname is enabled or not
|
|
||||||
if (ps && ps->proxy_hostnames
|
if (ps && ps->proxy_hostnames
|
||||||
&& (ps->type == settings_pack::socks5
|
&& (ps->type == settings_pack::socks5
|
||||||
|| ps->type == settings_pack::socks5_pw))
|
|| ps->type == settings_pack::socks5_pw))
|
||||||
|
@ -412,8 +412,6 @@ void http_connection::start(std::string const& hostname, int port
|
||||||
#if defined TORRENT_ASIO_DEBUGGING
|
#if defined TORRENT_ASIO_DEBUGGING
|
||||||
add_outstanding_async("http_connection::on_resolve");
|
add_outstanding_async("http_connection::on_resolve");
|
||||||
#endif
|
#endif
|
||||||
m_endpoints.clear();
|
|
||||||
m_next_ep = 0;
|
|
||||||
m_resolver.async_resolve(hostname, m_resolve_flags
|
m_resolver.async_resolve(hostname, m_resolve_flags
|
||||||
, boost::bind(&http_connection::on_resolve
|
, boost::bind(&http_connection::on_resolve
|
||||||
, me, _1, _2));
|
, me, _1, _2));
|
||||||
|
@ -579,19 +577,32 @@ void http_connection::connect()
|
||||||
&& (m_proxy.type == settings_pack::socks5
|
&& (m_proxy.type == settings_pack::socks5
|
||||||
|| m_proxy.type == settings_pack::socks5_pw))
|
|| m_proxy.type == settings_pack::socks5_pw))
|
||||||
{
|
{
|
||||||
// we're using a socks proxy and we're resolving
|
// test to see if m_hostname really just is an IP (and not a hostname). If it
|
||||||
// hostnames through it
|
// is, ec will be represent "success". If so, don't set it as the socks5
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
// hostname, just connect to the IP
|
||||||
if (m_ssl)
|
error_code ec;
|
||||||
|
address adr = address::from_string(m_hostname, ec);
|
||||||
|
|
||||||
|
if (ec)
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_sock.get<ssl_stream<socks5_stream> >());
|
// we're using a socks proxy and we're resolving
|
||||||
m_sock.get<ssl_stream<socks5_stream> >()->next_layer().set_dst_name(m_hostname);
|
// hostnames through it
|
||||||
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
|
if (m_ssl)
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_sock.get<ssl_stream<socks5_stream> >());
|
||||||
|
m_sock.get<ssl_stream<socks5_stream> >()->next_layer().set_dst_name(m_hostname);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
TORRENT_ASSERT(m_sock.get<socks5_stream>());
|
||||||
|
m_sock.get<socks5_stream>()->set_dst_name(m_hostname);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
TORRENT_ASSERT(m_sock.get<socks5_stream>());
|
m_endpoints[0].address(adr);
|
||||||
m_sock.get<socks5_stream>()->set_dst_name(m_hostname);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ struct test_storage : default_storage
|
||||||
{
|
{
|
||||||
std::cerr << "storage written: " << m_written << " limit: " << m_limit << std::endl;
|
std::cerr << "storage written: " << m_written << " limit: " << m_limit << std::endl;
|
||||||
error_code ec;
|
error_code ec;
|
||||||
ec = error_code(boost::system::errc::no_space_on_device, get_posix_category());
|
ec = error_code(boost::system::errc::no_space_on_device, generic_category());
|
||||||
se.ec = ec;
|
se.ec = ec;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue