*** empty log message ***

This commit is contained in:
Arvid Norberg 2004-03-21 02:03:37 +00:00
parent aa7055c212
commit bb52b74a9e
17 changed files with 356 additions and 59 deletions

View File

@ -45,32 +45,33 @@
<li><a class="reference" href="#file-error-alert" id="id37" name="id37">file_error_alert</a></li> <li><a class="reference" href="#file-error-alert" id="id37" name="id37">file_error_alert</a></li>
<li><a class="reference" href="#tracker-alert" id="id38" name="id38">tracker_alert</a></li> <li><a class="reference" href="#tracker-alert" id="id38" name="id38">tracker_alert</a></li>
<li><a class="reference" href="#hash-failed-alert" id="id39" name="id39">hash_failed_alert</a></li> <li><a class="reference" href="#hash-failed-alert" id="id39" name="id39">hash_failed_alert</a></li>
<li><a class="reference" href="#peer-error-alert" id="id40" name="id40">peer_error_alert</a></li> <li><a class="reference" href="#peer-ban-alert" id="id40" name="id40">peer_ban_alert</a></li>
<li><a class="reference" href="#invalid-request-alert" id="id41" name="id41">invalid_request_alert</a></li> <li><a class="reference" href="#peer-error-alert" id="id41" name="id41">peer_error_alert</a></li>
<li><a class="reference" href="#torrent-finished-alert" id="id42" name="id42">torrent_finished_alert</a></li> <li><a class="reference" href="#invalid-request-alert" id="id42" name="id42">invalid_request_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id43" name="id43">dispatcher</a></li> <li><a class="reference" href="#torrent-finished-alert" id="id43" name="id43">torrent_finished_alert</a></li>
<li><a class="reference" href="#dispatcher" id="id44" name="id44">dispatcher</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#exceptions" id="id44" name="id44">exceptions</a><ul> <li><a class="reference" href="#exceptions" id="id45" name="id45">exceptions</a><ul>
<li><a class="reference" href="#invalid-handle" id="id45" name="id45">invalid_handle</a></li> <li><a class="reference" href="#invalid-handle" id="id46" name="id46">invalid_handle</a></li>
<li><a class="reference" href="#duplicate-torrent" id="id46" name="id46">duplicate_torrent</a></li> <li><a class="reference" href="#duplicate-torrent" id="id47" name="id47">duplicate_torrent</a></li>
<li><a class="reference" href="#invalid-encoding" id="id47" name="id47">invalid_encoding</a></li> <li><a class="reference" href="#invalid-encoding" id="id48" name="id48">invalid_encoding</a></li>
<li><a class="reference" href="#type-error" id="id48" name="id48">type_error</a></li> <li><a class="reference" href="#type-error" id="id49" name="id49">type_error</a></li>
<li><a class="reference" href="#invalid-torrent-file" id="id49" name="id49">invalid_torrent_file</a></li> <li><a class="reference" href="#invalid-torrent-file" id="id50" name="id50">invalid_torrent_file</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#examples" id="id50" name="id50">examples</a><ul> <li><a class="reference" href="#examples" id="id51" name="id51">examples</a><ul>
<li><a class="reference" href="#dump-torrent" id="id51" name="id51">dump_torrent</a></li> <li><a class="reference" href="#dump-torrent" id="id52" name="id52">dump_torrent</a></li>
<li><a class="reference" href="#simple-client" id="id52" name="id52">simple client</a></li> <li><a class="reference" href="#simple-client" id="id53" name="id53">simple client</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#fast-resume" id="id53" name="id53">fast resume</a><ul> <li><a class="reference" href="#fast-resume" id="id54" name="id54">fast resume</a><ul>
<li><a class="reference" href="#file-format" id="id54" name="id54">file format</a></li> <li><a class="reference" href="#file-format" id="id55" name="id55">file format</a></li>
</ul> </ul>
</li> </li>
<li><a class="reference" href="#extensions" id="id55" name="id55">extensions</a></li> <li><a class="reference" href="#extensions" id="id56" name="id56">extensions</a></li>
<li><a class="reference" href="#filenames-checks" id="id56" name="id56">filenames checks</a></li> <li><a class="reference" href="#filenames-checks" id="id57" name="id57">filenames checks</a></li>
<li><a class="reference" href="#aknowledgements" id="id57" name="id57">aknowledgements</a></li> <li><a class="reference" href="#aknowledgements" id="id58" name="id58">aknowledgements</a></li>
</ul> </ul>
</div> </div>
<div class="section" id="introduction"> <div class="section" id="introduction">
@ -584,6 +585,10 @@ struct torrent_handle
void connect_peer(const address&amp; adr) const; void connect_peer(const address&amp; adr) const;
void set_ratio(float ratio); void set_ratio(float ratio);
void pause();
void resume();
bool is_paused() const;
void set_tracker_login(std::string const&amp; username, std::string const&amp; password); void set_tracker_login(std::string const&amp; username, std::string const&amp; password);
void use_interface(const char* net_interface); void use_interface(const char* net_interface);
@ -620,6 +625,11 @@ in return. With this setting it will work much like the standard clients.</p>
attempt to upload in return for each download. e.g. if set to 2, the client will try to upload attempt to upload in return for each download. e.g. if set to 2, the client will try to upload
2 bytes for every byte received. The default setting for this is 0, which will make it work 2 bytes for every byte received. The default setting for this is 0, which will make it work
as a standard client.</p> as a standard client.</p>
<p><tt class="literal"><span class="pre">pause()</span></tt>, and <tt class="literal"><span class="pre">resume()</span></tt> will disconnect all peers and reconnect all peers respectively.
When a torrent is paused, it will however remember all share ratios to all peers and remember
all potential (not connected) peers. You can use <tt class="literal"><span class="pre">is_paused()</span></tt> to determine if a torrent
is currently paused. Torrents may be paused automatically if there is a file error (eg. disk full)
or something similar. See <a class="reference" href="#file-error-alert">file_error_alert</a>.</p>
<p><tt class="literal"><span class="pre">set_tracker_login()</span></tt> sets a username and password that will be sent along in the HTTP-request <p><tt class="literal"><span class="pre">set_tracker_login()</span></tt> sets a username and password that will be sent along in the HTTP-request
of the tracker announce. Set this if the tracker requires authorization.</p> of the tracker announce. Set this if the tracker requires authorization.</p>
<p><tt class="literal"><span class="pre">use_interface()</span></tt> sets the network interface this torrent will use when it opens outgoing <p><tt class="literal"><span class="pre">use_interface()</span></tt> sets the network interface this torrent will use when it opens outgoing
@ -1162,7 +1172,7 @@ struct listen_failed_alert: alert
<div class="section" id="file-error-alert"> <div class="section" id="file-error-alert">
<h2><a name="file-error-alert">file_error_alert</a></h2> <h2><a name="file-error-alert">file_error_alert</a></h2>
<p>If the storage fails to read or write files that it needs access to, this alert is <p>If the storage fails to read or write files that it needs access to, this alert is
generated and the torrent is aborted. It is generated as severity level <tt class="literal"><span class="pre">fatal</span></tt>.</p> generated and the torrent is paused. It is generated as severity level <tt class="literal"><span class="pre">fatal</span></tt>.</p>
<pre class="literal-block"> <pre class="literal-block">
struct file_error_alert: alert struct file_error_alert: alert
{ {
@ -1211,6 +1221,26 @@ struct hash_failed_alert: alert
}; };
</pre> </pre>
</div> </div>
<div class="section" id="peer-ban-alert">
<h2><a name="peer-ban-alert">peer_ban_alert</a></h2>
<p>This alert is generated when a peer is banned because it has sent too many corrupt pieces
to us. It is generated at severity level <tt class="literal"><span class="pre">info</span></tt>. The <tt class="literal"><span class="pre">handle</span></tt> member is a <a class="reference" href="#torrent-handle">torrent_handle</a>
to the torrent that this peer was a member of.</p>
<pre class="literal-block">
struct peer_ban_alert: alert
{
peer_error_alert(
address const&amp; pip
, torrent_handle h
, const std::string&amp; msg);
virtual std::auto_ptr&lt;alert&gt; clone() const;
address ip;
torrent_handle handle;
};
</pre>
</div>
<div class="section" id="peer-error-alert"> <div class="section" id="peer-error-alert">
<h2><a name="peer-error-alert">peer_error_alert</a></h2> <h2><a name="peer-error-alert">peer_error_alert</a></h2>
<p>This alert is generated when a peer sends invalid data over the peer-peer protocol. The peer <p>This alert is generated when a peer sends invalid data over the peer-peer protocol. The peer

