there are still some serious issues with storage when having large torrents (about 700 meg and up at least)
This commit is contained in:
@@ -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)
|
||||||
{
|
{
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
131
src/policy.cpp
131
src/policy.cpp
@@ -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
|
||||||
}
|
}
|
||||||
|
@@ -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)
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
Reference in New Issue
Block a user