there are still some serious issues with storage when having large torrents (about 700 meg and up at least)

This commit is contained in:
Arvid Norberg
2003-12-01 05:01:40 +00:00
parent 0019e23b4f
commit f21d6a0f7f
18 changed files with 458 additions and 174 deletions

View File

@@ -182,8 +182,9 @@ int main(int argc, char* argv[])
in.unsetf(std::ios_base::skipws); in.unsetf(std::ios_base::skipws);
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>()); entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
torrent_info t(e); torrent_info t(e);
// t.convert_file_names();
t.print(std::cout); t.print(std::cout);
handles.push_back(s.add_torrent(t, "")); handles.push_back(s.add_torrent(t, boost::filesystem::path("", boost::filesystem::native)));
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@@ -137,7 +137,7 @@ namespace libtorrent
void cancel_block(piece_block block); void cancel_block(piece_block block);
bool is_interesting() const throw() { return m_interesting; } bool is_interesting() const throw() { return m_interesting; }
bool has_choked() const throw() { return m_choked; } bool is_choked() const throw() { return m_choked; }
bool is_peer_interested() const throw() { return m_peer_interested; } bool is_peer_interested() const throw() { return m_peer_interested; }
bool has_peer_choked() const throw() { return m_peer_choked; } bool has_peer_choked() const throw() { return m_peer_choked; }
@@ -146,7 +146,7 @@ namespace libtorrent
// may be zero if the connection is an incoming connection // may be zero if the connection is an incoming connection
// and it hasn't received enough information to determine // and it hasn't received enough information to determine
// which torrent it should be associated with // which torrent it should be associated with
torrent* associated_torrent() const throw() { return m_torrent; } torrent* associated_torrent() const throw() { return m_attached_to_torrent?m_torrent:0; }
const stat& statistics() const { return m_statistics; } const stat& statistics() const { return m_statistics; }
@@ -239,7 +239,20 @@ namespace libtorrent
selector& m_selector; selector& m_selector;
boost::shared_ptr<libtorrent::socket> m_socket; boost::shared_ptr<libtorrent::socket> m_socket;
// this is the torrent this connection is
// associated with. If the connection is an
// incoming conncetion, this is set to zero
// until the info_hash is received. Then it's
// set to the torrent it belongs to.
torrent* m_torrent; torrent* m_torrent;
// this is set to false until the peer_id
// is received from the other end. Or is
// true if the conenction was actively
// opened from our side.
bool m_attached_to_torrent;
detail::session_impl* m_ses; detail::session_impl* m_ses;
// is true if it was we that connected to the peer // is true if it was we that connected to the peer
// and false if we got an incomming connection // and false if we got an incomming connection

View File

@@ -36,6 +36,9 @@ POSSIBILITY OF SUCH DAMAGE.
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <boost/weak_ptr.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "libtorrent/peer.hpp" #include "libtorrent/peer.hpp"
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
@@ -53,9 +56,13 @@ namespace libtorrent
public: public:
policy(torrent* t); policy(torrent* t);
// this is called each time we get an incoming connection
// return true to accept the connection // this is called every 10 seconds to allow
bool accept_connection(const address& remote); // for peer choking management
void pulse();
// called when an incoming connection is accepted
void new_connection(const boost::weak_ptr<peer_connection>& c);
// this is called once for every peer we get from // this is called once for every peer we get from
// the tracker // the tracker
@@ -83,8 +90,77 @@ namespace libtorrent
// the peer is not interested in our pieces // the peer is not interested in our pieces
void not_interested(peer_connection& c); void not_interested(peer_connection& c);
#ifndef NDEBUG
bool has_connection(const peer_connection* p);
#endif
private: private:
struct peer
{
peer(const peer_id& pid)
: id(pid)
, last_optimistically_unchoked(boost::posix_time::second_clock::local_time())
, connected(boost::posix_time::second_clock::local_time())
, optimistic_unchokes(0)
, prev_amount_upload(0)
, prev_amount_download(0)
{}
bool operator==(const peer_id& pid) const
{ return id == pid; }
// the id of the peer. This is needed to store information
// about peers that aren't connected right now. This
// is to avoid peers reconnecting. unconnected entries
// will be saved a limited amount of time
peer_id id;
// the time when this peer was optimistically unchoked
// the last time.
boost::posix_time::ptime last_optimistically_unchoked;
// the time when the peer connected to us
// or disconnected if it isn't connected right now
boost::posix_time::ptime connected;
// the number of optimistic unchokes this peer has
// been given
int optimistic_unchokes;
// this is the accumulated amount of
// uploaded and downloaded data to this
// peer. It only accounts for what was
// shared during the last connection to
// this peer. i.e. These are only updated
// when the connection is closed. For the
// total amount of upload and download
// we'll have to add thes figures with the
// statistics from the peer_connection.
int prev_amount_upload;
int prev_amount_download;
// if the peer is connected now, this
// will refer to a valid peer_connection
boost::weak_ptr<peer_connection> connection;
};
// a functor that identifies peers that have disconnected and that
// are too old for still being saved.
struct old_disconnected_peer
{
bool operator()(const peer& p)
{
using namespace boost::posix_time;
return p.connection.expired()
&& second_clock::local_time() - p.connected > seconds(5*60);
}
};
std::vector<peer> m_peers;
int m_num_peers; int m_num_peers;
torrent* m_torrent; torrent* m_torrent;

View File

@@ -171,6 +171,7 @@ namespace libtorrent
alert_manager m_alerts; alert_manager m_alerts;
#ifndef NDEBUG #ifndef NDEBUG
void assert_invariant();
boost::shared_ptr<logger> create_log(std::string name); boost::shared_ptr<logger> create_log(std::string name);
boost::shared_ptr<logger> m_logger; boost::shared_ptr<logger> m_logger;
#endif #endif

View File