View File

@ -584,6 +584,10 @@ Its declaration looks like this::
void connect_peer(const address& adr) const; void connect_peer(const address& adr) const;
void set_ratio(float ratio); void set_ratio(float ratio);
void pause();
void resume();
bool is_paused() const;
void set_tracker_login(std::string const& username, std::string const& password); void set_tracker_login(std::string const& username, std::string const& password);
void use_interface(const char* net_interface); void use_interface(const char* net_interface);
@ -626,6 +630,12 @@ attempt to upload in return for each download. e.g. if set to 2, the client will
2 bytes for every byte received. The default setting for this is 0, which will make it work 2 bytes for every byte received. The default setting for this is 0, which will make it work
as a standard client. as a standard client.
``pause()``, and ``resume()`` will disconnect all peers and reconnect all peers respectively.
When a torrent is paused, it will however remember all share ratios to all peers and remember
all potential (not connected) peers. You can use ``is_paused()`` to determine if a torrent
is currently paused. Torrents may be paused automatically if there is a file error (eg. disk full)
or something similar. See file_error_alert_.
``set_tracker_login()`` sets a username and password that will be sent along in the HTTP-request ``set_tracker_login()`` sets a username and password that will be sent along in the HTTP-request
of the tracker announce. Set this if the tracker requires authorization. of the tracker announce. Set this if the tracker requires authorization.
@ -1213,7 +1223,7 @@ file_error_alert
---------------- ----------------
If the storage fails to read or write files that it needs access to, this alert is If the storage fails to read or write files that it needs access to, this alert is
generated and the torrent is aborted. It is generated as severity level ``fatal``. generated and the torrent is paused. It is generated as severity level ``fatal``.
:: ::
@ -1271,6 +1281,29 @@ This alert is generated as severity level ``info``.
}; };
peer_ban_alert
--------------
This alert is generated when a peer is banned because it has sent too many corrupt pieces
to us. It is generated at severity level ``info``. The ``handle`` member is a torrent_handle_
to the torrent that this peer was a member of.
::
struct peer_ban_alert: alert
{
peer_error_alert(
address const& pip
, torrent_handle h
, const std::string& msg);
virtual std::auto_ptr<alert> clone() const;
address ip;
torrent_handle handle;
};
peer_error_alert peer_error_alert
---------------- ----------------

