58
58
std::string hostname;
63
boost::tie(protocol, auth, hostname, port, path, error)
64
= parse_url_components(url);
63
boost::tie(protocol, auth, hostname, port, path)
64
= parse_url_components(url, ec);
66
66
int default_port = protocol == "https" ? 443 : 80;
69
69
// deletes this object
70
70
boost::shared_ptr<http_connection> me(shared_from_this());
74
callback(asio::error::socket_type_not_supported);
72
if (protocol != "http"
73
#ifdef TORRENT_USE_OPENSSL
74
&& protocol != "https"
78
error_code ec(errors::unsupported_url_protocol);
79
m_resolver.get_io_service().post(boost::bind(&http_connection::callback
80
, this, ec, (char*)0, 0));
86
m_resolver.get_io_service().post(boost::bind(&http_connection::callback
87
, this, ec, (char*)0, 0));
81
94
if (protocol == "https") ssl = true;
82
#ifndef TORRENT_USE_OPENSSL
85
callback(asio::error::socket_type_not_supported);
90
std::stringstream headers;
97
char* end = request + sizeof(request);
100
#define APPEND_FMT(fmt) ptr += snprintf(ptr, end - ptr, fmt)
101
#define APPEND_FMT1(fmt, arg) ptr += snprintf(ptr, end - ptr, fmt, arg)
102
#define APPEND_FMT2(fmt, arg1, arg2) ptr += snprintf(ptr, end - ptr, fmt, arg1, arg2)
91
104
if (ps && (ps->type == proxy_settings::http
92
105
|| ps->type == proxy_settings::http_pw)
95
108
// if we're using an http proxy and not an ssl
96
109
// connection, just do a regular http proxy request
97
headers << "GET " << url << " HTTP/1.0\r\n";
110
APPEND_FMT1("GET %s HTTP/1.0\r\n", url.c_str());
98
111
if (ps->type == proxy_settings::http_pw)
99
headers << "Proxy-Authorization: Basic " << base64encode(
100
ps->username + ":" + ps->password) << "\r\n";
112
APPEND_FMT1("Proxy-Authorization: Basic %s\r\n", base64encode(
113
ps->username + ":" + ps->password).c_str());
101
114
hostname = ps->hostname;
106
headers << "GET " << path << " HTTP/1.0\r\n"
107
"Host: " << hostname;
108
if (port != default_port) headers << ":" << to_string(port).elems;
119
APPEND_FMT2("GET %s HTTP/1.0\r\n"
120
"Host: %s", path.c_str(), hostname.c_str());
121
if (port != default_port) APPEND_FMT1(":%d\r\n", port);
122
else APPEND_FMT("\r\n");
112
125
if (!auth.empty())
113
headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
126
APPEND_FMT1("Authorization: Basic %s\r\n", base64encode(auth).c_str());
115
128
if (!user_agent.empty())
116
headers << "User-Agent: " << user_agent << "\r\n";
129
APPEND_FMT1("User-Agent: %s\r\n", user_agent.c_str());
119
"Connection: close\r\n"
120
"Accept-Encoding: gzip\r\n"
123
sendbuffer = headers.str();
132
APPEND_FMT("Accept-Encoding: gzip\r\n");
134
APPEND_FMT("Connection: close\r\n\r\n");
136
sendbuffer.assign(request);
125
138
start(hostname, to_string(port).elems, timeout, prio
126
139
, ps, ssl, handle_redirects, bind_addr);
302
318
std::transform(i, tcp::resolver::iterator(), std::back_inserter(m_endpoints)
303
319
, boost::bind(&tcp::resolver::iterator::value_type::endpoint, _1));
321
if (m_filter_handler) m_filter_handler(*this, m_endpoints);
322
if (m_endpoints.empty())
305
328
// The following statement causes msvc to crash (ICE). Since it's not
306
329
// necessary in the vast majority of cases, just ignore the endpoint
307
330
// order for windows
309
332
// sort the endpoints so that the ones with the same IP version as our
310
333
// bound listen socket are first. So that when contacting a tracker,
311
334
// we'll talk to it from the same IP that we're listening on
312
std::partition(m_endpoints.begin(), m_endpoints.end()
313
, boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1)) == m_bind_addr.is_v4());
335
if (m_bind_addr != address_v4::any())
336
std::partition(m_endpoints.begin(), m_endpoints.end()
337
, boost::bind(&address::is_v4, boost::bind(&tcp::endpoint::address, _1))
338
== m_bind_addr.is_v4());
367
392
void http_connection::callback(error_code const& e, char const* data, int size)
369
if (!m_bottled || !m_called)
394
if (m_bottled && m_called) return;
396
std::vector<char> buf;
397
if (m_bottled && m_parser.header_finished())
371
std::vector<char> buf;
372
if (m_bottled && m_parser.header_finished())
399
std::string const& encoding = m_parser.header("content-encoding");
400
if ((encoding == "gzip" || encoding == "x-gzip") && size > 0 && data)
374
std::string const& encoding = m_parser.header("content-encoding");
375
if ((encoding == "gzip" || encoding == "x-gzip") && size > 0 && data)
403
if (inflate_gzip(data, size, buf, max_bottled_buffer, error))
378
if (inflate_gzip(data, size, buf, max_bottled_buffer, error))
380
if (m_handler) m_handler(asio::error::fault, m_parser, data, size, *this);
384
size = int(buf.size());
385
data = size == 0 ? 0 : &buf[0];
405
if (m_handler) m_handler(errors::http_failed_decompress, m_parser, data, size, *this);
409
size = int(buf.size());
410
data = size == 0 ? 0 : &buf[0];
391
if (m_handler) m_handler(e, m_parser, data, size, *this);
416
if (m_handler) m_handler(e, m_parser, data, size, *this);
395
419
void http_connection::on_write(error_code const& e)
499
523
m_sock.close(ec);
500
524
using boost::tuples::ignore;
502
boost::tie(ignore, ignore, ignore, ignore, ignore, error)
503
= parse_url_components(location);
525
boost::tie(ignore, ignore, ignore, ignore, ignore)
526
= parse_url_components(location, ec);
506
529
get(location, m_timeout, m_priority, &m_proxy, m_redirects - 1);