@@ -33,6 +33,9 @@ POSSIBILITY OF SUCH DAMAGE.
#ifndef TORRENT_SOCKET_WIN_HPP_INCLUDED #ifndef TORRENT_SOCKET_WIN_HPP_INCLUDED
#define TORRENT_SOCKET_WIN_HPP_INCLUDED #define TORRENT_SOCKET_WIN_HPP_INCLUDED
// TODO: remove the dependency of
// platform specific headers here.
#if defined(_WIN32) #if defined(_WIN32)
#include <winsock2.h> #include <winsock2.h>
#else #else
@@ -135,57 +138,32 @@ namespace libtorrent
enum error_code enum error_code
{ {
#if defined(_WIN32) netdown,
netdown = WSAENETDOWN, fault,
fault = WSAEFAULT, access,
access = WSAEACCES, address_in_use,
address_in_use = WSAEADDRINUSE, address_not_available,
address_not_available = WSAEADDRNOTAVAIL, in_progress,
in_progress = WSAEINPROGRESS, interrupted,
interrupted = WSAEINTR, invalid,
invalid = WSAEINVAL, net_reset,
net_reset = WSAENETRESET, not_connected,
not_connected = WSAENOTCONN, no_buffers,
no_buffers = WSAENOBUFS, operation_not_supported,
operation_not_supported = WSAEOPNOTSUPP, not_socket,
not_socket = WSAENOTSOCK, shutdown,
shutdown = WSAESHUTDOWN, would_block,
would_block = WSAEWOULDBLOCK, connection_reset,
connection_reset = WSAECONNRESET, timed_out,
timed_out = WSAETIMEDOUT, connection_aborted,
connection_aborted = WSAECONNABORTED, message_size,
message_size = WSAEMSGSIZE, not_ready,
not_ready = WSAEALREADY, no_support,
no_support = WSAEAFNOSUPPORT, connection_refused,
connection_refused = WSAECONNREFUSED, is_connected,
is_connected = WSAEISCONN, net_unreachable,
net_unreachable = WSAENETUNREACH not_initialized,
#else unknown_error
netdown = ENETDOWN,
fault = EFAULT,
access = EACCES,
address_in_use = EADDRINUSE,
address_not_available = EADDRNOTAVAIL,
in_progress = EINPROGRESS,
interrupted = EINTR,
invalid = EINVAL,
net_reset = ENETRESET,
not_connected = ENOTCONN,
no_buffers = ENOMEM,
operation_not_supported = EOPNOTSUPP,
not_socket = ENOTSOCK,
shutdown = ESHUTDOWN,
would_block = EAGAIN,
connection_reset = ECONNRESET,
timed_out = ETIMEDOUT,
connection_aborted = ECONNABORTED,
message_size = EMSGSIZE,
not_ready = EALREADY,
no_support = EAFNOSUPPORT,
connection_refused = ECONNREFUSED,
is_connected = EISCONN,
net_unreachable = ENETUNREACH
#endif
}; };
error_code last_error() const; error_code last_error() const;

View File

@@ -58,6 +58,10 @@ namespace libtorrent
std::fill(m_upload_per_second_history, m_upload_per_second_history+history, 0); std::fill(m_upload_per_second_history, m_upload_per_second_history+history, 0);
} }
// TODO: these function should take two arguments
// to be able to count both total data sent and also
// count only the actual payload (not counting the
// protocol chatter)
void received_bytes(int num_bytes) void received_bytes(int num_bytes)
{ m_downloaded += num_bytes; m_total_download += num_bytes; } { m_downloaded += num_bytes; m_total_download += num_bytes; }
void sent_bytes(int num_bytes) void sent_bytes(int num_bytes)

View File

@@ -44,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
@@ -115,7 +116,7 @@ namespace libtorrent
void reopen(); void reopen();
// the file itself // the file itself
std::fstream m_file; boost::filesystem::fstream m_file;
// the mode with which this file was opened // the mode with which this file was opened
open_mode m_mode; open_mode m_mode;

View File

@@ -87,6 +87,9 @@ namespace libtorrent
void abort() { m_abort = true; m_event = event_stopped; } void abort() { m_abort = true; m_event = event_stopped; }
bool is_aborted() const { return m_abort; } bool is_aborted() const { return m_abort; }
// is called every second by session.
void second_tick();
// returns true if it time for this torrent to make another // returns true if it time for this torrent to make another
// tracker request // tracker request
bool should_request() const throw() bool should_request() const throw()
@@ -96,9 +99,6 @@ namespace libtorrent
return m_next_request < boost::posix_time::second_clock::local_time(); return m_next_request < boost::posix_time::second_clock::local_time();
} }
bool failed() const throw() { return !m_failed.empty(); }
const char* fail_reason() const throw() { return m_failed.c_str(); }
void print(std::ostream& os) const; void print(std::ostream& os) const;
void allocate_files(detail::piece_checker_data* data, void allocate_files(detail::piece_checker_data* data,
@@ -114,9 +114,12 @@ namespace libtorrent
torrent_status status() const; torrent_status status() const;
void connect_to_peer(const address& a, const peer_id& id); boost::weak_ptr<peer_connection> connect_to_peer(
const address& a
, const peer_id& id);
const torrent_info& torrent_file() const throw() { return m_torrent_file; } const torrent_info& torrent_file() const throw()
{ return m_torrent_file; }
policy& get_policy() { return *m_policy; } policy& get_policy() { return *m_policy; }
storage* filesystem() { return &m_storage; } storage* filesystem() { return &m_storage; }
@@ -128,11 +131,7 @@ namespace libtorrent
// used by peer_connection to attach itself to a torrent // used by peer_connection to attach itself to a torrent
// since incoming connections don't know what torrent // since incoming connections don't know what torrent
// they're a part of until they have received an info_hash. // they're a part of until they have received an info_hash.
void attach_peer(peer_connection* p) void attach_peer(peer_connection* p);
{
assert(std::find(m_connections.begin(), m_connections.end(), p) == m_connections.end());
m_connections.push_back(p);
}
// this will remove the peer and make sure all // this will remove the peer and make sure all
// the pieces it had have their reference counter // the pieces it had have their reference counter
@@ -142,9 +141,9 @@ namespace libtorrent
// the number of peers that belong to this torrent // the number of peers that belong to this torrent
int num_peers() const { return m_connections.size(); } int num_peers() const { return m_connections.size(); }
// returns the number of connections this torrent has to // returns true if this torrent has a connection
// the given peer_id (should be kept at max 1) // to a peer with the given peer_id
int num_connections(const peer_id& id) const; bool has_peer(const peer_id& id) const;
typedef std::vector<peer_connection*>::iterator peer_iterator; typedef std::vector<peer_connection*>::iterator peer_iterator;
typedef std::vector<peer_connection*>::const_iterator peer_const_iterator; typedef std::vector<peer_connection*>::const_iterator peer_const_iterator;
@@ -270,7 +269,6 @@ namespace libtorrent
// from the tracker // from the tracker
int m_duration; int m_duration;
std::string m_failed;
std::vector<peer_connection*> m_connections; std::vector<peer_connection*> m_connections;
// ----------------------------- // -----------------------------
@@ -285,6 +283,10 @@ namespace libtorrent
int m_last_working_tracker; int m_last_working_tracker;
int m_currently_trying_tracker; int m_currently_trying_tracker;
// this is a counter that is increased every
// second, and when it reaches 10, the policy::pulse()
// is called and the time scaler is reset to 0.
int m_time_scaler;
}; };
} }