View File

@ -319,6 +319,25 @@ int main(int argc, char* argv[])
, handles.end() , handles.end()
, boost::bind(&torrent_handle::force_reannounce, _1)); , boost::bind(&torrent_handle::force_reannounce, _1));
} }
if(c == 'p')
{
// pause all torrents
std::for_each(
handles.begin()
, handles.end()
, boost::bind(&torrent_handle::pause, _1));
}
if(c == 'u')
{
// unpause all torrents
std::for_each(
handles.begin()
, handles.end()
, boost::bind(&torrent_handle::resume, _1));
}
} }
std::auto_ptr<alert> a; std::auto_ptr<alert> a;

View File

@ -72,6 +72,22 @@ namespace libtorrent
int piece_index; int piece_index;
}; };
struct peer_ban_alert: alert
{
peer_ban_alert(const address& pip, torrent_handle h, const std::string& msg)
: alert(alert::info, msg)
, ip(pip)
, handle(h)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_ban_alert(*this)); }
address ip;
torrent_handle handle;
};
struct peer_error_alert: alert struct peer_error_alert: alert
{ {
peer_error_alert(const address& pip, const std::string& msg) peer_error_alert(const address& pip, const std::string& msg)

View File

@ -199,6 +199,9 @@ namespace libtorrent
// if it was an incoming connection, it is remote // if it was an incoming connection, it is remote
bool is_local() const { return m_active; } bool is_local() const { return m_active; }
void set_failed() { m_failed = true; }
bool failed() const { return m_failed; }
#ifndef NDEBUG #ifndef NDEBUG
boost::shared_ptr<logger> m_logger; boost::shared_ptr<logger> m_logger;
#endif #endif
@ -385,6 +388,12 @@ namespace libtorrent
// we have choked the upload to the peer // we have choked the upload to the peer
bool m_choked; bool m_choked;
// this is set to true if the connection timed
// out or closed the connection. In that
// case we will not try to reconnect to
// this peer
bool m_failed;
// this is set to true if the handshake from // this is set to true if the handshake from
// the peer indicated that it supports the // the peer indicated that it supports the
// extension protocol // extension protocol

View File

@ -76,6 +76,11 @@ namespace libtorrent
// return false if the connection closed // return false if the connection closed
void new_connection(peer_connection& c); void new_connection(peer_connection& c);
// this is called if a peer timed-out or
// forcefully closed the connection. This
// will mark the connection as non-reconnectale
void peer_failed(peer_connection const& c);
// the given connection was just closed // the given connection was just closed
void connection_closed(const peer_connection& c); void connection_closed(const peer_connection& c);
@ -163,6 +168,11 @@ namespace libtorrent
peer_connection* connection; peer_connection* connection;
}; };
int num_peers() const
{
return m_num_peers;
}
private: private:
bool unchoke_one_peer(); bool unchoke_one_peer();

