lt R_0_13 2366 sync

This commit is contained in:
Marcos Pinto 2008-06-01 23:37:15 +00:00
parent 4f0e77c68e
commit 44293bf6bd
23 changed files with 237 additions and 95 deletions

View File

@ -58,10 +58,12 @@ namespace libtorrent
tracker_alert(torrent_handle const& h tracker_alert(torrent_handle const& h
, int times , int times
, int status , int status
, std::string const& url_
, std::string const& msg) , std::string const& msg)
: torrent_alert(h, alert::warning, msg) : torrent_alert(h, alert::warning, msg)
, times_in_row(times) , times_in_row(times)
, status_code(status) , status_code(status)
, url(url_)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
@ -69,6 +71,7 @@ namespace libtorrent
int times_in_row; int times_in_row;
int status_code; int status_code;
std::string url;
}; };
struct TORRENT_EXPORT tracker_warning_alert: torrent_alert struct TORRENT_EXPORT tracker_warning_alert: torrent_alert

View File

@ -132,7 +132,6 @@ struct bandwidth_manager
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_lock& l) const
{ {
TORRENT_ASSERT(l.locked());
for (typename history_t::const_iterator i for (typename history_t::const_iterator i
= m_history.begin(), end(m_history.end()); i != end; ++i) = m_history.begin(), end(m_history.end()); i != end; ++i)
{ {
@ -265,7 +264,6 @@ private:
void hand_out_bandwidth(boost::mutex::scoped_lock& l) void hand_out_bandwidth(boost::mutex::scoped_lock& l)
{ {
TORRENT_ASSERT(l.locked());
// if we're already handing out bandwidth, just return back // if we're already handing out bandwidth, just return back
// to the loop further down on the callstack // to the loop further down on the callstack
if (m_in_hand_out_bandwidth) return; if (m_in_hand_out_bandwidth) return;

View File

@ -100,6 +100,7 @@ namespace libtorrent
bt_peer_connection( bt_peer_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo); , policy::peer* peerinfo);
~bt_peer_connection(); ~bt_peer_connection();

View File

@ -167,6 +167,8 @@ namespace libtorrent
#endif #endif
entry* find_key(char const* key); entry* find_key(char const* key);
entry const* find_key(char const* key) const; entry const* find_key(char const* key) const;
entry* find_key(std::string const& key);
entry const* find_key(std::string const& key) const;
void print(std::ostream& os, int indent = 0) const; void print(std::ostream& os, int indent = 0) const;

View File

@ -52,7 +52,7 @@ namespace libtorrent
struct http_connection; struct http_connection;
typedef boost::function<void(asio::error_code const& typedef boost::function<void(asio::error_code const&
, http_parser const&, char const* data, int size)> http_handler; , http_parser const&, char const* data, int size, http_connection&)> http_handler;
typedef boost::function<void(http_connection&)> http_connect_handler; typedef boost::function<void(http_connection&)> http_connect_handler;
@ -136,6 +136,7 @@ private:
bool m_called; bool m_called;
std::string m_hostname; std::string m_hostname;
std::string m_port; std::string m_port;
std::string m_url;
// the current download limit, in bytes per second // the current download limit, in bytes per second
// 0 is unlimited. // 0 is unlimited.

View File

@ -120,6 +120,7 @@ namespace libtorrent
peer_connection( peer_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo); , policy::peer* peerinfo);
virtual ~peer_connection(); virtual ~peer_connection();

View File

@ -141,6 +141,9 @@ namespace libtorrent
iterator begin() { return m_number; } iterator begin() { return m_number; }
iterator end() { return m_number+number_size; } iterator end() { return m_number+number_size; }
std::string to_string() const
{ return std::string((char const*)&m_number[0], number_size); }
private: private:
unsigned char m_number[number_size]; unsigned char m_number[number_size];

View File

@ -95,6 +95,7 @@ namespace libtorrent
typedef asio::io_service io_service; typedef asio::io_service io_service;
using asio::async_write; using asio::async_write;
using asio::error_code;
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer; typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer;

View File

@ -255,7 +255,7 @@ namespace libtorrent
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <Windows.h> #include <windows.h>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent

View File

@ -94,13 +94,14 @@ private:
struct rootdevice; struct rootdevice;
void on_upnp_xml(asio::error_code const& e void on_upnp_xml(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d); , libtorrent::http_parser const& p, rootdevice& d
, http_connection& c);
void on_upnp_map_response(asio::error_code const& e void on_upnp_map_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d , libtorrent::http_parser const& p, rootdevice& d
, int mapping); , int mapping, http_connection& c);
void on_upnp_unmap_response(asio::error_code const& e void on_upnp_unmap_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d , libtorrent::http_parser const& p, rootdevice& d
, int mapping); , int mapping, http_connection& c);
void on_expire(asio::error_code const& e); void on_expire(asio::error_code const& e);
void map_port(rootdevice& d, int i); void map_port(rootdevice& d, int i);

View File

@ -125,8 +125,9 @@ namespace libtorrent
bt_peer_connection::bt_peer_connection( bt_peer_connection::bt_peer_connection(
session_impl& ses session_impl& ses
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote
, policy::peer* peerinfo) , policy::peer* peerinfo)
: peer_connection(ses, s, peerinfo) : peer_connection(ses, s, remote, peerinfo)
, m_state(read_protocol_identifier) , m_state(read_protocol_identifier)
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
, m_supports_extensions(false) , m_supports_extensions(false)

View File

@ -54,19 +54,6 @@ namespace
TORRENT_ASSERT(o); TORRENT_ASSERT(o);
o->~T(); o->~T();
} }
struct compare_string
{
compare_string(char const* s): m_str(s) {}
bool operator()(
std::pair<std::string
, libtorrent::entry> const& e) const
{
return m_str && e.first == m_str;
}
char const* m_str;
};
} }
namespace libtorrent namespace libtorrent
@ -94,6 +81,16 @@ namespace libtorrent
} }
entry& entry::operator[](char const* key) entry& entry::operator[](char const* key)
{
dictionary_type::iterator i = dict().find(key);
if (i != dict().end()) return i->second;
dictionary_type::iterator ret = dict().insert(
dict().begin()
, std::make_pair(key, entry()));
return ret->second;
}
entry& entry::operator[](std::string const& key)
{ {
dictionary_type::iterator i = dict().find(key); dictionary_type::iterator i = dict().find(key);
if (i != dict().end()) return i->second; if (i != dict().end()) return i->second;
@ -103,21 +100,11 @@ namespace libtorrent
return ret->second; return ret->second;
} }
entry& entry::operator[](std::string const& key)
{
return (*this)[key.c_str()];
}
entry* entry::find_key(char const* key) entry* entry::find_key(char const* key)
{ {
dictionary_type::iterator i = std::find_if( dictionary_type::iterator i = dict().find(key);
dict().begin()
, dict().end()
, compare_string(key));
if (i == dict().end()) return 0; if (i == dict().end()) return 0;
return &i->second; return &i->second;
} }
entry const* entry::find_key(char const* key) const entry const* entry::find_key(char const* key) const
@ -127,6 +114,20 @@ namespace libtorrent
return &i->second; return &i->second;
} }
entry* entry::find_key(std::string const& key)
{
dictionary_type::iterator i = dict().find(key);
if (i == dict().end()) return 0;
return &i->second;
}
entry const* entry::find_key(std::string const& key) const
{
dictionary_type::const_iterator i = dict().find(key);
if (i == dict().end()) return 0;
return &i->second;
}
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
const entry& entry::operator[](char const* key) const const entry& entry::operator[](char const* key) const
{ {

View File

@ -61,6 +61,7 @@ void http_connection::get(std::string const& url, time_duration timeout
headers << "Authorization: Basic " << base64encode(auth) << "\r\n"; headers << "Authorization: Basic " << base64encode(auth) << "\r\n";
headers << "\r\n"; headers << "\r\n";
sendbuffer = headers.str(); sendbuffer = headers.str();
m_url = url;
start(hostname, boost::lexical_cast<std::string>(port), timeout, handle_redirects); start(hostname, boost::lexical_cast<std::string>(port), timeout, handle_redirects);
} }
@ -190,7 +191,7 @@ void http_connection::callback(asio::error_code const& e, char const* data, int
if (!m_bottled || !m_called) if (!m_bottled || !m_called)
{ {
m_called = true; m_called = true;
if (m_handler) m_handler(e, m_parser, data, size); if (m_handler) m_handler(e, m_parser, data, size, *this);
} }
} }
@ -269,8 +270,8 @@ void http_connection::on_read(asio::error_code const& e
catch (std::exception&) catch (std::exception&)
{ {
m_timer.cancel(); m_timer.cancel();
m_handler(asio::error::fault, m_parser, 0, 0); callback(asio::error::fault, 0, 0);
m_handler.clear(); close();
return; return;
} }
@ -282,17 +283,50 @@ void http_connection::on_read(asio::error_code const& e
if (code >= 300 && code < 400) if (code >= 300 && code < 400)
{ {
// attempt a redirect // attempt a redirect
std::string const& url = m_parser.header("location"); std::string const& location = m_parser.header("location");
if (url.empty()) if (location.empty())
{ {
// missing location header // missing location header
callback(e); callback(asio::error::fault);
close();
return; return;
} }
asio::error_code ec; try
m_sock.close(ec); {
get(url, m_timeout, m_redirects - 1); asio::error_code ec;
m_sock.close(ec);
get(location, m_timeout, m_redirects - 1);
return;
}
catch (std::exception& e)
{
// some broken web servers send out relative paths
// in the location header.
std::string url = m_url;
// remove the leaf filename
std::size_t i = url.find_last_of('/');
if (i == std::string::npos)
{
url += '/';
}
else
{
url.resize(i + 1);
}
url += location;
try
{
get(url, m_timeout, m_redirects - 1);
}
catch (std::exception& e)
{
// location header is invalid
callback(asio::error::fault);
close();
}
}
return; return;
} }

View File

@ -904,9 +904,7 @@ namespace libtorrent
if (tracker_req().kind == tracker_request::scrape_request) if (tracker_req().kind == tracker_request::scrape_request)
{ {
std::string ih; std::string ih = tracker_req().info_hash.to_string();
std::copy(tracker_req().info_hash.begin(), tracker_req().info_hash.end()
, std::back_inserter(ih));
entry scrape_data = e["files"][ih]; entry scrape_data = e["files"][ih];
int complete = -1; int complete = -1;

View File

@ -403,7 +403,7 @@ void node_impl::on_announce(msg const& m, msg& reply)
torrent_entry& v = m_map[m.info_hash]; torrent_entry& v = m_map[m.info_hash];
peer_entry e; peer_entry e;
e.addr = tcp::endpoint(m.addr.address(), m.addr.port()); e.addr = tcp::endpoint(m.addr.address(), m.port);
e.added = time_now(); e.added = time_now();
std::set<peer_entry>::iterator i = v.peers.find(e); std::set<peer_entry>::iterator i = v.peers.find(e);
if (i != v.peers.end()) v.peers.erase(i++); if (i != v.peers.end()) v.peers.erase(i++);

View File

@ -65,7 +65,7 @@ namespace libtorrent
session_impl& ses session_impl& ses
, boost::weak_ptr<torrent> tor , boost::weak_ptr<torrent> tor
, shared_ptr<socket_type> s , shared_ptr<socket_type> s
, tcp::endpoint const& remote , tcp::endpoint const& endp
, policy::peer* peerinfo) , policy::peer* peerinfo)
: :
#ifndef NDEBUG #ifndef NDEBUG
@ -85,7 +85,7 @@ namespace libtorrent
, m_last_receive(time_now()) , m_last_receive(time_now())
, m_last_sent(time_now()) , m_last_sent(time_now())
, m_socket(s) , m_socket(s)
, m_remote(remote) , m_remote(endp)
, m_torrent(tor) , m_torrent(tor)
, m_active(true) , m_active(true)
, m_peer_interested(false) , m_peer_interested(false)
@ -145,6 +145,7 @@ namespace libtorrent
peer_connection::peer_connection( peer_connection::peer_connection(
session_impl& ses session_impl& ses
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& endp
, policy::peer* peerinfo) , policy::peer* peerinfo)
: :
#ifndef NDEBUG #ifndef NDEBUG
@ -164,6 +165,7 @@ namespace libtorrent
, m_last_receive(time_now()) , m_last_receive(time_now())
, m_last_sent(time_now()) , m_last_sent(time_now())
, m_socket(s) , m_socket(s)
, m_remote(endp)
, m_active(false) , m_active(false)
, m_peer_interested(false) , m_peer_interested(false)
, m_peer_choked(true) , m_peer_choked(true)
@ -209,8 +211,9 @@ namespace libtorrent
m_remote = m_socket->remote_endpoint(); m_remote = m_socket->remote_endpoint();
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
TORRENT_ASSERT(m_socket->remote_endpoint() == remote()); error_code ec;
m_logger = m_ses.create_log(remote().address().to_string() + "_" TORRENT_ASSERT(m_socket->remote_endpoint(ec) == remote());
m_logger = m_ses.create_log(remote().address().to_string(ec) + "_"
+ boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port()); + boost::lexical_cast<std::string>(remote().port()), m_ses.listen_port());
(*m_logger) << "*** INCOMING CONNECTION\n"; (*m_logger) << "*** INCOMING CONNECTION\n";
#endif #endif
@ -1434,10 +1437,8 @@ namespace libtorrent
if (t->alerts().should_post(alert::fatal)) if (t->alerts().should_post(alert::fatal))
{ {
if (j.str != "write failed: No space left on device"){ std::string err = "torrent paused: disk write error, " + j.str;
std::string err = "torrent paused: disk write error, " + j.str; t->alerts().post_alert(file_error_alert(t->get_handle(), err));
t->alerts().post_alert(file_error_alert(t->get_handle(), err));
}
} }
t->pause(); t->pause();
return; return;

View File

@ -1093,7 +1093,13 @@ namespace detail
// check if we have any active torrents // check if we have any active torrents
// if we don't reject the connection // if we don't reject the connection
if (m_torrents.empty()) return; if (m_torrents.empty())
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << " There are no torrents, disconnect\n";
#endif
return;
}
bool has_active_torrent = false; bool has_active_torrent = false;
for (torrent_map::iterator i = m_torrents.begin() for (torrent_map::iterator i = m_torrents.begin()
@ -1105,10 +1111,16 @@ namespace detail
break; break;
} }
} }
if (!has_active_torrent) return; if (!has_active_torrent)
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << " There are no _active_ torrents, disconnect\n";
#endif
return;
}
boost::intrusive_ptr<peer_connection> c( boost::intrusive_ptr<peer_connection> c(
new bt_peer_connection(*this, s, 0)); new bt_peer_connection(*this, s, endp, 0));
#ifndef NDEBUG #ifndef NDEBUG
c->m_in_constructor = false; c->m_in_constructor = false;
#endif #endif