View File

@@ -122,6 +122,8 @@ namespace libtorrent
const std::string& name() const { return m_name; } const std::string& name() const { return m_name; }
void print(std::ostream& os) const; void print(std::ostream& os) const;
void convert_file_names();
entry::integer_type piece_size(unsigned int index) const entry::integer_type piece_size(unsigned int index) const
{ {
if (index == num_pieces()-1) if (index == num_pieces()-1)

View File

@@ -59,9 +59,9 @@ namespace libtorrent {
{ {
boost::mutex::scoped_lock lock(m_mutex); boost::mutex::scoped_lock lock(m_mutex);
assert(pending()); assert(!m_alerts.empty());
alert* result(m_alerts.front()); alert* result = m_alerts.front();
m_alerts.pop(); m_alerts.pop();
return std::auto_ptr<alert>(result); return std::auto_ptr<alert>(result);
} }

View File

@@ -86,6 +86,7 @@ libtorrent::peer_connection::peer_connection(
, m_selector(sel) , m_selector(sel)
, m_socket(s) , m_socket(s)
, m_torrent(t) , m_torrent(t)
, m_attached_to_torrent(true)
, m_ses(ses) , m_ses(ses)
, m_active(true) , m_active(true)
, m_added_to_selector(false) , m_added_to_selector(false)
@@ -130,6 +131,7 @@ libtorrent::peer_connection::peer_connection(
, m_selector(sel) , m_selector(sel)
, m_socket(s) , m_socket(s)
, m_torrent(0) , m_torrent(0)
, m_attached_to_torrent(0)
, m_ses(ses) , m_ses(ses)
, m_active(false) , m_active(false)
, m_added_to_selector(false) , m_added_to_selector(false)
@@ -159,7 +161,11 @@ libtorrent::peer_connection::peer_connection(
libtorrent::peer_connection::~peer_connection() libtorrent::peer_connection::~peer_connection()
{ {
m_selector.remove(m_socket); m_selector.remove(m_socket);
if (m_torrent) m_torrent->remove_peer(this); if (m_attached_to_torrent)
{
assert(m_torrent != 0);
m_torrent->remove_peer(this);
}
} }
void libtorrent::peer_connection::set_send_quota(int num_bytes) void libtorrent::peer_connection::set_send_quota(int num_bytes)
@@ -715,13 +721,17 @@ void libtorrent::peer_connection::send_have(int index)
void libtorrent::peer_connection::receive_data() void libtorrent::peer_connection::receive_data()
{ {
assert(!m_socket->is_blocking()); assert(!m_socket->is_blocking());
assert(m_packet_size > 0);
for(;;) for(;;)
{ {
// m_socket->set_blocking(false); assert(m_packet_size > 0);
int received = m_socket->receive(&m_recv_buffer[m_recv_pos], m_packet_size - m_recv_pos); int received = m_socket->receive(&m_recv_buffer[m_recv_pos], m_packet_size - m_recv_pos);
// connection closed // connection closed
if (received == 0) throw network_error(0); if (received == 0)
{
throw network_error(0);
}
// an error // an error
if (received < 0) if (received < 0)
@@ -754,6 +764,14 @@ void libtorrent::peer_connection::receive_data()
m_state = read_protocol_string; m_state = read_protocol_string;
m_recv_buffer.resize(m_packet_size); m_recv_buffer.resize(m_packet_size);
m_recv_pos = 0; m_recv_pos = 0;
if (m_packet_size == 0)
{
#ifndef NDEBUG
(*m_logger) << "incorrect protocol length\n";
#endif
throw network_error(0);
}
break; break;
@@ -765,7 +783,12 @@ void libtorrent::peer_connection::receive_data()
const char protocol_string[] = "BitTorrent protocol"; const char protocol_string[] = "BitTorrent protocol";
const int protocol_len = sizeof(protocol_string) - 1; const int protocol_len = sizeof(protocol_string) - 1;
if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), protocol_string)) if (!std::equal(m_recv_buffer.begin(), m_recv_buffer.end(), protocol_string))
{
#ifndef NDEBUG
(*m_logger) << "incorrect protocol name\n";
#endif
throw network_error(0); throw network_error(0);
}
m_state = read_info_hash; m_state = read_info_hash;
m_packet_size = 28; m_packet_size = 28;
@@ -800,7 +823,6 @@ void libtorrent::peer_connection::receive_data()
#endif #endif
throw network_error(0); throw network_error(0);
} }
m_torrent->attach_peer(this);
// 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());
@@ -855,13 +877,18 @@ void libtorrent::peer_connection::receive_data()
// check to make sure we don't have another connection with the same // check to make sure we don't have another connection with the same
// info_hash and peer_id. If we do. close this connection. // info_hash and peer_id. If we do. close this connection.
std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)m_peer_id.begin()); std::copy(m_recv_buffer.begin(), m_recv_buffer.begin() + 20, (char*)m_peer_id.begin());
if (m_torrent->num_connections(m_peer_id) > 1)
if (m_torrent->has_peer(m_peer_id))
{ {
#ifndef NDEBUG #ifndef NDEBUG
(*m_logger) << m_socket->sender().as_string() << " duplicate connection, closing\n"; (*m_logger) << m_socket->sender().as_string() << " duplicate connection, closing\n";
#endif #endif
throw network_error(0); throw network_error(0);
} }
m_attached_to_torrent = true;
m_torrent->attach_peer(this);
assert(m_torrent->get_policy().has_connection(this));
} }
m_state = read_packet_size; m_state = read_packet_size;
@@ -900,6 +927,7 @@ void libtorrent::peer_connection::receive_data()
m_recv_buffer.resize(m_packet_size); m_recv_buffer.resize(m_packet_size);
} }
m_recv_pos = 0; m_recv_pos = 0;
assert(m_packet_size > 0);
break; break;
case read_packet: case read_packet:
@@ -917,11 +945,13 @@ void libtorrent::peer_connection::receive_data()
m_packet_size = 4; m_packet_size = 4;
m_recv_buffer.resize(4); m_recv_buffer.resize(4);
m_recv_pos = 0; m_recv_pos = 0;
assert(m_packet_size > 0);
break; break;
} }
} }
} }
} }
assert(m_packet_size > 0);
} }