View File

@ -188,9 +188,14 @@ namespace libtorrent
// in loops that iterate over them. // in loops that iterate over them.
std::vector<connection_map::iterator> m_disconnect_peer; std::vector<connection_map::iterator> m_disconnect_peer;
// the peer id that is generated at the start of each torrent // the peer id that is generated at the start of the session
peer_id m_peer_id; peer_id m_peer_id;
// the key is an id that is used to identify the
// client with the tracker only. It is randomized
// at startup
int m_key;
// the range of ports we try to listen on // the range of ports we try to listen on
std::pair<int, int> m_listen_port_range; std::pair<int, int> m_listen_port_range;

View File

@ -101,14 +101,15 @@ namespace libtorrent
// tracker request // tracker request
bool should_request() const bool should_request() const
{ {
// boost::posix_time::time_duration d = m_next_request - boost::posix_time::second_clock::local_time(); namespace time = boost::posix_time;
// return d.is_negative(); return !m_paused &&
return m_next_request < boost::posix_time::second_clock::local_time(); m_next_request < time::second_clock::local_time();
} }
void force_tracker_request() void force_tracker_request()
{ {
m_next_request = boost::posix_time::second_clock::local_time(); namespace time = boost::posix_time;
m_next_request = time::second_clock::local_time();
} }
void print(std::ostream& os) const; void print(std::ostream& os) const;
@ -121,6 +122,10 @@ namespace libtorrent
size_type bytes_left() const; size_type bytes_left() const;
size_type bytes_done() const; size_type bytes_done() const;
void pause();
void resume();
bool is_paused() const { return m_paused; }
torrent_status status() const; torrent_status status() const;
void use_interface(const char* net_interface); void use_interface(const char* net_interface);
@ -188,7 +193,7 @@ namespace libtorrent
// generates a request string for sending // generates a request string for sending
// to the tracker // to the tracker
tracker_request generate_tracker_request(int port); tracker_request generate_tracker_request();
std::string tracker_password() const; std::string tracker_password() const;
boost::posix_time::ptime next_announce() const boost::posix_time::ptime next_announce() const
@ -293,6 +298,9 @@ namespace libtorrent
// been aborted. // been aborted.
bool m_abort; bool m_abort;
// is true if this torrent has been paused
bool m_paused;
tracker_request::event_t m_event; tracker_request::event_t m_event;
void parse_response(const entry& e, std::vector<peer_entry>& peer_list); void parse_response(const entry& e, std::vector<peer_entry>& peer_list);

View File

@ -96,6 +96,7 @@ namespace libtorrent
}; };
state_t state; state_t state;
bool paused;
float progress; float progress;
boost::posix_time::time_duration next_announce; boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval; boost::posix_time::time_duration announce_interval;
@ -152,6 +153,10 @@ namespace libtorrent
const torrent_info& get_torrent_info() const; const torrent_info& get_torrent_info() const;
bool is_valid() const; bool is_valid() const;
bool is_paused() const;
void pause();
void resume();
// set the interface to bind outgoing connections // set the interface to bind outgoing connections
// to. // to.
void use_interface(const char* net_interface); void use_interface(const char* net_interface);

View File

@ -90,6 +90,8 @@ namespace libtorrent
unsigned short listen_port; unsigned short listen_port;
event_t event; event_t event;
std::string url; std::string url;
int key;
int num_want;
}; };
struct request_callback struct request_callback

View File

@ -151,11 +151,16 @@ namespace libtorrent
m_send_buffer += "&event="; m_send_buffer += "&event=";
m_send_buffer += event_string[req.event - 1]; m_send_buffer += event_string[req.event - 1];
} }
m_send_buffer += "&key=";
// TODO: this should be encoded as hex
m_send_buffer += boost::lexical_cast<std::string>((unsigned int)req.key);
m_send_buffer += "&compact=1";
m_send_buffer += "&num_want=";
m_send_buffer += boost::lexical_cast<std::string>(req.num_want);
// extension that tells the tracker that // extension that tells the tracker that
// we don't need any peer_id's in the response // we don't need any peer_id's in the response
m_send_buffer += "&no_peer_id=1"; m_send_buffer += "&no_peer_id=1";
m_send_buffer += "&compact=1";
m_send_buffer += " HTTP/1.0\r\nAccept-Encoding: gzip\r\n" m_send_buffer += " HTTP/1.0\r\nAccept-Encoding: gzip\r\n"
"User-Agent: "; "User-Agent: ";

