lt sync 1717

This commit is contained in:
Marcos Pinto 2007-11-02 00:49:26 +00:00
commit 2eec0a766d
25 changed files with 496 additions and 536 deletions

View file

@ -178,9 +178,7 @@ namespace libtorrent
#endif #endif
friend struct checker_impl; friend struct checker_impl;
friend class invariant_access; friend class invariant_access;
typedef std::map<boost::shared_ptr<socket_type> typedef std::set<boost::intrusive_ptr<peer_connection> > connection_map;
, boost::intrusive_ptr<peer_connection> >
connection_map;
typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map; typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map;
session_impl( session_impl(
@ -190,7 +188,8 @@ namespace libtorrent
~session_impl(); ~session_impl();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext); void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(
torrent*, void*)> ext);
#endif #endif
void operator()(); void operator()();
@ -214,7 +213,7 @@ namespace libtorrent
peer_id const& get_peer_id() const { return m_peer_id; } peer_id const& get_peer_id() const { return m_peer_id; }
void close_connection(boost::intrusive_ptr<peer_connection> const& p); void close_connection(boost::intrusive_ptr<peer_connection> const& p);
void connection_failed(boost::shared_ptr<socket_type> const& s void connection_failed(boost::intrusive_ptr<peer_connection> const& p
, tcp::endpoint const& a, char const* message); , tcp::endpoint const& a, char const* message);
void set_settings(session_settings const& s); void set_settings(session_settings const& s);
@ -342,8 +341,8 @@ namespace libtorrent
for (connection_map::const_iterator i = m_connections.begin() for (connection_map::const_iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i) , end(m_connections.end()); i != end; ++i)
{ {
send_buffer_capacity += i->second->send_buffer_capacity(); send_buffer_capacity += (*i)->send_buffer_capacity();
used_send_buffer += i->second->send_buffer_size(); used_send_buffer += (*i)->send_buffer_size();
} }
TORRENT_ASSERT(send_buffer_capacity >= used_send_buffer); TORRENT_ASSERT(send_buffer_capacity >= used_send_buffer);
m_buffer_usage_logger << log_time() << " send_buffer_size: " << send_buffer_capacity << std::endl; m_buffer_usage_logger << log_time() << " send_buffer_size: " << send_buffer_capacity << std::endl;
@ -375,12 +374,6 @@ namespace libtorrent
// buffers from. // buffers from.
boost::pool<> m_send_buffers; boost::pool<> m_send_buffers;
// this is where all active sockets are stored.
// the selector can sleep while there's no activity on
// them
io_service m_io_service;
asio::strand m_strand;
// the file pool that all storages in this session's // the file pool that all storages in this session's
// torrents uses. It sets a limit on the number of // torrents uses. It sets a limit on the number of
// open files by this session. // open files by this session.
@ -392,9 +385,17 @@ namespace libtorrent
// handles disk io requests asynchronously // handles disk io requests asynchronously
// peers have pointers into the disk buffer // peers have pointers into the disk buffer
// pool, and must be destructed before this // pool, and must be destructed before this
// object. // object. The disk thread relies on the file
// pool object, and must be destructed before
// m_files.
disk_io_thread m_disk_thread; disk_io_thread m_disk_thread;
// this is where all active sockets are stored.
// the selector can sleep while there's no activity on
// them
io_service m_io_service;
asio::strand m_strand;
// this is a list of half-open tcp connections // this is a list of half-open tcp connections
// (only outgoing connections) // (only outgoing connections)
// this has to be one of the last // this has to be one of the last
@ -646,7 +647,7 @@ namespace libtorrent
void debug_log(const std::string& line) void debug_log(const std::string& line)
{ {
(*m_ses.m_logger) << line << "\n"; (*m_ses.m_logger) << time_now_string() << " " << line << "\n";
} }
session_impl& m_ses; session_impl& m_ses;
}; };

View file

@ -56,6 +56,7 @@ public:
void done(int ticket); void done(int ticket);
void limit(int limit); void limit(int limit);
int limit() const; int limit() const;
void close();
#ifndef NDEBUG #ifndef NDEBUG

View file

@ -130,6 +130,8 @@ namespace libtorrent
, proxy_settings const& ps , proxy_settings const& ps
, std::string const& password = ""); , std::string const& password = "");
void close();
private: private:
boost::intrusive_ptr<http_tracker_connection> self() boost::intrusive_ptr<http_tracker_connection> self()

View file

@ -367,8 +367,12 @@ namespace libtorrent
return boost::optional<piece_block_progress>(); return boost::optional<piece_block_progress>();
} }
void send_buffer(char const* begin, int size); // these functions are virtual to let bt_peer_connection hook into them
buffer::interval allocate_send_buffer(int size); // and encrypt the content
virtual void send_buffer(char const* begin, int size);
virtual buffer::interval allocate_send_buffer(int size);
virtual void setup_send();
template <class Destructor> template <class Destructor>
void append_send_buffer(char* buffer, int size, Destructor const& destructor) void append_send_buffer(char* buffer, int size, Destructor const& destructor)
{ {
@ -378,7 +382,6 @@ namespace libtorrent
m_ses.log_buffer_usage(); m_ses.log_buffer_usage();
#endif #endif
} }
void setup_send();
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void set_country(char const* c) void set_country(char const* c)
@ -466,9 +469,6 @@ namespace libtorrent
// the peer belongs to. // the peer belongs to.
aux::session_impl& m_ses; aux::session_impl& m_ses;
boost::intrusive_ptr<peer_connection> self()
{ return boost::intrusive_ptr<peer_connection>(this); }
// called from the main loop when this connection has any // called from the main loop when this connection has any
// work to do. // work to do.
void on_send_data(asio::error_code const& error void on_send_data(asio::error_code const& error

View file

@ -85,6 +85,7 @@ namespace libtorrent
// the tracker, pex, lsd or dht. // the tracker, pex, lsd or dht.
policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid
, int source, char flags); , int source, char flags);
void update_peer_port(int port, policy::peer* p, int src);
// called when an incoming connection is accepted // called when an incoming connection is accepted
void new_connection(peer_connection& c); void new_connection(peer_connection& c);
@ -219,6 +220,8 @@ namespace libtorrent
typedef std::multimap<address, peer>::const_iterator const_iterator; typedef std::multimap<address, peer>::const_iterator const_iterator;
iterator begin_peer() { return m_peers.begin(); } iterator begin_peer() { return m_peers.begin(); }
iterator end_peer() { return m_peers.end(); } iterator end_peer() { return m_peers.end(); }
const_iterator begin_peer() const { return m_peers.begin(); }
const_iterator end_peer() const { return m_peers.end(); }
bool connect_one_peer(); bool connect_one_peer();
bool disconnect_one_peer(); bool disconnect_one_peer();

View file

@ -345,7 +345,7 @@ namespace libtorrent
// used to move pieces while expanding // used to move pieces while expanding
// the storage from compact allocation // the storage from compact allocation
// to full allocation // to full allocation
buffer m_scratch_buffer; buffer m_scratch_buffer;
buffer m_scratch_buffer2; buffer m_scratch_buffer2;
// the piece that is in the scratch buffer // the piece that is in the scratch buffer
int m_scratch_piece; int m_scratch_piece;

View file

@ -171,7 +171,7 @@ namespace libtorrent
boost::tuples::tuple<size_type, size_type> bytes_done() const; boost::tuples::tuple<size_type, size_type> bytes_done() const;
size_type quantized_bytes_done() const; size_type quantized_bytes_done() const;
void ip_filter_updated() { m_policy->ip_filter_updated(); } void ip_filter_updated() { m_policy.ip_filter_updated(); }
void pause(); void pause();
void resume(); void resume();
@ -204,7 +204,7 @@ namespace libtorrent
tcp::endpoint const& get_interface() const { return m_net_interface; } tcp::endpoint const& get_interface() const { return m_net_interface; }
void connect_to_url_seed(std::string const& url); void connect_to_url_seed(std::string const& url);
peer_connection* connect_to_peer(policy::peer* peerinfo); bool connect_to_peer(policy::peer* peerinfo) throw();
void set_ratio(float ratio) void set_ratio(float ratio)
{ TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; } { TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; }
@ -276,31 +276,12 @@ namespace libtorrent
bool want_more_peers() const; bool want_more_peers() const;
bool try_connect_peer(); bool try_connect_peer();
peer_connection* connection_for(tcp::endpoint const& a)
{
peer_iterator i = m_connections.find(a);
if (i == m_connections.end()) return 0;
return i->second;
}
#ifndef NDEBUG
void connection_for(address const& a, std::vector<peer_connection*>& pc)
{
for (peer_iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i)
{
if (i->first.address() == a) pc.push_back(i->second);
}
return;
}
#endif
// the number of peers that belong to this torrent // the number of peers that belong to this torrent
int num_peers() const { return (int)m_connections.size(); } int num_peers() const { return (int)m_connections.size(); }
int num_seeds() const; int num_seeds() const;
typedef std::map<tcp::endpoint, peer_connection*>::iterator peer_iterator; typedef std::set<peer_connection*>::iterator peer_iterator;
typedef std::map<tcp::endpoint, peer_connection*>::const_iterator const_peer_iterator; typedef std::set<peer_connection*>::const_iterator const_peer_iterator;
const_peer_iterator begin() const { return m_connections.begin(); } const_peer_iterator begin() const { return m_connections.begin(); }
const_peer_iterator end() const { return m_connections.end(); } const_peer_iterator end() const { return m_connections.end(); }
@ -495,11 +476,7 @@ namespace libtorrent
{ {
return m_picker.get() != 0; return m_picker.get() != 0;
} }
policy& get_policy() policy& get_policy() { return m_policy; }
{
TORRENT_ASSERT(m_policy);
return *m_policy;
}
piece_manager& filesystem(); piece_manager& filesystem();
torrent_info const& torrent_file() const torrent_info const& torrent_file() const
{ return *m_torrent_file; } { return *m_torrent_file; }
@ -550,7 +527,7 @@ namespace libtorrent
// to the checker thread for initial checking // to the checker thread for initial checking
// of the storage. // of the storage.
void set_metadata(entry const&); void set_metadata(entry const&);
private: private:
void on_files_deleted(int ret, disk_io_job const& j); void on_files_deleted(int ret, disk_io_job const& j);
@ -633,7 +610,7 @@ namespace libtorrent
#ifndef NDEBUG #ifndef NDEBUG
public: public:
#endif #endif
std::map<tcp::endpoint, peer_connection*> m_connections; std::set<peer_connection*> m_connections;
#ifndef NDEBUG #ifndef NDEBUG
private: private:
#endif #endif
@ -689,8 +666,6 @@ namespace libtorrent
// ----------------------------- // -----------------------------
boost::shared_ptr<policy> m_policy;
// a back reference to the session // a back reference to the session
// this torrent belongs to. // this torrent belongs to.
aux::session_impl& m_ses; aux::session_impl& m_ses;
@ -802,6 +777,8 @@ namespace libtorrent
// total_done - m_initial_done <= total_payload_download // total_done - m_initial_done <= total_payload_download
size_type m_initial_done; size_type m_initial_done;
#endif #endif
policy m_policy;
}; };
inline ptime torrent::next_announce() const inline ptime torrent::next_announce() const

View file

@ -184,6 +184,7 @@ namespace libtorrent
typedef boost::mutex mutex_t; typedef boost::mutex mutex_t;
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
bool m_abort;
}; };
struct TORRENT_EXPORT tracker_connection struct TORRENT_EXPORT tracker_connection
@ -202,7 +203,7 @@ namespace libtorrent
void fail(int code, char const* msg); void fail(int code, char const* msg);
void fail_timeout(); void fail_timeout();
void close(); virtual void close();
address const& bind_interface() const { return m_bind_interface; } address const& bind_interface() const { return m_bind_interface; }
protected: protected:

View file

@ -74,6 +74,8 @@ namespace libtorrent
, boost::weak_ptr<request_callback> c , boost::weak_ptr<request_callback> c
, session_settings const& stn); , session_settings const& stn);
void close();
private: private:
enum action_t enum action_t

View file