View File

@@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
#include <vector> #include <vector>
#include <cmath> #include <cmath>
#include <algorithm>
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
@@ -40,8 +41,13 @@ POSSIBILITY OF SUCH DAMAGE.
#include "libtorrent/peer_connection.hpp" #include "libtorrent/peer_connection.hpp"
#endif #endif
#if defined(_MSC_VER) #if defined(_MSC_VER) && _MSC_VER < 1300
#define for if (false) {} else for #define for if (false) {} else for
namespace std
{
template<class T>
inline T min(T a, T b) { return a<b?a:b; }
}
#endif #endif
namespace libtorrent namespace libtorrent
@@ -85,7 +91,7 @@ namespace libtorrent
m_piece_info[peer_count].push_back(index); m_piece_info[peer_count].push_back(index);
} }
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
// TODO: random_shuffle // TODO: random_shuffle
} }
@@ -299,7 +305,7 @@ namespace libtorrent
move(true, m_piece_map[index].peer_count, m_piece_map[index].index); move(true, m_piece_map[index].peer_count, m_piece_map[index].index);
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
} }
@@ -356,7 +362,7 @@ namespace libtorrent
assert(info_index != 0xffffff); assert(info_index != 0xffffff);
remove(m_piece_map[index].downloading, peer_count, info_index); remove(m_piece_map[index].downloading, peer_count, info_index);
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
} }
@@ -367,7 +373,7 @@ namespace libtorrent
assert(pieces.size() == m_piece_map.size()); assert(pieces.size() == m_piece_map.size());
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
// free refers to pieces that are free to download, noone else // free refers to pieces that are free to download, noone else
@@ -502,7 +508,7 @@ namespace libtorrent
void piece_picker::mark_as_downloading(piece_block block, const peer_id& peer) void piece_picker::mark_as_downloading(piece_block block, const peer_id& peer)
{ {
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
assert(block.piece_index < m_piece_map.size()); assert(block.piece_index < m_piece_map.size());
assert(block.block_index < blocks_in_piece(block.piece_index)); assert(block.block_index < blocks_in_piece(block.piece_index));
@@ -529,14 +535,14 @@ namespace libtorrent
i->requested_blocks[block.block_index] = 1; i->requested_blocks[block.block_index] = 1;
} }
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
} }
void piece_picker::mark_as_finished(piece_block block, const peer_id& peer) void piece_picker::mark_as_finished(piece_block block, const peer_id& peer)
{ {
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
assert(block.piece_index < m_piece_map.size()); assert(block.piece_index < m_piece_map.size());
assert(block.block_index < blocks_in_piece(block.piece_index)); assert(block.block_index < blocks_in_piece(block.piece_index));
@@ -564,7 +570,7 @@ namespace libtorrent
i->finished_blocks[block.block_index] = 1; i->finished_blocks[block.block_index] = 1;
} }
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
} }
/* /*
@@ -610,7 +616,7 @@ namespace libtorrent
void piece_picker::abort_download(piece_block block) void piece_picker::abort_download(piece_block block)
{ {
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
assert(block.piece_index < m_piece_map.size()); assert(block.piece_index < m_piece_map.size());
@@ -643,7 +649,7 @@ namespace libtorrent
move(true, m_piece_map[block.piece_index].peer_count, m_piece_map[block.piece_index].index); move(true, m_piece_map[block.piece_index].peer_count, m_piece_map[block.piece_index].index);
} }
#ifndef NDEBUG #ifndef NDEBUG
integrity_check(); // integrity_check();
#endif #endif
} }

View File

@@ -32,6 +32,8 @@ POSSIBILITY OF SUCH DAMAGE.
#include <iostream> #include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include "libtorrent/policy.hpp" #include "libtorrent/policy.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
@@ -137,7 +139,7 @@ namespace
peer_connection* peer = 0; peer_connection* peer = 0;
float down_speed = -1.f; float down_speed = -1.f;
// find the peer with the lowest download // find the peer with the lowest download
// speed that also has a piece thatt this // speed that also has a piece that this
// peer could send us // peer could send us
for (torrent::peer_iterator i = t.begin(); for (torrent::peer_iterator i = t.begin();
i != t.end(); i != t.end();
@@ -171,6 +173,7 @@ namespace
num_requests--; num_requests--;
} }
} }
namespace libtorrent namespace libtorrent
@@ -197,14 +200,6 @@ namespace libtorrent
TODO: to implement choking/unchoking we need a list with all TODO: to implement choking/unchoking we need a list with all
connected peers. Something like this: connected peers. Something like this:
struct peer
{
peer_id id;
boost::posix_time::ptime last_optimistically_unchoked;
float average_down_rate;
boost::weak_ptr<peer_connection> connection;
};
*/ */
@@ -213,21 +208,92 @@ namespace libtorrent
, m_torrent(t) , m_torrent(t)
{} {}
void policy::pulse()
// this is called when a connection is made, before any
// handshake (it's possible to ban certain ip:s).
bool policy::accept_connection(const address& remote)
{ {
m_num_peers++; using namespace boost::posix_time;
return true;
// remove old disconnected peers from the list
m_peers.erase(
std::remove_if(m_peers.begin()
, m_peers.end()
, old_disconnected_peer())
, m_peers.end());
// choke peers that have leeched too much without giving anything back
for (std::vector<peer>::iterator i = m_peers.begin(); i != m_peers.end(); ++i)
{
boost::shared_ptr<peer_connection> c = i->connection.lock();
if (c.get() == 0) continue;
int downloaded = i->prev_amount_download + c->statistics().total_download();
int uploaded = i->prev_amount_upload + c->statistics().total_upload();
if (uploaded - downloaded > m_torrent->torrent_file().piece_length()
&& !c->is_choked())
{
// if we have uploaded more than a piece for free, choke peer and
// wait until we catch up with our download.
c->choke();
}
else if (uploaded - downloaded <= m_torrent->block_size()
&& c->is_choked() && c->is_peer_interested())
{
// we have catched up. We have now shared the same amount
// to eachother. Unchoke this peer.
c->unchoke();
}
}
}
void policy::new_connection(const boost::weak_ptr<peer_connection>& c)
{
boost::shared_ptr<peer_connection> con = c.lock();
assert(con.get() != 0);
if (con.get() == 0) return;
std::vector<peer>::iterator i
= std::find(m_peers.begin(), m_peers.end(), con->get_peer_id());
if (i == m_peers.end())
{
// we don't have ny info about this peer.
// add a new entry
peer p(con->get_peer_id());
m_peers.push_back(p);
i = m_peers.end()-1;
}
else
{
assert(i->connection.expired());
}
i->connected = boost::posix_time::second_clock::local_time();
i->connection = c;
} }
void policy::peer_from_tracker(const address& remote, const peer_id& id) void policy::peer_from_tracker(const address& remote, const peer_id& id)
{ {
try try
{ {
m_torrent->connect_to_peer(remote, id); std::vector<peer>::iterator i = std::find(m_peers.begin(), m_peers.end(), id);
m_num_peers++; if (i == m_peers.end())
{
// we don't have ny info about this peer.
// add a new entry
peer p(id);
m_peers.push_back(p);
i = m_peers.end()-1;
}
else if (!i->connection.expired())
{
// this means we're already connected
// to this peer. don't connect to
// it again.
return;
}
i->connected = boost::posix_time::second_clock::local_time();
i->connection = m_torrent->connect_to_peer(remote, id);
} }
catch(network_error&) {} catch(network_error&) {}
} }
@@ -237,9 +303,9 @@ namespace libtorrent
// anything for a while // anything for a while
void policy::choked(peer_connection& c) void policy::choked(peer_connection& c)
{ {
c.choke();
} }
// TODO: the peer_connection argument here should be removed.
void policy::piece_finished(peer_connection& c, int index, bool successfully_verified) void policy::piece_finished(peer_connection& c, int index, bool successfully_verified)
{ {
// TODO: if verification failed, mark the peers that were involved // TODO: if verification failed, mark the peers that were involved
@@ -248,8 +314,8 @@ namespace libtorrent
void policy::block_finished(peer_connection& c, piece_block b) void policy::block_finished(peer_connection& c, piece_block b)
{ {
if (c.has_peer_choked()) return; // if the peer hasn't choked us, ask for another piece
request_a_block(*m_torrent, c); if (!c.has_peer_choked()) request_a_block(*m_torrent, c);
} }
// this is called when we are unchoked by a peer // this is called when we are unchoked by a peer
@@ -257,21 +323,33 @@ namespace libtorrent
// data from now on // data from now on
void policy::unchoked(peer_connection& c) void policy::unchoked(peer_connection& c)
{ {
c.unchoke(); if (c.is_interesting())
if (c.is_interesting()) request_a_block(*m_torrent, c); {
request_a_block(*m_torrent, c);
}
} }
void policy::interested(peer_connection& c) void policy::interested(peer_connection& c)
{ {
c.unchoke(); // if we're interested in the peer, we unchoke it
// and hopes it will unchoke us too
} }
void policy::not_interested(peer_connection& c) void policy::not_interested(peer_connection& c)
{ {
} }
// this is called whenever a peer connection is closed
void policy::connection_closed(const peer_connection& c) void policy::connection_closed(const peer_connection& c)
{ {
std::vector<peer>::iterator i
= std::find(m_peers.begin(), m_peers.end(), c.get_peer_id());
assert(i != m_peers.end());
i->connected = boost::posix_time::second_clock::local_time();
i->prev_amount_download += c.statistics().total_download();
i->prev_amount_upload += c.statistics().total_upload();
} }
void policy::peer_is_interesting(peer_connection& c) void policy::peer_is_interesting(peer_connection& c)
@@ -280,4 +358,11 @@ namespace libtorrent
if (c.has_peer_choked()) return; if (c.has_peer_choked()) return;
request_a_block(*m_torrent, c); request_a_block(*m_torrent, c);
} }
#ifndef NDEBUG
bool policy::has_connection(const peer_connection* p)
{
return std::find(m_peers.begin(), m_peers.end(), p->get_peer_id()) != m_peers.end();
}
#endif
} }

