Merge pull request #239 from arvidn/http_connection-sim

start of an http_connection test under the simulator
This commit is contained in:
Arvid Norberg
2015-11-24 00:41:10 -05:00
14 changed files with 550 additions and 100 deletions

View File

@@ -482,28 +482,11 @@ namespace libtorrent
TORRENT_EXPORT boost::system::error_category& get_http_category();
using boost::system::error_code;
// hidden
inline boost::system::error_category const& system_category()
#if BOOST_VERSION < 104400
{ return boost::system::get_system_category(); }
#else
{ return boost::system::system_category(); }
#endif
// hidden
inline boost::system::error_category const& get_posix_category()
#if BOOST_VERSION < 103600
{ return boost::system::get_posix_category(); }
#elif BOOST_VERSION < 104400
{ return boost::system::get_generic_category(); }
#else
{ return boost::system::generic_category(); }
#endif // BOOST_VERSION < 103600
using boost::system::error_condition;
// internal
inline boost::system::error_category const& generic_category()
{ return get_posix_category(); }
using boost::system::generic_category;
using boost::system::system_category;
#ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT libtorrent_exception: std::exception

View File

@@ -146,7 +146,7 @@ private:
, error_code const& e);
void on_assign_bandwidth(error_code const& e);
void callback(error_code e, char* data = 0, int size = 0);
void callback(error_code e, char* data = NULL, int size = 0);
std::vector<char> m_recvbuffer;

View File

@@ -111,6 +111,17 @@ public:
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;
if (m_dst_name.size() > 255)
m_dst_name.resize(255);
@@ -118,7 +129,6 @@ public:
void close(error_code& ec)
{
m_hostname.clear();
m_dst_name.clear();
proxy_base::close(ec);
}
@@ -126,7 +136,6 @@ public:
#ifndef BOOST_NO_EXCEPTIONS
void close()
{
m_hostname.clear();
m_dst_name.clear();
proxy_base::close();
}

View File

@@ -24,6 +24,7 @@ project
;
alias libtorrent-sims :
[ run test_http_connection.cpp ]
[ run test_auto_manage.cpp ]
[ run test_torrent_status.cpp ]
[ run test_swarm.cpp ]

View File