@ -190,7 +190,7 @@ namespace libtorrent
void broadcast_socket::close() void broadcast_socket::close()
{ {
m_on_receive.clear(); m_on_receive.clear();
for (std::list<socket_entry>::iterator i = m_sockets.begin() for (std::list<socket_entry>::iterator i = m_sockets.begin()
, end(m_sockets.end()); i != end; ++i) , end(m_sockets.end()); i != end; ++i)

View file

@ -582,9 +582,8 @@ namespace libtorrent
{ {
TORRENT_ASSERT(buf); TORRENT_ASSERT(buf);
TORRENT_ASSERT(size > 0); TORRENT_ASSERT(size > 0);
TORRENT_ASSERT(!m_rc4_encrypted || m_encrypted);
if (m_rc4_encrypted) if (m_encrypted && m_rc4_encrypted)
m_RC4_handler->encrypt(buf, size); m_RC4_handler->encrypt(buf, size);
peer_connection::send_buffer(buf, size); peer_connection::send_buffer(buf, size);
@ -592,9 +591,7 @@ namespace libtorrent
buffer::interval bt_peer_connection::allocate_send_buffer(int size) buffer::interval bt_peer_connection::allocate_send_buffer(int size)
{ {
TORRENT_ASSERT(!m_rc4_encrypted || m_encrypted); if (m_encrypted && m_rc4_encrypted)
if (m_rc4_encrypted)
{ {
TORRENT_ASSERT(m_enc_send_buffer.left() == 0); TORRENT_ASSERT(m_enc_send_buffer.left() == 0);
m_enc_send_buffer = peer_connection::allocate_send_buffer(size); m_enc_send_buffer = peer_connection::allocate_send_buffer(size);
@ -609,9 +606,7 @@ namespace libtorrent
void bt_peer_connection::setup_send() void bt_peer_connection::setup_send()
{ {
TORRENT_ASSERT(!m_rc4_encrypted || m_encrypted); if (m_encrypted && m_rc4_encrypted && m_enc_send_buffer.left())
if (m_rc4_encrypted && m_enc_send_buffer.left())
{ {
TORRENT_ASSERT(m_enc_send_buffer.begin); TORRENT_ASSERT(m_enc_send_buffer.begin);
TORRENT_ASSERT(m_enc_send_buffer.end); TORRENT_ASSERT(m_enc_send_buffer.end);
@ -1208,11 +1203,11 @@ namespace libtorrent
// there is supposed to be a remote listen port // there is supposed to be a remote listen port
if (entry* listen_port = root.find_key("p")) if (entry* listen_port = root.find_key("p"))
{ {
if (listen_port->type() == entry::int_t) if (listen_port->type() == entry::int_t
&& peer_info_struct() != 0)
{ {
tcp::endpoint adr(remote().address() t->get_policy().update_peer_port(listen_port->integer()
, (unsigned short)listen_port->integer()); , peer_info_struct(), peer_info::incoming);
t->get_policy().peer_from_tracker(adr, pid(), peer_info::incoming, 0);
} }
} }
// there should be a version too // there should be a version too

View file

@ -86,6 +86,11 @@ namespace libtorrent
try_connect(); try_connect();
} }
void connection_queue::close()
{
m_timer.cancel();
}
void connection_queue::limit(int limit) void connection_queue::limit(int limit)
{ m_half_open_limit = limit; } { m_half_open_limit = limit; }
@ -111,8 +116,14 @@ namespace libtorrent
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
if (!free_slots() || m_queue.empty()) if (!free_slots())
return; return;
if (m_queue.empty())
{
m_timer.cancel();
return;
}
std::list<entry>::iterator i = std::find_if(m_queue.begin() std::list<entry>::iterator i = std::find_if(m_queue.begin()
, m_queue.end(), boost::bind(&entry::connecting, _1) == false); , m_queue.end(), boost::bind(&entry::connecting, _1) == false);

View file

@ -344,6 +344,7 @@ namespace libtorrent
#ifndef NDEBUG #ifndef NDEBUG
m_current.storage = 0; m_current.storage = 0;
m_current.callback.clear();
#endif #endif
if (j.buffer && free_buffer) if (j.buffer && free_buffer)

View file

@ -489,7 +489,9 @@ namespace libtorrent
, boost::lexical_cast<std::string>(m_port)); , boost::lexical_cast<std::string>(m_port));
m_name_lookup.async_resolve(q, m_strand.wrap( m_name_lookup.async_resolve(q, m_strand.wrap(
boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2))); boost::bind(&http_tracker_connection::name_lookup, self(), _1, _2)));
set_timeout(m_settings.tracker_completion_timeout set_timeout(req.event == tracker_request::stopped
? m_settings.stop_tracker_timeout
: m_settings.tracker_completion_timeout
, m_settings.tracker_receive_timeout); , m_settings.tracker_receive_timeout);
} }
@ -503,6 +505,23 @@ namespace libtorrent
fail_timeout(); fail_timeout();
} }
void http_tracker_connection::close()
{
asio::error_code ec;
m_socket.close(ec);
m_name_lookup.cancel();
if (m_connection_ticket > -1) m_cc.done(m_connection_ticket);
m_connection_ticket = -1;
m_timed_out = true;
tracker_connection::close();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<request_callback> cb = requester();
std::stringstream msg;
msg << "http_tracker_connection::close() " << m_man.num_requests();
if (cb) cb->debug_log(msg.str());
#endif
}
void http_tracker_connection::name_lookup(asio::error_code const& error void http_tracker_connection::name_lookup(asio::error_code const& error
, tcp::resolver::iterator i) try , tcp::resolver::iterator i) try
{ {
@ -759,7 +778,6 @@ namespace libtorrent
if (m_parser.status_code() != 200) if (m_parser.status_code() != 200)
{ {
fail(m_parser.status_code(), m_parser.message().c_str()); fail(m_parser.status_code(), m_parser.message().c_str());
close();
return; return;
} }
@ -821,6 +839,7 @@ namespace libtorrent
TORRENT_ASSERT(false); TORRENT_ASSERT(false);
} }
#endif #endif
close();
} }
peer_entry http_tracker_connection::extract_peer_info(const entry& info) peer_entry http_tracker_connection::extract_peer_info(const entry& info)

View file

@ -504,11 +504,10 @@ namespace libtorrent { namespace
// extension and that has metadata // extension and that has metadata
int peers = 0; int peers = 0;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::map<tcp::endpoint, peer_connection*> conn_map; for (torrent::peer_iterator i = m_torrent.begin()
for (conn_map::iterator i = m_torrent.begin()
, end(m_torrent.end()); i != end; ++i) , end(m_torrent.end()); i != end; ++i)
{ {
bt_peer_connection* c = dynamic_cast<bt_peer_connection*>(i->second); bt_peer_connection* c = dynamic_cast<bt_peer_connection*>(*i);
if (c == 0) continue; if (c == 0) continue;
metadata_peer_plugin* p metadata_peer_plugin* p
= c->supports_extension<metadata_peer_plugin>(); = c->supports_extension<metadata_peer_plugin>();

View file

@ -390,7 +390,6 @@ namespace libtorrent
TORRENT_ASSERT(m_peer_info->connection == 0); TORRENT_ASSERT(m_peer_info->connection == 0);
boost::shared_ptr<torrent> t = m_torrent.lock(); boost::shared_ptr<torrent> t = m_torrent.lock();
if (t) TORRENT_ASSERT(t->connection_for(remote()) != this);
#endif #endif
} }
@ -1394,7 +1393,7 @@ namespace libtorrent
if (!t) if (!t)
{ {
m_ses.connection_failed(m_socket, remote(), j.str.c_str()); m_ses.connection_failed(self(), remote(), j.str.c_str());
return; return;
} }
@ -1944,7 +1943,7 @@ namespace libtorrent
(*m_ses.m_logger) << "CONNECTION TIMED OUT: " << m_remote.address().to_string() (*m_ses.m_logger) << "CONNECTION TIMED OUT: " << m_remote.address().to_string()
<< "\n"; << "\n";
#endif #endif
m_ses.connection_failed(m_socket, m_remote, "timed out"); m_ses.connection_failed(self(), m_remote, "timed out");
} }
void peer_connection::disconnect() void peer_connection::disconnect()
@ -2290,7 +2289,7 @@ namespace libtorrent
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "**ERROR**: " << e.what() << "\n"; (*m_logger) << "**ERROR**: " << e.what() << "\n";
#endif #endif
m_ses.connection_failed(m_socket, remote(), e.what()); m_ses.connection_failed(self(), remote(), e.what());
} }
} }
@ -2340,7 +2339,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock(); boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t) if (!t)
{ {
m_ses.connection_failed(m_socket, remote(), j.str.c_str()); m_ses.connection_failed(self(), remote(), j.str.c_str());
return; return;
} }
@ -2676,7 +2675,7 @@ namespace libtorrent
boost::shared_ptr<torrent> t = m_torrent.lock(); boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t) if (!t)
{ {
m_ses.connection_failed(m_socket, remote(), e.what()); m_ses.connection_failed(self(), remote(), e.what());
return; return;
} }
@ -2691,14 +2690,14 @@ namespace libtorrent
catch (std::exception& e) catch (std::exception& e)
{ {
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), e.what()); m_ses.connection_failed(self(), remote(), e.what());
} }
catch (...) catch (...)
{ {
// all exceptions should derive from std::exception // all exceptions should derive from std::exception
TORRENT_ASSERT(false); TORRENT_ASSERT(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), "connection failed for unknown reason"); m_ses.connection_failed(self(), remote(), "connection failed for unknown reason");
} }
bool peer_connection::can_write() const bool peer_connection::can_write() const
@ -2779,7 +2778,7 @@ namespace libtorrent
(*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string() (*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string()
<< ": " << e.message() << "\n"; << ": " << e.message() << "\n";
#endif #endif
m_ses.connection_failed(m_socket, m_remote, e.message().c_str()); m_ses.connection_failed(self(), m_remote, e.message().c_str());
return; return;
} }
@ -2799,14 +2798,14 @@ namespace libtorrent
catch (std::exception& ex) catch (std::exception& ex)
{ {
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), ex.what()); m_ses.connection_failed(self(), remote(), ex.what());
} }
catch (...) catch (...)
{ {
// all exceptions should derive from std::exception // all exceptions should derive from std::exception
TORRENT_ASSERT(false); TORRENT_ASSERT(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), "connection failed for unkown reason"); m_ses.connection_failed(self(), remote(), "connection failed for unkown reason");
} }
// -------------------------- // --------------------------
@ -2856,14 +2855,14 @@ namespace libtorrent
catch (std::exception& e) catch (std::exception& e)
{ {
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), e.what()); m_ses.connection_failed(self(), remote(), e.what());
} }
catch (...) catch (...)
{ {
// all exceptions should derive from std::exception // all exceptions should derive from std::exception
TORRENT_ASSERT(false); TORRENT_ASSERT(false);
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
m_ses.connection_failed(m_socket, remote(), "connection failed for unknown reason"); m_ses.connection_failed(self(), remote(), "connection failed for unknown reason");
} }
@ -2880,26 +2879,18 @@ namespace libtorrent
} }
boost::shared_ptr<torrent> t = m_torrent.lock(); boost::shared_ptr<torrent> t = m_torrent.lock();
if (!t) if (!t) return;
if (m_peer_info)
{ {
typedef session_impl::torrent_map torrent_map; policy::const_iterator i;
torrent_map& m = m_ses.m_torrents; for (i = t->get_policy().begin_peer();
for (torrent_map::iterator i = m.begin(), end(m.end()); i != end; ++i) i != t->get_policy().end_peer(); ++i)
{ {
torrent& t = *i->second; if (&i->second == m_peer_info) break;
TORRENT_ASSERT(t.connection_for(m_remote) != this);
} }
return; TORRENT_ASSERT(i != t->get_policy().end_peer());
} }
TORRENT_ASSERT(t->connection_for(remote()) != 0 || m_in_constructor);
if (!m_in_constructor && t->connection_for(remote()) != this
&& !m_ses.settings().allow_multiple_connections_per_ip)
{
TORRENT_ASSERT(false);
}
if (t->has_picker() && !t->is_aborted()) if (t->has_picker() && !t->is_aborted())
{ {
// make sure that pieces that have completed the download // make sure that pieces that have completed the download

View file

@ -82,13 +82,13 @@ namespace
// want to trade it's surplus uploads for downloads itself // want to trade it's surplus uploads for downloads itself
// (and we should not consider it free). If the share diff is // (and we should not consider it free). If the share diff is
// negative, there's no free download to get from this peer. // negative, there's no free download to get from this peer.
size_type diff = i->second->share_diff(); size_type diff = (*i)->share_diff();
TORRENT_ASSERT(diff < (std::numeric_limits<size_type>::max)()); TORRENT_ASSERT(diff < (std::numeric_limits<size_type>::max)());
if (i->second->is_peer_interested() || diff <= 0) if ((*i)->is_peer_interested() || diff <= 0)
continue; continue;
TORRENT_ASSERT(diff > 0); TORRENT_ASSERT(diff > 0);
i->second->add_free_upload(-diff); (*i)->add_free_upload(-diff);
accumulator += diff; accumulator += diff;
TORRENT_ASSERT(accumulator > 0); TORRENT_ASSERT(accumulator > 0);
} }
@ -109,10 +109,10 @@ namespace
size_type total_diff = 0; size_type total_diff = 0;
for (torrent::peer_iterator i = start; i != end; ++i) for (torrent::peer_iterator i = start; i != end; ++i)
{ {
size_type d = i->second->share_diff(); size_type d = (*i)->share_diff();
TORRENT_ASSERT(d < (std::numeric_limits<size_type>::max)()); TORRENT_ASSERT(d < (std::numeric_limits<size_type>::max)());
total_diff += d; total_diff += d;
if (!i->second->is_peer_interested() || i->second->share_diff() >= 0) continue; if (!(*i)->is_peer_interested() || (*i)->share_diff() >= 0) continue;
++num_peers; ++num_peers;
} }
@ -130,7 +130,7 @@ namespace
for (torrent::peer_iterator i = start; i != end; ++i) for (torrent::peer_iterator i = start; i != end; ++i)
{ {
peer_connection* p = i->second; peer_connection* p = *i;
if (!p->is_peer_interested() || p->share_diff() >= 0) continue; if (!p->is_peer_interested() || p->share_diff() >= 0) continue;
p->add_free_upload(upload_share); p->add_free_upload(upload_share);
free_upload -= upload_share; free_upload -= upload_share;
@ -904,7 +904,7 @@ namespace libtorrent
{ {
TORRENT_ASSERT(!c.is_local()); TORRENT_ASSERT(!c.is_local());
INVARIANT_CHECK; // INVARIANT_CHECK;
// if the connection comes from the tracker, // if the connection comes from the tracker,
// it's probably just a NAT-check. Ignore the // it's probably just a NAT-check. Ignore the
@ -932,10 +932,11 @@ namespace libtorrent
if (m_torrent->settings().allow_multiple_connections_per_ip) if (m_torrent->settings().allow_multiple_connections_per_ip)
{ {
i = std::find_if( tcp::endpoint remote = c.remote();
m_peers.begin() std::pair<iterator, iterator> range = m_peers.equal_range(remote.address());
, m_peers.end() i = std::find_if(range.first, range.second, match_peer_endpoint(remote));
, match_peer_connection(c));
if (i == range.second) i = m_peers.end();
} }
else else
{ {
@ -977,8 +978,6 @@ namespace libtorrent
i = m_peers.insert(std::make_pair(c.remote().address(), p)); i = m_peers.insert(std::make_pair(c.remote().address(), p));
} }
TORRENT_ASSERT(m_torrent->connection_for(c.remote()) == &c);
c.set_peer_info(&i->second); c.set_peer_info(&i->second);
TORRENT_ASSERT(i->second.connection == 0); TORRENT_ASSERT(i->second.connection == 0);
c.add_stat(i->second.prev_amount_download, i->second.prev_amount_upload); c.add_stat(i->second.prev_amount_download, i->second.prev_amount_upload);
@ -991,7 +990,38 @@ namespace libtorrent
// m_last_optimistic_disconnect = time_now(); // m_last_optimistic_disconnect = time_now();
} }
policy::peer* policy::peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid void policy::update_peer_port(int port, policy::peer* p, int src)
{
TORRENT_ASSERT(p != 0);
if (p->ip.port() == port) return;
if (m_torrent->settings().allow_multiple_connections_per_ip)
{
tcp::endpoint remote(p->ip.address(), port);
std::pair<iterator, iterator> range = m_peers.equal_range(remote.address());
iterator i = std::find_if(range.first, range.second
, match_peer_endpoint(remote));
if (i != m_peers.end())
{
policy::peer& pp = i->second;
if (pp.connection)
{
throw protocol_error("duplicate connection");
}
if (m_torrent->has_picker())
m_torrent->picker().clear_peer(&i->second);
m_peers.erase(i);
}
}
else
{
TORRENT_ASSERT(m_peers.count(p->ip.address()) == 1);
}
p->ip.port(port);
p->source |= src;
}
policy::peer* policy::peer_from_tracker(tcp::endpoint const& remote, peer_id const& pid
, int src, char flags) , int src, char flags)
{ {
// too expensive // too expensive
@ -1022,9 +1052,7 @@ namespace libtorrent
{ {
std::pair<iterator, iterator> range = m_peers.equal_range(remote.address()); std::pair<iterator, iterator> range = m_peers.equal_range(remote.address());
i = std::find_if(range.first, range.second, match_peer_endpoint(remote)); i = std::find_if(range.first, range.second, match_peer_endpoint(remote));
if (i == range.second) i = m_peers.end();
if (i == range.second)
i = std::find_if(m_peers.begin(), m_peers.end(), match_peer_id(pid));
} }
else else
{ {
@ -1066,9 +1094,6 @@ namespace libtorrent
{ {
i->second.type = peer::connectable; i->second.type = peer::connectable;
// in case we got the ip from a remote connection, port is
// not known, so save it. Client may also have changed port
// for some reason.
i->second.ip = remote; i->second.ip = remote;
i->second.source |= src; i->second.source |= src;
@ -1281,10 +1306,7 @@ namespace libtorrent
try try
{ {
p->second.connected = time_now(); if (!m_torrent->connect_to_peer(&p->second))
p->second.connection = m_torrent->connect_to_peer(&p->second);
TORRENT_ASSERT(p->second.connection == m_torrent->connection_for(p->second.ip));
if (p->second.connection == 0)
{ {
++p->second.failcount; ++p->second.failcount;
return false; return false;
@ -1396,6 +1418,7 @@ namespace libtorrent
void policy::check_invariant() const void policy::check_invariant() const
{ {
if (m_torrent->is_aborted()) return; if (m_torrent->is_aborted()) return;
int connected_peers = 0; int connected_peers = 0;
int total_connections = 0; int total_connections = 0;
@ -1414,20 +1437,14 @@ namespace libtorrent
{ {
TORRENT_ASSERT(unique_test.count(p.ip) == 0); TORRENT_ASSERT(unique_test.count(p.ip) == 0);
unique_test.insert(p.ip); unique_test.insert(p.ip);
TORRENT_ASSERT(i->first == p.ip.address());
// TORRENT_ASSERT(p.connection == 0 || p.ip == p.connection->remote());
} }
++total_connections; ++total_connections;
if (!p.connection) if (!p.connection)
{ {
continue; continue;
} }
if (!m_torrent->settings().allow_multiple_connections_per_ip)
{
std::vector<peer_connection*> conns;
m_torrent->connection_for(p.ip.address(), conns);
TORRENT_ASSERT(std::find_if(conns.begin(), conns.end()
, boost::bind(std::equal_to<peer_connection*>(), _1, p.connection))
!= conns.end());
}
if (p.optimistically_unchoked) if (p.optimistically_unchoked)
{ {
TORRENT_ASSERT(p.connection); TORRENT_ASSERT(p.connection);
@ -1444,10 +1461,10 @@ namespace libtorrent
for (torrent::const_peer_iterator i = m_torrent->begin(); for (torrent::const_peer_iterator i = m_torrent->begin();
i != m_torrent->end(); ++i) i != m_torrent->end(); ++i)
{ {
if (i->second->is_disconnecting()) continue; if ((*i)->is_disconnecting()) continue;
// ignore web_peer_connections since they are not managed // ignore web_peer_connections since they are not managed
// by the policy class // by the policy class
if (dynamic_cast<web_peer_connection*>(i->second)) continue; if (dynamic_cast<web_peer_connection*>(*i)) continue;
++num_torrent_peers; ++num_torrent_peers;
} }

View file

@ -547,8 +547,8 @@ namespace detail
, fingerprint const& cl_fprint , fingerprint const& cl_fprint
, char const* listen_interface) , char const* listen_interface)
: m_send_buffers(send_buffer_size) : m_send_buffers(send_buffer_size)
, m_strand(m_io_service)
, m_files(40) , m_files(40)
, m_strand(m_io_service)
, m_half_open(m_io_service) , m_half_open(m_io_service)
, m_download_channel(m_io_service, peer_connection::download_channel) , m_download_channel(m_io_service, peer_connection::download_channel)
, m_upload_channel(m_io_service, peer_connection::upload_channel) , m_upload_channel(m_io_service, peer_connection::upload_channel)
@ -675,6 +675,17 @@ namespace detail
if (m_dht) m_dht->stop(); if (m_dht) m_dht->stop();
#endif #endif
m_timer.cancel(); m_timer.cancel();
// close the listen sockets
for (std::list<listen_socket_t>::iterator i = m_listen_sockets.begin()
, end(m_listen_sockets.end()); i != end; ++i)
{
i->sock->close();
}
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " aborting all torrents\n";
#endif
// abort all torrents // abort all torrents
for (torrent_map::iterator i = m_torrents.begin() for (torrent_map::iterator i = m_torrents.begin()
, end(m_torrents.end()); i != end; ++i) , end(m_torrents.end()); i != end; ++i)
@ -682,7 +693,65 @@ namespace detail
i->second->abort(); i->second->abort();
} }
m_io_service.stop(); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " aborting all tracker requests\n";
#endif
m_tracker_manager.abort_all_requests();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " sending event=stopped to trackers\n";
int counter = 0;
#endif
for (torrent_map::iterator i = m_torrents.begin();
i != m_torrents.end(); ++i)
{
torrent& t = *i->second;
if ((!t.is_paused() || t.should_request())
&& !t.trackers().empty())
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
++counter;
#endif
tracker_request req = t.generate_tracker_request();
TORRENT_ASSERT(req.event == tracker_request::stopped);
req.listen_port = 0;
if (!m_listen_sockets.empty())
req.listen_port = m_listen_sockets.front().external_port;
req.key = m_key;
std::string login = i->second->tracker_login();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<tracker_logger> tl(new tracker_logger(*this));
m_tracker_loggers.push_back(tl);
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
, m_listen_interface.address(), tl);
#else
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
, m_listen_interface.address());
#endif
}
}
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " sent " << counter << " tracker stop requests\n";
#endif
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " aborting all connections (" << m_connections.size() << ")\n";
#endif
// abort all connections
while (!m_connections.empty())
{
#ifndef NDEBUG
int conn = m_connections.size();
#endif
(*m_connections.begin())->disconnect();
TORRENT_ASSERT(conn == m_connections.size() + 1);
}
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " shutting down connection queue\n";
#endif
m_half_open.close();
mutex::scoped_lock l2(m_checker_impl.m_mutex); mutex::scoped_lock l2(m_checker_impl.m_mutex);
// abort the checker thread // abort the checker thread
@ -974,16 +1043,16 @@ namespace detail
m_alerts.post_alert(peer_blocked_alert(endp.address() m_alerts.post_alert(peer_blocked_alert(endp.address()
, "incoming connection blocked by IP filter")); , "incoming connection blocked by IP filter"));
} }
return; return;
} }
// don't allow more connections than the max setting // don't allow more connections than the max setting
if (m_connections.size() > max_connections()) if (num_connections() > max_connections())
{ {
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << "number of connections limit exceeded (conns: " (*m_logger) << "number of connections limit exceeded (conns: "
<< num_connections() << ", limit: " << max_connections() << num_connections() << ", limit: " << max_connections()
<< "), connection rejected\n"; << "), connection rejected\n";
#endif #endif
return; return;
} }
@ -1010,7 +1079,7 @@ namespace detail
c->m_in_constructor = false; c->m_in_constructor = false;
#endif #endif
m_connections.insert(std::make_pair(s, c)); m_connections.insert(c);
} }
catch (std::exception& exc) catch (std::exception& exc)
{ {
@ -1019,7 +1088,7 @@ namespace detail
#endif #endif
}; };
void session_impl::connection_failed(boost::shared_ptr<socket_type> const& s void session_impl::connection_failed(boost::intrusive_ptr<peer_connection> const& peer
, tcp::endpoint const& a, char const* message) , tcp::endpoint const& a, char const* message)
#ifndef NDEBUG #ifndef NDEBUG
try try
@ -1030,7 +1099,7 @@ namespace detail
// too expensive // too expensive
// INVARIANT_CHECK; // INVARIANT_CHECK;
connection_map::iterator p = m_connections.find(s); connection_map::iterator p = m_connections.find(peer);
// the connection may have been disconnected in the receive or send phase // the connection may have been disconnected in the receive or send phase
if (p == m_connections.end()) return; if (p == m_connections.end()) return;
@ -1039,15 +1108,15 @@ namespace detail
m_alerts.post_alert( m_alerts.post_alert(
peer_error_alert( peer_error_alert(
a a
, p->second->pid() , (*p)->pid()
, message)); , message));
} }
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*p->second->m_logger) << "*** CONNECTION FAILED " << message << "\n"; (*(*p)->m_logger) << "*** CONNECTION FAILED " << message << "\n";
#endif #endif
p->second->set_failed(); (*p)->set_failed();
p->second->disconnect(); (*p)->disconnect();
} }
#ifndef NDEBUG #ifndef NDEBUG
catch (...) catch (...)
@ -1064,10 +1133,10 @@ namespace detail
// INVARIANT_CHECK; // INVARIANT_CHECK;
TORRENT_ASSERT(p->is_disconnecting()); TORRENT_ASSERT(p->is_disconnecting());
connection_map::iterator i = m_connections.find(p->get_socket()); connection_map::iterator i = m_connections.find(p);
if (i != m_connections.end()) if (i != m_connections.end())
{ {
if (!i->second->is_choked()) --m_num_unchoked; if (!(*i)->is_choked()) --m_num_unchoked;
m_connections.erase(i); m_connections.erase(i);
} }
} }
@ -1126,7 +1195,7 @@ namespace detail
for (connection_map::iterator i = m_connections.begin() for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i) , end(m_connections.end()); i != end; ++i)
{ {
if (i->second->is_connecting()) if ((*i)->is_connecting())
++num_half_open; ++num_half_open;
else else
++num_complete_connections; ++num_complete_connections;
@ -1214,7 +1283,7 @@ namespace detail
++i; ++i;
// if this socket has timed out // if this socket has timed out
// close it. // close it.
peer_connection& c = *j->second; peer_connection& c = *j->get();
if (c.has_timed_out()) if (c.has_timed_out())
{ {
if (m_alerts.should_post(alert::debug)) if (m_alerts.should_post(alert::debug))
@ -1281,7 +1350,7 @@ namespace detail
for (connection_map::iterator i = m_connections.begin() for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i) , end(m_connections.end()); i != end; ++i)
{ {
peer_connection* p = i->second.get(); peer_connection* p = i->get();
torrent* t = p->associated_torrent().lock().get(); torrent* t = p->associated_torrent().lock().get();
if (!p->peer_info_struct() if (!p->peer_info_struct()
|| t == 0 || t == 0
@ -1291,7 +1360,7 @@ namespace detail
|| (p->share_diff() < -free_upload_amount || (p->share_diff() < -free_upload_amount
&& !t->is_seed())) && !t->is_seed()))
{ {
if (!i->second->is_choked() && t) if (!(*i)->is_choked() && t)
{ {
policy::peer* pi = p->peer_info_struct(); policy::peer* pi = p->peer_info_struct();
if (pi && pi->optimistically_unchoked) if (pi && pi->optimistically_unchoked)
@ -1300,11 +1369,11 @@ namespace detail
// force a new optimistic unchoke // force a new optimistic unchoke
m_optimistic_unchoke_time_scaler = 0; m_optimistic_unchoke_time_scaler = 0;
} }
t->choke_peer(*i->second); t->choke_peer(*(*i));
} }
continue; continue;
} }
peers.push_back(i->second.get()); peers.push_back(i->get());
} }
// sort the peers that are eligible for unchoke by download rate and secondary // sort the peers that are eligible for unchoke by download rate and secondary
@ -1376,7 +1445,7 @@ namespace detail
for (connection_map::iterator i = m_connections.begin() for (connection_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i) , end(m_connections.end()); i != end; ++i)
{ {
peer_connection* p = i->second.get(); peer_connection* p = i->get();
TORRENT_ASSERT(p); TORRENT_ASSERT(p);
policy::peer* pi = p->peer_info_struct(); policy::peer* pi = p->peer_info_struct();
if (!pi) continue; if (!pi) continue;
@ -1407,21 +1476,21 @@ namespace detail
{ {
if (current_optimistic_unchoke != m_connections.end()) if (current_optimistic_unchoke != m_connections.end())
{ {
torrent* t = current_optimistic_unchoke->second->associated_torrent().lock().get(); torrent* t = (*current_optimistic_unchoke)->associated_torrent().lock().get();
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
current_optimistic_unchoke->second->peer_info_struct()->optimistically_unchoked = false; (*current_optimistic_unchoke)->peer_info_struct()->optimistically_unchoked = false;
t->choke_peer(*current_optimistic_unchoke->second); t->choke_peer(*current_optimistic_unchoke->get());
} }
else else
{ {
++m_num_unchoked; ++m_num_unchoked;
} }
torrent* t = optimistic_unchoke_candidate->second->associated_torrent().lock().get(); torrent* t = (*optimistic_unchoke_candidate)->associated_torrent().lock().get();
TORRENT_ASSERT(t); TORRENT_ASSERT(t);
bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->second); bool ret = t->unchoke_peer(*optimistic_unchoke_candidate->get());
TORRENT_ASSERT(ret); TORRENT_ASSERT(ret);
optimistic_unchoke_candidate->second->peer_info_struct()->optimistically_unchoked = true; (*optimistic_unchoke_candidate)->peer_info_struct()->optimistically_unchoked = true;
} }
} }
} }
@ -1484,96 +1553,11 @@ namespace detail
} }
while (!m_abort); while (!m_abort);
deadline_timer tracker_timer(m_io_service);
// this will remove the port mappings
if (m_natpmp.get())
m_natpmp->close();
if (m_upnp.get())
m_upnp->close();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " locking mutex\n"; (*m_logger) << time_now_string() << " locking mutex\n";
#endif #endif
session_impl::mutex_t::scoped_lock l(m_mutex); session_impl::mutex_t::scoped_lock l(m_mutex);
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " aborting all tracker requests\n";
#endif
m_tracker_manager.abort_all_requests();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " sending stopped to all torrent's trackers\n";
#endif
for (std::map<sha1_hash, boost::shared_ptr<torrent> >::iterator i =
m_torrents.begin(); i != m_torrents.end(); ++i)
{
i->second->abort();
// generate a tracker request in case the torrent is not paused
// (in which case it's not currently announced with the tracker)
// or if the torrent itself thinks we should request. Do not build
// a request in case the torrent doesn't have any trackers
if ((!i->second->is_paused() || i->second->should_request())
&& !i->second->trackers().empty())
{
tracker_request req = i->second->generate_tracker_request();
TORRENT_ASSERT(!m_listen_sockets.empty());
req.listen_port = 0;
if (!m_listen_sockets.empty())
req.listen_port = m_listen_sockets.front().external_port;
req.key = m_key;
std::string login = i->second->tracker_login();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
boost::shared_ptr<tracker_logger> tl(new tracker_logger(*this));
m_tracker_loggers.push_back(tl);
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
, m_listen_interface.address(), tl);
#else
m_tracker_manager.queue_request(m_strand, m_half_open, req, login
, m_listen_interface.address());
#endif
}
}
// close the listen sockets
m_listen_sockets.clear();
ptime start(time_now());
l.unlock();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " waiting for trackers to respond ("
<< m_settings.stop_tracker_timeout << " seconds timeout)\n";
#endif
while (time_now() - start < seconds(
m_settings.stop_tracker_timeout)
&& !m_tracker_manager.empty())
{
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " " << m_tracker_manager.num_requests()
<< " tracker requests pending\n";
#endif
tracker_timer.expires_from_now(milliseconds(100));
tracker_timer.async_wait(m_strand.wrap(
bind(&io_service::stop, &m_io_service)));
m_io_service.reset();
m_io_service.run();
}
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " tracker shutdown complete, locking mutex\n";
#endif
l.lock();
TORRENT_ASSERT(m_abort);
m_abort = true;
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " cleaning up connections\n";
#endif
while (!m_connections.empty())
m_connections.begin()->second->disconnect();
#ifndef NDEBUG #ifndef NDEBUG
for (torrent_map::iterator i = m_torrents.begin(); for (torrent_map::iterator i = m_torrents.begin();
i != m_torrents.end(); ++i) i != m_torrents.end(); ++i)
@ -2101,8 +2085,8 @@ namespace detail
entry session_impl::dht_state() const entry session_impl::dht_state() const
{ {
TORRENT_ASSERT(m_dht);
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
if (!m_dht) return entry();
return m_dht->state(); return m_dht->state();
} }
@ -2138,16 +2122,10 @@ namespace detail
session_impl::~session_impl() session_impl::~session_impl()
{ {
abort();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n"; (*m_logger) << time_now_string() << "\n\n *** shutting down session *** \n\n";
#endif #endif
// lock the main thread and abort it abort();
mutex_t::scoped_lock l(m_mutex);
m_abort = true;
m_io_service.stop();
l.unlock();
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
(*m_logger) << time_now_string() << " waiting for main thread\n"; (*m_logger) << time_now_string() << " waiting for main thread\n";
@ -2388,19 +2366,20 @@ namespace detail
for (connection_map::const_iterator i = m_connections.begin(); for (connection_map::const_iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
TORRENT_ASSERT(i->second); TORRENT_ASSERT(*i);
boost::shared_ptr<torrent> t = i->second->associated_torrent().lock(); boost::shared_ptr<torrent> t = (*i)->associated_torrent().lock();
if (!i->second->is_choked()) ++unchokes; peer_connection* p = i->get();
if (i->second->peer_info_struct() if (!p->is_choked()) ++unchokes;
&& i->second->peer_info_struct()->optimistically_unchoked) if (p->peer_info_struct()
&& p->peer_info_struct()->optimistically_unchoked)
{ {
++num_optimistic; ++num_optimistic;
TORRENT_ASSERT(!i->second->is_choked()); TORRENT_ASSERT(!p->is_choked());
} }
if (t && i->second->peer_info_struct()) if (t && p->peer_info_struct())
{ {
TORRENT_ASSERT(t->get_policy().has_connection(boost::get_pointer(i->second))); TORRENT_ASSERT(t->get_policy().has_connection(p));
} }
} }
TORRENT_ASSERT(num_optimistic == 0 || num_optimistic == 1); TORRENT_ASSERT(num_optimistic == 0 || num_optimistic == 1);

View file

@ -1624,8 +1624,8 @@ namespace libtorrent
if (m_current_slot == m_info->num_pieces()) if (m_current_slot == m_info->num_pieces())
{ {
m_state = state_create_files; m_state = state_create_files;
buffer().swap(m_scratch_buffer); buffer().swap(m_scratch_buffer);
buffer().swap(m_scratch_buffer2); buffer().swap(m_scratch_buffer2);
if (m_storage_mode != storage_mode_compact) if (m_storage_mode != storage_mode_compact)
{ {
std::vector<int>().swap(m_piece_to_slot); std::vector<int>().swap(m_piece_to_slot);

View file

@ -116,11 +116,11 @@ namespace
, tor(t) , tor(t)
{ TORRENT_ASSERT(t != 0); } { TORRENT_ASSERT(t != 0); }
bool operator()(const session_impl::connection_map::value_type& c) const bool operator()(session_impl::connection_map::value_type const& c) const
{ {
tcp::endpoint sender = c.first->remote_endpoint(); tcp::endpoint const& sender = c->remote();
if (sender.address() != ip.address()) return false; if (sender.address() != ip.address()) return false;
if (tor != c.second->associated_torrent().lock().get()) return false; if (tor != c->associated_torrent().lock().get()) return false;
return true; return true;
} }
@ -132,9 +132,9 @@ namespace
{ {
peer_by_id(const peer_id& i): pid(i) {} peer_by_id(const peer_id& i): pid(i) {}
bool operator()(const std::pair<tcp::endpoint, peer_connection*>& p) const bool operator()(session_impl::connection_map::value_type const& p) const
{ {
if (p.second->pid() != pid) return false; if (p->pid() != pid) return false;
// have a special case for all zeros. We can have any number // have a special case for all zeros. We can have any number
// of peers with that pid, since it's used to indicate no pid. // of peers with that pid, since it's used to indicate no pid.
if (std::count(pid.begin(), pid.end(), 0) == 20) return false; if (std::count(pid.begin(), pid.end(), 0) == 20) return false;
@ -178,7 +178,6 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
, m_last_dht_announce(time_now() - minutes(15)) , m_last_dht_announce(time_now() - minutes(15))
#endif #endif
, m_policy()
, m_ses(ses) , m_ses(ses)
, m_checker(checker) , m_checker(checker)
, m_picker(0) , m_picker(0)
@ -203,8 +202,8 @@ namespace libtorrent
, m_max_uploads((std::numeric_limits<int>::max)()) , m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0) , m_num_uploads(0)
, m_max_connections((std::numeric_limits<int>::max)()) , m_max_connections((std::numeric_limits<int>::max)())
, m_policy(this)
{ {
m_policy.reset(new policy(this));
} }
torrent::torrent( torrent::torrent(
@ -239,7 +238,6 @@ namespace libtorrent
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
, m_last_dht_announce(time_now() - minutes(15)) , m_last_dht_announce(time_now() - minutes(15))
#endif #endif
, m_policy()
, m_ses(ses) , m_ses(ses)
, m_checker(checker) , m_checker(checker)
, m_picker(0) , m_picker(0)
@ -263,6 +261,7 @@ namespace libtorrent
, m_max_uploads((std::numeric_limits<int>::max)()) , m_max_uploads((std::numeric_limits<int>::max)())
, m_num_uploads(0) , m_num_uploads(0)
, m_max_connections((std::numeric_limits<int>::max)()) , m_max_connections((std::numeric_limits<int>::max)())
, m_policy(this)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
@ -273,8 +272,6 @@ namespace libtorrent
m_trackers.push_back(announce_entry(tracker_url)); m_trackers.push_back(announce_entry(tracker_url));
m_torrent_file->add_tracker(tracker_url); m_torrent_file->add_tracker(tracker_url);
} }
m_policy.reset(new policy(this));
} }
void torrent::start() void torrent::start()
@ -317,7 +314,7 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin(); for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
(*i->second->m_logger) << "*** DESTRUCTING TORRENT\n"; (*(*i)->m_logger) << "*** DESTRUCTING TORRENT\n";
} }
#endif #endif
@ -566,7 +563,7 @@ namespace libtorrent
continue; continue;
} }
m_policy->peer_from_tracker(a, i->pid, peer_info::tracker, 0); m_policy.peer_from_tracker(a, i->pid, peer_info::tracker, 0);
} }
catch (std::exception&) catch (std::exception&)
{ {
@ -614,7 +611,7 @@ namespace libtorrent
return; return;
} }
m_policy->peer_from_tracker(*host, pid, peer_info::tracker, 0); m_policy.peer_from_tracker(*host, pid, peer_info::tracker, 0);
} }
catch (std::exception&) catch (std::exception&)
{}; {};
@ -744,7 +741,7 @@ namespace libtorrent
std::map<piece_block, int> downloading_piece; std::map<piece_block, int> downloading_piece;
for (const_peer_iterator i = begin(); i != end(); ++i) for (const_peer_iterator i = begin(); i != end(); ++i)
{ {
peer_connection* pc = i->second; peer_connection* pc = *i;
boost::optional<piece_block_progress> p boost::optional<piece_block_progress> p
= pc->downloading_piece_progress(); = pc->downloading_piece_progress();
if (p) if (p)
@ -885,7 +882,7 @@ namespace libtorrent
{ {
#endif #endif
m_policy->piece_finished(index, passed_hash_check); m_policy.piece_finished(index, passed_hash_check);
#ifndef NDEBUG #ifndef NDEBUG
} }
@ -925,7 +922,7 @@ namespace libtorrent
// resets the download queue. So, we cannot do the // resets the download queue. So, we cannot do the
// invariant check here since it assumes: // invariant check here since it assumes:
// (total_done == m_torrent_file->total_size()) => is_seed() // (total_done == m_torrent_file->total_size()) => is_seed()
// INVARIANT_CHECK; INVARIANT_CHECK;
TORRENT_ASSERT(m_storage); TORRENT_ASSERT(m_storage);
TORRENT_ASSERT(m_storage->refcount() > 0); TORRENT_ASSERT(m_storage->refcount() > 0);
@ -964,17 +961,6 @@ namespace libtorrent
{ {
policy::peer* p = static_cast<policy::peer*>(*i); policy::peer* p = static_cast<policy::peer*>(*i);
if (p == 0) continue; if (p == 0) continue;
#ifndef NDEBUG
if (!settings().allow_multiple_connections_per_ip)
{
std::vector<peer_connection*> conns;
connection_for(p->ip.address(), conns);
TORRENT_ASSERT(p->connection == 0
|| std::find_if(conns.begin(), conns.end()
, boost::bind(std::equal_to<peer_connection*>(), _1, p->connection))
!= conns.end());
}
#endif
if (p->connection) p->connection->received_invalid_data(index); if (p->connection) p->connection->received_invalid_data(index);
// either, we have received too many failed hashes // either, we have received too many failed hashes
@ -1039,7 +1025,7 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin(); for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
(*i->second->m_logger) << "*** ABORTING TORRENT\n"; (*(*i)->m_logger) << "*** ABORTING TORRENT\n";
} }
#endif #endif
@ -1108,7 +1094,7 @@ namespace libtorrent
m_picker->we_have(index); m_picker->we_have(index);
for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i) for (peer_iterator i = m_connections.begin(); i != m_connections.end(); ++i)
try { i->second->announce_piece(index); } catch (std::exception&) {} try { (*i)->announce_piece(index); } catch (std::exception&) {}
for (std::set<void*>::iterator i = peers.begin() for (std::set<void*>::iterator i = peers.begin()
, end(peers.end()); i != end; ++i) , end(peers.end()); i != end; ++i)
@ -1279,7 +1265,7 @@ namespace libtorrent
void torrent::update_peer_interest() void torrent::update_peer_interest()
{ {
for (peer_iterator i = begin(); i != end(); ++i) for (peer_iterator i = begin(); i != end(); ++i)
i->second->update_interest(); (*i)->update_interest();
} }
void torrent::filter_piece(int index, bool filter) void torrent::filter_piece(int index, bool filter)
@ -1461,7 +1447,7 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin() for (peer_iterator i = m_connections.begin()
, end(m_connections.end()); i != end; ++i) , end(m_connections.end()); i != end; ++i)
{ {
i->second->cancel_request(block); (*i)->cancel_request(block);
} }
} }
@ -1471,7 +1457,7 @@ namespace libtorrent
TORRENT_ASSERT(p != 0); TORRENT_ASSERT(p != 0);
peer_iterator i = m_connections.find(p->remote()); peer_iterator i = m_connections.find(p);
if (i == m_connections.end()) if (i == m_connections.end())
{ {
TORRENT_ASSERT(false); TORRENT_ASSERT(false);
@ -1509,8 +1495,9 @@ namespace libtorrent
if (!p->is_choked()) if (!p->is_choked())
--m_num_uploads; --m_num_uploads;
m_policy->connection_closed(*p); m_policy.connection_closed(*p);
p->set_peer_info(0); p->set_peer_info(0);
TORRENT_ASSERT(i != m_connections.end());
m_connections.erase(i); m_connections.erase(i);
} }
catch (std::exception& e) catch (std::exception& e)
@ -1663,14 +1650,6 @@ namespace libtorrent
return; return;
} }
peer_iterator conn = m_connections.find(a);
if (conn != m_connections.end())
{
if (dynamic_cast<web_peer_connection*>(conn->second) == 0
|| conn->second->is_disconnecting()) conn->second->disconnect();
else return;
}
boost::shared_ptr<socket_type> s(new socket_type); boost::shared_ptr<socket_type> s(new socket_type);
bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s); bool ret = instantiate_connection(m_ses.m_io_service, m_ses.web_seed_proxy(), *s);
@ -1702,10 +1681,8 @@ namespace libtorrent
try try
{ {
// add the newly connected peer to this torrent's peer list // add the newly connected peer to this torrent's peer list
TORRENT_ASSERT(m_connections.find(a) == m_connections.end()); m_connections.insert(boost::get_pointer(c));
m_connections.insert( m_ses.m_connections.insert(c);
std::make_pair(a, boost::get_pointer(c)));
m_ses.m_connections.insert(std::make_pair(s, c));
m_ses.m_half_open.enqueue( m_ses.m_half_open.enqueue(
bind(&peer_connection::connect, c, _1) bind(&peer_connection::connect, c, _1)
@ -1721,7 +1698,7 @@ namespace libtorrent
// TODO: post an error alert! // TODO: post an error alert!
// std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a); // std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
// if (i != m_connections.end()) m_connections.erase(i); // if (i != m_connections.end()) m_connections.erase(i);
m_ses.connection_failed(s, a, e.what()); m_ses.connection_failed(c, a, e.what());
c->disconnect(); c->disconnect();
} }
} }
@ -1866,19 +1843,19 @@ namespace libtorrent
} }
#endif #endif
peer_connection* torrent::connect_to_peer(policy::peer* peerinfo) bool torrent::connect_to_peer(policy::peer* peerinfo) throw()
{ {
INVARIANT_CHECK; INVARIANT_CHECK;
TORRENT_ASSERT(peerinfo); TORRENT_ASSERT(peerinfo);
TORRENT_ASSERT(peerinfo->connection == 0); TORRENT_ASSERT(peerinfo->connection == 0);
peerinfo->connected = time_now();
#ifndef NDEBUG #ifndef NDEBUG
// this asserts that we don't have duplicates in the policy's peer list // this asserts that we don't have duplicates in the policy's peer list
peer_iterator i_ = m_connections.find(peerinfo->ip); peer_iterator i_ = std::find_if(m_connections.begin(), m_connections.end()
, bind(&peer_connection::remote, _1) == peerinfo->ip);
TORRENT_ASSERT(i_ == m_connections.end() TORRENT_ASSERT(i_ == m_connections.end()
|| i_->second->is_disconnecting() || dynamic_cast<bt_peer_connection*>(*i_) == 0);
|| dynamic_cast<bt_peer_connection*>(i_->second) == 0
|| m_ses.settings().allow_multiple_connections_per_ip);
#endif #endif
TORRENT_ASSERT(want_more_peers()); TORRENT_ASSERT(want_more_peers());
@ -1899,23 +1876,20 @@ namespace libtorrent
c->m_in_constructor = false; c->m_in_constructor = false;
#endif #endif
#ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
{
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
if (pp) c->add_extension(pp);
}
#endif
try try
{ {
TORRENT_ASSERT(m_connections.find(a) == m_connections.end()); #ifndef TORRENT_DISABLE_EXTENSIONS
for (extension_list_t::iterator i = m_extensions.begin()
, end(m_extensions.end()); i != end; ++i)
{
boost::shared_ptr<peer_plugin> pp((*i)->new_connection(c.get()));
if (pp) c->add_extension(pp);
}
#endif
// add the newly connected peer to this torrent's peer list // add the newly connected peer to this torrent's peer list
m_connections.insert( m_connections.insert(boost::get_pointer(c));
std::make_pair(a, boost::get_pointer(c))); m_ses.m_connections.insert(c);
m_ses.m_connections.insert(std::make_pair(s, c));
int timeout = settings().peer_connect_timeout; int timeout = settings().peer_connect_timeout;
if (peerinfo) timeout += 3 * peerinfo->failcount; if (peerinfo) timeout += 3 * peerinfo->failcount;
@ -1927,16 +1901,15 @@ namespace libtorrent
} }
catch (std::exception& e) catch (std::exception& e)
{ {
TORRENT_ASSERT(false); std::set<peer_connection*>::iterator i
// TODO: post an error alert! = m_connections.find(boost::get_pointer(c));
std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
if (i != m_connections.end()) m_connections.erase(i); if (i != m_connections.end()) m_connections.erase(i);
m_ses.connection_failed(s, a, e.what()); m_ses.connection_failed(c, a, e.what());
c->disconnect(); c->disconnect();
throw; return false;
} }
if (c->is_disconnecting()) throw protocol_error("failed to connect"); peerinfo->connection = c.get();
return c.get(); return true;
} }
void torrent::set_metadata(entry const& metadata) void torrent::set_metadata(entry const& metadata)
@ -1980,25 +1953,7 @@ namespace libtorrent
TORRENT_ASSERT(p != 0); TORRENT_ASSERT(p != 0);
TORRENT_ASSERT(!p->is_local()); TORRENT_ASSERT(!p->is_local());
std::map<tcp::endpoint, peer_connection*>::iterator c if (m_ses.m_connections.find(p) == m_ses.m_connections.end())
= m_connections.find(p->remote());
if (c != m_connections.end())
{
TORRENT_ASSERT(p != c->second);
// we already have a peer_connection to this ip.
// It may currently be waiting for completing a
// connection attempt that might fail. So,
// prioritize this current connection since
// it has already succeeded.
if (!c->second->is_connecting())
{
throw protocol_error("already connected to peer");
}
c->second->disconnect();
}
if (m_ses.m_connections.find(p->get_socket())
== m_ses.m_connections.end())
{ {
throw protocol_error("peer is not properly constructed"); throw protocol_error("peer is not properly constructed");
} }
@ -2008,9 +1963,8 @@ namespace libtorrent
throw protocol_error("session is closing"); throw protocol_error("session is closing");
} }
TORRENT_ASSERT(m_connections.find(p->remote()) == m_connections.end()); TORRENT_ASSERT(m_connections.find(p) == m_connections.end());
peer_iterator ci = m_connections.insert( peer_iterator ci = m_connections.insert(p).first;
std::make_pair(p->remote(), p)).first;
try try
{ {
// if new_connection throws, we have to remove the // if new_connection throws, we have to remove the
@ -2024,9 +1978,9 @@ namespace libtorrent
if (pp) p->add_extension(pp); if (pp) p->add_extension(pp);
} }
#endif #endif
TORRENT_ASSERT(connection_for(p->remote()) == p); TORRENT_ASSERT(m_connections.find(p) == ci);
TORRENT_ASSERT(ci->second == p); TORRENT_ASSERT(*ci == p);
m_policy->new_connection(*ci->second); m_policy.new_connection(**ci);
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -2036,7 +1990,7 @@ namespace libtorrent
TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint()); TORRENT_ASSERT(p->remote() == p->get_socket()->remote_endpoint());
#ifndef NDEBUG #ifndef NDEBUG
m_policy->check_invariant(); m_policy.check_invariant();
#endif #endif
} }
@ -2055,19 +2009,19 @@ namespace libtorrent
while (!m_connections.empty()) while (!m_connections.empty())
{ {
peer_connection& p = *m_connections.begin()->second; peer_connection* p = *m_connections.begin();
TORRENT_ASSERT(p.associated_torrent().lock().get() == this); TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
if (m_abort) if (m_abort)
(*p.m_logger) << "*** CLOSING CONNECTION 'aborting'\n"; (*p->m_logger) << "*** CLOSING CONNECTION 'aborting'\n";
else else
(*p.m_logger) << "*** CLOSING CONNECTION 'pausing'\n"; (*p->m_logger) << "*** CLOSING CONNECTION 'pausing'\n";
#endif #endif
#ifndef NDEBUG #ifndef NDEBUG
std::size_t size = m_connections.size(); std::size_t size = m_connections.size();
#endif #endif
p.disconnect(); p->disconnect();
TORRENT_ASSERT(m_connections.size() <= size); TORRENT_ASSERT(m_connections.size() <= size);
} }
} }
@ -2158,13 +2112,14 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin(); for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
TORRENT_ASSERT(i->second->associated_torrent().lock().get() == this); peer_connection* p = *i;
if (i->second->is_seed()) TORRENT_ASSERT(p->associated_torrent().lock().get() == this);
if (p->is_seed())
{ {
#if defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING)
(*i->second->m_logger) << "*** SEED, CLOSING CONNECTION\n"; (*p->m_logger) << "*** SEED, CLOSING CONNECTION\n";
#endif #endif
seeds.push_back(i->second); seeds.push_back(p);
} }
} }
std::for_each(seeds.begin(), seeds.end() std::for_each(seeds.begin(), seeds.end()
@ -2365,23 +2320,21 @@ namespace libtorrent
m_connections_initialized = true; m_connections_initialized = true;
// all peer connections have to initialize themselves now that the metadata // all peer connections have to initialize themselves now that the metadata
// is available // is available
typedef std::map<tcp::endpoint, peer_connection*> conn_map; for (torrent::peer_iterator i = m_connections.begin()
for (conn_map::iterator i = m_connections.begin()
, end(m_connections.end()); i != end;) , end(m_connections.end()); i != end;)
{ {
try try
{ {
i->second->on_metadata(); (*i)->on_metadata();
i->second->init(); (*i)->init();
++i; ++i;
} }
catch (std::exception& e) catch (std::exception& e)
{ {
// the connection failed, close it // the connection failed, close it
conn_map::iterator j = i; torrent::peer_iterator j = i;
++j; ++j;
m_ses.connection_failed(i->second->get_socket() m_ses.connection_failed(*i, (*i)->remote(), e.what());
, i->first, e.what());
i = j; i = j;
} }
} }
@ -2452,7 +2405,7 @@ namespace libtorrent
std::map<piece_block, int> num_requests; std::map<piece_block, int> num_requests;
for (const_peer_iterator i = begin(); i != end(); ++i) for (const_peer_iterator i = begin(); i != end(); ++i)
{ {
peer_connection const& p = *i->second; peer_connection const& p = *(*i);
for (std::deque<piece_block>::const_iterator i = p.request_queue().begin() for (std::deque<piece_block>::const_iterator i = p.request_queue().begin()
, end(p.request_queue().end()); i != end; ++i) , end(p.request_queue().end()); i != end; ++i)
++num_requests[*i]; ++num_requests[*i];
@ -2484,12 +2437,12 @@ namespace libtorrent
TORRENT_ASSERT(m_abort || m_have_pieces.empty()); TORRENT_ASSERT(m_abort || m_have_pieces.empty());
} }
/* for (policy::const_iterator i = m_policy->begin_peer() for (policy::const_iterator i = m_policy.begin_peer()
, end(m_policy->end_peer()); i != end; ++i) , end(m_policy.end_peer()); i != end; ++i)
{ {
TORRENT_ASSERT(i->connection == const_cast<torrent*>(this)->connection_for(i->ip)); TORRENT_ASSERT(i->second.ip.address() == i->first);
} }
*/
size_type total_done = quantized_bytes_done(); size_type total_done = quantized_bytes_done();
if (m_torrent_file->is_valid()) if (m_torrent_file->is_valid())
{ {
@ -2572,17 +2525,19 @@ namespace libtorrent
void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit) void torrent::set_peer_upload_limit(tcp::endpoint ip, int limit)
{ {
TORRENT_ASSERT(limit >= -1); TORRENT_ASSERT(limit >= -1);
peer_connection* p = connection_for(ip); peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
if (p == 0) return; , bind(&peer_connection::remote, _1) == ip);
p->set_upload_limit(limit); if (i == m_connections.end()) return;
(*i)->set_upload_limit(limit);
} }
void torrent::set_peer_download_limit(tcp::endpoint ip, int limit) void torrent::set_peer_download_limit(tcp::endpoint ip, int limit)
{ {
TORRENT_ASSERT(limit >= -1); TORRENT_ASSERT(limit >= -1);
peer_connection* p = connection_for(ip); peer_iterator i = std::find_if(m_connections.begin(), m_connections.end()
if (p == 0) return; , bind(&peer_connection::remote, _1) == ip);
p->set_download_limit(limit); if (i == m_connections.end()) return;
(*i)->set_download_limit(limit);
} }
void torrent::set_upload_limit(int limit) void torrent::set_upload_limit(int limit)
@ -2621,7 +2576,7 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin(); for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
(*i->second->m_logger) << "*** DELETING FILES IN TORRENT\n"; (*(*i)->m_logger) << "*** DELETING FILES IN TORRENT\n";
} }
#endif #endif
@ -2656,7 +2611,7 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin(); for (peer_iterator i = m_connections.begin();
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
(*i->second->m_logger) << "*** PAUSING TORRENT\n"; (*(*i)->m_logger) << "*** PAUSING TORRENT\n";
} }
#endif #endif
@ -2730,7 +2685,7 @@ namespace libtorrent
i != m_connections.end(); ++i) i != m_connections.end(); ++i)
{ {
web_peer_connection* p web_peer_connection* p
= dynamic_cast<web_peer_connection*>(i->second); = dynamic_cast<web_peer_connection*>(*i);
if (!p) continue; if (!p) continue;
web_seeds.insert(p->url()); web_seeds.insert(p->url());
} }
@ -2753,7 +2708,7 @@ namespace libtorrent
for (peer_iterator i = m_connections.begin(); for (peer_iterator i = m_connections.begin();
i != m_connections.end();) i != m_connections.end();)
{ {
peer_connection* p = i->second; peer_connection* p = *i;
++i; ++i;
m_stat += p->statistics(); m_stat += p->statistics();
// updates the peer connection's ul/dl bandwidth // updates the peer connection's ul/dl bandwidth
@ -2778,14 +2733,14 @@ namespace libtorrent
if (m_time_scaler <= 0) if (m_time_scaler <= 0)
{ {
m_time_scaler = 10; m_time_scaler = 10;
m_policy->pulse(); m_policy.pulse();
} }
} }
bool torrent::try_connect_peer() bool torrent::try_connect_peer()
{ {
TORRENT_ASSERT(want_more_peers()); TORRENT_ASSERT(want_more_peers());
return m_policy->connect_one_peer(); return m_policy.connect_one_peer();
} }
void torrent::async_verify_piece(int piece_index, boost::function<void(bool)> const& f) void torrent::async_verify_piece(int piece_index, boost::function<void(bool)> const& f)
@ -2869,8 +2824,7 @@ namespace libtorrent
torrent_status st; torrent_status st;
st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end(), st.num_peers = (int)std::count_if(m_connections.begin(), m_connections.end(),
!boost::bind(&peer_connection::is_connecting !boost::bind(&peer_connection::is_connecting, _1));
, boost::bind(&std::map<tcp::endpoint,peer_connection*>::value_type::second, _1)));
st.storage_mode = m_storage_mode; st.storage_mode = m_storage_mode;
@ -2997,9 +2951,7 @@ namespace libtorrent
INVARIANT_CHECK; INVARIANT_CHECK;
return (int)std::count_if(m_connections.begin(), m_connections.end() return (int)std::count_if(m_connections.begin(), m_connections.end()
, boost::bind(&peer_connection::is_seed , boost::bind(&peer_connection::is_seed, _1));
, boost::bind(&std::map<tcp::endpoint
, peer_connection*>::value_type::second, _1)));
} }
void torrent::tracker_request_timed_out( void torrent::tracker_request_timed_out(
@ -3055,7 +3007,7 @@ namespace libtorrent
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
void torrent::debug_log(const std::string& line) void torrent::debug_log(const std::string& line)
{ {
(*m_ses.m_logger) << line << "\n"; (*m_ses.m_logger) << time_now_string() << " " << line << "\n";
} }
#endif #endif

View file

@ -908,7 +908,7 @@ namespace libtorrent
for (torrent::const_peer_iterator i = t->begin(); for (torrent::const_peer_iterator i = t->begin();
i != t->end(); ++i) i != t->end(); ++i)
{ {
peer_connection* peer = i->second; peer_connection* peer = *i;
// incoming peers that haven't finished the handshake should // incoming peers that haven't finished the handshake should
// not be included in this list // not be included in this list

View file

@ -296,18 +296,20 @@ namespace libtorrent
, m_timeout(str.io_service()) , m_timeout(str.io_service())
, m_completion_timeout(0) , m_completion_timeout(0)
, m_read_timeout(0) , m_read_timeout(0)
, m_abort(false)
{} {}
void timeout_handler::set_timeout(int completion_timeout, int read_timeout) void timeout_handler::set_timeout(int completion_timeout, int read_timeout)
{ {
m_completion_timeout = completion_timeout; m_completion_timeout = completion_timeout;
m_read_timeout = read_timeout; m_read_timeout = read_timeout;
m_start_time = time_now(); m_start_time = m_read_time = time_now();
m_read_time = time_now();
m_timeout.expires_at((std::min)( if (m_abort) return;
m_read_time + seconds(m_read_timeout)
, m_start_time + seconds(m_completion_timeout))); int timeout = (std::min)(
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
m_timeout.expires_at(m_read_time + seconds(timeout));
m_timeout.async_wait(m_strand.wrap(bind( m_timeout.async_wait(m_strand.wrap(bind(
&timeout_handler::timeout_callback, self(), _1))); &timeout_handler::timeout_callback, self(), _1)));
} }
@ -319,6 +321,7 @@ namespace libtorrent
void timeout_handler::cancel() void timeout_handler::cancel()
{ {
m_abort = true;
m_completion_timeout = 0; m_completion_timeout = 0;
m_timeout.cancel(); m_timeout.cancel();
} }
@ -341,9 +344,11 @@ namespace libtorrent
return; return;
} }
m_timeout.expires_at((std::min)( if (m_abort) return;
m_read_time + seconds(m_read_timeout)
, m_start_time + seconds(m_completion_timeout))); int timeout = (std::min)(
m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
m_timeout.expires_at(m_read_time + seconds(timeout));
m_timeout.async_wait(m_strand.wrap( m_timeout.async_wait(m_strand.wrap(
bind(&timeout_handler::timeout_callback, self(), _1))); bind(&timeout_handler::timeout_callback, self(), _1)));
} }
@ -567,24 +572,24 @@ namespace libtorrent
m_abort = true; m_abort = true;
tracker_connections_t keep_connections; tracker_connections_t keep_connections;
while (!m_connections.empty()) while (!m_connections.empty())
{ {
boost::intrusive_ptr<tracker_connection>& c = m_connections.back(); boost::intrusive_ptr<tracker_connection>& c = m_connections.back();
if (!c) if (!c)
{ {
m_connections.pop_back(); m_connections.pop_back();
continue; continue;
} }
tracker_request const& req = c->tracker_req(); tracker_request const& req = c->tracker_req();
if (req.event == tracker_request::stopped) if (req.event == tracker_request::stopped)
{ {
keep_connections.push_back(c); keep_connections.push_back(c);
m_connections.pop_back(); m_connections.pop_back();
continue; continue;
} }
// close will remove the entry from m_connections // close will remove the entry from m_connections
// so no need to pop // so no need to pop
c->close(); c->close();
} }
std::swap(m_connections, keep_connections); std::swap(m_connections, keep_connections);

View file

@ -96,7 +96,9 @@ namespace libtorrent
m_name_lookup.async_resolve(q m_name_lookup.async_resolve(q
, m_strand.wrap(boost::bind( , m_strand.wrap(boost::bind(
&udp_tracker_connection::name_lookup, self(), _1, _2))); &udp_tracker_connection::name_lookup, self(), _1, _2)));
set_timeout(m_settings.tracker_completion_timeout set_timeout(req.event == tracker_request::stopped
? m_settings.stop_tracker_timeout
: m_settings.tracker_completion_timeout
, m_settings.tracker_receive_timeout); , m_settings.tracker_receive_timeout);
} }
@ -156,11 +158,20 @@ namespace libtorrent
void udp_tracker_connection::on_timeout() void udp_tracker_connection::on_timeout()
{ {
m_socket.close(); asio::error_code ec;
m_socket.close(ec);
m_name_lookup.cancel(); m_name_lookup.cancel();
fail_timeout(); fail_timeout();
} }
void udp_tracker_connection::close()
{
asio::error_code ec;
m_socket.close(ec);
m_name_lookup.cancel();
tracker_connection::close();
}
void udp_tracker_connection::send_udp_connect() void udp_tracker_connection::send_udp_connect()
{ {
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
@ -468,6 +479,7 @@ namespace libtorrent
, complete, incomplete); , complete, incomplete);
m_man.remove_request(this); m_man.remove_request(this);
close();
return; return;
} }
catch (std::exception& e) catch (std::exception& e)
@ -543,6 +555,7 @@ namespace libtorrent
if (!cb) if (!cb)
{ {
m_man.remove_request(this); m_man.remove_request(this);
close();
return; return;
} }
@ -551,6 +564,7 @@ namespace libtorrent
, complete, incomplete); , complete, incomplete);
m_man.remove_request(this); m_man.remove_request(this);
close();
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View file