View File

@@ -105,7 +105,7 @@ namespace libtorrent
std::make_pair(t->info_hash, t->torrent_ptr)).first; std::make_pair(t->info_hash, t->torrent_ptr)).first;
} }
} }
catch(const boost::filesystem::filesystem_error& e) catch(const std::exception& e)
{ {
#ifndef NDEBUG #ifndef NDEBUG
std::cerr << "error while checking files: " << e.what() << "\n"; std::cerr << "error while checking files: " << e.what() << "\n";
@@ -206,40 +206,26 @@ namespace libtorrent
m_selector.monitor_readability(listener); m_selector.monitor_readability(listener);
m_selector.monitor_errors(listener); m_selector.monitor_errors(listener);
/*
// temp
const peer& p = *m_peer_list.begin();
boost::shared_ptr<libtorrent::socket> s(new socket(socket::tcp, false));
address a(p.ip, p.port);
s->connect(a);
m_connections.insert(std::make_pair(s, peer_connection(this, s, p.id)));
m_selector.monitor_readability(s);
m_selector.monitor_errors(s);
// ~temp
*/
std::vector<boost::shared_ptr<socket> > readable_clients; std::vector<boost::shared_ptr<socket> > readable_clients;
std::vector<boost::shared_ptr<socket> > writable_clients; std::vector<boost::shared_ptr<socket> > writable_clients;
std::vector<boost::shared_ptr<socket> > error_clients; std::vector<boost::shared_ptr<socket> > error_clients;
boost::posix_time::ptime timer = boost::posix_time::second_clock::local_time(); boost::posix_time::ptime timer = boost::posix_time::second_clock::local_time();
#ifndef NDEBUG
int loops_per_second = 0;
#endif
for(;;) for(;;)
{ {
#ifndef NDEBUG #ifndef NDEBUG
for (connection_map::iterator i = m_connections.begin(); assert_invariant();
i != m_connections.end(); loops_per_second++;
++i)
{
assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
}
#endif #endif
// if nothing happens within 500000 microseconds (0.5 seconds) // if nothing happens within 500000 microseconds (0.5 seconds)
// do the loop anyway to check if anything else has changed // do the loop anyway to check if anything else has changed
// (*m_logger) << "sleeping\n"; // << "sleeping\n";
m_selector.wait(500000, readable_clients, writable_clients, error_clients); m_selector.wait(500000, readable_clients, writable_clients, error_clients);
boost::mutex::scoped_lock l(m_mutex); boost::mutex::scoped_lock l(m_mutex);
@@ -263,6 +249,9 @@ namespace libtorrent
break; break;
} }
#ifndef NDEBUG
assert_invariant();
#endif
// ************************ // ************************
// RECEIVE SOCKETS // RECEIVE SOCKETS
// ************************ // ************************
@@ -286,18 +275,18 @@ namespace libtorrent
// TODO: the send buffer size should be controllable from the outside // TODO: the send buffer size should be controllable from the outside
// s->set_send_bufsize(2048); // s->set_send_bufsize(2048);
// TODO: add some possibility to filter IP:s // TODO: filter ip:s
boost::shared_ptr<peer_connection> c( boost::shared_ptr<peer_connection> c(
new peer_connection(this, m_selector, s)); new peer_connection(this, m_selector, s));
if (m_upload_rate != -1) c->set_send_quota(0); if (m_upload_rate != -1) c->set_send_quota(0);
m_connections.insert(std::make_pair(s, c)); m_connections.insert(std::make_pair(s, c));
m_selector.monitor_readability(s); m_selector.monitor_readability(s);
m_selector.monitor_errors(s); m_selector.monitor_errors(s);
} }
continue; continue;
} }
connection_map::iterator p = m_connections.find(*i); connection_map::iterator p = m_connections.find(*i);
if(p == m_connections.end()) if(p == m_connections.end())
{ {
@@ -320,6 +309,10 @@ namespace libtorrent
} }
} }
#ifndef NDEBUG
assert_invariant();
#endif
// ************************ // ************************
// SEND SOCKETS // SEND SOCKETS
// ************************ // ************************
@@ -373,12 +366,7 @@ namespace libtorrent
} }
#ifndef NDEBUG #ifndef NDEBUG
for (connection_map::iterator i = m_connections.begin(); assert_invariant();
i != m_connections.end();
++i)
{
assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
}
#endif #endif
boost::posix_time::time_duration d = boost::posix_time::second_clock::local_time() - timer; boost::posix_time::time_duration d = boost::posix_time::second_clock::local_time() - timer;
@@ -389,6 +377,11 @@ namespace libtorrent
// THE SECTION BELOW IS EXECUTED ONCE EVERY SECOND // THE SECTION BELOW IS EXECUTED ONCE EVERY SECOND
// ************************ // ************************
#ifndef NDEBUG
// std::cout << "\n\nloops: " << loops_per_second << "\n";
loops_per_second = 0;
#endif
// distribute the maximum upload rate among the peers // distribute the maximum upload rate among the peers
// TODO: implement an intelligent algorithm that // TODO: implement an intelligent algorithm that
// will shift bandwidth from the peers that can't // will shift bandwidth from the peers that can't
@@ -458,6 +451,8 @@ namespace libtorrent
i->second->generate_tracker_request(m_listen_port), i->second->generate_tracker_request(m_listen_port),
boost::get_pointer(i->second)); boost::get_pointer(i->second));
} }
i->second->second_tick();
++i; ++i;
} }
m_tracker_manager.tick(); m_tracker_manager.tick();
@@ -527,6 +522,23 @@ namespace libtorrent
} }
#endif #endif
#ifndef NDEBUG
void session_impl::assert_invariant()
{
for (connection_map::iterator i = m_connections.begin();
i != m_connections.end();
++i)
{
assert(i->second->has_data() == m_selector.is_writability_monitored(i->first));
if (i->second->associated_torrent())
{
assert(i->second->associated_torrent()
->get_policy().has_connection(boost::get_pointer(i->second)));
}
}
}
#endif
} }
session::session(int listen_port, const std::string& fingerprint) session::session(int listen_port, const std::string& fingerprint)