View File

@ -97,6 +97,7 @@ namespace libtorrent
, m_peer_choked(true) , m_peer_choked(true)
, m_interesting(false) , m_interesting(false)
, m_choked(true) , m_choked(true)
, m_failed(false)
, m_supports_extensions(false) , m_supports_extensions(false)
, m_num_pieces(0) , m_num_pieces(0)
, m_free_upload(0) , m_free_upload(0)
@ -159,6 +160,7 @@ namespace libtorrent
, m_peer_choked(true) , m_peer_choked(true)
, m_interesting(false) , m_interesting(false)
, m_choked(true) , m_choked(true)
, m_failed(false)
, m_supports_extensions(false) , m_supports_extensions(false)
, m_num_pieces(0) , m_num_pieces(0)
, m_free_upload(0) , m_free_upload(0)
@ -247,8 +249,10 @@ namespace libtorrent
void peer_connection::received_invalid_data() void peer_connection::received_invalid_data()
{ {
m_trust_points--; // we decrease more than we increase, to keep the
if (m_trust_points < -5) m_trust_points = -5; // allowed failed/passed ratio low.
m_trust_points -= 2;
if (m_trust_points < -7) m_trust_points = -7;
} }
int peer_connection::trust_points() const int peer_connection::trust_points() const
@ -1530,6 +1534,16 @@ namespace libtorrent
throw protocol_error("got info-hash that is not in our session"); throw protocol_error("got info-hash that is not in our session");
} }
if (m_torrent->is_paused())
{
// paused torrents will not accept
// incoming connections
#ifndef NDEBUG
(*m_logger) << " rejected connection to paused torrent\n";
#endif
throw protocol_error("connection rejected by paused torrent");
}
// assume the other end has no pieces // assume the other end has no pieces
m_have_piece.resize(m_torrent->torrent_file().num_pieces()); m_have_piece.resize(m_torrent->torrent_file().num_pieces());
std::fill(m_have_piece.begin(), m_have_piece.end(), false); std::fill(m_have_piece.begin(), m_have_piece.end(), false);
@ -1576,6 +1590,13 @@ namespace libtorrent
std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)tmp.begin()); std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)tmp.begin());
std::stringstream s; std::stringstream s;
s << "received peer_id: " << tmp << " client: " << identify_client(tmp) << "\n"; s << "received peer_id: " << tmp << " client: " << identify_client(tmp) << "\n";
s << "as ascii: ";
for (peer_id::iterator i = tmp.begin(); i != tmp.end(); ++i)
{
if (std::isprint(*i)) s << *i;
else s << ".";
}
s << "\n";
(*m_logger) << s.str(); (*m_logger) << s.str();
} }
#endif #endif

View File

