there are still some serious issues with storage when having large torrents (about 700 meg and up at least)
This commit is contained in:
parent
0019e23b4f
commit
f21d6a0f7f
|
@ -182,8 +182,9 @@ int main(int argc, char* argv[])
|
|||
in.unsetf(std::ios_base::skipws);
|
||||
entry e = bdecode(std::istream_iterator<char>(in), std::istream_iterator<char>());
|
||||
torrent_info t(e);
|
||||
// t.convert_file_names();
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -137,7 +137,7 @@ namespace libtorrent
|
|||
void cancel_block(piece_block block);
|
||||
|
||||
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 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
|
||||
// and it hasn't received enough information to determine
|
||||
// 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; }
|
||||
|
||||
|
@ -239,7 +239,20 @@ namespace libtorrent
|
|||
|
||||
selector& m_selector;
|
||||
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;
|
||||
|
||||
// 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;
|
||||
// is true if it was we that connected to the peer
|
||||
// and false if we got an incomming connection
|
||||
|
|
|
@ -36,6 +36,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/weak_ptr.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
#include "libtorrent/peer.hpp"
|
||||
#include "libtorrent/piece_picker.hpp"
|
||||
|
||||
|
@ -53,9 +56,13 @@ namespace libtorrent
|
|||
public:
|
||||
|
||||
policy(torrent* t);
|
||||
// this is called each time we get an incoming connection
|
||||
// return true to accept the connection
|
||||
bool accept_connection(const address& remote);
|
||||
|
||||
// this is called every 10 seconds to allow
|
||||
// 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
|
||||
// the tracker
|
||||
|
@ -83,8 +90,77 @@ namespace libtorrent
|
|||
// the peer is not interested in our pieces
|
||||
void not_interested(peer_connection& c);
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool has_connection(const peer_connection* p);
|
||||
#endif
|
||||
|
||||
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;
|
||||
torrent* m_torrent;
|
||||
|
||||
|
|
|
@ -171,6 +171,7 @@ namespace libtorrent
|
|||
alert_manager m_alerts;
|
||||
|
||||
#ifndef NDEBUG
|
||||
void assert_invariant();
|
||||
boost::shared_ptr<logger> create_log(std::string name);
|
||||
boost::shared_ptr<logger> m_logger;
|
||||
#endif
|
||||
|
|
|
@ -33,6 +33,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_SOCKET_WIN_HPP_INCLUDED
|
||||
#define TORRENT_SOCKET_WIN_HPP_INCLUDED
|
||||
|
||||
// TODO: remove the dependency of
|
||||
// platform specific headers here.
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <winsock2.h>
|
||||
#else
|
||||
|
@ -135,57 +138,32 @@ namespace libtorrent
|
|||
|
||||
enum error_code
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
netdown = WSAENETDOWN,
|
||||
fault = WSAEFAULT,
|
||||
access = WSAEACCES,
|
||||
address_in_use = WSAEADDRINUSE,
|
||||
address_not_available = WSAEADDRNOTAVAIL,
|
||||
in_progress = WSAEINPROGRESS,
|
||||
interrupted = WSAEINTR,
|
||||
invalid = WSAEINVAL,
|
||||
net_reset = WSAENETRESET,
|
||||
not_connected = WSAENOTCONN,
|
||||
no_buffers = WSAENOBUFS,
|
||||
operation_not_supported = WSAEOPNOTSUPP,
|
||||
not_socket = WSAENOTSOCK,
|
||||
shutdown = WSAESHUTDOWN,
|
||||
would_block = WSAEWOULDBLOCK,
|
||||
connection_reset = WSAECONNRESET,
|
||||
timed_out = WSAETIMEDOUT,
|
||||
connection_aborted = WSAECONNABORTED,
|
||||
message_size = WSAEMSGSIZE,
|
||||
not_ready = WSAEALREADY,
|
||||
no_support = WSAEAFNOSUPPORT,
|
||||
connection_refused = WSAECONNREFUSED,
|
||||
is_connected = WSAEISCONN,
|
||||
net_unreachable = WSAENETUNREACH
|
||||
#else
|
||||
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
|
||||
netdown,
|
||||
fault,
|
||||
access,
|
||||
address_in_use,
|
||||
address_not_available,
|
||||
in_progress,
|
||||
interrupted,
|
||||
invalid,
|
||||
net_reset,
|
||||
not_connected,
|
||||
no_buffers,
|
||||
operation_not_supported,
|
||||
not_socket,
|
||||
shutdown,
|
||||
would_block,
|
||||
connection_reset,
|
||||
timed_out,
|
||||
connection_aborted,
|
||||
message_size,
|
||||
not_ready,
|
||||
no_support,
|
||||
connection_refused,
|
||||
is_connected,
|
||||
net_unreachable,
|
||||
not_initialized,
|
||||
unknown_error
|
||||
};
|
||||
|
||||
error_code last_error() const;
|
||||
|
|
|
@ -58,6 +58,10 @@ namespace libtorrent
|
|||
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)
|
||||
{ m_downloaded += num_bytes; m_total_download += num_bytes; }
|
||||
void sent_bytes(int num_bytes)
|
||||
|
|
|
@ -44,6 +44,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
|
||||
#include "libtorrent/entry.hpp"
|
||||
|
@ -115,7 +116,7 @@ namespace libtorrent
|
|||
void reopen();
|
||||
|
||||
// the file itself
|
||||
std::fstream m_file;
|
||||
boost::filesystem::fstream m_file;
|
||||
|
||||
// the mode with which this file was opened
|
||||
open_mode m_mode;
|
||||
|
|
|
@ -87,6 +87,9 @@ namespace libtorrent
|
|||
void abort() { m_abort = true; m_event = event_stopped; }
|
||||
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
|
||||
// tracker request
|
||||
bool should_request() const throw()
|
||||
|
@ -96,9 +99,6 @@ namespace libtorrent
|
|||
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 allocate_files(detail::piece_checker_data* data,
|
||||
|
@ -114,9 +114,12 @@ namespace libtorrent
|
|||
|
||||
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; }
|
||||
storage* filesystem() { return &m_storage; }
|
||||
|
@ -128,11 +131,7 @@ namespace libtorrent
|
|||
// used by peer_connection to attach itself to a torrent
|
||||
// since incoming connections don't know what torrent
|
||||
// they're a part of until they have received an info_hash.
|
||||
void attach_peer(peer_connection* p)
|
||||
{
|
||||
assert(std::find(m_connections.begin(), m_connections.end(), p) == m_connections.end());
|
||||
m_connections.push_back(p);
|
||||
}
|
||||
void attach_peer(peer_connection* p);
|
||||
|
||||
// this will remove the peer and make sure all
|
||||
// the pieces it had have their reference counter
|
||||
|
@ -142,9 +141,9 @@ namespace libtorrent
|
|||
// the number of peers that belong to this torrent
|
||||
int num_peers() const { return m_connections.size(); }
|
||||
|
||||
// returns the number of connections this torrent has to
|
||||
// the given peer_id (should be kept at max 1)
|
||||
int num_connections(const peer_id& id) const;
|
||||
// returns true if this torrent has a connection
|
||||
// to a peer with the given peer_id
|
||||
bool has_peer(const peer_id& id) const;
|
||||
|
||||
typedef std::vector<peer_connection*>::iterator peer_iterator;
|
||||
typedef std::vector<peer_connection*>::const_iterator peer_const_iterator;
|
||||
|
@ -270,7 +269,6 @@ namespace libtorrent
|
|||
// from the tracker
|
||||
int m_duration;
|
||||
|
||||
std::string m_failed;
|
||||
std::vector<peer_connection*> m_connections;
|
||||
|
||||
// -----------------------------
|
||||
|
@ -285,6 +283,10 @@ namespace libtorrent
|
|||
int m_last_working_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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -122,6 +122,8 @@ namespace libtorrent
|
|||
const std::string& name() const { return m_name; }
|
||||
void print(std::ostream& os) const;
|
||||
|
||||
void convert_file_names();
|
||||
|
||||
entry::integer_type piece_size(unsigned int index) const
|
||||
{
|
||||
if (index == num_pieces()-1)
|
||||
|
|
|
@ -59,9 +59,9 @@ namespace libtorrent {
|
|||
{
|
||||
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();
|
||||
return std::auto_ptr<alert>(result);
|
||||
}
|
||||
|
|
|
@ -86,6 +86,7 @@ libtorrent::peer_connection::peer_connection(
|
|||
, m_selector(sel)
|
||||
, m_socket(s)
|
||||
, m_torrent(t)
|
||||
, m_attached_to_torrent(true)
|
||||
, m_ses(ses)
|
||||
, m_active(true)
|
||||
, m_added_to_selector(false)
|
||||
|
@ -130,6 +131,7 @@ libtorrent::peer_connection::peer_connection(
|
|||
, m_selector(sel)
|
||||
, m_socket(s)
|
||||
, m_torrent(0)
|
||||
, m_attached_to_torrent(0)
|
||||
, m_ses(ses)
|
||||
, m_active(false)
|
||||
, m_added_to_selector(false)
|
||||
|
@ -159,7 +161,11 @@ libtorrent::peer_connection::peer_connection(
|
|||
libtorrent::peer_connection::~peer_connection()
|
||||
{
|
||||
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)
|
||||
|
@ -715,13 +721,17 @@ void libtorrent::peer_connection::send_have(int index)
|
|||
void libtorrent::peer_connection::receive_data()
|
||||
{
|
||||
assert(!m_socket->is_blocking());
|
||||
assert(m_packet_size > 0);
|
||||
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);
|
||||
|
||||
// connection closed
|
||||
if (received == 0) throw network_error(0);
|
||||
if (received == 0)
|
||||
{
|
||||
throw network_error(0);
|
||||
}
|
||||
|
||||
// an error
|
||||
if (received < 0)
|
||||
|
@ -754,6 +764,14 @@ void libtorrent::peer_connection::receive_data()
|
|||
m_state = read_protocol_string;
|
||||
m_recv_buffer.resize(m_packet_size);
|
||||
m_recv_pos = 0;
|
||||
|
||||
if (m_packet_size == 0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << "incorrect protocol length\n";
|
||||
#endif
|
||||
throw network_error(0);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
@ -765,7 +783,12 @@ void libtorrent::peer_connection::receive_data()
|
|||
const char protocol_string[] = "BitTorrent protocol";
|
||||
const int protocol_len = sizeof(protocol_string) - 1;
|
||||
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);
|
||||
}
|
||||
|
||||
m_state = read_info_hash;
|
||||
m_packet_size = 28;
|
||||
|
@ -800,7 +823,6 @@ void libtorrent::peer_connection::receive_data()
|
|||
#endif
|
||||
throw network_error(0);
|
||||
}
|
||||
m_torrent->attach_peer(this);
|
||||
|
||||
// assume the other end has no 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
|
||||
// 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());
|
||||
if (m_torrent->num_connections(m_peer_id) > 1)
|
||||
|
||||
if (m_torrent->has_peer(m_peer_id))
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
(*m_logger) << m_socket->sender().as_string() << " duplicate connection, closing\n";
|
||||
#endif
|
||||
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;
|
||||
|
@ -900,6 +927,7 @@ void libtorrent::peer_connection::receive_data()
|
|||
m_recv_buffer.resize(m_packet_size);
|
||||
}
|
||||
m_recv_pos = 0;
|
||||
assert(m_packet_size > 0);
|
||||
break;
|
||||
|
||||
case read_packet:
|
||||
|
@ -917,11 +945,13 @@ void libtorrent::peer_connection::receive_data()
|
|||
m_packet_size = 4;
|
||||
m_recv_buffer.resize(4);
|
||||
m_recv_pos = 0;
|
||||
assert(m_packet_size > 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert(m_packet_size > 0);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <vector>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#include "libtorrent/piece_picker.hpp"
|
||||
|
||||
|
@ -40,8 +41,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/peer_connection.hpp"
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1300
|
||||
#define for if (false) {} else for
|
||||
namespace std
|
||||
{
|
||||
template<class T>
|
||||
inline T min(T a, T b) { return a<b?a:b; }
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
|
@ -85,7 +91,7 @@ namespace libtorrent
|
|||
m_piece_info[peer_count].push_back(index);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
// TODO: random_shuffle
|
||||
}
|
||||
|
@ -299,7 +305,7 @@ namespace libtorrent
|
|||
move(true, m_piece_map[index].peer_count, m_piece_map[index].index);
|
||||
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -356,7 +362,7 @@ namespace libtorrent
|
|||
assert(info_index != 0xffffff);
|
||||
remove(m_piece_map[index].downloading, peer_count, info_index);
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -367,7 +373,7 @@ namespace libtorrent
|
|||
assert(pieces.size() == m_piece_map.size());
|
||||
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
|
||||
// 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)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
assert(block.piece_index < m_piece_map.size());
|
||||
assert(block.block_index < blocks_in_piece(block.piece_index));
|
||||
|
@ -529,14 +535,14 @@ namespace libtorrent
|
|||
i->requested_blocks[block.block_index] = 1;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
void piece_picker::mark_as_finished(piece_block block, const peer_id& peer)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
assert(block.piece_index < m_piece_map.size());
|
||||
assert(block.block_index < blocks_in_piece(block.piece_index));
|
||||
|
@ -564,7 +570,7 @@ namespace libtorrent
|
|||
i->finished_blocks[block.block_index] = 1;
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
|
@ -610,7 +616,7 @@ namespace libtorrent
|
|||
void piece_picker::abort_download(piece_block block)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
integrity_check();
|
||||
// integrity_check();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
131
src/policy.cpp
131
src/policy.cpp
|
@ -32,6 +32,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
|
||||
#include "libtorrent/policy.hpp"
|
||||
#include "libtorrent/torrent.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
|
@ -137,7 +139,7 @@ namespace
|
|||
peer_connection* peer = 0;
|
||||
float down_speed = -1.f;
|
||||
// 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
|
||||
for (torrent::peer_iterator i = t.begin();
|
||||
i != t.end();
|
||||
|
@ -171,6 +173,7 @@ namespace
|
|||
|
||||
num_requests--;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace libtorrent
|
||||
|
@ -197,14 +200,6 @@ namespace libtorrent
|
|||
TODO: to implement choking/unchoking we need a list with all
|
||||
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)
|
||||
{}
|
||||
|
||||
|
||||
// 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)
|
||||
void policy::pulse()
|
||||
{
|
||||
m_num_peers++;
|
||||
return true;
|
||||
using namespace boost::posix_time;
|
||||
|
||||
// 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)
|
||||
{
|
||||
try
|
||||
{
|
||||
m_torrent->connect_to_peer(remote, id);
|
||||
m_num_peers++;
|
||||
std::vector<peer>::iterator i = std::find(m_peers.begin(), m_peers.end(), id);
|
||||
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&) {}
|
||||
}
|
||||
|
@ -237,9 +303,9 @@ namespace libtorrent
|
|||
// anything for a while
|
||||
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)
|
||||
{
|
||||
// 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)
|
||||
{
|
||||
if (c.has_peer_choked()) return;
|
||||
request_a_block(*m_torrent, c);
|
||||
// if the peer hasn't choked us, ask for another piece
|
||||
if (!c.has_peer_choked()) request_a_block(*m_torrent, c);
|
||||
}
|
||||
|
||||
// this is called when we are unchoked by a peer
|
||||
|
@ -257,21 +323,33 @@ namespace libtorrent
|
|||
// data from now on
|
||||
void policy::unchoked(peer_connection& c)
|
||||
{
|
||||
c.unchoke();
|
||||
if (c.is_interesting()) request_a_block(*m_torrent, c);
|
||||
if (c.is_interesting())
|
||||
{
|
||||
request_a_block(*m_torrent, 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)
|
||||
{
|
||||
}
|
||||
|
||||
// this is called whenever a peer connection is closed
|
||||
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)
|
||||
|
@ -280,4 +358,11 @@ namespace libtorrent
|
|||
if (c.has_peer_choked()) return;
|
||||
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
|
||||
}
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace libtorrent
|
|||
std::make_pair(t->info_hash, t->torrent_ptr)).first;
|
||||
}
|
||||
}
|
||||
catch(const boost::filesystem::filesystem_error& e)
|
||||
catch(const std::exception& e)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "error while checking files: " << e.what() << "\n";
|
||||
|
@ -206,40 +206,26 @@ namespace libtorrent
|
|||
m_selector.monitor_readability(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> > writable_clients;
|
||||
std::vector<boost::shared_ptr<socket> > error_clients;
|
||||
boost::posix_time::ptime timer = boost::posix_time::second_clock::local_time();
|
||||
|
||||
#ifndef NDEBUG
|
||||
int loops_per_second = 0;
|
||||
#endif
|
||||
for(;;)
|
||||
{
|
||||
|
||||
#ifndef NDEBUG
|
||||
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));
|
||||
}
|
||||
assert_invariant();
|
||||
loops_per_second++;
|
||||
#endif
|
||||
|
||||
|
||||
// if nothing happens within 500000 microseconds (0.5 seconds)
|
||||
// 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);
|
||||
|
||||
boost::mutex::scoped_lock l(m_mutex);
|
||||
|
@ -263,6 +249,9 @@ namespace libtorrent
|
|||
break;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert_invariant();
|
||||
#endif
|
||||
// ************************
|
||||
// RECEIVE SOCKETS
|
||||
// ************************
|
||||
|
@ -286,18 +275,18 @@ namespace libtorrent
|
|||
// TODO: the send buffer size should be controllable from the outside
|
||||
// s->set_send_bufsize(2048);
|
||||
|
||||
// TODO: add some possibility to filter IP:s
|
||||
// TODO: filter ip:s
|
||||
|
||||
boost::shared_ptr<peer_connection> c(
|
||||
new peer_connection(this, m_selector, s));
|
||||
|
||||
if (m_upload_rate != -1) c->set_send_quota(0);
|
||||
m_connections.insert(std::make_pair(s, c));
|
||||
m_selector.monitor_readability(s);
|
||||
m_selector.monitor_errors(s);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
connection_map::iterator p = m_connections.find(*i);
|
||||
if(p == m_connections.end())
|
||||
{
|
||||
|
@ -320,6 +309,10 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
assert_invariant();
|
||||
#endif
|
||||
|
||||
// ************************
|
||||
// SEND SOCKETS
|
||||
// ************************
|
||||
|
@ -373,12 +366,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
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));
|
||||
}
|
||||
assert_invariant();
|
||||
#endif
|
||||
|
||||
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
|
||||
// ************************
|
||||
|
||||
#ifndef NDEBUG
|
||||
// std::cout << "\n\nloops: " << loops_per_second << "\n";
|
||||
loops_per_second = 0;
|
||||
#endif
|
||||
|
||||
// distribute the maximum upload rate among the peers
|
||||
// TODO: implement an intelligent algorithm that
|
||||
// will shift bandwidth from the peers that can't
|
||||
|
@ -458,6 +451,8 @@ namespace libtorrent
|
|||
i->second->generate_tracker_request(m_listen_port),
|
||||
boost::get_pointer(i->second));
|
||||
}
|
||||
|
||||
i->second->second_tick();
|
||||
++i;
|
||||
}
|
||||
m_tracker_manager.tick();
|
||||
|
@ -527,6 +522,23 @@ namespace libtorrent
|
|||
}
|
||||
#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)
|
||||
|
|
|
@ -156,7 +156,7 @@ void libtorrent::piece_file::reopen()
|
|||
m_file.close();
|
||||
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);
|
||||
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_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);
|
||||
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_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";
|
||||
if (m_file.fail())
|
||||
{
|
||||
|
@ -373,6 +373,7 @@ int libtorrent::piece_file::read(char* buf, int size, bool lock_)
|
|||
|
||||
left_to_read -= read_bytes;
|
||||
buf_pos += read_bytes;
|
||||
assert(buf_pos >= 0);
|
||||
m_file_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.close();
|
||||
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),
|
||||
static_cast<entry::integer_type>(left_to_read));
|
||||
|
||||
assert(buf_pos >= 0);
|
||||
m_file.read(buf + buf_pos, available);
|
||||
int read = m_file.gcount();
|
||||
assert(read > 0);
|
||||
left_to_read -= read;
|
||||
read_total += read;
|
||||
buf_pos += read;
|
||||
assert(buf_pos >= 0);
|
||||
m_file_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.close();
|
||||
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";
|
||||
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)
|
||||
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);
|
||||
|
||||
left_to_write -= write_bytes;
|
||||
buf_pos += write_bytes;
|
||||
assert(buf_pos >= 0);
|
||||
m_file_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.close();
|
||||
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
|
||||
|
||||
/*
|
||||
assert(m_mode == out);
|
||||
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.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";
|
||||
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);
|
||||
|
||||
*/
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -608,7 +615,7 @@ void libtorrent::piece_file::seek_forward(int step, bool lock_)
|
|||
path /= m_file_iter->filename;
|
||||
|
||||
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;
|
||||
|
@ -771,9 +778,9 @@ void libtorrent::storage::allocate_pieces(int num)
|
|||
fs::ofstream out;
|
||||
|
||||
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
|
||||
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::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())
|
||||
{
|
||||
allocate_pieces(5000);
|
||||
allocate_pieces(5);
|
||||
assert(!m_free_pieces.empty());
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1189,7 @@ void libtorrent::storage::initialize_pieces(torrent* t,
|
|||
{
|
||||
in.close();
|
||||
in.clear();
|
||||
in.open(path.native_file_string().c_str(), std::ios_base::binary);
|
||||
in.open(path, std::ios_base::binary);
|
||||
|
||||
changed_file = false;
|
||||
|
||||
|
|
|
@ -128,6 +128,13 @@ namespace
|
|||
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 torrent* tor;
|
||||
};
|
||||
|
@ -151,6 +158,7 @@ namespace libtorrent
|
|||
(torrent_file.total_size()+m_block_size-1)/m_block_size)
|
||||
, m_last_working_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;
|
||||
for (detail::session_impl::connection_map::const_iterator i = m_ses->m_connections.begin();
|
||||
i != m_ses->m_connections.end();
|
||||
++i)
|
||||
{
|
||||
if (i->second->get_peer_id() == id && i->second->associated_torrent() == this) ++num;
|
||||
}
|
||||
return num;
|
||||
assert(std::count_if(m_connections.begin()
|
||||
, m_connections.end()
|
||||
, find_peer(id, this)) <= 1);
|
||||
|
||||
return std::find_if(
|
||||
m_connections.begin()
|
||||
, m_connections.end()
|
||||
, find_peer(id, this))
|
||||
!= m_connections.end();
|
||||
}
|
||||
|
||||
void torrent::announce_piece(int index)
|
||||
|
@ -236,10 +245,6 @@ namespace libtorrent
|
|||
m_picker.we_have(index);
|
||||
for (std::vector<peer_connection*>::iterator i = m_connections.begin(); i != m_connections.end(); ++i)
|
||||
(*i)->announce_piece(index);
|
||||
|
||||
#ifndef NDEBUG
|
||||
m_picker.integrity_check(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string torrent::generate_tracker_request(int port)
|
||||
|
@ -335,7 +340,7 @@ namespace libtorrent
|
|||
#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));
|
||||
// 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);
|
||||
detail::session_impl::connection_map::iterator p =
|
||||
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_errors(s);
|
||||
// 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()
|
||||
|
@ -412,6 +437,16 @@ namespace libtorrent
|
|||
#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 st;
|
||||
|
|
|
@ -165,6 +165,8 @@ namespace libtorrent
|
|||
p.id = peer->get_peer_id();
|
||||
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_upload = statistics.total_upload();
|
||||
|
||||
|
@ -172,7 +174,7 @@ namespace libtorrent
|
|||
|
||||
p.flags = 0;
|
||||
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->has_peer_choked()) p.flags |= peer_info::remote_choked;
|
||||
|
||||
|
|
|
@ -204,6 +204,35 @@ namespace libtorrent
|
|||
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)
|
||||
{
|
||||
if (index > m_urls.size()) return m_urls.size()-1;
|
||||
|
|
Loading…
Reference in New Issue