forked from premiere/premiere-libtorrent
fix IPv6 tracker announce issue
This commit is contained in:
parent
1593916e62
commit
5e7666526e
|
@ -1,4 +1,5 @@
|
|||
|
||||
* fix IPv6 tracker announce issue
|
||||
* restore path sanitization behavior of ":"
|
||||
* fix listen socket issue when disabling "force_proxy" mode
|
||||
* fix full allocation failure on APFS
|
||||
|
|
|
@ -54,6 +54,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/unordered_map.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
#include "libtorrent/ssl_stream.hpp"
|
||||
#endif
|
||||
|
@ -231,8 +233,8 @@ namespace libtorrent
|
|||
// if we are listening on an IPv6 interface
|
||||
// this will return one of the IPv6 addresses on this
|
||||
// machine, otherwise just an empty endpoint
|
||||
tcp::endpoint get_ipv6_interface() const TORRENT_OVERRIDE;
|
||||
tcp::endpoint get_ipv4_interface() const TORRENT_OVERRIDE;
|
||||
boost::optional<tcp::endpoint> get_ipv6_interface() const TORRENT_OVERRIDE;
|
||||
boost::optional<tcp::endpoint> get_ipv4_interface() const TORRENT_OVERRIDE;
|
||||
|
||||
void async_accept(boost::shared_ptr<tcp::acceptor> const& listener, bool ssl);
|
||||
void on_accept_connection(boost::shared_ptr<socket_type> const& s
|
||||
|
@ -870,8 +872,8 @@ namespace libtorrent
|
|||
// if we're listening on an IPv6 interface
|
||||
// this is one of the non local IPv6 interfaces
|
||||
// on this machine
|
||||
tcp::endpoint m_ipv6_interface;
|
||||
tcp::endpoint m_ipv4_interface;
|
||||
boost::optional<tcp::endpoint> m_ipv6_interface;
|
||||
boost::optional<tcp::endpoint> m_ipv4_interface;
|
||||
|
||||
// since we might be listening on multiple interfaces
|
||||
// we might need more than one listen socket
|
||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
@ -255,8 +256,8 @@ namespace libtorrent { namespace aux
|
|||
|
||||
virtual void prioritize_connections(boost::weak_ptr<torrent> t) = 0;
|
||||
|
||||
virtual tcp::endpoint get_ipv6_interface() const = 0;
|
||||
virtual tcp::endpoint get_ipv4_interface() const = 0;
|
||||
virtual boost::optional<tcp::endpoint> get_ipv6_interface() const = 0;
|
||||
virtual boost::optional<tcp::endpoint> get_ipv4_interface() const = 0;
|
||||
|
||||
virtual void trigger_auto_manage() = 0;
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
@ -113,7 +114,7 @@ struct TORRENT_EXTRA_EXPORT http_connection
|
|||
void get(std::string const& url, time_duration timeout = seconds(30)
|
||||
, int prio = 0, aux::proxy_settings const* ps = NULL, int handle_redirects = 5
|
||||
, std::string const& user_agent = std::string()
|
||||
, address const& bind_addr = address_v4::any()
|
||||
, boost::optional<address> bind_addr = boost::none
|
||||
, int resolve_flags = 0, std::string const& auth_ = std::string()
|
||||
#if TORRENT_USE_I2P
|
||||
, i2p_connection* i2p_conn = 0
|
||||
|
@ -123,7 +124,7 @@ struct TORRENT_EXTRA_EXPORT http_connection
|
|||
void start(std::string const& hostname, int port
|
||||
, time_duration timeout, int prio = 0, aux::proxy_settings const* ps = NULL
|
||||
, bool ssl = false, int handle_redirect = 5
|
||||
, address const& bind_addr = address_v4::any()
|
||||
, boost::optional<address> bind_addr = boost::none
|
||||
, int resolve_flags = 0
|
||||
#if TORRENT_USE_I2P
|
||||
, i2p_connection* i2p_conn = 0
|
||||
|
@ -199,9 +200,8 @@ private:
|
|||
// configured to use a proxy
|
||||
aux::proxy_settings m_proxy;
|
||||
|
||||
// the address to bind to. address_v4::any()
|
||||
// means do not bind
|
||||
address m_bind_addr;
|
||||
// the address to bind to. unset means do not bind
|
||||
boost::optional<address> m_bind_addr;
|
||||
|
||||
// if username password was passed in, remember it in case we need to
|
||||
// re-issue the request for a redirect
|
||||
|
|
|
@ -744,8 +744,7 @@ namespace libtorrent
|
|||
void force_tracker_request(time_point, int tracker_idx);
|
||||
void scrape_tracker(int idx, bool user_triggered);
|
||||
void announce_with_tracker(boost::uint8_t e
|
||||
= tracker_request::none
|
||||
, address const& bind_interface = address_v4::any());
|
||||
= tracker_request::none);
|
||||
int seconds_since_last_scrape() const
|
||||
{
|
||||
return m_last_scrape == (std::numeric_limits<boost::int16_t>::min)()
|
||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
// there is no forward declaration header for asio
|
||||
|
@ -164,7 +165,7 @@ namespace libtorrent
|
|||
#endif
|
||||
sha1_hash info_hash;
|
||||
peer_id pid;
|
||||
address bind_ip;
|
||||
boost::optional<address> bind_ip;
|
||||
|
||||
bool send_stats;
|
||||
|
||||
|
@ -329,7 +330,6 @@ namespace libtorrent
|
|||
, int interval = 0, int min_interval = 0);
|
||||
virtual void start() = 0;
|
||||
virtual void close();
|
||||
address const& bind_interface() const { return m_req.bind_ip; }
|
||||
void sent_bytes(int bytes);
|
||||
void received_bytes(int bytes);
|
||||
virtual bool on_receive(error_code const&, udp::endpoint const&
|
||||
|
|
|
@ -142,7 +142,7 @@ struct dht_node final : lt::dht::udp_socket_interface
|
|||
// since the simulation is single threaded, we can get away with just
|
||||
// allocating a single of these
|
||||
static bdecode_node msg;
|
||||
int ret = bdecode(m_buffer, m_buffer + bytes_transferred, msg, err, &pos, 10, 500);
|
||||
int const ret = bdecode(m_buffer, m_buffer + bytes_transferred, msg, err, &pos, 10, 500);
|
||||
if (ret != 0) return;
|
||||
|
||||
if (msg.type() != bdecode_node::dict_t) return;
|
||||
|
|
|
@ -175,7 +175,7 @@ boost::shared_ptr<http_connection> test_request(io_service& ios
|
|||
printf("CONNECTED: %s\n", url.c_str());
|
||||
});
|
||||
|
||||
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", address_v4::any()
|
||||
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", boost::none
|
||||
, 0, auth);
|
||||
return h;
|
||||
}
|
||||
|
|
|
@ -311,6 +311,7 @@ void test_ipv6_support(char const* listen_interfaces
|
|||
++v4_announces;
|
||||
TEST_EQUAL(method, "GET");
|
||||
|
||||
TEST_CHECK(req.find("&port=6881") != std::string::npos);
|
||||
char response[500];
|
||||
int size = snprintf(response, sizeof(response), "d8:intervali1800e5:peers0:e");
|
||||
return sim::send_response(200, "OK", size) + response;
|
||||
|
@ -323,6 +324,7 @@ void test_ipv6_support(char const* listen_interfaces
|
|||
++v6_announces;
|
||||
TEST_EQUAL(method, "GET");
|
||||
|
||||
TEST_CHECK(req.find("&port=6881") != std::string::npos);
|
||||
char response[500];
|
||||
int size = snprintf(response, sizeof(response), "d8:intervali1800e5:peers0:e");
|
||||
return sim::send_response(200, "OK", size) + response;
|
||||
|
|
|
@ -118,7 +118,7 @@ http_connection::~http_connection()
|
|||
|
||||
void http_connection::get(std::string const& url, time_duration timeout, int prio
|
||||
, aux::proxy_settings const* ps, int handle_redirects, std::string const& user_agent
|
||||
, address const& bind_addr, int resolve_flags, std::string const& auth_
|
||||
, boost::optional<address> bind_addr, int resolve_flags, std::string const& auth_
|
||||
#if TORRENT_USE_I2P
|
||||
, i2p_connection* i2p_conn
|
||||
#endif
|
||||
|
@ -227,7 +227,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
|||
void http_connection::start(std::string const& hostname, int port
|
||||
, time_duration timeout, int prio, aux::proxy_settings const* ps, bool ssl
|
||||
, int handle_redirects
|
||||
, address const& bind_addr
|
||||
, boost::optional<address> bind_addr
|
||||
, int resolve_flags
|
||||
#if TORRENT_USE_I2P
|
||||
, i2p_connection* i2p_conn
|
||||
|
@ -359,10 +359,10 @@ void http_connection::start(std::string const& hostname, int port
|
|||
instantiate_connection(m_timer.get_io_service()
|
||||
, proxy ? *proxy : null_proxy, m_sock, userdata, NULL, false, false);
|
||||
|
||||
if (m_bind_addr != address_v4::any())
|
||||
if (m_bind_addr)
|
||||
{
|
||||
m_sock.open(m_bind_addr.is_v4()?tcp::v4():tcp::v6(), ec);
|
||||
m_sock.bind(tcp::endpoint(m_bind_addr, 0), ec);
|
||||
m_sock.open(m_bind_addr->is_v4()?tcp::v4():tcp::v6(), ec);
|
||||
m_sock.bind(tcp::endpoint(*m_bind_addr, 0), ec);
|
||||
if (ec)
|
||||
{
|
||||
m_timer.get_io_service().post(boost::bind(&http_connection::callback
|
||||
|
@ -560,10 +560,10 @@ void http_connection::on_resolve(error_code const& e
|
|||
// sort the endpoints so that the ones with the same IP version as our
|
||||
// bound listen socket are first. So that when contacting a tracker,
|
||||
// we'll talk to it from the same IP that we're listening on
|
||||
if (m_bind_addr != address_v4::any())
|
||||
if (m_bind_addr)
|
||||
std::partition(m_endpoints.begin(), m_endpoints.end()
|
||||
, boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1))
|
||||
== m_bind_addr.is_v4());
|
||||
== m_bind_addr->is_v4());
|
||||
#endif
|
||||
|
||||
connect();
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace libtorrent
|
|||
m_tracker_connection->get(url, seconds(timeout)
|
||||
, tracker_req().event == tracker_request::stopped ? 2 : 1
|
||||
, ps.proxy_tracker_connections ? &ps : NULL
|
||||
, 5, user_agent, bind_interface()
|
||||
, 5, user_agent, tracker_req().bind_ip
|
||||
, tracker_req().event == tracker_request::stopped
|
||||
? resolver_interface::cache_only : 0
|
||||
| resolver_interface::abort_on_shutdown
|
||||
|
|
|
@ -1349,7 +1349,7 @@ namespace aux {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (is_any(req.bind_ip)) req.bind_ip = m_listen_interface.address();
|
||||
if (!req.bind_ip) req.bind_ip = m_listen_interface.address();
|
||||
m_tracker_manager.queue_request(get_io_service(), req, c);
|
||||
}
|
||||
|
||||
|
@ -1709,12 +1709,12 @@ namespace aux {
|
|||
}
|
||||
#endif
|
||||
|
||||
tcp::endpoint session_impl::get_ipv6_interface() const
|
||||
boost::optional<tcp::endpoint> session_impl::get_ipv6_interface() const
|
||||
{
|
||||
return m_ipv6_interface;
|
||||
}
|
||||
|
||||
tcp::endpoint session_impl::get_ipv4_interface() const
|
||||
boost::optional<tcp::endpoint> session_impl::get_ipv4_interface() const
|
||||
{
|
||||
return m_ipv4_interface;
|
||||
}
|
||||
|
@ -1887,8 +1887,8 @@ retry:
|
|||
|
||||
if (m_abort) return;
|
||||
|
||||
m_ipv6_interface = tcp::endpoint();
|
||||
m_ipv4_interface = tcp::endpoint();
|
||||
m_ipv6_interface = boost::none;
|
||||
m_ipv4_interface = boost::none;
|
||||
|
||||
// TODO: instead of having a special case for this, just make the
|
||||
// default listen interfaces be "0.0.0.0:6881,[::]:6881" and use
|
||||
|
@ -1960,18 +1960,6 @@ retry:
|
|||
}
|
||||
#endif // TORRENT_USE_IPV6
|
||||
|
||||
// set our main IPv4 and IPv6 interfaces
|
||||
// used to send to the tracker
|
||||
std::vector<ip_interface> ifs = enum_net_interfaces(m_io_service, ec);
|
||||
for (std::vector<ip_interface>::const_iterator i = ifs.begin()
|
||||
, end(ifs.end()); i != end; ++i)
|
||||
{
|
||||
address const& addr = i->interface_address;
|
||||
if (addr.is_v6() && !is_local(addr) && !is_loopback(addr))
|
||||
m_ipv6_interface = tcp::endpoint(addr, m_listen_interface.port());
|
||||
else if (addr.is_v4() && !is_local(addr) && !is_loopback(addr))
|
||||
m_ipv4_interface = tcp::endpoint(addr, m_listen_interface.port());
|
||||
}
|
||||
}
|
||||
else if (!m_settings.get_bool(settings_pack::force_proxy))
|
||||
{
|
||||
|
@ -2074,6 +2062,38 @@ retry:
|
|||
return;
|
||||
}
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
bool want_v6 = (m_ipv6_interface && is_any(m_ipv6_interface->address()))
|
||||
|| m_listen_interfaces.empty();
|
||||
#else
|
||||
bool const want_v6 = false;
|
||||
#endif
|
||||
bool want_v4 = (m_ipv4_interface && is_any(m_ipv4_interface->address()))
|
||||
|| m_listen_interfaces.empty();
|
||||
if (want_v6 || want_v4)
|
||||
{
|
||||
// set our main IPv4 and IPv6 interfaces
|
||||
// used to send to the tracker
|
||||
std::vector<ip_interface> ifs = enum_net_interfaces(m_io_service, ec);
|
||||
for (std::vector<ip_interface>::const_iterator i = ifs.begin()
|
||||
, end(ifs.end()); i != end && (want_v4 && want_v6); ++i)
|
||||
{
|
||||
address const& addr = i->interface_address;
|
||||
if (want_v4 && addr.is_v4() && !is_local(addr) && !is_loopback(addr))
|
||||
{
|
||||
m_ipv4_interface = tcp::endpoint(addr, m_listen_interface.port());
|
||||
want_v4 = false;
|
||||
}
|
||||
#if TORRENT_USE_IPV6
|
||||
else if (want_v6 && addr.is_v6() && !is_local(addr) && !is_loopback(addr))
|
||||
{
|
||||
m_ipv6_interface = tcp::endpoint(addr, m_listen_interface.port());
|
||||
want_v6 = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TORRENT_USE_OPENSSL
|
||||
int const ssl_port = m_settings.get_int(settings_pack::ssl_listen);
|
||||
udp::endpoint ssl_bind_if(m_listen_interface.address(), ssl_port);
|
||||
|
|
|
@ -3121,8 +3121,7 @@ namespace {
|
|||
|
||||
#endif
|
||||
|
||||
void torrent::announce_with_tracker(boost::uint8_t e
|
||||
, address const& bind_interface)
|
||||
void torrent::announce_with_tracker(boost::uint8_t e)
|
||||
{
|
||||
TORRENT_ASSERT(is_single_thread());
|
||||
TORRENT_ASSERT(e == tracker_request::stopped || state() != torrent_status::checking_files);
|
||||
|
@ -3196,9 +3195,8 @@ namespace {
|
|||
&& m_torrent_file
|
||||
&& m_torrent_file->priv())
|
||||
{
|
||||
tcp::endpoint ep;
|
||||
ep = m_ses.get_ipv6_interface();
|
||||
if (ep != tcp::endpoint()) req.ipv6 = ep.address().to_v6();
|
||||
boost::optional<tcp::endpoint> ep = m_ses.get_ipv6_interface();
|
||||
if (ep) req.ipv6 = ep->address().to_v6();
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3261,8 +3259,6 @@ namespace {
|
|||
req.triggered_manually = ae.triggered_manually;
|
||||
ae.triggered_manually = false;
|
||||
|
||||
req.bind_ip = bind_interface;
|
||||
|
||||
if (settings().get_bool(settings_pack::force_proxy))
|
||||
{
|
||||
// in force_proxy mode we don't talk directly to trackers
|
||||
|
@ -3533,31 +3529,10 @@ namespace {
|
|||
"external ip: %s\n"
|
||||
"resolved to: %s\n"
|
||||
"we connected to: %s\n"
|
||||
"peers:"
|
||||
, interval
|
||||
, print_address(resp.external_ip).c_str()
|
||||
, resolved_to.c_str()
|
||||
, print_address(tracker_ip).c_str());
|
||||
|
||||
for (std::vector<peer_entry>::const_iterator i = resp.peers.begin();
|
||||
i != resp.peers.end(); ++i)
|
||||
{
|
||||
debug_log(" %16s %5d %s %s", i->hostname.c_str(), i->port
|
||||
, i->pid.is_all_zeros()?"":to_hex(i->pid.to_string()).c_str()
|
||||
, identify_client(i->pid).c_str());
|
||||
}
|
||||
for (std::vector<ipv4_peer_entry>::const_iterator i = resp.peers4.begin();
|
||||
i != resp.peers4.end(); ++i)
|
||||
{
|
||||
debug_log(" %s:%d", print_address(address_v4(i->ip)).c_str(), i->port);
|
||||
}
|
||||
#if TORRENT_USE_IPV6
|
||||
for (std::vector<ipv6_peer_entry>::const_iterator i = resp.peers6.begin();
|
||||
i != resp.peers6.end(); ++i)
|
||||
{
|
||||
debug_log(" [%s]:%d", print_address(address_v6(i->ip)).c_str(), i->port);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// for each of the peers we got from the tracker
|
||||
|
@ -3651,8 +3626,8 @@ namespace {
|
|||
// in order to avoid triggering this case over and over, check whether
|
||||
// this announce was itself triggered by this logic (second_announce)
|
||||
|
||||
if (((!is_any(m_ses.get_ipv6_interface().address()) && tracker_ip.is_v4())
|
||||
|| (!is_any(m_ses.get_ipv4_interface().address()) && tracker_ip.is_v6()))
|
||||
if (((m_ses.get_ipv6_interface() && tracker_ip.is_v4())
|
||||
|| (m_ses.get_ipv4_interface() && tracker_ip.is_v6()))
|
||||
&& !r.second_announce)
|
||||
{
|
||||
std::list<address>::const_iterator i = std::find_if(tracker_ips.begin()
|
||||
|
@ -3662,7 +3637,7 @@ namespace {
|
|||
// the tracker did resolve to a different type of address, so announce
|
||||
// to that as well
|
||||
|
||||
// TODO 2: there's a bug when removing a torrent or shutting down the session,
|
||||
// TODO 3: there's a bug when removing a torrent or shutting down the session,
|
||||
// where the second announce is skipped (in this case, the one to the IPv6
|
||||
// name). This should be fixed by generalizing the tracker list structure to
|
||||
// separate the IPv6 and IPv4 addresses as conceptually separate trackers,
|
||||
|
@ -3675,11 +3650,11 @@ namespace {
|
|||
|
||||
// tell the tracker to bind to the opposite protocol type
|
||||
req.bind_ip = tracker_ip.is_v4()
|
||||
? m_ses.get_ipv6_interface().address()
|
||||
: m_ses.get_ipv4_interface().address();
|
||||
? m_ses.get_ipv6_interface()->address()
|
||||
: m_ses.get_ipv4_interface()->address();
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
debug_log("announce again using %s as the bind interface"
|
||||
, print_address(req.bind_ip).c_str());
|
||||
debug_log("announce again using %s as the bind interface. port: %d"
|
||||
, print_address(*req.bind_ip).c_str(), req.listen_port);
|
||||
#endif
|
||||
m_ses.queue_tracker_request(req, shared_from_this());
|
||||
}
|
||||
|
|
|
@ -282,6 +282,12 @@ namespace libtorrent
|
|||
if (req.event == tracker_request::stopped)
|
||||
req.num_want = 0;
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
boost::shared_ptr<request_callback> cb = c.lock();
|
||||
if (cb) cb->debug_log("*** QUEUE_TRACKER_REQUEST [ listen_port: %d ]"
|
||||
, req.listen_port);
|
||||
#endif
|
||||
|
||||
TORRENT_ASSERT(!m_abort || req.event == tracker_request::stopped);
|
||||
if (m_abort && req.event != tracker_request::stopped)
|
||||
return;
|
||||
|
|
|
@ -243,23 +243,23 @@ namespace libtorrent
|
|||
std::vector<tcp::endpoint>::const_iterator iter = m_endpoints.begin();
|
||||
udp::endpoint target = udp::endpoint(iter->address(), iter->port());
|
||||
|
||||
if (bind_interface() != address_v4::any())
|
||||
if (tracker_req().bind_ip)
|
||||
{
|
||||
// find first endpoint that matches our bind interface type
|
||||
for (; iter != m_endpoints.end() && iter->address().is_v4()
|
||||
!= bind_interface().is_v4(); ++iter);
|
||||
!= tracker_req().bind_ip->is_v4(); ++iter);
|
||||
|
||||
if (iter == m_endpoints.end())
|
||||
{
|
||||
TORRENT_ASSERT(target.address().is_v4() != bind_interface().is_v4());
|
||||
TORRENT_ASSERT(target.address().is_v4() != tracker_req().bind_ip->is_v4());
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb)
|
||||
{
|
||||
char const* tracker_address_type = target.address().is_v4() ? "IPv4" : "IPv6";
|
||||
char const* bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
|
||||
char const* bind_address_type = tracker_req().bind_ip->is_v4() ? "IPv4" : "IPv6";
|
||||
char msg[200];
|
||||
snprintf(msg, sizeof(msg)
|
||||
, "the tracker only resolves to an %s address, and you're "
|
||||
, "the tracker only resolves to an %s address, and you're "
|
||||
"listening on an %s socket. This may prevent you from receiving "
|
||||
"incoming connections."
|
||||
, tracker_address_type, bind_address_type);
|
||||
|
|
|
@ -121,8 +121,7 @@ void run_test(std::string const& url, int size, int status, int connected
|
|||
|
||||
boost::shared_ptr<http_connection> h(new http_connection(ios
|
||||
, res, &::http_handler, true, 1024*1024, &::http_connect_handler));
|
||||
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", address_v4::any()
|
||||
, 0, auth);
|
||||
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", boost::none, 0, auth);
|
||||
ios.reset();
|
||||
error_code e;
|
||||
ios.run(e);
|
||||
|
|
Loading…
Reference in New Issue