@ -456,12 +456,11 @@ namespace libtorrent
{ {
if(i->connection) continue; if(i->connection) continue;
if(i->banned) continue; if(i->banned) continue;
if(i->type==peer::not_connectable) continue; if(i->type == peer::not_connectable) continue;
assert(i->connected <= local_time); assert(i->connected <= local_time);
boost::posix_time::ptime next_connect boost::posix_time::ptime next_connect = i->connected;
= i->connected + boost::posix_time::seconds(10 * 60);
if (next_connect <= ptime) if (next_connect <= ptime)
{ {
@ -736,6 +735,8 @@ namespace libtorrent
assert(i != m_peers.end()); assert(i != m_peers.end());
i->type = peer::not_connectable;
i->id.port = address::any_port;
i->banned = true; i->banned = true;
} }
@ -782,7 +783,7 @@ namespace libtorrent
if (i->connection != 0) if (i->connection != 0)
throw protocol_error("duplicate connection, closing"); throw protocol_error("duplicate connection, closing");
if (i->banned) if (i->banned)
throw protocol_error("ip address banned, disconnected"); throw protocol_error("ip address banned, closing");
} }
assert(i->connection == 0); assert(i->connection == 0);
@ -948,6 +949,11 @@ namespace libtorrent
c.add_free_upload(-diff); c.add_free_upload(-diff);
} }
} }
if (!c.is_choked())
{
c.send_choke();
--m_num_unchoked;
}
} }
bool policy::unchoke_one_peer() bool policy::unchoke_one_peer()
@ -999,7 +1005,7 @@ namespace libtorrent
bool policy::disconnect_one_peer() bool policy::disconnect_one_peer()
{ {
peer *p=find_disconnect_candidate(); peer *p = find_disconnect_candidate();
if(!p) if(!p)
return false; return false;
p->connection->disconnect(); p->connection->disconnect();
@ -1014,16 +1020,26 @@ namespace libtorrent
, m_peers.end() , m_peers.end()
, match_peer_connection(c)); , match_peer_connection(c));
// if we couldn't find the connection in our list, just ignore it.
if (i == m_peers.end()) return; if (i == m_peers.end()) return;
assert(i->connection == &c); assert(i->connection == &c);
i->connected = boost::posix_time::second_clock::local_time(); i->connected = boost::posix_time::second_clock::local_time();
if (!i->connection->is_choked() && !m_torrent->is_aborted()) if (!i->connection->is_choked() && !m_torrent->is_aborted())
{ {
// if the peer that is diconnecting is unchoked
// then unchoke another peer in order to maintain
// the total number of unchoked peers
--m_num_unchoked; --m_num_unchoked;
unchoke_one_peer(); unchoke_one_peer();
} }
if (c.failed())
{
i->type = peer::not_connectable;
i->id.port = address::any_port;
}
// if the share ratio is 0 (infinite), the // if the share ratio is 0 (infinite), the
// m_available_free_upload isn't used, // m_available_free_upload isn't used,
// because it isn't necessary. // because it isn't necessary.

View File