View File

@ -499,8 +499,15 @@ namespace libtorrent
std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string()); std::pair<iter_t, bool> ret = directories.insert((m_save_path / bp).string());
bp = bp.branch_path(); bp = bp.branch_path();
} }
#if defined(_WIN32) && defined(UNICODE)
try
{ fs::remove(safe_convert(p)); }
catch (std::exception& e)
{ error = e.what(); }
#else
if (std::remove(p.c_str()) != 0 && errno != ENOENT) if (std::remove(p.c_str()) != 0 && errno != ENOENT)
error = std::strerror(errno); error = std::strerror(errno);
#endif
} }
// remove the directories. Reverse order to delete // remove the directories. Reverse order to delete
@ -509,8 +516,15 @@ namespace libtorrent
for (std::set<std::string>::reverse_iterator i = directories.rbegin() for (std::set<std::string>::reverse_iterator i = directories.rbegin()
, end(directories.rend()); i != end; ++i) , end(directories.rend()); i != end; ++i)
{ {
#if defined(_WIN32) && defined(UNICODE)
try
{ fs::remove(safe_convert(*i)); }
catch (std::exception& e)
{ error = e.what(); }
#else
if (std::remove(i->c_str()) != 0 && errno != ENOENT) if (std::remove(i->c_str()) != 0 && errno != ENOENT)
error = std::strerror(errno); error = std::strerror(errno);
#endif
} }
if (!error.empty()) throw std::runtime_error(error); if (!error.empty()) throw std::runtime_error(error);
@ -1688,6 +1702,12 @@ namespace libtorrent
try try
{ {
if (m_info->num_pieces() == 0)
{
m_state = state_create_files;
return std::make_pair(false, 1.f);
}
// initialization for the full check // initialization for the full check
if (m_hash_to_piece.empty()) if (m_hash_to_piece.empty())
{ {
@ -1915,7 +1935,7 @@ namespace libtorrent
{ {
// find the file that failed, and skip all the blocks in that file // find the file that failed, and skip all the blocks in that file
size_type file_offset = 0; size_type file_offset = 0;
size_type current_offset = m_current_slot * m_info->piece_length(); size_type current_offset = size_type(m_current_slot) * m_info->piece_length();
for (torrent_info::file_iterator i = m_info->begin_files(true); for (torrent_info::file_iterator i = m_info->begin_files(true);
i != m_info->end_files(true); ++i) i != m_info->end_files(true); ++i)
{ {
@ -2182,7 +2202,8 @@ namespace libtorrent
if (m_unallocated_slots.empty() && m_state == state_finished) if (m_unallocated_slots.empty() && m_state == state_finished)
{ {
TORRENT_ASSERT(m_storage_mode != storage_mode_compact); TORRENT_ASSERT(m_storage_mode != storage_mode_compact
|| m_info->num_pieces() == 0);
} }
if (m_storage_mode != storage_mode_compact) if (m_storage_mode != storage_mode_compact)

View File

@ -1635,8 +1635,22 @@ namespace libtorrent
std::string hostname; std::string hostname;
int port; int port;
std::string path; std::string path;
boost::tie(protocol, auth, hostname, port, path)
= parse_url_components(url); try
{
boost::tie(protocol, auth, hostname, port, path)
= parse_url_components(url);
}
catch (std::exception& e)
{
if (m_ses.m_alerts.should_post(alert::warning))
{
m_ses.m_alerts.post_alert(
url_seed_alert(get_handle(), url, e.what()));
}
remove_url_seed(url);
return;
}
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
if (protocol != "http" && protocol != "https") if (protocol != "http" && protocol != "https")
@ -1691,6 +1705,18 @@ namespace libtorrent
} }
else else
{ {
if (m_ses.m_port_filter.access(port) & port_filter::blocked)
{
if (m_ses.m_alerts.should_post(alert::warning))
{
m_ses.m_alerts.post_alert(
url_seed_alert(get_handle(), url, "port blocked by port-filter"));
}
// never try it again
remove_url_seed(url);
return;
}
tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port)); tcp::resolver::query q(hostname, boost::lexical_cast<std::string>(port));
m_host_resolver.async_resolve(q, m_ses.m_strand.wrap( m_host_resolver.async_resolve(q, m_ses.m_strand.wrap(
bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url bind(&torrent::on_name_lookup, shared_from_this(), _1, _2, url
@ -1733,8 +1759,21 @@ namespace libtorrent
using boost::tuples::ignore; using boost::tuples::ignore;
std::string hostname; std::string hostname;
int port; int port;
boost::tie(ignore, ignore, hostname, port, ignore) try
= parse_url_components(url); {
boost::tie(ignore, ignore, hostname, port, ignore)
= parse_url_components(url);
}
catch (std::exception& e)
{
if (m_ses.m_alerts.should_post(alert::warning))
{
m_ses.m_alerts.post_alert(
url_seed_alert(get_handle(), url, e.what()));
}
remove_url_seed(url);
return;
}
if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked) if (m_ses.m_ip_filter.access(a.address()) & ip_filter::blocked)
{ {
@ -1743,6 +1782,7 @@ namespace libtorrent
m_ses.m_alerts.post_alert(peer_blocked_alert(a.address() m_ses.m_alerts.post_alert(peer_blocked_alert(a.address()
, "proxy (" + hostname + ") blocked by IP filter")); , "proxy (" + hostname + ") blocked by IP filter"));
} }
remove_url_seed(url);
return; return;
} }
@ -3226,7 +3266,7 @@ namespace libtorrent
--filtered_pieces; --filtered_pieces;
} }
st.total_wanted -= filtered_pieces * m_torrent_file->piece_length(); st.total_wanted -= size_type(filtered_pieces) * m_torrent_file->piece_length();
} }
TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done); TORRENT_ASSERT(st.total_wanted >= st.total_wanted_done);
@ -3290,7 +3330,7 @@ namespace libtorrent
if (r.kind == tracker_request::announce_request) if (r.kind == tracker_request::announce_request)
{ {
m_ses.m_alerts.post_alert(tracker_alert(get_handle() m_ses.m_alerts.post_alert(tracker_alert(get_handle()
, m_failed_trackers + 1, 0, s.str())); , m_failed_trackers + 1, 0, r.url, s.str()));
} }
else if (r.kind == tracker_request::scrape_request) else if (r.kind == tracker_request::scrape_request)
{ {
@ -3322,7 +3362,7 @@ namespace libtorrent
if (r.kind == tracker_request::announce_request) if (r.kind == tracker_request::announce_request)
{ {
m_ses.m_alerts.post_alert(tracker_alert(get_handle() m_ses.m_alerts.post_alert(tracker_alert(get_handle()
, m_failed_trackers + 1, response_code, s.str())); , m_failed_trackers + 1, response_code, r.url, s.str()));
} }
else if (r.kind == tracker_request::scrape_request) else if (r.kind == tracker_request::scrape_request)
{ {

View File

@ -443,14 +443,17 @@ namespace libtorrent
void torrent_info::read_torrent_info(const entry& torrent_file) void torrent_info::read_torrent_info(const entry& torrent_file)
{ {
// extract the url of the tracker // extract the url of the tracker
if (entry const* i = torrent_file.find_key("announce-list")) entry const* i = torrent_file.find_key("announce-list");
if (i && i->type() == entry::list_t)
{ {
const entry::list_type& l = i->list(); const entry::list_type& l = i->list();
for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j) for (entry::list_type::const_iterator j = l.begin(); j != l.end(); ++j)
{ {
if (j->type() != entry::list_t) continue;
const entry::list_type& ll = j->list(); const entry::list_type& ll = j->list();
for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k) for (entry::list_type::const_iterator k = ll.begin(); k != ll.end(); ++k)
{ {
if (k->type() != entry::string_t) continue;
announce_entry e(k->string()); announce_entry e(k->string());
e.tier = (int)std::distance(l.begin(), j); e.tier = (int)std::distance(l.begin(), j);
m_urls.push_back(e); m_urls.push_back(e);
@ -823,7 +826,7 @@ namespace libtorrent
if (index == num_pieces()-1) if (index == num_pieces()-1)
{ {
size_type size = total_size() size_type size = total_size()
- (num_pieces() - 1) * piece_length(); - size_type(num_pieces() - 1) * piece_length();
TORRENT_ASSERT(size > 0); TORRENT_ASSERT(size > 0);
TORRENT_ASSERT(size <= piece_length()); TORRENT_ASSERT(size <= piece_length());
return int(size); return int(size);

View File

@ -424,13 +424,13 @@ namespace libtorrent
= std::find(url.begin(), url.end(), ':'); = std::find(url.begin(), url.end(), ':');
protocol.assign(start, end); protocol.assign(start, end);
if (end == url.end()) throw std::runtime_error("invalid url"); if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'");
++end; ++end;
if (end == url.end()) throw std::runtime_error("invalid url"); if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'");
if (*end != '/') throw std::runtime_error("invalid url"); if (*end != '/') throw std::runtime_error("invalid url '" + url + "'");
++end; ++end;
if (end == url.end()) throw std::runtime_error("invalid url"); if (end == url.end()) throw std::runtime_error("invalid url '" + url + "'");
if (*end != '/') throw std::runtime_error("invalid url"); if (*end != '/') throw std::runtime_error("invalid url '" + url + "'");
++end; ++end;
start = end; start = end;
@ -454,7 +454,7 @@ namespace libtorrent
if (start != url.end() && *start == '[') if (start != url.end() && *start == '[')
{ {
port_pos = std::find(start, url.end(), ']'); port_pos = std::find(start, url.end(), ']');
if (port_pos == url.end()) throw std::runtime_error("invalid hostname syntax"); if (port_pos == url.end()) throw std::runtime_error("invalid hostname syntax '" + url + "'");
port_pos = std::find(port_pos, url.end(), ':'); port_pos = std::find(port_pos, url.end(), ':');
} }
else else

View File

@ -71,7 +71,7 @@ upnp::upnp(io_service& ios, connection_queue& cc
, m_io_service(ios) , m_io_service(ios)
, m_strand(ios) , m_strand(ios)
, m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900) , m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900)
, m_strand.wrap(bind(&upnp::on_reply, self(), _1, _2, _3)), false) , bind(&upnp::on_reply, self(), _1, _2, _3), false)
, m_broadcast_timer(ios) , m_broadcast_timer(ios)
, m_refresh_timer(ios) , m_refresh_timer(ios)
, m_disabled(false) , m_disabled(false)
@ -119,8 +119,8 @@ void upnp::discover_device() try
++m_retry_count; ++m_retry_count;
m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count)); m_broadcast_timer.expires_from_now(milliseconds(250 * m_retry_count));
m_broadcast_timer.async_wait(m_strand.wrap(bind(&upnp::resend_request m_broadcast_timer.async_wait(bind(&upnp::resend_request
, self(), _1))); , self(), _1));
#ifdef TORRENT_UPNP_LOGGING #ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string() m_log << time_now_string()
@ -209,9 +209,10 @@ try
m_log << time_now_string() m_log << time_now_string()
<< " ==> connecting to " << d.url << std::endl; << " ==> connecting to " << d.url << std::endl;
#endif #endif
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2 , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
, boost::ref(d))))); , boost::ref(d), _5)));
d.upnp_connection->get(d.url); d.upnp_connection->get(d.url);
} }
catch (std::exception& e) catch (std::exception& e)
@ -358,8 +359,20 @@ try
std::string protocol; std::string protocol;
std::string auth; std::string auth;
// we don't have this device in our list. Add it // we don't have this device in our list. Add it
boost::tie(protocol, auth, d.hostname, d.port, d.path) try
= parse_url_components(d.url); {
boost::tie(protocol, auth, d.hostname, d.port, d.path)
= parse_url_components(d.url);
}
catch (std::exception& e)
{
#ifdef TORRENT_UPNP_LOGGING
m_log << time_now_string()
<< " <== (" << from << ") invalid url: '" << d.url
<< "'. Ignoring device" << std::endl;
#endif
return;
}
// ignore the auth here. It will be re-parsed // ignore the auth here. It will be re-parsed
// by the http connection later // by the http connection later
@ -444,9 +457,10 @@ try
m_log << time_now_string() m_log << time_now_string()
<< " ==> connecting to " << d.url << std::endl; << " ==> connecting to " << d.url << std::endl;
#endif #endif
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, self(), _1, _2 , m_cc, bind(&upnp::on_upnp_xml, self(), _1, _2
, boost::ref(d))))); , boost::ref(d), _5)));
d.upnp_connection->get(d.url); d.upnp_connection->get(d.url);
} }
catch (std::exception& e) catch (std::exception& e)
@ -552,9 +566,10 @@ void upnp::map_port(rootdevice& d, int i)
m_log << time_now_string() m_log << time_now_string()
<< " ==> connecting to " << d.hostname << std::endl; << " ==> connecting to " << d.hostname << std::endl;
#endif #endif
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, self(), _1, _2 , m_cc, bind(&upnp::on_upnp_map_response, self(), _1, _2
, boost::ref(d), i)), true , boost::ref(d), i, _5), true
, bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i))); , bind(&upnp::create_port_mapping, self(), _1, boost::ref(d), i)));
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port) d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
@ -609,9 +624,11 @@ void upnp::unmap_port(rootdevice& d, int i)
m_log << time_now_string() m_log << time_now_string()
<< " ==> connecting to " << d.hostname << std::endl; << " ==> connecting to " << d.hostname << std::endl;
#endif #endif
if (d.upnp_connection) d.upnp_connection->close();
d.upnp_connection.reset(new http_connection(m_io_service d.upnp_connection.reset(new http_connection(m_io_service
, m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, self(), _1, _2 , m_cc, bind(&upnp::on_upnp_unmap_response, self(), _1, _2
, boost::ref(d), i)), true , boost::ref(d), i, _5), true
, bind(&upnp::delete_port_mapping, self(), boost::ref(d), i))); , bind(&upnp::delete_port_mapping, self(), boost::ref(d), i)));
d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port) d.upnp_connection->start(d.hostname, boost::lexical_cast<std::string>(d.port)
, seconds(10)); , seconds(10));
@ -675,10 +692,11 @@ namespace
} }
void upnp::on_upnp_xml(asio::error_code const& e void upnp::on_upnp_xml(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d) try , libtorrent::http_parser const& p, rootdevice& d
, http_connection& c) try
{ {
TORRENT_ASSERT(d.magic == 1337); TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection) if (d.upnp_connection && d.upnp_connection.get() == &c)
{ {
d.upnp_connection->close(); d.upnp_connection->close();
d.upnp_connection.reset(); d.upnp_connection.reset();
@ -823,10 +841,11 @@ namespace
} }
void upnp::on_upnp_map_response(asio::error_code const& e void upnp::on_upnp_map_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try , libtorrent::http_parser const& p, rootdevice& d, int mapping
, http_connection& c) try
{ {
TORRENT_ASSERT(d.magic == 1337); TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection) if (d.upnp_connection && d.upnp_connection.get() == &c)
{ {
d.upnp_connection->close(); d.upnp_connection->close();
d.upnp_connection.reset(); d.upnp_connection.reset();
@ -945,7 +964,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|| next_expire > d.mapping[mapping].expires) || next_expire > d.mapping[mapping].expires)
{ {
m_refresh_timer.expires_at(d.mapping[mapping].expires); m_refresh_timer.expires_at(d.mapping[mapping].expires);
m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, self(), _1))); m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
} }
} }
else else
@ -969,10 +988,11 @@ catch (std::exception&)
}; };
void upnp::on_upnp_unmap_response(asio::error_code const& e void upnp::on_upnp_unmap_response(asio::error_code const& e
, libtorrent::http_parser const& p, rootdevice& d, int mapping) try , libtorrent::http_parser const& p, rootdevice& d, int mapping
, http_connection& c) try
{ {
TORRENT_ASSERT(d.magic == 1337); TORRENT_ASSERT(d.magic == 1337);
if (d.upnp_connection) if (d.upnp_connection && d.upnp_connection.get() == &c)
{ {
d.upnp_connection->close(); d.upnp_connection->close();
d.upnp_connection.reset(); d.upnp_connection.reset();
@ -1054,7 +1074,7 @@ void upnp::on_expire(asio::error_code const& e) try
if (next_expire != max_time()) if (next_expire != max_time())
{ {
m_refresh_timer.expires_at(next_expire); m_refresh_timer.expires_at(next_expire);
m_refresh_timer.async_wait(m_strand.wrap(bind(&upnp::on_expire, self(), _1))); m_refresh_timer.async_wait(bind(&upnp::on_expire, self(), _1));
} }
} }
catch (std::exception&) catch (std::exception&)

View File

@ -224,7 +224,7 @@ namespace libtorrent
request += "\r\nProxy-Connection: keep-alive"; request += "\r\nProxy-Connection: keep-alive";
} }
request += "\r\nRange: bytes="; request += "\r\nRange: bytes=";
request += boost::lexical_cast<std::string>(r.piece request += boost::lexical_cast<std::string>(size_type(r.piece)
* info.piece_length() + r.start); * info.piece_length() + r.start);
request += "-"; request += "-";
request += boost::lexical_cast<std::string>(r.piece request += boost::lexical_cast<std::string>(r.piece