added support for http redirection

This commit is contained in:
Arvid Norberg 2004-07-25 20:57:44 +00:00
parent bd296f3657
commit 7f21b35a33
5 changed files with 75 additions and 25 deletions

View File

@ -66,7 +66,8 @@ namespace libtorrent
public:
http_tracker_connection(
tracker_request const& req
tracker_manager& man
, tracker_request const& req
, std::string const& hostname
, unsigned short port
, std::string const& request
@ -79,13 +80,19 @@ namespace libtorrent
private:
void init_send_buffer(
std::string const& hostname
, std::string const& request);
void parse(const entry& e);
peer_entry extract_peer_info(const entry& e);
tracker_manager& m_man;
enum { read_status, read_header, read_body } m_state;
enum { plain, gzip } m_content_encoding;
int m_content_length;
std::string m_location;
boost::shared_ptr<socket> m_socket;
int m_recv_pos;
@ -99,6 +106,9 @@ namespace libtorrent
std::string m_server_protocol;
const http_settings& m_settings;
tracker_request m_req;
std::string m_password;
int m_code;
};
}

View File

@ -151,7 +151,9 @@ namespace libtorrent
private:
std::vector<boost::shared_ptr<tracker_connection> > m_connections;
typedef std::list<boost::shared_ptr<tracker_connection> >
tracker_connections_t;
tracker_connections_t m_connections;
const http_settings& m_settings;
};

View File

@ -95,7 +95,9 @@ namespace libtorrent
assert(len >= 0);
// http://www.ietf.org/rfc/rfc2396.txt
// section 2.3
static const char unreserved_chars[] = "-_.!~*'()";
// some trackers seems to require that ' is escaped
// static const char unreserved_chars[] = "-_.!~*'()";
static const char unreserved_chars[] = "-_.!~*()";
std::stringstream ret;
ret << std::hex << std::setfill('0');
@ -109,6 +111,10 @@ namespace libtorrent
{
ret << *str;
}
else if (*str == ' ')
{
ret << '+';
}
else
{
ret << '%'

View File

@ -75,9 +75,9 @@ namespace
namespace libtorrent
{
http_tracker_connection::http_tracker_connection(
tracker_request const& req
tracker_manager& man
, tracker_request const& req
, std::string const& hostname
, unsigned short port
, std::string const& request
@ -85,12 +85,16 @@ namespace libtorrent
, const http_settings& stn
, std::string const& password)
: tracker_connection(c)
, m_man(man)
, m_state(read_status)
, m_content_encoding(plain)
, m_content_length(0)
, m_recv_pos(0)
, m_request_time(boost::posix_time::second_clock::local_time())
, m_settings(stn)
, m_req(req)
, m_password(password)
, m_code(0)
{
const std::string* connect_to_host;
bool using_proxy = false;
@ -320,15 +324,19 @@ namespace libtorrent
if (requester()) requester()->tracker_request_error(-1, error_msg.c_str());
return true;
}
int code;
line >> code;
line >> m_code;
std::getline(line, m_server_message);
m_state = read_header;
if (code != 200)
if (m_code != 200
&& m_code != 301
&& m_code != 302
&& m_code != 303
&& m_code != 307)
{
std::string error_msg = boost::lexical_cast<std::string>(code) + " " + m_server_message;
if (requester()) requester()->tracker_request_error(code, error_msg.c_str());
std::string error_msg = boost::lexical_cast<std::string>(m_code)
+ " " + m_server_message;
if (requester()) requester()->tracker_request_error(m_code, error_msg.c_str());
return true;
}
}
@ -381,7 +389,7 @@ namespace libtorrent
return true;
}
if (m_content_length < minimum_tracker_response_length)
if (m_content_length < minimum_tracker_response_length && m_code == 200)
{
if (requester())
{
@ -404,18 +412,44 @@ namespace libtorrent
error_str += line.substr(18, line.length() - 18 - 2);
error_str += "\"";
if (requester())
{
requester()->tracker_request_error(-1, error_str.c_str());
}
return true;
}
}
else if (line.substr(0, 10) == "Location: ")
{
m_location.assign(line.begin() + 10, line.end());
}
else if (line.size() < 3)
{
m_state = read_body;
#ifndef NDEBUG
if (requester()) requester()->debug_log("end of http header");
#endif
if (m_code >= 300 && m_code < 400)
{
if (m_location.empty())
{
std::string error_str = "got redirection response (";
error_str += boost::lexical_cast<std::string>(m_code);
error_str += ") without 'Location' header";
if (requester())
requester()->tracker_request_error(m_code, error_str.c_str());
return true;
}
#ifndef NDEBUG
if (requester()) requester()->debug_log("Redirecting to \"" + m_location + "\"");
#endif
std::string::size_type i = m_location.find('?');
if (i == std::string::npos)
m_req.url = m_location;
else
m_req.url.assign(m_location.begin(), m_location.begin() + i);
m_man.queue_request(m_req, requester(), m_password);
return true;
}
}
++newline;

View File

@ -283,7 +283,7 @@ namespace libtorrent
void tracker_manager::tick()
{
std::vector<boost::shared_ptr<tracker_connection> >::iterator i;
tracker_connections_t::iterator i;
for (i = m_connections.begin(); i != m_connections.end(); ++i)
{
boost::shared_ptr<tracker_connection>& c = *i;
@ -297,8 +297,7 @@ namespace libtorrent
c->requester()->tracker_request_error(-1, e.what());
}
if (c->requester()) c->requester()->m_manager = 0;
m_connections.erase(i);
--i; // compensate for the remove
i = m_connections.erase(i);
}
}
@ -347,7 +346,7 @@ namespace libtorrent
}
catch(boost::bad_lexical_cast&)
{
throw std::runtime_error("invalid url");
throw std::runtime_error("invalid url: \"" + req.url + "\"");
}
}
else
@ -363,7 +362,8 @@ namespace libtorrent
if (protocol == "http")
{
con.reset(new http_tracker_connection(
req
*this
, req
, hostname
, port
, request_string
@ -398,7 +398,7 @@ namespace libtorrent
void tracker_manager::abort_request(request_callback* c)
{
assert(c != 0);
std::vector<boost::shared_ptr<tracker_connection> >::iterator i;
tracker_connections_t::iterator i;
for (i = m_connections.begin(); i != m_connections.end(); ++i)
{
if ((*i)->requester() == c)
@ -415,9 +415,9 @@ namespace libtorrent
// except those with a requester == 0 (since those are
// 'event=stopped'-requests)
std::vector<boost::shared_ptr<tracker_connection> > keep_connections;
tracker_connections_t keep_connections;
for (std::vector<boost::shared_ptr<tracker_connection> >::const_iterator i =
for (tracker_connections_t::const_iterator i =
m_connections.begin();
i != m_connections.end();
++i)
@ -430,10 +430,8 @@ namespace libtorrent
bool tracker_manager::send_finished() const
{
for (std::vector<boost::shared_ptr<tracker_connection> >::const_iterator i =
m_connections.begin();
i != m_connections.end();
++i)
for (tracker_connections_t::const_iterator i =
m_connections.begin(); i != m_connections.end(); ++i)
{
if (!(*i)->send_finished()) return false;
}