@ -277,6 +277,7 @@ namespace libtorrent { namespace detail
std::srand((unsigned int)std::time(0)); std::srand((unsigned int)std::time(0));
m_key = rand() + (rand() << 15) + (rand() << 30);
std::string print = cl_fprint.to_string(); std::string print = cl_fprint.to_string();
assert(print.length() == 8); assert(print.length() == 8);
@ -423,7 +424,10 @@ namespace libtorrent { namespace detail
++i) ++i)
{ {
i->second->abort(); i->second->abort();
m_tracker_manager.queue_request(i->second->generate_tracker_request(m_listen_interface.port)); tracker_request req = i->second->generate_tracker_request();
req.listen_port = m_listen_interface.port;
req.key = m_key;
m_tracker_manager.queue_request(req);
} }
m_connections.clear(); m_connections.clear();
m_torrents.clear(); m_torrents.clear();
@ -438,7 +442,7 @@ namespace libtorrent { namespace detail
// SEND SOCKETS // SEND SOCKETS
// ************************ // ************************
// let the writable clients send data // let the writable connections send data
for (std::vector<boost::shared_ptr<socket> >::iterator i for (std::vector<boost::shared_ptr<socket> >::iterator i
= writable_clients.begin(); = writable_clients.begin();
i != writable_clients.end(); i != writable_clients.end();
@ -473,10 +477,9 @@ namespace libtorrent { namespace detail
, e.what())); , e.what()));
} }
m_selector.remove(*i); // pause the torrent
m_connections.erase(p); t->pause();
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket); assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
t->abort();
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -488,6 +491,7 @@ namespace libtorrent { namespace detail
peer_error_alert(p->first->sender(), e.what())); peer_error_alert(p->first->sender(), e.what()));
} }
p->second->set_failed();
m_selector.remove(*i); m_selector.remove(*i);
m_connections.erase(p); m_connections.erase(p);
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket); assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
@ -547,7 +551,6 @@ namespace libtorrent { namespace detail
{ {
try try
{ {
// (*m_logger) << "readable: " << p->first->sender().as_string() << "\n";
p->second->receive_data(); p->second->receive_data();
} }
catch (file_error& e) catch (file_error& e)
@ -563,10 +566,8 @@ namespace libtorrent { namespace detail
, e.what())); , e.what()));
} }
m_selector.remove(*i);
m_connections.erase(p);
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket); assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
t->abort(); t->pause();
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -577,6 +578,7 @@ namespace libtorrent { namespace detail
} }
// the connection wants to disconnect for some reason, remove it // the connection wants to disconnect for some reason, remove it
// from the connection-list // from the connection-list
p->second->set_failed();
m_selector.remove(*i); m_selector.remove(*i);
m_connections.erase(p); m_connections.erase(p);
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket); assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
@ -611,6 +613,7 @@ namespace libtorrent { namespace detail
// 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()) if (p != m_connections.end())
{ {
p->second->set_failed();
m_connections.erase(p); m_connections.erase(p);
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket); assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
} }
@ -651,6 +654,7 @@ namespace libtorrent { namespace detail
m_alerts.post_alert( m_alerts.post_alert(
peer_error_alert(j->first->sender(), "connection timed out")); peer_error_alert(j->first->sender(), "connection timed out"));
} }
j->second->set_failed();
m_selector.remove(j->first); m_selector.remove(j->first);
m_connections.erase(j); m_connections.erase(j);
assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket); assert(m_selector.count_read_monitors() == (int)m_connections.size() + (bool)m_listen_socket);
@ -668,8 +672,10 @@ namespace libtorrent { namespace detail
{ {
if (i->second->is_aborted()) if (i->second->is_aborted())
{ {
m_tracker_manager.queue_request( tracker_request req = i->second->generate_tracker_request();
i->second->generate_tracker_request(m_listen_interface.port)); req.listen_port = m_listen_interface.port;
req.key = m_key;
m_tracker_manager.queue_request(req);
i->second->disconnect_all(); i->second->disconnect_all();
purge_connections(); purge_connections();
#ifndef NDEBUG #ifndef NDEBUG
@ -683,8 +689,11 @@ namespace libtorrent { namespace detail
} }
else if (i->second->should_request()) else if (i->second->should_request())
{ {
tracker_request req = i->second->generate_tracker_request();
req.listen_port = m_listen_interface.port;
req.key = m_key;
m_tracker_manager.queue_request( m_tracker_manager.queue_request(
i->second->generate_tracker_request(m_listen_interface.port) req
, boost::get_pointer(i->second)); , boost::get_pointer(i->second));
} }

View File

@ -220,6 +220,7 @@ namespace libtorrent
, address const& net_interface) , address const& net_interface)
: m_block_size(calculate_block_size(torrent_file)) : m_block_size(calculate_block_size(torrent_file))
, m_abort(false) , m_abort(false)
, m_paused(false)
, m_event(tracker_request::started) , m_event(tracker_request::started)
, m_torrent_file(torrent_file) , m_torrent_file(torrent_file)
, m_storage(m_torrent_file, save_path) , m_storage(m_torrent_file, save_path)
@ -419,11 +420,18 @@ namespace libtorrent
if (p == m_connections.end()) continue; if (p == m_connections.end()) continue;
p->second->received_invalid_data(); p->second->received_invalid_data();
if (p->second->trust_points() <= -5) if (p->second->trust_points() <= -7)
{ {
// we don't trust this peer anymore // we don't trust this peer anymore
// ban it. // ban it.
m_policy->ban_peer(*p->second); m_policy->ban_peer(*p->second);
if (m_ses.m_alerts.should_post(alert::info))
{
m_ses.m_alerts.post_alert(peer_ban_alert(
p->first
, get_handle()
, "banning peer because of too many corrupt pieces"));
}
} }
} }
@ -473,10 +481,8 @@ namespace libtorrent
return m_username + ":" + m_password; return m_username + ":" + m_password;
} }
tracker_request torrent::generate_tracker_request(int port) tracker_request torrent::generate_tracker_request()
{ {
assert(port > 0);
assert((unsigned short)port == port);
m_duration = 1800; m_duration = 1800;
m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration); m_next_request = boost::posix_time::second_clock::local_time() + boost::posix_time::seconds(m_duration);
@ -486,9 +492,16 @@ namespace libtorrent
req.downloaded = m_stat.total_payload_download(); req.downloaded = m_stat.total_payload_download();
req.uploaded = m_stat.total_payload_upload(); req.uploaded = m_stat.total_payload_upload();
req.left = bytes_left(); req.left = bytes_left();
req.listen_port = port;
req.event = m_event; req.event = m_event;
req.url = m_torrent_file.trackers()[m_currently_trying_tracker].url; req.url = m_torrent_file.trackers()[m_currently_trying_tracker].url;
req.num_want = (m_policy->get_max_connections()
- m_policy->num_peers()) * 2;
// default initialize, these should be set by caller
// before passing the request to the tracker_manager
req.listen_port = 0;
req.key = 0;
return req; return req;
} }
@ -530,9 +543,6 @@ namespace libtorrent
m_policy->connection_closed(*p); m_policy->connection_closed(*p);
m_connections.erase(i); m_connections.erase(i);
#ifndef NDEBUG
// m_picker.integrity_check(this);
#endif
} }
peer_connection& torrent::connect_to_peer(const address& a) peer_connection& torrent::connect_to_peer(const address& a)
@ -670,12 +680,31 @@ namespace libtorrent
} }
#endif #endif
void torrent::pause()
{
disconnect_all();
// TODO: announce to tracker that we stopped!
// possibly with some delay
m_paused = true;
}
void torrent::resume()
{
m_paused = false;
// TODO: announce to the tracker that we started.
// possibly with some delay
// make pulse be called as soon as possible
m_time_scaler = 0;
}
void torrent::second_tick() void torrent::second_tick()
{ {
m_time_scaler++; if (m_paused) return;
if (m_time_scaler >= 10)
m_time_scaler--;
if (m_time_scaler <= 0)
{ {
m_time_scaler = 0; m_time_scaler = 10;
m_policy->pulse(); m_policy->pulse();
} }
@ -738,6 +767,7 @@ namespace libtorrent
= m_torrent_file.trackers()[m_last_working_tracker].url; = m_torrent_file.trackers()[m_last_working_tracker].url;
} }
st.paused = m_paused;
st.total_done = bytes_done(); st.total_done = bytes_done();
// payload transfer // payload transfer
@ -759,9 +789,10 @@ namespace libtorrent
st.next_announce = next_announce() st.next_announce = next_announce()
- boost::posix_time::second_clock::local_time(); - boost::posix_time::second_clock::local_time();
if (st.next_announce.is_negative()) st.next_announce
= boost::posix_time::seconds(0);
st.announce_interval = boost::posix_time::seconds(m_duration); st.announce_interval = boost::posix_time::seconds(m_duration);
st.num_peers = (int)m_connections.size(); st.num_peers = (int)m_connections.size();
st.pieces = &m_have_pieces; st.pieces = &m_have_pieces;