@@ -0,0 +1,485 @@
/*
Copyright (c) 2010, Arvid Norberg
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distribution.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
#include "test.hpp"
#include "settings.hpp"
#include "setup_swarm.hpp"
#include "swarm_config.hpp"
#include "simulator/simulator.hpp"
#include "simulator/http_server.hpp"
#include "simulator/socks_server.hpp"
#include "libtorrent/alert_types.hpp"
#include "libtorrent/aux_/proxy_settings.hpp"
#include "libtorrent/http_connection.hpp"
#include "libtorrent/resolver.hpp"
#include "libtorrent/io.hpp"
#include <boost/crc.hpp>
using namespace libtorrent;
using namespace sim;
namespace lt = libtorrent;
namespace io = lt::detail;
using chrono::duration_cast;
struct sim_config : sim::default_config
{
chrono::high_resolution_clock::duration hostname_lookup(
asio::ip::address const& requestor
, std::string hostname
, std::vector<asio::ip::address>& result
, boost::system::error_code& ec)
{
if (hostname == "try-next.com")
{
result.push_back(address_v4::from_string("10.0.0.10"));
result.push_back(address_v4::from_string("10.0.0.9"));
result.push_back(address_v4::from_string("10.0.0.8"));
result.push_back(address_v4::from_string("10.0.0.7"));
result.push_back(address_v4::from_string("10.0.0.6"));
result.push_back(address_v4::from_string("10.0.0.5"));
result.push_back(address_v4::from_string("10.0.0.4"));
result.push_back(address_v4::from_string("10.0.0.3"));
// this is the IP that works, all other should fail
result.push_back(address_v4::from_string("10.0.0.2"));
return duration_cast<chrono::high_resolution_clock::duration>(chrono::milliseconds(100));
}
if (hostname == "test-hostname.com")
{
result.push_back(address_v4::from_string("10.0.0.2"));
return duration_cast<chrono::high_resolution_clock::duration>(chrono::milliseconds(100));
}
return default_config::hostname_lookup(requestor, hostname, result, ec);
}
};
// takes a string of data and chunks it up using HTTP chunked encoding
std::string chunk_string(std::string s)
{
size_t i = 10;
std::string ret;
while (!s.empty())
{
i = std::min(i, s.size());
char header[50];
snprintf(header, sizeof(header), "%x\r\n", int(i));
ret += header;
ret += s.substr(0, i);
s.erase(s.begin(), s.begin() + i);
i *= 2;
}
ret += "0\r\n\r\n";
return ret;
}
boost::shared_ptr<http_connection> test_request(io_service& ios
, resolver& res
, std::string const& url
, char const* expected_data
, int expected_size
, int expected_status
, error_condition expected_error
, lt::aux::proxy_settings const& ps
, int* connect_handler_called
, int* handler_called
, std::string const& auth = std::string())
{
fprintf(stderr, " ===== TESTING: %s =====\n", url.c_str());
auto h = boost::make_shared<http_connection>(ios
, res
, [=](error_code const& ec, http_parser const& parser
, char const* data, const int size, http_connection& c)
{
printf("RESPONSE: %s\n", url.c_str());
++*handler_called;
// this is pretty gross. Since boost.asio is a header-only library, when this test is
// build against shared libraries of libtorrent and simulator, there will be multiple
// (distinct) error categories in boost.asio. The traditional comparison of error_code
// and error_condition may hence fail.
const bool error_ok = ec == expected_error
|| (strcmp(ec.category().name(), expected_error.category().name()) == 0
&& ec.value() == expected_error.value());
if (!error_ok)
{
printf("ERROR: %s (expected: %s)\n"
, ec.message().c_str()
, expected_error.message().c_str());
}
const int http_status = parser.status_code();
if (expected_size != -1)
{
TEST_EQUAL(size, expected_size);
}
TEST_CHECK(error_ok);
if (expected_status != -1)
{
TEST_EQUAL(http_status, expected_status);
}
if (http_status == 200)
{
TEST_CHECK(expected_data
&& size == expected_size
&& memcmp(expected_data, data, size) == 0);
}
}
, true, 1024*1024
, [=](http_connection& c)
{
++*connect_handler_called;
TEST_CHECK(c.socket().is_open());
printf("CONNECTED: %s\n", url.c_str());
});
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", address_v4::any()
, 0, auth);
return h;
}
void print_http_header(std::map<std::string, std::string> const& headers)
{
for (std::map<std::string, std::string>::const_iterator i
= headers.begin(), end(headers.end()); i != end; ++i)
{
printf("%s: %s\n", i->first.c_str(), i->second.c_str());
}
}
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);
enum expect_counters
{
connect_handler = 0,
handler = 1,
test_file_req = 2,
redirect_req = 3,
rel_redirect_req = 4,
inf_redirect_req = 5,
chunked_req = 6,
test_file_gz_req = 7,
num_counters
};
void run_suite(lt::aux::proxy_settings ps)
{
std::string url_base = "http://10.0.0.2:8080";
run_test(ps, url_base + "/test_file", 1337, 200, error_condition(), { 1, 1, 1});
// positive test with a successful hostname
run_test(ps, "http://test-hostname.com:8080/test_file", 1337, 200, error_condition(), { 1, 1, 1});
run_test(ps, url_base + "/non-existent", 0, 404, error_condition(), { 1, 1 });
run_test(ps, url_base + "/redirect", 1337, 200, error_condition(), { 2, 1, 1, 1 });
run_test(ps, url_base + "/relative/redirect", 1337, 200, error_condition(), {2, 1, 1, 0, 1});
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});
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
// error is correctly propagated
// with socks5 we would be able to do this, assuming the socks server
// supported it, but the current socks implementation in libsimulator does
// not support IPv6
if (ps.type != settings_pack::socks5)
{
run_test(ps, "http://[ff::dead:beef]:8080/test_file", 0, -1
, error_condition(boost::system::errc::address_family_not_supported, generic_category())
, {0,1});
}
// there is no node at 10.0.0.10, this should fail with connection refused
run_test(ps, "http://10.0.0.10:8080/test_file", 0, -1,
error_condition(boost::system::errc::connection_refused, generic_category())
, {0,1});
// the try-next test in his case would test the socks proxy itself, whether
// it has robust retry behavior (which the simple test proxy that comes with
// libsimulator doesn't).
if (ps.proxy_hostnames == false)
{
// 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});
}
const error_condition expected_error = ps.proxy_hostnames
? error_condition(boost::system::errc::host_unreachable, generic_category())
: error_condition(asio::error::host_not_found, boost::asio::error::get_netdb_category());
// make sure hostname lookup failures are passed through correctly
run_test(ps, "http://non-existent.com/test_file", 0, -1
, expected_error, { 0, 1});
// make sure we handle gzipped content correctly
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 https
}
lt::aux::proxy_settings make_proxy_settings(lt::settings_pack::proxy_type_t proxy_type)
{
lt::aux::proxy_settings ps;
ps.type = proxy_type;
ps.proxy_hostnames = false;
if (proxy_type != settings_pack::none)
{
ps.hostname = "50.50.50.50";
ps.port = 4444;
ps.username = "testuser";
ps.password = "testpass";
}
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)
{
using sim::asio::ip::address_v4;
sim_config network_cfg;
sim::simulation sim{network_cfg};
// allow sparse expected counters
expect_counters.resize(num_counters, 0);
sim::asio::io_service web_server(sim, address_v4::from_string("10.0.0.2"));
sim::asio::io_service 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(ios);
sim::http_server http(web_server, 8080);
sim::socks_server socks(proxy_ios, 4444, ps.type == settings_pack::socks4 ? 4 : 5);
char data_buffer[4000];
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
std::vector<int> counters(num_counters, 0);
http.register_handler("/test_file"
, [&data_buffer,&counters](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
++counters[test_file_req];
print_http_header(headers);
TEST_EQUAL(method, "GET");
return sim::send_response(200, "OK", 1337).append(data_buffer, 1337);
});
http.register_handler("/chunked_encoding"
, [&data_buffer,&counters](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
++counters[chunked_req];
print_http_header(headers);
TEST_EQUAL(method, "GET");
// there's no content length with chunked encoding
return "HTTP/1.1 200 OK\r\nTransfer-encoding: Chunked\r\n\r\n"
+ chunk_string(std::string(data_buffer, 1337));
});
http.register_handler("/test_file.gz"
, [&data_buffer,&counters](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
++counters[test_file_gz_req];
print_http_header(headers);
TEST_EQUAL(method, "GET");
char const* extra_headers[4] = {"Content-Encoding: gzip\r\n", "", "", ""};
unsigned char const gzheader[] = {
0x1f , 0x8b , 0x08 , 0x00 // ID, compression=deflate, flags=0
, 0x00 , 0x00 , 0x00 , 0x00 // mtime=0
, 0x00, 0x01 // extra headers, OS
, 0x01 // last block, uncompressed
, 0x39 , 0x05, 0xc6 , 0xfa // length = 1337 (little endian 16 bit and inverted)
};
unsigned char trailer[8] = { 0, 0, 0, 0, 0x39, 0x05, 0x00, 0x00 };
boost::crc_32_type crc;
crc.process_bytes(data_buffer, 1337);
boost::uint32_t checksum = crc.checksum();
trailer[0] = checksum >> 24;
trailer[1] = (checksum >> 16) & 0xff;
trailer[2] = (checksum >> 8) & 0xff;
trailer[3] = (checksum) & 0xff;
std::string ret = sim::send_response(200, "OK", 1337 + sizeof(gzheader)
+ sizeof(trailer), extra_headers);
ret.append(std::string((char const*)gzheader, sizeof(gzheader)));
ret.append(data_buffer, 1337);
ret.append(std::string((char const*)trailer, sizeof(trailer)));
return ret;
});
http.register_handler("/redirect"
, [&data_buffer,&counters](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
++counters[redirect_req];
TEST_EQUAL(method, "GET");
return "HTTP/1.1 301 Moved Temporarily\r\n"
"Location: /test_file\r\n"
"\r\n";
});
http.register_handler("/relative/redirect"
, [&data_buffer,&counters](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
++counters[rel_redirect_req];
TEST_EQUAL(method, "GET");
return "HTTP/1.1 301 Moved Temporarily\r\n"
"Location: ../test_file\r\n"
"\r\n";
});
http.register_handler("/infinite/redirect"
, [&data_buffer,&counters](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
++counters[inf_redirect_req];
TEST_EQUAL(method, "GET");
return "HTTP/1.1 301 Moved Temporarily\r\n"
"Location: /infinite/redirect\r\n"
"\r\n";
});
auto c = test_request(ios, res, url, data_buffer, expect_size
, expect_status, expect_error, ps, &counters[connect_handler]
, &counters[handler]);
error_code e;
sim.run(e);
if (e) std::cerr << " run failed: " << e.message() << std::endl;
TEST_EQUAL(e, error_code());
TEST_EQUAL(counters.size(), expect_counters.size());
for (int i = 0; i < counters.size(); ++i)
{
if (counters[i] != expect_counters[i]) fprintf(stderr, "i=%d\n", i);
TEST_EQUAL(counters[i], expect_counters[i]);
}
}
TORRENT_TEST(http_connection)
{
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::none);
run_suite(ps);
}
TORRENT_TEST(http_connection_socks4)
{
lt::aux::proxy_settings ps = make_proxy_settings(settings_pack::socks4);
run_suite(ps);
}
TORRENT_TEST(http_connection_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)
{
// if we set up to user a proxy that does not exist, expect failure!
using sim::asio::ip::address_v4;
sim_config network_cfg;
sim::simulation sim{network_cfg};
sim::asio::io_service web_server(sim, address_v4::from_string("10.0.0.2"));
sim::asio::io_service ios(sim, address_v4::from_string("10.0.0.1"));
lt::resolver res(ios);
sim::http_server http(web_server, 8080);
lt::aux::proxy_settings ps;
ps.hostname = "50.50.50.50";
ps.port = 4444;
ps.username = "testuser";
ps.password = "testpass";
ps.type = settings_pack::socks5;
char data_buffer[4000];
std::generate(data_buffer, data_buffer + sizeof(data_buffer), &std::rand);
http.register_handler("/test_file"
, [&data_buffer](std::string method, std::string req
, std::map<std::string, std::string>& headers)
{
print_http_header(headers);
TEST_CHECK(false && "we're not supposed to get here!");
return sim::send_response(200, "OK", 1337).append(data_buffer, 1337);
});
int connect_counter = 0;
int handler_counter = 0;
auto c = test_request(ios, res, "http://10.0.0.2:8080/test_file"
, data_buffer, -1, -1
, error_condition(boost::system::errc::connection_refused, boost::system::generic_category())
, ps, &connect_counter, &handler_counter);
error_code e;
sim.run(e);
if (e) std::cerr << " run failed: " << e.message() << std::endl;
TEST_EQUAL(e, error_code());
}
// TODO: test http proxy
// TODO: test socks5 with password
// TODO: test SSL
// TODO: test keepalive

View File

@@ -140,7 +140,7 @@ void test_interval(int interval)
http.register_handler("/announce"
, [&announces,interval,start](std::string method, std::string req
, std::map<std::string, std::string>& headers)
, std::map<std::string, std::string>&)
{
boost::uint32_t seconds = chrono::duration_cast<lt::seconds>(
lt::clock_type::now() - start).count();
@@ -185,7 +185,7 @@ void test_completed()
http.register_handler("/announce"
, [&announces,interval,start](std::string method, std::string req
, std::map<std::string, std::string>& headers)
, std::map<std::string, std::string>&)
{
TEST_EQUAL(method, "GET");
announces.push_back(req);
@@ -309,15 +309,12 @@ TORRENT_TEST(ipv6_support)
sim::http_server http_v4(web_server_v4, 8080);
sim::http_server http_v6(web_server_v6, 8080);
// the timestamps (in seconds) of all announces
std::vector<std::string> announces;
int v4_announces = 0;
int v6_announces = 0;
http_v4.register_handler("/announce"
, [&v4_announces](std::string method, std::string req
, std::map<std::string, std::string>& headers)
, std::map<std::string, std::string>&)
{
++v4_announces;
TEST_EQUAL(method, "GET");
@@ -329,7 +326,7 @@ TORRENT_TEST(ipv6_support)
http_v6.register_handler("/announce"
, [&v6_announces](std::string method, std::string req
, std::map<std::string, std::string>& headers)
, std::map<std::string, std::string>&)
{
++v6_announces;
TEST_EQUAL(method, "GET");

View File

@@ -201,7 +201,7 @@ namespace libtorrent
e.file_ptr = boost::make_shared<file>();
if (!e.file_ptr)
{
ec = error_code(ENOMEM, get_posix_category());
ec = error_code(boost::system::errc::not_enough_memory, generic_category());
return e.file_ptr;
}
std::string full_path = fs.file_path(file_index, p);

View File

@@ -119,6 +119,8 @@ namespace libtorrent
const unsigned char* buffer = reinterpret_cast<const unsigned char*>(buf);
const int total_size = size;
// gzip is defined in https://tools.ietf.org/html/rfc1952
// The zip header cannot be shorter than 10 bytes
if (size < 10 || buf == 0) return -1;
@@ -129,9 +131,14 @@ namespace libtorrent
int flags = buffer[3];
// check for reserved flag and make sure it's compressed with the correct metod
// we only support deflate
if (method != 8 || (flags & FRESERVED) != 0) return -1;
// skip time, xflags, OS code
// skip time, xflags, OS code. The first 10 bytes of the header:
// +---+---+---+---+---+---+---+---+---+---+
// |ID1|ID2|CM |FLG| MTIME |XFL|OS | (more-->)
// +---+---+---+---+---+---+---+---+---+---+
size -= 10;
buffer += 10;

View File

@@ -379,6 +379,9 @@ void http_connection::start(std::string const& hostname, int port
return;
}
m_endpoints.clear();
m_next_ep = 0;
#if TORRENT_USE_I2P
if (is_i2p)
{
@@ -409,8 +412,6 @@ void http_connection::start(std::string const& hostname, int port
#if defined TORRENT_ASIO_DEBUGGING
add_outstanding_async("http_connection::on_resolve");
#endif
m_endpoints.clear();
m_next_ep = 0;
m_resolver.async_resolve(hostname, m_resolve_flags
, boost::bind(&http_connection::on_resolve
, me, _1, _2));
@@ -450,7 +451,6 @@ void http_connection::on_timeout(boost::weak_ptr<http_connection> p
else
{
c->callback(boost::asio::error::timed_out);
c->close(true);
}
return;
}
@@ -519,7 +519,6 @@ void http_connection::on_i2p_resolve(error_code const& e
if (e)
{
callback(e);
close();
return;
}
connect_i2p_tracker(destination);
@@ -534,10 +533,7 @@ void http_connection::on_resolve(error_code const& e
#endif
if (e)
{
boost::shared_ptr<http_connection> me(shared_from_this());
callback(e);
close();
return;
}
TORRENT_ASSERT(!addresses.empty());
@@ -581,19 +577,32 @@ void http_connection::connect()
&& (m_proxy.type == settings_pack::socks5
|| m_proxy.type == settings_pack::socks5_pw))
{
// we're using a socks proxy and we're resolving
// hostnames through it
#ifdef TORRENT_USE_OPENSSL
if (m_ssl)
// test to see if m_hostname really just is an IP (and not a hostname). If it
// is, ec will be represent "success". If so, don't set it as the socks5
// hostname, just connect to the IP
error_code ec;
address adr = address::from_string(m_hostname, ec);
if (ec)
{
TORRENT_ASSERT(m_sock.get<ssl_stream<socks5_stream> >());
m_sock.get<ssl_stream<socks5_stream> >()->next_layer().set_dst_name(m_hostname);
// we're using a socks proxy and we're resolving
// 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
#endif
{
TORRENT_ASSERT(m_sock.get<socks5_stream>());
m_sock.get<socks5_stream>()->set_dst_name(m_hostname);
m_endpoints[0].address(adr);
}
}
@@ -640,9 +649,7 @@ void http_connection::on_connect(error_code const& e)
}
else
{
boost::shared_ptr<http_connection> me(shared_from_this());
callback(e);
close();
}
}
@@ -664,7 +671,6 @@ void http_connection::callback(error_code e, char* data, int size)
if (ec)
{
if (m_handler) m_handler(ec, m_parser, data, size, *this);
close();
return;
}
size = int(buf.size());
@@ -692,9 +698,7 @@ void http_connection::on_write(error_code const& e)
if (e)
{
boost::shared_ptr<http_connection> me(shared_from_this());
callback(e);
close();
return;
}
@@ -763,7 +767,6 @@ void http_connection::on_read(error_code const& e
size = m_parser.get_body().left();
}
callback(ec, data, size);
close();
return;
}
@@ -771,7 +774,6 @@ void http_connection::on_read(error_code const& e
{
TORRENT_ASSERT(bytes_transferred == 0);
callback(e);
close();
return;
}
@@ -805,7 +807,6 @@ void http_connection::on_read(error_code const& e
{
// missing location header
callback(error_code(errors::http_missing_location));
close();
return;
}
@@ -825,7 +826,7 @@ void http_connection::on_read(error_code const& e
);
return;
}
m_redirects = 0;
}
@@ -861,7 +862,6 @@ void http_connection::on_read(error_code const& e
// if we've reached the size limit, terminate the connection and
// report the error
callback(error_code(boost::system::errc::file_too_large, generic_category()));
close();
return;
}
int amount_to_read = m_recvbuffer.size() - m_read_pos;

View File

@@ -141,8 +141,6 @@ namespace libtorrent
else
{
(*h)(socks_error::unsupported_version);
error_code ec;
close(ec);
}
}
@@ -177,8 +175,6 @@ namespace libtorrent
if (version < m_version)
{
(*h)(socks_error::unsupported_version);
error_code ec;
close(ec);
return;
}
@@ -191,8 +187,6 @@ namespace libtorrent
if (m_user.empty())
{
(*h)(socks_error::username_required);
error_code ec;
close(ec);
return;
}
@@ -214,8 +208,6 @@ namespace libtorrent
else
{
(*h)(socks_error::unsupported_authentication_method);
error_code ec;
close(ec);
return;
}
}
@@ -253,16 +245,12 @@ namespace libtorrent
if (version != 1)
{
(*h)(socks_error::unsupported_authentication_version);
error_code ec;
close(ec);
return;
}
if (status != 0)
{
(*h)(socks_error::authentication_error);
error_code ec;
close(ec);
return;
}
@@ -309,8 +297,6 @@ namespace libtorrent
if (!m_remote_endpoint.address().is_v4())
{
(*h)(boost::asio::error::address_family_not_supported);
error_code ec;
close(ec);
return;
}
m_buffer.resize(m_user.size() + 9);
@@ -326,8 +312,6 @@ namespace libtorrent
else
{
(*h)(socks_error::unsupported_version);
error_code ec;
close(ec);
return;
}
@@ -376,8 +360,6 @@ namespace libtorrent
if (version < m_version)
{
(*h)(socks_error::unsupported_version);
error_code ec;
close(ec);
return;
}
if (response != 0)
@@ -394,7 +376,6 @@ namespace libtorrent
case 8: ec = boost::asio::error::address_family_not_supported; break;
}
(*h)(ec);
close(ec);
return;
}
p += 1; // reserved
@@ -437,8 +418,6 @@ namespace libtorrent
else
{
(*h)(boost::asio::error::address_family_not_supported);
error_code ec;
close(ec);
return;
}
m_buffer.resize(m_buffer.size() + extra_bytes);
@@ -455,8 +434,6 @@ namespace libtorrent
if (version != 0)
{
(*h)(socks_error::general_failure);
error_code ec;
close(ec);
return;
}
@@ -487,16 +464,14 @@ namespace libtorrent
return;
}
int code = socks_error::general_failure;
error_code ec(socks_error::general_failure, get_socks_category());
switch (response)
{
case 91: code = socks_error::authentication_error; break;
case 92: code = socks_error::no_identd; break;
case 93: code = socks_error::identd_error; break;
case 91: ec = boost::asio::error::connection_refused; break;
case 92: ec = socks_error::no_identd; break;
case 93: ec = socks_error::identd_error; break;
}
error_code ec(code, get_socks_category());
(*h)(ec);
close(ec);
}
}

View File

@@ -310,6 +310,10 @@ EXPORT int main(int argc, char const* argv[])
}
}
// get proper interleaving of stderr and stdout
setbuf(stdout, NULL);
setbuf(stderr, NULL);
_g_test_idx = i;
current_test = &t;

View File

@@ -219,26 +219,15 @@ void run_suite(std::string const& protocol
stop_web_server();
}
TORRENT_TEST(no_proxy) { run_suite("http", settings_pack::none); }
TORRENT_TEST(socks4) { run_suite("http", settings_pack::socks4); }
TORRENT_TEST(socks5) { run_suite("http", settings_pack::socks5); }
TORRENT_TEST(socks5_pw) { run_suite("http", settings_pack::socks5_pw); }
TORRENT_TEST(http) { run_suite("http", settings_pack::http); }
TORRENT_TEST(http_pw) { run_suite("http", settings_pack::http_pw); }
#ifdef TORRENT_USE_OPENSSL
TORRENT_TEST(no_proxy_ssl) { run_suite("https", settings_pack::none); }
TORRENT_TEST(socks4_ssl) { run_suite("https", settings_pack::socks4); }
TORRENT_TEST(socks5_ssl) { run_suite("https", settings_pack::socks5); }
TORRENT_TEST(socks5_pw_ssl) { run_suite("https", settings_pack::socks5_pw); }
TORRENT_TEST(http_ssl) { run_suite("https", settings_pack::http); }
TORRENT_TEST(http_pw_ssl) { run_suite("https", settings_pack::http_pw); }
#endif // USE_OPENSSL
TORRENT_TEST(chunked_encoding)
{
run_suite("http", settings_pack::none, flag_chunked_encoding | flag_keepalive);
}
TORRENT_TEST(no_keepalive)
{
run_suite("http", settings_pack::none, 0);

View File

@@ -104,7 +104,7 @@ struct test_storage : default_storage
{
std::cerr << "storage written: " << m_written << " limit: " << m_limit << std::endl;
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;
return 0;
}