@ -72,7 +72,7 @@ namespace libtorrent { namespace
struct ut_pex_plugin: torrent_plugin struct ut_pex_plugin: torrent_plugin
{ {
ut_pex_plugin(torrent& t): m_torrent(t), m_1_minute(0) {} ut_pex_plugin(torrent& t): m_torrent(t), m_1_minute(55) {}
virtual boost::shared_ptr<peer_plugin> new_connection(peer_connection* pc); virtual boost::shared_ptr<peer_plugin> new_connection(peer_connection* pc);
@ -113,18 +113,20 @@ namespace libtorrent { namespace
for (torrent::peer_iterator i = m_torrent.begin() for (torrent::peer_iterator i = m_torrent.begin()
, end(m_torrent.end()); i != end; ++i) , end(m_torrent.end()); i != end; ++i)
{ {
if (!send_peer(*i->second)) continue; peer_connection* peer = *i;
if (!send_peer(*peer)) continue;
m_old_peers.insert(i->first); tcp::endpoint const& remote = peer->remote();
m_old_peers.insert(remote);
std::set<tcp::endpoint>::iterator di = dropped.find(i->first); std::set<tcp::endpoint>::iterator di = dropped.find(remote);
if (di == dropped.end()) if (di == dropped.end())
{ {
// don't write too big of a package // don't write too big of a package
if (num_added >= max_peer_entries) break; if (num_added >= max_peer_entries) break;
// only send proper bittorrent peers // only send proper bittorrent peers
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(i->second); bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(peer);
if (!p) continue; if (!p) continue;
// no supported flags to set yet // no supported flags to set yet
@ -135,14 +137,14 @@ namespace libtorrent { namespace
flags |= p->supports_encryption() ? 1 : 0; flags |= p->supports_encryption() ? 1 : 0;
#endif #endif
// i->first was added since the last time // i->first was added since the last time
if (i->first.address().is_v4()) if (remote.address().is_v4())
{ {
detail::write_endpoint(i->first, pla_out); detail::write_endpoint(remote, pla_out);
detail::write_uint8(flags, plf_out); detail::write_uint8(flags, plf_out);
} }
else else
{ {
detail::write_endpoint(i->first, pla6_out); detail::write_endpoint(remote, pla6_out);
detail::write_uint8(flags, plf6_out); detail::write_uint8(flags, plf6_out);
} }
++num_added; ++num_added;
@ -156,7 +158,7 @@ namespace libtorrent { namespace
} }
for (std::set<tcp::endpoint>::const_iterator i = dropped.begin() for (std::set<tcp::endpoint>::const_iterator i = dropped.begin()
, end(dropped.end());i != end; ++i) , end(dropped.end()); i != end; ++i)
{ {
if (i->address().is_v4()) if (i->address().is_v4())
detail::write_endpoint(*i, pld_out); detail::write_endpoint(*i, pld_out);
@ -183,7 +185,7 @@ namespace libtorrent { namespace
: m_torrent(t) : m_torrent(t)
, m_pc(pc) , m_pc(pc)
, m_tp(tp) , m_tp(tp)
, m_1_minute(0) , m_1_minute(55)
, m_message_index(0) , m_message_index(0)
, m_first_time(true) , m_first_time(true)
{} {}
@ -327,13 +329,14 @@ namespace libtorrent { namespace
for (torrent::peer_iterator i = m_torrent.begin() for (torrent::peer_iterator i = m_torrent.begin()
, end(m_torrent.end()); i != end; ++i) , end(m_torrent.end()); i != end; ++i)
{ {
if (!send_peer(*i->second)) continue; peer_connection* peer = *i;
if (!send_peer(*peer)) continue;
// don't write too big of a package // don't write too big of a package
if (num_added >= max_peer_entries) break; if (num_added >= max_peer_entries) break;
// only send proper bittorrent peers // only send proper bittorrent peers
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(i->second); bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(peer);
if (!p) continue; if (!p) continue;
// no supported flags to set yet // no supported flags to set yet
@ -343,15 +346,16 @@ namespace libtorrent { namespace
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
flags |= p->supports_encryption() ? 1 : 0; flags |= p->supports_encryption() ? 1 : 0;
#endif #endif
tcp::endpoint const& remote = peer->remote();
// i->first was added since the last time // i->first was added since the last time
if (i->first.address().is_v4()) if (remote.address().is_v4())
{ {
detail::write_endpoint(i->first, pla_out); detail::write_endpoint(remote, pla_out);
detail::write_uint8(flags, plf_out); detail::write_uint8(flags, plf_out);
} }
else else
{ {
detail::write_endpoint(i->first, pla6_out); detail::write_endpoint(remote, pla6_out);
detail::write_uint8(flags, plf6_out); detail::write_uint8(flags, plf6_out);
} }
++num_added; ++num_added;

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2007-10-27 20:34-0500\n" "POT-Creation-Date: 2007-11-01 18:39-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -88,7 +88,7 @@ msgstr ""
msgid "<b>Torrent Info</b>" msgid "<b>Torrent Info</b>"
msgstr "" msgstr ""
#: glade/delugegtk.glade:750 plugins/WebUi/scripts/template_strings.py:8 #: glade/delugegtk.glade:750 plugins/WebUi/scripts/template_strings.py:9
msgid "Details" msgid "Details"
msgstr "" msgstr ""
@ -149,23 +149,25 @@ msgid "Status"
msgstr "" msgstr ""
#: glade/delugegtk.glade:965 src/interface.py:602 #: glade/delugegtk.glade:965 src/interface.py:602
#: plugins/WebUi/scripts/template_strings.py:19 #: plugins/WebUi/scripts/template_strings.py:21
msgid "Seeders" msgid "Seeders"
msgstr "" msgstr ""
#: glade/delugegtk.glade:974 src/interface.py:605 #: glade/delugegtk.glade:974 src/interface.py:605
#: plugins/TorrentPeers/__init__.py:72 #: plugins/TorrentPeers/__init__.py:72
#: plugins/WebUi/scripts/template_strings.py:15 #: plugins/WebUi/scripts/template_strings.py:17
msgid "Peers" msgid "Peers"
msgstr "" msgstr ""
#: glade/delugegtk.glade:983 src/interface.py:608 src/interface.py:1114 #: glade/delugegtk.glade:983 src/interface.py:608 src/interface.py:1103
#: src/interface.py:1145 plugins/TorrentPeers/tab_peers.py:89 #: src/interface.py:1134 plugins/TorrentPeers/tab_peers.py:89
#: plugins/WebUi/scripts/template_strings.py:10
msgid "Down Speed" msgid "Down Speed"
msgstr "" msgstr ""
#: glade/delugegtk.glade:992 src/interface.py:611 src/interface.py:1115 #: glade/delugegtk.glade:992 src/interface.py:611 src/interface.py:1104
#: src/interface.py:1146 plugins/TorrentPeers/tab_peers.py:91 #: src/interface.py:1135 plugins/TorrentPeers/tab_peers.py:91
#: plugins/WebUi/scripts/template_strings.py:29
msgid "Up Speed" msgid "Up Speed"
msgstr "" msgstr ""
@ -173,11 +175,11 @@ msgstr ""
msgid "Time Remaining" msgid "Time Remaining"
msgstr "" msgstr ""
#: glade/delugegtk.glade:1010 plugins/WebUi/scripts/template_strings.py:4 #: glade/delugegtk.glade:1010 plugins/WebUi/scripts/template_strings.py:5
msgid "Availability" msgid "Availability"
msgstr "" msgstr ""
#: glade/delugegtk.glade:1019 plugins/WebUi/scripts/template_strings.py:21 #: glade/delugegtk.glade:1019 plugins/WebUi/scripts/template_strings.py:23
msgid "Share Ratio" msgid "Share Ratio"
msgstr "" msgstr ""
@ -213,7 +215,7 @@ msgstr ""
msgid "Remove Torrent" msgid "Remove Torrent"
msgstr "" msgstr ""
#: glade/delugegtk.glade:1157 plugins/WebUi/scripts/template_strings.py:18 #: glade/delugegtk.glade:1157 plugins/WebUi/scripts/template_strings.py:20
msgid "Remove" msgid "Remove"
msgstr "" msgstr ""
@ -280,7 +282,7 @@ msgstr ""
msgid "Delete downloaded files" msgid "Delete downloaded files"
msgstr "" msgstr ""
#: glade/dgtkpopups.glade:88 plugins/WebUi/scripts/template_strings.py:6 #: glade/dgtkpopups.glade:88 plugins/WebUi/scripts/template_strings.py:7
msgid "Delete .torrent file" msgid "Delete .torrent file"
msgstr "" msgstr ""
@ -296,7 +298,7 @@ msgstr ""
msgid "Clear Finished" msgid "Clear Finished"
msgstr "" msgstr ""
#: glade/dgtkpopups.glade:241 plugins/WebUi/scripts/template_strings.py:22 #: glade/dgtkpopups.glade:241 plugins/WebUi/scripts/template_strings.py:24
msgid "Speed" msgid "Speed"
msgstr "" msgstr ""
@ -649,7 +651,7 @@ msgstr ""
#: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1672 #: glade/preferences_dialog.glade:1478 glade/preferences_dialog.glade:1672
#: glade/preferences_dialog.glade:1866 glade/preferences_dialog.glade:2060 #: glade/preferences_dialog.glade:1866 glade/preferences_dialog.glade:2060
#: plugins/WebUi/scripts/template_strings.py:13 #: plugins/WebUi/scripts/template_strings.py:15
msgid "Password" msgid "Password"
msgstr "" msgstr ""
@ -960,8 +962,8 @@ msgid "KiB/s"
msgstr "" msgstr ""
#: src/interface.py:289 src/interface.py:350 src/interface.py:376 #: src/interface.py:289 src/interface.py:350 src/interface.py:376
#: src/interface.py:1096 src/interface.py:1103 src/interface.py:1108 #: src/interface.py:1085 src/interface.py:1092 src/interface.py:1097
#: src/interface.py:1136 src/interface.py:1138 #: src/interface.py:1125 src/interface.py:1127
#: plugins/SpeedLimiter/__init__.py:137 plugins/SpeedLimiter/__init__.py:169 #: plugins/SpeedLimiter/__init__.py:137 plugins/SpeedLimiter/__init__.py:169
msgid "Unlimited" msgid "Unlimited"
msgstr "" msgstr ""
@ -1008,7 +1010,7 @@ msgstr ""
msgid "Name" msgid "Name"
msgstr "" msgstr ""
#: src/interface.py:614 plugins/WebUi/scripts/template_strings.py:10 #: src/interface.py:614 plugins/WebUi/scripts/template_strings.py:12
msgid "ETA" msgid "ETA"
msgstr "" msgstr ""
@ -1025,70 +1027,70 @@ msgstr ""
msgid "Paused %s" msgid "Paused %s"
msgstr "" msgstr ""
#: src/interface.py:1114 #: src/interface.py:1103
msgid "Connections" msgid "Connections"
msgstr "" msgstr ""
#: src/interface.py:1132 #: src/interface.py:1121
msgid "DHT" msgid "DHT"
msgstr "" msgstr ""
#: src/interface.py:1141 plugins/TorrentCreator/__init__.py:148 #: src/interface.py:1130 plugins/TorrentCreator/__init__.py:148
msgid "Deluge" msgid "Deluge"
msgstr "" msgstr ""
#: src/interface.py:1141 #: src/interface.py:1130
msgid "Download" msgid "Download"
msgstr "" msgstr ""
#: src/interface.py:1142 #: src/interface.py:1131
msgid "Upload" msgid "Upload"
msgstr "" msgstr ""
#: src/interface.py:1145 #: src/interface.py:1134
msgid "Deluge Bittorrent Client" msgid "Deluge Bittorrent Client"
msgstr "" msgstr ""
#: src/interface.py:1222 #: src/interface.py:1211
msgid "Choose a download directory" msgid "Choose a download directory"
msgstr "" msgstr ""
#: src/interface.py:1249 #: src/interface.py:1238
msgid "" msgid ""
"An error occured while trying to add the torrent. It's possible your ." "An error occured while trying to add the torrent. It's possible your ."
"torrent file is corrupted." "torrent file is corrupted."
msgstr "" msgstr ""
#: src/interface.py:1274 #: src/interface.py:1263
msgid "Unknown duplicate torrent error." msgid "Unknown duplicate torrent error."
msgstr "" msgstr ""
#: src/interface.py:1279 #: src/interface.py:1268
msgid "" msgid ""
"There is not enough free disk space to complete your download." "There is not enough free disk space to complete your download."
msgstr "" msgstr ""
#: src/interface.py:1281 #: src/interface.py:1270
msgid "Space Needed:" msgid "Space Needed:"
msgstr "" msgstr ""
#: src/interface.py:1282 #: src/interface.py:1271
msgid "Available Space:" msgid "Available Space:"
msgstr "" msgstr ""
#: src/interface.py:1299 #: src/interface.py:1288
msgid "Add torrent from URL" msgid "Add torrent from URL"
msgstr "" msgstr ""
#: src/interface.py:1303 #: src/interface.py:1292
msgid "Enter the URL of the .torrent to download" msgid "Enter the URL of the .torrent to download"
msgstr "" msgstr ""
#: src/interface.py:1364 #: src/interface.py:1353
msgid "Warning - all downloaded files for this torrent will be deleted!" msgid "Warning - all downloaded files for this torrent will be deleted!"
msgstr "" msgstr ""
#: src/interface.py:1375 #: src/interface.py:1364
msgid "Are you sure that you want to remove all seeding torrents?" msgid "Are you sure that you want to remove all seeding torrents?"
msgstr "" msgstr ""
@ -1172,19 +1174,19 @@ msgid ""
"re-add this torrent." "re-add this torrent."
msgstr "" msgstr ""
#: src/dialogs.py:68 #: src/dialogs.py:69
msgid "Plugin" msgid "Plugin"
msgstr "" msgstr ""
#: src/dialogs.py:70 #: src/dialogs.py:71
msgid "Enabled" msgid "Enabled"
msgstr "" msgstr ""
#: src/dialogs.py:435 #: src/dialogs.py:438
msgid "translator-credits" msgid "translator-credits"
msgstr "" msgstr ""
#: src/dialogs.py:436 #: src/dialogs.py:439
msgid "" msgid ""
"Deluge is free software, you can redistribute it and/or\n" "Deluge is free software, you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public\n" "modify it under the terms of the GNU General Public\n"
@ -1201,15 +1203,15 @@ msgid ""
"1301 USA" "1301 USA"
msgstr "" msgstr ""
#: src/dialogs.py:476 #: src/dialogs.py:480
msgid "Choose a .torrent file" msgid "Choose a .torrent file"
msgstr "" msgstr ""
#: src/dialogs.py:481 #: src/dialogs.py:485
msgid "Torrent files" msgid "Torrent files"
msgstr "" msgstr ""
#: src/dialogs.py:485 #: src/dialogs.py:489
msgid "All files" msgid "All files"
msgstr "" msgstr ""
@ -1639,11 +1641,11 @@ msgid ""
"notification" "notification"
msgstr "" msgstr ""
#: plugins/TorrentNotification/__init__.py:109 #: plugins/TorrentNotification/__init__.py:112
msgid "Torrent complete" msgid "Torrent complete"
msgstr "" msgstr ""
#: plugins/TorrentNotification/__init__.py:110 #: plugins/TorrentNotification/__init__.py:113
#: plugins/TorrentFiles/__init__.py:71 #: plugins/TorrentFiles/__init__.py:71
msgid "Files" msgid "Files"
msgstr "" msgstr ""
@ -2109,26 +2111,6 @@ msgid ""
"be obeyed." "be obeyed."
msgstr "" msgstr ""
#: plugins/WebUi/__init__.py:31
msgid "Web User Interface"
msgstr ""
#: plugins/WebUi/__init__.py:34
msgid ""
"A Web based User Interface\n"
"\n"
"Firefox greasemonkey script: http://userscripts.org/scripts/show/12639\n"
"\n"
"Remotely add a file: \"curl -F torrent=@./test1.torrent -F pwd=deluge http://"
"localhost:8112/remote/torrent/add\"\n"
"\n"
"There is support for multiple templates, but just one is included.\n"
"\n"
"Other contributors:\n"
"*somedude : template enhancements.\n"
"*markybob : stability : synced with his changes in deluge-svn.\n"
msgstr ""
#: plugins/WebUi/__init__.py:179 #: plugins/WebUi/__init__.py:179
msgid "WebUi Config" msgid "WebUi Config"
msgstr "" msgstr ""
@ -2177,23 +2159,23 @@ msgstr ""
msgid "translate something" msgid "translate something"
msgstr "" msgstr ""
#: plugins/WebUi/deluge_webserver.py:142 #: plugins/WebUi/deluge_webserver.py:147
msgid "Choose an url or a torrent, not both." msgid "Choose an url or a torrent, not both."
msgstr "" msgstr ""
#: plugins/WebUi/deluge_webserver.py:153 #: plugins/WebUi/deluge_webserver.py:158
msgid "no data." msgid "no data."
msgstr "" msgstr ""
#: plugins/WebUi/deluge_webserver.py:230 #: plugins/WebUi/deluge_webserver.py:235
msgid "refresh must be > 0" msgid "refresh must be > 0"
msgstr "" msgstr ""
#: plugins/WebUi/deluge_webserver.py:238 #: plugins/WebUi/deluge_webserver.py:243
msgid "Download Speed Limit" msgid "Download Speed Limit"
msgstr "" msgstr ""
#: plugins/WebUi/deluge_webserver.py:242 #: plugins/WebUi/deluge_webserver.py:247
msgid "Upload Speed Limit" msgid "Upload Speed Limit"
msgstr "" msgstr ""
@ -2206,73 +2188,77 @@ msgid "About"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:3 #: plugins/WebUi/scripts/template_strings.py:3
msgid "Apply"
msgstr ""
#: plugins/WebUi/scripts/template_strings.py:4
msgid "Auto refresh:" msgid "Auto refresh:"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:5 #: plugins/WebUi/scripts/template_strings.py:6
msgid "Debug:Data Dump" msgid "Debug:Data Dump"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:7 #: plugins/WebUi/scripts/template_strings.py:8
msgid "Delete downloaded files." msgid "Delete downloaded files."
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:9 #: plugins/WebUi/scripts/template_strings.py:11
msgid "Downloaded" msgid "Downloaded"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:11 #: plugins/WebUi/scripts/template_strings.py:13
msgid "Next Announce" msgid "Next Announce"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:12 #: plugins/WebUi/scripts/template_strings.py:14
msgid "Off" msgid "Off"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:14 #: plugins/WebUi/scripts/template_strings.py:16
msgid "Password is invalid,try again" msgid "Password is invalid,try again"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:16 #: plugins/WebUi/scripts/template_strings.py:18
msgid "Pieces" msgid "Pieces"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:17 #: plugins/WebUi/scripts/template_strings.py:19
msgid "Refresh page every:" msgid "Refresh page every:"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:20 #: plugins/WebUi/scripts/template_strings.py:22
msgid "Set" msgid "Set"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:23 #: plugins/WebUi/scripts/template_strings.py:25
msgid "Submit" msgid "Submit"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:24 #: plugins/WebUi/scripts/template_strings.py:26
msgid "Total Size" msgid "Total Size"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:25 #: plugins/WebUi/scripts/template_strings.py:27
msgid "Tracker" msgid "Tracker"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:26 #: plugins/WebUi/scripts/template_strings.py:28
msgid "Tracker Status" msgid "Tracker Status"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:27 #: plugins/WebUi/scripts/template_strings.py:30
msgid "Upload torrent" msgid "Upload torrent"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:28 #: plugins/WebUi/scripts/template_strings.py:31
msgid "Uploaded" msgid "Uploaded"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:29 #: plugins/WebUi/scripts/template_strings.py:32
msgid "Url" msgid "Url"
msgstr "" msgstr ""
#: plugins/WebUi/scripts/template_strings.py:30 #: plugins/WebUi/scripts/template_strings.py:33
msgid "seconds" msgid "seconds"
msgstr "" msgstr ""