View File

@@ -156,7 +156,7 @@ void libtorrent::piece_file::reopen()
m_file.close(); m_file.close();
m_file.clear(); m_file.clear();
m_file.open(path.native_file_string().c_str(), m_file_mode); m_file.open(path, m_file_mode);
if (m_mode == in) m_file.seekg(m_file_offset, std::ios_base::beg); if (m_mode == in) m_file.seekg(m_file_offset, std::ios_base::beg);
else m_file.seekp(m_file_offset, std::ios_base::beg); else m_file.seekp(m_file_offset, std::ios_base::beg);
@@ -242,7 +242,7 @@ void libtorrent::piece_file::open(storage* s, int index, open_mode o, int seek_o
m_file.clear(); m_file.clear();
m_file_mode = m; m_file_mode = m;
m_file.open(path.native_file_string().c_str(), m_file_mode); m_file.open(path, m_file_mode);
if (m_mode == in) m_file.seekg(m_file_offset, std::ios_base::beg); if (m_mode == in) m_file.seekg(m_file_offset, std::ios_base::beg);
else m_file.seekp(m_file_offset, std::ios_base::beg); else m_file.seekp(m_file_offset, std::ios_base::beg);
@@ -294,7 +294,7 @@ void libtorrent::piece_file::open(storage* s, int index, open_mode o, int seek_o
m_file.clear(); m_file.clear();
m_file_mode = m; m_file_mode = m;
m_file.open(p.native_file_string().c_str(), m_file_mode); m_file.open(p, m_file_mode);
// std::cout << "opening file: '" << p.native_file_string() << "'\n"; // std::cout << "opening file: '" << p.native_file_string() << "'\n";
if (m_file.fail()) if (m_file.fail())
{ {
@@ -373,6 +373,7 @@ int libtorrent::piece_file::read(char* buf, int size, bool lock_)
left_to_read -= read_bytes; left_to_read -= read_bytes;
buf_pos += read_bytes; buf_pos += read_bytes;
assert(buf_pos >= 0);
m_file_offset += read_bytes; m_file_offset += read_bytes;
m_piece_offset += read_bytes; m_piece_offset += read_bytes;
@@ -385,7 +386,7 @@ int libtorrent::piece_file::read(char* buf, int size, bool lock_)
m_file_offset = 0; m_file_offset = 0;
m_file.close(); m_file.close();
m_file.clear(); m_file.clear();
m_file.open(path.native_file_string().c_str(), m_file_mode); m_file.open(path, m_file_mode);
} }
} }
@@ -413,11 +414,14 @@ int libtorrent::piece_file::read(char* buf, int size, bool lock_)
int available = std::min(static_cast<entry::integer_type>(m_file_iter->size - m_file_offset), int available = std::min(static_cast<entry::integer_type>(m_file_iter->size - m_file_offset),
static_cast<entry::integer_type>(left_to_read)); static_cast<entry::integer_type>(left_to_read));
assert(buf_pos >= 0);
m_file.read(buf + buf_pos, available); m_file.read(buf + buf_pos, available);
int read = m_file.gcount(); int read = m_file.gcount();
assert(read > 0);
left_to_read -= read; left_to_read -= read;
read_total += read; read_total += read;
buf_pos += read; buf_pos += read;
assert(buf_pos >= 0);
m_file_offset += read; m_file_offset += read;
m_piece_offset += read; m_piece_offset += read;
@@ -432,7 +436,7 @@ int libtorrent::piece_file::read(char* buf, int size, bool lock_)
m_file_offset = 0; m_file_offset = 0;
m_file.close(); m_file.close();
m_file.clear(); m_file.clear();
m_file.open(path.native_file_string().c_str(), m_file_mode); m_file.open(path, m_file_mode);
// std::cout << "opening file: '" << path.native_file_string() << "'\n"; // std::cout << "opening file: '" << path.native_file_string() << "'\n";
if (m_file.fail()) if (m_file.fail())
{ {
@@ -503,10 +507,13 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
if (m_file_offset + write_bytes > m_file_iter->size) if (m_file_offset + write_bytes > m_file_iter->size)
write_bytes = m_file_iter->size - m_file_offset; write_bytes = m_file_iter->size - m_file_offset;
assert(buf_pos >= 0);
assert(write_bytes > 0);
m_file.write(buf + buf_pos, write_bytes); m_file.write(buf + buf_pos, write_bytes);
left_to_write -= write_bytes; left_to_write -= write_bytes;
buf_pos += write_bytes; buf_pos += write_bytes;
assert(buf_pos >= 0);
m_file_offset += write_bytes; m_file_offset += write_bytes;
m_piece_offset += write_bytes; m_piece_offset += write_bytes;
@@ -522,12 +529,12 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
m_file_offset = 0; m_file_offset = 0;
m_file.close(); m_file.close();
m_file.clear(); m_file.clear();
m_file.open(path.native_file_string().c_str(), m_file_mode); m_file.open(path, m_file_mode);
} }
} }
#if 0 // old implementation #if 0 // old implementation
/*
assert(m_mode == out); assert(m_mode == out);
int left_to_write = size; int left_to_write = size;
@@ -558,7 +565,7 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
m_file_offset = 0; m_file_offset = 0;
m_file.close(); m_file.close();
m_file.open(path.native_file_string().c_str(), m_file_mode); m_file.open(path, m_file_mode);
// std::cout << "opening file: '" << path.native_file_string() << "'\n"; // std::cout << "opening file: '" << path.native_file_string() << "'\n";
if (m_file.fail()) if (m_file.fail())
{ {
@@ -567,7 +574,7 @@ void libtorrent::piece_file::write(const char* buf, int size, bool lock_)
} }
} }
} while (left_to_write > 0); } while (left_to_write > 0);
*/
#endif #endif
} }
@@ -608,7 +615,7 @@ void libtorrent::piece_file::seek_forward(int step, bool lock_)
path /= m_file_iter->filename; path /= m_file_iter->filename;
m_file.close(); m_file.close();
m_file.open(path.native_file_string().c_str(), std::ios_base::in | std::ios_base::binary); m_file.open(path, std::ios_base::in | std::ios_base::binary);
} }
m_file_offset += left_to_seek; m_file_offset += left_to_seek;
@@ -771,9 +778,9 @@ void libtorrent::storage::allocate_pieces(int num)
fs::ofstream out; fs::ofstream out;
if (fs::exists(path)) if (fs::exists(path))
out.open(path.native_file_string().c_str(), std::ios_base::binary | std::ios_base::in); out.open(path, std::ios_base::binary | std::ios_base::in);
else else
out.open(path.native_file_string().c_str(), std::ios_base::binary); out.open(path, std::ios_base::binary);
// std::ofstream out((m_save_path / file_iter->path / file_iter->filename).native_file_string().c_str() // std::ofstream out((m_save_path / file_iter->path / file_iter->filename).native_file_string().c_str()
// , std::ios_base::binary | std::ios_base::in); // , std::ios_base::binary | std::ios_base::in);
@@ -831,7 +838,7 @@ entry::integer_type libtorrent::storage::piece_storage(int piece)
if (m_free_pieces.empty()) if (m_free_pieces.empty())
{ {
allocate_pieces(5000); allocate_pieces(5);
assert(!m_free_pieces.empty()); assert(!m_free_pieces.empty());
} }
@@ -1182,7 +1189,7 @@ void libtorrent::storage::initialize_pieces(torrent* t,
{ {
in.close(); in.close();
in.clear(); in.clear();
in.open(path.native_file_string().c_str(), std::ios_base::binary); in.open(path, std::ios_base::binary);
changed_file = false; changed_file = false;

View File

@@ -128,6 +128,13 @@ namespace
return true; return true;
} }
bool operator()(const peer_connection* p) const
{
if (p->get_peer_id() != id) return false;
if (tor != p->associated_torrent()) return false;
return true;
}
const peer_id& id; const peer_id& id;
const torrent* tor; const torrent* tor;
}; };
@@ -151,6 +158,7 @@ namespace libtorrent
(torrent_file.total_size()+m_block_size-1)/m_block_size) (torrent_file.total_size()+m_block_size-1)/m_block_size)
, m_last_working_tracker(0) , m_last_working_tracker(0)
, m_currently_trying_tracker(0) , m_currently_trying_tracker(0)
, m_time_scaler(0)
{ {
} }
@@ -219,16 +227,17 @@ namespace libtorrent
} }
int torrent::num_connections(const peer_id& id) const bool torrent::has_peer(const peer_id& id) const
{ {
int num = 0; assert(std::count_if(m_connections.begin()
for (detail::session_impl::connection_map::const_iterator i = m_ses->m_connections.begin(); , m_connections.end()
i != m_ses->m_connections.end(); , find_peer(id, this)) <= 1);
++i)
{ return std::find_if(
if (i->second->get_peer_id() == id && i->second->associated_torrent() == this) ++num; m_connections.begin()
} , m_connections.end()
return num; , find_peer(id, this))
!= m_connections.end();
} }
void torrent::announce_piece(int index) void torrent::announce_piece(int index)
@@ -236,10 +245,6 @@ namespace libtorrent
m_picker.we_have(index); m_picker.we_have(index);
for (std::vector<peer_connection*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i) for (std::vector<peer_connection*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i)
(*i)->announce_piece(index); (*i)->announce_piece(index);
#ifndef NDEBUG
m_picker.integrity_check(this);
#endif
} }
std::string torrent::generate_tracker_request(int port) std::string torrent::generate_tracker_request(int port)
@@ -335,7 +340,7 @@ namespace libtorrent
#endif #endif
} }
void torrent::connect_to_peer(const address& a, const peer_id& id) boost::weak_ptr<peer_connection> torrent::connect_to_peer(const address& a, const peer_id& id)
{ {
boost::shared_ptr<socket> s(new socket(socket::tcp, false)); boost::shared_ptr<socket> s(new socket(socket::tcp, false));
// TODO: the send buffer size should be controllable from the outside // TODO: the send buffer size should be controllable from the outside
@@ -350,10 +355,30 @@ namespace libtorrent
if (m_ses->m_upload_rate != -1) c->set_send_quota(0); if (m_ses->m_upload_rate != -1) c->set_send_quota(0);
detail::session_impl::connection_map::iterator p = detail::session_impl::connection_map::iterator p =
m_ses->m_connections.insert(std::make_pair(s, c)).first; m_ses->m_connections.insert(std::make_pair(s, c)).first;
attach_peer(boost::get_pointer(p->second));
// add the newly connected peer to this torrent's peer list
assert(std::find(m_connections.begin()
, m_connections.end()
, boost::get_pointer(p->second))
== m_connections.end());
m_connections.push_back(boost::get_pointer(p->second));
m_ses->m_selector.monitor_readability(s); m_ses->m_selector.monitor_readability(s);
m_ses->m_selector.monitor_errors(s); m_ses->m_selector.monitor_errors(s);
// std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n"; // std::cout << "connecting to: " << a.as_string() << ":" << a.port() << "\n";
return c;
}
void torrent::attach_peer(peer_connection* p)
{
assert(std::find(m_connections.begin(), m_connections.end(), p) == m_connections.end());
m_connections.push_back(p);
detail::session_impl::connection_map::iterator i
= m_ses->m_connections.find(p->get_socket());
assert(i != m_ses->m_connections.end());
m_policy->new_connection(i->second);
} }
void torrent::close_all_connections() void torrent::close_all_connections()
@@ -412,6 +437,16 @@ namespace libtorrent
#endif #endif
} }
void torrent::second_tick()
{
m_time_scaler++;
if (m_time_scaler >= 10)
{
m_time_scaler = 0;
m_policy->pulse();
}
}
torrent_status torrent::status() const torrent_status torrent::status() const
{ {
torrent_status st; torrent_status st;

View File

@@ -165,6 +165,8 @@ namespace libtorrent
p.id = peer->get_peer_id(); p.id = peer->get_peer_id();
p.ip = peer->get_socket()->sender(); p.ip = peer->get_socket()->sender();
// TODO: add the prev_amount_downloaded and prev_amount_uploaded
// from the peer list in the policy
p.total_download = statistics.total_download(); p.total_download = statistics.total_download();
p.total_upload = statistics.total_upload(); p.total_upload = statistics.total_upload();
@@ -172,7 +174,7 @@ namespace libtorrent
p.flags = 0; p.flags = 0;
if (peer->is_interesting()) p.flags |= peer_info::interesting; if (peer->is_interesting()) p.flags |= peer_info::interesting;
if (peer->has_choked()) p.flags |= peer_info::choked; if (peer->is_choked()) p.flags |= peer_info::choked;
if (peer->is_peer_interested()) p.flags |= peer_info::remote_interested; if (peer->is_peer_interested()) p.flags |= peer_info::remote_interested;
if (peer->has_peer_choked()) p.flags |= peer_info::remote_choked; if (peer->has_peer_choked()) p.flags |= peer_info::remote_choked;

View File

@@ -204,6 +204,35 @@ namespace libtorrent
std::copy(hash_string.begin() + i*20, hash_string.begin() + (i+1)*20, m_piece_hash[i].begin()); std::copy(hash_string.begin() + i*20, hash_string.begin() + (i+1)*20, m_piece_hash[i].begin());
} }
void torrent_info::convert_file_names()
{
for (std::vector<file>::iterator i = m_files.begin(); i != m_files.end(); ++i)
{
// replace all dots in directory names with underscores
std::string& path = i->path;
std::string& filename = i->filename;
for (std::string::iterator c = path.begin(); c != path.end(); ++c)
{
if (*c == '.') *c = '_';
if (*c == ' ') *c = '_';
if (*c == '[') *c = '_';
if (*c == ']') *c = '_';
}
// replace all dots, but the last one,
// in file names with underscores
std::string::reverse_iterator last_dot
= std::find(filename.rbegin(), filename.rend(), '.');
for (std::string::reverse_iterator c = filename.rbegin(); c != filename.rend(); ++c)
{
if (c != last_dot && *c == '.') *c = '_';
if (*c == ' ') *c = '_';
if (*c == '[') *c = '_';
if (*c == ']') *c = '_';
}
}
}
int torrent_info::prioritize_tracker(int index) int torrent_info::prioritize_tracker(int index)
{ {
if (index > m_urls.size()) return m_urls.size()-1; if (index > m_urls.size()) return m_urls.size()-1;