support http basic auth in http_connection passed in from the outside as opposed to part of the url
This commit is contained in:
parent
04c33d6fb2
commit
1b9b6f7292
|
@ -97,12 +97,13 @@ struct TORRENT_EXTRA_EXPORT http_connection
|
||||||
int rate_limit() const
|
int rate_limit() const
|
||||||
{ return m_rate_limit; }
|
{ return m_rate_limit; }
|
||||||
|
|
||||||
std::string 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, proxy_settings const* ps = 0, int handle_redirects = 5
|
, int prio = 0, proxy_settings const* ps = 0, int handle_redirects = 5
|
||||||
, std::string const& user_agent = "", address const& bind_addr = address_v4::any()
|
, std::string const& user_agent = std::string()
|
||||||
, int resolve_flags = 0
|
, address const& bind_addr = address_v4::any()
|
||||||
|
, int resolve_flags = 0, std::string const& auth_ = std::string()
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
, i2p_connection* i2p_conn = 0
|
, i2p_connection* i2p_conn = 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -150,12 +151,13 @@ private:
|
||||||
|
|
||||||
std::vector<tcp::endpoint> m_endpoints;
|
std::vector<tcp::endpoint> m_endpoints;
|
||||||
|
|
||||||
|
socket_type m_sock;
|
||||||
|
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
asio::ssl::context* m_ssl_ctx;
|
asio::ssl::context* m_ssl_ctx;
|
||||||
bool m_own_ssl_context;
|
bool m_own_ssl_context;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
socket_type m_sock;
|
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
i2p_connection* m_i2p_conn;
|
i2p_connection* m_i2p_conn;
|
||||||
#endif
|
#endif
|
||||||
|
@ -185,6 +187,10 @@ private:
|
||||||
// means do not bind
|
// means do not bind
|
||||||
address m_bind_addr;
|
address m_bind_addr;
|
||||||
|
|
||||||
|
// if username password was passed in, remember it in case we need to
|
||||||
|
// re-issue the request for a redirect
|
||||||
|
std::string m_auth;
|
||||||
|
|
||||||
int m_read_pos;
|
int m_read_pos;
|
||||||
|
|
||||||
// the number of redirects to follow (in sequence)
|
// the number of redirects to follow (in sequence)
|
||||||
|
|
|
@ -61,16 +61,15 @@ http_connection::http_connection(io_service& ios
|
||||||
, boost::asio::ssl::context* ssl_ctx
|
, boost::asio::ssl::context* ssl_ctx
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
:
|
: m_sock(ios)
|
||||||
#ifdef TORRENT_USE_OPENSSL
|
#ifdef TORRENT_USE_OPENSSL
|
||||||
m_ssl_ctx(ssl_ctx),
|
, m_ssl_ctx(ssl_ctx)
|
||||||
m_own_ssl_context(false),
|
, m_own_ssl_context(false)
|
||||||
#endif
|
#endif
|
||||||
m_sock(ios),
|
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
m_i2p_conn(0),
|
, m_i2p_conn(0)
|
||||||
#endif
|
#endif
|
||||||
m_resolver(resolver)
|
, m_resolver(resolver)
|
||||||
, m_handler(handler)
|
, m_handler(handler)
|
||||||
, m_connect_handler(ch)
|
, m_connect_handler(ch)
|
||||||
, m_filter_handler(fh)
|
, m_filter_handler(fh)
|
||||||
|
@ -105,7 +104,7 @@ http_connection::~http_connection()
|
||||||
|
|
||||||
void http_connection::get(std::string const& url, time_duration timeout, int prio
|
void http_connection::get(std::string const& url, time_duration timeout, int prio
|
||||||
, proxy_settings const* ps, int handle_redirects, std::string const& user_agent
|
, proxy_settings const* ps, int handle_redirects, std::string const& user_agent
|
||||||
, address const& bind_addr, int resolve_flags
|
, address const& bind_addr, int resolve_flags, std::string const& auth_
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
, i2p_connection* i2p_conn
|
, i2p_connection* i2p_conn
|
||||||
#endif
|
#endif
|
||||||
|
@ -124,6 +123,10 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
||||||
boost::tie(protocol, auth, hostname, port, path)
|
boost::tie(protocol, auth, hostname, port, path)
|
||||||
= parse_url_components(url, ec);
|
= parse_url_components(url, ec);
|
||||||
|
|
||||||
|
if (auth.empty()) auth = auth_;
|
||||||
|
|
||||||
|
m_auth = auth;
|
||||||
|
|
||||||
int default_port = protocol == "https" ? 443 : 80;
|
int default_port = protocol == "https" ? 443 : 80;
|
||||||
if (port == -1) port = default_port;
|
if (port == -1) port = default_port;
|
||||||
|
|
||||||
|
@ -204,7 +207,7 @@ void http_connection::get(std::string const& url, time_duration timeout, int pri
|
||||||
|
|
||||||
APPEND_FMT("Connection: close\r\n\r\n");
|
APPEND_FMT("Connection: close\r\n\r\n");
|
||||||
|
|
||||||
sendbuffer.assign(request);
|
m_sendbuffer.assign(request);
|
||||||
m_url = url;
|
m_url = url;
|
||||||
start(hostname, port, timeout, prio
|
start(hostname, port, timeout, prio
|
||||||
, ps, ssl, handle_redirects, bind_addr, m_resolve_flags
|
, ps, ssl, handle_redirects, bind_addr, m_resolve_flags
|
||||||
|
@ -264,7 +267,7 @@ 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_write");
|
add_outstanding_async("http_connection::on_write");
|
||||||
#endif
|
#endif
|
||||||
async_write(m_sock, asio::buffer(sendbuffer)
|
async_write(m_sock, asio::buffer(m_sendbuffer)
|
||||||
, boost::bind(&http_connection::on_write, me, _1));
|
, boost::bind(&http_connection::on_write, me, _1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -602,7 +605,7 @@ void http_connection::on_connect(error_code const& e)
|
||||||
#if defined TORRENT_ASIO_DEBUGGING
|
#if defined TORRENT_ASIO_DEBUGGING
|
||||||
add_outstanding_async("http_connection::on_write");
|
add_outstanding_async("http_connection::on_write");
|
||||||
#endif
|
#endif
|
||||||
async_write(m_sock, asio::buffer(sendbuffer)
|
async_write(m_sock, asio::buffer(m_sendbuffer)
|
||||||
, boost::bind(&http_connection::on_write, shared_from_this(), _1));
|
, boost::bind(&http_connection::on_write, shared_from_this(), _1));
|
||||||
}
|
}
|
||||||
else if (!m_endpoints.empty() && !m_abort)
|
else if (!m_endpoints.empty() && !m_abort)
|
||||||
|
@ -674,7 +677,7 @@ void http_connection::on_write(error_code const& e)
|
||||||
|
|
||||||
if (m_abort) return;
|
if (m_abort) return;
|
||||||
|
|
||||||
std::string().swap(sendbuffer);
|
std::string().swap(m_sendbuffer);
|
||||||
m_recvbuffer.resize(4096);
|
m_recvbuffer.resize(4096);
|
||||||
|
|
||||||
int amount_to_read = m_recvbuffer.size() - m_read_pos;
|
int amount_to_read = m_recvbuffer.size() - m_read_pos;
|
||||||
|
@ -792,7 +795,7 @@ void http_connection::on_read(error_code const& e
|
||||||
|
|
||||||
std::string url = resolve_redirect_location(m_url, location);
|
std::string url = resolve_redirect_location(m_url, location);
|
||||||
get(url, m_completion_timeout, m_priority, &m_proxy, m_redirects - 1
|
get(url, m_completion_timeout, m_priority, &m_proxy, m_redirects - 1
|
||||||
, m_user_agent, m_bind_addr, m_resolve_flags
|
, m_user_agent, m_bind_addr, m_resolve_flags, m_auth
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
, m_i2p_conn
|
, m_i2p_conn
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -82,8 +82,6 @@ namespace libtorrent
|
||||||
|
|
||||||
void http_tracker_connection::start()
|
void http_tracker_connection::start()
|
||||||
{
|
{
|
||||||
// TODO: 3 take tracker_req().auth into account. Use it when making the
|
|
||||||
// request
|
|
||||||
std::string url = tracker_req().url;
|
std::string url = tracker_req().url;
|
||||||
|
|
||||||
if (tracker_req().kind == tracker_request::scrape_request)
|
if (tracker_req().kind == tracker_request::scrape_request)
|
||||||
|
@ -225,6 +223,7 @@ namespace libtorrent
|
||||||
, tracker_req().event == tracker_request::stopped
|
, tracker_req().event == tracker_request::stopped
|
||||||
? resolver_interface::prefer_cache
|
? resolver_interface::prefer_cache
|
||||||
: resolver_interface::abort_on_shutdown
|
: resolver_interface::abort_on_shutdown
|
||||||
|
, tracker_req().auth
|
||||||
#if TORRENT_USE_I2P
|
#if TORRENT_USE_I2P
|
||||||
, tracker_req().i2pconn
|
, tracker_req().i2pconn
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -866,11 +866,6 @@ namespace libtorrent
|
||||||
// the common pieces first, just to make
|
// the common pieces first, just to make
|
||||||
// it more likely for all snubbed peers to
|
// it more likely for all snubbed peers to
|
||||||
// request blocks from the same piece
|
// request blocks from the same piece
|
||||||
// TODO: 3 this may cause a priority inversion! making a snubbed peer
|
|
||||||
// open up a new piece may cause that piece to become the highest
|
|
||||||
// priority. Unless there is some way to mark pieces as low-priority
|
|
||||||
// this is probably not a good idea. We just want to make all snubbed
|
|
||||||
// peers pick the same common piece.
|
|
||||||
ret |= piece_picker::reverse;
|
ret |= piece_picker::reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4869,6 +4869,7 @@ namespace libtorrent
|
||||||
alerts().post_alert(torrent_paused_alert(get_handle()));
|
alerts().post_alert(torrent_paused_alert(get_handle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: 2 the tracker login feature should probably be deprecated
|
||||||
std::string torrent::tracker_login() const
|
std::string torrent::tracker_login() const
|
||||||
{
|
{
|
||||||
if (m_username.empty() && m_password.empty()) return "";
|
if (m_username.empty() && m_password.empty()) return "";
|
||||||
|
|
|
@ -230,7 +230,7 @@ namespace libtorrent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ir all endpoints were filtered by the IP filter, we can't connect
|
// if all endpoints were filtered by the IP filter, we can't connect
|
||||||
if (m_endpoints.empty())
|
if (m_endpoints.empty())
|
||||||
{
|
{
|
||||||
fail(error_code(errors::banned_by_ip_filter));
|
fail(error_code(errors::banned_by_ip_filter));
|
||||||
|
|
|
@ -669,7 +669,7 @@ void upnp::post(upnp::rootdevice const& d, char const* soap
|
||||||
, int(strlen(soap)), d.service_namespace, soap_action
|
, int(strlen(soap)), d.service_namespace, soap_action
|
||||||
, soap);
|
, soap);
|
||||||
|
|
||||||
d.upnp_connection->sendbuffer = header;
|
d.upnp_connection->m_sendbuffer = header;
|
||||||
|
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
snprintf(msg, sizeof(msg), "sending: %s", header);
|
snprintf(msg, sizeof(msg), "sending: %s", header);
|
||||||
|
|
|
@ -104,7 +104,8 @@ void reset_globals()
|
||||||
}
|
}
|
||||||
|
|
||||||
void run_test(std::string const& url, int size, int status, int connected
|
void run_test(std::string const& url, int size, int status, int connected
|
||||||
, boost::optional<error_code> ec, proxy_settings const& ps)
|
, boost::optional<error_code> ec, proxy_settings const& ps
|
||||||
|
, std::string const& auth = std::string())
|
||||||
{
|
{
|
||||||
reset_globals();
|
reset_globals();
|
||||||
|
|
||||||
|
@ -118,7 +119,8 @@ void run_test(std::string const& url, int size, int status, int connected
|
||||||
|
|
||||||
boost::shared_ptr<http_connection> h(new http_connection(ios
|
boost::shared_ptr<http_connection> h(new http_connection(ios
|
||||||
, res, &::http_handler, true, 1024*1024, &::http_connect_handler));
|
, res, &::http_handler, true, 1024*1024, &::http_connect_handler));
|
||||||
h->get(url, seconds(1), 0, &ps);
|
h->get(url, seconds(1), 0, &ps, 5, "test/user-agent", address_v4::any()
|
||||||
|
, 0, auth);
|
||||||
ios.reset();
|
ios.reset();
|
||||||
error_code e;
|
error_code e;
|
||||||
ios.run(e);
|
ios.run(e);
|
||||||
|
@ -166,6 +168,8 @@ void run_suite(std::string const& protocol, proxy_settings ps, int port)
|
||||||
run_test(url_base + "test_file", 3216, 200, 1, error_code(), ps);
|
run_test(url_base + "test_file", 3216, 200, 1, error_code(), ps);
|
||||||
run_test(url_base + "test_file.gz", 3216, 200, 1, error_code(), ps);
|
run_test(url_base + "test_file.gz", 3216, 200, 1, error_code(), ps);
|
||||||
run_test(url_base + "non-existing-file", -1, 404, 1, err(), ps);
|
run_test(url_base + "non-existing-file", -1, 404, 1, err(), ps);
|
||||||
|
run_test(url_base + "password_protected", 3216, 200, 1, error_code(), ps
|
||||||
|
, "testuser:testpass");
|
||||||
|
|
||||||
// only run the tests to handle NX_DOMAIN if we have a proper internet
|
// only run the tests to handle NX_DOMAIN if we have a proper internet
|
||||||
// connection that doesn't inject false DNS responses (like Comcast does)
|
// connection that doesn't inject false DNS responses (like Comcast does)
|
||||||
|
|
|
@ -4,6 +4,7 @@ import sys
|
||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
import gzip
|
import gzip
|
||||||
|
import base64
|
||||||
|
|
||||||
chunked_encoding = False
|
chunked_encoding = False
|
||||||
keepalive = True
|
keepalive = True
|
||||||
|
@ -41,6 +42,21 @@ class http_handler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||||
|
|
||||||
file_path = os.path.normpath(s.path)
|
file_path = os.path.normpath(s.path)
|
||||||
|
|
||||||
|
if s.path == '/password_protected':
|
||||||
|
passed = False
|
||||||
|
if 'Authorization' in s.headers:
|
||||||
|
auth = s.headers['Authorization']
|
||||||
|
passed = auth == 'Basic %s' % base64.b64encode('testuser:testpass')
|
||||||
|
|
||||||
|
if not passed:
|
||||||
|
s.send_response(401)
|
||||||
|
s.send_header("Connection", "close")
|
||||||
|
s.end_headers()
|
||||||
|
return
|
||||||
|
|
||||||
|
s.path = '/test_file'
|
||||||
|
file_path = os.path.normpath('/test_file')
|
||||||
|
|
||||||
if s.path == '/redirect':
|
if s.path == '/redirect':
|
||||||
s.send_response(301)
|
s.send_response(301)
|
||||||
s.send_header("Location", "/test_file")
|
s.send_header("Location", "/test_file")
|
||||||
|
|
Loading…
Reference in New Issue