View File

@ -204,7 +204,18 @@ namespace libtorrent
else else
st.state = torrent_status::queued_for_checking; st.state = torrent_status::queued_for_checking;
st.progress = d->progress; st.progress = d->progress;
st.paused = false;
st.next_announce = boost::posix_time::time_duration(); st.next_announce = boost::posix_time::time_duration();
st.announce_interval = boost::posix_time::time_duration();
st.total_download = 0;
st.total_upload = 0;
st.total_payload_download = 0;
st.total_payload_upload = 0;
st.download_rate = 0.f;
st.upload_rate = 0.f;
st.num_peers = 0;
st.pieces = 0;
st.total_done = 0;
return st; return st;
} }
} }
@ -234,6 +245,73 @@ namespace libtorrent
throw invalid_handle(); throw invalid_handle();
} }
bool torrent_handle::is_paused() const
{
INVARIANT_CHECK;
if (m_ses == 0) throw invalid_handle();
{
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);
if (t != 0) return t->is_paused();
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
if (d != 0) return d->torrent_ptr->is_paused();
}
throw invalid_handle();
}
void torrent_handle::pause()
{
INVARIANT_CHECK;
if (m_ses == 0) throw invalid_handle();
{
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);
if (t != 0) return t->pause();
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
if (d != 0) return d->torrent_ptr->pause();
}
throw invalid_handle();
}
void torrent_handle::resume()
{
INVARIANT_CHECK;
if (m_ses == 0) throw invalid_handle();
{
boost::mutex::scoped_lock l(m_ses->m_mutex);
torrent* t = m_ses->find_torrent(m_info_hash);
if (t != 0) return t->resume();
}
if (m_chk)
{
boost::mutex::scoped_lock l(m_chk->m_mutex);
detail::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
if (d != 0) return d->torrent_ptr->resume();
}
throw invalid_handle();
}
void torrent_handle::set_tracker_login(std::string const& name, std::string const& password) void torrent_handle::set_tracker_login(std::string const& name, std::string const& password)
{ {
INVARIANT_CHECK; INVARIANT_CHECK;

View File

@ -180,7 +180,7 @@ namespace libtorrent
// ip address // ip address
detail::write_int32(0, ptr); detail::write_int32(0, ptr);
// num_want // num_want
detail::write_int32(-1, ptr); detail::write_int32(m_request.num_want, ptr);
// port // port
detail::write_uint16(m_request.listen_port, ptr); detail::write_uint16(m_request.listen_port, ptr);