alert.hpp   alert.hpp 
skipping to change at line 47 skipping to change at line 47
#include <queue> #include <queue>
#include <string> #include <string>
#include <typeinfo> #include <typeinfo>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/function.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp> #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/preprocessor/repetition/enum_shifted_binary_params.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/socket.hpp" // for io_service
#ifndef TORRENT_MAX_ALERT_TYPES #ifndef TORRENT_MAX_ALERT_TYPES
#define TORRENT_MAX_ALERT_TYPES 15 #define TORRENT_MAX_ALERT_TYPES 15
#endif #endif
namespace libtorrent { namespace libtorrent {
class TORRENT_EXPORT alert class TORRENT_EXPORT alert
{ {
public: public:
skipping to change at line 86 skipping to change at line 89
error_notification = 0x1, error_notification = 0x1,
peer_notification = 0x2, peer_notification = 0x2,
port_mapping_notification = 0x4, port_mapping_notification = 0x4,
storage_notification = 0x8, storage_notification = 0x8,
tracker_notification = 0x10, tracker_notification = 0x10,
debug_notification = 0x20, debug_notification = 0x20,
status_notification = 0x40, status_notification = 0x40,
progress_notification = 0x80, progress_notification = 0x80,
ip_block_notification = 0x100, ip_block_notification = 0x100,
performance_warning = 0x200, performance_warning = 0x200,
dht_notification = 0x400,
stats_notification = 0x800,
all_categories = 0xffffffff all_categories = 0xffffffff
}; };
alert(); alert();
virtual ~alert(); virtual ~alert();
// a timestamp is automatically created in the constructor // a timestamp is automatically created in the constructor
ptime timestamp() const; ptime timestamp() const;
virtual char const* what() const = 0; virtual char const* what() const = 0;
virtual std::string message() const = 0; virtual std::string message() const = 0;
virtual int category() const = 0; virtual int category() const = 0;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX
severity_t severity() const TORRENT_DEPRECATED { return warn ing; } severity_t severity() const TORRENT_DEPRECATED { return warn ing; }
#endif #endif
virtual std::auto_ptr<alert> clone() const = 0; virtual std::auto_ptr<alert> clone() const = 0;
private: private:
ptime m_timestamp; ptime m_timestamp;
}; };
template <class T>
T* alert_cast(alert* a)
{
return dynamic_cast<T*>(a);
}
template <class T>
T const* alert_cast(alert const* a)
{
return dynamic_cast<T const*>(a);
}
class TORRENT_EXPORT alert_manager class TORRENT_EXPORT alert_manager
{ {
public: public:
enum { queue_size_limit_default = 1000 }; enum { queue_size_limit_default = 1000 };
alert_manager(); alert_manager(io_service& ios);
~alert_manager(); ~alert_manager();
void post_alert(const alert& alert_); void post_alert(const alert& alert_);
bool pending() const; bool pending() const;
std::auto_ptr<alert> get(); std::auto_ptr<alert> get();
template <class T> template <class T>
bool should_post() const { return (m_alert_mask & T::static_ bool should_post() const
category) != 0; } {
boost::mutex::scoped_lock lock(m_mutex);
if (m_alerts.size() >= m_queue_size_limit) return fa
lse;
return (m_alert_mask & T::static_category) != 0;
}
alert const* wait_for_alert(time_duration max_wait); alert const* wait_for_alert(time_duration max_wait);
void set_alert_mask(int m) { m_alert_mask = m; } void set_alert_mask(int m)
{
boost::mutex::scoped_lock lock(m_mutex);
m_alert_mask = m;
}
size_t alert_queue_size_limit() const { return m_queue_size_ limit; } size_t alert_queue_size_limit() const { return m_queue_size_ limit; }
size_t set_alert_queue_size_limit(size_t queue_size_limit_); size_t set_alert_queue_size_limit(size_t queue_size_limit_);
void set_dispatch_function(boost::function<void(alert const&
)> const&);
private: private:
std::queue<alert*> m_alerts; std::queue<alert*> m_alerts;
mutable boost::mutex m_mutex; mutable boost::mutex m_mutex;
boost::condition m_condition; boost::condition m_condition;
int m_alert_mask; int m_alert_mask;
size_t m_queue_size_limit; size_t m_queue_size_limit;
boost::function<void(alert const&)> m_dispatch;
io_service& m_ios;
}; };
struct TORRENT_EXPORT unhandled_alert : std::exception struct TORRENT_EXPORT unhandled_alert : std::exception
{ {
unhandled_alert() {} unhandled_alert() {}
}; };
namespace detail { namespace detail {
struct void_; struct void_;
template<class Handler template<class Handler
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, clas s T)> , BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, clas s T)>
void handle_alert_dispatch( void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_, const Handler& h andler const std::auto_ptr<alert>& alert_, const Handler& h andler
, const std::type_info& typeid_ , const std::type_info& typeid_
, BOOST_PP_ENUM_BINARY_PARAMS(TORRENT_MAX_ALERT_TYPE S, T, *p)) , T0*, BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(TORRENT_M AX_ALERT_TYPES, T, *p))
{ {
if (typeid_ == typeid(T0)) if (typeid_ == typeid(T0))
handler(*static_cast<T0*>(alert_.get())); handler(*static_cast<T0*>(alert_.get()));
else else
handle_alert_dispatch(alert_, handler, typei d_ handle_alert_dispatch(alert_, handler, typei d_
, BOOST_PP_ENUM_SHIFTED_PARAMS( , BOOST_PP_ENUM_SHIFTED_PARAMS(
TORRENT_MAX_ALERT_TYPES, p), (void_* )0); TORRENT_MAX_ALERT_TYPES, p), (void_* )0);
} }
template<class Handler> template<class Handler>
void handle_alert_dispatch( void handle_alert_dispatch(
const std::auto_ptr<alert>& alert_ const std::auto_ptr<alert>&
, const Handler& handler , const Handler&
, const std::type_info& typeid_ , const std::type_info&
, BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void _* BOOST_PP_INTERCEPT)) , BOOST_PP_ENUM_PARAMS(TORRENT_MAX_ALERT_TYPES, void _* BOOST_PP_INTERCEPT))
{ {
throw unhandled_alert(); throw unhandled_alert();
} }
} // namespace detail } // namespace detail
template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT( template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(
TORRENT_MAX_ALERT_TYPES, class T, detail::void_)> TORRENT_MAX_ALERT_TYPES, class T, detail::void_)>
struct TORRENT_EXPORT handle_alert struct TORRENT_EXPORT handle_alert
 End of changes. 13 change blocks. 
8 lines changed or deleted 40 lines changed or added


 alert_types.hpp   alert_types.hpp 
skipping to change at line 43 skipping to change at line 43
#ifndef TORRENT_ALERT_TYPES_HPP_INCLUDED #ifndef TORRENT_ALERT_TYPES_HPP_INCLUDED
#define TORRENT_ALERT_TYPES_HPP_INCLUDED #define TORRENT_ALERT_TYPES_HPP_INCLUDED
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_connection.hpp" #include "libtorrent/peer_connection.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/identify_client.hpp" #include "libtorrent/identify_client.hpp"
#include "libtorrent/stat.hpp"
#include <boost/lexical_cast.hpp>
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT torrent_alert: alert struct TORRENT_EXPORT torrent_alert: alert
{ {
torrent_alert(torrent_handle const& h) torrent_alert(torrent_handle const& h)
: handle(h) : handle(h)
{} {}
virtual std::string message() const virtual std::string message() const
skipping to change at line 100 skipping to change at line 99
const static int static_category = alert::tracker_notificati on; const static int static_category = alert::tracker_notificati on;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " (" + url + ")"; return torrent_alert::message() + " (" + url + ")";
} }
std::string url; std::string url;
}; };
struct TORRENT_EXPORT read_piece_alert: torrent_alert
{
read_piece_alert(torrent_handle const& h
, int p, boost::shared_array<char> d, int s)
: torrent_alert(h)
, buffer(d)
, piece(p)
, size(s)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new read_piece_alert(*this));
}
const static int static_category = alert::storage_notificati
on;
virtual int category() const { return static_category; }
virtual char const* what() const { return "read piece"; }
virtual std::string message() const
{
char msg[200];
snprintf(msg, sizeof(msg), "%s: piece %s %u", torren
t_alert::message().c_str()
, buffer ? "successful" : "failed", piece);
return msg;
}
boost::shared_array<char> buffer;
int piece;
int size;
};
struct TORRENT_EXPORT file_completed_alert: torrent_alert
{
file_completed_alert(torrent_handle const& h
, int index_)
: torrent_alert(h)
, index(index_)
{}
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_completed_alert(*this
)); }
const static int static_category = alert::progress_notificat
ion;
virtual int category() const { return static_category; }
virtual char const* what() const { return "file completed";
}
virtual std::string message() const
{
char msg[200];
snprintf(msg, sizeof(msg), "%s: file %d finished dow
nloading"
, torrent_alert::message().c_str(), index);
return msg;
}
int index;
};
struct TORRENT_EXPORT file_renamed_alert: torrent_alert struct TORRENT_EXPORT file_renamed_alert: torrent_alert
{ {
file_renamed_alert(torrent_handle const& h file_renamed_alert(torrent_handle const& h
, std::string const& name_ , std::string const& name_
, int index_) , int index_)
: torrent_alert(h) : torrent_alert(h)
, name(name_) , name(name_)
, index(index_) , index(index_)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_renamed_alert(*this)) ; } { return std::auto_ptr<alert>(new file_renamed_alert(*this)) ; }
const static int static_category = alert::storage_notificati on; const static int static_category = alert::storage_notificati on;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual char const* what() const { return "file renamed"; } virtual char const* what() const { return "file renamed"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char msg[200 + NAME_MAX];
ret << torrent_alert::message() << ": file " snprintf(msg, sizeof(msg), "%s: file %d renamed to %
<< index << " renamed to " << name; s", torrent_alert::message().c_str()
return ret.str(); , index, name.c_str());
return msg;
} }
std::string name; std::string name;
int index; int index;
}; };
struct TORRENT_EXPORT file_rename_failed_alert: torrent_alert struct TORRENT_EXPORT file_rename_failed_alert: torrent_alert
{ {
file_rename_failed_alert(torrent_handle const& h file_rename_failed_alert(torrent_handle const& h
, std::string const& msg_ , int index_
, int index_) , error_code ec_)
: torrent_alert(h) : torrent_alert(h)
, msg(msg_)
, index(index_) , index(index_)
, error(ec_)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_rename_failed_alert(* this)); } { return std::auto_ptr<alert>(new file_rename_failed_alert(* this)); }
virtual char const* what() const { return "file rename faile d"; } virtual char const* what() const { return "file rename faile d"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200 + NAME_MAX];
ret << torrent_alert::message() << ": failed to rena snprintf(ret, sizeof(ret), "%s: failed to rename fil
me file " e %d: %s"
<< index << ": " << msg; , torrent_alert::message().c_str(), index, e
return ret.str(); rror.message().c_str());
return ret;
} }
const static int static_category = alert::storage_notificati on; const static int static_category = alert::storage_notificati on;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
std::string msg;
int index; int index;
error_code error;
}; };
struct TORRENT_EXPORT performance_alert: torrent_alert struct TORRENT_EXPORT performance_alert: torrent_alert
{ {
enum performance_warning_t enum performance_warning_t
{ {
outstanding_disk_buffer_limit_reached, outstanding_disk_buffer_limit_reached,
outstanding_request_limit_reached outstanding_request_limit_reached,
upload_limit_too_low,
download_limit_too_low,
send_buffer_watermark_too_low,
num_warnings
}; };
performance_alert(torrent_handle const& h performance_alert(torrent_handle const& h
, performance_warning_t w) , performance_warning_t w)
: torrent_alert(h) : torrent_alert(h)
, warning_code(w) , warning_code(w)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new performance_alert(*this)); } { return std::auto_ptr<alert>(new performance_alert(*this)); }
virtual char const* what() const { return "performance warni ng"; } virtual char const* what() const { return "performance warni ng"; }
virtual std::string message() const virtual std::string message() const
{ {
static char const* warning_str[] = static char const* warning_str[] =
{ {
"max outstanding disk writes reached", "max outstanding disk writes reached",
"max outstanding piece requests reached", "max outstanding piece requests reached",
"upload limit too low (download rate will su
ffer)",
"download limit too low (upload rate will su
ffer)",
"send buffer watermark too low (upload rate
will suffer)"
}; };
return torrent_alert::message() + ": performance war ning: " return torrent_alert::message() + ": performance war ning: "
+ warning_str[warning_code]; + warning_str[warning_code];
} }
const static int static_category = alert::performance_warnin g; const static int static_category = alert::performance_warnin g;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
performance_warning_t warning_code; performance_warning_t warning_code;
}; };
struct TORRENT_EXPORT state_changed_alert: torrent_alert struct TORRENT_EXPORT state_changed_alert: torrent_alert
{ {
state_changed_alert(torrent_handle const& h state_changed_alert(torrent_handle const& h
, torrent_status::state_t const& state_) , torrent_status::state_t state_
, torrent_status::state_t prev_state_)
: torrent_alert(h) : torrent_alert(h)
, state(state_) , state(state_)
, prev_state(prev_state_)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new state_changed_alert(*this) ); } { return std::auto_ptr<alert>(new state_changed_alert(*this) ); }
virtual char const* what() const { return "torrent state cha nged"; } virtual char const* what() const { return "torrent state cha nged"; }
virtual std::string message() const virtual std::string message() const
{ {
static char const* state_str[] = static char const* state_str[] =
{"checking (q)", "checking", "dl metadata" {"checking (q)", "checking", "dl metadata"
skipping to change at line 219 skipping to change at line 280
, "checking (r)"}; , "checking (r)"};
return torrent_alert::message() + ": state changed t o: " return torrent_alert::message() + ": state changed t o: "
+ state_str[state]; + state_str[state];
} }
const static int static_category = alert::status_notificatio n; const static int static_category = alert::status_notificatio n;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
torrent_status::state_t state; torrent_status::state_t state;
torrent_status::state_t prev_state;
}; };
struct TORRENT_EXPORT tracker_error_alert: tracker_alert struct TORRENT_EXPORT tracker_error_alert: tracker_alert
{ {
tracker_error_alert(torrent_handle const& h tracker_error_alert(torrent_handle const& h
, int times , int times
, int status , int status
, std::string const& url_ , std::string const& url_
, error_code const& e)
: tracker_alert(h, url_)
, times_in_row(times)
, status_code(status)
, msg(e.message())
{
TORRENT_ASSERT(!url.empty());
}
tracker_error_alert(torrent_handle const& h
, int times
, int status
, std::string const& url_
, std::string const& msg_) , std::string const& msg_)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, times_in_row(times) , times_in_row(times)
, status_code(status) , status_code(status)
, msg(msg_) , msg(msg_)
{ TORRENT_ASSERT(!url.empty()); } {
TORRENT_ASSERT(!url.empty());
}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_error_alert(*this) ); } { return std::auto_ptr<alert>(new tracker_error_alert(*this) ); }
const static int static_category = alert::tracker_notificati on | alert::error_notification; const static int static_category = alert::tracker_notificati on | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual char const* what() const { return "tracker error"; } virtual char const* what() const { return "tracker error"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[400];
ret << tracker_alert::message() << " (" << status_co snprintf(ret, sizeof(ret), "%s (%d) %s (%d)"
de << ") " , tracker_alert::message().c_str(), status_c
<< msg << " (" << times_in_row << ")"; ode
return ret.str(); , msg.c_str(), times_in_row);
return ret;
} }
int times_in_row; int times_in_row;
int status_code; int status_code;
std::string msg; std::string msg;
}; };
struct TORRENT_EXPORT tracker_warning_alert: tracker_alert struct TORRENT_EXPORT tracker_warning_alert: tracker_alert
{ {
tracker_warning_alert(torrent_handle const& h tracker_warning_alert(torrent_handle const& h
skipping to change at line 293 skipping to change at line 371
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
int incomplete; int incomplete;
int complete; int complete;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new scrape_reply_alert(*this)) ; } { return std::auto_ptr<alert>(new scrape_reply_alert(*this)) ; }
virtual char const* what() const { return "tracker scrape re ply"; } virtual char const* what() const { return "tracker scrape re ply"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[400];
ret << tracker_alert::message() << " scrape reply: " snprintf(ret, sizeof(ret), "%s scrape reply: %u %u"
<< incomplete , tracker_alert::message().c_str(), incomple
<< " " << complete; te, complete);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT scrape_failed_alert: tracker_alert struct TORRENT_EXPORT scrape_failed_alert: tracker_alert
{ {
scrape_failed_alert(torrent_handle const& h scrape_failed_alert(torrent_handle const& h
, std::string const& url_ , std::string const& url_
, error_code const& e)
: tracker_alert(h, url_)
, msg(e.message())
{ TORRENT_ASSERT(!url.empty()); }
scrape_failed_alert(torrent_handle const& h
, std::string const& url_
, std::string const& msg_) , std::string const& msg_)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, msg(msg_) , msg(msg_)
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
std::string msg; std::string msg;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new scrape_failed_alert(*this) ); } { return std::auto_ptr<alert>(new scrape_failed_alert(*this) ); }
const static int static_category = alert::tracker_notificati on | alert::error_notification; const static int static_category = alert::tracker_notificati on | alert::error_notification;
skipping to change at line 338 skipping to change at line 423
, num_peers(np) , num_peers(np)
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
int num_peers; int num_peers;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_reply_alert(*this) ); } { return std::auto_ptr<alert>(new tracker_reply_alert(*this) ); }
virtual char const* what() const { return "tracker reply"; } virtual char const* what() const { return "tracker reply"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[400];
ret << tracker_alert::message() << " received peers: snprintf(ret, sizeof(ret), "%s received peers: %u"
" , tracker_alert::message().c_str(), num_peer
<< num_peers; s);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT dht_reply_alert: tracker_alert struct TORRENT_EXPORT dht_reply_alert: tracker_alert
{ {
dht_reply_alert(torrent_handle const& h dht_reply_alert(torrent_handle const& h
, int np) , int np)
: tracker_alert(h, "") : tracker_alert(h, "")
, num_peers(np) , num_peers(np)
{} {}
int num_peers; int num_peers;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new dht_reply_alert(*this)); } { return std::auto_ptr<alert>(new dht_reply_alert(*this)); }
virtual char const* what() const { return "DHT reply"; } virtual char const* what() const { return "DHT reply"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[400];
ret << tracker_alert::message() << " received DHT pe snprintf(ret, sizeof(ret), "%s received DHT peers: %
ers: " u"
<< num_peers; , tracker_alert::message().c_str(), num_peer
return ret.str(); s);
return ret;
} }
}; };
struct TORRENT_EXPORT tracker_announce_alert: tracker_alert struct TORRENT_EXPORT tracker_announce_alert: tracker_alert
{ {
tracker_announce_alert(torrent_handle const& h tracker_announce_alert(torrent_handle const& h
, std::string const& url_, int event_) , std::string const& url_, int event_)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, event(event_) , event(event_)
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
skipping to change at line 403 skipping to change at line 488
, piece_index(index) , piece_index(index)
{ TORRENT_ASSERT(index >= 0);} { TORRENT_ASSERT(index >= 0);}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new hash_failed_alert(*this)); } { return std::auto_ptr<alert>(new hash_failed_alert(*this)); }
virtual char const* what() const { return "piece hash failed "; } virtual char const* what() const { return "piece hash failed "; }
const static int static_category = alert::status_notificatio n; const static int static_category = alert::status_notificatio n;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[400];
ret << torrent_alert::message() << " hash for piece snprintf(ret, sizeof(ret), "%s hash for piece %u fai
" led"
<< piece_index << " failed"; , torrent_alert::message().c_str(), piece_in
return ret.str(); dex);
return ret;
} }
int piece_index; int piece_index;
}; };
struct TORRENT_EXPORT peer_ban_alert: peer_alert struct TORRENT_EXPORT peer_ban_alert: peer_alert
{ {
peer_ban_alert(torrent_handle h, tcp::endpoint const& ip peer_ban_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& pid) , peer_id const& peer_id)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_ban_alert(*this)); } { return std::auto_ptr<alert>(new peer_ban_alert(*this)); }
virtual char const* what() const { return "peer banned"; } virtual char const* what() const { return "peer banned"; }
virtual std::string message() const virtual std::string message() const
{ {
error_code ec; error_code ec;
return peer_alert::message() + " banned peer"; return peer_alert::message() + " banned peer";
} }
}; };
struct TORRENT_EXPORT peer_unsnubbed_alert: peer_alert struct TORRENT_EXPORT peer_unsnubbed_alert: peer_alert
{ {
peer_unsnubbed_alert(torrent_handle h, tcp::endpoint const& peer_unsnubbed_alert(torrent_handle h, tcp::endpoint const&
ip ep
, peer_id const& pid) , peer_id const& peer_id)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_unsnubbed_alert(*this )); } { return std::auto_ptr<alert>(new peer_unsnubbed_alert(*this )); }
virtual char const* what() const { return "peer unsnubbed"; } virtual char const* what() const { return "peer unsnubbed"; }
virtual std::string message() const virtual std::string message() const
{ {
return peer_alert::message() + " peer unsnubbed"; return peer_alert::message() + " peer unsnubbed";
} }
}; };
struct TORRENT_EXPORT peer_snubbed_alert: peer_alert struct TORRENT_EXPORT peer_snubbed_alert: peer_alert
{ {
peer_snubbed_alert(torrent_handle h, tcp::endpoint const& ip peer_snubbed_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& pid) , peer_id const& peer_id)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_snubbed_alert(*this)) ; } { return std::auto_ptr<alert>(new peer_snubbed_alert(*this)) ; }
virtual char const* what() const { return "peer snubbed"; } virtual char const* what() const { return "peer snubbed"; }
virtual std::string message() const virtual std::string message() const
{ {
return peer_alert::message() + " peer snubbed"; return peer_alert::message() + " peer snubbed";
} }
}; };
struct TORRENT_EXPORT peer_error_alert: peer_alert struct TORRENT_EXPORT peer_error_alert: peer_alert
{ {
peer_error_alert(torrent_handle const& h, tcp::endpoint cons peer_error_alert(torrent_handle const& h, tcp::endpoint cons
t& ip t& ep
, peer_id const& pid, std::string const& msg_) , peer_id const& peer_id, error_code const& e)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
, msg(msg_) , error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_error_alert(*this)); } { return std::auto_ptr<alert>(new peer_error_alert(*this)); }
virtual char const* what() const { return "peer error"; } virtual char const* what() const { return "peer error"; }
const static int static_category = alert::peer_notification; const static int static_category = alert::peer_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
error_code ec; error_code ec;
return peer_alert::message() + " peer error: " + msg ; return peer_alert::message() + " peer error: " + err or.message();
} }
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
}; };
struct TORRENT_EXPORT peer_connect_alert: peer_alert struct TORRENT_EXPORT peer_connect_alert: peer_alert
{ {
peer_connect_alert(torrent_handle h, tcp::endpoint const& ip peer_connect_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& pid) , peer_id const& peer_id)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_connect_alert(*this)) ; } { return std::auto_ptr<alert>(new peer_connect_alert(*this)) ; }
virtual char const* what() const { return "connecting to pee r"; } virtual char const* what() const { return "connecting to pee r"; }
const static int static_category = alert::debug_notification ; const static int static_category = alert::debug_notification ;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return peer_alert::message() + " connecting to peer" ; return peer_alert::message() + " connecting to peer" ;
} }
}; };
struct TORRENT_EXPORT peer_disconnected_alert: peer_alert struct TORRENT_EXPORT peer_disconnected_alert: peer_alert
{ {
peer_disconnected_alert(torrent_handle const& h, tcp::endpoi peer_disconnected_alert(torrent_handle const& h, tcp::endpoi
nt const& ip nt const& ep
, peer_id const& pid, std::string const& msg_) , peer_id const& peer_id, error_code const& e)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
, msg(msg_) , error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_disconnected_alert(*t his)); } { return std::auto_ptr<alert>(new peer_disconnected_alert(*t his)); }
virtual char const* what() const { return "peer disconnected "; } virtual char const* what() const { return "peer disconnected "; }
const static int static_category = alert::debug_notification ; const static int static_category = alert::debug_notification ;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return peer_alert::message() + " disconnecting: " + msg; return peer_alert::message() + " disconnecting: " + error.message();
} }
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
}; };
struct TORRENT_EXPORT invalid_request_alert: peer_alert struct TORRENT_EXPORT invalid_request_alert: peer_alert
{ {
invalid_request_alert(torrent_handle const& h, tcp::endpoint invalid_request_alert(torrent_handle const& h, tcp::endpoint
const& ip const& ep
, peer_id const& pid, peer_request const& r) , peer_id const& peer_id, peer_request const& r)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
, request(r) , request(r)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new invalid_request_alert(*thi s)); } { return std::auto_ptr<alert>(new invalid_request_alert(*thi s)); }
virtual char const* what() const { return "invalid piece req uest"; } virtual char const* what() const { return "invalid piece req uest"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << peer_alert::message() << " peer sent an inval snprintf(ret, sizeof(ret), "%s peer sent an invalid
id piece request " piece request (piece: %u start: %u len: %u)"
"( piece: " << request.piece << " start: " < , torrent_alert::message().c_str(), request.
< request.start piece, request.start, request.length);
<< " len: " << request.length << ")"; return ret;
return ret.str();
} }
peer_request request; peer_request request;
}; };
struct TORRENT_EXPORT torrent_finished_alert: torrent_alert struct TORRENT_EXPORT torrent_finished_alert: torrent_alert
{ {
torrent_finished_alert( torrent_finished_alert(
const torrent_handle& h) const torrent_handle& h)
: torrent_alert(h) : torrent_alert(h)
skipping to change at line 581 skipping to change at line 681
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new piece_finished_alert(*this )); } { return std::auto_ptr<alert>(new piece_finished_alert(*this )); }
virtual char const* what() const { return "piece finished do wnloading"; } virtual char const* what() const { return "piece finished do wnloading"; }
const static int static_category = alert::progress_notificat ion; const static int static_category = alert::progress_notificat ion;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << torrent_alert::message() << " piece " << piec snprintf(ret, sizeof(ret), "%s piece: %u finished do
e_index wnloading"
<< " finished downloading"; , torrent_alert::message().c_str(), piece_in
return ret.str(); dex);
return ret;
} }
}; };
struct TORRENT_EXPORT request_dropped_alert: peer_alert struct TORRENT_EXPORT request_dropped_alert: peer_alert
{ {
request_dropped_alert(const torrent_handle& h, tcp::endpoint request_dropped_alert(const torrent_handle& h, tcp::endpoint
const& ip const& ep
, peer_id const& pid, int block_num, int piece_num) , peer_id const& peer_id, int block_num, int piece_n
: peer_alert(h, ip, pid) um)
: peer_alert(h, ep, peer_id)
, block_index(block_num) , block_index(block_num)
, piece_index(piece_num) , piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
int block_index; int block_index;
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new request_dropped_alert(*thi s)); } { return std::auto_ptr<alert>(new request_dropped_alert(*thi s)); }
virtual char const* what() const { return "block request dro pped"; } virtual char const* what() const { return "block request dro pped"; }
const static int static_category = alert::progress_notificat ion const static int static_category = alert::progress_notificat ion
| alert::peer_notification; | alert::peer_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << peer_alert::message() << " peer dropped block snprintf(ret, sizeof(ret), "%s peer dropped block (
( piece: " piece: %u block: %u)"
<< piece_index << " block: " << block_index , torrent_alert::message().c_str(), piece_in
<< ")"; dex, block_index);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT block_timeout_alert: peer_alert struct TORRENT_EXPORT block_timeout_alert: peer_alert
{ {
block_timeout_alert(const torrent_handle& h, tcp::endpoint c block_timeout_alert(const torrent_handle& h, tcp::endpoint c
onst& ip onst& ep
, peer_id const& pid, int block_num, int piece_num) , peer_id const& peer_id, int block_num, int piece_n
: peer_alert(h, ip, pid) um)
: peer_alert(h, ep, peer_id)
, block_index(block_num) , block_index(block_num)
, piece_index(piece_num) , piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
int block_index; int block_index;
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_timeout_alert(*this) ); } { return std::auto_ptr<alert>(new block_timeout_alert(*this) ); }
virtual char const* what() const { return "block timed out"; } virtual char const* what() const { return "block timed out"; }
const static int static_category = alert::progress_notificat ion const static int static_category = alert::progress_notificat ion
| alert::peer_notification; | alert::peer_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << peer_alert::message() << " peer timed out req snprintf(ret, sizeof(ret), "%s peer timed out reques
uest ( piece: " t ( piece: %u block: %u)"
<< piece_index << " block: " << block_index , torrent_alert::message().c_str(), piece_in
<< ")"; dex, block_index);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT block_finished_alert: peer_alert struct TORRENT_EXPORT block_finished_alert: peer_alert
{ {
block_finished_alert(const torrent_handle& h, tcp::endpoint block_finished_alert(const torrent_handle& h, tcp::endpoint
const& ip const& ep
, peer_id const& pid, int block_num, int piece_num) , peer_id const& peer_id, int block_num, int piece_n
: peer_alert(h, ip, pid) um)
: peer_alert(h, ep, peer_id)
, block_index(block_num) , block_index(block_num)
, piece_index(piece_num) , piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
int block_index; int block_index;
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_finished_alert(*this )); } { return std::auto_ptr<alert>(new block_finished_alert(*this )); }
virtual char const* what() const { return "block finished do wnloading"; } virtual char const* what() const { return "block finished do wnloading"; }
const static int static_category = alert::progress_notificat ion; const static int static_category = alert::progress_notificat ion;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << peer_alert::message() << " block finished dow snprintf(ret, sizeof(ret), "%s block finished downlo
nloading ( piece: " ading (piece: %u block: %u)"
<< piece_index << " block: " << block_index , torrent_alert::message().c_str(), piece_in
<< ")"; dex, block_index);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT block_downloading_alert: peer_alert struct TORRENT_EXPORT block_downloading_alert: peer_alert
{ {
block_downloading_alert(const torrent_handle& h, tcp::endpoi block_downloading_alert(const torrent_handle& h, tcp::endpoi
nt const& ip nt const& ep
, peer_id const& pid, char const* speedmsg, int bloc , peer_id const& peer_id, char const* speedmsg, int
k_num, int piece_num) block_num, int piece_num)
: peer_alert(h, ip, pid) : peer_alert(h, ep, peer_id)
, peer_speedmsg(speedmsg) , peer_speedmsg(speedmsg)
, block_index(block_num) , block_index(block_num)
, piece_index(piece_num) , piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
char const* peer_speedmsg; char const* peer_speedmsg;
int block_index; int block_index;
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_downloading_alert(*t his)); } { return std::auto_ptr<alert>(new block_downloading_alert(*t his)); }
virtual char const* what() const { return "block requested"; } virtual char const* what() const { return "block requested"; }
const static int static_category = alert::progress_notificat ion; const static int static_category = alert::progress_notificat ion;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << peer_alert::message() << " requested block ( snprintf(ret, sizeof(ret), "%s requested block (piec
piece: " e: %u block: %u) %s"
<< piece_index << " block: " << block_index , torrent_alert::message().c_str(), piece_in
<< ") " << peer_speedmsg; dex, block_index, peer_speedmsg);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT unwanted_block_alert: peer_alert struct TORRENT_EXPORT unwanted_block_alert: peer_alert
{ {
unwanted_block_alert(const torrent_handle& h, tcp::endpoint unwanted_block_alert(const torrent_handle& h, tcp::endpoint
const& ip const& ep
, peer_id const& pid, int block_num, int piece_num) , peer_id const& peer_id, int block_num, int piece_n
: peer_alert(h, ip, pid) um)
: peer_alert(h, ep, peer_id)
, block_index(block_num) , block_index(block_num)
, piece_index(piece_num) , piece_index(piece_num)
{ TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);} { TORRENT_ASSERT(block_index >= 0 && piece_index >= 0);}
int block_index; int block_index;
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new unwanted_block_alert(*this )); } { return std::auto_ptr<alert>(new unwanted_block_alert(*this )); }
virtual char const* what() const { return "unwanted block re ceived"; } virtual char const* what() const { return "unwanted block re ceived"; }
virtual std::string message() const virtual std::string message() const
{ {
std::stringstream ret; char ret[200];
ret << peer_alert::message() << " received block not snprintf(ret, sizeof(ret), "%s received block not in
in download queue ( piece: " download queue (piece: %u block: %u)"
<< piece_index << " block: " << block_index , torrent_alert::message().c_str(), piece_in
<< ")"; dex, block_index);
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT storage_moved_alert: torrent_alert struct TORRENT_EXPORT storage_moved_alert: torrent_alert
{ {
storage_moved_alert(torrent_handle const& h, std::string con st& path_) storage_moved_alert(torrent_handle const& h, std::string con st& path_)
: torrent_alert(h) : torrent_alert(h)
, path(path_) , path(path_)
{} {}
skipping to change at line 764 skipping to change at line 864
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " storage move fai led: " return torrent_alert::message() + " storage move fai led: "
+ error.message(); + error.message();
} }
}; };
struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert
{ {
torrent_deleted_alert(torrent_handle const& h) torrent_deleted_alert(torrent_handle const& h, sha1_hash con st& ih)
: torrent_alert(h) : torrent_alert(h)
{} { info_hash = ih; }
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_deleted_alert(*thi s)); } { return std::auto_ptr<alert>(new torrent_deleted_alert(*thi s)); }
virtual char const* what() const { return "torrent deleted"; } virtual char const* what() const { return "torrent deleted"; }
const static int static_category = alert::storage_notificati on; const static int static_category = alert::storage_notificati on;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " deleted"; return torrent_alert::message() + " deleted";
} }
sha1_hash info_hash;
}; };
struct TORRENT_EXPORT torrent_delete_failed_alert: torrent_alert struct TORRENT_EXPORT torrent_delete_failed_alert: torrent_alert
{ {
torrent_delete_failed_alert(torrent_handle const& h, std::st ring msg_) torrent_delete_failed_alert(torrent_handle const& h, error_c ode const& e)
: torrent_alert(h) : torrent_alert(h)
, msg(msg_) , error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_delete_failed_aler t(*this)); } { return std::auto_ptr<alert>(new torrent_delete_failed_aler t(*this)); }
virtual char const* what() const { return "torrent delete fa iled"; } virtual char const* what() const { return "torrent delete fa iled"; }
const static int static_category = alert::storage_notificati on const static int static_category = alert::storage_notificati on
| alert::error_notification; | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " torrent deletion failed: " return torrent_alert::message() + " torrent deletion failed: "
+ msg; + error.message();
} }
}; };
struct TORRENT_EXPORT save_resume_data_alert: torrent_alert struct TORRENT_EXPORT save_resume_data_alert: torrent_alert
{ {
save_resume_data_alert(boost::shared_ptr<entry> const& rd save_resume_data_alert(boost::shared_ptr<entry> const& rd
, torrent_handle const& h) , torrent_handle const& h)
: torrent_alert(h) : torrent_alert(h)
, resume_data(rd) , resume_data(rd)
{} {}
skipping to change at line 825 skipping to change at line 935
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " resume data gene rated"; return torrent_alert::message() + " resume data gene rated";
} }
}; };
struct TORRENT_EXPORT save_resume_data_failed_alert: torrent_alert struct TORRENT_EXPORT save_resume_data_failed_alert: torrent_alert
{ {
save_resume_data_failed_alert(torrent_handle const& h save_resume_data_failed_alert(torrent_handle const& h
, std::string const& msg_) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, msg(msg_) , error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new save_resume_data_failed_al ert(*this)); } { return std::auto_ptr<alert>(new save_resume_data_failed_al ert(*this)); }
virtual char const* what() const { return "save resume data failed"; } virtual char const* what() const { return "save resume data failed"; }
const static int static_category = alert::storage_notificati on const static int static_category = alert::storage_notificati on
| alert::error_notification; | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " resume data was not generated: " return torrent_alert::message() + " resume data was not generated: "
+ msg; + error.message();
} }
}; };
struct TORRENT_EXPORT torrent_paused_alert: torrent_alert struct TORRENT_EXPORT torrent_paused_alert: torrent_alert
{ {
torrent_paused_alert(torrent_handle const& h) torrent_paused_alert(torrent_handle const& h)
: torrent_alert(h) : torrent_alert(h)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
skipping to change at line 899 skipping to change at line 1017
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " checked"; return torrent_alert::message() + " checked";
} }
}; };
struct TORRENT_EXPORT url_seed_alert: torrent_alert struct TORRENT_EXPORT url_seed_alert: torrent_alert
{ {
url_seed_alert( url_seed_alert(
torrent_handle const& h torrent_handle const& h
, const std::string& url_ , std::string const& url_
, const std::string& msg_) , error_code const& e)
: torrent_alert(h)
, url(url_)
, msg(e.message())
{}
url_seed_alert(
torrent_handle const& h
, std::string const& url_
, std::string const& msg_)
: torrent_alert(h) : torrent_alert(h)
, url(url_) , url(url_)
, msg(msg_) , msg(msg_)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new url_seed_alert(*this)); } { return std::auto_ptr<alert>(new url_seed_alert(*this)); }
virtual char const* what() const { return "web seed error"; } virtual char const* what() const { return "web seed error"; }
const static int static_category = alert::peer_notification | alert::error_notification; const static int static_category = alert::peer_notification | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
skipping to change at line 925 skipping to change at line 1052
} }
std::string url; std::string url;
std::string msg; std::string msg;
}; };
struct TORRENT_EXPORT file_error_alert: torrent_alert struct TORRENT_EXPORT file_error_alert: torrent_alert
{ {
file_error_alert( file_error_alert(
std::string const& f std::string const& f
, const torrent_handle& h , torrent_handle const& h
, const std::string& msg_) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, file(f) , file(f)
, msg(msg_) , error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
std::string file; std::string file;
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_error_alert(*this)); } { return std::auto_ptr<alert>(new file_error_alert(*this)); }
virtual char const* what() const { return "file error"; } virtual char const* what() const { return "file error"; }
const static int static_category = alert::status_notificatio n const static int static_category = alert::status_notificatio n
| alert::error_notification | alert::error_notification
| alert::storage_notification; | alert::storage_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " file (" + file + ") error: " return torrent_alert::message() + " file (" + file + ") error: "
+ msg; + error.message();
} }
}; };
struct TORRENT_EXPORT metadata_failed_alert: torrent_alert struct TORRENT_EXPORT metadata_failed_alert: torrent_alert
{ {
metadata_failed_alert(const torrent_handle& h) metadata_failed_alert(const torrent_handle& h)
: torrent_alert(h) : torrent_alert(h)
{} {}
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
skipping to change at line 1047 skipping to change at line 1182
tcp::endpoint endpoint; tcp::endpoint endpoint;
error_code error; error_code error;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_failed_alert(*this) ); } { return std::auto_ptr<alert>(new listen_failed_alert(*this) ); }
virtual char const* what() const { return "listen failed"; } virtual char const* what() const { return "listen failed"; }
const static int static_category = alert::status_notificatio n | alert::error_notification; const static int static_category = alert::status_notificatio n | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
error_code ec; char ret[200];
std::stringstream ret; snprintf(ret, sizeof(ret), "listening on %s failed:
ret << "listening on " << endpoint %s"
<< " failed: " << error.message(); , print_endpoint(endpoint).c_str(), error.me
return ret.str(); ssage().c_str());
return ret;
} }
}; };
struct TORRENT_EXPORT listen_succeeded_alert: alert struct TORRENT_EXPORT listen_succeeded_alert: alert
{ {
listen_succeeded_alert(tcp::endpoint const& ep) listen_succeeded_alert(tcp::endpoint const& ep)
: endpoint(ep) : endpoint(ep)
{} {}
tcp::endpoint endpoint; tcp::endpoint endpoint;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_succeeded_alert(*th is)); } { return std::auto_ptr<alert>(new listen_succeeded_alert(*th is)); }
virtual char const* what() const { return "listen succeeded" ; } virtual char const* what() const { return "listen succeeded" ; }
const static int static_category = alert::status_notificatio n; const static int static_category = alert::status_notificatio n;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
error_code ec; char ret[200];
std::stringstream ret; snprintf(ret, sizeof(ret), "successfully listening o
ret << "successfully listening on " << endpoint; n %s", print_endpoint(endpoint).c_str());
return ret.str(); return ret;
} }
}; };
struct TORRENT_EXPORT portmap_error_alert: alert struct TORRENT_EXPORT portmap_error_alert: alert
{ {
portmap_error_alert(int i, int t, const std::string& msg_) portmap_error_alert(int i, int t, error_code const& e)
: mapping(i), type(t), msg(msg_) : mapping(i), type(t), error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
int mapping; int mapping;
int type; int type;
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_error_alert(*this) ); } { return std::auto_ptr<alert>(new portmap_error_alert(*this) ); }
virtual char const* what() const { return "port map error"; } virtual char const* what() const { return "port map error"; }
const static int static_category = alert::port_mapping_notif ication const static int static_category = alert::port_mapping_notif ication
| alert::error_notification; | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
static char const* type_str[] = {"NAT-PMP", "UPnP"}; static char const* type_str[] = {"NAT-PMP", "UPnP"};
return std::string("could not map port using ") + ty pe_str[type] return std::string("could not map port using ") + ty pe_str[type]
+ ": " + msg; + ": " + error.message();
} }
}; };
struct TORRENT_EXPORT portmap_alert: alert struct TORRENT_EXPORT portmap_alert: alert
{ {
portmap_alert(int i, int port, int t) portmap_alert(int i, int port, int t)
: mapping(i), external_port(port), type(t) : mapping(i), external_port(port), type(t)
{} {}
int mapping; int mapping;
skipping to change at line 1119 skipping to change at line 1259
int type; int type;
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_alert(*this)); } { return std::auto_ptr<alert>(new portmap_alert(*this)); }
virtual char const* what() const { return "port map succeede d"; } virtual char const* what() const { return "port map succeede d"; }
const static int static_category = alert::port_mapping_notif ication; const static int static_category = alert::port_mapping_notif ication;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
static char const* type_str[] = {"NAT-PMP", "UPnP"}; static char const* type_str[] = {"NAT-PMP", "UPnP"};
std::stringstream ret; char ret[200];
ret << "successfully mapped port using " << type_str snprintf(ret, sizeof(ret), "successfully mapped port
[type] using %s. external port: %u"
<< ". external port: " << external_port; , type_str[type], external_port);
return ret.str(); return ret;
}
};
struct TORRENT_EXPORT portmap_log_alert: alert
{
portmap_log_alert(int t, std::string const& m)
: type(t), msg(m)
{}
int type;
std::string msg;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_log_alert(*this));
}
virtual char const* what() const { return "port map log"; }
const static int static_category = alert::port_mapping_notif
ication;
virtual int category() const { return static_category; }
virtual std::string message() const
{
static char const* type_str[] = {"NAT-PMP", "UPnP"};
char ret[600];
snprintf(ret, sizeof(ret), "%s: %s", type_str[type],
msg.c_str());
return ret;
} }
}; };
struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert struct TORRENT_EXPORT fastresume_rejected_alert: torrent_alert
{ {
fastresume_rejected_alert(torrent_handle const& h fastresume_rejected_alert(torrent_handle const& h
, std::string const& msg_) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, msg(msg_) , error(e)
{} {
#ifndef TORRENT_NO_DEPRECATE
msg = error.message();
#endif
}
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new fastresume_rejected_alert( *this)); } { return std::auto_ptr<alert>(new fastresume_rejected_alert( *this)); }
virtual char const* what() const { return "resume data rejec ted"; } virtual char const* what() const { return "resume data rejec ted"; }
const static int static_category = alert::status_notificatio n const static int static_category = alert::status_notificatio n
| alert::error_notification; | alert::error_notification;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " fast resume reje cted: " + msg; return torrent_alert::message() + " fast resume reje cted: " + error.message();
} }
}; };
struct TORRENT_EXPORT peer_blocked_alert: alert struct TORRENT_EXPORT peer_blocked_alert: alert
{ {
peer_blocked_alert(address const& ip_) peer_blocked_alert(address const& ip_)
: ip(ip_) : ip(ip_)
{} {}
address ip; address ip;
skipping to change at line 1167 skipping to change at line 1338
{ return std::auto_ptr<alert>(new peer_blocked_alert(*this)) ; } { return std::auto_ptr<alert>(new peer_blocked_alert(*this)) ; }
virtual char const* what() const { return "peer blocked"; } virtual char const* what() const { return "peer blocked"; }
const static int static_category = alert::ip_block_notificat ion; const static int static_category = alert::ip_block_notificat ion;
virtual int category() const { return static_category; } virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
error_code ec; error_code ec;
return "blocked peer: " + ip.to_string(ec); return "blocked peer: " + ip.to_string(ec);
} }
}; };
struct TORRENT_EXPORT dht_announce_alert: alert
{
dht_announce_alert(address const& ip_, int port_
, sha1_hash const& info_hash_)
: ip(ip_)
, port(port_)
, info_hash(info_hash_)
{}
address ip;
int port;
sha1_hash info_hash;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new dht_announce_alert(*this))
; }
virtual char const* what() const { return "incoming dht anno
unce"; }
const static int static_category = alert::dht_notification;
virtual int category() const { return static_category; }
virtual std::string message() const
{
error_code ec;
char ih_hex[41];
to_hex((const char*)&info_hash[0], 20, ih_hex);
char msg[200];
snprintf(msg, sizeof(msg), "incoming dht announce: %
s:%u (%s)"
, ip.to_string(ec).c_str(), port, ih_hex);
return msg;
}
};
struct TORRENT_EXPORT dht_get_peers_alert: alert
{
dht_get_peers_alert(sha1_hash const& info_hash_)
: info_hash(info_hash_)
{}
sha1_hash info_hash;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new dht_get_peers_alert(*this)
); }
virtual char const* what() const { return "incoming dht get_
peers request"; }
const static int static_category = alert::dht_notification;
virtual int category() const { return static_category; }
virtual std::string message() const
{
char ih_hex[41];
to_hex((const char*)&info_hash[0], 20, ih_hex);
char msg[200];
snprintf(msg, sizeof(msg), "incoming dht get_peers:
%s", ih_hex);
return msg;
}
};
struct TORRENT_EXPORT stats_alert: torrent_alert
{
stats_alert(torrent_handle const& h, int interval
, stat const& s);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new stats_alert(*this)); }
const static int static_category = alert::stats_notification
;
virtual int category() const { return static_category; }
virtual char const* what() const { return "stats_alert"; }
virtual std::string message() const;
enum stats_channel
{
upload_payload,
upload_protocol,
upload_ip_protocol,
upload_dht_protocol,
upload_tracker_protocol,
download_payload,
download_protocol,
download_ip_protocol,
download_dht_protocol,
download_tracker_protocol,
num_channels
};
int transferred[num_channels];
int interval;
};
struct TORRENT_EXPORT cache_flushed_alert: torrent_alert
{
cache_flushed_alert(torrent_handle const& h);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new cache_flushed_alert(*this)
); }
const static int static_category = alert::storage_notificati
on;
virtual int category() const { return static_category; }
virtual char const* what() const { return "cache_flushed_ale
rt"; }
};
} }
#endif #endif
 End of changes. 79 change blocks. 
176 lines changed or deleted 478 lines changed or added


 bandwidth_limit.hpp   bandwidth_limit.hpp 
skipping to change at line 33 skipping to change at line 33
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED #ifndef TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED
#define TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED #define TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED
#include <boost/integer_traits.hpp> #include <boost/integer_traits.hpp>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent { namespace libtorrent {
// member of peer_connection // member of peer_connection
struct bandwidth_limit struct TORRENT_EXPORT bandwidth_channel
{ {
static const int inf = boost::integer_traits<int>::const_max; static const int inf = boost::integer_traits<int>::const_max;
bandwidth_limit() bandwidth_channel()
: m_quota_left(0) : m_quota_left(0)
, m_local_limit(inf) , m_limit(0)
, m_current_rate(0)
{} {}
// 0 means infinite
void throttle(int limit) void throttle(int limit)
{ {
TORRENT_ASSERT(limit > 0); TORRENT_ASSERT(limit >= 0);
m_local_limit = limit; // if the throttle is more than this, we might overflow
TORRENT_ASSERT(limit < INT_MAX / 31);
m_limit = limit;
} }
int throttle() const int throttle() const
{ {
return m_local_limit; return m_limit;
} }
void assign(int amount) int quota_left() const
{ {
TORRENT_ASSERT(amount >= 0); if (m_limit == 0) return inf;
m_current_rate += amount; return (std::max)(m_quota_left, 0);
m_quota_left += amount;
} }
void use_quota(int amount) void update_quota(int dt_milliseconds)
{ {
TORRENT_ASSERT(amount <= m_quota_left); if (m_limit == 0) return;
m_quota_left -= amount; m_quota_left += (m_limit * dt_milliseconds + 500) / 1000;
if (m_quota_left > m_limit * 3) m_quota_left = m_limit * 3;
distribute_quota = (std::max)(m_quota_left, 0);
// fprintf(stderr, "%p: [%d]: + %d limit: %d\n", this, dt_milli
seconds, (m_limit * dt_milliseconds + 500) / 1000, m_limit);
} }
int quota_left() const // this is used when connections disconnect with
// some quota left. It's returned to its bandwidth
// channels.
void return_quota(int amount)
{ {
return (std::max)(m_quota_left, 0); TORRENT_ASSERT(amount >= 0);
if (m_limit == 0) return;
TORRENT_ASSERT(m_quota_left <= m_quota_left + amount);
m_quota_left += amount;
} }
void expire(int amount) void use_quota(int amount)
{ {
TORRENT_ASSERT(amount >= 0); TORRENT_ASSERT(amount >= 0);
m_current_rate -= amount; TORRENT_ASSERT(m_limit >= 0);
if (m_limit == 0) return;
m_quota_left -= amount;
} }
int max_assignable() const // used as temporary storage while distributing
{ // bandwidth
if (m_local_limit == inf) return inf; int tmp;
if (m_local_limit <= m_current_rate) return 0;
return m_local_limit - m_current_rate; // this is the number of bytes to distribute this round
} int distribute_quota;
private: private:
// this is the amount of bandwidth we have // this is the amount of bandwidth we have
// been assigned without using yet. i.e. // been assigned without using yet.
// the bandwidth that we use up every time
// we receive or send a message. Once this
// hits zero, we need to request more
// bandwidth from the torrent which
// in turn will request bandwidth from
// the bandwidth manager
int m_quota_left; int m_quota_left;
// the local limit is the number of bytes // the limit is the number of bytes
// per window size we are allowed to use. // per second we are allowed to use.
int m_local_limit; int m_limit;
// the current rate is the number of
// bytes we have been assigned within
// the window size.
int m_current_rate;
}; };
} }
#endif #endif
 End of changes. 18 change blocks. 
41 lines changed or deleted 43 lines changed or added


 bandwidth_manager.hpp   bandwidth_manager.hpp 
skipping to change at line 36 skipping to change at line 36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED #ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED #define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED
#include <boost/shared_ptr.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/integer_traits.hpp>
#include <boost/thread/mutex.hpp>
#include <deque>
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
#include <fstream> #include <fstream>
#endif #endif
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/bandwidth_limit.hpp" #include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_queue_entry.hpp" #include "libtorrent/bandwidth_queue_entry.hpp"
using boost::weak_ptr;
using boost::shared_ptr;
using boost::intrusive_ptr; using boost::intrusive_ptr;
using boost::bind;
namespace libtorrent { namespace libtorrent {
// the maximum block of bandwidth quota to template<class PeerConnection>
// hand out is 33kB. The block size may
// be smaller on lower limits
enum
{
max_bandwidth_block_size = 33000,
min_bandwidth_block_size = 400
};
const time_duration bw_window_size = seconds(1);
template<class PeerConnection, class Torrent>
struct history_entry
{
history_entry(intrusive_ptr<PeerConnection> p, weak_ptr<Torrent> t
, int a, ptime exp)
: expires_at(exp), amount(a), peer(p), tor(t) {}
history_entry(int a, ptime exp)
: expires_at(exp), amount(a), peer(), tor() {}
ptime expires_at;
int amount;
intrusive_ptr<PeerConnection> peer;
weak_ptr<Torrent> tor;
};
template<class T>
T clamp(T val, T ceiling, T floor)
{
TORRENT_ASSERT(ceiling >= floor);
if (val >= ceiling) return ceiling;
else if (val <= floor) return floor;
return val;
}
template<class T>
struct assign_at_exit
{
assign_at_exit(T& var, T val): var_(var), val_(val) {}
~assign_at_exit() { var_ = val_; }
T& var_;
T val_;
};
template<class PeerConnection, class Torrent>
struct bandwidth_manager struct bandwidth_manager
{ {
bandwidth_manager(io_service& ios, int channel bandwidth_manager(int channel
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
, bool log = false , bool log = false
#endif #endif
) )
: m_ios(ios) : m_queued_bytes(0)
, m_history_timer(m_ios)
, m_limit(bandwidth_limit::inf)
, m_drain_quota(0)
, m_current_quota(0)
, m_channel(channel) , m_channel(channel)
, m_in_hand_out_bandwidth(false)
, m_abort(false) , m_abort(false)
{ {
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
if (log) if (log)
m_log.open("bandwidth_limiter.log", std::ios::trunc) ; m_log.open("bandwidth_limiter.log", std::ios::trunc) ;
m_start = time_now(); m_start = time_now();
#endif #endif
} }
void drain(int bytes)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(bytes >= 0);
m_drain_quota += bytes;
if (m_drain_quota > m_limit * 5) m_drain_quota = m_limit * 5
;
}
void throttle(int limit)
{
mutex_t::scoped_lock l(m_mutex);
TORRENT_ASSERT(limit >= 0);
m_limit = limit;
}
int throttle() const
{
mutex_t::scoped_lock l(m_mutex);
return m_limit;
}
void close() void close()
{ {
mutex_t::scoped_lock l(m_mutex);
m_abort = true; m_abort = true;
m_queue.clear(); m_queue.clear();
m_history.clear(); m_queued_bytes = 0;
m_current_quota = 0;
error_code ec; error_code ec;
m_history_timer.cancel(ec);
} }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool is_queued(PeerConnection const* peer) const bool is_queued(PeerConnection const* peer) const
{ {
mutex_t::scoped_lock l(m_mutex);
return is_queued(peer);
}
bool is_queued(PeerConnection const* peer, boost::mutex::scoped_lock
& l) const
{
for (typename queue_t::const_iterator i = m_queue.begin() for (typename queue_t::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i) , end(m_queue.end()); i != end; ++i)
{ {
if (i->peer.get() == peer) return true; if (i->peer.get() == peer) return true;
} }
return false; return false;
} }
bool is_in_history(PeerConnection const* peer) const
{
mutex_t::scoped_lock l(m_mutex);
return is_in_history(peer, l);
}
bool is_in_history(PeerConnection const* peer, boost::mutex::scoped_
lock& l) const
{
for (typename history_t::const_iterator i
= m_history.begin(), end(m_history.end()); i != end;
++i)
{
if (i->peer.get() == peer) return true;
}
return false;
}
#endif #endif
int queue_size() const int queue_size() const
{ {
mutex_t::scoped_lock l(m_mutex);
return m_queue.size(); return m_queue.size();
} }
int queued_bytes() const
{
return m_queued_bytes;
}
// non prioritized means that, if there's a line for bandwidth, // non prioritized means that, if there's a line for bandwidth,
// others will cut in front of the non-prioritized peers. // others will cut in front of the non-prioritized peers.
// this is used by web seeds // this is used by web seeds
void request_bandwidth(intrusive_ptr<PeerConnection> const& peer void request_bandwidth(intrusive_ptr<PeerConnection> const& peer
, int blk, int priority) , int blk, int priority
, bandwidth_channel* chan1 = 0
, bandwidth_channel* chan2 = 0
, bandwidth_channel* chan3 = 0
, bandwidth_channel* chan4 = 0
, bandwidth_channel* chan5 = 0
)
{ {
mutex_t::scoped_lock l(m_mutex);
INVARIANT_CHECK; INVARIANT_CHECK;
if (m_abort) return; if (m_abort) return;
TORRENT_ASSERT(blk > 0);
TORRENT_ASSERT(!is_queued(peer.get(), l));
// make sure this peer isn't already in line TORRENT_ASSERT(blk > 0);
// waiting for bandwidth TORRENT_ASSERT(priority > 0);
TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0 TORRENT_ASSERT(!is_queued(peer.get()));
);
typename queue_t::reverse_iterator i(m_queue.rbegin()); bw_request<PeerConnection> bwr(peer, blk, priority);
while (i != m_queue.rend() && priority > i->priority) int i = 0;
if (chan1 && chan1->throttle() > 0) bwr.channel[i++] = chan1
;
if (chan2 && chan2->throttle() > 0) bwr.channel[i++] = chan2
;
if (chan3 && chan3->throttle() > 0) bwr.channel[i++] = chan3
;
if (chan4 && chan4->throttle() > 0) bwr.channel[i++] = chan4
;
if (chan5 && chan5->throttle() > 0) bwr.channel[i++] = chan5
;
if (i == 0)
{ {
++i->priority; // the connection is not rate limited by any of its
++i; // bandwidth channels, or it doesn't belong to any
// channels. There's no point in adding it to
// the queue, just satisfy the request immediately
bwr.peer->assign_bandwidth(m_channel, blk);
return;
} }
m_queue.insert(i.base(), bw_queue_entry<PeerConnection, Torr m_queued_bytes += blk;
ent>(peer, blk, priority)); m_queue.push_back(bwr);
if (!m_queue.empty()) hand_out_bandwidth(l);
} }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const void check_invariant() const
{ {
int current_quota = 0; int queued = 0;
for (typename history_t::const_iterator i for (typename queue_t::const_iterator i = m_queue.begin()
= m_history.begin(), end(m_history.end()); i != end; , end(m_queue.end()); i != end; ++i)
++i)
{
current_quota += i->amount;
}
TORRENT_ASSERT(current_quota == m_current_quota);
typename queue_t::const_iterator j = m_queue.begin();
if (j != m_queue.end())
{ {
++j; queued += i->request_size - i->assigned;
for (typename queue_t::const_iterator i = m_queue.be
gin()
, end(m_queue.end()); i != end && j != end;
++i, ++j)
TORRENT_ASSERT(i->priority >= j->priority);
} }
TORRENT_ASSERT(queued == m_queued_bytes);
} }
#endif #endif
private: void update_quotas(time_duration const& dt)
void add_history_entry(history_entry<PeerConnection, Torrent> const&
e)
{
INVARIANT_CHECK;
m_history.push_front(e);
m_current_quota += e.amount;
// in case the size > 1 there is already a timer
// active that will be invoked, no need to set one up
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
m_log << std::setw(7) << total_milliseconds(time_now() - m_s
tart) << " + "
" queue: " << std::setw(3) << m_queue.size()
<< " used: " << std::setw(7) << m_current_quota
<< " limit: " << std::setw(7) << m_limit
<< " history: " << std::setw(3) << m_history.size()
<< std::endl;
#endif
if (m_history.size() > 1) return;
if (m_abort) return;
error_code ec;
// TORRENT_ASSERT(e.expires_at > time_now());
m_history_timer.expires_at(e.expires_at, ec);
m_history_timer.async_wait(bind(&bandwidth_manager::on_histo
ry_expire, this, _1));
}
void on_history_expire(error_code const& e)
{ {
if (e) return;
mutex_t::scoped_lock l(m_mutex);
if (m_abort) return; if (m_abort) return;
INVARIANT_CHECK; if (m_queue.empty()) return;
TORRENT_ASSERT(!m_history.empty());
ptime now(time_now());
while (!m_history.empty() && m_history.back().expires_at <=
now)
{
history_entry<PeerConnection, Torrent> e = m_history
.back();
m_history.pop_back();
m_current_quota -= e.amount;
TORRENT_ASSERT(m_current_quota >= 0);
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
m_log << std::setw(7) << total_milliseconds(time_now
() - m_start) << " - "
" queue: " << std::setw(3) << m_queue.size()
<< " used: " << std::setw(7) << m_current_qu
ota
<< " limit: " << std::setw(7) << m_limit
<< " history: " << std::setw(3) << m_history
.size()
<< std::endl;
#endif
intrusive_ptr<PeerConnection> c = e.peer;
if (!c) continue;
shared_ptr<Torrent> t = e.tor.lock();
l.unlock();
if (!c->is_disconnecting()) c->expire_bandwidth(m_ch
annel, e.amount);
if (t) t->expire_bandwidth(m_channel, e.amount);
l.lock();
}
// now, wait for the next chunk to expire
if (!m_history.empty() && !m_abort)
{
error_code ec;
TORRENT_ASSERT(m_history.back().expires_at > now);
m_history_timer.expires_at(m_history.back().expires_
at, ec);
m_history_timer.async_wait(bind(&bandwidth_manager::
on_history_expire, this, _1));
}
// since some bandwidth just expired, it
// means we can hand out more (in case there
// are still consumers in line)
if (!m_queue.empty()) hand_out_bandwidth(l);
}
void hand_out_bandwidth(boost::mutex::scoped_lock& l)
{
// if we're already handing out bandwidth, just return back
// to the loop further down on the callstack
if (m_in_hand_out_bandwidth) return;
m_in_hand_out_bandwidth = true;
// set it to false when exiting function
assign_at_exit<bool> sg(m_in_hand_out_bandwidth, false);
INVARIANT_CHECK; INVARIANT_CHECK;
ptime now(time_now()); int dt_milliseconds = total_milliseconds(dt);
if (dt_milliseconds > 3000) dt_milliseconds = 3000;
int limit = m_limit;
// available bandwidth to hand out // for each bandwidth channel, call update_quota(dt)
int amount = limit - m_current_quota;
if (amount <= 0) return; std::vector<bandwidth_channel*> channels;
if (m_drain_quota > 0) for (typename queue_t::iterator i = m_queue.begin();
i != m_queue.end();)
{ {
int drain_amount = (std::min)(m_drain_quota, amount) if (i->peer->is_disconnecting())
; {
m_drain_quota -= drain_amount; m_queued_bytes -= i->request_size - i->assig
amount -= drain_amount; ned;
add_history_entry(history_entry<PeerConnection, Torr
ent>(
drain_amount, now + bw_window_size));
}
queue_t tmp; // return all assigned quota to all the
while (!m_queue.empty() && amount > 0) // bandwidth channels this peer belongs to
{ for (int j = 0; j < 5 && i->channel[j]; ++j)
bw_queue_entry<PeerConnection, Torrent> qe = m_queue {
.front(); bandwidth_channel* bwc = i->channel[
TORRENT_ASSERT(qe.max_block_size > 0); j];
m_queue.pop_front(); bwc->return_quota(i->assigned);
}
shared_ptr<Torrent> t = qe.torrent.lock(); i = m_queue.erase(i);
if (!t) continue;
if (qe.peer->is_disconnecting())
{
l.unlock();
t->expire_bandwidth(m_channel, qe.max_block_
size);
l.lock();
continue; continue;
} }
for (int j = 0; j < 5 && i->channel[j]; ++j)
{
bandwidth_channel* bwc = i->channel[j];
bwc->tmp = 0;
}
++i;
}
// at this point, max_assignable may actually be zer for (typename queue_t::iterator i = m_queue.begin()
o. Since , end(m_queue.end()); i != end; ++i)
// the rate limit of the peer might have changed whi {
le it for (int j = 0; j < 5 && i->channel[j]; ++j)
// was in the queue.
int max_assignable = qe.peer->max_assignable_bandwid
th(m_channel);
if (max_assignable == 0)
{ {
TORRENT_ASSERT(is_in_history(qe.peer.get(), bandwidth_channel* bwc = i->channel[j];
l)); if (bwc->tmp == 0) channels.push_back(bwc);
tmp.push_back(qe); bwc->tmp += i->priority;
continue; TORRENT_ASSERT(i->priority > 0);
} }
}
// this is the limit of the block size. It depends o for (std::vector<bandwidth_channel*>::iterator i = channels.
n the throttle begin()
// so that it can be closer to optimal. Larger block , end(channels.end()); i != end; ++i)
sizes will give lower {
// granularity to the rate but will be more efficien (*i)->update_quota(dt_milliseconds);
t. At high rates }
// the block sizes are bigger and at low rates, the
granularity
// is more important and block sizes are smaller
// the minimum rate that can be given is the block s queue_t tm;
ize, so, the
// block size must be smaller for lower rates. This
is because
// the history window is one second, and the block w
ill be forgotten
// after one second.
int block_size = (std::min)(qe.peer->bandwidth_throt
tle(m_channel)
, limit / 10);
if (block_size < min_bandwidth_block_size) for (typename queue_t::iterator i = m_queue.begin();
{ i != m_queue.end();)
block_size = (std::min)(int(min_bandwidth_bl {
ock_size), limit); int a = i->assign_bandwidth();
} if (i->assigned == i->request_size
else if (block_size > max_bandwidth_block_size) || (i->ttl <= 0 && i->assigned > 0))
{ {
if (limit == bandwidth_limit::inf) a += i->request_size - i->assigned;
{ TORRENT_ASSERT(i->assigned <= i->request_siz
block_size = max_bandwidth_block_siz e);
e; tm.push_back(*i);
} i = m_queue.erase(i);
else
{
// try to make the block_size a divi
sor of
// m_limit to make the distributions
as fair
// as possible
// TODO: move this calculcation to w
here the limit
// is changed
block_size = limit
/ (limit / max_bandwidth_blo
ck_size);
}
} }
if (block_size > qe.max_block_size) block_size = qe. else
max_block_size;
if (amount < block_size / 4)
{ {
tmp.push_back(qe); ++i;
// m_queue.push_front(qe);
break;
} }
m_queued_bytes -= a;
}
// so, hand out max_assignable, but no more than while (!tm.empty())
// the available bandwidth (amount) and no more {
// than the max_bandwidth_block_size bw_request<PeerConnection>& bwr = tm.back();
int hand_out_amount = (std::min)((std::min)(block_si bwr.peer->assign_bandwidth(m_channel, bwr.assigned);
ze, max_assignable) tm.pop_back();
, amount);
TORRENT_ASSERT(hand_out_amount > 0);
amount -= hand_out_amount;
TORRENT_ASSERT(hand_out_amount <= qe.max_block_size)
;
l.unlock();
t->assign_bandwidth(m_channel, hand_out_amount, qe.m
ax_block_size);
qe.peer->assign_bandwidth(m_channel, hand_out_amount
);
l.lock();
add_history_entry(history_entry<PeerConnection, Torr
ent>(
qe.peer, t, hand_out_amount, now + bw_window
_size));
} }
if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin( ), tmp.end());
} }
typedef boost::mutex mutex_t;
mutable mutex_t m_mutex;
// the io_service used for the timer
io_service& m_ios;
// the timer that is waiting for the entries
// in the history queue to expire (slide out
// of the history window)
deadline_timer m_history_timer;
// the rate limit (bytes per second)
int m_limit;
// bytes to drain without handing out to a peer
// used to deduct the IP overhead
int m_drain_quota;
// the sum of all recently handed out bandwidth blocks
int m_current_quota;
// these are the consumers that want bandwidth // these are the consumers that want bandwidth
typedef std::deque<bw_queue_entry<PeerConnection, Torrent> > queue_t ; typedef std::vector<bw_request<PeerConnection> > queue_t;
queue_t m_queue; queue_t m_queue;
// the number of bytes all the requests in queue are for
// these are the consumers that have received bandwidth int m_queued_bytes;
// that will expire
typedef std::deque<history_entry<PeerConnection, Torrent> > history_
t;
history_t m_history;
// this is the channel within the consumers // this is the channel within the consumers
// that bandwidth is assigned to (upload or download) // that bandwidth is assigned to (upload or download)
int m_channel; int m_channel;
// this is true while we're in the hand_out_bandwidth loop
// to prevent recursive invocations to interfere
bool m_in_hand_out_bandwidth;
bool m_abort; bool m_abort;
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
std::ofstream m_log; std::ofstream m_log;
ptime m_start; ptime m_start;
#endif #endif
}; };
} }
 End of changes. 53 change blocks. 
386 lines changed or deleted 112 lines changed or added


 bandwidth_queue_entry.hpp   bandwidth_queue_entry.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED #ifndef TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED #define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include "libtorrent/bandwidth_limit.hpp"
namespace libtorrent { namespace libtorrent {
template<class PeerConnection, class Torrent> template<class PeerConnection>
struct bw_queue_entry struct bw_request
{ {
bw_queue_entry(boost::intrusive_ptr<PeerConnection> const& pe bw_request(boost::intrusive_ptr<PeerConnection> const& pe
, int blk, int prio) , int blk, int prio)
: peer(pe), torrent(peer->associated_torrent()) : peer(pe)
, max_block_size(blk), priority(prio) {} , priority(prio)
, assigned(0)
, request_size(blk)
, ttl(20)
{
TORRENT_ASSERT(priority > 0);
std::memset(channel, 0, sizeof(channel));
}
boost::intrusive_ptr<PeerConnection> peer; boost::intrusive_ptr<PeerConnection> peer;
boost::weak_ptr<Torrent> torrent; // 1 is normal prio
int max_block_size; int priority;
int priority; // 0 is low prio // the number of bytes assigned to this request so far
int assigned;
// once assigned reaches this, we dispatch the request function
int request_size;
// the max number of rounds for this request to survive
// this ensures that requests gets responses at very low
// rate limits, when the requested size would take a long
// time to satisfy
int ttl;
// loops over the bandwidth channels and assigns bandwidth
// from the most limiting one
int assign_bandwidth()
{
TORRENT_ASSERT(assigned < request_size);
int quota = request_size - assigned;
TORRENT_ASSERT(quota >= 0);
for (int j = 0; j < 5 && channel[j]; ++j)
{
if (channel[j]->throttle() == 0) continue;
quota = (std::min)(int(boost::uint64_t(channel[j]->d
istribute_quota)
* priority / channel[j]->tmp), quota);
}
assigned += quota;
for (int j = 0; j < 5 && channel[j]; ++j)
channel[j]->use_quota(quota);
TORRENT_ASSERT(assigned <= request_size);
--ttl;
TORRENT_ASSERT(assigned <= request_size);
return quota;
}
bandwidth_channel* channel[5];
}; };
} }
#endif #endif
 End of changes. 5 change blocks. 
8 lines changed or deleted 51 lines changed or added


 bitfield.hpp   bitfield.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_BITFIELD_HPP_INCLUDED #ifndef TORRENT_BITFIELD_HPP_INCLUDED
#define TORRENT_BITFIELD_HPP_INCLUDED #define TORRENT_BITFIELD_HPP_INCLUDED
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include <cstring> // for memset and memcpy #include <cstring> // for memset and memcpy
#include <cstdlib> // for malloc, free and realloc
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT bitfield struct TORRENT_EXPORT bitfield
{ {
bitfield(): m_bytes(0), m_size(0), m_own(false) {} bitfield(): m_bytes(0), m_size(0), m_own(false) {}
bitfield(int bits): m_bytes(0), m_size(0) bitfield(int bits): m_bytes(0), m_size(0)
{ resize(bits); } { resize(bits); }
bitfield(int bits, bool val): m_bytes(0), m_size(0) bitfield(int bits, bool val): m_bytes(0), m_size(0)
{ resize(bits, val); } { resize(bits, val); }
bitfield(char const* bytes, int bits): m_bytes(0), m_size(0) bitfield(char const* b, int bits): m_bytes(0), m_size(0)
{ assign(bytes, bits); } { assign(b, bits); }
bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own( false) bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own( false)
{ assign(rhs.bytes(), rhs.size()); } { assign(rhs.bytes(), rhs.size()); }
void borrow_bytes(char* bytes, int bits) void borrow_bytes(char* b, int bits)
{ {
dealloc(); dealloc();
m_bytes = (unsigned char*)bytes; m_bytes = (unsigned char*)b;
m_size = bits; m_size = bits;
m_own = false; m_own = false;
} }
~bitfield() { dealloc(); } ~bitfield() { dealloc(); }
void assign(char const* bytes, int bits) void assign(char const* b, int bits)
{ resize(bits); std::memcpy(m_bytes, bytes, (bits + 7) / 8); { resize(bits); std::memcpy(m_bytes, b, (bits + 7) / 8); cle
clear_trailing_bits(); } ar_trailing_bits(); }
bool operator[](int index) const bool operator[](int index) const
{ return get_bit(index); } { return get_bit(index); }
bool get_bit(int index) const bool get_bit(int index) const
{ {
TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_size); TORRENT_ASSERT(index < m_size);
return (m_bytes[index / 8] & (0x80 >> (index & 7))) != 0; return (m_bytes[index / 8] & (0x80 >> (index & 7))) != 0;
} }
skipping to change at line 225 skipping to change at line 224
clear_trailing_bits(); clear_trailing_bits();
} }
void clear_all() void clear_all()
{ {
std::memset(m_bytes, 0x00, (m_size + 7) / 8); std::memset(m_bytes, 0x00, (m_size + 7) / 8);
} }
void resize(int bits) void resize(int bits)
{ {
const int bytes = (bits + 7) / 8; const int b = (bits + 7) / 8;
if (m_bytes) if (m_bytes)
{ {
if (m_own) if (m_own)
{ {
m_bytes = (unsigned char*)std::reall oc(m_bytes, bytes); m_bytes = (unsigned char*)std::reall oc(m_bytes, b);
m_own = true; m_own = true;
} }
else if (bits > m_size) else if (bits > m_size)
{ {
unsigned char* tmp = (unsigned char* unsigned char* tmp = (unsigned char*
)std::malloc(bytes); )std::malloc(b);
std::memcpy(tmp, m_bytes, (std::min) std::memcpy(tmp, m_bytes, (std::min)
((m_size + 7)/ 8, bytes)); (int(m_size + 7)/ 8, b));
m_bytes = tmp; m_bytes = tmp;
m_own = true; m_own = true;
} }
} }
else else
{ {
m_bytes = (unsigned char*)std::malloc(bytes) ; m_bytes = (unsigned char*)std::malloc(b);
m_own = true; m_own = true;
} }
m_size = bits; m_size = bits;
clear_trailing_bits(); clear_trailing_bits();
} }
void free() { dealloc(); m_size = 0; }
private: private:
void clear_trailing_bits() void clear_trailing_bits()
{ {
// clear the tail bits in the last byte // clear the tail bits in the last byte
if (m_size & 7) m_bytes[(m_size + 7) / 8 - 1] &= 0xf f << (8 - (m_size & 7)); if (m_size & 7) m_bytes[(m_size + 7) / 8 - 1] &= 0xf f << (8 - (m_size & 7));
} }
void dealloc() { if (m_own) std::free(m_bytes); m_bytes = 0; } void dealloc() { if (m_own) std::free(m_bytes); m_bytes = 0; }
unsigned char* m_bytes; unsigned char* m_bytes;
int m_size; // in bits int m_size:31; // in bits
bool m_own; bool m_own:1;
}; };
} }
#endif // TORRENT_BITFIELD_HPP_INCLUDED #endif // TORRENT_BITFIELD_HPP_INCLUDED
 End of changes. 11 change blocks. 
17 lines changed or deleted 18 lines changed or added


 broadcast_socket.hpp   broadcast_socket.hpp 
skipping to change at line 54 skipping to change at line 54
TORRENT_EXPORT bool is_local(address const& a); TORRENT_EXPORT bool is_local(address const& a);
TORRENT_EXPORT bool is_loopback(address const& addr); TORRENT_EXPORT bool is_loopback(address const& addr);
TORRENT_EXPORT bool is_multicast(address const& addr); TORRENT_EXPORT bool is_multicast(address const& addr);
TORRENT_EXPORT bool is_any(address const& addr); TORRENT_EXPORT bool is_any(address const& addr);
TORRENT_EXPORT int cidr_distance(address const& a1, address const& a 2); TORRENT_EXPORT int cidr_distance(address const& a1, address const& a 2);
// determines if the operating system supports IPv6 // determines if the operating system supports IPv6
TORRENT_EXPORT bool supports_ipv6(); TORRENT_EXPORT bool supports_ipv6();
int common_bits(unsigned char const* b1 TORRENT_EXPORT int common_bits(unsigned char const* b1
, unsigned char const* b2, int n); , unsigned char const* b2, int n);
TORRENT_EXPORT address guess_local_address(io_service&); TORRENT_EXPORT address guess_local_address(io_service&);
typedef boost::function<void(udp::endpoint const& from typedef boost::function<void(udp::endpoint const& from
, char* buffer, int size)> receive_handler_t; , char* buffer, int size)> receive_handler_t;
class TORRENT_EXPORT broadcast_socket class TORRENT_EXPORT broadcast_socket
{ {
public: public:
broadcast_socket(io_service& ios, udp::endpoint const& multi cast_endpoint broadcast_socket(io_service& ios, udp::endpoint const& multi cast_endpoint
, receive_handler_t const& handler, bool loopback = true); , receive_handler_t const& handler, bool loopback = true);
~broadcast_socket() { close(); } ~broadcast_socket() { close(); }
void send(char const* buffer, int size, error_code& ec); void send(char const* buffer, int size, error_code& ec);
void close(); void close();
int num_send_sockets() const { return m_unicast_sockets.size (); }
private: private:
struct socket_entry struct socket_entry
{ {
socket_entry(boost::shared_ptr<datagram_socket> cons t& s): socket(s) {} socket_entry(boost::shared_ptr<datagram_socket> cons t& s): socket(s) {}
boost::shared_ptr<datagram_socket> socket; boost::shared_ptr<datagram_socket> socket;
char buffer[1024]; char buffer[1024];
udp::endpoint remote; udp::endpoint remote;
void close() void close()
 End of changes. 2 change blocks. 
1 lines changed or deleted 2 lines changed or added


 bt_peer_connection.hpp   bt_peer_connection.hpp 
skipping to change at line 40 skipping to change at line 40
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED #ifndef TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED #define TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <deque>
#include <string> #include <string>
#include "libtorrent/debug.hpp" #include "libtorrent/debug.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/smart_ptr.hpp> #include <boost/smart_ptr.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
skipping to change at line 108 skipping to change at line 107
// with this constructor we have been contacted and we still don't // with this constructor we have been contacted and we still don't
// know which torrent the connection belongs to // know which torrent the connection belongs to
bt_peer_connection( bt_peer_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote , tcp::endpoint const& remote
, policy::peer* peerinfo); , policy::peer* peerinfo);
void start(); void start();
enum { upload_only_msg = 2 };
~bt_peer_connection(); ~bt_peer_connection();
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
bool supports_encryption() const bool supports_encryption() const
{ return m_encrypted; } { return m_encrypted; }
#endif #endif
enum message_type enum message_type
{ {
// standard messages // standard messages
skipping to change at line 218 skipping to change at line 219
void write_interested(); void write_interested();
void write_not_interested(); void write_not_interested();
void write_request(peer_request const& r); void write_request(peer_request const& r);
void write_cancel(peer_request const& r); void write_cancel(peer_request const& r);
void write_bitfield(); void write_bitfield();
void write_have(int index); void write_have(int index);
void write_piece(peer_request const& r, disk_buffer_holder& buffer); void write_piece(peer_request const& r, disk_buffer_holder& buffer);
void write_handshake(); void write_handshake();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void write_extensions(); void write_extensions();
void write_upload_only();
#endif #endif
void write_chat_message(const std::string& msg);
void write_metadata(std::pair<int, int> req); void write_metadata(std::pair<int, int> req);
void write_metadata_request(std::pair<int, int> req); void write_metadata_request(std::pair<int, int> req);
void write_keepalive(); void write_keepalive();
// DHT extension // DHT extension
void write_dht_port(int listen_port); void write_dht_port(int listen_port);
// FAST extension // FAST extension
void write_have_all(); void write_have_all();
void write_have_none(); void write_have_none();
skipping to change at line 278 skipping to change at line 279
// stream key (info hash of attached torrent) // stream key (info hash of attached torrent)
// secret is the DH shared secret // secret is the DH shared secret
// initializes m_RC4_handler // initializes m_RC4_handler
void init_pe_RC4_handler(char const* secret, sha1_hash const & stream_key); void init_pe_RC4_handler(char const* secret, sha1_hash const & stream_key);
public: public:
// these functions encrypt the send buffer if m_rc4_encrypte d // these functions encrypt the send buffer if m_rc4_encrypte d
// is true, otherwise it passes the call to the // is true, otherwise it passes the call to the
// peer_connection functions of the same names // peer_connection functions of the same names
virtual void append_const_send_buffer(char const* buffer, in t size);
void send_buffer(char const* buf, int size, int flags = 0); void send_buffer(char const* buf, int size, int flags = 0);
buffer::interval allocate_send_buffer(int size); buffer::interval allocate_send_buffer(int size);
template <class Destructor> template <class Destructor>
void append_send_buffer(char* buffer, int size, Destructor c onst& destructor) void append_send_buffer(char* buffer, int size, Destructor c onst& destructor)
{ {
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
if (m_rc4_encrypted) if (m_rc4_encrypted)
{ {
TORRENT_ASSERT(send_buffer_size() == m_encry pted_bytes); TORRENT_ASSERT(send_buffer_size() == m_encry pted_bytes);
m_RC4_handler->encrypt(buffer, size); m_RC4_handler->encrypt(buffer, size);
skipping to change at line 367 skipping to change at line 367
, length(l) , length(l)
{ {
TORRENT_ASSERT(s >= 0); TORRENT_ASSERT(s >= 0);
TORRENT_ASSERT(l > 0); TORRENT_ASSERT(l > 0);
} }
int start; int start;
int length; int length;
}; };
static bool range_below_zero(const range& r) static bool range_below_zero(const range& r)
{ return r.start < 0; } { return r.start < 0; }
std::deque<range> m_payloads; std::vector<range> m_payloads;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
// the message ID for upload only message
// 0 if not supported
int m_upload_only_id;
char m_reserved_bits[8];
// this is set to true if the handshake from // this is set to true if the handshake from
// the peer indicated that it supports the // the peer indicated that it supports the
// extension protocol // extension protocol
bool m_supports_extensions; bool m_supports_extensions:1;
char m_reserved_bits[20];
#endif #endif
bool m_supports_dht_port; bool m_supports_dht_port:1;
bool m_supports_fast; bool m_supports_fast:1;
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
// this is set to true after the encryption method has been // this is set to true after the encryption method has been
// succesfully negotiated (either plaintext or rc4), to sign al // succesfully negotiated (either plaintext or rc4), to sign al
// automatic encryption/decryption. // automatic encryption/decryption.
bool m_encrypted; bool m_encrypted;
// true if rc4, false if plaintext // true if rc4, false if plaintext
bool m_rc4_encrypted; bool m_rc4_encrypted;
skipping to change at line 429 skipping to change at line 433
// bitfield is sent to this peer // bitfield is sent to this peer
bool m_sent_bitfield; bool m_sent_bitfield;
bool m_in_constructor; bool m_in_constructor;
bool m_sent_handshake; bool m_sent_handshake;
// the number of bytes in the send buffer // the number of bytes in the send buffer
// that have been encrypted (only used for // that have been encrypted (only used for
// encrypted connections) // encrypted connections)
public:
int m_encrypted_bytes; int m_encrypted_bytes;
#endif #endif
}; };
} }
#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 10 change blocks. 
8 lines changed or deleted 13 lines changed or added


 buffer.hpp   buffer.hpp 
skipping to change at line 52 skipping to change at line 52
class buffer class buffer
{ {
public: public:
struct interval struct interval
{ {
interval() interval()
: begin(0) : begin(0)
, end(0) , end(0)
{} {}
interval(char* begin, char* end) interval(char* b, char* e)
: begin(begin) : begin(b)
, end(end) , end(e)
{} {}
char operator[](int index) const char operator[](int index) const
{ {
TORRENT_ASSERT(begin + index < end); TORRENT_ASSERT(begin + index < end);
return begin[index]; return begin[index];
} }
int left() const { TORRENT_ASSERT(end >= begin); return end - begin; } int left() const { TORRENT_ASSERT(end >= begin); return end - begin; }
char* begin; char* begin;
char* end; char* end;
}; };
struct const_interval struct const_interval
{ {
const_interval(char const* begin, char const* end) const_interval(interval const& i)
: begin(begin) : begin(i.begin)
, end(end) , end(i.end)
{}
const_interval(char const* b, char const* e)
: begin(b)
, end(e)
{} {}
char operator[](int index) const char operator[](int index) const
{ {
TORRENT_ASSERT(begin + index < end); TORRENT_ASSERT(begin + index < end);
return begin[index]; return begin[index];
} }
bool operator==(const const_interval& p_interval) bool operator==(const const_interval& p_interval)
{ {
skipping to change at line 114 skipping to change at line 119
, m_end(0) , m_end(0)
, m_last(0) , m_last(0)
{ {
if (b.size() == 0) return; if (b.size() == 0) return;
resize(b.size()); resize(b.size());
std::memcpy(m_begin, b.begin(), b.size()); std::memcpy(m_begin, b.begin(), b.size());
} }
buffer& operator=(buffer const& b) buffer& operator=(buffer const& b)
{ {
if (&b == this) return *this;
resize(b.size()); resize(b.size());
std::memcpy(m_begin, b.begin(), b.size()); std::memcpy(m_begin, b.begin(), b.size());
return *this; return *this;
} }
~buffer() ~buffer()
{ {
::operator delete (m_begin); std::free(m_begin);
} }
buffer::interval data() { return interval(m_begin, m_end); } buffer::interval data() { return interval(m_begin, m_end); }
buffer::const_interval data() const { return const_interval(m_begin, m_end); } buffer::const_interval data() const { return const_interval(m_begin, m_end); }
void resize(std::size_t n) void resize(std::size_t n)
{ {
reserve(n); reserve(n);
m_end = m_begin + n; m_end = m_begin + n;
} }
skipping to change at line 148 skipping to change at line 154
resize(size() + last - first); resize(size() + last - first);
std::memcpy(m_begin + p, first, last - first); std::memcpy(m_begin + p, first, last - first);
return; return;
} }
resize(size() + last - first); resize(size() + last - first);
std::memmove(m_begin + p + (last - first), m_begin + p, last - first); std::memmove(m_begin + p + (last - first), m_begin + p, last - first);
std::memcpy(m_begin + p, first, last - first); std::memcpy(m_begin + p, first, last - first);
} }
void erase(char* begin, char* end) void erase(char* b, char* e)
{ {
TORRENT_ASSERT(end <= m_end); TORRENT_ASSERT(e <= m_end);
TORRENT_ASSERT(begin >= m_begin); TORRENT_ASSERT(b >= m_begin);
TORRENT_ASSERT(begin <= end); TORRENT_ASSERT(b <= e);
if (end == m_end) if (e == m_end)
{ {
resize(begin - m_begin); resize(b - m_begin);
return; return;
} }
std::memmove(begin, end, m_end - end); std::memmove(b, e, m_end - e);
m_end = begin + (m_end - end); m_end = b + (m_end - e);
} }
void clear() { m_end = m_begin; } void clear() { m_end = m_begin; }
std::size_t size() const { return m_end - m_begin; } std::size_t size() const { return m_end - m_begin; }
std::size_t capacity() const { return m_last - m_begin; } std::size_t capacity() const { return m_last - m_begin; }
void reserve(std::size_t n) void reserve(std::size_t n)
{ {
if (n <= capacity()) return; if (n <= capacity()) return;
TORRENT_ASSERT(n > 0); TORRENT_ASSERT(n > 0);
char* buf = (char*)::operator new(n);
std::size_t s = size(); std::size_t s = size();
std::memcpy(buf, m_begin, s); m_begin = (char*)std::realloc(m_begin, n);
::operator delete (m_begin); m_end = m_begin + s;
m_begin = buf;
m_end = buf + s;
m_last = m_begin + n; m_last = m_begin + n;
} }
bool empty() const { return m_begin == m_end; } bool empty() const { return m_begin == m_end; }
char& operator[](std::size_t i) { TORRENT_ASSERT(i < size()); return m_begin[i]; } char& operator[](std::size_t i) { TORRENT_ASSERT(i < size()); return m_begin[i]; }
char const& operator[](std::size_t i) const { TORRENT_ASSERT(i < siz e()); return m_begin[i]; } char const& operator[](std::size_t i) const { TORRENT_ASSERT(i < siz e()); return m_begin[i]; }
char* begin() { return m_begin; } char* begin() { return m_begin; }
char const* begin() const { return m_begin; } char const* begin() const { return m_begin; }
char* end() { return m_end; } char* end() { return m_end; }
 End of changes. 10 change blocks. 
20 lines changed or deleted 23 lines changed or added


 chained_buffer.hpp   chained_buffer.hpp 
skipping to change at line 98 skipping to change at line 98
m_capacity -= b.size; m_capacity -= b.size;
bytes_to_pop -= b.used_size; bytes_to_pop -= b.used_size;
TORRENT_ASSERT(m_bytes >= 0); TORRENT_ASSERT(m_bytes >= 0);
TORRENT_ASSERT(m_capacity >= 0); TORRENT_ASSERT(m_capacity >= 0);
TORRENT_ASSERT(m_bytes <= m_capacity); TORRENT_ASSERT(m_bytes <= m_capacity);
m_vec.pop_front(); m_vec.pop_front();
} }
} }
template <class D> template <class D>
void append_buffer(char* buffer, int size, int used_size, D const& destructor) void append_buffer(char* buffer, int s, int used_size, D con st& destructor)
{ {
TORRENT_ASSERT(size >= used_size); TORRENT_ASSERT(s >= used_size);
buffer_t b; buffer_t b;
b.buf = buffer; b.buf = buffer;
b.size = size; b.size = s;
b.start = buffer; b.start = buffer;
b.used_size = used_size; b.used_size = used_size;
b.free = destructor; b.free = destructor;
m_vec.push_back(b); m_vec.push_back(b);
m_bytes += used_size; m_bytes += used_size;
m_capacity += size; m_capacity += s;
TORRENT_ASSERT(m_bytes <= m_capacity); TORRENT_ASSERT(m_bytes <= m_capacity);
} }
// returns the number of bytes available at the // returns the number of bytes available at the
// end of the last chained buffer. // end of the last chained buffer.
int space_in_last_buffer() int space_in_last_buffer()
{ {
if (m_vec.empty()) return 0; if (m_vec.empty()) return 0;
buffer_t& b = m_vec.back(); buffer_t& b = m_vec.back();
return b.size - b.used_size - (b.start - b.buf); return b.size - b.used_size - (b.start - b.buf);
} }
// tries to copy the given buffer to the end of the // tries to copy the given buffer to the end of the
// last chained buffer. If there's not enough room // last chained buffer. If there's not enough room
// it returns false // it returns false
bool append(char const* buf, int size) bool append(char const* buf, int s)
{ {
char* insert = allocate_appendix(size); char* insert = allocate_appendix(s);
if (insert == 0) return false; if (insert == 0) return false;
std::memcpy(insert, buf, size); std::memcpy(insert, buf, s);
return true; return true;
} }
// tries to allocate memory from the end // tries to allocate memory from the end
// of the last buffer. If there isn't // of the last buffer. If there isn't
// enough room, returns 0 // enough room, returns 0
char* allocate_appendix(int size) char* allocate_appendix(int s)
{ {
if (m_vec.empty()) return 0; if (m_vec.empty()) return 0;
buffer_t& b = m_vec.back(); buffer_t& b = m_vec.back();
char* insert = b.start + b.used_size; char* insert = b.start + b.used_size;
if (insert + size > b.buf + b.size) return 0; if (insert + s > b.buf + b.size) return 0;
b.used_size += size; b.used_size += s;
m_bytes += size; m_bytes += s;
TORRENT_ASSERT(m_bytes <= m_capacity); TORRENT_ASSERT(m_bytes <= m_capacity);
return insert; return insert;
} }
std::list<asio::const_buffer> const& build_iovec(int to_send ) std::list<asio::const_buffer> const& build_iovec(int to_send )
{ {
m_tmp_vec.clear(); m_tmp_vec.clear();
for (std::list<buffer_t>::iterator i = m_vec.begin() for (std::list<buffer_t>::iterator i = m_vec.begin()
, end(m_vec.end()); to_send > 0 && i != end; ++i) , end(m_vec.end()); to_send > 0 && i != end; ++i)
 End of changes. 9 change blocks. 
11 lines changed or deleted 11 lines changed or added


 closest_nodes.hpp   closest_nodes.hpp 
skipping to change at line 60 skipping to change at line 60
// -------- closest nodes ----------- // -------- closest nodes -----------
class closest_nodes : public traversal_algorithm class closest_nodes : public traversal_algorithm
{ {
public: public:
typedef boost::function< typedef boost::function<
void(std::vector<node_entry> const&) void(std::vector<node_entry> const&)
> done_callback; > done_callback;
static void initiate( closest_nodes(
node_id target node_impl& node
, int branch_factor , node_id target
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback , done_callback const& callback
); );
virtual char const* name() const { return "closest nodes"; }
private: private:
void done(); void done();
void invoke(node_id const& id, udp::endpoint addr); void invoke(node_id const& id, udp::endpoint addr);
closest_nodes(
node_id target
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
done_callback m_done_callback; done_callback m_done_callback;
}; };
class closest_nodes_observer : public observer class closest_nodes_observer : public observer
{ {
public: public:
closest_nodes_observer( closest_nodes_observer(
boost::intrusive_ptr<traversal_algorithm> const& algorithm boost::intrusive_ptr<traversal_algorithm> const& algorithm
, node_id self , node_id self)
, node_id target)
: observer(algorithm->allocator()) : observer(algorithm->allocator())
, m_algorithm(algorithm) , m_algorithm(algorithm)
, m_target(target)
, m_self(self) , m_self(self)
{} {}
~closest_nodes_observer(); ~closest_nodes_observer();
void send(msg& p) void send(msg& p)
{ {
p.info_hash = m_target; p.info_hash = m_algorithm->target();
} }
void timeout(); void timeout();
void reply(msg const&); void reply(msg const&);
void abort() { m_algorithm = 0; } void abort() { m_algorithm = 0; }
private: private:
boost::intrusive_ptr<traversal_algorithm> m_algorithm; boost::intrusive_ptr<traversal_algorithm> m_algorithm;
node_id const m_target;
node_id const m_self; node_id const m_self;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // CLOSEST_NODES_050323_HPP #endif // CLOSEST_NODES_050323_HPP
 End of changes. 7 change blocks. 
20 lines changed or deleted 7 lines changed or added


 config.hpp   config.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_CONFIG_HPP_INCLUDED #ifndef TORRENT_CONFIG_HPP_INCLUDED
#define TORRENT_CONFIG_HPP_INCLUDED #define TORRENT_CONFIG_HPP_INCLUDED
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/version.hpp> #include <boost/version.hpp>
#include <stdio.h> // for snprintf
#if defined(__GNUC__) && __GNUC__ >= 4 #ifndef WIN32
#define __STDC_FORMAT_MACROS
#include <inttypes.h>
#endif
#define TORRENT_DEPRECATED __attribute__ ((deprecated)) #ifndef PRId64
#ifdef _WIN32
#define PRId64 "I64d"
#else
#define PRId64 "lld"
#endif
#endif
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED) // ======= GCC =========
# define TORRENT_EXPORT __attribute__ ((visibility("default")))
#if defined __GNUC__
# define TORRENT_DEPRECATED __attribute__ ((deprecated))
// GCC pre 4.0 did not have support for the visibility attribute
# if __GNUC__ >= 4
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
# define TORRENT_EXPORT __attribute__ ((visibility("default")))
# else
# define TORRENT_EXPORT
# endif
# else # else
# define TORRENT_EXPORT # define TORRENT_EXPORT
# endif # endif
#elif defined(__GNUC__) // ======= SUNPRO =========
# define TORRENT_EXPORT #elif defined __SUNPRO_CC
#elif defined(BOOST_MSVC) # if __SUNPRO_CC >= 0x550
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
# define TORRENT_EXPORT __global
# else
# define TORRENT_EXPORT
# endif
# else
# define TORRENT_EXPORT
# endif
// ======= MSVC =========
#elif defined BOOST_MSVC
#pragma warning(disable: 4258) #pragma warning(disable: 4258)
#pragma warning(disable: 4251)
# if defined(TORRENT_BUILDING_SHARED) # if defined(TORRENT_BUILDING_SHARED)
# define TORRENT_EXPORT __declspec(dllexport) # define TORRENT_EXPORT __declspec(dllexport)
# elif defined(TORRENT_LINKING_SHARED) # elif defined(TORRENT_LINKING_SHARED)
# define TORRENT_EXPORT __declspec(dllimport) # define TORRENT_EXPORT __declspec(dllimport)
# else # else
# define TORRENT_EXPORT # define TORRENT_EXPORT
# endif # endif
#define TORRENT_DEPRECATED_PREFIX __declspec(deprecated)
// ======= GENERIC COMPILER =========
#else #else
# define TORRENT_EXPORT # define TORRENT_EXPORT
#endif #endif
#ifndef TORRENT_DEPRECATED_PREFIX
#define TORRENT_DEPRECATED_PREFIX
#endif
#ifndef TORRENT_DEPRECATED #ifndef TORRENT_DEPRECATED
#define TORRENT_DEPRECATED #define TORRENT_DEPRECATED
#endif #endif
// set up defines for target environments // set up defines for target environments
#if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __Net BSD__ \ #if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __Net BSD__ \
|| defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \ || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \
|| defined __FreeBSD_kernel__ || defined __FreeBSD_kernel__
#define TORRENT_BSD #define TORRENT_BSD
#define TORRENT_HAS_FALLOCATE 0
#elif defined __linux__ #elif defined __linux__
#define TORRENT_LINUX #define TORRENT_LINUX
#elif defined __MINGW32__ #elif defined __MINGW32__
#define TORRENT_MINGW #define TORRENT_MINGW
#define TORRENT_WINDOWS #define TORRENT_WINDOWS
#define TORRENT_HAS_FALLOCATE 0
#elif defined WIN32 #elif defined WIN32
#define TORRENT_WINDOWS #define TORRENT_WINDOWS
#define TORRENT_HAS_FALLOCATE 0
#elif defined sun || defined __sun #elif defined sun || defined __sun
#define TORRENT_SOLARIS #define TORRENT_SOLARIS
#define TORRENT_COMPLETE_TYPES_REQUIRED 1 #define TORRENT_COMPLETE_TYPES_REQUIRED 1
#else #else
#warning unknown OS, assuming BSD #warning unknown OS, assuming BSD
#define TORRENT_BSD #define TORRENT_BSD
#endif #endif
#define TORRENT_USE_IPV6 1
#define TORRENT_USE_MLOCK 1
#define TORRENT_USE_READV 1
#define TORRENT_USE_WRITEV 1
#define TORRENT_USE_IOSTREAM 1
#if defined TORRENT_BSD || defined TORRENT_LINUX || defined TORRENT_SOLARIS #if defined TORRENT_BSD || defined TORRENT_LINUX || defined TORRENT_SOLARIS
#define TORRENT_USE_RLIMIT 1 #define TORRENT_USE_RLIMIT 1
#else #else
#define TORRENT_USE_RLIMIT 0 #define TORRENT_USE_RLIMIT 0
#endif #endif
#ifndef TORRENT_HAS_FALLOCATE
#define TORRENT_HAS_FALLOCATE 1
#endif
// should wpath or path be used? // should wpath or path be used?
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY \ #if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY \
&& BOOST_VERSION >= 103400 && defined WIN32 && !defined TORRENT_MING W && BOOST_VERSION >= 103400 && !defined __APPLE__ && !defined TORRENT _MINGW
#define TORRENT_USE_WPATH 1 #define TORRENT_USE_WPATH 1
#else #else
#define TORRENT_USE_WPATH 0 #define TORRENT_USE_WPATH 0
#endif #endif
// set this to 1 to disable all floating point operations
// (disables some float-dependent APIs)
#define TORRENT_NO_FPU 0
// make sure NAME_MAX is defined
#ifndef NAME_MAX
#ifdef MAXPATH
#define NAME_MAX MAXPATH
#else
// this is the maximum number of characters in a
// path element / filename on windows
#define NAME_MAX 255
#endif // MAXPATH
#endif // NAME_MAX
#if defined TORRENT_WINDOWS && !defined TORRENT_MINGW
#pragma warning(disable:4251) // class X needs to have dll-interface to be
used by clients of class Y
#include <stdarg.h>
// '_vsnprintf': This function or variable may be unsafe
#pragma warning(disable:4996)
inline int snprintf(char* buf, int len, char const* fmt, ...)
{
va_list lp;
va_start(lp, fmt);
int ret = _vsnprintf(buf, len, fmt, lp);
va_end(lp);
if (ret < 0) { buf[len-1] = 0; ret = len-1; }
return ret;
}
#define strtoll _strtoi64
#else
#include <limits.h>
#endif
#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defi
ned (TORRENT_UPNP_LOGGING)
#define TORRENT_UPNP_LOGGING
#endif
#if !TORRENT_USE_WPATH && defined TORRENT_LINUX
// libiconv presence, not implemented yet
#define TORRENT_USE_LOCALE_FILENAMES 1
#else
#define TORRENT_USE_LOCALE_FILENAMES 0
#endif
#if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# define TORRENT_READ_HANDLER_MAX_SIZE 256
#endif
#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE)
# define TORRENT_WRITE_HANDLER_MAX_SIZE 256
#endif
#if defined _MSC_VER && _MSC_VER <= 1200
#define for if (false) {} else for
#endif
// determine what timer implementation we can use
#if defined(__MACH__)
#define TORRENT_USE_ABSOLUTE_TIME 1
#elif defined(_WIN32)
#define TORRENT_USE_QUERY_PERFORMANCE_TIMER 1
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#define TORRENT_USE_CLOCK_GETTIME 1
#else
#define TORRENT_USE_BOOST_DATE_TIME 1
#endif
#endif // TORRENT_CONFIG_HPP_INCLUDED #endif // TORRENT_CONFIG_HPP_INCLUDED
 End of changes. 17 change blocks. 
8 lines changed or deleted 138 lines changed or added


 connection_queue.hpp   connection_queue.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_CONNECTION_QUEUE #ifndef TORRENT_CONNECTION_QUEUE
#define TORRENT_CONNECTION_QUEUE #define TORRENT_CONNECTION_QUEUE
#include <list> #include <list>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/thread/recursive_mutex.hpp> #include <boost/thread/mutex.hpp>
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#ifdef TORRENT_CONNECTION_LOGGING #ifdef TORRENT_CONNECTION_LOGGING
#include <fstream> #include <fstream>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
class connection_queue : public boost::noncopyable class TORRENT_EXPORT connection_queue : public boost::noncopyable
{ {
public: public:
connection_queue(io_service& ios); connection_queue(io_service& ios);
// if there are no free slots, returns the negative // if there are no free slots, returns the negative
// number of queued up connections // number of queued up connections
int free_slots() const; int free_slots() const;
void enqueue(boost::function<void(int)> const& on_connect void enqueue(boost::function<void(int)> const& on_connect
, boost::function<void()> const& on_timeout , boost::function<void()> const& on_timeout
skipping to change at line 74 skipping to change at line 74
int limit() const; int limit() const;
void close(); void close();
int size() const { return m_queue.size(); } int size() const { return m_queue.size(); }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
private: private:
void try_connect(); typedef boost::mutex mutex_t;
void try_connect(mutex_t::scoped_lock& l);
void on_timeout(error_code const& e); void on_timeout(error_code const& e);
void on_try_connect();
struct entry struct entry
{ {
entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {} entry(): connecting(false), ticket(0), expires(max_time()), priority(0) {}
// called when the connection is initiated // called when the connection is initiated
boost::function<void(int)> on_connect; boost::function<void(int)> on_connect;
// called if done hasn't been called within the timeout // called if done hasn't been called within the timeout
boost::function<void()> on_timeout; boost::function<void()> on_timeout;
bool connecting; bool connecting;
int ticket; int ticket;
skipping to change at line 101 skipping to change at line 104
std::list<entry> m_queue; std::list<entry> m_queue;
// the next ticket id a connection will be given // the next ticket id a connection will be given
int m_next_ticket; int m_next_ticket;
int m_num_connecting; int m_num_connecting;
int m_half_open_limit; int m_half_open_limit;
bool m_abort; bool m_abort;
deadline_timer m_timer; deadline_timer m_timer;
typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool m_in_timeout_function; bool m_in_timeout_function;
#endif #endif
#ifdef TORRENT_CONNECTION_LOGGING #ifdef TORRENT_CONNECTION_LOGGING
std::ofstream m_log; std::ofstream m_log;
#endif #endif
}; };
 End of changes. 5 change blocks. 
4 lines changed or deleted 6 lines changed or added


 create_torrent.hpp   create_torrent.hpp 
skipping to change at line 43 skipping to change at line 43
#ifndef TORRENT_CREATE_TORRENT_HPP_INCLUDED #ifndef TORRENT_CREATE_TORRENT_HPP_INCLUDED
#define TORRENT_CREATE_TORRENT_HPP_INCLUDED #define TORRENT_CREATE_TORRENT_HPP_INCLUDED
#include "libtorrent/bencode.hpp" #include "libtorrent/bencode.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/file_storage.hpp" #include "libtorrent/file_storage.hpp"
#include "libtorrent/file_pool.hpp" #include "libtorrent/file_pool.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp" #include "libtorrent/hasher.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/allocator.hpp"
#include <vector> #include <vector>
#include <string> #include <string>
#include <utility> #include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include <boost/config.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace pt = boost::posix_time; namespace pt = boost::posix_time;
class torrent_info;
struct TORRENT_EXPORT create_torrent struct TORRENT_EXPORT create_torrent
{ {
create_torrent(file_storage& fs, int piece_size); enum {
create_torrent(file_storage& fs); optimize = 1
, merkle = 2
, modification_time = 4
, symlinks = 8
};
create_torrent(file_storage& fs, int piece_size = 0
, int pad_file_limit = -1, int flags = optimize);
create_torrent(torrent_info const& ti);
entry generate() const; entry generate() const;
file_storage const& files() const { return m_files; } file_storage const& files() const { return m_files; }
void set_comment(char const* str); void set_comment(char const* str);
void set_creator(char const* str); void set_creator(char const* str);
void set_hash(int index, sha1_hash const& h); void set_hash(int index, sha1_hash const& h);
void add_url_seed(std::string const& url); void add_url_seed(std::string const& url);
void add_node(std::pair<std::string, int> const& node); void add_node(std::pair<std::string, int> const& node);
void add_tracker(std::string const& url, int tier = 0); void add_tracker(std::string const& url, int tier = 0);
void set_priv(bool p) { m_private = p; } void set_priv(bool p) { m_private = p; }
int num_pieces() const { return m_files.num_pieces(); } int num_pieces() const { return m_files.num_pieces(); }
int piece_length() const { return m_files.piece_length(); } int piece_length() const { return m_files.piece_length(); }
int piece_size(int i) const { return m_files.piece_size(i); } int piece_size(int i) const { return m_files.piece_size(i); }
bool priv() const { return m_private; } bool priv() const { return m_private; }
private: private:
file_storage& m_files; file_storage& m_files;
// if m_info_dict is initialized, it is
// used instead of m_files to generate
// the info dictionary
entry m_info_dict;
// the urls to the trackers // the urls to the trackers
typedef std::pair<std::string, int> announce_entry; typedef std::pair<std::string, int> announce_entry;
std::vector<announce_entry> m_urls; std::vector<announce_entry> m_urls;
std::vector<std::string> m_url_seeds; std::vector<std::string> m_url_seeds;
std::vector<sha1_hash> m_piece_hash; std::vector<sha1_hash> m_piece_hash;
// dht nodes to add to the routing table/bootstrap from // dht nodes to add to the routing table/bootstrap from
skipping to change at line 127 skipping to change at line 143
// an optional string naming the software used // an optional string naming the software used
// to create the torrent file // to create the torrent file
std::string m_created_by; std::string m_created_by;
// this is used when creating a torrent. If there's // this is used when creating a torrent. If there's
// only one file there are cases where it's impossible // only one file there are cases where it's impossible
// to know if it should be written as a multifile torrent // to know if it should be written as a multifile torrent
// or not. e.g. test/test there's one file and one director y // or not. e.g. test/test there's one file and one director y
// and they have the same name. // and they have the same name.
bool m_multifile; bool m_multifile:1;
// this is true if the torrent is private. i.e., is should n ot // this is true if the torrent is private. i.e., is should n ot
// be announced on the dht // be announced on the dht
bool m_private; bool m_private:1;
// if set to one, a merkle torrent will be generated
bool m_merkle_torrent:1;
// if set, include the 'mtime' modification time in the
// torrent file
bool m_include_mtime:1;
// if set, symbolic links are declared as such in
// the torrent file. The full data of the pointed-to
// file is still included
bool m_include_symlinks:1;
}; };
namespace detail namespace detail
{ {
inline bool default_pred(boost::filesystem::path const&) { r eturn true; } inline bool default_pred(boost::filesystem::path const&) { r eturn true; }
#if TORRENT_USE_WPATH
inline bool wdefault_pred(boost::filesystem::wpath const&) {
return true; }
#endif
inline bool ignore_subdir(std::string const& leaf)
{ return leaf == ".." || leaf == "."; }
inline bool ignore_subdir(std::wstring const& leaf)
{ return leaf == L".." || leaf == L"."; }
inline void nop(int i) {} inline void nop(int i) {}
template <class Pred> int TORRENT_EXPORT get_file_attributes(boost::filesystem::pa
void add_files_impl(file_storage& fs, boost::filesystem::pat th const& p);
h const& p #if TORRENT_USE_WPATH
, boost::filesystem::path const& l, Pred pred) int TORRENT_EXPORT get_file_attributes(boost::filesystem::wp
ath const& p);
#endif
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem:
:path const& p);
#if TORRENT_USE_WPATH
std::time_t TORRENT_EXPORT get_file_mtime(boost::filesystem:
:wpath const& p);
#endif
fs::path TORRENT_EXPORT get_symlink_path(boost::filesystem::
path const& p);
#if TORRENT_USE_WPATH
fs::path TORRENT_EXPORT get_symlink_path(boost::filesystem::
wpath const& p);
#endif
template <class Pred, class Str, class PathTraits>
void add_files_impl(file_storage& fs, boost::filesystem::bas
ic_path<Str, PathTraits> const& p
, boost::filesystem::basic_path<Str, PathTraits> con
st& l, Pred pred)
{ {
using boost::filesystem::path; using boost::filesystem::basic_path;
using boost::filesystem::directory_iterator; using boost::filesystem::basic_directory_iterator;
if (!pred(l)) return; basic_path<Str, PathTraits> f(p / l);
path f(p / l); if (!pred(f)) return;
if (is_directory(f)) if (is_directory(f))
{ {
for (directory_iterator i(f), end; i != end; ++i) for (basic_directory_iterator<basic_path<Str , PathTraits> > i(f), end; i != end; ++i)
{ {
#if BOOST_VERSION < 103600 #if BOOST_VERSION < 103600
std::string leaf = i->path().leaf(); Str const& leaf = i->path().leaf();
#else #else
std::string leaf = i->path().filenam e(); Str const& leaf = i->path().filename ();
#endif #endif
if (leaf == ".." || leaf == ".") con tinue; if (ignore_subdir(leaf)) continue;
add_files_impl(fs, p, l / leaf, pred ); add_files_impl(fs, p, l / leaf, pred );
} }
} }
else else
{ {
fs.add_file(l, file_size(f)); int file_flags = get_file_attributes(f);
std::time_t mtime = get_file_mtime(f);
//Masking all bits to check if the file is a
symlink
if(file_flags & file_storage::attribute_syml
ink)
{
fs::path sym_path = get_symlink_path
(f);
fs.add_file(l, 0 ,file_flags, mtime,
sym_path);
}
else
{
fs.add_file(l, file_size(f), file_fl
ags, mtime);
}
} }
} }
} }
// path versions
template <class Pred> template <class Pred>
void add_files(file_storage& fs, boost::filesystem::path const& file , Pred p) void add_files(file_storage& fs, boost::filesystem::path const& file , Pred p)
{ {
using boost::filesystem::path;
boost::filesystem::path f = file; boost::filesystem::path f = file;
#if BOOST_VERSION < 103600 #if BOOST_VERSION < 103600
if (f.leaf() == ".") f = f.branch_path(); if (f.leaf() == ".") f = f.branch_path();
detail::add_files_impl(fs, complete(f).branch_path(), f.leaf (), p); detail::add_files_impl(fs, complete(f).branch_path(), path(f .leaf()), p);
#else #else
if (f.filename() == ".") f = f.parent_path(); if (f.filename() == ".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), f.file name(), p); detail::add_files_impl(fs, complete(f).parent_path(), path(f .filename()), p);
#endif #endif
} }
inline void add_files(file_storage& fs, boost::filesystem::path cons t& file) inline void add_files(file_storage& fs, boost::filesystem::path cons t& file)
{ {
using boost::filesystem::path;
boost::filesystem::path f = file; boost::filesystem::path f = file;
#if BOOST_VERSION < 103600 #if BOOST_VERSION < 103600
if (f.leaf() == ".") f = f.branch_path(); if (f.leaf() == ".") f = f.branch_path();
detail::add_files_impl(fs, complete(f).branch_path(), f.leaf (), detail::default_pred); detail::add_files_impl(fs, complete(f).branch_path(), path(f .leaf()), detail::default_pred);
#else #else
if (f.filename() == ".") f = f.parent_path(); if (f.filename() == ".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), f.file name(), detail::default_pred); detail::add_files_impl(fs, complete(f).parent_path(), path(f .filename()), detail::default_pred);
#endif #endif
} }
struct piece_holder
{
piece_holder(int bytes): m_piece(page_aligned_allocator::mal
loc(bytes)) {}
~piece_holder() { page_aligned_allocator::free(m_piece); }
char* bytes() { return m_piece; }
private:
char* m_piece;
};
template <class Fun> template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::path con st& p, Fun f void set_piece_hashes(create_torrent& t, boost::filesystem::path con st& p, Fun f
, error_code& ec) , error_code& ec)
{ {
file_pool fp; file_pool fp;
boost::scoped_ptr<storage_interface> st( boost::scoped_ptr<storage_interface> st(
default_storage_constructor(const_cast<file_storage& >(t.files()), 0, p, fp)); default_storage_constructor(const_cast<file_storage& >(t.files()), 0, p, fp));
// calculate the hash for all pieces // calculate the hash for all pieces
int num = t.num_pieces(); int num = t.num_pieces();
std::vector<char> buf(t.piece_length()); piece_holder buf(t.piece_length());
for (int i = 0; i < num; ++i) for (int i = 0; i < num; ++i)
{ {
// read hits the disk and will block. Progress shoul d // read hits the disk and will block. Progress shoul d
// be updated in between reads // be updated in between reads
st->read(&buf[0], i, 0, t.piece_size(i)); st->read(buf.bytes(), i, 0, t.piece_size(i));
if (st->error()) if (st->error())
{ {
ec = st->error(); ec = st->error();
return; return;
} }
hasher h(&buf[0], t.piece_size(i)); hasher h(buf.bytes(), t.piece_size(i));
t.set_hash(i, h.final()); t.set_hash(i, h.final());
f(i); f(i);
} }
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
template <class Fun> template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::path con st& p, Fun f) void set_piece_hashes(create_torrent& t, boost::filesystem::path con st& p, Fun f)
{ {
error_code ec; error_code ec;
skipping to change at line 241 skipping to change at line 317
error_code ec; error_code ec;
set_piece_hashes(t, p, detail::nop, ec); set_piece_hashes(t, p, detail::nop, ec);
if (ec) throw libtorrent_exception(ec); if (ec) throw libtorrent_exception(ec);
} }
#endif #endif
inline void set_piece_hashes(create_torrent& t, boost::filesystem::p ath const& p, error_code& ec) inline void set_piece_hashes(create_torrent& t, boost::filesystem::p ath const& p, error_code& ec)
{ {
set_piece_hashes(t, p, detail::nop, ec); set_piece_hashes(t, p, detail::nop, ec);
} }
#if TORRENT_USE_WPATH
// wpath versions
template <class Pred>
void add_files(file_storage& fs, boost::filesystem::wpath const& fil
e, Pred p)
{
using boost::filesystem::wpath;
wpath f = file;
#if BOOST_VERSION < 103600
if (f.leaf() == L".") f = f.branch_path();
detail::add_files_impl(fs, complete(f).branch_path(), wpath(
f.leaf()), p);
#else
if (f.filename() == L".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), wpath(
f.filename()), p);
#endif
}
inline void add_files(file_storage& fs, boost::filesystem::wpath con
st& file)
{
using boost::filesystem::wpath;
wpath f = file;
#if BOOST_VERSION < 103600
if (f.leaf() == L".") f = f.branch_path();
detail::add_files_impl(fs, complete(f).branch_path(), wpath(
f.leaf()), detail::wdefault_pred);
#else
if (f.filename() == L".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), wpath(
f.filename()), detail::wdefault_pred);
#endif
}
template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::wpath co
nst& p, Fun f
, error_code& ec)
{
file_pool fp;
std::string utf8;
wchar_utf8(p.string(), utf8);
boost::scoped_ptr<storage_interface> st(
default_storage_constructor(const_cast<file_storage&
>(t.files()), 0, utf8, fp));
// calculate the hash for all pieces
int num = t.num_pieces();
std::vector<char> buf(t.piece_length());
for (int i = 0; i < num; ++i)
{
// read hits the disk and will block. Progress shoul
d
// be updated in between reads
st->read(&buf[0], i, 0, t.piece_size(i));
if (st->error())
{
ec = st->error();
return;
}
hasher h(&buf[0], t.piece_size(i));
t.set_hash(i, h.final());
f(i);
}
}
#ifndef BOOST_NO_EXCEPTIONS
template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::wpath co
nst& p, Fun f)
{
error_code ec;
set_piece_hashes(t, p, f, ec);
if (ec) throw libtorrent_exception(ec);
}
inline void set_piece_hashes(create_torrent& t, boost::filesystem::w
path const& p)
{
error_code ec;
set_piece_hashes(t, p, detail::nop, ec);
if (ec) throw libtorrent_exception(ec);
}
#endif
inline void set_piece_hashes(create_torrent& t, boost::filesystem::w
path const& p, error_code& ec)
{
set_piece_hashes(t, p, detail::nop, ec);
}
#endif // TORRENT_USE_WPATH
} }
#endif #endif
 End of changes. 28 change blocks. 
25 lines changed or deleted 211 lines changed or added


 dht_tracker.hpp   dht_tracker.hpp 
skipping to change at line 44 skipping to change at line 44
#ifndef TORRENT_DHT_TRACKER #ifndef TORRENT_DHT_TRACKER
#define TORRENT_DHT_TRACKER #define TORRENT_DHT_TRACKER
#include <fstream> #include <fstream>
#include <set> #include <set>
#include <numeric> #include <numeric>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include "libtorrent/kademlia/node.hpp" #include "libtorrent/kademlia/node.hpp"
#include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/kademlia/traversal_algorithm.hpp" #include "libtorrent/kademlia/traversal_algorithm.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/session_status.hpp" #include "libtorrent/session_status.hpp"
#include "libtorrent/udp_socket.hpp" #include "libtorrent/udp_socket.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
namespace libtorrent
{
namespace aux { struct session_impl; }
struct lazy_entry;
}
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(dht_tracker); TORRENT_DECLARE_LOG(dht_tracker);
#endif #endif
struct dht_tracker; struct dht_tracker;
TORRENT_EXPORT void intrusive_ptr_add_ref(dht_tracker const*); TORRENT_EXPORT void intrusive_ptr_add_ref(dht_tracker const*);
TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*); TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*);
struct dht_tracker struct dht_tracker
{ {
friend void intrusive_ptr_add_ref(dht_tracker const*); friend void intrusive_ptr_add_ref(dht_tracker const*);
friend void intrusive_ptr_release(dht_tracker const*); friend void intrusive_ptr_release(dht_tracker const*);
dht_tracker(udp_socket& sock, dht_settings const& settings dht_tracker(libtorrent::aux::session_impl& ses, rate_limited
, entry const* state); _udp_socket& sock
, dht_settings const& settings, entry const* state =
0);
void start(entry const& bootstrap); void start(entry const& bootstrap);
void stop(); void stop();
void add_node(udp::endpoint node); void add_node(udp::endpoint node);
void add_node(std::pair<std::string, int> const& node); void add_node(std::pair<std::string, int> const& node);
void add_router_node(udp::endpoint const& node); void add_router_node(udp::endpoint const& node);
entry state() const; entry state() const;
void announce(sha1_hash const& ih, int listen_port void announce(sha1_hash const& ih, int listen_port
, boost::function<void(std::vector<tcp::endpoint> co , boost::function<void(std::vector<tcp::endpoint> co
nst& nst&)> f);
, sha1_hash const&)> f);
void dht_status(session_status& s); void dht_status(session_status& s);
void network_stats(int& sent, int& received);
// translate bittorrent kademlia message into the generic ka demlia message // translate bittorrent kademlia message into the generic ka demlia message
// used by the library // used by the library
void on_receive(udp::endpoint const& ep, char const* pkt, in t size); void on_receive(udp::endpoint const& ep, char const* pkt, in t size);
void on_unreachable(udp::endpoint const& ep); void on_unreachable(udp::endpoint const& ep);
private: private:
boost::intrusive_ptr<dht_tracker> self() boost::intrusive_ptr<dht_tracker> self()
{ return boost::intrusive_ptr<dht_tracker>(this); } { return boost::intrusive_ptr<dht_tracker>(this); }
skipping to change at line 113 skipping to change at line 118
, udp::resolver::iterator host); , udp::resolver::iterator host);
void on_router_name_lookup(error_code const& e void on_router_name_lookup(error_code const& e
, udp::resolver::iterator host); , udp::resolver::iterator host);
void connection_timeout(error_code const& e); void connection_timeout(error_code const& e);
void refresh_timeout(error_code const& e); void refresh_timeout(error_code const& e);
void tick(error_code const& e); void tick(error_code const& e);
void on_bootstrap(); void on_bootstrap();
void send_packet(msg const& m); void send_packet(msg const& m);
void incoming_error(char const* msg, lazy_entry const& e, ud
p::endpoint const& ep);
node_impl m_dht; node_impl m_dht;
udp_socket& m_sock; libtorrent::aux::session_impl& m_ses;
rate_limited_udp_socket& m_sock;
std::vector<char> m_send_buf; std::vector<char> m_send_buf;
ptime m_last_new_key; ptime m_last_new_key;
deadline_timer m_timer; deadline_timer m_timer;
deadline_timer m_connection_timer; deadline_timer m_connection_timer;
deadline_timer m_refresh_timer; deadline_timer m_refresh_timer;
dht_settings const& m_settings; dht_settings const& m_settings;
int m_refresh_bucket; int m_refresh_bucket;
// The mutex is used to abort the dht node // The mutex is used to abort the dht node
// it's only used to set m_abort to true // it's only used to set m_abort to true
typedef boost::mutex mutex_t; typedef boost::mutex mutex_t;
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
bool m_abort; bool m_abort;
// used to resolve hostnames for nodes // used to resolve hostnames for nodes
udp::resolver m_host_resolver; udp::resolver m_host_resolver;
// sent and received bytes since queried last time
int m_sent_bytes;
int m_received_bytes;
// used to ignore abusive dht nodes // used to ignore abusive dht nodes
struct node_ban_entry struct node_ban_entry
{ {
node_ban_entry(): count(0) {} node_ban_entry(): count(0) {}
udp::endpoint src; address src;
ptime limit; ptime limit;
int count; int count;
}; };
enum { num_ban_nodes = 20 }; enum { num_ban_nodes = 20 };
node_ban_entry m_ban_nodes[num_ban_nodes]; node_ban_entry m_ban_nodes[num_ban_nodes];
// reference counter for intrusive_ptr // reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs; mutable boost::detail::atomic_count m_refs;
skipping to change at line 160 skipping to change at line 172
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
int m_replies_sent[5]; int m_replies_sent[5];
int m_queries_received[5]; int m_queries_received[5];
int m_replies_bytes_sent[5]; int m_replies_bytes_sent[5];
int m_queries_bytes_received[5]; int m_queries_bytes_received[5];
int m_counter; int m_counter;
int m_announces; int m_announces;
int m_failed_announces; int m_failed_announces;
int m_total_message_input; int m_total_message_input;
int m_az_message_input;
int m_ut_message_input; int m_ut_message_input;
int m_lt_message_input; int m_lt_message_input;
int m_mp_message_input; int m_mp_message_input;
int m_gr_message_input; int m_gr_message_input;
int m_mo_message_input; int m_mo_message_input;
int m_total_in_bytes; int m_total_in_bytes;
int m_total_out_bytes; int m_total_out_bytes;
int m_queries_out_bytes; int m_queries_out_bytes;
 End of changes. 10 change blocks. 
8 lines changed or deleted 24 lines changed or added


 disk_buffer_holder.hpp   disk_buffer_holder.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED #ifndef TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED
#define TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED #define TORRENT_DISK_BUFFER_HOLDER_HPP_INCLUDED
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp"
#include <algorithm>
namespace libtorrent namespace libtorrent
{ {
namespace aux { struct session_impl; } namespace aux { struct session_impl; }
struct disk_io_thread; struct disk_buffer_pool;
struct TORRENT_EXPORT disk_buffer_holder struct TORRENT_EXPORT disk_buffer_holder
{ {
disk_buffer_holder(aux::session_impl& ses, char* buf); disk_buffer_holder(aux::session_impl& ses, char* buf);
disk_buffer_holder(disk_io_thread& iothread, char* buf); disk_buffer_holder(disk_buffer_pool& disk_pool, char* buf);
disk_buffer_holder(disk_buffer_pool& disk_pool, char* buf, i
nt num_blocks);
~disk_buffer_holder(); ~disk_buffer_holder();
char* release(); char* release();
char* get() const { return m_buf; } char* get() const { return m_buf; }
void reset(char* buf = 0); void reset(char* buf = 0, int num_blocks = 1);
void swap(disk_buffer_holder& h)
{
TORRENT_ASSERT(&h.m_disk_pool == &m_disk_pool);
std::swap(h.m_buf, m_buf);
}
typedef char* (disk_buffer_holder::*unspecified_bool_type)() ; typedef char* (disk_buffer_holder::*unspecified_bool_type)() ;
operator unspecified_bool_type() const operator unspecified_bool_type() const
{ return m_buf == 0? 0: &disk_buffer_holder::release; } { return m_buf == 0? 0: &disk_buffer_holder::release; }
private: private:
disk_io_thread& m_iothread; disk_buffer_pool& m_disk_pool;
char* m_buf; char* m_buf;
int m_num_blocks;
}; };
} }
#endif #endif
 End of changes. 6 change blocks. 
4 lines changed or deleted 14 lines changed or added


 disk_io_thread.hpp   disk_io_thread.hpp 
skipping to change at line 36 skipping to change at line 36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_DISK_IO_THREAD #ifndef TORRENT_DISK_IO_THREAD
#define TORRENT_DISK_IO_THREAD #define TORRENT_DISK_IO_THREAD
#ifdef TORRENT_DISK_STATS #if defined TORRENT_DISK_STATS || defined TORRENT_STATS
#include <fstream> #include <fstream>
#endif #endif
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/allocator.hpp"
#include <boost/thread/thread.hpp> #include <boost/thread/thread.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/shared_array.hpp> #include <boost/shared_array.hpp>
#include <list> #include <list>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
#include <boost/pool/pool.hpp> #include <boost/pool/pool.hpp>
#endif #endif
#include "libtorrent/session_settings.hpp"
namespace libtorrent namespace libtorrent
{ {
struct cached_piece_info struct cached_piece_info
{ {
int piece; int piece;
std::vector<bool> blocks; std::vector<bool> blocks;
ptime last_use; ptime last_use;
enum kind_t { read_cache = 0, write_cache = 1 }; enum kind_t { read_cache = 0, write_cache = 1 };
kind_t kind; kind_t kind;
}; };
struct disk_io_job struct disk_io_job
skipping to change at line 92 skipping to change at line 93
, move_storage , move_storage
, release_files , release_files
, delete_files , delete_files
, check_fastresume , check_fastresume
, check_files , check_files
, save_resume_data , save_resume_data
, rename_file , rename_file
, abort_thread , abort_thread
, clear_read_cache , clear_read_cache
, abort_torrent , abort_torrent
, update_settings
, read_and_hash
}; };
action_t action; action_t action;
char* buffer; char* buffer;
int buffer_size; int buffer_size;
boost::intrusive_ptr<piece_manager> storage; boost::intrusive_ptr<piece_manager> storage;
// arguments used for read and write // arguments used for read and write
int piece, offset; int piece, offset;
// used for move_storage and rename_file. On errors, this is set // used for move_storage and rename_file. On errors, this is set
skipping to change at line 124 skipping to change at line 127
boost::shared_ptr<entry> resume_data; boost::shared_ptr<entry> resume_data;
// the error code from the file operation // the error code from the file operation
error_code error; error_code error;
// this is called when operation completes // this is called when operation completes
boost::function<void(int, disk_io_job const&)> callback; boost::function<void(int, disk_io_job const&)> callback;
}; };
// returns true if the fundamental operation
// of the given disk job is a read operation
bool is_read_operation(disk_io_job const& j);
// this is true if the buffer field in the disk_io_job
// points to a disk buffer
bool operation_has_buffer(disk_io_job const& j);
struct cache_status struct cache_status
{ {
cache_status() cache_status()
: blocks_written(0) : blocks_written(0)
, writes(0) , writes(0)
, blocks_read(0) , blocks_read(0)
, blocks_read_hit(0) , blocks_read_hit(0)
, reads(0) , reads(0)
, cache_size(0) , cache_size(0)
, read_cache_size(0) , read_cache_size(0)
, total_used_buffers(0)
{} {}
// the number of 16kB blocks written // the number of 16kB blocks written
size_type blocks_written; size_type blocks_written;
// the number of write operations used // the number of write operations used
size_type writes; size_type writes;
// (blocks_written - writes) / blocks_written represents the // (blocks_written - writes) / blocks_written represents the
// "cache hit" ratio in the write cache // "cache hit" ratio in the write cache
// the number of blocks read // the number of blocks read
// the number of blocks passed back to the bittorrent engine // the number of blocks passed back to the bittorrent engine
size_type blocks_read; size_type blocks_read;
// the number of blocks that was just copied from the read c ache // the number of blocks that was just copied from the read c ache
size_type blocks_read_hit; size_type blocks_read_hit;
// the number of read operations used // the number of read operations used
size_type reads; size_type reads;
mutable size_type queued_bytes;
// the number of blocks in the cache (both read and write) // the number of blocks in the cache (both read and write)
int cache_size; int cache_size;
// the number of blocks in the cache used for read cache // the number of blocks in the cache used for read cache
int read_cache_size; int read_cache_size;
// the total number of blocks that are currently in use
// this includes send and receive buffers
mutable int total_used_buffers;
}; };
// this is a singleton consisting of the thread and a queue struct TORRENT_EXPORT disk_buffer_pool : boost::noncopyable
// of disk io jobs
struct disk_io_thread : boost::noncopyable
{ {
disk_io_thread(io_service& ios, int block_size = 16 * 1024); disk_buffer_pool(int block_size);
~disk_io_thread(); #ifdef TORRENT_DEBUG
~disk_buffer_pool();
#endif
#if defined TORRENT_DEBUG || defined TORRENT_DISK_STATS
bool is_disk_buffer(char* buffer
, boost::mutex::scoped_lock& l) const;
bool is_disk_buffer(char* buffer) const;
#endif
char* allocate_buffer(char const* category);
void free_buffer(char* buf);
char* allocate_buffers(int blocks, char const* category);
void free_buffers(char* buf, int blocks);
int block_size() const { return m_block_size; }
#ifdef TORRENT_STATS #ifdef TORRENT_STATS
int disk_allocations() const int disk_allocations() const
{ return m_allocations; } { return m_allocations; }
#endif #endif
#ifdef TORRENT_DISK_STATS
std::ofstream m_disk_access_log;
#endif
void release_memory();
int in_use() const { return m_in_use; }
protected:
// number of bytes per block. The BitTorrent
// protocol defines the block size to 16 KiB.
const int m_block_size;
// number of disk buffers currently allocated
int m_in_use;
session_settings m_settings;
private:
// this only protects the pool allocator
typedef boost::mutex mutex_t;
mutable mutex_t m_pool_mutex;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// memory pool for read and write operations
// and disk cache
boost::pool<page_aligned_allocator> m_pool;
#endif
#if defined TORRENT_DISK_STATS || defined TORRENT_STATS
int m_allocations;
#endif
#ifdef TORRENT_DISK_STATS
public:
void rename_buffer(char* buf, char const* category);
protected:
std::map<std::string, int> m_categories;
std::map<char*, std::string> m_buf_to_category;
std::ofstream m_log;
private:
#endif
#ifdef TORRENT_DEBUG
int m_magic;
#endif
};
// this is a singleton consisting of the thread and a queue
// of disk io jobs
struct TORRENT_EXPORT disk_io_thread : disk_buffer_pool
{
disk_io_thread(io_service& ios
, boost::function<void()> const& queue_callback
, file_pool& fp
, int block_size = 16 * 1024);
~disk_io_thread();
void join(); void join();
// aborts read operations // aborts read operations
void stop(boost::intrusive_ptr<piece_manager> s); void stop(boost::intrusive_ptr<piece_manager> s);
void add_job(disk_io_job const& j void add_job(disk_io_job const& j
, boost::function<void(int, disk_io_job const&)> con st& f , boost::function<void(int, disk_io_job const&)> con st& f
= boost::function<void(int, disk_io_job const&)>()); = boost::function<void(int, disk_io_job const&)>());
// keep track of the number of bytes in the job queue // keep track of the number of bytes in the job queue
// at any given time. i.e. the sum of all buffer_size. // at any given time. i.e. the sum of all buffer_size.
// this is used to slow down the download global download // this is used to slow down the download global download
// speed when the queue buffer size is too big. // speed when the queue buffer size is too big.
size_type queue_buffer_size() const size_type queue_buffer_size() const;
{ return m_queue_buffer_size; }
void get_cache_info(sha1_hash const& ih void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const; , std::vector<cached_piece_info>& ret) const;
cache_status status() const; cache_status status() const;
void set_cache_size(int s);
void set_cache_expiry(int ex);
void operator()(); void operator()();
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool is_disk_buffer(char* buffer) const;
#endif
char* allocate_buffer();
void free_buffer(char* buf);
#ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
private: struct cached_block_entry
{
cached_block_entry(): buf(0) {}
// the buffer pointer (this is a disk_pool buffer)
// or 0
char* buf;
// callback for when this block is flushed to disk
boost::function<void(int, disk_io_job const&)> callb
ack;
};
struct cached_piece_entry struct cached_piece_entry
{ {
int piece; int piece;
// storage this piece belongs to // storage this piece belongs to
boost::intrusive_ptr<piece_manager> storage; boost::intrusive_ptr<piece_manager> storage;
// the last time a block was writting to this piece // the last time a block was writting to this piece
ptime last_use; ptime last_use;
// the number of blocks in the cache for this piece // the number of blocks in the cache for this piece
int num_blocks; int num_blocks;
// the pointers to the block data // the pointers to the block data
boost::shared_array<char*> blocks; boost::shared_array<cached_block_entry> blocks;
}; };
typedef boost::recursive_mutex mutex_t; typedef boost::recursive_mutex mutex_t;
// TODO: turn this into a multi-index list
// sorted by piece and last use time
typedef std::list<cached_piece_entry> cache_t; typedef std::list<cached_piece_entry> cache_t;
private:
bool test_error(disk_io_job& j); bool test_error(disk_io_job& j);
void post_callback(boost::function<void(int, disk_io_job con st&)> const& handler void post_callback(boost::function<void(int, disk_io_job con st&)> const& handler
, disk_io_job const& j, int ret); , disk_io_job const& j, int ret);
// cache operations // cache operations
cache_t::iterator find_cached_piece( cache_t::iterator find_cached_piece(
cache_t& cache, disk_io_job const& j cache_t& cache, disk_io_job const& j
, mutex_t::scoped_lock& l); , mutex_t::scoped_lock& l);
bool is_cache_hit(cache_t::iterator p
, disk_io_job const& j, mutex_t::scoped_lock& l);
int copy_from_piece(cache_t::iterator p, bool& hit
, disk_io_job const& j, mutex_t::scoped_lock& l);
// write cache operations // write cache operations
void flush_oldest_piece(mutex_t::scoped_lock& l); enum options_t { dont_flush_write_blocks = 1, ignore_cache_s
ize = 2 };
int flush_cache_blocks(mutex_t::scoped_lock& l
, int blocks, cache_t::iterator ignore
, int options = 0);
void flush_expired_pieces(); void flush_expired_pieces();
void flush_and_remove(cache_t::iterator i, mutex_t::scoped_l int flush_and_remove(cache_t::iterator i, mutex_t::scoped_lo
ock& l); ck& l);
void flush(cache_t::iterator i, mutex_t::scoped_lock& l); int flush_contiguous_blocks(disk_io_thread::cache_t::iterato
int cache_block(disk_io_job& j, mutex_t::scoped_lock& l); r e
, mutex_t::scoped_lock& l, int lower_limit = 0);
int flush_range(cache_t::iterator i, int start, int end, mut
ex_t::scoped_lock& l);
int cache_block(disk_io_job& j
, boost::function<void(int,disk_io_job const&)>& han
dler
, mutex_t::scoped_lock& l);
// read cache operations // read cache operations
bool clear_oldest_read_piece(cache_t::iterator ignore int clear_oldest_read_piece(int num_blocks, cache_t::iterato r ignore
, mutex_t::scoped_lock& l); , mutex_t::scoped_lock& l);
int read_into_piece(cached_piece_entry& p, int start_block, int read_into_piece(cached_piece_entry& p, int start_block
mutex_t::scoped_lock& l); , int options, int num_blocks, mutex_t::scoped_lock&
l);
int cache_read_block(disk_io_job const& j, mutex_t::scoped_l ock& l); int cache_read_block(disk_io_job const& j, mutex_t::scoped_l ock& l);
void free_piece(cached_piece_entry& p, mutex_t::scoped_lock& int cache_read_piece(disk_io_job const& j, mutex_t::scoped_l
l); ock& l);
bool make_room(int num_blocks int free_piece(cached_piece_entry& p, mutex_t::scoped_lock&
, cache_t::iterator ignore l);
, mutex_t::scoped_lock& l);
int try_read_from_cache(disk_io_job const& j); int try_read_from_cache(disk_io_job const& j);
int read_piece_from_cache_and_hash(disk_io_job const& j, sha 1_hash& h);
// this mutex only protects m_jobs, m_queue_buffer_size // this mutex only protects m_jobs, m_queue_buffer_size
// and m_abort // and m_abort
mutable mutex_t m_queue_mutex; mutable mutex_t m_queue_mutex;
boost::condition m_signal; boost::condition m_signal;
bool m_abort; bool m_abort;
bool m_waiting_to_shutdown;
std::list<disk_io_job> m_jobs; std::list<disk_io_job> m_jobs;
size_type m_queue_buffer_size; size_type m_queue_buffer_size;
ptime m_last_file_check;
// this protects the piece cache and related members // this protects the piece cache and related members
mutable mutex_t m_piece_mutex; mutable mutex_t m_piece_mutex;
// write cache // write cache
cache_t m_pieces; cache_t m_pieces;
// read cache // read cache
cache_t m_read_pieces; cache_t m_read_pieces;
// total number of blocks in use by both the read // total number of blocks in use by both the read
// and the write cache. This is not supposed to // and the write cache. This is not supposed to
// exceed m_cache_size // exceed m_cache_size
cache_status m_cache_stats; cache_status m_cache_stats;
// in (16kB) blocks
int m_cache_size;
// expiration time of cache entries in seconds
int m_cache_expiry;
// if set to true, each piece flush will allocate
// one piece worth of temporary memory on the heap
// and copy the block data into it, and then perform
// a single write operation from that buffer.
// if memory is constrained, that temporary buffer
// might is avoided by setting this to false.
// in case the allocation fails, the piece flush
// falls back to writing each block separately.
bool m_coalesce_writes;
bool m_coalesce_reads;
bool m_use_read_cache;
// this only protects the pool allocator
mutable mutex_t m_pool_mutex;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// memory pool for read and write operations
// and disk cache
boost::pool<> m_pool;
#endif
// number of bytes per block. The BitTorrent
// protocol defines the block size to 16 KiB.
int m_block_size;
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
std::ofstream m_log; std::ofstream m_log;
#endif #endif
#ifdef TORRENT_STATS
int m_allocations;
#endif
size_type m_writes;
size_type m_blocks_written;
io_service& m_ios; io_service& m_ios;
boost::function<void()> m_queue_callback;
// this keeps the io_service::run() call blocked from // this keeps the io_service::run() call blocked from
// returning. When shutting down, it's possible that // returning. When shutting down, it's possible that
// the event queue is drained before the disk_io_thread // the event queue is drained before the disk_io_thread
// has posted its last callback. When this happens, the // has posted its last callback. When this happens, the
// io_service will have a pending callback from the // io_service will have a pending callback from the
// disk_io_thread, but the event loop is not running. // disk_io_thread, but the event loop is not running.
// this means that the event is destructed after the // this means that the event is destructed after the
// disk_io_thread. If the event refers to a disk buffer // disk_io_thread. If the event refers to a disk buffer
// it will try to free it, but the buffer pool won't // it will try to free it, but the buffer pool won't
// exist anymore, and crash. This prevents that. // exist anymore, and crash. This prevents that.
boost::optional<asio::io_service::work> m_work; boost::optional<asio::io_service::work> m_work;
// reference to the file_pool which is a member of
// the session_impl object
file_pool& m_file_pool;
// thread for performing blocking disk io operations // thread for performing blocking disk io operations
boost::thread m_disk_io_thread; boost::thread m_disk_io_thread;
#ifdef TORRENT_DEBUG
int m_magic;
#endif
}; };
} }
#endif #endif
 End of changes. 33 change blocks. 
72 lines changed or deleted 152 lines changed or added


 entry.hpp   entry.hpp 
skipping to change at line 61 skipping to change at line 61
* are asking for, otherwise you will get an * are asking for, otherwise you will get an
* assertion failure. * assertion failure.
* When you default construct an entry, it is * When you default construct an entry, it is
* uninitialized. You can initialize it through the * uninitialized. You can initialize it through the
* assignment operator, copy-constructor or * assignment operator, copy-constructor or
* the constructor that takes a data_type enum. * the constructor that takes a data_type enum.
* *
* *
*/ */
#include <iosfwd>
#include <map> #include <map>
#include <list> #include <list>
#include <string> #include <string>
#include <stdexcept> #include <stdexcept>
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/error_code.hpp"
#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif
namespace libtorrent namespace libtorrent
{ {
struct lazy_entry;
struct TORRENT_EXPORT type_error: std::runtime_error struct TORRENT_EXPORT type_error: std::runtime_error
{ {
type_error(const char* error): std::runtime_error(error) {} type_error(const char* error): std::runtime_error(error) {}
}; };
namespace detail namespace detail
{ {
template<int v1, int v2> template<int v1, int v2>
struct max2 { enum { value = v1>v2?v1:v2 }; }; struct max2 { enum { value = v1>v2?v1:v2 }; };
skipping to change at line 142 skipping to change at line 147
entry(list_type const&); entry(list_type const&);
entry(integer_type const&); entry(integer_type const&);
entry(); entry();
entry(data_type t); entry(data_type t);
entry(entry const& e); entry(entry const& e);
~entry(); ~entry();
bool operator==(entry const& e) const; bool operator==(entry const& e) const;
void operator=(lazy_entry const&);
void operator=(entry const&); void operator=(entry const&);
void operator=(dictionary_type const&); void operator=(dictionary_type const&);
void operator=(string_type const&); void operator=(string_type const&);
void operator=(list_type const&); void operator=(list_type const&);
void operator=(integer_type const&); void operator=(integer_type const&);
integer_type& integer(); integer_type& integer();
const integer_type& integer() const; const integer_type& integer() const;
string_type& string(); string_type& string();
const string_type& string() const; const string_type& string() const;
skipping to change at line 172 skipping to change at line 178
entry& operator[](std::string const& key); entry& operator[](std::string const& key);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
const entry& operator[](char const* key) const; const entry& operator[](char const* key) const;
const entry& operator[](std::string const& key) const; const entry& operator[](std::string const& key) const;
#endif #endif
entry* find_key(char const* key); entry* find_key(char const* key);
entry const* find_key(char const* key) const; entry const* find_key(char const* key) const;
entry* find_key(std::string const& key); entry* find_key(std::string const& key);
entry const* find_key(std::string const& key) const; entry const* find_key(std::string const& key) const;
#if (defined TORRENT_VERBOSE_LOGGING || defined TORRENT_DEBUG) && TORRENT_U SE_IOSTREAM
void print(std::ostream& os, int indent = 0) const; void print(std::ostream& os, int indent = 0) const;
#endif
protected: protected:
void construct(data_type t); void construct(data_type t);
void copy(const entry& e); void copy(const entry& e);
void destruct(); void destruct();
private: private:
data_type m_type; data_type m_type;
skipping to change at line 220 skipping to change at line 228
// in debug mode this is set to false by bdecode // in debug mode this is set to false by bdecode
// to indicate that the program has not yet queried // to indicate that the program has not yet queried
// the type of this entry, and sould not assume // the type of this entry, and sould not assume
// that it has a certain type. This is asserted in // that it has a certain type. This is asserted in
// the accessor functions. This does not apply if // the accessor functions. This does not apply if
// exceptions are used. // exceptions are used.
mutable bool m_type_queried; mutable bool m_type_queried;
#endif #endif
}; };
#if defined TORRENT_DEBUG && TORRENT_USE_IOSTREAM
inline std::ostream& operator<<(std::ostream& os, const entry& e) inline std::ostream& operator<<(std::ostream& os, const entry& e)
{ {
e.print(os, 0); e.print(os, 0);
return os; return os;
} }
#endif
#ifndef BOOST_NO_EXCEPTIONS
inline void throw_type_error()
{
throw libtorrent_exception(error_code(errors::invalid_entry_
type
, get_libtorrent_category()));
}
#endif
inline entry::data_type entry::type() const inline entry::data_type entry::type() const
{ {
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
m_type_queried = true; m_type_queried = true;
#endif #endif
return m_type; return m_type;
} }
inline entry::~entry() { destruct(); } inline entry::~entry() { destruct(); }
skipping to change at line 246 skipping to change at line 264
inline void entry::operator=(const entry& e) inline void entry::operator=(const entry& e)
{ {
destruct(); destruct();
copy(e); copy(e);
} }
inline entry::integer_type& entry::integer() inline entry::integer_type& entry::integer()
{ {
if (m_type == undefined_t) construct(int_t); if (m_type == undefined_t) construct(int_t);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requeste d from entry"); if (m_type != int_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == int_t); TORRENT_ASSERT(m_type == int_t);
return *reinterpret_cast<integer_type*>(data); return *reinterpret_cast<integer_type*>(data);
} }
inline entry::integer_type const& entry::integer() const inline entry::integer_type const& entry::integer() const
{ {
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != int_t) throw type_error("invalid type requeste d from entry"); if (m_type != int_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == int_t); TORRENT_ASSERT(m_type == int_t);
return *reinterpret_cast<const integer_type*>(data); return *reinterpret_cast<const integer_type*>(data);
} }
inline entry::string_type& entry::string() inline entry::string_type& entry::string()
{ {
if (m_type == undefined_t) construct(string_t); if (m_type == undefined_t) construct(string_t);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type reque sted from entry"); if (m_type != string_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == string_t); TORRENT_ASSERT(m_type == string_t);
return *reinterpret_cast<string_type*>(data); return *reinterpret_cast<string_type*>(data);
} }
inline entry::string_type const& entry::string() const inline entry::string_type const& entry::string() const
{ {
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != string_t) throw type_error("invalid type reque sted from entry"); if (m_type != string_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == string_t); TORRENT_ASSERT(m_type == string_t);
return *reinterpret_cast<const string_type*>(data); return *reinterpret_cast<const string_type*>(data);
} }
inline entry::list_type& entry::list() inline entry::list_type& entry::list()
{ {
if (m_type == undefined_t) construct(list_t); if (m_type == undefined_t) construct(list_t);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type request ed from entry"); if (m_type != list_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == list_t); TORRENT_ASSERT(m_type == list_t);
return *reinterpret_cast<list_type*>(data); return *reinterpret_cast<list_type*>(data);
} }
inline entry::list_type const& entry::list() const inline entry::list_type const& entry::list() const
{ {
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != list_t) throw type_error("invalid type request ed from entry"); if (m_type != list_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == list_t); TORRENT_ASSERT(m_type == list_t);
return *reinterpret_cast<const list_type*>(data); return *reinterpret_cast<const list_type*>(data);
} }
inline entry::dictionary_type& entry::dict() inline entry::dictionary_type& entry::dict()
{ {
if (m_type == undefined_t) construct(dictionary_t); if (m_type == undefined_t) construct(dictionary_t);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type r equested from entry"); if (m_type != dictionary_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == dictionary_t); TORRENT_ASSERT(m_type == dictionary_t);
return *reinterpret_cast<dictionary_type*>(data); return *reinterpret_cast<dictionary_type*>(data);
} }
inline entry::dictionary_type const& entry::dict() const inline entry::dictionary_type const& entry::dict() const
{ {
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
if (m_type != dictionary_t) throw type_error("invalid type r equested from entry"); if (m_type != dictionary_t) throw_type_error();
#elif defined TORRENT_DEBUG #elif defined TORRENT_DEBUG
TORRENT_ASSERT(m_type_queried); TORRENT_ASSERT(m_type_queried);
#endif #endif
TORRENT_ASSERT(m_type == dictionary_t); TORRENT_ASSERT(m_type == dictionary_t);
return *reinterpret_cast<const dictionary_type*>(data); return *reinterpret_cast<const dictionary_type*>(data);
} }
} }
#endif // TORRENT_ENTRY_HPP_INCLUDED #endif // TORRENT_ENTRY_HPP_INCLUDED
 End of changes. 16 change blocks. 
9 lines changed or deleted 28 lines changed or added


 error_code.hpp   error_code.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_ERROR_CODE_HPP_INCLUDED #ifndef TORRENT_ERROR_CODE_HPP_INCLUDED
#define TORRENT_ERROR_CODE_HPP_INCLUDED #define TORRENT_ERROR_CODE_HPP_INCLUDED
#include <boost/version.hpp> #include <boost/version.hpp>
#include <boost/shared_ptr.hpp>
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/error_code.hpp> #include <asio/error_code.hpp>
#else #else
#include <boost/system/error_code.hpp> #include <boost/system/error_code.hpp>
#endif #endif
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include <boost/shared_ptr.hpp>
#include <string>
namespace libtorrent namespace libtorrent
{ {
namespace errors namespace errors
{ {
enum error_code_enum enum error_code_enum
{ {
no_error = 0, no_error = 0,
file_collision file_collision,
failed_hash_check,
torrent_is_no_dict,
torrent_missing_info,
torrent_info_no_dict,
torrent_missing_piece_length,
torrent_missing_name,
torrent_invalid_name,
torrent_invalid_length,
torrent_file_parse_failed,
torrent_missing_pieces,
torrent_invalid_hashes,
too_many_pieces_in_torrent,
invalid_swarm_metadata,
invalid_bencoding,
no_files_in_torrent,
invalid_escaped_string,
session_is_closing,
duplicate_torrent,
invalid_torrent_handle,
invalid_entry_type,
missing_info_hash_in_uri,
file_too_short,
unsupported_url_protocol,
url_parse_error,
peer_sent_empty_piece,
parse_failed,
invalid_file_tag,
missing_info_hash,
mismatching_info_hash,
invalid_hostname,
invalid_port,
port_blocked,
expected_close_bracket_in_address,
destructing_torrent,
timed_out,
upload_upload_connection,
uninteresting_upload_peer,
invalid_info_hash,
torrent_paused,
invalid_have,
invalid_bitfield_size,
too_many_requests_when_choked,
invalid_piece,
no_memory,
torrent_aborted,
self_connection,
invalid_piece_size,
timed_out_no_interest,
timed_out_inactivity,
timed_out_no_handshake,
timed_out_no_request,
invalid_choke,
invalid_unchoke,
invalid_interested,
invalid_not_interested,
invalid_request,
invalid_hash_list,
invalid_hash_piece,
invalid_cancel,
invalid_dht_port,
invalid_suggest,
invalid_have_all,
invalid_have_none,
invalid_reject,
invalid_allow_fast,
invalid_extended,
invalid_message,
sync_hash_not_found,
invalid_encryption_constant,
no_plaintext_mode,
no_rc4_mode,
unsupported_encryption_mode,
unsupported_encryption_mode_selected,
invalid_pad_size,
invalid_encrypt_handshake,
no_incoming_encrypted,
no_incoming_regular,
duplicate_peer_id,
torrent_removed,
packet_too_large,
reserved,
http_error,
missing_location,
invalid_redirection,
redirecting,
invalid_range,
no_content_length,
banned_by_ip_filter,
too_many_connections,
peer_banned,
stopping_torrent,
too_many_corrupt_pieces,
torrent_not_ready,
peer_not_constructed,
session_closing,
optimistic_disconnect,
torrent_finished,
no_router,
metadata_too_large,
invalid_metadata_request,
invalid_metadata_size,
invalid_metadata_offset,
invalid_metadata_message,
pex_message_too_large,
invalid_pex_message,
invalid_lt_tracker_message,
reserved108,
reserved109,
reserved110,
reserved111,
reserved112,
reserved113,
reserved114,
reserved115,
reserved116,
reserved117,
reserved118,
reserved119,
// natpmp errors
unsupported_protocol_version, // 120
natpmp_not_authorized,
network_failure,
no_resources,
unsupported_opcode,
reserved125,
reserved126,
reserved127,
reserved128,
reserved129,
// fastresume errors
missing_file_sizes, // 130
no_files_in_resume_data,
missing_pieces,
mismatching_number_of_files,
mismatching_file_size,
mismatching_file_timestamp,
not_a_dictionary,
invalid_blocks_per_piece,
missing_slots,
too_many_slots,
invalid_slot_list,
invalid_piece_index,
pieces_need_reorder,
reserved143,
reserved144,
reserved145,
reserved146,
reserved147,
reserved148,
reserved149,
// HTTP errors
http_parse_error, // 150
http_missing_location,
http_failed_decompress,
reserved153,
reserved154,
reserved155,
reserved156,
reserved157,
reserved158,
reserved159,
error_code_max
}; };
} }
}
#if BOOST_VERSION >= 103500
namespace boost { namespace system {
template<> struct is_error_code_enum<libtorrent::errors::error_code_
enum>
{ static const bool value = true; };
template<> struct is_error_condition_enum<libtorrent::errors::error_
code_enum>
{ static const bool value = true; };
} }
#endif
namespace libtorrent
{
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
typedef asio::error_code error_code; typedef asio::error_code error_code;
inline asio::error::error_category get_posix_category() { return asi o::error::system_category; } inline asio::error::error_category get_posix_category() { return asi o::error::system_category; }
inline asio::error::error_category get_system_category() { return as io::error::system_category; } inline asio::error::error_category get_system_category() { return as io::error::system_category; }
boost::system::error_category const& get_libtorrent_category()
{
static ::asio::error::error_category libtorrent_category(20)
;
return libtorrent_category;
}
#else #else
struct libtorrent_error_category : boost::system::error_category struct TORRENT_EXPORT libtorrent_error_category : boost::system::err or_category
{ {
virtual const char* name() const; virtual const char* name() const;
virtual std::string message(int ev) const; virtual std::string message(int ev) const;
virtual boost::system::error_condition default_error_conditi on(int ev) const virtual boost::system::error_condition default_error_conditi on(int ev) const
{ return boost::system::error_condition(ev, *this); } { return boost::system::error_condition(ev, *this); }
}; };
extern libtorrent_error_category libtorrent_category; inline boost::system::error_category& get_libtorrent_category()
{
static libtorrent_error_category libtorrent_category;
return libtorrent_category;
}
namespace errors
{
inline boost::system::error_code make_error_code(error_code_
enum e)
{
return boost::system::error_code(e, get_libtorrent_c
ategory());
}
}
using boost::system::error_code; using boost::system::error_code;
inline boost::system::error_category const& get_system_category() inline boost::system::error_category const& get_system_category()
{ return boost::system::get_system_category(); } { return boost::system::get_system_category(); }
inline boost::system::error_category const& get_posix_category() inline boost::system::error_category const& get_posix_category()
#if BOOST_VERSION < 103600 #if BOOST_VERSION < 103600
{ return boost::system::get_posix_category(); } { return boost::system::get_posix_category(); }
#else #else
{ return boost::system::get_generic_category(); } { return boost::system::get_generic_category(); }
#endif #endif // BOOST_VERSION < 103600
#endif #endif // BOOST_VERSION < 103500
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT libtorrent_exception: std::exception struct TORRENT_EXPORT libtorrent_exception: std::exception
{ {
libtorrent_exception(error_code const& s): m_error(s) {} libtorrent_exception(error_code const& s): m_error(s) {}
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
if (!m_msg) m_msg.reset(new std::string(m_error.mess age())); if (!m_msg) m_msg.reset(new std::string(m_error.mess age()));
return m_msg->c_str(); return m_msg->c_str();
} }
 End of changes. 8 change blocks. 
7 lines changed or deleted 217 lines changed or added


 escape_string.hpp   escape_string.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_ESCAPE_STRING_HPP_INCLUDED #ifndef TORRENT_ESCAPE_STRING_HPP_INCLUDED
#define TORRENT_ESCAPE_STRING_HPP_INCLUDED #define TORRENT_ESCAPE_STRING_HPP_INCLUDED
#include <string> #include <string>
#include <limits> #include <limits>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent namespace libtorrent
{ {
boost::array<char, 3 + std::numeric_limits<size_type>::digits10> TOR TORRENT_EXPORT boost::array<char, 3 + std::numeric_limits<size_type>
RENT_EXPORT to_string(size_type n); ::digits10> to_string(size_type n);
bool TORRENT_EXPORT is_digit(char c); TORRENT_EXPORT bool is_digit(char c);
bool TORRENT_EXPORT isprint(char c); TORRENT_EXPORT bool is_print(char c);
TORRENT_EXPORT bool is_space(char c);
TORRENT_EXPORT char to_lower(char c);
std::string TORRENT_EXPORT unescape_string(std::string const& s); TORRENT_EXPORT bool string_begins_no_case(char const* s1, char const
std::string TORRENT_EXPORT escape_string(const char* str, int len); * s2);
std::string TORRENT_EXPORT escape_path(const char* str, int len); TORRENT_EXPORT bool string_equal_no_case(char const* s1, char const*
s2);
TORRENT_EXPORT std::string unescape_string(std::string const& s, err
or_code& ec);
// replaces all disallowed URL characters by their %-encoding
TORRENT_EXPORT std::string escape_string(const char* str, int len);
// same as escape_string but does not encode '/'
TORRENT_EXPORT std::string escape_path(const char* str, int len);
// if the url does not appear to be encoded, and it contains illegal
url characters
// it will be encoded
TORRENT_EXPORT std::string maybe_url_encode(std::string const& url);
TORRENT_EXPORT bool need_encoding(char const* str, int len);
// encodes a string using the base64 scheme // encodes a string using the base64 scheme
TORRENT_EXPORT std::string base64encode(std::string const& s); TORRENT_EXPORT std::string base64encode(std::string const& s);
// encodes a string using the base32 scheme // encodes a string using the base32 scheme
TORRENT_EXPORT std::string base32encode(std::string const& s); TORRENT_EXPORT std::string base32encode(std::string const& s);
TORRENT_EXPORT std::string base32decode(std::string const& s); TORRENT_EXPORT std::string base32decode(std::string const& s);
TORRENT_EXPORT boost::optional<std::string> url_has_argument( TORRENT_EXPORT boost::optional<std::string> url_has_argument(
std::string const& url, std::string argument); std::string const& url, std::string argument, int* out_pos = 0);
TORRENT_EXPORT std::string read_until(char const*& str, char delim, char const* end);
TORRENT_EXPORT std::string to_hex(std::string const& s); TORRENT_EXPORT std::string to_hex(std::string const& s);
TORRENT_EXPORT bool is_hex(char const *in, int len);
TORRENT_EXPORT void to_hex(char const *in, int len, char* out);
TORRENT_EXPORT bool from_hex(char const *in, int len, char* out);
#if TORRENT_USE_WPATH
TORRENT_EXPORT std::wstring convert_to_wstring(std::string const& s)
;
#endif
#if defined TORRENT_WINDOWS || TORRENT_USE_LOCALE_FILENAMES
TORRENT_EXPORT std::string convert_to_native(std::string const& s);
#else
inline std::string const& convert_to_native(std::string const& s) {
return s; }
#endif
} }
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED #endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED
 End of changes. 6 change blocks. 
8 lines changed or deleted 42 lines changed or added


 file.hpp   file.hpp 
skipping to change at line 44 skipping to change at line 44
#define TORRENT_FILE_HPP_INCLUDED #define TORRENT_FILE_HPP_INCLUDED
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#ifdef WIN32
#include <windows.h>
#endif
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/error_code.hpp" #include "libtorrent/error_code.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#ifdef TORRENT_WINDOWS
// windows part
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winioctl.h>
#else
// posix part
#define _FILE_OFFSET_BITS 64
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600
#endif
#include <unistd.h>
#include <sys/uio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#endif
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
class TORRENT_EXPORT file: public boost::noncopyable class TORRENT_EXPORT file: public boost::noncopyable
{ {
public: public:
class seek_mode enum
{ {
friend class file; // when a file is opened with no_buffer
private: // file offsets have to be aligned to
seek_mode(int v): m_val(v) {} // pos_alignment() and buffer addresses
int m_val; // to buf_alignment() and read/write sizes
}; // to size_alignment()
read_only = 0,
write_only = 1,
read_write = 2,
rw_mask = read_only | write_only | read_write,
no_buffer = 4,
mode_mask = rw_mask | no_buffer,
sparse = 8,
static const seek_mode begin; attribute_hidden = 0x1000,
static const seek_mode end; attribute_executable = 0x2000,
attribute_mask = attribute_hidden | attribute_execut
able
};
class open_mode #ifdef TORRENT_WINDOWS
struct iovec_t
{ {
friend class file; void* iov_base;
public: size_t iov_len;
open_mode(): m_mask(0) {}
open_mode operator|(open_mode m) const
{ return open_mode(m.m_mask | m_mask); }
open_mode operator&(open_mode m) const
{ return open_mode(m.m_mask & m_mask); }
open_mode operator|=(open_mode m)
{
m_mask |= m.m_mask;
return *this;
}
bool operator==(open_mode m) const { return m_mask =
= m.m_mask; }
bool operator!=(open_mode m) const { return m_mask !
= m.m_mask; }
operator bool() const { return m_mask != 0; }
private:
open_mode(int val): m_mask(val) {}
int m_mask;
}; };
#else
typedef iovec iovec_t;
#endif
static const open_mode in; // use a typedef for the type of iovec_t::iov_base
static const open_mode out; // since it may differ
#ifdef TORRENT_SOLARIS
typedef char* iovec_base_t;
#else
typedef void* iovec_base_t;
#endif
file(); file();
file(fs::path const& p, open_mode m, error_code& ec); file(fs::path const& p, int m, error_code& ec);
~file(); ~file();
bool open(fs::path const& p, open_mode m, error_code& ec); bool open(fs::path const& p, int m, error_code& ec);
bool is_open() const; bool is_open() const;
void close(); void close();
bool set_size(size_type size, error_code& ec); bool set_size(size_type size, error_code& ec);
size_type write(const char*, size_type num_bytes, error_code int open_mode() const { return m_open_mode; }
& ec);
size_type read(char*, size_type num_bytes, error_code& ec);
size_type seek(size_type pos, seek_mode m, error_code& ec); // when opened in unbuffered mode, this is the
size_type tell(error_code& ec); // required alignment of file_offsets. i.e.
// any (file_offset & (pos_alignment()-1)) == 0
// is a precondition to read and write operations
int pos_alignment() const;
// when opened in unbuffered mode, this is the
// required alignment of buffer addresses
int buf_alignment() const;
// read/write buffer sizes needs to be aligned to
// this when in unbuffered mode
int size_alignment() const;
size_type writev(size_type file_offset, iovec_t const* bufs,
int num_bufs, error_code& ec);
size_type readv(size_type file_offset, iovec_t const* bufs,
int num_bufs, error_code& ec);
size_type get_size(error_code& ec) const;
// return the offset of the first byte that
// belongs to a data-region
size_type sparse_end(size_type start) const;
size_type phys_offset(size_type offset);
#ifdef TORRENT_WINDOWS
HANDLE native_handle() const { return m_file_handle; }
#else
int native_handle() const { return m_fd; }
#endif
private: private:
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
HANDLE m_file_handle; HANDLE m_file_handle;
#if TORRENT_USE_WPATH
std::wstring m_path;
#else
std::string m_path;
#endif
#else #else
int m_fd; int m_fd;
#endif #endif
#ifdef TORRENT_DEBUG #if defined TORRENT_WINDOWS || defined TORRENT_LINUX || defined TORRENT_DEB
open_mode m_open_mode; UG
static void init_file();
static int m_page_size;
#endif
int m_open_mode;
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX
mutable int m_sector_size;
#endif
#if defined TORRENT_WINDOWS
mutable int m_cluster_size;
#endif #endif
}; };
} }
#endif // TORRENT_FILE_HPP_INCLUDED #endif // TORRENT_FILE_HPP_INCLUDED
 End of changes. 16 change blocks. 
51 lines changed or deleted 108 lines changed or added


 file_pool.hpp   file_pool.hpp 
skipping to change at line 41 skipping to change at line 41
*/ */
#ifndef TORRENT_FILE_POOL_HPP #ifndef TORRENT_FILE_POOL_HPP
#define TORRENT_FILE_POOL_HPP #define TORRENT_FILE_POOL_HPP
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/file.hpp" #include "libtorrent/file.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
namespace libtorrent namespace libtorrent
{ {
using boost::multi_index::multi_index_container;
using boost::multi_index::ordered_non_unique;
using boost::multi_index::ordered_unique;
using boost::multi_index::indexed_by;
using boost::multi_index::member;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
struct TORRENT_EXPORT file_pool : boost::noncopyable struct TORRENT_EXPORT file_pool : boost::noncopyable
{ {
file_pool(int size = 40): m_size(size) {} file_pool(int size = 40): m_size(size), m_low_prio_io(true) {}
boost::shared_ptr<file> open_file(void* st, fs::path const& p boost::shared_ptr<file> open_file(void* st, fs::path const& p
, file::open_mode m, error_code& ec); , int m, error_code& ec);
void release(void* st); void release(void* st);
void release(fs::path const& p); void release(fs::path const& p);
void resize(int size); void resize(int size);
int size_limit() const { return m_size; }
void set_low_prio_io(bool b) { m_low_prio_io = b; }
private: private:
file_pool(file_pool const&);
void remove_oldest();
int m_size; int m_size;
bool m_low_prio_io;
struct lru_file_entry struct lru_file_entry
{ {
lru_file_entry(): last_use(time_now()) {} lru_file_entry(): last_use(time_now()) {}
mutable boost::shared_ptr<file> file_ptr; mutable boost::shared_ptr<file> file_ptr;
fs::path file_path;
void* key; void* key;
ptime last_use; ptime last_use;
file::open_mode mode; int mode;
}; };
typedef multi_index_container< typedef std::map<std::string, lru_file_entry> file_set;
lru_file_entry, indexed_by<
ordered_unique<member<lru_file_entry, fs::pa
th
, &lru_file_entry::file_path> >
, ordered_non_unique<member<lru_file_entry,
ptime
, &lru_file_entry::last_use> >
, ordered_non_unique<member<lru_file_entry,
void*
, &lru_file_entry::key> >
>
> file_set;
file_set m_files; file_set m_files;
boost::mutex m_mutex; boost::mutex m_mutex;
}; };
} }
#endif #endif
 End of changes. 10 change blocks. 
26 lines changed or deleted 11 lines changed or added


 file_storage.hpp   file_storage.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_FILE_STORAGE_HPP_INCLUDED #ifndef TORRENT_FILE_STORAGE_HPP_INCLUDED
#define TORRENT_FILE_STORAGE_HPP_INCLUDED #define TORRENT_FILE_STORAGE_HPP_INCLUDED
#include <string> #include <string>
#include <vector> #include <vector>
#include <ctime>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
skipping to change at line 59 skipping to change at line 60
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
struct TORRENT_EXPORT file_entry struct TORRENT_EXPORT file_entry
{ {
file_entry(): offset(0), size(0), file_base(0) {} file_entry(): offset(0), size(0), file_base(0)
, mtime(0), pad_file(false), hidden_attribute(false)
, executable_attribute(false)
, symlink_attribute(false)
{}
fs::path path; fs::path path;
size_type offset; // the offset of this file inside the torr ent size_type offset; // the offset of this file inside the torr ent
size_type size; // the size of this file size_type size; // the size of this file
// the offset in the file where the storage starts. // the offset in the file where the storage starts.
// This is always 0 unless parts of the torrent is // This is always 0 unless parts of the torrent is
// compressed into a single file, such as a so-called part f ile. // compressed into a single file, such as a so-called part f ile.
size_type file_base; size_type file_base;
std::time_t mtime;
bool pad_file:1;
bool hidden_attribute:1;
bool executable_attribute:1;
bool symlink_attribute:1;
fs::path symlink_path;
}; };
struct TORRENT_EXPORT file_slice struct TORRENT_EXPORT file_slice
{ {
int file_index; int file_index;
size_type offset; size_type offset;
size_type size; size_type size;
}; };
class TORRENT_EXPORT file_storage class TORRENT_EXPORT file_storage
{ {
friend class torrent_info; friend class torrent_info;
public: public:
file_storage(); file_storage();
~file_storage() {} ~file_storage() {}
bool is_valid() const { return m_piece_length > 0; } bool is_valid() const { return m_piece_length > 0; }
enum flags_t
{
pad_file = 1,
attribute_hidden = 2,
attribute_executable = 4,
attribute_symlink = 8
};
void add_file(file_entry const& e); void add_file(file_entry const& e);
void add_file(fs::path const& p, size_type size); void add_file(fs::path const& p, size_type size, int flags = 0, std::time_t mtime = 0, fs::path const& s_p = "");
void rename_file(int index, std::string const& new_filename) ; void rename_file(int index, std::string const& new_filename) ;
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
void add_file(fs::wpath const& p, size_type size, int flags
= 0, std::time_t mtime = 0, fs::path const& s_p = "");
void rename_file(int index, std::wstring const& new_filename
);
void set_name(std::wstring const& n);
#endif
std::vector<file_slice> map_block(int piece, size_type offse t std::vector<file_slice> map_block(int piece, size_type offse t
, int size) const; , int size) const;
peer_request map_file(int file, size_type offset, int size) const; peer_request map_file(int file, size_type offset, int size) const;
typedef std::vector<file_entry>::const_iterator iterator; typedef std::vector<file_entry>::const_iterator iterator;
typedef std::vector<file_entry>::const_reverse_iterator reve rse_iterator; typedef std::vector<file_entry>::const_reverse_iterator reve rse_iterator;
iterator file_at_offset(size_type offset) const; iterator file_at_offset(size_type offset) const;
iterator begin() const { return m_files.begin(); } iterator begin() const { return m_files.begin(); }
iterator end() const { return m_files.end(); } iterator end() const { return m_files.end(); }
skipping to change at line 131 skipping to change at line 156
void swap(file_storage& ti) void swap(file_storage& ti)
{ {
using std::swap; using std::swap;
swap(ti.m_piece_length, m_piece_length); swap(ti.m_piece_length, m_piece_length);
swap(ti.m_files, m_files); swap(ti.m_files, m_files);
swap(ti.m_total_size, m_total_size); swap(ti.m_total_size, m_total_size);
swap(ti.m_num_pieces, m_num_pieces); swap(ti.m_num_pieces, m_num_pieces);
swap(ti.m_name, m_name); swap(ti.m_name, m_name);
} }
// if pad_file_limit >= 0, files larger than
// that limit will be padded, default is to
// not add any padding
void optimize(int pad_file_limit = -1);
private: private:
int m_piece_length; int m_piece_length;
// the list of files that this torrent consists of // the list of files that this torrent consists of
std::vector<file_entry> m_files; std::vector<file_entry> m_files;
// the sum of all filesizes // the sum of all filesizes
size_type m_total_size; size_type m_total_size;
// the number of pieces in the torrent // the number of pieces in the torrent
 End of changes. 7 change blocks. 
2 lines changed or deleted 34 lines changed or added


 find_data.hpp   find_data.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef FIND_DATA_050323_HPP #ifndef FIND_DATA_050323_HPP
#define FIND_DATA_050323_HPP #define FIND_DATA_050323_HPP
#include <vector> #include <vector>
#include <map>
#include <libtorrent/kademlia/traversal_algorithm.hpp> #include <libtorrent/kademlia/traversal_algorithm.hpp>
#include <libtorrent/kademlia/node_id.hpp> #include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/routing_table.hpp> #include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp> #include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/observer.hpp> #include <libtorrent/kademlia/observer.hpp>
#include <libtorrent/kademlia/msg.hpp> #include <libtorrent/kademlia/msg.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
typedef std::vector<char> packet_t; typedef std::vector<char> packet_t;
class rpc_manager; class rpc_manager;
class node_impl;
// -------- find data ----------- // -------- find data -----------
class find_data : public traversal_algorithm class find_data : public traversal_algorithm
{ {
public: public:
typedef boost::function<void(msg const*)> done_callback; typedef boost::function<void(std::vector<tcp::endpoint> const&)> dat
a_callback;
static void initiate( typedef boost::function<void(std::vector<std::pair<node_entry, std::
node_id target string> > const&)> nodes_callback;
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
void got_data(msg const* m); void got_data(msg const* m);
void got_write_token(node_id const& n, std::string const& write_toke
n)
{ m_write_tokens[n] = write_token; }
find_data(node_impl& node, node_id target
, data_callback const& dcallback
, nodes_callback const& ncallback);
virtual char const* name() const { return "get_peers"; }
node_id const target() const { return m_target; }
private: private:
void done(); void done();
void invoke(node_id const& id, udp::endpoint addr); void invoke(node_id const& id, udp::endpoint addr);
find_data( data_callback m_data_callback;
node_id target nodes_callback m_nodes_callback;
, int branch_factor std::map<node_id, std::string> m_write_tokens;
, int max_results node_id const m_target;
, routing_table& table
, rpc_manager& rpc
, done_callback const& callback
);
done_callback m_done_callback;
boost::shared_ptr<packet_t> m_packet;
bool m_done; bool m_done;
}; };
class find_data_observer : public observer class find_data_observer : public observer
{ {
public: public:
find_data_observer( find_data_observer(
boost::intrusive_ptr<find_data> const& algorithm boost::intrusive_ptr<find_data> const& algorithm
, node_id self , node_id self)
, node_id target)
: observer(algorithm->allocator()) : observer(algorithm->allocator())
, m_algorithm(algorithm) , m_algorithm(algorithm)
, m_target(target)
, m_self(self) , m_self(self)
{} {}
~find_data_observer(); ~find_data_observer();
void send(msg& m) void send(msg& m)
{ {
m.reply = false; m.reply = false;
m.message_id = messages::get_peers; m.message_id = messages::get_peers;
m.info_hash = m_target; m.info_hash = m_algorithm->target();
} }
void timeout(); void timeout();
void reply(msg const&); void reply(msg const&);
void abort() { m_algorithm = 0; } void abort() { m_algorithm = 0; }
private: private:
boost::intrusive_ptr<find_data> m_algorithm; boost::intrusive_ptr<find_data> m_algorithm;
node_id const m_target;
node_id const m_self; node_id const m_self;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // FIND_DATA_050323_HPP #endif // FIND_DATA_050323_HPP
 End of changes. 10 change blocks. 
26 lines changed or deleted 23 lines changed or added


 fingerprint.hpp   fingerprint.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_FINGERPRINT_HPP_INCLUDED #ifndef TORRENT_FINGERPRINT_HPP_INCLUDED
#define TORRENT_FINGERPRINT_HPP_INCLUDED #define TORRENT_FINGERPRINT_HPP_INCLUDED
#include <string> #include <string>
#include <sstream> #include <cstdio>
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
struct fingerprint struct fingerprint
{ {
fingerprint(const char* id_string, int major, int minor, int revision, int tag) fingerprint(const char* id_string, int major, int minor, int revision, int tag)
: major_version(major) : major_version(major)
skipping to change at line 65 skipping to change at line 66
TORRENT_ASSERT(minor >= 0); TORRENT_ASSERT(minor >= 0);
TORRENT_ASSERT(revision >= 0); TORRENT_ASSERT(revision >= 0);
TORRENT_ASSERT(tag >= 0); TORRENT_ASSERT(tag >= 0);
TORRENT_ASSERT(std::strlen(id_string) == 2); TORRENT_ASSERT(std::strlen(id_string) == 2);
name[0] = id_string[0]; name[0] = id_string[0];
name[1] = id_string[1]; name[1] = id_string[1];
} }
std::string to_string() const std::string to_string() const
{ {
std::stringstream s; char s[100];
s << "-" << name[0] << name[1] snprintf(s, 100, "-%c%c%c%c%c%c-"
<< version_to_char(major_version) , name[0], name[1]
<< version_to_char(minor_version) , version_to_char(major_version)
<< version_to_char(revision_version) , version_to_char(minor_version)
<< version_to_char(tag_version) << "-"; , version_to_char(revision_version)
return s.str(); , version_to_char(tag_version));
return s;
} }
char name[2]; char name[2];
int major_version; int major_version;
int minor_version; int minor_version;
int revision_version; int revision_version;
int tag_version; int tag_version;
private: private:
 End of changes. 3 change blocks. 
8 lines changed or deleted 10 lines changed or added


 hasher.hpp   hasher.hpp 
skipping to change at line 98 skipping to change at line 98
public: public:
hasher() { SHA1_Init(&m_context); } hasher() { SHA1_Init(&m_context); }
hasher(const char* data, int len) hasher(const char* data, int len)
{ {
SHA1_Init(&m_context); SHA1_Init(&m_context);
TORRENT_ASSERT(data != 0); TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0); TORRENT_ASSERT(len > 0);
SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len); SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len);
} }
void update(std::string const& data) { update(&data[0], data .size()); }
void update(const char* data, int len) void update(const char* data, int len)
{ {
TORRENT_ASSERT(data != 0); TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0); TORRENT_ASSERT(len > 0);
SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len); SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len);
} }
sha1_hash final() sha1_hash final()
{ {
sha1_hash digest; sha1_hash digest;
 End of changes. 1 change blocks. 
0 lines changed or deleted 1 lines changed or added


 http_connection.hpp   http_connection.hpp 
skipping to change at line 62 skipping to change at line 62
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
#include "libtorrent/ssl_stream.hpp" #include "libtorrent/ssl_stream.hpp"
#include "libtorrent/variant_stream.hpp" #include "libtorrent/variant_stream.hpp"
#endif #endif
namespace libtorrent namespace libtorrent
{ {
struct http_connection; struct http_connection;
class connection_queue; class connection_queue;
struct ip_filter;
typedef boost::function<void(error_code const& typedef boost::function<void(error_code const&
, http_parser const&, char const* data, int size, http_connection&)> http_handler; , http_parser const&, char const* data, int size, http_connection&)> http_handler;
typedef boost::function<void(http_connection&)> http_connect_handler; typedef boost::function<void(http_connection&)> http_connect_handler;
// TODO: add bind interface typedef boost::function<void(http_connection&, std::list<tcp::endpoint>&)> http_filter_handler;
// when bottled, the last two arguments to the handler // when bottled, the last two arguments to the handler
// will always be 0 // will always be 0
struct http_connection : boost::enable_shared_from_this<http_connection>, b oost::noncopyable struct TORRENT_EXPORT http_connection : boost::enable_shared_from_this<http _connection>, boost::noncopyable
{ {
http_connection(io_service& ios, connection_queue& cc http_connection(io_service& ios, connection_queue& cc
, http_handler const& handler, bool bottled = true , http_handler const& handler, bool bottled = true
, http_connect_handler const& ch = http_connect_handler() , http_connect_handler const& ch = http_connect_handler()
, ip_filter const* ipf = 0) , http_filter_handler const& fh = http_filter_handler())
: m_sock(ios) : m_sock(ios)
, m_read_pos(0) , m_read_pos(0)
, m_resolver(ios) , m_resolver(ios)
, m_handler(handler) , m_handler(handler)
, m_connect_handler(ch) , m_connect_handler(ch)
, m_filter_handler(fh)
, m_timer(ios) , m_timer(ios)
, m_last_receive(time_now()) , m_last_receive(time_now())
, m_bottled(bottled) , m_bottled(bottled)
, m_called(false) , m_called(false)
, m_rate_limit(0) , m_rate_limit(0)
, m_download_quota(0) , m_download_quota(0)
, m_limiter_timer_active(false) , m_limiter_timer_active(false)
, m_limiter_timer(ios) , m_limiter_timer(ios)
, m_redirects(5) , m_redirects(5)
, m_connection_ticket(-1) , m_connection_ticket(-1)
, m_cc(cc) , m_cc(cc)
, m_ssl(false) , m_ssl(false)
, m_priority(0) , m_priority(0)
, m_abort(false) , m_abort(false)
, m_ip_filter(ipf)
{ {
TORRENT_ASSERT(!m_handler.empty()); TORRENT_ASSERT(!m_handler.empty());
} }
void rate_limit(int limit); void rate_limit(int limit);
int rate_limit() const int rate_limit() const
{ return m_rate_limit; } { return m_rate_limit; }
std::string sendbuffer; std::string sendbuffer;
skipping to change at line 127 skipping to change at line 126
, address const& bind_addr = address_v4::any()); , address const& bind_addr = address_v4::any());
void close(); void close();
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
variant_stream<socket_type, ssl_stream<socket_type> > const& socket( ) const { return m_sock; } variant_stream<socket_type, ssl_stream<socket_type> > const& socket( ) const { return m_sock; }
#else #else
socket_type const& socket() const { return m_sock; } socket_type const& socket() const { return m_sock; }
#endif #endif
std::list<tcp::endpoint> const& endpoints() const { return m_endpoin
ts; }
private: private:
void on_resolve(error_code const& e void on_resolve(error_code const& e
, tcp::resolver::iterator i); , tcp::resolver::iterator i);
void queue_connect(); void queue_connect();
void connect(int ticket, tcp::endpoint target_address); void connect(int ticket, tcp::endpoint target_address);
void on_connect_timeout(); void on_connect_timeout();
void on_connect(error_code const& e); void on_connect(error_code const& e);
void on_write(error_code const& e); void on_write(error_code const& e);
void on_read(error_code const& e, std::size_t bytes_transferred); void on_read(error_code const& e, std::size_t bytes_transferred);
skipping to change at line 154 skipping to change at line 155
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
variant_stream<socket_type, ssl_stream<socket_type> > m_sock; variant_stream<socket_type, ssl_stream<socket_type> > m_sock;
#else #else
socket_type m_sock; socket_type m_sock;
#endif #endif
int m_read_pos; int m_read_pos;
tcp::resolver m_resolver; tcp::resolver m_resolver;
http_parser m_parser; http_parser m_parser;
http_handler m_handler; http_handler m_handler;
http_connect_handler m_connect_handler; http_connect_handler m_connect_handler;
http_filter_handler m_filter_handler;
deadline_timer m_timer; deadline_timer m_timer;
time_duration m_timeout; time_duration m_timeout;
ptime m_last_receive; ptime m_last_receive;
// bottled means that the handler is called once, when // bottled means that the handler is called once, when
// everything is received (and buffered in memory). // everything is received (and buffered in memory).
// non bottled means that once the headers have been // non bottled means that once the headers have been
// received, data is streamed to the handler // received, data is streamed to the handler
bool m_bottled; bool m_bottled;
// set to true the first time the handler is called // set to true the first time the handler is called
bool m_called; bool m_called;
skipping to change at line 208 skipping to change at line 210
// the address to bind to. address_v4::any() // the address to bind to. address_v4::any()
// means do not bind // means do not bind
address m_bind_addr; address m_bind_addr;
// the priority we have in the connection queue. // the priority we have in the connection queue.
// 0 is normal, 1 is high // 0 is normal, 1 is high
int m_priority; int m_priority;
bool m_abort; bool m_abort;
ip_filter const* m_ip_filter;
}; };
} }
#endif #endif
 End of changes. 9 change blocks. 
7 lines changed or deleted 8 lines changed or added


 http_parser.hpp   http_parser.hpp 
skipping to change at line 46 skipping to change at line 46
#include <map> #include <map>
#include <string> #include <string>
#include <utility> #include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/lexical_cast.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp" #include "libtorrent/buffer.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
namespace libtorrent namespace libtorrent
{ {
class http_parser class TORRENT_EXPORT http_parser
{ {
public: public:
http_parser(); http_parser();
std::string const& header(char const* key) const std::string const& header(char const* key) const
{ {
static std::string empty; static std::string empty;
std::map<std::string, std::string>::const_iterator i std::map<std::string, std::string>::const_iterator i
= m_header.find(key); = m_header.find(key);
if (i == m_header.end()) return empty; if (i == m_header.end()) return empty;
return i->second; return i->second;
skipping to change at line 84 skipping to change at line 83
std::string const& method() const { return m_method; } std::string const& method() const { return m_method; }
std::string const& path() const { return m_path; } std::string const& path() const { return m_path; }
std::string const& message() const { return m_server_message ; } std::string const& message() const { return m_server_message ; }
buffer::const_interval get_body() const; buffer::const_interval get_body() const;
bool header_finished() const { return m_state == read_body; } bool header_finished() const { return m_state == read_body; }
bool finished() const { return m_finished; } bool finished() const { return m_finished; }
boost::tuple<int, int> incoming(buffer::const_interval recv_ buffer boost::tuple<int, int> incoming(buffer::const_interval recv_ buffer
, bool& error); , bool& error);
int body_start() const { return m_body_start_pos; } int body_start() const { return m_body_start_pos; }
size_type content_length() const { return m_content_length; } size_type content_length() const { return m_content_length; }
std::pair<size_type, size_type> content_range() const
{ return std::make_pair(m_range_start, m_range_end); }
void reset(); void reset();
std::map<std::string, std::string> const& headers() const { return m_header; } std::map<std::string, std::string> const& headers() const { return m_header; }
private: private:
int m_recv_pos; int m_recv_pos;
int m_status_code; int m_status_code;
std::string m_method; std::string m_method;
std::string m_path; std::string m_path;
std::string m_protocol; std::string m_protocol;
std::string m_server_message; std::string m_server_message;
size_type m_content_length; size_type m_content_length;
size_type m_range_start;
size_type m_range_end;
enum { read_status, read_header, read_body, error_state } m_ state; enum { read_status, read_header, read_body, error_state } m_ state;
std::map<std::string, std::string> m_header; std::map<std::string, std::string> m_header;
buffer::const_interval m_recv_buffer; buffer::const_interval m_recv_buffer;
int m_body_start_pos; int m_body_start_pos;
bool m_finished; bool m_finished;
}; };
 End of changes. 4 change blocks. 
2 lines changed or deleted 5 lines changed or added


 http_stream.hpp   http_stream.hpp 
skipping to change at line 72 skipping to change at line 72
{ {
m_remote_endpoint = endpoint; m_remote_endpoint = endpoint;
// the connect is split up in the following steps: // the connect is split up in the following steps:
// 1. resolve name of proxy server // 1. resolve name of proxy server
// 2. connect to proxy server // 2. connect to proxy server
// 3. send HTTP CONNECT method and possibly username+passwor d // 3. send HTTP CONNECT method and possibly username+passwor d
// 4. read CONNECT response // 4. read CONNECT response
// to avoid unnecessary copying of the handler, // to avoid unnecessary copying of the handler,
// store it in a shaed_ptr // store it in a shared_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler)) ; boost::shared_ptr<handler_type> h(new handler_type(handler)) ;
tcp::resolver::query q(m_hostname tcp::resolver::query q(m_hostname, to_string(m_port).elems);
, boost::lexical_cast<std::string>(m_port));
m_resolver.async_resolve(q, boost::bind( m_resolver.async_resolve(q, boost::bind(
&http_stream::name_lookup, this, _1, _2, h)); &http_stream::name_lookup, this, _1, _2, h));
} }
private: private:
void name_lookup(error_code const& e, tcp::resolver::iterator i void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h); , boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h); void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h); void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
 End of changes. 2 change blocks. 
3 lines changed or deleted 2 lines changed or added


 http_tracker_connection.hpp   http_tracker_connection.hpp 
skipping to change at line 48 skipping to change at line 48
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp"
#include "libtorrent/lazy_entry.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp" #include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
namespace libtorrent namespace libtorrent
{ {
struct http_connection; struct http_connection;
class entry; class entry;
class http_parser; class http_parser;
class connection_queue; class connection_queue;
struct session_settings; struct session_settings;
struct ip_filter; namespace aux { struct session_impl; }
class TORRENT_EXPORT http_tracker_connection class TORRENT_EXPORT http_tracker_connection
: public tracker_connection : public tracker_connection
{ {
friend class tracker_manager; friend class tracker_manager;
public: public:
http_tracker_connection( http_tracker_connection(
io_service& ios io_service& ios
, connection_queue& cc , connection_queue& cc
, tracker_manager& man , tracker_manager& man
, tracker_request const& req , tracker_request const& req
, address bind_infc
, boost::weak_ptr<request_callback> c , boost::weak_ptr<request_callback> c
, session_settings const& stn , aux::session_impl const& ses
, proxy_settings const& ps , proxy_settings const& ps
, std::string const& password = "" , std::string const& password = "");
, ip_filter const* ipf = 0);
void start(); void start();
void close(); void close();
private: private:
boost::intrusive_ptr<http_tracker_connection> self() boost::intrusive_ptr<http_tracker_connection> self()
{ return boost::intrusive_ptr<http_tracker_connection>(this) ; } { return boost::intrusive_ptr<http_tracker_connection>(this) ; }
void on_filter(http_connection& c, std::list<tcp::endpoint>&
endpoints);
void on_connect(http_connection& c);
void on_response(error_code const& ec, http_parser const& pa rser void on_response(error_code const& ec, http_parser const& pa rser
, char const* data, int size); , char const* data, int size);
virtual void on_timeout() {} virtual void on_timeout() {}
void parse(int status_code, const entry& e); void parse(int status_code, lazy_entry const& e);
bool extract_peer_info(const entry& e, peer_entry& ret); bool extract_peer_info(lazy_entry const& e, peer_entry& ret)
;
tracker_manager& m_man; tracker_manager& m_man;
boost::shared_ptr<http_connection> m_tracker_connection; boost::shared_ptr<http_connection> m_tracker_connection;
session_settings const& m_settings; aux::session_impl const& m_ses;
address m_bind_iface; address m_tracker_ip;
proxy_settings const& m_ps; proxy_settings const& m_ps;
connection_queue& m_cc; connection_queue& m_cc;
io_service& m_ios; io_service& m_ios;
ip_filter const* m_ip_filter;
}; };
} }
#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED #endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
 End of changes. 9 change blocks. 
10 lines changed or deleted 13 lines changed or added


 io.hpp   io.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_IO_HPP_INCLUDED #ifndef TORRENT_IO_HPP_INCLUDED
#define TORRENT_IO_HPP_INCLUDED #define TORRENT_IO_HPP_INCLUDED
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <string> #include <string>
#include <algorithm> // for copy
#include <cstring> // for memcpy
namespace libtorrent namespace libtorrent
{ {
namespace detail namespace detail
{ {
template <class T> struct type {}; template <class T> struct type {};
// reads an integer from a byte stream // reads an integer from a byte stream
// in big endian byte order and converts // in big endian byte order and converts
// it to native endianess // it to native endianess
skipping to change at line 139 skipping to change at line 141
template <class OutIt> template <class OutIt>
void write_uint8(boost::uint8_t val, OutIt& start) void write_uint8(boost::uint8_t val, OutIt& start)
{ write_impl(val, start); } { write_impl(val, start); }
template <class OutIt> template <class OutIt>
void write_int8(boost::int8_t val, OutIt& start) void write_int8(boost::int8_t val, OutIt& start)
{ write_impl(val, start); } { write_impl(val, start); }
inline void write_string(std::string const& str, char*& star t) inline void write_string(std::string const& str, char*& star t)
{ {
std::copy(str.begin(), str.end(), start); std::memcpy((void*)start, &str[0], str.size());
start += str.size(); start += str.size();
} }
template <class OutIt> template <class OutIt>
void write_string(std::string const& str, OutIt& start) void write_string(std::string const& str, OutIt& start)
{ {
std::copy(str.begin(), str.end(), start); std::copy(str.begin(), str.end(), start);
} }
} }
 End of changes. 2 change blocks. 
1 lines changed or deleted 3 lines changed or added


 ip_filter.hpp   ip_filter.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_IP_FILTER_HPP #ifndef TORRENT_IP_FILTER_HPP
#define TORRENT_IP_FILTER_HPP #define TORRENT_IP_FILTER_HPP
#include <set> #include <set>
#include <iostream>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
skipping to change at line 90 skipping to change at line 89
return zero; return zero;
} }
template<> template<>
inline boost::uint16_t zero<boost::uint16_t>() { return 0; } inline boost::uint16_t zero<boost::uint16_t>() { return 0; }
template<class Addr> template<class Addr>
Addr plus_one(Addr const& a) Addr plus_one(Addr const& a)
{ {
Addr tmp(a); Addr tmp(a);
typedef typename Addr::reverse_iterator iter; for (int i = tmp.size() - 1; i >= 0; --i)
for (iter i = tmp.rbegin()
, end(tmp.rend()); i != end; ++i)
{ {
if (*i < (std::numeric_limits<typename iter::value_t ype>::max)()) if (tmp[i] < (std::numeric_limits<typename Addr::val ue_type>::max)())
{ {
*i += 1; tmp[i] += 1;
break; break;
} }
*i = 0; tmp[i] = 0;
} }
return tmp; return tmp;
} }
inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; } inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; }
template<class Addr> template<class Addr>
Addr minus_one(Addr const& a) Addr minus_one(Addr const& a)
{ {
Addr tmp(a); Addr tmp(a);
typedef typename Addr::reverse_iterator iter; for (int i = tmp.size() - 1; i >= 0; --i)
for (iter i = tmp.rbegin()
, end(tmp.rend()); i != end; ++i)
{ {
if (*i > 0) if (tmp[i] > 0)
{ {
*i -= 1; tmp[i] -= 1;
break; break;
} }
*i = (std::numeric_limits<typename iter::value_type> ::max)(); tmp[i] = (std::numeric_limits<typename Addr::value_t ype>::max)();
} }
return tmp; return tmp;
} }
inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; } inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; }
template<class Addr> template<class Addr>
Addr max_addr() Addr max_addr()
{ {
Addr tmp; Addr tmp;
skipping to change at line 250 skipping to change at line 245
ret.push_back(r); ret.push_back(r);
} }
return ret; return ret;
} }
private: private:
struct range struct range
{ {
range(Addr addr, int access = 0): start(addr), acces s(access) {} range(Addr addr, int a = 0): start(addr), access(a) {}
bool operator<(range const& r) const bool operator<(range const& r) const
{ return start < r.start; } { return start < r.start; }
bool operator<(Addr const& a) const bool operator<(Addr const& a) const
{ return start < a; } { return start < a; }
Addr start; Addr start;
// the end of the range is implicit // the end of the range is implicit
// and given by the next entry in the set // and given by the next entry in the set
int access; int access;
}; };
typedef std::set<range> range_t; typedef std::set<range> range_t;
range_t m_access_list; range_t m_access_list;
}; };
} }
struct TORRENT_EXPORT ip_filter class TORRENT_EXPORT ip_filter
{ {
public:
enum access_flags enum access_flags
{ {
blocked = 1 blocked = 1
}; };
// both addresses MUST be of the same type (i.e. both must // both addresses MUST be of the same type (i.e. both must
// be either IPv4 or both must be IPv6) // be either IPv4 or both must be IPv6)
void add_rule(address first, address last, int flags); void add_rule(address first, address last, int flags);
int access(address const& addr) const; int access(address const& addr) const;
typedef boost::tuple<std::vector<ip_range<address_v4> > typedef boost::tuple<std::vector<ip_range<address_v4> >
, std::vector<ip_range<address_v6> > > filter_tuple_t; , std::vector<ip_range<address_v6> > > filter_tuple_t;
filter_tuple_t export_filter() const; filter_tuple_t export_filter() const;
// void print() const; // void print() const;
private: private:
detail::filter_impl<address_v4::bytes_type> m_filter4; detail::filter_impl<address_v4::bytes_type> m_filter4;
#if TORRENT_USE_IPV6
detail::filter_impl<address_v6::bytes_type> m_filter6; detail::filter_impl<address_v6::bytes_type> m_filter6;
#endif
}; };
class TORRENT_EXPORT port_filter class TORRENT_EXPORT port_filter
{ {
public: public:
enum access_flags enum access_flags
{ {
blocked = 1 blocked = 1
}; };
 End of changes. 14 change blocks. 
15 lines changed or deleted 14 lines changed or added


 lazy_entry.hpp   lazy_entry.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED #ifndef TORRENT_LAZY_ENTRY_HPP_INCLUDED
#define TORRENT_LAZY_ENTRY_HPP_INCLUDED #define TORRENT_LAZY_ENTRY_HPP_INCLUDED
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <iosfwd>
#include <string> #include <string>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#if TORRENT_USE_IOSTREAM
#include <iosfwd>
#endif
namespace libtorrent namespace libtorrent
{ {
struct lazy_entry; struct lazy_entry;
TORRENT_EXPORT char const* parse_int(char const* start, char const* end TORRENT_EXPORT char const* parse_int(char const* start, char const* end
, char delimiter, boost::int64_t& val); , char delimiter, boost::int64_t& val);
// return 0 = success // return 0 = success
TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000); TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end, lazy_entry& ret, int depth_limit = 1000);
struct lazy_dict_entry;
struct TORRENT_EXPORT lazy_entry struct TORRENT_EXPORT lazy_entry
{ {
enum entry_type_t enum entry_type_t
{ {
none_t, dict_t, list_t, string_t, int_t none_t, dict_t, list_t, string_t, int_t
}; };
lazy_entry() : m_type(none_t), m_begin(0), m_end(0) lazy_entry() : m_type(none_t), m_begin(0), m_end(0)
{ m_data.start = 0; } { m_data.start = 0; }
skipping to change at line 131 skipping to change at line 136
lazy_entry* dict_append(char const* name); lazy_entry* dict_append(char const* name);
lazy_entry* dict_find(char const* name); lazy_entry* dict_find(char const* name);
lazy_entry const* dict_find(char const* name) const lazy_entry const* dict_find(char const* name) const
{ return const_cast<lazy_entry*>(this)->dict_find(name); } { return const_cast<lazy_entry*>(this)->dict_find(name); }
std::string dict_find_string_value(char const* name) const; std::string dict_find_string_value(char const* name) const;
size_type dict_find_int_value(char const* name, size_type de fault_val = 0) const; size_type dict_find_int_value(char const* name, size_type de fault_val = 0) const;
lazy_entry const* dict_find_dict(char const* name) const; lazy_entry const* dict_find_dict(char const* name) const;
lazy_entry const* dict_find_list(char const* name) const; lazy_entry const* dict_find_list(char const* name) const;
lazy_entry const* dict_find_string(char const* name) const; lazy_entry const* dict_find_string(char const* name) const;
lazy_entry const* dict_find_int(char const* name) const;
std::pair<std::string, lazy_entry const*> dict_at(int i) con std::pair<std::string, lazy_entry const*> dict_at(int i) con
st st;
{
TORRENT_ASSERT(m_type == dict_t);
TORRENT_ASSERT(i < m_size);
std::pair<char const*, lazy_entry> const& e = m_data
.dict[i];
return std::make_pair(std::string(e.first, e.second.
m_begin - e.first), &e.second);
}
int dict_size() const int dict_size() const
{ {
TORRENT_ASSERT(m_type == dict_t); TORRENT_ASSERT(m_type == dict_t);
return m_size; return m_size;
} }
// list functions // list functions
// ============== // ==============
skipping to change at line 218 skipping to change at line 218
swap(m_capacity, e.m_capacity); swap(m_capacity, e.m_capacity);
swap(m_begin, e.m_begin); swap(m_begin, e.m_begin);
swap(m_end, e.m_end); swap(m_end, e.m_end);
} }
private: private:
entry_type_t m_type; entry_type_t m_type;
union data_t union data_t
{ {
std::pair<char const*, lazy_entry>* dict; lazy_dict_entry* dict;
lazy_entry* list; lazy_entry* list;
char const* start; char const* start;
} m_data; } m_data;
int m_size; // if list or dictionary, the number of items int m_size; // if list or dictionary, the number of items
int m_capacity; // if list or dictionary, allocated number o f items int m_capacity; // if list or dictionary, allocated number o f items
// used for dictionaries and lists to record the range // used for dictionaries and lists to record the range
// in the original buffer they are based on // in the original buffer they are based on
char const* m_begin; char const* m_begin;
char const* m_end; char const* m_end;
// non-copyable
lazy_entry(lazy_entry const&);
lazy_entry const& operator=(lazy_entry const&);
};
struct lazy_dict_entry
{
char const* name;
lazy_entry val;
}; };
TORRENT_EXPORT std::string print_entry(lazy_entry const& e);
#if TORRENT_USE_IOSTREAM
TORRENT_EXPORT std::ostream& operator<<(std::ostream& os, lazy_entry const& e); TORRENT_EXPORT std::ostream& operator<<(std::ostream& os, lazy_entry const& e);
#endif
} }
#endif #endif
 End of changes. 10 change blocks. 
12 lines changed or deleted 24 lines changed or added


 logger.hpp   logger.hpp 
skipping to change at line 46 skipping to change at line 46
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp"
#if TORRENT_USE_IOSTREAM
namespace libtorrent namespace libtorrent
{ {
struct torrent_plugin; struct torrent_plugin;
class torrent; class torrent;
boost::shared_ptr<torrent_plugin> create_logger_plugin(torrent*); boost::shared_ptr<torrent_plugin> create_logger_plugin(torrent*);
} }
#endif
#endif // TORRENT_LOGGER_HPP_INCLUDED #endif // TORRENT_LOGGER_HPP_INCLUDED
 End of changes. 2 change blocks. 
0 lines changed or deleted 6 lines changed or added


 logging.hpp   logging.hpp 
skipping to change at line 36 skipping to change at line 36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_LOGGING_HPP #ifndef TORRENT_LOGGING_HPP
#define TORRENT_LOGGING_HPP #define TORRENT_LOGGING_HPP
#include "libtorrent/config.hpp"
#if TORRENT_USE_IOSTREAM
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "libtorrent/time.hpp"
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
class log class log
{ {
public: public:
log(char const* id, std::ostream& stream) log(char const* id, std::ostream& stream)
: m_id(id) : m_id(id)
, m_enabled(true) , m_enabled(true)
skipping to change at line 89 skipping to change at line 94
std::ostream& m_stream; std::ostream& m_stream;
}; };
class log_event class log_event
{ {
public: public:
log_event(log& log) log_event(log& log)
: log_(log) : log_(log)
{ {
if (log_.enabled()) if (log_.enabled())
log_ << '[' << log.id() << "] "; log_ << time_now_string() << " [" << log.id() << "] ";
} }
~log_event() ~log_event()
{ {
if (log_.enabled()) if (log_.enabled())
{ {
log_ << "\n"; log_ << "\n";
log_.flush(); log_.flush();
} }
} }
skipping to change at line 145 skipping to change at line 150
{ \ { \
static std::ofstream log_file("dht.log", std::ios::app); \ static std::ofstream log_file("dht.log", std::ios::app); \
static libtorrent::dht::log instance(#name, log_file); \ static libtorrent::dht::log instance(#name, log_file); \
return instance; \ return instance; \
} }
#define TORRENT_LOG(name) \ #define TORRENT_LOG(name) \
if (libtorrent::dht::inverted_log_event event_object__ = name ## _lo g()); \ if (libtorrent::dht::inverted_log_event event_object__ = name ## _lo g()); \
else static_cast<log_event&>(event_object__) else static_cast<log_event&>(event_object__)
#endif // TORRENT_USE_IOSTREAM
#endif #endif
 End of changes. 4 change blocks. 
1 lines changed or deleted 8 lines changed or added


 magnet_uri.hpp   magnet_uri.hpp 
skipping to change at line 51 skipping to change at line 51
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
struct torrent_handle; struct torrent_handle;
std::string TORRENT_EXPORT make_magnet_uri(torrent_handle const& han dle); std::string TORRENT_EXPORT make_magnet_uri(torrent_handle const& han dle);
std::string TORRENT_EXPORT make_magnet_uri(torrent_info const& info) ; std::string TORRENT_EXPORT make_magnet_uri(torrent_info const& info) ;
#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.14 // deprecated in 0.14
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::stri ng const& uri torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::stri ng const& uri
, fs::path const& save_path , fs::path const& save_path
, storage_mode_t storage_mode = storage_mode_sparse , storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false , bool paused = false
, storage_constructor_type sc = default_storage_constructor , storage_constructor_type sc = default_storage_constructor
, void* userdata = 0) TORRENT_DEPRECATED; , void* userdata = 0) TORRENT_DEPRECATED;
#endif #endif
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::stri ng const& uri torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::stri ng const& uri
, add_torrent_params p); , add_torrent_params p);
#endif
torrent_handle TORRENT_EXPORT add_magnet_uri(session& ses, std::stri
ng const& uri
, add_torrent_params p, error_code& ec);
} }
#endif #endif
 End of changes. 2 change blocks. 
0 lines changed or deleted 6 lines changed or added


 msg.hpp   msg.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef MSG_HPP #ifndef MSG_HPP
#define MSG_HPP #define MSG_HPP
#include <string> #include <string>
#include <libtorrent/kademlia/node_id.hpp> #include <libtorrent/kademlia/node_id.hpp>
#include "libtorrent/entry.hpp"
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/ip/udp.hpp> #include <asio/ip/udp.hpp>
#else #else
#include <boost/asio/ip/udp.hpp> #include <boost/asio/ip/udp.hpp>
#endif #endif
namespace libtorrent { namespace libtorrent {
namespace dht { namespace dht {
typedef std::vector<char> packet_t; typedef std::vector<char> packet_t;
namespace messages namespace messages
{ {
enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, er ror = 4 }; enum { ping = 0, find_node = 1, get_peers = 2, announce_peer = 3, er ror = 4 };
char const* const ids[] = { "ping", "find_node", "get_peers", "annou nce_peer", "error" }; char const* const ids[] = { "ping", "find_node", "get_peers", "annou nce_peer", "error" };
} // namespace messages } // namespace messages
struct msg struct msg
{ {
msg() : reply(false), piggy_backed_ping(false) msg()
, message_id(-1), port(0) {} : reply(false)
, message_id(-1)
, port(0)
{}
// true if this message is a reply // true if this message is a reply
bool reply; bool reply;
// true if this is a reply with a piggy backed ping
bool piggy_backed_ping;
// the kind if message // the kind if message
int message_id; int message_id;
// if this is a reply, a copy of the transaction id // if this is a reply, a copy of the transaction id
// from the request. If it's a request, a transaction // from the request. If it's a request, a transaction
// id that should be sent back in the reply // id that should be sent back in the reply
std::string transaction_id; std::string transaction_id;
// if this packet has a piggy backed ping, this
// is the transaction id of that ping
std::string ping_transaction_id;
// the node id of the process sending the message // the node id of the process sending the message
node_id id; node_id id;
// the address of the process sending or receiving // the address of the process sending or receiving
// the message. // the message.
udp::endpoint addr; udp::endpoint addr;
// if this is a nodes response, these are the nodes // if this is a nodes response, these are the nodes
typedef std::vector<node_entry> nodes_t; typedef std::vector<node_entry> nodes_t;
nodes_t nodes; nodes_t nodes;
typedef std::vector<tcp::endpoint> peers_t; typedef std::vector<tcp::endpoint> peers_t;
peers_t peers; peers_t peers;
// similar to transaction_id but for write operations. // similar to transaction_id but for write operations.
entry write_token; std::string write_token;
// the info has for peer_requests, announce_peer // the info has for peer_requests, announce_peer
// and responses // and responses
node_id info_hash; node_id info_hash;
// port for announce_peer messages // port for announce_peer messages
int port; int port;
// ERROR MESSAGES // ERROR MESSAGES
int error_code; int error_code;
 End of changes. 5 change blocks. 
9 lines changed or deleted 6 lines changed or added


 natpmp.hpp   natpmp.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_NATPMP_HPP #ifndef TORRENT_NATPMP_HPP
#define TORRENT_NATPMP_HPP #define TORRENT_NATPMP_HPP
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream>
#endif
namespace libtorrent namespace libtorrent
{ {
// int: port mapping index // int: port mapping index
// int: external port // int: external port
// std::string: error message // std::string: error message
typedef boost::function<void(int, int, std::string const&)> portmap_callbac typedef boost::function<void(int, int, error_code const&)> portmap_callback
k_t; _t;
typedef boost::function<void(char const*)> log_callback_t;
class natpmp : public intrusive_ptr_base<natpmp> class TORRENT_EXPORT natpmp : public intrusive_ptr_base<natpmp>
{ {
public: public:
natpmp(io_service& ios, address const& listen_interface, portmap_cal natpmp(io_service& ios, address const& listen_interface
lback_t const& cb); , portmap_callback_t const& cb
, log_callback_t const& lcb);
void rebind(address const& listen_interface); void rebind(address const& listen_interface);
// maps the ports, if a port is set to 0 // maps the ports, if a port is set to 0
// it will not be mapped // it will not be mapped
enum protocol_type { none = 0, udp = 1, tcp = 2 }; enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type p, int external_port, int local_port); int add_mapping(protocol_type p, int external_port, int local_port);
void delete_mapping(int mapping_index); void delete_mapping(int mapping_index);
bool get_mapping(int mapping_index, int& local_port, int& external_p ort, int& protocol) const;
void close(); void close();
private: private:
void update_mapping(int i); typedef boost::mutex mutex_t;
void send_map_request(int i);
void update_mapping(int i, mutex_t::scoped_lock& l);
void send_map_request(int i, mutex_t::scoped_lock& l);
void resend_request(int i, error_code const& e); void resend_request(int i, error_code const& e);
void on_reply(error_code const& e void on_reply(error_code const& e
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void try_next_mapping(int i); void try_next_mapping(int i, mutex_t::scoped_lock& l);
void update_expiration_timer(); void update_expiration_timer();
void mapping_expired(error_code const& e, int i); void mapping_expired(error_code const& e, int i);
void close_impl(); void close_impl(mutex_t::scoped_lock& l);
void disable(char const* message); void log(char const* msg, mutex_t::scoped_lock& l);
void disable(error_code const& ec, mutex_t::scoped_lock& l);
struct mapping_t struct mapping_t
{ {
enum action_t { action_none, action_add, action_delete }; enum action_t { action_none, action_add, action_delete };
mapping_t() mapping_t()
: action(action_none) : action(action_none)
, local_port(0) , local_port(0)
, external_port(0) , external_port(0)
, protocol(none) , protocol(none)
, map_sent(false)
{} {}
// indicates that the mapping has changed // indicates that the mapping has changed
// and needs an update // and needs an update
int action; int action;
// the time the port mapping will expire // the time the port mapping will expire
ptime expires; ptime expires;
// the local port for this mapping. If this is set // the local port for this mapping. If this is set
// to 0, the mapping is not in use // to 0, the mapping is not in use
int local_port; int local_port;
// the external (on the NAT router) port // the external (on the NAT router) port
// for the mapping. This is the port we // for the mapping. This is the port we
// should announce to others // should announce to others
int external_port; int external_port;
int protocol; int protocol;
// set to true when the first map request is sent
bool map_sent;
}; };
portmap_callback_t m_callback; portmap_callback_t m_callback;
log_callback_t m_log_callback;
std::vector<mapping_t> m_mappings; std::vector<mapping_t> m_mappings;
// the endpoint to the nat router // the endpoint to the nat router
udp::endpoint m_nat_endpoint; udp::endpoint m_nat_endpoint;
// this is the mapping that is currently // this is the mapping that is currently
// being updated. It is -1 in case no // being updated. It is -1 in case no
// mapping is being updated at the moment // mapping is being updated at the moment
int m_currently_mapping; int m_currently_mapping;
skipping to change at line 151 skipping to change at line 159
// timer used to refresh mappings // timer used to refresh mappings
deadline_timer m_refresh_timer; deadline_timer m_refresh_timer;
// the mapping index that will expire next // the mapping index that will expire next
int m_next_refresh; int m_next_refresh;
bool m_disabled; bool m_disabled;
bool m_abort; bool m_abort;
typedef boost::mutex mutex_t; mutable mutex_t m_mutex;
mutex_t m_mutex;
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
std::ofstream m_log;
#endif
}; };
} }
#endif #endif
 End of changes. 13 change blocks. 
20 lines changed or deleted 22 lines changed or added


 node.hpp   node.hpp 
skipping to change at line 53 skipping to change at line 53
#include <libtorrent/kademlia/msg.hpp> #include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/io.hpp> #include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp> #include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp> #include <libtorrent/assert.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/optional.hpp>
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
namespace libtorrent {
namespace aux { struct session_impl; }
struct session_status;
}
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node); TORRENT_DECLARE_LOG(node);
#endif #endif
struct traversal_algorithm;
// this is the entry for every peer // this is the entry for every peer
// the timestamp is there to make it possible // the timestamp is there to make it possible
// to remove stale peers // to remove stale peers
struct peer_entry struct peer_entry
{ {
tcp::endpoint addr; tcp::endpoint addr;
ptime added; ptime added;
}; };
// this is a group. It contains a set of group members // this is a group. It contains a set of group members
skipping to change at line 93 skipping to change at line 104
} }
struct null_type {}; struct null_type {};
class announce_observer : public observer class announce_observer : public observer
{ {
public: public:
announce_observer(boost::pool<>& allocator announce_observer(boost::pool<>& allocator
, sha1_hash const& info_hash , sha1_hash const& info_hash
, int listen_port , int listen_port
, entry const& write_token) , std::string const& write_token)
: observer(allocator) : observer(allocator)
, m_info_hash(info_hash) , m_info_hash(info_hash)
, m_listen_port(listen_port) , m_listen_port(listen_port)
, m_token(write_token) , m_token(write_token)
{} {}
void send(msg& m) void send(msg& m)
{ {
m.port = m_listen_port; m.port = m_listen_port;
m.info_hash = m_info_hash; m.info_hash = m_info_hash;
m.write_token = m_token; m.write_token = m_token;
} }
void timeout() {} void timeout() {}
void reply(msg const&) {} void reply(msg const&) {}
void abort() {} void abort() {}
private: private:
sha1_hash m_info_hash; sha1_hash m_info_hash;
int m_listen_port; int m_listen_port;
entry m_token; std::string m_token;
};
class get_peers_observer : public observer
{
public:
get_peers_observer(sha1_hash const& info_hash
, int listen_port
, rpc_manager& rpc
, boost::function<void(std::vector<tcp::endpoint> const&, sh
a1_hash const&)> f)
: observer(rpc.allocator())
, m_info_hash(info_hash)
, m_listen_port(listen_port)
, m_rpc(rpc)
, m_fun(f)
{}
void send(msg& m)
{
m.port = m_listen_port;
m.info_hash = m_info_hash;
}
void timeout() {}
void reply(msg const& r)
{
observer_ptr o(new (m_rpc.allocator().malloc()) announce_obs
erver(
m_rpc.allocator(), m_info_hash, m_listen_port, r.wri
te_token));
#ifdef TORRENT_DEBUG
o->m_in_constructor = false;
#endif
m_rpc.invoke(messages::announce_peer, r.addr, o);
m_fun(r.peers, m_info_hash);
}
void abort() {}
private:
sha1_hash m_info_hash;
int m_listen_port;
rpc_manager& m_rpc;
boost::function<void(std::vector<tcp::endpoint> const&, sha1_hash co
nst&)> m_fun;
}; };
class node_impl : boost::noncopyable class node_impl : boost::noncopyable
{ {
typedef std::map<node_id, torrent_entry> table_t; typedef std::map<node_id, torrent_entry> table_t;
public: public:
node_impl(boost::function<void(msg const&)> const& f node_impl(libtorrent::aux::session_impl& ses, boost::function<void(m sg const&)> const& f
, dht_settings const& settings, boost::optional<node_id> nid ); , dht_settings const& settings, boost::optional<node_id> nid );
virtual ~node_impl() {} virtual ~node_impl() {}
void refresh(node_id const& id, boost::function0<void> f); void refresh(node_id const& id, boost::function0<void> f);
void bootstrap(std::vector<udp::endpoint> const& nodes void bootstrap(std::vector<udp::endpoint> const& nodes
, boost::function0<void> f); , boost::function0<void> f);
void find_node(node_id const& id, boost::function< void find_node(node_id const& id, boost::function<
void(std::vector<node_entry> const&)> f); void(std::vector<node_entry> const&)> f);
void add_router_node(udp::endpoint router); void add_router_node(udp::endpoint router);
skipping to change at line 203 skipping to change at line 174
data_iterator begin_data() { return m_map.begin(); } data_iterator begin_data() { return m_map.begin(); }
data_iterator end_data() { return m_map.end(); } data_iterator end_data() { return m_map.end(); }
int data_size() const { return int(m_map.size()); } int data_size() const { return int(m_map.size()); }
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
void print_state(std::ostream& os) const void print_state(std::ostream& os) const
{ m_table.print_state(os); } { m_table.print_state(os); }
#endif #endif
void announce(sha1_hash const& info_hash, int listen_port void announce(sha1_hash const& info_hash, int listen_port
, boost::function<void(std::vector<tcp::endpoint> const& , boost::function<void(std::vector<tcp::endpoint> const&)> f
, sha1_hash const&)> f); );
bool verify_token(msg const& m); bool verify_token(msg const& m);
entry generate_token(msg const& m); std::string generate_token(msg const& m);
// the returned time is the delay until connection_timeout() // the returned time is the delay until connection_timeout()
// should be called again the next time // should be called again the next time
time_duration connection_timeout(); time_duration connection_timeout();
time_duration refresh_timeout(); time_duration refresh_timeout();
// generates a new secret number used to generate write tokens // generates a new secret number used to generate write tokens
void new_write_key(); void new_write_key();
// pings the given node, and adds it to // pings the given node, and adds it to
// the routing table if it respons and if the // the routing table if it respons and if the
// bucket is not full. // bucket is not full.
void add_node(udp::endpoint node); void add_node(udp::endpoint node);
void replacement_cache(bucket_t& nodes) const void replacement_cache(bucket_t& nodes) const
{ m_table.replacement_cache(nodes); } { m_table.replacement_cache(nodes); }
int branch_factor() const { return m_settings.search_branching; }
void add_traversal_algorithm(traversal_algorithm* a)
{
mutex_t::scoped_lock l(m_mutex);
m_running_requests.insert(a);
}
void remove_traversal_algorithm(traversal_algorithm* a)
{
mutex_t::scoped_lock l(m_mutex);
m_running_requests.erase(a);
}
void status(libtorrent::session_status& s);
protected: protected:
// is called when a find data request is received. Should // is called when a find data request is received. Should
// return false if the data is not stored on this node. If // return false if the data is not stored on this node. If
// the data is stored, it should be serialized into 'data'. // the data is stored, it should be serialized into 'data'.
bool on_find(msg const& m, std::vector<tcp::endpoint>& peers) const; bool on_find(msg const& m, std::vector<tcp::endpoint>& peers) const;
// this is called when a store request is received. The data // this is called when a store request is received. The data
// is store-parameters and the data to be stored. // is store-parameters and the data to be stored.
void on_announce(msg const& m, msg& reply); void on_announce(msg const& m, msg& reply);
dht_settings const& m_settings; dht_settings const& m_settings;
// the maximum number of peers to send in a get_peers // the maximum number of peers to send in a get_peers
// reply. Ordinary trackers usually limit this to 50. // reply. Ordinary trackers usually limit this to 50.
// 50 => 6 * 50 = 250 bytes + packet overhead // 50 => 6 * 50 = 250 bytes + packet overhead
int m_max_peers_reply; int m_max_peers_reply;
private: private:
typedef boost::mutex mutex_t;
mutex_t m_mutex;
// this list must be destructed after the rpc manager
// since it might have references to it
std::set<traversal_algorithm*> m_running_requests;
void incoming_request(msg const& h); void incoming_request(msg const& h);
node_id m_id; node_id m_id;
public:
routing_table m_table; routing_table m_table;
rpc_manager m_rpc; rpc_manager m_rpc;
private:
table_t m_map; table_t m_map;
ptime m_last_tracker_tick; ptime m_last_tracker_tick;
// secret random numbers used to create write tokens // secret random numbers used to create write tokens
int m_secret[2]; int m_secret[2];
libtorrent::aux::session_impl& m_ses;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // NODE_HPP #endif // NODE_HPP
 End of changes. 13 change blocks. 
50 lines changed or deleted 46 lines changed or added


 node_entry.hpp   node_entry.hpp 
skipping to change at line 44 skipping to change at line 44
#define KADEMLIA_NODE_ENTRY_HPP #define KADEMLIA_NODE_ENTRY_HPP
#include "libtorrent/kademlia/node_id.hpp" #include "libtorrent/kademlia/node_id.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
struct node_entry struct node_entry
{ {
node_entry(node_id const& id_, udp::endpoint addr_) node_entry(node_id const& id_, udp::endpoint ep, bool pinged = false
: id(id_) )
, addr(addr_) : addr(ep.address())
, fail_count(0) , port(ep.port())
, timeout_count(pinged ? 0 : 0xffff)
, id(id_)
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now(); first_seen = time_now();
#endif #endif
} }
node_entry(udp::endpoint addr_) node_entry(udp::endpoint ep)
: id(0) : addr(ep.address())
, addr(addr_) , port(ep.port())
, fail_count(0) , timeout_count(0xffff)
, id(0)
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now(); first_seen = time_now();
#endif #endif
} }
node_id id; node_entry()
udp::endpoint addr; : timeout_count(0xffff)
, id(0)
{
#ifdef TORRENT_DHT_VERBOSE_LOGGING
first_seen = time_now();
#endif
}
bool pinged() const { return timeout_count != 0xffff; }
void set_pinged() { if (timeout_count == 0xffff) timeout_count = 0;
}
void timed_out() { if (pinged()) ++timeout_count; }
int fail_count() const { return pinged() ? timeout_count : 0; }
void reset_fail_count() { if (pinged()) timeout_count = 0; }
udp::endpoint ep() const { return udp::endpoint(addr, port); }
bool confirmed() const { return timeout_count == 0; }
address addr;
boost::uint16_t port;
// the number of times this node has failed to // the number of times this node has failed to
// respond in a row // respond in a row
int fail_count; boost::uint16_t timeout_count;
node_id id;
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
ptime first_seen; ptime first_seen;
#endif #endif
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif #endif
 End of changes. 4 change blocks. 
11 lines changed or deleted 33 lines changed or added


 node_id.hpp   node_id.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef NODE_ID_HPP #ifndef NODE_ID_HPP
#define NODE_ID_HPP #define NODE_ID_HPP
#include <algorithm> #include <algorithm>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/config.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
typedef libtorrent::big_number node_id; typedef libtorrent::big_number node_id;
// returns the distance between the two nodes // returns the distance between the two nodes
// using the kademlia XOR-metric // using the kademlia XOR-metric
node_id distance(node_id const& n1, node_id const& n2); node_id TORRENT_EXPORT distance(node_id const& n1, node_id const& n2);
// returns true if: distance(n1, ref) < distance(n2, ref) // returns true if: distance(n1, ref) < distance(n2, ref)
bool compare_ref(node_id const& n1, node_id const& n2, node_id const& ref); bool TORRENT_EXPORT compare_ref(node_id const& n1, node_id const& n2, node_ id const& ref);
// returns n in: 2^n <= distance(n1, n2) < 2^(n+1) // returns n in: 2^n <= distance(n1, n2) < 2^(n+1)
// usefult for finding out which bucket a node belongs to // usefult for finding out which bucket a node belongs to
int distance_exp(node_id const& n1, node_id const& n2); int TORRENT_EXPORT distance_exp(node_id const& n1, node_id const& n2);
node_id generate_id(); node_id TORRENT_EXPORT generate_id();
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // NODE_ID_HPP #endif // NODE_ID_HPP
 End of changes. 5 change blocks. 
4 lines changed or deleted 5 lines changed or added


 observer.hpp   observer.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef OBSERVER_HPP #ifndef OBSERVER_HPP
#define OBSERVER_HPP #define OBSERVER_HPP
#include <boost/pool/pool.hpp> #include <boost/pool/pool.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/cstdint.hpp>
namespace libtorrent { namespace libtorrent {
namespace dht { namespace dht {
struct observer; struct observer;
struct msg; struct msg;
// defined in rpc_manager.cpp // defined in rpc_manager.cpp
TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*); TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*);
TORRENT_EXPORT void intrusive_ptr_release(observer const*); TORRENT_EXPORT void intrusive_ptr_release(observer const*);
skipping to change at line 87 skipping to change at line 88
// this is called when no reply has been received within // this is called when no reply has been received within
// some timeout // some timeout
virtual void timeout() = 0; virtual void timeout() = 0;
// if this is called the destructor should // if this is called the destructor should
// not invoke any new messages, and should // not invoke any new messages, and should
// only clean up. It means the rpc-manager // only clean up. It means the rpc-manager
// is being destructed // is being destructed
virtual void abort() = 0; virtual void abort() = 0;
udp::endpoint target_addr; #if TORRENT_USE_IPV6
address target_addr;
#else
address_v4 target_addr;
#endif
boost::uint16_t port;
udp::endpoint target_ep() const { return udp::endpoint(target_addr,
port); }
ptime sent; ptime sent;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool m_in_constructor; bool m_in_constructor;
#endif #endif
private: private:
boost::pool<>& pool_allocator; boost::pool<>& pool_allocator;
// reference counter for intrusive_ptr // reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs; mutable boost::detail::atomic_count m_refs;
}; };
 End of changes. 2 change blocks. 
1 lines changed or deleted 9 lines changed or added


 parse_url.hpp   parse_url.hpp 
skipping to change at line 48 skipping to change at line 48
#endif #endif
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include <string> #include <string>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent namespace libtorrent
{ {
TORRENT_EXPORT boost::tuple<std::string, std::string TORRENT_EXPORT boost::tuple<std::string, std::string
, std::string, int, std::string, char const*> , std::string, int, std::string>
parse_url_components(std::string url); parse_url_components(std::string url, error_code& ec);
} }
#endif #endif
 End of changes. 2 change blocks. 
2 lines changed or deleted 3 lines changed or added


 pch.hpp   pch.hpp 
skipping to change at line 61 skipping to change at line 61
#include <boost/filesystem/fstream.hpp> #include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.hpp> #include <boost/filesystem/operations.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/integer_traits.hpp> #include <boost/integer_traits.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include <boost/iterator_adaptors.hpp> #include <boost/iterator_adaptors.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/next_prior.hpp> #include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/preprocessor/repetition/enum.hpp> #include <boost/preprocessor/repetition/enum.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp> #include <boost/preprocessor/repetition/enum_params.hpp>
#include <boost/preprocessor/repetition/enum_params_with_a_default.hpp> #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
#include <boost/preprocessor/repetition/enum_shifted_params.hpp> #include <boost/preprocessor/repetition/enum_shifted_params.hpp>
#include <boost/ref.hpp> #include <boost/ref.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
 End of changes. 2 change blocks. 
4 lines changed or deleted 0 lines changed or added


 pe_crypto.hpp   pe_crypto.hpp 
skipping to change at line 47 skipping to change at line 47
#include <openssl/dh.h> #include <openssl/dh.h>
#include <openssl/engine.h> #include <openssl/engine.h>
#include <openssl/rc4.h> #include <openssl/rc4.h>
#include "libtorrent/peer_id.hpp" // For sha1_hash #include "libtorrent/peer_id.hpp" // For sha1_hash
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
class dh_key_exchange class TORRENT_EXPORT dh_key_exchange
{ {
public: public:
dh_key_exchange(); dh_key_exchange();
~dh_key_exchange(); ~dh_key_exchange();
bool good() const { return m_dh; } bool good() const { return m_dh; }
// Get local public key, always 96 bytes // Get local public key, always 96 bytes
char const* get_local_key() const; char const* get_local_key() const;
// read remote_pubkey, generate and store shared secret in // read remote_pubkey, generate and store shared secret in
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 peer_connection.hpp   peer_connection.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_PEER_CONNECTION_HPP_INCLUDED #ifndef TORRENT_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_PEER_CONNECTION_HPP_INCLUDED #define TORRENT_PEER_CONNECTION_HPP_INCLUDED
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <deque>
#include <string> #include <string>
#include "libtorrent/debug.hpp" #include "libtorrent/debug.hpp"
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/smart_ptr.hpp> #include <boost/smart_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/pool/pool.hpp> #include <boost/pool/pool.hpp>
#include <boost/aligned_storage.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/buffer.hpp" #include "libtorrent/buffer.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp" #include "libtorrent/stat.hpp"
skipping to change at line 97 skipping to change at line 97
class torrent; class torrent;
struct peer_plugin; struct peer_plugin;
namespace detail namespace detail
{ {
struct session_impl; struct session_impl;
} }
struct pending_block struct pending_block
{ {
pending_block(piece_block const& b): skipped(0), block(b) {} pending_block(piece_block const& b)
int skipped; : skipped(0), not_wanted(false), timed_out(false)
, busy(false), block(b) {}
// the number of times the request // the number of times the request
// has been skipped by out of order blocks // has been skipped by out of order blocks
boost::uint16_t skipped;
// if any of these are set to true, this block
// is not allocated
// in the piece picker anymore, and open for
// other peers to pick. This may be caused by
// it either timing out or being received
// unexpectedly from the peer
bool not_wanted:1;
bool timed_out:1;
// the busy flag is set if the block was
// requested from another peer when this
// request was queued. We only allow a single
// busy request at a time in each peer's queue
bool busy:1;
piece_block block; piece_block block;
bool operator==(pending_block const& b) bool operator==(pending_block const& b)
{ return b.skipped == skipped && b.block == block; } {
return b.skipped == skipped && b.block == block
&& b.not_wanted == not_wanted && b.timed_out
== timed_out;
}
}; };
struct has_block struct has_block
{ {
has_block(piece_block const& b): block(b) {} has_block(piece_block const& b): block(b) {}
piece_block const& block; piece_block const& block;
bool operator()(pending_block const& pb) const bool operator()(pending_block const& pb) const
{ return pb.block == block; } { return pb.block == block; }
}; };
skipping to change at line 211 skipping to change at line 233
void prefer_whole_pieces(int num) void prefer_whole_pieces(int num)
{ m_prefer_whole_pieces = num; } { m_prefer_whole_pieces = num; }
bool request_large_blocks() const bool request_large_blocks() const
{ return m_request_large_blocks; } { return m_request_large_blocks; }
void request_large_blocks(bool b) void request_large_blocks(bool b)
{ m_request_large_blocks = b; } { m_request_large_blocks = b; }
bool no_download() const { return m_no_download; }
void no_download(bool b) { m_no_download = b; }
void set_priority(int p) void set_priority(int p)
{ m_priority = p; } {
TORRENT_ASSERT(p > 0);
TORRENT_ASSERT(m_priority <= 255);
if (p > 255) p = 255;
m_priority = p;
}
void fast_reconnect(bool r); void fast_reconnect(bool r);
bool fast_reconnect() const { return m_fast_reconnect; } bool fast_reconnect() const { return m_fast_reconnect; }
// this adds an announcement in the announcement queue // this adds an announcement in the announcement queue
// it will let the peer know that we have the given piece // it will let the peer know that we have the given piece
void announce_piece(int index); void announce_piece(int index);
// this will tell the peer to announce the given piece
// and only allow it to request that piece
void superseed_piece(int index);
int superseed_piece() const { return m_superseed_piece; }
// tells if this connection has data it want to send // tells if this connection has data it want to send
// and has enough upload bandwidth quota left to send it. // and has enough upload bandwidth quota left to send it.
bool can_write() const; bool can_write() const;
bool can_read() const; bool can_read(char* state = 0) const;
bool is_seed() const; bool is_seed() const;
void set_upload_only(bool u) void set_upload_only(bool u);
{
m_upload_only = u;
disconnect_if_redundant();
}
bool upload_only() const { return m_upload_only; } bool upload_only() const { return m_upload_only; }
// will send a keep-alive message to the peer // will send a keep-alive message to the peer
void keep_alive(); void keep_alive();
peer_id const& pid() const { return m_peer_id; } peer_id const& pid() const { return m_peer_id; }
void set_pid(const peer_id& pid) { m_peer_id = pid; } void set_pid(const peer_id& peer_id) { m_peer_id = peer_id; }
bool has_piece(int i) const; bool has_piece(int i) const;
std::deque<pending_block> const& download_queue() const; std::vector<pending_block> const& download_queue() const;
std::deque<piece_block> const& request_queue() const; std::vector<pending_block> const& request_queue() const;
std::deque<peer_request> const& upload_queue() const; std::vector<peer_request> const& upload_queue() const;
// estimate of how long it will take until we have
// received all piece requests that we have sent
// if extra_bytes is specified, it will include those
// bytes as if they've been requested
time_duration download_queue_time(int extra_bytes = 0) const
;
bool is_interesting() const { return m_interesting; } bool is_interesting() const { return m_interesting; }
bool is_choked() const { return m_choked; } bool is_choked() const { return m_choked; }
bool is_peer_interested() const { return m_peer_interested; } bool is_peer_interested() const { return m_peer_interested; }
bool has_peer_choked() const { return m_peer_choked; } bool has_peer_choked() const { return m_peer_choked; }
void update_interest(); void update_interest();
virtual void get_peer_info(peer_info& p) const; virtual void get_peer_info(peer_info& p) const;
skipping to change at line 267 skipping to change at line 303
// returns the torrent this connection is a part of // returns the torrent this connection is a part of
// 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
boost::weak_ptr<torrent> associated_torrent() const boost::weak_ptr<torrent> associated_torrent() const
{ return m_torrent; } { return m_torrent; }
const stat& statistics() const { return m_statistics; } const stat& statistics() const { return m_statistics; }
void add_stat(size_type downloaded, size_type uploaded); void add_stat(size_type downloaded, size_type uploaded);
void calc_ip_overhead();
// is called once every second by the main loop // is called once every second by the main loop
void second_tick(float tick_interval); void second_tick(int tick_interval_ms);
void timeout_requests(); void timeout_requests();
boost::shared_ptr<socket_type> get_socket() const { return m _socket; } boost::shared_ptr<socket_type> get_socket() const { return m _socket; }
tcp::endpoint const& remote() const { return m_remote; } tcp::endpoint const& remote() const { return m_remote; }
bitfield const& get_bitfield() const; bitfield const& get_bitfield() const;
std::vector<int> const& allowed_fast(); std::vector<int> const& allowed_fast();
std::vector<int> const& suggested_pieces() const { return m_ suggested_pieces; } std::vector<int> const& suggested_pieces() const { return m_ suggested_pieces; }
ptime connected_time() const { return m_connect; } ptime connected_time() const { return m_connect; }
ptime last_received() const { return m_last_receive; } ptime last_received() const { return m_last_receive; }
void timed_out(); void on_timeout();
// this will cause this peer_connection to be disconnected. // this will cause this peer_connection to be disconnected.
void disconnect(char const* message, int error = 0); void disconnect(error_code const& ec, int error = 0);
bool is_disconnecting() const { return m_disconnecting; } bool is_disconnecting() const { return m_disconnecting; }
// this is called when the connection attempt has succeeded // this is called when the connection attempt has succeeded
// and the peer_connection is supposed to set m_connecting // and the peer_connection is supposed to set m_connecting
// to false, and stop monitor writability // to false, and stop monitor writability
void on_connection_complete(error_code const& e); void on_connection_complete(error_code const& e);
// returns true if this connection is still waiting to // returns true if this connection is still waiting to
// finish the connection attempt // finish the connection attempt
bool is_connecting() const { return m_connecting; } bool is_connecting() const { return m_connecting; }
// returns true if the socket of this peer hasn't been // returns true if the socket of this peer hasn't been
// attempted to connect yet (i.e. it's queued for // attempted to connect yet (i.e. it's queued for
// connection attempt). // connection attempt).
bool is_queued() const { return m_queued; } bool is_queued() const { return m_queued; }
// called when it's time for this peer_conncetion to actuall y // called when it's time for this peer_conncetion to actuall y
// initiate the tcp connection. This may be postponed until // initiate the tcp connection. This may be postponed until
// the library isn't using up the limitation of half-open // the library isn't using up the limitation of half-open
// tcp connections. // tcp connections.
void connect(int ticket); void on_connect(int ticket);
// This is called for every peer right after the upload // This is called for every peer right after the upload
// bandwidth has been distributed among them // bandwidth has been distributed among them
// It will reset the used bandwidth to 0. // It will reset the used bandwidth to 0.
void reset_upload_quota(); void reset_upload_quota();
// free upload. // free upload.
size_type total_free_upload() const; size_type total_free_upload() const;
void add_free_upload(size_type free_upload); void add_free_upload(size_type free_upload);
skipping to change at line 331 skipping to change at line 365
size_type share_diff() const; size_type share_diff() const;
// a connection is local if it was initiated by us. // a connection is local if it was initiated by us.
// if it was an incoming connection, it is remote // if it was an incoming connection, it is remote
bool is_local() const { return m_active; } bool is_local() const { return m_active; }
bool on_local_network() const; bool on_local_network() const;
bool ignore_bandwidth_limits() const bool ignore_bandwidth_limits() const
{ return m_ignore_bandwidth_limits; } { return m_ignore_bandwidth_limits; }
void ignore_bandwidth_limits(bool i)
{ m_ignore_bandwidth_limits = i; }
bool ignore_unchoke_slots() const;
void ignore_unchoke_slots(bool i)
{ m_ignore_unchoke_slots = i; }
bool failed() const { return m_failed; } bool failed() const { return m_failed; }
int desired_queue_size() const { return m_desired_queue_size ; } int desired_queue_size() const { return m_desired_queue_size ; }
// compares this connection against the given connection // compares this connection against the given connection
// for which one is more eligible for an unchoke. // for which one is more eligible for an unchoke.
// returns true if this is more eligible // returns true if this is more eligible
bool unchoke_compare(boost::intrusive_ptr<peer_connection co nst> const& p) const; bool unchoke_compare(boost::intrusive_ptr<peer_connection co nst> const& p) const;
bool upload_rate_compare(peer_connection const* p) const;
// resets the byte counters that are used to measure // resets the byte counters that are used to measure
// the number of bytes transferred within unchoke cycles // the number of bytes transferred within unchoke cycles
void reset_choke_counters(); void reset_choke_counters();
// if this peer connection is useless (neither party is // if this peer connection is useless (neither party is
// interested in the other), disconnect it // interested in the other), disconnect it
void disconnect_if_redundant(); void disconnect_if_redundant();
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
skipping to change at line 371 skipping to change at line 412
void incoming_keepalive(); void incoming_keepalive();
void incoming_choke(); void incoming_choke();
void incoming_unchoke(); void incoming_unchoke();
void incoming_interested(); void incoming_interested();
void incoming_not_interested(); void incoming_not_interested();
void incoming_have(int piece_index); void incoming_have(int piece_index);
void incoming_bitfield(bitfield const& bits); void incoming_bitfield(bitfield const& bits);
void incoming_request(peer_request const& r); void incoming_request(peer_request const& r);
void incoming_piece(peer_request const& p, disk_buffer_holde r& data); void incoming_piece(peer_request const& p, disk_buffer_holde r& data);
void incoming_piece(peer_request const& p, char const* data) ; void incoming_piece(peer_request const& p, char const* data) ;
void incoming_piece_fragment(); void incoming_piece_fragment(int bytes);
void start_receive_piece(peer_request const& r);
void incoming_cancel(peer_request const& r); void incoming_cancel(peer_request const& r);
void incoming_dht_port(int listen_port); void incoming_dht_port(int listen_port);
void incoming_reject_request(peer_request const& r); void incoming_reject_request(peer_request const& r);
void incoming_have_all(); void incoming_have_all();
void incoming_have_none(); void incoming_have_none();
void incoming_allowed_fast(int index); void incoming_allowed_fast(int index);
void incoming_suggest(int index); void incoming_suggest(int index);
// the following functions appends messages // the following functions appends messages
// to the send buffer // to the send buffer
void send_choke(); bool send_choke();
bool send_unchoke(); bool send_unchoke();
void send_interested(); void send_interested();
void send_not_interested(); void send_not_interested();
void snub_peer(); void snub_peer();
bool can_request_time_critical() const;
void make_time_critical(piece_block const& block);
// adds a block to the request queue // adds a block to the request queue
void add_request(piece_block const& b); // returns true if successful, false otherwise
enum flags_t { req_time_critical = 1, req_busy = 2 };
bool add_request(piece_block const& b, int flags = 0);
// clears the request queue and sends cancels for all messag
es
// in the download queue
void cancel_all_requests();
// removes a block from the request queue or download queue // removes a block from the request queue or download queue
// sends a cancel message if appropriate // sends a cancel message if appropriate
// refills the request queue, and possibly ignoring pieces r equested // refills the request queue, and possibly ignoring pieces r equested
// by peers in the ignore list (to avoid recursion) // by peers in the ignore list (to avoid recursion)
void cancel_request(piece_block const& b); void cancel_request(piece_block const& b);
void send_block_requests(); void send_block_requests();
int max_assignable_bandwidth(int channel) const
{ return m_bandwidth_limit[channel].max_assignable(); }
int bandwidth_throttle(int channel) const int bandwidth_throttle(int channel) const
{ return m_bandwidth_limit[channel].throttle(); } { return m_bandwidth_channel[channel].throttle(); }
void assign_bandwidth(int channel, int amount); void assign_bandwidth(int channel, int amount);
void expire_bandwidth(int channel, int amount);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
ptime m_last_choke; ptime m_last_choke;
#endif #endif
// is true until we can be sure that the other end // is true until we can be sure that the other end
// speaks our protocol (be it bittorrent or http). // speaks our protocol (be it bittorrent or http).
virtual bool in_handshake() const = 0; virtual bool in_handshake() const = 0;
skipping to change at line 442 skipping to change at line 491
// these functions are virtual to let bt_peer_connection hoo k into them // these functions are virtual to let bt_peer_connection hoo k into them
// and encrypt the content // and encrypt the content
enum message_type_flags { message_type_request = 1 }; enum message_type_flags { message_type_request = 1 };
virtual void send_buffer(char const* begin, int size, int fl ags = 0); virtual void send_buffer(char const* begin, int size, int fl ags = 0);
virtual buffer::interval allocate_send_buffer(int size); virtual buffer::interval allocate_send_buffer(int size);
virtual void setup_send(); virtual void setup_send();
template <class Destructor> template <class Destructor>
void append_send_buffer(char* buffer, int size, Destructor c onst& destructor) void append_send_buffer(char* buffer, int size, Destructor c onst& destructor)
{ {
#if TORRENT_DISK_STATS
if (m_ses.m_disk_thread.is_disk_buffer(buffer))
m_ses.m_disk_thread.rename_buffer(buffer, "q
ueued send buffer");
#endif
m_send_buffer.append_buffer(buffer, size, size, dest ructor); m_send_buffer.append_buffer(buffer, size, size, dest ructor);
#ifdef TORRENT_STATS #if defined TORRENT_STATS && defined TORRENT_DISK_STATS
m_ses.m_buffer_usage_logger << log_time() << " appen d_send_buffer: " << size << std::endl; m_ses.m_buffer_usage_logger << log_time() << " appen d_send_buffer: " << size << std::endl;
m_ses.log_buffer_usage(); m_ses.log_buffer_usage();
#endif #endif
} }
virtual void append_const_send_buffer(char const* buffer, in
t size);
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void set_country(char const* c) void set_country(char const* c)
{ {
TORRENT_ASSERT(strlen(c) == 2); TORRENT_ASSERT(strlen(c) == 2);
m_country[0] = c[0]; m_country[0] = c[0];
m_country[1] = c[1]; m_country[1] = c[1];
} }
bool has_country() const { return m_country[0] != 0; } bool has_country() const { return m_country[0] != 0; }
#endif #endif
skipping to change at line 480 skipping to change at line 531
{ return m_packet_size <= m_recv_pos; } { return m_packet_size <= m_recv_pos; }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool piece_failed; bool piece_failed;
#endif #endif
// upload and download channel state // upload and download channel state
// enum from peer_info::bw_state // enum from peer_info::bw_state
char m_channel_state[2]; char m_channel_state[2];
size_type uploaded_since_unchoke() const
{ return m_statistics.total_payload_upload() - m_uploaded_at
_last_unchoke; }
size_type downloaded_since_unchoke() const
{ return m_statistics.total_payload_download() - m_downloade
d_at_last_unchoke; }
void setup_receive();
protected: protected:
virtual void get_specific_peer_info(peer_info& p) const = 0; virtual void get_specific_peer_info(peer_info& p) const = 0;
virtual void write_choke() = 0; virtual void write_choke() = 0;
virtual void write_unchoke() = 0; virtual void write_unchoke() = 0;
virtual void write_interested() = 0; virtual void write_interested() = 0;
virtual void write_not_interested() = 0; virtual void write_not_interested() = 0;
virtual void write_request(peer_request const& r) = 0; virtual void write_request(peer_request const& r) = 0;
virtual void write_cancel(peer_request const& r) = 0; virtual void write_cancel(peer_request const& r) = 0;
skipping to change at line 530 skipping to change at line 589
if (m_recv_buffer.empty()) return buffer::const_inte rval(0,0); if (m_recv_buffer.empty()) return buffer::const_inte rval(0,0);
return buffer::const_interval(&m_recv_buffer[0] return buffer::const_interval(&m_recv_buffer[0]
, &m_recv_buffer[0] + m_recv_pos); , &m_recv_buffer[0] + m_recv_pos);
} }
bool allocate_disk_receive_buffer(int disk_buffer_size); bool allocate_disk_receive_buffer(int disk_buffer_size);
char* release_disk_receive_buffer(); char* release_disk_receive_buffer();
bool has_disk_receive_buffer() const { return m_disk_recv_bu ffer; } bool has_disk_receive_buffer() const { return m_disk_recv_bu ffer; }
void cut_receive_buffer(int size, int packet_size); void cut_receive_buffer(int size, int packet_size);
void reset_recv_buffer(int packet_size); void reset_recv_buffer(int packet_size);
void set_soft_packet_size(int size) { m_soft_packet_size = s
void setup_receive(); ize; }
void attach_to_torrent(sha1_hash const& ih); void attach_to_torrent(sha1_hash const& ih);
bool verify_piece(peer_request const& p) const; bool verify_piece(peer_request const& p) const;
// the bandwidth channels, upload and download // the bandwidth channels, upload and download
// keeps track of the current quotas // keeps track of the current quotas
bandwidth_limit m_bandwidth_limit[num_channels]; bandwidth_channel m_bandwidth_channel[num_channels];
// number of bytes this peer can send and receive
int m_quota[2];
// statistics about upload and download speeds // statistics about upload and download speeds
// and total amount of uploads and downloads for // and total amount of uploads and downloads for
// this peer // this peer
stat m_statistics; stat m_statistics;
// a back reference to the session // a back reference to the session
// the peer belongs to. // the peer belongs to.
aux::session_impl& m_ses; aux::session_impl& m_ses;
skipping to change at line 594 skipping to change at line 655
return intrusive_ptr_base<peer_connection>::self(); return intrusive_ptr_base<peer_connection>::self();
} }
#endif #endif
private: private:
void fill_send_buffer(); void fill_send_buffer();
void on_disk_read_complete(int ret, disk_io_job const& j, pe er_request r); void on_disk_read_complete(int ret, disk_io_job const& j, pe er_request r);
void on_disk_write_complete(int ret, disk_io_job const& j void on_disk_write_complete(int ret, disk_io_job const& j
, peer_request r, boost::shared_ptr<torrent> t); , peer_request r, boost::shared_ptr<torrent> t);
void request_upload_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0);
void request_download_bandwidth(
bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0);
// keep the io_service running as long as we // keep the io_service running as long as we
// have peer connections // have peer connections
io_service::work m_work; io_service::work m_work;
// the time when we last got a part of a // the time when we last got a part of a
// piece packet from this peer // piece packet from this peer
ptime m_last_piece; ptime m_last_piece;
// the time we sent a request to // the time we sent a request to
// this peer the last time // this peer the last time
skipping to change at line 656 skipping to change at line 727
// we get free download, and positive on peers // we get free download, and positive on peers
// that we give the free upload, to keep the balance. // that we give the free upload, to keep the balance.
size_type m_free_upload; size_type m_free_upload;
// the total payload download bytes // the total payload download bytes
// at the last unchoke cycle. This is used to // at the last unchoke cycle. This is used to
// measure the number of bytes transferred during // measure the number of bytes transferred during
// an unchoke cycle, to unchoke peers the more bytes // an unchoke cycle, to unchoke peers the more bytes
// they sent us // they sent us
size_type m_downloaded_at_last_unchoke; size_type m_downloaded_at_last_unchoke;
size_type m_uploaded_at_last_unchoke;
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
std::string m_inet_as_name; std::string m_inet_as_name;
#endif #endif
buffer m_recv_buffer; buffer m_recv_buffer;
// if this peer is receiving a piece, this // if this peer is receiving a piece, this
// points to a disk buffer that the data is // points to a disk buffer that the data is
// read into. This eliminates a memcopy from // read into. This eliminates a memcopy from
skipping to change at line 679 skipping to change at line 751
chained_buffer m_send_buffer; chained_buffer m_send_buffer;
boost::shared_ptr<socket_type> m_socket; boost::shared_ptr<socket_type> m_socket;
// this is the peer we're actually talking to // this is the peer we're actually talking to
// it may not necessarily be the peer we're // it may not necessarily be the peer we're
// connected to, in case we use a proxy // connected to, in case we use a proxy
tcp::endpoint m_remote; tcp::endpoint m_remote;
// this is the torrent this connection is // this is the torrent this connection is
// associated with. If the connection is an // associated with. If the connection is an
// incoming conncetion, this is set to zero // incoming connection, this is set to zero
// until the info_hash is received. Then it's // until the info_hash is received. Then it's
// set to the torrent it belongs to. // set to the torrent it belongs to.
boost::weak_ptr<torrent> m_torrent; boost::weak_ptr<torrent> m_torrent;
// remote peer's id // remote peer's id
peer_id m_peer_id; peer_id m_peer_id;
// the pieces the other end have // the pieces the other end have
bitfield m_have_piece; bitfield m_have_piece;
// the queue of requests we have got // the queue of requests we have got
// from this peer // from this peer
std::deque<peer_request> m_requests; std::vector<peer_request> m_requests;
// the blocks we have reserved in the piece // the blocks we have reserved in the piece
// picker and will request from this peer. // picker and will request from this peer.
std::deque<piece_block> m_request_queue; std::vector<pending_block> m_request_queue;
// the queue of blocks we have requested // the queue of blocks we have requested
// from this peer // from this peer
std::deque<pending_block> m_download_queue; std::vector<pending_block> m_download_queue;
// the pieces we will send to the peer // the pieces we will send to the peer
// if requested (regardless of choke state) // if requested (regardless of choke state)
std::set<int> m_accept_fast; std::vector<int> m_accept_fast;
// the pieces the peer will send us if // the pieces the peer will send us if
// requested (regardless of choke state) // requested (regardless of choke state)
std::vector<int> m_allowed_fast; std::vector<int> m_allowed_fast;
// pieces that has been suggested to be // pieces that has been suggested to be
// downloaded from this peer // downloaded from this peer
std::vector<int> m_suggested_pieces; std::vector<int> m_suggested_pieces;
// a list of byte offsets inside the send buffer // a list of byte offsets inside the send buffer
// the piece requests // the piece requests
std::vector<int> m_requests_in_buffer; std::vector<int> m_requests_in_buffer;
// the block we're currently receiving. Or
// (-1, -1) if we're not receiving one
piece_block m_receiving_block;
// the number of bytes that the other
// end has to send us in order to respond
// to all outstanding piece requests we
// have sent to it
int m_outstanding_bytes;
// the number of outstanding bytes expected
// to be received by extensions
int m_extension_outstanding_bytes;
// the number of time critical requests
// queued up in the m_request_queue that
// soon will be committed to the download
// queue. This is included in download_queue_time()
// so that it can be used while adding more
// requests and take the previous requests
// into account without submitting it all
// immediately
int m_queued_time_critical;
// the number of pieces this peer // the number of pieces this peer
// has. Must be the same as // has. Must be the same as
// std::count(m_have_piece.begin(), // std::count(m_have_piece.begin(),
// m_have_piece.end(), true) // m_have_piece.end(), true)
int m_num_pieces; int m_num_pieces;
// the timeout in seconds // the timeout in seconds
int m_timeout; int m_timeout;
// the size (in bytes) of the bittorrent message // the size (in bytes) of the bittorrent message
// we're currently receiving // we're currently receiving
int m_packet_size; int m_packet_size;
// some messages needs to be read from the socket
// buffer in multiple stages. This soft packet
// size limits the read size between message handler
// dispatch. Ignored when set to 0
int m_soft_packet_size;
// the number of bytes of the bittorrent payload // the number of bytes of the bittorrent payload
// we've received so far // we've received so far
int m_recv_pos; int m_recv_pos;
int m_disk_recv_buffer_size; int m_disk_recv_buffer_size;
// the number of bytes we are currently reading // the number of bytes we are currently reading
// from disk, that will be added to the send // from disk, that will be added to the send
// buffer as soon as they complete // buffer as soon as they complete
int m_reading_bytes; int m_reading_bytes;
skipping to change at line 774 skipping to change at line 876
// it allows some variance without changing // it allows some variance without changing
// back and forth between states // back and forth between states
peer_speed_t m_speed; peer_speed_t m_speed;
// the ticket id from the connection queue. // the ticket id from the connection queue.
// This is used to identify the connection // This is used to identify the connection
// so that it can be removed from the queue // so that it can be removed from the queue
// once the connection completes // once the connection completes
int m_connection_ticket; int m_connection_ticket;
// if this is -1, superseeding is not active. If it is >= 0
// this is the piece that is available to this peer. Only
// this piece can be downloaded from us by this peer.
// This will remain the current piece for this peer until
// another peer sends us a have message for this piece
int m_superseed_piece;
// bytes downloaded since last second // bytes downloaded since last second
// timer timeout; used for determining // timer timeout; used for determining
// approx download rate // approx download rate
int m_remote_bytes_dled; int m_remote_bytes_dled;
// approximate peer download rate // approximate peer download rate
int m_remote_dl_rate; int m_remote_dl_rate;
// the number of bytes send to the disk-io // the number of bytes send to the disk-io
// thread that hasn't yet been completely written. // thread that hasn't yet been completely written.
skipping to change at line 808 skipping to change at line 917
// where n is the value of this variable. // where n is the value of this variable.
// if it is 0, the download rate limit setting // if it is 0, the download rate limit setting
// will be used to determine if whole pieces // will be used to determine if whole pieces
// are preferred. // are preferred.
boost::uint8_t m_prefer_whole_pieces; boost::uint8_t m_prefer_whole_pieces;
// the number of request we should queue up // the number of request we should queue up
// at the remote end. // at the remote end.
boost::uint8_t m_desired_queue_size; boost::uint8_t m_desired_queue_size;
// the number of piece requests we have rejected
// in a row because the peer is choked. This is
// used to re-send the choked message in case the
// other end keeps requesting pieces while being
// choked, and eventuelly disconnect if it keeps
// requesting too many pieces while being choked
boost::uint8_t m_choke_rejects;
// if this is true, the disconnection // if this is true, the disconnection
// timestamp is not updated when the connection // timestamp is not updated when the connection
// is closed. This means the time until we can // is closed. This means the time until we can
// reconnect to this peer is shorter, and likely // reconnect to this peer is shorter, and likely
// immediate. // immediate.
bool m_fast_reconnect:1; bool m_fast_reconnect:1;
// 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 incoming connection // and false if we got an incoming connection
// could be considered: true = local, false = remote // could be considered: true = local, false = remote
skipping to change at line 845 skipping to change at line 962
// out or closed the connection. In that // out or closed the connection. In that
// case we will not try to reconnect to // case we will not try to reconnect to
// this peer // this peer
bool m_failed:1; bool m_failed:1;
// if this is set to true, the peer will not // if this is set to true, the peer will not
// request bandwidth from the limiter, but instead // request bandwidth from the limiter, but instead
// just send and receive as much as possible. // just send and receive as much as possible.
bool m_ignore_bandwidth_limits:1; bool m_ignore_bandwidth_limits:1;
// set to true if this peer controls its unchoke
// state individually, regardless of the global
// unchoker
bool m_ignore_unchoke_slots:1;
// this is set to true when a have_all // this is set to true when a have_all
// message is received. This information // message is received. This information
// is used to fill the bitmask in init() // is used to fill the bitmask in init()
bool m_have_all:1; bool m_have_all:1;
// this is true if this connection has been added // this is true if this connection has been added
// to the list of connections that will be closed. // to the list of connections that will be closed.
bool m_disconnecting:1; bool m_disconnecting:1;
// this is true until this socket has become // this is true until this socket has become
skipping to change at line 888 skipping to change at line 1010
bool m_upload_only:1; bool m_upload_only:1;
// set to true when a piece request times out. The // set to true when a piece request times out. The
// result is that the desired pending queue size // result is that the desired pending queue size
// is set to 1 // is set to 1
bool m_snubbed:1; bool m_snubbed:1;
// this is set to true once the bitfield is received // this is set to true once the bitfield is received
bool m_bitfield_received:1; bool m_bitfield_received:1;
// if this is set to true, the client will not
// pick any pieces from this peer
bool m_no_download:1;
template <std::size_t Size>
struct handler_storage
{
#ifdef TORRENT_DEBUG
handler_storage()
: used(false)
{}
bool used;
#endif
boost::aligned_storage<Size> bytes;
};
handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> m_read_handle
r_storage;
handler_storage<TORRENT_WRITE_HANDLER_MAX_SIZE> m_write_hand
ler_storage;
template <class Handler, std::size_t Size>
struct allocating_handler
{
allocating_handler(
Handler const& h, handler_storage<Size>& s
)
: handler(h)
, storage(s)
{}
template <class A0>
void operator()(A0 const& a0) const
{
handler(a0);
}
template <class A0, class A1>
void operator()(A0 const& a0, A1 const& a1) const
{
handler(a0, a1);
}
template <class A0, class A1, class A2>
void operator()(A0 const& a0, A1 const& a1, A2 const
& a2) const
{
handler(a0, a1, a2);
}
friend void* asio_handler_allocate(
std::size_t size, allocating_handler<Handler, Si
ze>* ctx)
{
assert(size <= Size);
#ifdef TORRENT_DEBUG
assert(!ctx->storage.used);
ctx->storage.used = true;
#endif
return &ctx->storage.bytes;
}
friend void asio_handler_deallocate(
void*, std::size_t, allocating_handler<Handl
er, Size>* ctx)
{
#ifdef TORRENT_DEBUG
ctx->storage.used = false;
#endif
}
Handler handler;
handler_storage<Size>& storage;
};
template <class Handler>
allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>
make_read_handler(Handler const& handler)
{
return allocating_handler<Handler, TORRENT_READ_HAND
LER_MAX_SIZE>(
handler, m_read_handler_storage
);
}
template <class Handler>
allocating_handler<Handler, TORRENT_WRITE_HANDLER_MAX_SIZE>
make_write_handler(Handler const& handler)
{
return allocating_handler<Handler, TORRENT_WRITE_HAN
DLER_MAX_SIZE>(
handler, m_write_handler_storage
);
}
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
public: public:
bool m_in_constructor:1; bool m_in_constructor:1;
bool m_disconnect_started:1; bool m_disconnect_started:1;
bool m_initialized:1; bool m_initialized:1;
int m_received_in_piece;
#endif #endif
}; };
} }
#endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 46 change blocks. 
42 lines changed or deleted 267 lines changed or added


 peer_id.hpp   peer_id.hpp 
skipping to change at line 36 skipping to change at line 36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_PEER_ID_HPP_INCLUDED #ifndef TORRENT_PEER_ID_HPP_INCLUDED
#define TORRENT_PEER_ID_HPP_INCLUDED #define TORRENT_PEER_ID_HPP_INCLUDED
#include <iostream>
#include <iomanip>
#include <cctype> #include <cctype>
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <cstring> #include <cstring>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/escape_string.hpp" #include "libtorrent/escape_string.hpp"
#if TORRENT_USE_IOSTREAM
#include <iostream>
#include <iomanip>
#endif
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif
namespace libtorrent namespace libtorrent
{ {
class TORRENT_EXPORT big_number class TORRENT_EXPORT big_number
{ {
// the number of bytes of the number // the number of bytes of the number
enum { number_size = 20 }; enum { number_size = 20 };
public: public:
enum { size = number_size }; enum { size = number_size };
skipping to change at line 79 skipping to change at line 90
std::memcpy(m_number, &s[0], sl); std::memcpy(m_number, &s[0], sl);
} }
void assign(std::string const& s) void assign(std::string const& s)
{ {
TORRENT_ASSERT(s.size() >= 20); TORRENT_ASSERT(s.size() >= 20);
int sl = int(s.size()) < size ? int(s.size()) : size ; int sl = int(s.size()) < size ? int(s.size()) : size ;
std::memcpy(m_number, &s[0], sl); std::memcpy(m_number, &s[0], sl);
} }
void assign(char const* str)
{
std::memcpy(m_number, str, size);
}
void clear() void clear()
{ {
std::fill(m_number,m_number+number_size,0); std::fill(m_number,m_number+number_size,(const unsig ned char)(0));
} }
bool is_all_zeros() const bool is_all_zeros() const
{ {
return std::count(m_number,m_number+number_size,0) = for (const unsigned char* i = m_number; i < m_number
= number_size; +number_size; ++i)
if (*i != 0) return false;
return true;
} }
bool operator==(big_number const& n) const bool operator==(big_number const& n) const
{ {
return std::equal(n.m_number, n.m_number+number_size , m_number); return std::equal(n.m_number, n.m_number+number_size , m_number);
} }
bool operator!=(big_number const& n) const bool operator!=(big_number const& n) const
{ {
return !std::equal(n.m_number, n.m_number+number_siz e, m_number); return !std::equal(n.m_number, n.m_number+number_siz e, m_number);
skipping to change at line 165 skipping to change at line 183
private: private:
unsigned char m_number[number_size]; unsigned char m_number[number_size];
}; };
typedef big_number peer_id; typedef big_number peer_id;
typedef big_number sha1_hash; typedef big_number sha1_hash;
#if TORRENT_USE_IOSTREAM
inline std::ostream& operator<<(std::ostream& os, big_number const& peer) inline std::ostream& operator<<(std::ostream& os, big_number const& peer)
{ {
for (big_number::const_iterator i = peer.begin(); char out[41];
i != peer.end(); ++i) to_hex((char const*)&peer[0], big_number::size, out);
{ return os << out;
os << std::hex << std::setw(2) << std::setfill('0')
<< static_cast<unsigned int>(*i);
}
os << std::dec << std::setfill(' ');
return os;
} }
inline std::istream& operator>>(std::istream& is, big_number& peer) inline std::istream& operator>>(std::istream& is, big_number& peer)
{ {
for (big_number::iterator i = peer.begin(); char hex[40];
i != peer.end(); ++i) is.read(hex, 40);
{ if (!from_hex(hex, 40, (char*)&peer[0]))
char c[2]; is.setstate(std::ios_base::failbit);
is >> c[0] >> c[1];
c[0] = tolower(c[0]);
c[1] = tolower(c[1]);
if (
((c[0] < '0' || c[0] > '9') && (c[0] < 'a' |
| c[0] > 'f'))
|| ((c[1] < '0' || c[1] > '9') && (c[1] < 'a
' || c[1] > 'f'))
|| is.fail())
{
is.setstate(std::ios_base::failbit);
return is;
}
*i = ((is_digit(c[0])?c[0]-'0':c[0]-'a'+10) << 4)
+ (is_digit(c[1])?c[1]-'0':c[1]-'a'+10);
}
return is; return is;
} }
#endif // TORRENT_USE_IOSTREAM
} }
#endif // TORRENT_PEER_ID_HPP_INCLUDED #endif // TORRENT_PEER_ID_HPP_INCLUDED
 End of changes. 9 change blocks. 
34 lines changed or deleted 32 lines changed or added


 peer_info.hpp   peer_info.hpp 
skipping to change at line 83 skipping to change at line 83
dht = 0x2, dht = 0x2,
pex = 0x4, pex = 0x4,
lsd = 0x8, lsd = 0x8,
resume_data = 0x10, resume_data = 0x10,
incoming = 0x20 incoming = 0x20
}; };
int source; int source;
// bw_idle: the channel is not used // bw_idle: the channel is not used
// bw_torrent: the channel is waiting for torrent quota // bw_limit: the channel is waiting for quota
// bw_global: the channel is waiting for global quota
// bw_network: the channel is waiting for an async write // bw_network: the channel is waiting for an async write
// for read operation to complete // for read operation to complete
enum bw_state { bw_idle, bw_torrent, bw_global, bw_network } // bw_disk: the peer is waiting for the disk io thread
; // to catch up
enum bw_state { bw_idle, bw_limit, bw_network, bw_disk };
#ifndef TORRENT_NO_DEPRECATE
enum bw_state_deprecated { bw_torrent = bw_limit, bw_global
= bw_limit };
#endif
char read_state; char read_state;
char write_state; char write_state;
tcp::endpoint ip; tcp::endpoint ip;
float up_speed; int up_speed;
float down_speed; int down_speed;
float payload_up_speed; int payload_up_speed;
float payload_down_speed; int payload_down_speed;
size_type total_download; size_type total_download;
size_type total_upload; size_type total_upload;
peer_id pid; peer_id pid;
bitfield pieces; bitfield pieces;
int upload_limit; int upload_limit;
int download_limit; int download_limit;
// time since last request // time since last request
time_duration last_request; time_duration last_request;
// time since last download or upload // time since last download or upload
time_duration last_active; time_duration last_active;
// the time until all blocks in the request
// queue will be d
time_duration download_queue_time;
int queue_bytes;
// the number of seconds until the current // the number of seconds until the current
// pending request times out // pending request times out
int request_timeout; int request_timeout;
// the size of the send buffer for this peer, in bytes // the size of the send buffer for this peer, in bytes
int send_buffer_size; int send_buffer_size;
// the number bytes that's actually used of the send buffer // the number bytes that's actually used of the send buffer
int used_send_buffer; int used_send_buffer;
int receive_buffer_size; int receive_buffer_size;
skipping to change at line 178 skipping to change at line 187
int downloading_piece_index; int downloading_piece_index;
int downloading_block_index; int downloading_block_index;
int downloading_progress; int downloading_progress;
int downloading_total; int downloading_total;
std::string client; std::string client;
enum enum
{ {
standard_bittorrent = 0, standard_bittorrent = 0,
web_seed = 1 web_seed = 1,
http_seed = 2
}; };
int connection_type; int connection_type;
// approximate peer download rate // approximate peer download rate
int remote_dl_rate; int remote_dl_rate;
// number of bytes this peer has in // number of bytes this peer has in
// the disk write queue // the disk write queue
int pending_disk_bytes; int pending_disk_bytes;
// numbers used for bandwidth limiting // numbers used for bandwidth limiting
int send_quota; int send_quota;
int receive_quota; int receive_quota;
// estimated rtt to peer, in milliseconds // estimated rtt to peer, in milliseconds
int rtt; int rtt;
// the number of pieces this peer has
int num_pieces;
// the highest transfer rates seen for this peer // the highest transfer rates seen for this peer
int download_rate_peak; int download_rate_peak;
int upload_rate_peak; int upload_rate_peak;
// the peers progress // the peers progress
float progress; float progress; // [0, 1]
int progress_ppm; // [0, 1000000]
}; };
struct TORRENT_EXPORT peer_list_entry struct TORRENT_EXPORT peer_list_entry
{ {
enum flags_t enum flags_t
{ {
banned = 1 banned = 1
}; };
tcp::endpoint ip; tcp::endpoint ip;
int flags; int flags;
boost::uint8_t failcount; boost::uint8_t failcount;
boost::uint8_t source; boost::uint8_t source;
}; };
// defined in policy.cpp
int source_rank(int source_bitmask);
} }
#endif // TORRENT_PEER_INFO_HPP_INCLUDED #endif // TORRENT_PEER_INFO_HPP_INCLUDED
 End of changes. 8 change blocks. 
10 lines changed or deleted 27 lines changed or added


 peer_request.hpp   peer_request.hpp 
skipping to change at line 44 skipping to change at line 44
#define TORRENT_PEER_REQUEST_HPP_INCLUDED #define TORRENT_PEER_REQUEST_HPP_INCLUDED
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT peer_request struct TORRENT_EXPORT peer_request
{ {
int piece; int piece;
int start; int start;
int length; int length;
bool operator==(peer_request const& r) const bool operator==(peer_request const& r) const
{ return piece == r.piece && start == r.start && length == r .length; } { return piece == r.piece && start == r.start && length == r .length; }
}; };
} }
#endif // TORRENT_PEER_REQUEST_HPP_INCLUDED #endif // TORRENT_PEER_REQUEST_HPP_INCLUDED
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 piece_picker.hpp   piece_picker.hpp 
skipping to change at line 66 skipping to change at line 66
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
class peer_connection; class peer_connection;
struct bitfield; struct bitfield;
struct TORRENT_EXPORT piece_block struct TORRENT_EXPORT piece_block
{ {
piece_block() {}
piece_block(int p_index, int b_index) piece_block(int p_index, int b_index)
: piece_index(p_index) : piece_index(p_index)
, block_index(b_index) , block_index(b_index)
{} {}
int piece_index; int piece_index;
int block_index; int block_index;
bool operator<(piece_block const& b) const bool operator<(piece_block const& b) const
{ {
if (piece_index < b.piece_index) return true; if (piece_index < b.piece_index) return true;
skipping to change at line 133 skipping to change at line 134
{ {
// pick rarest first // pick rarest first
rarest_first = 1, rarest_first = 1,
// pick the most common first, or the last pieces if sequential // pick the most common first, or the last pieces if sequential
reverse = 2, reverse = 2,
// only pick pieces exclusively requested from this peer // only pick pieces exclusively requested from this peer
on_parole = 4, on_parole = 4,
// always pick partial pieces before any other piece // always pick partial pieces before any other piece
prioritize_partials = 8, prioritize_partials = 8,
// pick pieces in sequential order // pick pieces in sequential order
sequential = 16 sequential = 16,
// have affinity to pieces with the same speed categ
ory
speed_affinity = 32,
// ignore the prefer_whole_pieces parameter
ignore_whole_pieces = 64
}; };
struct downloading_piece struct downloading_piece
{ {
downloading_piece(): last_request(min_time()), finis hed(0), writing(0), requested(0) {} downloading_piece(): last_request(min_time()), finis hed(0), writing(0), requested(0) {}
piece_state_t state; piece_state_t state;
ptime last_request; ptime last_request;
// the index of the piece // the index of the piece
int index; int index;
skipping to change at line 187 skipping to change at line 192
// This indicates that we just received this piece // This indicates that we just received this piece
// it means that the refcounter will indicate that // it means that the refcounter will indicate that
// we are not interested in this piece anymore // we are not interested in this piece anymore
// (i.e. we don't have to maintain a refcount) // (i.e. we don't have to maintain a refcount)
void we_have(int index); void we_have(int index);
void we_dont_have(int index); void we_dont_have(int index);
int cursor() const { return m_cursor; } int cursor() const { return m_cursor; }
int reverse_cursor() const { return m_reverse_cursor; } int reverse_cursor() const { return m_reverse_cursor; }
int sparse_regions() const { return m_sparse_regions; }
// sets all pieces to dont-have // sets all pieces to dont-have
void init(int blocks_per_piece, int blocks_in_last_piece, in t total_num_pieces); void init(int blocks_per_piece, int blocks_in_last_piece, in t total_num_pieces);
int num_pieces() const { return int(m_piece_map.size()); } int num_pieces() const { return int(m_piece_map.size()); }
bool have_piece(int index) const bool have_piece(int index) const
{ {
TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < int(m_piece_map.size())); TORRENT_ASSERT(index < int(m_piece_map.size()));
return m_piece_map[index].index == piece_pos::we_hav e_index; return m_piece_map[index].index == piece_pos::we_hav e_index;
skipping to change at line 321 skipping to change at line 327
int num_have() const { return m_num_have; } int num_have() const { return m_num_have; }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// used in debug mode // used in debug mode
void verify_priority(int start, int end, int prio) const; void verify_priority(int start, int end, int prio) const;
void check_invariant(const torrent* t = 0) const; void check_invariant(const torrent* t = 0) const;
void verify_pick(std::vector<piece_block> const& picked void verify_pick(std::vector<piece_block> const& picked
, bitfield const& bits) const; , bitfield const& bits) const;
#endif #endif
#if defined TORRENT_PICKER_LOG || defined TORRENT_DEBUG #if defined TORRENT_PICKER_LOG
void print_pieces() const; void print_pieces() const;
#endif #endif
// functor that compares indices on downloading_pieces // functor that compares indices on downloading_pieces
struct has_index struct has_index
{ {
has_index(int i): index(i) { TORRENT_ASSERT(i >= 0); } has_index(int i): index(i) { TORRENT_ASSERT(i >= 0); }
bool operator()(const downloading_piece& p) const bool operator()(const downloading_piece& p) const
{ return p.index == index; } { return p.index == index; }
int index; int index;
}; };
int blocks_in_last_piece() const int blocks_in_last_piece() const
{ return m_blocks_in_last_piece; } { return m_blocks_in_last_piece; }
float distributed_copies() const; std::pair<int, int> distributed_copies() const;
private: private:
friend struct piece_pos; friend struct piece_pos;
bool can_pick(int piece, bitfield const& bitmask) const; bool can_pick(int piece, bitfield const& bitmask) const;
bool is_piece_free(int piece, bitfield const& bitmask) const ; bool is_piece_free(int piece, bitfield const& bitmask) const ;
std::pair<int, int> expand_piece(int piece, int whole_pieces std::pair<int, int> expand_piece(int piece, int whole_pieces
, bitfield const& have) const; , bitfield const& have) const;
skipping to change at line 422 skipping to change at line 428
// availability = 0 should not be present in the piece list // availability = 0 should not be present in the piece list
// returning -1 indicates that they shouldn' t. // returning -1 indicates that they shouldn' t.
if (filtered() || have() || peer_count + pic ker->m_seeds == 0) if (filtered() || have() || peer_count + pic ker->m_seeds == 0)
return -1; return -1;
// prio 7 disregards availability // prio 7 disregards availability
if (piece_priority == priority_levels - 1) r eturn 1 - downloading; if (piece_priority == priority_levels - 1) r eturn 1 - downloading;
// prio 4,5,6 halves the availability of a p iece // prio 4,5,6 halves the availability of a p iece
int availability = peer_count; int availability = peer_count;
int priority = piece_priority; int p = piece_priority;
if (piece_priority >= priority_levels / 2) if (piece_priority >= priority_levels / 2)
{ {
availability /= 2; availability /= 2;
priority -= (priority_levels - 2) / 2; p -= (priority_levels - 2) / 2;
} }
if (downloading) return availability * prio_ factor; if (downloading) return availability * prio_ factor;
return availability * prio_factor + (priorit y_levels / 2) - priority; return availability * prio_factor + (priorit y_levels / 2) - p;
} }
bool operator!=(piece_pos p) const bool operator!=(piece_pos p) const
{ return index != p.index || peer_count != p.peer_co unt; } { return index != p.index || peer_count != p.peer_co unt; }
bool operator==(piece_pos p) const bool operator==(piece_pos p) const
{ return index == p.index && peer_count == p.peer_co unt; } { return index == p.index && peer_count == p.peer_co unt; }
}; };
skipping to change at line 529 skipping to change at line 535
// we have all pieces in the range [0, m_cursor) // we have all pieces in the range [0, m_cursor)
// m_cursor is the first piece we don't have // m_cursor is the first piece we don't have
int m_cursor; int m_cursor;
// we have all pieces in the range [m_reverse_cursor, end) // we have all pieces in the range [m_reverse_cursor, end)
// m_reverse_cursor is the first piece where we also have // m_reverse_cursor is the first piece where we also have
// all the subsequent pieces // all the subsequent pieces
int m_reverse_cursor; int m_reverse_cursor;
// the number of regions of pieces we don't have.
int m_sparse_regions;
// if this is set to true, it means update_pieces() // if this is set to true, it means update_pieces()
// has to be called before accessing m_pieces. // has to be called before accessing m_pieces.
mutable bool m_dirty; mutable bool m_dirty;
public: public:
enum { max_pieces = piece_pos::we_have_index - 1 }; enum { max_pieces = piece_pos::we_have_index - 1 };
}; };
inline int piece_picker::blocks_in_piece(int index) const inline int piece_picker::blocks_in_piece(int index) const
 End of changes. 9 change blocks. 
6 lines changed or deleted 16 lines changed or added


 policy.hpp   policy.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_POLICY_HPP_INCLUDED #ifndef TORRENT_POLICY_HPP_INCLUDED
#define TORRENT_POLICY_HPP_INCLUDED #define TORRENT_POLICY_HPP_INCLUDED
#include <algorithm> #include <algorithm>
#include <vector> #include <deque>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "libtorrent/peer.hpp" #include "libtorrent/peer.hpp"
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
class peer_connection; class peer_connection;
// this is compressed as an unsigned floating point value
// the top 13 bits are the mantissa and the low
// 3 bits is the unsigned exponent. The exponent
// has an implicit + 4 as well.
// This means that the resolution is no less than 16
// The actual rate is: (upload_rate >> 4) << ((upload_rate & 0xf) +
4)
// the resolution gets worse the higher the value is
// min value is 0, max value is 16775168
struct ufloat16
{
ufloat16() {}
ufloat16(int v)
{ *this = v; }
operator int()
{
return (m_val >> 3) << ((m_val & 7) + 4);
}
ufloat16& operator=(int v)
{
if (v > 0x1fff << (7 + 4)) m_val = 0xffff;
else if (v <= 0) m_val = 0;
else
{
int exp = 4;
v >>= 4;
while (v > 0x1fff)
{
v >>= 1;
++exp;
}
TORRENT_ASSERT(exp <= 7);
m_val = (v << 3) || (exp & 7);
}
return *this;
}
private:
unsigned int m_val;
};
enum enum
{ {
// the limits of the download queue size // the limits of the download queue size
min_request_queue = 2, min_request_queue = 2,
// the amount of free upload allowed before // the amount of free upload allowed before
// the peer is choked // the peer is choked
free_upload_amount = 4 * 16 * 1024 free_upload_amount = 4 * 16 * 1024
}; };
skipping to change at line 86 skipping to change at line 118
policy(torrent* t); policy(torrent* t);
// this is called every 10 seconds to allow // this is called every 10 seconds to allow
// for peer choking management // for peer choking management
void pulse(); void pulse();
struct peer; struct peer;
// this is called once for every peer we get from // this is called once for every peer we get from
// the tracker, pex, lsd or dht. // the tracker, pex, lsd or dht.
policy::peer* peer_from_tracker(const tcp::endpoint& remote, const peer_id& pid policy::peer* add_peer(const tcp::endpoint& remote, const pe er_id& pid
, int source, char flags); , int source, char flags);
// false means duplicate connection // false means duplicate connection
bool update_peer_port(int port, policy::peer* p, int src); bool update_peer_port(int port, policy::peer* p, int src);
// called when an incoming connection is accepted // called when an incoming connection is accepted
// false means the connection was refused or failed // false means the connection was refused or failed
bool new_connection(peer_connection& c); bool new_connection(peer_connection& c, int session_time);
// the given connection was just closed // the given connection was just closed
void connection_closed(const peer_connection& c); void connection_closed(const peer_connection& c, int session _time);
void ban_peer(policy::peer* p); void ban_peer(policy::peer* p);
void set_connection(policy::peer* p, peer_connection* c);
void set_failcount(policy::peer* p, int f);
// the peer has got at least one interesting piece // the peer has got at least one interesting piece
void peer_is_interesting(peer_connection& c); void peer_is_interesting(peer_connection& c);
// the peer unchoked us
void unchoked(peer_connection& c);
// the peer is interested in our pieces
void interested(peer_connection& c);
// the peer is not interested in our pieces
void not_interested(peer_connection& c);
void ip_filter_updated(); void ip_filter_updated();
void set_seed(policy::peer* p, bool s); void set_seed(policy::peer* p, bool s);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool has_connection(const peer_connection* p); bool has_connection(const peer_connection* p);
void check_invariant() const; void check_invariant() const;
#endif #endif
struct peer // intended struct layout (on 32 bit architectures)
// offset size alignment field
// 0 12 1 prev_amount_upload, prev_amount_download
// 12 4 4 connection
// 16 2 2 last_optimistically_unchoked
// 18 2 2 last_connected
// 20 16 1 addr
// 36 2 2 port
// 38 2 2 upload_rate_limit
// 40 2 2 download_rate_limit
// 42 1 1 hashfails
// 43 1 1 failcount, connectable, optimistically_unchoked,
seed
// 44 1 1 fast_reconnects, trust_points
// 45 1 1 source, pe_support, is_v6_addr
// 46 1 1 on_parole, banned, added_to_dht
// 47 1 1 <padding>
// 48
struct TORRENT_EXPORT peer
{ {
enum connection_type { not_connectable, connectable peer();
}; peer(boost::uint16_t port, bool connectable, int src
peer(tcp::endpoint const& ip, connection_type t, int );
src);
size_type total_download() const; size_type total_download() const;
size_type total_upload() const; size_type total_upload() const;
tcp::endpoint ip() const { return tcp::endpoint(addr libtorrent::address address() const;
, port); }
void set_ip(tcp::endpoint const& endp) tcp::endpoint ip() const { return tcp::endpoint(addr
{ addr = endp.address(); port = endp.port(); } ess(), port); }
// this is the accumulated amount of // this is the accumulated amount of
// uploaded and downloaded data to this // uploaded and downloaded data to this
// peer. It only accounts for what was // peer. It only accounts for what was
// shared during the last connection to // shared during the last connection to
// this peer. i.e. These are only updated // this peer. i.e. These are only updated
// when the connection is closed. For the // when the connection is closed. For the
// total amount of upload and download // total amount of upload and download
// we'll have to add thes figures with the // we'll have to add thes figures with the
// statistics from the peer_connection. // statistics from the peer_connection.
size_type prev_amount_upload; // 48 bits can fit 256 Terabytes
size_type prev_amount_download; #ifdef __SUNPRO_CC
unsigned prev_amount_upload:48;
// the ip address this peer is or was connected on unsigned prev_amount_download:48;
address addr; #else
boost::uint64_t prev_amount_upload:48;
// the time when this peer was optimistically unchok boost::uint64_t prev_amount_download:48;
ed #endif
// the last time.
libtorrent::ptime last_optimistically_unchoked;
// the time when the peer connected to us
// or disconnected if it isn't connected right now
libtorrent::ptime connected;
// if the peer is connected now, this // if the peer is connected now, this
// will refer to a valid peer_connection // will refer to a valid peer_connection
peer_connection* connection; peer_connection* connection;
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
// only used in debug mode to assert that // only used in debug mode to assert that
// the first entry in the AS pair keeps the same // the first entry in the AS pair keeps the same
boost::uint16_t inet_as_num; boost::uint16_t inet_as_num;
#endif #endif
// The AS this peer belongs to // The AS this peer belongs to
std::pair<const int, int>* inet_as; std::pair<const int, int>* inet_as;
#endif #endif
// the time when this peer was optimistically unchok
ed
// the last time. in seconds since session was creat
ed
// 16 bits is enough to last for 18.2 hours
// when the session time reaches 18 hours, it jumps
back by
// 9 hours, and all peers' times are updated to be
// relative to that new time offset
boost::uint16_t last_optimistically_unchoked;
// the time when the peer connected to us
// or disconnected if it isn't connected right now
// in number of seconds since session was created
boost::uint16_t last_connected;
// the port this peer is or was connected on // the port this peer is or was connected on
boost::uint16_t port; boost::uint16_t port;
// the upload and download rate limits set for this
peer
ufloat16 upload_rate_limit;
ufloat16 download_rate_limit;
// the number of times this peer has been
// part of a piece that failed the hash check
boost::uint8_t hashfails;
// the number of failed connection attempts // the number of failed connection attempts
// this peer has // this peer has
boost::uint8_t failcount; unsigned failcount:5; // [0, 31]
// incoming peers (that don't advertize their listen
port)
// will not be considered connectable. Peers that
// we have a listen port for will be assumed to be.
bool connectable:1;
// true if this peer currently is unchoked
// because of an optimistic unchoke.
// when the optimistic unchoke is moved to
// another peer, this peer will be choked
// if this is true
bool optimistically_unchoked:1;
// this is true if the peer is a seed
bool seed:1;
// the number of times we have allowed a fast
// reconnect for this peer.
unsigned fast_reconnects:4;
// for every valid piece we receive where this // for every valid piece we receive where this
// peer was one of the participants, we increase // peer was one of the participants, we increase
// this value. For every invalid piece we receive // this value. For every invalid piece we receive
// where this peer was a participant, we decrease // where this peer was a participant, we decrease
// this value. If it sinks below a threshold, its // this value. If it sinks below a threshold, its
// considered a bad peer and will be banned. // considered a bad peer and will be banned.
boost::int8_t trust_points; signed trust_points:4; // [-7, 8]
// a bitmap combining the peer_source flags // a bitmap combining the peer_source flags
// from peer_info. // from peer_info.
boost::uint8_t source; unsigned source:6;
// the number of times this peer has been
// part of a piece that failed the hash check
boost::uint8_t hashfails;
// type specifies if the connection was incoming
// or outgoing. If we ever saw this peer as connecta
ble
// it will remain as connectable
unsigned type:4;
// the number of times we have allowed a fast
// reconnect for this peer.
unsigned fast_reconnects:4;
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
// Hints encryption support of peer. Only effective // Hints encryption support of peer. Only effective
// for and when the outgoing encryption policy // for and when the outgoing encryption policy
// allows both encrypted and non encrypted // allows both encrypted and non encrypted
// connections (pe_settings::out_enc_policy // connections (pe_settings::out_enc_policy
// == enabled). The initial state of this flag // == enabled). The initial state of this flag
// determines the initial connection attempt // determines the initial connection attempt
// type (true = encrypted, false = standard). // type (true = encrypted, false = standard).
// This will be toggled everytime either an // This will be toggled everytime either an
// encrypted or non-encrypted handshake fails. // encrypted or non-encrypted handshake fails.
bool pe_support:1; bool pe_support:1;
#endif #endif
// true if this peer currently is unchoked
// because of an optimistic unchoke.
// when the optimistic unchoke is moved to
// another peer, this peer will be choked
// if this is true
bool optimistically_unchoked:1;
// this is true if the peer is a seed #if TORRENT_USE_IPV6
bool seed:1; // this is true if the v6 union member in addr is
// the one to use, false if it's the v4 one
bool is_v6_addr:1;
#endif
// if this is true, the peer has previously // if this is true, the peer has previously
// participated in a piece that failed the piece // participated in a piece that failed the piece
// hash check. This will put the peer on parole // hash check. This will put the peer on parole
// and only request entire pieces. If a piece pass // and only request entire pieces. If a piece pass
// that was partially requested from this peer it // that was partially requested from this peer it
// will leave parole mode and continue download // will leave parole mode and continue download
// pieces as normal peers. // pieces as normal peers.
bool on_parole:1; bool on_parole:1;
// is set to true if this peer has been banned // is set to true if this peer has been banned
bool banned:1; bool banned:1;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
// this is set to true when this peer as been // this is set to true when this peer as been
// pinged by the DHT // pinged by the DHT
bool added_to_dht:1; bool added_to_dht:1;
#endif #endif
}; };
struct TORRENT_EXPORT ipv4_peer : peer
{
ipv4_peer(tcp::endpoint const& ip, bool connectable,
int src);
ipv4_peer(libtorrent::address const& a);
address_v4 addr;
};
#if TORRENT_USE_IPV6
struct TORRENT_EXPORT ipv6_peer : peer
{
ipv6_peer(tcp::endpoint const& ip, bool connectable,
int src);
ipv6_peer(libtorrent::address const& a);
address_v6::bytes_type addr;
};
#endif
int num_peers() const { return m_peers.size(); } int num_peers() const { return m_peers.size(); }
typedef std::multimap<address, peer>::iterator iterator; struct peer_address_compare
typedef std::multimap<address, peer>::const_iterator const_i {
terator; bool operator()(
peer const* lhs, libtorrent::address const&
rhs) const
{
return lhs->address() < rhs;
}
bool operator()(
libtorrent::address const& lhs, peer const*
rhs) const
{
return lhs < rhs->address();
}
bool operator()(
peer const* lhs, peer const* rhs) const
{
return lhs->address() < rhs->address();
}
};
typedef std::deque<peer*> peers_t;
typedef peers_t::iterator iterator;
typedef peers_t::const_iterator const_iterator;
iterator begin_peer() { return m_peers.begin(); } iterator begin_peer() { return m_peers.begin(); }
iterator end_peer() { return m_peers.end(); } iterator end_peer() { return m_peers.end(); }
const_iterator begin_peer() const { return m_peers.begin(); } const_iterator begin_peer() const { return m_peers.begin(); }
const_iterator end_peer() const { return m_peers.end(); } const_iterator end_peer() const { return m_peers.end(); }
std::pair<iterator, iterator> find_peers(address const& a) std::pair<iterator, iterator> find_peers(address const& a)
{ return m_peers.equal_range(a); } {
return std::equal_range(
m_peers.begin(), m_peers.end(), a, peer_addr
ess_compare());
}
bool connect_one_peer(); std::pair<const_iterator, const_iterator> find_peers(address
const& a) const
{
return std::equal_range(
m_peers.begin(), m_peers.end(), a, peer_addr
ess_compare());
}
bool connect_one_peer(int session_time);
bool has_peer(policy::peer const* p) const; bool has_peer(policy::peer const* p) const;
int num_seeds() const { return m_num_seeds; } int num_seeds() const { return m_num_seeds; }
int num_connect_candidates() const { return m_num_connect_ca ndidates; } int num_connect_candidates() const { return m_num_connect_ca ndidates; }
void recalculate_connect_candidates(); void recalculate_connect_candidates();
void erase_peer(policy::peer* p);
void erase_peer(iterator i); void erase_peer(iterator i);
private: private:
bool compare_peer_erase(policy::peer const& lhs, policy::pee r const& rhs) const;
bool compare_peer(policy::peer const& lhs, policy::peer cons t& rhs bool compare_peer(policy::peer const& lhs, policy::peer cons t& rhs
, address const& external_ip) const; , address const& external_ip) const;
iterator find_connect_candidate(); iterator find_connect_candidate(int session_time);
bool is_connect_candidate(peer const& p, bool finished) cons t; bool is_connect_candidate(peer const& p, bool finished) cons t;
bool is_erase_candidate(peer const& p, bool finished) const;
bool should_erase_immediately(peer const& p) const;
std::multimap<address, peer> m_peers; void erase_peers();
peers_t m_peers;
// since the peer list can grow too large // since the peer list can grow too large
// to scan all of it, start at this iterator // to scan all of it, start at this iterator
iterator m_round_robin; int m_round_robin;
torrent* m_torrent; torrent* m_torrent;
// free download we have got that hasn't
// been distributed yet.
size_type m_available_free_upload;
// The number of peers in our peer list // The number of peers in our peer list
// that are connect candidates. i.e. they're // that are connect candidates. i.e. they're
// not already connected and they have not // not already connected and they have not
// yet reached their max try count and they // yet reached their max try count and they
// have the connectable state (we have a listen // have the connectable state (we have a listen
// port for them). // port for them).
int m_num_connect_candidates; int m_num_connect_candidates;
// the number of seeds in the peer list // the number of seeds in the peer list
int m_num_seeds; int m_num_seeds;
skipping to change at line 309 skipping to change at line 423
// last time we recalculated the number of // last time we recalculated the number of
// connect candidates. Since seeds (or upload // connect candidates. Since seeds (or upload
// only) peers are not connect candidates // only) peers are not connect candidates
// when we're finished, the set depends on // when we're finished, the set depends on
// this state. Every time m_torrent->is_finished() // this state. Every time m_torrent->is_finished()
// is different from this state, we need to // is different from this state, we need to
// recalculate the connect candidates. // recalculate the connect candidates.
bool m_finished; bool m_finished;
}; };
inline policy::ipv4_peer::ipv4_peer(
tcp::endpoint const& ep, bool c, int src
)
: peer(ep.port(), c, src)
, addr(ep.address().to_v4())
{
is_v6_addr = false;
}
inline policy::ipv4_peer::ipv4_peer(libtorrent::address const& a)
: addr(a.to_v4())
{
is_v6_addr = false;
}
inline policy::ipv6_peer::ipv6_peer(
tcp::endpoint const& ep, bool c, int src
)
: peer(ep.port(), c, src)
, addr(ep.address().to_v6().to_bytes())
{
is_v6_addr = true;
}
inline policy::ipv6_peer::ipv6_peer(libtorrent::address const& a)
: addr(a.to_v6().to_bytes())
{
is_v6_addr = true;
}
inline libtorrent::address policy::peer::address() const
{
#if TORRENT_USE_IPV6
if (is_v6_addr)
return libtorrent::address_v6(
static_cast<policy::ipv6_peer const*>(this)-
>addr);
#endif
return static_cast<policy::ipv4_peer const*>(this)->addr;
}
} }
#endif // TORRENT_POLICY_HPP_INCLUDED #endif // TORRENT_POLICY_HPP_INCLUDED
 End of changes. 31 change blocks. 
81 lines changed or deleted 246 lines changed or added


 proxy_base.hpp   proxy_base.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_PROXY_BASE_HPP_INCLUDED #ifndef TORRENT_PROXY_BASE_HPP_INCLUDED
#define TORRENT_PROXY_BASE_HPP_INCLUDED #define TORRENT_PROXY_BASE_HPP_INCLUDED
#include "libtorrent/io.hpp" #include "libtorrent/io.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/read.hpp> #include <asio/read.hpp>
#include <asio/write.hpp> #include <asio/write.hpp>
#else #else
#include <boost/asio/read.hpp> #include <boost/asio/read.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#endif #endif
namespace libtorrent { namespace libtorrent {
skipping to change at line 168 skipping to change at line 167
m_resolver.cancel(); m_resolver.cancel();
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
endpoint_type remote_endpoint() const endpoint_type remote_endpoint() const
{ {
return m_remote_endpoint; return m_remote_endpoint;
} }
#endif #endif
endpoint_type remote_endpoint(error_code& ec) const endpoint_type remote_endpoint(error_code& /*ec*/) const
{ {
return m_remote_endpoint; return m_remote_endpoint;
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
endpoint_type local_endpoint() const endpoint_type local_endpoint() const
{ {
return m_sock.local_endpoint(); return m_sock.local_endpoint();
} }
#endif #endif
 End of changes. 2 change blocks. 
2 lines changed or deleted 1 lines changed or added


 refresh.hpp   refresh.hpp 
skipping to change at line 58 skipping to change at line 58
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(refresh); TORRENT_DECLARE_LOG(refresh);
#endif #endif
class routing_table; class routing_table;
class rpc_manager; class rpc_manager;
class refresh : public traversal_algorithm class refresh : public traversal_algorithm
{ {
public: public:
typedef std::vector<node_entry>::iterator InIt;
typedef boost::function<void()> done_callback; typedef boost::function<void()> done_callback;
template<class InIt>
static void initiate(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
);
void ping_reply(node_id id); void ping_reply(node_id id);
void ping_timeout(node_id id, bool prevent_request = false); void ping_timeout(node_id id, bool prevent_request = false);
refresh(node_impl& node, node_id target, InIt first, InIt last
, done_callback const& callback);
virtual char const* name() const { return "refresh"; }
private: private:
template<class InIt>
refresh(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
);
void done(); void done();
void invoke(node_id const& id, udp::endpoint addr); void invoke(node_id const& id, udp::endpoint addr);
void invoke_pings_or_finish(bool prevent_request = false); void invoke_pings_or_finish(bool prevent_request = false);
int m_max_active_pings; int m_max_active_pings;
int m_active_pings; int m_active_pings;
done_callback m_done_callback; done_callback m_done_callback;
std::vector<result>::iterator m_leftover_nodes_iterator; std::vector<result>::iterator m_leftover_nodes_iterator;
}; };
class refresh_observer : public observer class refresh_observer : public observer
{ {
public: public:
refresh_observer( refresh_observer(
boost::intrusive_ptr<refresh> const& algorithm boost::intrusive_ptr<refresh> const& algorithm
, node_id self , node_id self)
, node_id target)
: observer(algorithm->allocator()) : observer(algorithm->allocator())
, m_target(target)
, m_self(self)
, m_algorithm(algorithm) , m_algorithm(algorithm)
, m_self(self)
{} {}
~refresh_observer(); ~refresh_observer();
void send(msg& m) void send(msg& m)
{ {
m.info_hash = m_target; m.info_hash = m_algorithm->target();
} }
void timeout(); void timeout();
void reply(msg const& m); void reply(msg const& m);
void abort() { m_algorithm = 0; } void abort() { m_algorithm = 0; }
private: private:
node_id const m_target;
node_id const m_self;
boost::intrusive_ptr<refresh> m_algorithm; boost::intrusive_ptr<refresh> m_algorithm;
node_id const m_self;
}; };
class ping_observer : public observer class ping_observer : public observer
{ {
public: public:
ping_observer( ping_observer(
boost::intrusive_ptr<refresh> const& algorithm boost::intrusive_ptr<refresh> const& algorithm
, node_id self) , node_id self)
: observer(algorithm->allocator()) : observer(algorithm->allocator())
, m_self(self) , m_self(self)
skipping to change at line 154 skipping to change at line 132
void send(msg& p) {} void send(msg& p) {}
void timeout(); void timeout();
void reply(msg const& m); void reply(msg const& m);
void abort() { m_algorithm = 0; } void abort() { m_algorithm = 0; }
private: private:
node_id const m_self; node_id const m_self;
boost::intrusive_ptr<refresh> m_algorithm; boost::intrusive_ptr<refresh> m_algorithm;
}; };
template<class InIt>
inline refresh::refresh( inline refresh::refresh(
node_id target node_impl& node
, int branch_factor , node_id target
, int max_active_pings , refresh::InIt first
, int max_results , refresh::InIt last
, routing_table& table , done_callback const& callback)
, InIt first : traversal_algorithm(node, target, first, last)
, InIt last , m_max_active_pings(10)
, rpc_manager& rpc
, done_callback const& callback
)
: traversal_algorithm(
target
, branch_factor
, max_results
, table
, rpc
, first
, last
)
, m_max_active_pings(max_active_pings)
, m_active_pings(0) , m_active_pings(0)
, m_done_callback(callback) , m_done_callback(callback)
{ {
boost::intrusive_ptr<refresh> self(this); boost::intrusive_ptr<refresh> self(this);
add_requests(); add_requests();
} }
template<class InIt>
inline void refresh::initiate(
node_id target
, int branch_factor
, int max_active_pings
, int max_results
, routing_table& table
, InIt first
, InIt last
, rpc_manager& rpc
, done_callback const& callback
)
{
new refresh(
target
, branch_factor
, max_active_pings
, max_results
, table
, first
, last
, rpc
, callback
);
}
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // REFRESH_050324_HPP #endif // REFRESH_050324_HPP
 End of changes. 13 change blocks. 
79 lines changed or deleted 17 lines changed or added


 routing_table.hpp   routing_table.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef ROUTING_TABLE_HPP #ifndef ROUTING_TABLE_HPP
#define ROUTING_TABLE_HPP #define ROUTING_TABLE_HPP
#include <vector> #include <vector>
#include <deque>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/iterator/iterator_facade.hpp> #include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_categories.hpp> #include <boost/iterator/iterator_categories.hpp>
#include <boost/utility.hpp> #include <boost/utility.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/array.hpp> #include <boost/array.hpp>
#include <set> #include <set>
#include <libtorrent/kademlia/logging.hpp> #include <libtorrent/kademlia/logging.hpp>
#include <libtorrent/kademlia/node_id.hpp> #include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/node_entry.hpp> #include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/session_settings.hpp> #include <libtorrent/session_settings.hpp>
#include <libtorrent/size_type.hpp> #include <libtorrent/size_type.hpp>
#include <libtorrent/assert.hpp> #include <libtorrent/assert.hpp>
namespace libtorrent
{
struct session_status;
}
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(table); TORRENT_DECLARE_LOG(table);
#endif #endif
typedef std::vector<node_entry> bucket_t; typedef std::vector<node_entry> bucket_t;
// differences in the implementation from the description in // differences in the implementation from the description in
skipping to change at line 153 skipping to change at line 157
bucket_iterator_t m_bucket_end; bucket_iterator_t m_bucket_end;
// when debug iterators are enabled, default constructed // when debug iterators are enabled, default constructed
// iterators are not allowed to be copied. In the case // iterators are not allowed to be copied. In the case
// where the routing table is empty, m_iterator would be // where the routing table is empty, m_iterator would be
// default constructed and not copyable. // default constructed and not copyable.
boost::optional<bucket_t::const_iterator> m_iterator; boost::optional<bucket_t::const_iterator> m_iterator;
}; };
} // namespace aux } // namespace aux
class routing_table class TORRENT_EXPORT routing_table
{ {
public: public:
typedef aux::routing_table_iterator iterator; typedef aux::routing_table_iterator iterator;
typedef iterator const_iterator; typedef iterator const_iterator;
routing_table(node_id const& id, int bucket_size routing_table(node_id const& id, int bucket_size
, dht_settings const& settings); , dht_settings const& settings);
void status(session_status& s) const;
void node_failed(node_id const& id); void node_failed(node_id const& id);
// adds an endpoint that will never be added to // adds an endpoint that will never be added to
// the routing table // the routing table
void add_router_node(udp::endpoint router); void add_router_node(udp::endpoint router);
// iterates over the router nodes added // iterates over the router nodes added
typedef std::set<udp::endpoint>::const_iterator router_iterator; typedef std::set<udp::endpoint>::const_iterator router_iterator;
router_iterator router_begin() const { return m_router_nodes.begin() ; } router_iterator router_begin() const { return m_router_nodes.begin() ; }
router_iterator router_end() const { return m_router_nodes.end(); } router_iterator router_end() const { return m_router_nodes.end(); }
skipping to change at line 185 skipping to change at line 191
// be inserted in the k-buckets or be moved to the top // be inserted in the k-buckets or be moved to the top
// of its bucket. // of its bucket.
bool node_seen(node_id const& id, udp::endpoint addr); bool node_seen(node_id const& id, udp::endpoint addr);
// returns time when the given bucket needs another refresh. // returns time when the given bucket needs another refresh.
// if the given bucket is empty but there are nodes // if the given bucket is empty but there are nodes
// in a bucket closer to us, or if the bucket is non-empty and // in a bucket closer to us, or if the bucket is non-empty and
// the time from the last activity is more than 15 minutes // the time from the last activity is more than 15 minutes
ptime next_refresh(int bucket); ptime next_refresh(int bucket);
enum
{
include_self = 1,
include_failed = 2
};
// fills the vector with the count nodes from our buckets that // fills the vector with the count nodes from our buckets that
// are nearest to the given id. // are nearest to the given id.
void find_node(node_id const& id, std::vector<node_entry>& l void find_node(node_id const& id, std::vector<node_entry>& l
, bool include_self, int count = 0); , int options, int count = 0);
// returns true if the given node would be placed in a bucket // this may add a node to the routing table and mark it as
// that is not full. If the node already exists in the table // not pinged. If the bucket the node falls into is full,
// this function returns false // the node will be ignored.
bool need_node(node_id const& id); void heard_about(node_id const& id, udp::endpoint const& ep);
// this will set the given bucket's latest activity // this will set the given bucket's latest activity
// to the current time // to the current time
void touch_bucket(int bucket); void touch_bucket(int bucket);
int bucket_size(int bucket) int bucket_size(int bucket)
{ {
TORRENT_ASSERT(bucket >= 0 && bucket < 160); TORRENT_ASSERT(bucket >= 0 && bucket < 160);
return (int)m_buckets[bucket].first.size(); return (int)m_buckets[bucket].first.size();
} }
skipping to change at line 240 skipping to change at line 251
dht_settings const& m_settings; dht_settings const& m_settings;
// 160 (k-bucket, replacement cache) pairs // 160 (k-bucket, replacement cache) pairs
typedef boost::array<std::pair<bucket_t, bucket_t>, 160> table_t; typedef boost::array<std::pair<bucket_t, bucket_t>, 160> table_t;
table_t m_buckets; table_t m_buckets;
// timestamps of the last activity in each bucket // timestamps of the last activity in each bucket
typedef boost::array<ptime, 160> table_activity_t; typedef boost::array<ptime, 160> table_activity_t;
table_activity_t m_bucket_activity; table_activity_t m_bucket_activity;
node_id m_id; // our own node id node_id m_id; // our own node id
// the last time need_bootstrap() returned true
mutable ptime m_last_bootstrap;
// this is a set of all the endpoints that have // this is a set of all the endpoints that have
// been identified as router nodes. They will // been identified as router nodes. They will
// be used in searches, but they will never // be used in searches, but they will never
// be added to the routing table. // be added to the routing table.
std::set<udp::endpoint> m_router_nodes; std::set<udp::endpoint> m_router_nodes;
// this is the lowest bucket index with nodes in it // this is the lowest bucket index with nodes in it
int m_lowest_active_bucket; int m_lowest_active_bucket;
}; };
 End of changes. 8 change blocks. 
7 lines changed or deleted 21 lines changed or added


 rpc_manager.hpp   rpc_manager.hpp 
skipping to change at line 94 skipping to change at line 94
void unreachable(udp::endpoint const& ep); void unreachable(udp::endpoint const& ep);
// returns true if the node needs a refresh // returns true if the node needs a refresh
bool incoming(msg const&); bool incoming(msg const&);
time_duration tick(); time_duration tick();
void invoke(int message_id, udp::endpoint target void invoke(int message_id, udp::endpoint target
, observer_ptr o); , observer_ptr o);
void reply(msg& m); void reply(msg& m);
void reply_with_ping(msg& m);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
size_t allocation_size() const; size_t allocation_size() const;
void check_invariant() const; void check_invariant() const;
#endif #endif
boost::pool<>& allocator() const boost::pool<>& allocator() const
{ return m_pool_allocator; } { return m_pool_allocator; }
private: private:
 End of changes. 1 change blocks. 
1 lines changed or deleted 0 lines changed or added


 session.hpp   session.hpp 
skipping to change at line 36 skipping to change at line 36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_SESSION_HPP_INCLUDED #ifndef TORRENT_SESSION_HPP_INCLUDED
#define TORRENT_SESSION_HPP_INCLUDED #define TORRENT_SESSION_HPP_INCLUDED
#include <ctime>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <set>
#include <list>
#include <deque>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/session_status.hpp" #include "libtorrent/session_status.hpp"
#include "libtorrent/version.hpp" #include "libtorrent/version.hpp"
#include "libtorrent/fingerprint.hpp" #include "libtorrent/fingerprint.hpp"
#include "libtorrent/time.hpp"
#include "libtorrent/disk_io_thread.hpp" #include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include <boost/preprocessor/cat.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
# include <eh.h> # include <eh.h>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
struct torrent_plugin; struct torrent_plugin;
class torrent; class torrent;
struct ip_filter; class ip_filter;
class port_filter; class port_filter;
class connection_queue; class connection_queue;
class natpmp; class natpmp;
class upnp; class upnp;
class alert;
// this is used to create linker errors when trying to link to
// a library with a conflicting build configuration than the applica
tion
#ifdef TORRENT_DEBUG
#define G _release
#else
#define G _debug
#endif
#ifdef TORRENT_USE_OPENSSL
#define S _ssl
#else
#define S _nossl
#endif
#ifdef TORRENT_DISABLE_DHT
#define D _nodht
#else
#define D _dht
#endif
#ifdef TORRENT_DISABLE_POOL_ALLOCATOR
#define P _nopoolalloc
#else
#define P _poolalloc
#endif
#define TORRENT_LINK_TEST_PREFIX libtorrent_build_config
#define TORRENT_LINK_TEST_NAME BOOST_PP_CAT(TORRENT_LINK_TEST_PREFIX, BOOST
_PP_CAT(P, BOOST_PP_CAT(D, BOOST_PP_CAT(S, G))))
#undef P
#undef D
#undef S
#undef G
inline void test_link()
{
extern void TORRENT_LINK_TEST_NAME();
TORRENT_LINK_TEST_NAME();
}
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
session_settings min_memory_usage();
session_settings high_performance_seed();
namespace aux namespace aux
{ {
// workaround for microsofts // workaround for microsofts
// hardware exceptions that makes // hardware exceptions that makes
// it hard to debug stuff // it hard to debug stuff
#ifdef _MSC_VER #ifdef _MSC_VER
struct eh_initializer struct eh_initializer
{ {
eh_initializer() eh_initializer()
{ {
skipping to change at line 136 skipping to change at line 174
add_torrent_params(storage_constructor_type sc = default_sto rage_constructor) add_torrent_params(storage_constructor_type sc = default_sto rage_constructor)
: tracker_url(0) : tracker_url(0)
, name(0) , name(0)
, resume_data(0) , resume_data(0)
, storage_mode(storage_mode_sparse) , storage_mode(storage_mode_sparse)
, paused(true) , paused(true)
, auto_managed(true) , auto_managed(true)
, duplicate_is_error(false) , duplicate_is_error(false)
, storage(sc) , storage(sc)
, userdata(0) , userdata(0)
, seed_mode(false)
, override_resume_data(false)
, upload_mode(false)
{} {}
boost::intrusive_ptr<torrent_info> ti; boost::intrusive_ptr<torrent_info> ti;
char const* tracker_url; char const* tracker_url;
sha1_hash info_hash; sha1_hash info_hash;
char const* name; char const* name;
fs::path save_path; fs::path save_path;
std::vector<char>* resume_data; std::vector<char>* resume_data;
storage_mode_t storage_mode; storage_mode_t storage_mode;
bool paused; bool paused;
bool auto_managed; bool auto_managed;
bool duplicate_is_error; bool duplicate_is_error;
storage_constructor_type storage; storage_constructor_type storage;
void* userdata; void* userdata;
bool seed_mode;
bool override_resume_data;
bool upload_mode;
}; };
class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_ini tializer class TORRENT_EXPORT session: public boost::noncopyable, aux::eh_ini tializer
{ {
public: public:
session(fingerprint const& print = fingerprint("LT" session(fingerprint const& print = fingerprint("LT"
, LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR , 0, 0) , LIBTORRENT_VERSION_MAJOR, LIBTORRENT_VERSION_MINOR , 0, 0)
, int flags = start_default_features | add_default_p lugins , int flags = start_default_features | add_default_p lugins
, int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING
, fs::path logpath = "." , fs::path logpath = "."
#endif #endif
); );
session( session(
fingerprint const& print fingerprint const& print
, std::pair<int, int> listen_port_range , std::pair<int, int> listen_port_range
, char const* listen_interface = "0.0.0.0" , char const* listen_interface = "0.0.0.0"
, int flags = start_default_features | add_default_p lugins , int flags = start_default_features | add_default_p lugins
, int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING
, fs::path logpath = "." , fs::path logpath = "."
#endif #endif
); );
~session(); ~session();
enum save_state_flags_t
{
save_settings = 0x001,
save_dht_settings = 0x002,
save_dht_proxy = 0x004,
save_dht_state = 0x008,
save_i2p_proxy = 0x010,
save_encryption_settings = 0x020,
save_peer_proxy = 0x040,
save_web_proxy = 0x080,
save_tracker_proxy = 0x100,
save_as_map = 0x200,
};
void save_state(entry& e, boost::uint32_t flags = 0xffffffff
) const;
void load_state(lazy_entry const& e);
// returns a list of all torrents in this session // returns a list of all torrents in this session
std::vector<torrent_handle> get_torrents() const; std::vector<torrent_handle> get_torrents() const;
io_service& get_io_service();
// returns an invalid handle in case the torrent doesn't exi st // returns an invalid handle in case the torrent doesn't exi st
torrent_handle find_torrent(sha1_hash const& info_hash) cons t; torrent_handle find_torrent(sha1_hash const& info_hash) cons t;
// all torrent_handles must be destructed before the session is destructed! // all torrent_handles must be destructed before the session is destructed!
torrent_handle add_torrent(add_torrent_params const& params) ; torrent_handle add_torrent(add_torrent_params const& params) ;
torrent_handle add_torrent(add_torrent_params const& params, error_code& ec);
#ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.14 // deprecated in 0.14
TORRENT_DEPRECATED_PREFIX
torrent_handle add_torrent( torrent_handle add_torrent(
torrent_info const& ti torrent_info const& ti
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data = entry() , entry const& resume_data = entry()
, storage_mode_t storage_mode = storage_mode_sparse , storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false , bool paused = false
, storage_constructor_type sc = default_storage_cons tructor) TORRENT_DEPRECATED; , storage_constructor_type sc = default_storage_cons tructor) TORRENT_DEPRECATED;
// deprecated in 0.14 // deprecated in 0.14
TORRENT_DEPRECATED_PREFIX
torrent_handle add_torrent( torrent_handle add_torrent(
boost::intrusive_ptr<torrent_info> ti boost::intrusive_ptr<torrent_info> ti
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data = entry() , entry const& resume_data = entry()
, storage_mode_t storage_mode = storage_mode_sparse , storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false , bool paused = false
, storage_constructor_type sc = default_storage_cons tructor , storage_constructor_type sc = default_storage_cons tructor
, void* userdata = 0) TORRENT_DEPRECATED; , void* userdata = 0) TORRENT_DEPRECATED;
// deprecated in 0.14 // deprecated in 0.14
TORRENT_DEPRECATED_PREFIX
torrent_handle add_torrent( torrent_handle add_torrent(
char const* tracker_url char const* tracker_url
, sha1_hash const& info_hash , sha1_hash const& info_hash
, char const* name , char const* name
, fs::path const& save_path , fs::path const& save_path
, entry const& resume_data = entry() , entry const& resume_data = entry()
, storage_mode_t storage_mode = storage_mode_sparse , storage_mode_t storage_mode = storage_mode_sparse
, bool paused = false , bool paused = false
, storage_constructor_type sc = default_storage_cons tructor , storage_constructor_type sc = default_storage_cons tructor
, void* userdata = 0) TORRENT_DEPRECATED; , void* userdata = 0) TORRENT_DEPRECATED;
#endif #endif
#endif
session_proxy abort() { return session_proxy(m_impl); } session_proxy abort() { return session_proxy(m_impl); }
void pause(); void pause();
void resume(); void resume();
bool is_paused() const; bool is_paused() const;
session_status status() const; session_status status() const;
cache_status get_cache_status() const; cache_status get_cache_status() const;
void get_cache_info(sha1_hash const& ih void get_cache_info(sha1_hash const& ih
, std::vector<cached_piece_info>& ret) const; , std::vector<cached_piece_info>& ret) const;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void start_dht(entry const& startup_state = entry()); void start_dht();
void stop_dht(); void stop_dht();
void set_dht_settings(dht_settings const& settings); void set_dht_settings(dht_settings const& settings);
entry dht_state() const; #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.15
// use save_state and load_state instead
TORRENT_DEPRECATED_PREFIX
entry dht_state() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void start_dht(entry const& startup_state) TORRENT_DEPRECATE
D;
#endif
void add_dht_node(std::pair<std::string, int> const& node); void add_dht_node(std::pair<std::string, int> const& node);
void add_dht_router(std::pair<std::string, int> const& node) ; void add_dht_router(std::pair<std::string, int> const& node) ;
bool is_dht_running() const;
#endif #endif
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings); void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const; pe_settings const& get_pe_settings() const;
#endif #endif
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent _plugin>(torrent*, void*)> ext); void add_extension(boost::function<boost::shared_ptr<torrent _plugin>(torrent*, void*)> ext);
#endif #endif
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
int as_for_ip(address const& addr); int as_for_ip(address const& addr);
bool load_asnum_db(char const* file); bool load_asnum_db(char const* file);
bool load_country_db(char const* file); bool load_country_db(char const* file);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
bool load_country_db(wchar_t const* file);
bool load_asnum_db(wchar_t const* file);
#endif
#endif #endif
void load_state(entry const& ses_state); #ifndef TORRENT_NO_DEPRECATE
entry state() const; // deprecated in 0.15
// use load_state and save_state instead
TORRENT_DEPRECATED_PREFIX
void load_state(entry const& ses_state) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
entry state() const TORRENT_DEPRECATED;
#endif
void set_ip_filter(ip_filter const& f); void set_ip_filter(ip_filter const& f);
ip_filter const& get_ip_filter() const; ip_filter const& get_ip_filter() const;
void set_port_filter(port_filter const& f); void set_port_filter(port_filter const& f);
void set_peer_id(peer_id const& pid); void set_peer_id(peer_id const& pid);
void set_key(int key); void set_key(int key);
peer_id id() const; peer_id id() const;
bool is_listening() const; bool is_listening() const;
skipping to change at line 323 skipping to change at line 411
proxy_settings const& web_seed_proxy() const; proxy_settings const& web_seed_proxy() const;
proxy_settings const& tracker_proxy() const; proxy_settings const& tracker_proxy() const;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void set_dht_proxy(proxy_settings const& s); void set_dht_proxy(proxy_settings const& s);
proxy_settings const& dht_proxy() const; proxy_settings const& dht_proxy() const;
#endif #endif
int upload_rate_limit() const; int upload_rate_limit() const;
int download_rate_limit() const; int download_rate_limit() const;
int local_upload_rate_limit() const;
int local_download_rate_limit() const;
int max_half_open_connections() const; int max_half_open_connections() const;
void set_local_upload_rate_limit(int bytes_per_second);
void set_local_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second); void set_upload_rate_limit(int bytes_per_second);
void set_download_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second);
void set_max_uploads(int limit); void set_max_uploads(int limit);
void set_max_connections(int limit); void set_max_connections(int limit);
void set_max_half_open_connections(int limit); void set_max_half_open_connections(int limit);
int max_connections() const;
int max_uploads() const;
std::auto_ptr<alert> pop_alert(); std::auto_ptr<alert> pop_alert();
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX
void set_severity_level(alert::severity_t s) TORRENT_DEPRECA TED; void set_severity_level(alert::severity_t s) TORRENT_DEPRECA TED;
#endif #endif
void set_alert_mask(int m); void set_alert_mask(int m);
size_t set_alert_queue_size_limit(size_t queue_size_limit_); size_t set_alert_queue_size_limit(size_t queue_size_limit_);
alert const* wait_for_alert(time_duration max_wait); alert const* wait_for_alert(time_duration max_wait);
void set_alert_dispatch(boost::function<void(alert const&)> const& fun);
connection_queue& get_connection_queue(); connection_queue& get_connection_queue();
// starts/stops UPnP, NATPMP or LSD port mappers // starts/stops UPnP, NATPMP or LSD port mappers
// they are stopped by default // they are stopped by default
void start_lsd(); void start_lsd();
natpmp* start_natpmp(); natpmp* start_natpmp();
upnp* start_upnp(); upnp* start_upnp();
void stop_lsd(); void stop_lsd();
 End of changes. 32 change blocks. 
12 lines changed or deleted 113 lines changed or added


 session_impl.hpp   session_impl.hpp 
skipping to change at line 36 skipping to change at line 36
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED #ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED
#define TORRENT_SESSION_IMPL_HPP_INCLUDED #define TORRENT_SESSION_IMPL_HPP_INCLUDED
#include <ctime>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <set> #include <set>
#include <list> #include <list>
#include <deque>
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
#ifdef WITH_SHIPPED_GEOIP_H #ifdef WITH_SHIPPED_GEOIP_H
#include "libtorrent/GeoIP.h" #include "libtorrent/GeoIP.h"
#else #else
#include <GeoIP.h> #include <GeoIP.h>
#endif #endif
#endif #endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/limits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/thread/recursive_mutex.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <boost/pool/object_pool.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/tracker_manager.hpp" #include "libtorrent/tracker_manager.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/debug.hpp" #include "libtorrent/debug.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/ip_filter.hpp" #include "libtorrent/ip_filter.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/session_status.hpp" #include "libtorrent/session_status.hpp"
#include "libtorrent/session.hpp" #include "libtorrent/session.hpp"
#include "libtorrent/stat.hpp" #include "libtorrent/stat.hpp"
#include "libtorrent/file_pool.hpp" #include "libtorrent/file_pool.hpp"
#include "libtorrent/bandwidth_manager.hpp" #include "libtorrent/bandwidth_manager.hpp"
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/disk_io_thread.hpp" #include "libtorrent/disk_io_thread.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/udp_socket.hpp" #include "libtorrent/udp_socket.hpp"
#include "libtorrent/assert.hpp"
#include "libtorrent/policy.hpp" // for policy::peer
#include "libtorrent/alert.hpp" // for alert_manager
#if TORRENT_COMPLETE_TYPES_REQUIRED #if TORRENT_COMPLETE_TYPES_REQUIRED
#include "libtorrent/peer_connection.hpp" #include "libtorrent/peer_connection.hpp"
#endif #endif
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
class peer_connection; class peer_connection;
class upnp; class upnp;
class natpmp; class natpmp;
class lsd; class lsd;
struct fingerprint; struct fingerprint;
class torrent;
class alert;
namespace dht namespace dht
{ {
class dht_tracker; struct dht_tracker;
} }
namespace aux namespace aux
{ {
struct session_impl; struct session_impl;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING
struct tracker_logger; struct tracker_logger;
#endif #endif
// used to initialize the g_current_time before
// anything else
struct initialize_timer
{
initialize_timer();
};
// this is the link between the main thread and the // this is the link between the main thread and the
// thread started to run the main downloader loop // thread started to run the main downloader loop
struct session_impl: boost::noncopyable struct session_impl: boost::noncopyable, initialize_timer
{ {
// the size of each allocation that is chained in th e send buffer // the size of each allocation that is chained in th e send buffer
enum { send_buffer_size = 200 }; enum { send_buffer_size = 128 };
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
friend class ::libtorrent::peer_connection; friend class ::libtorrent::peer_connection;
#endif #endif
friend struct checker_impl; friend struct checker_impl;
friend class invariant_access; friend class invariant_access;
typedef std::set<boost::intrusive_ptr<peer_connectio n> > connection_map; typedef std::set<boost::intrusive_ptr<peer_connectio n> > connection_map;
typedef std::map<sha1_hash, boost::shared_ptr<torren t> > torrent_map; typedef std::map<sha1_hash, boost::shared_ptr<torren t> > torrent_map;
session_impl( session_impl(
skipping to change at line 164 skipping to change at line 170
void open_listen_port(); void open_listen_port();
// if we are listening on an IPv6 interface // if we are listening on an IPv6 interface
// this will return one of the IPv6 addresses on thi s // this will return one of the IPv6 addresses on thi s
// machine, otherwise just an empty endpoint // machine, otherwise just an empty endpoint
tcp::endpoint get_ipv6_interface() const; tcp::endpoint get_ipv6_interface() const;
tcp::endpoint get_ipv4_interface() const; tcp::endpoint get_ipv4_interface() const;
void async_accept(boost::shared_ptr<socket_acceptor> const& listener); void async_accept(boost::shared_ptr<socket_acceptor> const& listener);
void on_incoming_connection(boost::shared_ptr<socket _type> const& s void on_accept_connection(boost::shared_ptr<socket_t ype> const& s
, boost::weak_ptr<socket_acceptor> listener, error_code const& e); , boost::weak_ptr<socket_acceptor> listener, error_code const& e);
void on_socks_accept(boost::shared_ptr<socket_type>
const& s
, error_code const& e);
void incoming_connection(boost::shared_ptr<socket_ty
pe> const& s);
// must be locked to access the data // must be locked to access the data
// in this struct // in this struct
typedef boost::recursive_mutex mutex_t; typedef boost::mutex mutex_t;
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
boost::weak_ptr<torrent> find_torrent(const sha1_has h& info_hash); boost::weak_ptr<torrent> find_torrent(const sha1_has h& info_hash);
peer_id const& get_peer_id() const { return m_peer_i d; } peer_id const& get_peer_id() const { return m_peer_i d; }
void close_connection(peer_connection const* p void close_connection(peer_connection const* p, erro
, char const* message); r_code const& ec);
void set_settings(session_settings const& s); void set_settings(session_settings const& s);
session_settings const& settings() const { return m_ settings; } session_settings const& settings() const { return m_ settings; }
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void add_dht_node(std::pair<std::string, int> const& node); void add_dht_node(std::pair<std::string, int> const& node);
void add_dht_node(udp::endpoint n); void add_dht_node(udp::endpoint n);
void add_dht_router(std::pair<std::string, int> cons t& node); void add_dht_router(std::pair<std::string, int> cons t& node);
void set_dht_settings(dht_settings const& s); void set_dht_settings(dht_settings const& s);
dht_settings const& get_dht_settings() const { retur n m_dht_settings; } dht_settings const& get_dht_settings() const { retur n m_dht_settings; }
void start_dht(entry const& startup_state); void start_dht();
void stop_dht(); void stop_dht();
void start_dht(entry const& startup_state);
entry dht_state() const; #ifndef TORRENT_NO_DEPRECATE
entry dht_state(session_impl::mutex_t::scoped_lock&
l) const;
#endif
void maybe_update_udp_mapping(int nat, int local_por
t, int external_port);
void on_dht_router_name_lookup(error_code const& e void on_dht_router_name_lookup(error_code const& e
, tcp::resolver::iterator host); , tcp::resolver::iterator host);
#endif #endif
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
void set_pe_settings(pe_settings const& settings); void set_pe_settings(pe_settings const& settings);
pe_settings const& get_pe_settings() const { return m_pe_settings; } pe_settings const& get_pe_settings() const { return m_pe_settings; }
#endif #endif
void on_port_map_log(char const* msg, int map_transp
ort);
void on_lsd_announce(error_code const& e);
// called when a port mapping is successful, or a ro uter returns // called when a port mapping is successful, or a ro uter returns
// a failure to map a port // a failure to map a port
void on_port_mapping(int mapping, int port, std::str ing const& errmsg void on_port_mapping(int mapping, int port, error_co de const& ec
, int nat_transport); , int nat_transport);
bool is_aborted() const { return m_abort; } bool is_aborted() const { return m_abort; }
bool is_paused() const { return m_paused; } bool is_paused() const { return m_paused; }
void pause(); void pause();
void resume(); void resume();
void set_ip_filter(ip_filter const& f); void set_ip_filter(ip_filter const& f);
ip_filter const& get_ip_filter() const; ip_filter const& get_ip_filter() const;
void set_port_filter(port_filter const& f); void set_port_filter(port_filter const& f);
bool listen_on( bool listen_on(
std::pair<int, int> const& port_range std::pair<int, int> const& port_range
, const char* net_interface = 0); , const char* net_interface = 0);
bool is_listening() const; bool is_listening() const;
torrent_handle add_torrent(add_torrent_params const& ); torrent_handle add_torrent(add_torrent_params const& , error_code& ec);
void remove_torrent(torrent_handle const& h, int opt ions); void remove_torrent(torrent_handle const& h, int opt ions);
std::vector<torrent_handle> get_torrents(); std::vector<torrent_handle> get_torrents();
void check_torrent(boost::shared_ptr<torrent> const& void queue_check_torrent(boost::shared_ptr<torrent>
t); const& t);
void done_checking(boost::shared_ptr<torrent> const& void dequeue_check_torrent(boost::shared_ptr<torrent
t); > const& t);
void set_alert_mask(int m); void set_alert_mask(int m);
size_t set_alert_queue_size_limit(size_t queue_size_ limit_); size_t set_alert_queue_size_limit(size_t queue_size_ limit_);
std::auto_ptr<alert> pop_alert(); std::auto_ptr<alert> pop_alert();
void set_alert_dispatch(boost::function<void(alert c onst&)> const&);
alert const* wait_for_alert(time_duration max_wait); alert const* wait_for_alert(time_duration max_wait);
int upload_rate_limit() const; int upload_rate_limit() const;
int download_rate_limit() const; int download_rate_limit() const;
int local_upload_rate_limit() const;
int local_download_rate_limit() const;
void set_local_download_rate_limit(int bytes_per_sec
ond);
void set_local_upload_rate_limit(int bytes_per_secon
d);
void set_download_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second);
void set_upload_rate_limit(int bytes_per_second); void set_upload_rate_limit(int bytes_per_second);
void set_max_half_open_connections(int limit); void set_max_half_open_connections(int limit);
void set_max_connections(int limit); void set_max_connections(int limit);
void set_max_uploads(int limit); void set_max_uploads(int limit);
int max_connections() const { return m_max_connectio ns; } int max_connections() const { return m_max_connectio ns; }
int max_uploads() const { return m_max_uploads; } int max_uploads() const { return m_max_uploads; }
int max_half_open_connections() const { return m_hal f_open.limit(); } int max_half_open_connections() const { return m_hal f_open.limit(); }
int num_uploads() const { return m_num_unchoked; } int num_uploads() const { return m_num_unchoked; }
int num_connections() const int num_connections() const
{ return m_connections.size(); } { return m_connections.size(); }
void unchoke_peer(peer_connection& c); void unchoke_peer(peer_connection& c);
void choke_peer(peer_connection& c);
session_status status() const; session_status status() const;
void set_peer_id(peer_id const& id); void set_peer_id(peer_id const& id);
void set_key(int key); void set_key(int key);
unsigned short listen_port() const; unsigned short listen_port() const;
void abort(); void abort();
torrent_handle find_torrent_handle(sha1_hash const& info_hash); torrent_handle find_torrent_handle(sha1_hash const& info_hash);
void announce_lsd(sha1_hash const& ih); void announce_lsd(sha1_hash const& ih);
void save_state(entry& e, boost::uint32_t flags, ses
sion_impl::mutex_t::scoped_lock& l) const;
void load_state(lazy_entry const& e);
void set_peer_proxy(proxy_settings const& s) void set_peer_proxy(proxy_settings const& s)
{ m_peer_proxy = s; } {
m_peer_proxy = s;
// in case we just set a socks proxy, we mig
ht have to
// open the socks incoming connection
if (!m_socks_listen_socket) open_new_incomin
g_socks_connection();
}
void set_web_seed_proxy(proxy_settings const& s) void set_web_seed_proxy(proxy_settings const& s)
{ m_web_seed_proxy = s; } { m_web_seed_proxy = s; }
void set_tracker_proxy(proxy_settings const& s) void set_tracker_proxy(proxy_settings const& s)
{ m_tracker_proxy = s; } { m_tracker_proxy = s; }
proxy_settings const& peer_proxy() const proxy_settings const& peer_proxy() const
{ return m_peer_proxy; } { return m_peer_proxy; }
proxy_settings const& web_seed_proxy() const proxy_settings const& web_seed_proxy() const
{ return m_web_seed_proxy; } { return m_web_seed_proxy; }
proxy_settings const& tracker_proxy() const proxy_settings const& tracker_proxy() const
skipping to change at line 300 skipping to change at line 332
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
std::string as_name_for_ip(address const& a); std::string as_name_for_ip(address const& a);
int as_for_ip(address const& a); int as_for_ip(address const& a);
std::pair<const int, int>* lookup_as(int as); std::pair<const int, int>* lookup_as(int as);
bool load_asnum_db(char const* file); bool load_asnum_db(char const* file);
bool has_asnum_db() const { return m_asnum_db; } bool has_asnum_db() const { return m_asnum_db; }
bool load_country_db(char const* file); bool load_country_db(char const* file);
bool has_country_db() const { return m_country_db; } bool has_country_db() const { return m_country_db; }
char const* country_for_ip(address const& a); char const* country_for_ip(address const& a);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
bool load_asnum_db(wchar_t const* file);
bool load_country_db(wchar_t const* file);
#endif
#endif #endif
void load_state(entry const& ses_state); void load_state(entry const& ses_state);
entry state() const; entry state() const;
void start_lsd(); void start_lsd();
natpmp* start_natpmp(); void start_natpmp(natpmp* n);
upnp* start_upnp(); void start_upnp(upnp* u);
void stop_lsd(); void stop_lsd();
void stop_natpmp(); void stop_natpmp();
void stop_upnp(); void stop_upnp();
int next_port(); int next_port();
void add_redundant_bytes(size_type b) void add_redundant_bytes(size_type b)
{ {
TORRENT_ASSERT(b > 0); TORRENT_ASSERT(b > 0);
m_total_redundant_bytes += b; m_total_redundant_bytes += b;
} }
void add_failed_bytes(size_type b) void add_failed_bytes(size_type b)
{ {
TORRENT_ASSERT(b > 0); TORRENT_ASSERT(b > 0);
m_total_failed_bytes += b; m_total_failed_bytes += b;
} }
// handles delayed alerts
alert_manager m_alerts;
std::pair<char*, int> allocate_buffer(int size); std::pair<char*, int> allocate_buffer(int size);
void free_buffer(char* buf, int size); void free_buffer(char* buf, int size);
char* allocate_disk_buffer(); char* allocate_disk_buffer(char const* category);
void free_disk_buffer(char* buf); void free_disk_buffer(char* buf);
void set_external_address(address const& ip); void set_external_address(address const& ip);
address const& external_address() const { return m_e xternal_address; } address const& external_address() const { return m_e xternal_address; }
// private: // private:
void dht_state_callback(boost::condition& c void update_disk_thread_settings();
void on_dht_state_callback(boost::condition& c
, entry& e, bool& done) const; , entry& e, bool& done) const;
void on_lsd_peer(tcp::endpoint peer, sha1_hash const & ih); void on_lsd_peer(tcp::endpoint peer, sha1_hash const & ih);
void setup_socket_buffers(socket_type& s);
// this is a shared pool where policy_peer objects
// are allocated. It's a pool since we're likely
// to have tens of thousands of peers, and a pool
// saves significant overhead
#ifdef TORRENT_STATS
struct logging_allocator
{
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
static char* malloc(const size_type bytes)
{
allocated_bytes += bytes;
++allocations;
return (char*)::malloc(bytes);
}
static void free(char* const block)
{
--allocations;
return ::free(block);
}
static int allocations;
static int allocated_bytes;
};
boost::object_pool<
policy::ipv4_peer, logging_allocator> m_ipv4
_peer_pool;
# if TORRENT_USE_IPV6
boost::object_pool<
policy::ipv6_peer, logging_allocator> m_ipv6
_peer_pool;
# endif
#else
boost::object_pool<policy::ipv4_peer> m_ipv4_peer_po
ol;
# if TORRENT_USE_IPV6
boost::object_pool<policy::ipv6_peer> m_ipv6_peer_po
ol;
# endif
#endif
// this vector is used to store the block_info
// objects pointed to by partial_piece_info returned
// by torrent::get_download_queue.
std::vector<block_info> m_block_info_storage;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR #ifndef TORRENT_DISABLE_POOL_ALLOCATOR
// this pool is used to allocate and recycle send // this pool is used to allocate and recycle send
// buffers from. // buffers from.
boost::pool<> m_send_buffers; boost::pool<> m_send_buffers;
#endif #endif
boost::mutex m_send_buffer_mutex; boost::mutex m_send_buffer_mutex;
// the file pool that all storages in this session's // the file pool that all storages in this session's
// torrents uses. It sets a limit on the number of // torrents uses. It sets a limit on the number of
skipping to change at line 367 skipping to change at line 447
// when they are destructed. // when they are destructed.
file_pool m_files; file_pool m_files;
// this is where all active sockets are stored. // this is where all active sockets are stored.
// the selector can sleep while there's no activity on // the selector can sleep while there's no activity on
// them // them
mutable io_service m_io_service; mutable io_service m_io_service;
tcp::resolver m_host_resolver; tcp::resolver m_host_resolver;
// handles delayed alerts
alert_manager m_alerts;
// handles disk io requests asynchronously // handles disk io requests asynchronously
// peers have pointers into the disk buffer // peers have pointers into the disk buffer
// pool, and must be destructed before this // pool, and must be destructed before this
// object. The disk thread relies on the file // object. The disk thread relies on the file
// pool object, and must be destructed before // pool object, and must be destructed before
// m_files. The disk io thread posts completion // m_files. The disk io thread posts completion
// events to the io service, and needs to be // events to the io service, and needs to be
// constructed after it. // constructed after it.
disk_io_thread m_disk_thread; disk_io_thread m_disk_thread;
// this is a list of half-open tcp connections // this is a list of half-open tcp connections
// (only outgoing connections) // (only outgoing connections)
// this has to be one of the last // this has to be one of the last
// members to be destructed // members to be destructed
connection_queue m_half_open; connection_queue m_half_open;
// the bandwidth manager is responsible for // the bandwidth manager is responsible for
// handing out bandwidth to connections that // handing out bandwidth to connections that
// asks for it, it can also throttle the // asks for it, it can also throttle the
// rate. // rate.
bandwidth_manager<peer_connection, torrent> m_downlo bandwidth_manager<peer_connection> m_download_rate;
ad_channel; bandwidth_manager<peer_connection> m_upload_rate;
bandwidth_manager<peer_connection, torrent> m_upload
_channel;
bandwidth_manager<peer_connection, torrent>* m_bandw // the global rate limiter bandwidth channels
idth_manager[2]; bandwidth_channel m_download_channel;
bandwidth_channel m_upload_channel;
// bandwidth channels for local peers when
// rate limits are ignored. They are only
// throttled by these global rate limiters
// and they don't have a rate limit set by
// default
bandwidth_channel m_local_download_channel;
bandwidth_channel m_local_upload_channel;
bandwidth_channel* m_bandwidth_channel[2];
tracker_manager m_tracker_manager; tracker_manager m_tracker_manager;
torrent_map m_torrents; torrent_map m_torrents;
typedef std::list<boost::shared_ptr<torrent> > check _queue_t; typedef std::list<boost::shared_ptr<torrent> > check _queue_t;
// this has all torrents that wants to be checked in
it
check_queue_t m_queued_for_checking; check_queue_t m_queued_for_checking;
// this maps sockets to their peer_connection // this maps sockets to their peer_connection
// object. It is the complete list of all connected // object. It is the complete list of all connected
// peers. // peers.
connection_map m_connections; connection_map m_connections;
// filters incoming connections // filters incoming connections
ip_filter m_ip_filter; ip_filter m_ip_filter;
skipping to change at line 453 skipping to change at line 550
// the client is reachable through. // the client is reachable through.
int external_port; int external_port;
// the actual socket // the actual socket
boost::shared_ptr<socket_acceptor> sock; boost::shared_ptr<socket_acceptor> sock;
}; };
// since we might be listening on multiple interface s // since we might be listening on multiple interface s
// we might need more than one listen socket // we might need more than one listen socket
std::list<listen_socket_t> m_listen_sockets; std::list<listen_socket_t> m_listen_sockets;
// when as a socks proxy is used for peers, also
// listen for incoming connections on a socks connec
tion
boost::shared_ptr<socket_type> m_socks_listen_socket
;
void open_new_incoming_socks_connection();
listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false); listen_socket_t setup_listener(tcp::endpoint ep, int retries, bool v6_only = false);
// the settings for the client // the settings for the client
session_settings m_settings; session_settings m_settings;
// the proxy settings for different // the proxy settings for different
// kinds of connections // kinds of connections
proxy_settings m_peer_proxy; proxy_settings m_peer_proxy;
proxy_settings m_web_seed_proxy; proxy_settings m_web_seed_proxy;
proxy_settings m_tracker_proxy; proxy_settings m_tracker_proxy;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
proxy_settings m_dht_proxy; proxy_settings m_dht_proxy;
#endif #endif
#ifndef TORRENT_DISABLE_DHT
entry m_dht_state;
#endif
// set to true when the session object // set to true when the session object
// is being destructed and the thread // is being destructed and the thread
// should exit // should exit
bool m_abort; volatile bool m_abort;
// is true if the session is paused // is true if the session is paused
bool m_paused; bool m_paused;
// the max number of unchoked peers as set by the us er // the max number of unchoked peers as set by the us er
int m_max_uploads; int m_max_uploads;
// the number of unchoked peers as set by the auto-u nchoker // the number of unchoked peers as set by the auto-u nchoker
// this should always be >= m_max_uploads // this should always be >= m_max_uploads
int m_allowed_upload_slots; int m_allowed_upload_slots;
skipping to change at line 524 skipping to change at line 630
// statistics gathered from all torrents. // statistics gathered from all torrents.
stat m_stat; stat m_stat;
// is false by default and set to true when // is false by default and set to true when
// the first incoming connection is established // the first incoming connection is established
// this is used to know if the client is behind // this is used to know if the client is behind
// NAT or not. // NAT or not.
bool m_incoming_connection; bool m_incoming_connection;
void second_tick(error_code const& e); void on_disk_queue();
void on_tick(error_code const& e);
int auto_manage_torrents(std::vector<torrent*>& list
, int hard_limit, int type_limit);
void recalculate_auto_managed_torrents(); void recalculate_auto_managed_torrents();
void recalculate_unchoke_slots(int congested_torrent s void recalculate_unchoke_slots(int congested_torrent s
, int uncongested_torrents); , int uncongested_torrents);
void recalculate_optimistic_unchoke_slot();
ptime m_created;
int session_time() const { return total_seconds(time
_now() - m_created); }
ptime m_last_tick; ptime m_last_tick;
ptime m_last_second_tick;
// the last time we went through the peers
// to decide which ones to choke/unchoke
ptime m_last_choke;
// when outgoing_ports is configured, this is the // when outgoing_ports is configured, this is the
// port we'll bind the next outgoing socket to // port we'll bind the next outgoing socket to
int m_next_port; int m_next_port;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
boost::intrusive_ptr<dht::dht_tracker> m_dht; boost::intrusive_ptr<dht::dht_tracker> m_dht;
dht_settings m_dht_settings; dht_settings m_dht_settings;
// if this is set to true, the dht listen port // if this is set to true, the dht listen port
// will be set to the same as the tcp listen port // will be set to the same as the tcp listen port
// and will be synchronlized with it as it changes // and will be synchronlized with it as it changes
// it defaults to true // it defaults to true
bool m_dht_same_port; bool m_dht_same_port;
// see m_external_listen_port. This is the same // see m_external_listen_port. This is the same
// but for the udp port used by the DHT. // but for the udp port used by the DHT.
int m_external_udp_port; int m_external_udp_port;
udp_socket m_dht_socket; rate_limited_udp_socket m_dht_socket;
// these are used when starting the DHT // these are used when starting the DHT
// (and bootstrapping it), and then erased // (and bootstrapping it), and then erased
std::list<udp::endpoint> m_dht_router_nodes; std::list<udp::endpoint> m_dht_router_nodes;
void on_receive_udp(error_code const& e void on_receive_udp(error_code const& e
, udp::endpoint const& ep, char const* buf, int len); , udp::endpoint const& ep, char const* buf, int len);
#endif #endif
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
skipping to change at line 570 skipping to change at line 689
#endif #endif
boost::intrusive_ptr<natpmp> m_natpmp; boost::intrusive_ptr<natpmp> m_natpmp;
boost::intrusive_ptr<upnp> m_upnp; boost::intrusive_ptr<upnp> m_upnp;
boost::intrusive_ptr<lsd> m_lsd; boost::intrusive_ptr<lsd> m_lsd;
// 0 is natpmp 1 is upnp // 0 is natpmp 1 is upnp
int m_tcp_mapping[2]; int m_tcp_mapping[2];
int m_udp_mapping[2]; int m_udp_mapping[2];
// the timer used to fire the second_tick // the timer used to fire the tick
deadline_timer m_timer; deadline_timer m_timer;
// torrents are announced on the local network in a
// round-robin fashion. All torrents are cycled thro
ugh
// within the LSD announce interval (which defaults
to
// 5 minutes)
torrent_map::iterator m_next_lsd_torrent;
// this announce timer is used
// by Local service discovery
deadline_timer m_lsd_announce_timer;
// the index of the torrent that will be offered to // the index of the torrent that will be offered to
// connect to a peer next time second_tick is called . // connect to a peer next time on_tick is called.
// This implements a round robin. // This implements a round robin.
int m_next_connect_torrent; torrent_map::iterator m_next_connect_torrent;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
#ifdef TORRENT_STATS #if defined TORRENT_STATS && defined TORRENT_DISK_STATS
void log_buffer_usage(); void log_buffer_usage();
#endif
#if defined TORRENT_STATS
// logger used to write bandwidth usage statistics // logger used to write bandwidth usage statistics
std::ofstream m_stats_logger; std::ofstream m_stats_logger;
int m_second_counter; int m_second_counter;
// used to log send buffer usage statistics // used to log send buffer usage statistics
std::ofstream m_buffer_usage_logger; std::ofstream m_buffer_usage_logger;
// the number of send buffers that are allocated // the number of send buffers that are allocated
int m_buffer_allocations; int m_buffer_allocations;
#endif #endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING
boost::shared_ptr<logger> create_log(std::string con st& name boost::shared_ptr<logger> create_log(std::string con st& name
skipping to change at line 607 skipping to change at line 738
// shutting down. This list is just here to keep the m alive during // shutting down. This list is just here to keep the m alive during
// whe shutting down process // whe shutting down process
std::list<boost::shared_ptr<tracker_logger> > m_trac ker_loggers; std::list<boost::shared_ptr<tracker_logger> > m_trac ker_loggers;
fs::path m_logpath; fs::path m_logpath;
public: public:
boost::shared_ptr<logger> m_logger; boost::shared_ptr<logger> m_logger;
private: private:
#endif #endif
#ifdef TORRENT_UPNP_LOGGING
std::ofstream m_upnp_log;
#endif
address m_external_address; address m_external_address;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::function<boost::shared_ptr< typedef std::list<boost::function<boost::shared_ptr<
torrent_plugin>(torrent*, void*)> > extensio n_list_t; torrent_plugin>(torrent*, void*)> > extensio n_list_t;
extension_list_t m_extensions; extension_list_t m_extensions;
#endif #endif
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
skipping to change at line 646 skipping to change at line 780
struct tracker_logger : request_callback struct tracker_logger : request_callback
{ {
tracker_logger(session_impl& ses): m_ses(ses) {} tracker_logger(session_impl& ses): m_ses(ses) {}
void tracker_warning(tracker_request const& req void tracker_warning(tracker_request const& req
, std::string const& str) , std::string const& str)
{ {
debug_log("*** tracker warning: " + str); debug_log("*** tracker warning: " + str);
} }
void tracker_response(tracker_request const& void tracker_response(tracker_request const&
, libtorrent::address const& tracker_ip
, std::list<address> const& ip_list
, std::vector<peer_entry>& peers , std::vector<peer_entry>& peers
, int interval , int interval
, int min_interval
, int complete , int complete
, int incomplete , int incomplete
, address const& external_ip) , address const& external_ip)
{ {
std::stringstream s; std::string s;
s << "TRACKER RESPONSE:\n" s = "TRACKER RESPONSE:\n";
"interval: " << interval << "\n" char tmp[200];
"peers:\n"; snprintf(tmp, 200, "interval: %d\nmin_interv
al: %d\npeers:\n", interval, min_interval);
s += tmp;
for (std::vector<peer_entry>::const_iterator i = peers.begin(); for (std::vector<peer_entry>::const_iterator i = peers.begin();
i != peers.end(); ++i) i != peers.end(); ++i)
{ {
s << " " << std::setfill(' ') << st char pid[41];
d::setw(16) << i->ip to_hex((const char*)&i->pid[0], 20,
<< " " << std::setw(5) << st pid);
d::dec << i->port << " "; if (i->pid.is_all_zeros()) pid[0] =
if (!i->pid.is_all_zeros()) s << " " 0;
<< i->pid;
s << "\n"; snprintf(tmp, 200, " %-16s %-5d %s\n
", i->ip.c_str(), i->port, pid);
s += tmp;
} }
s << "external ip: " << external_ip << "\n"; snprintf(tmp, 200, "external ip: %s\n", prin
debug_log(s.str()); t_address(external_ip).c_str());
s += tmp;
debug_log(s);
} }
void tracker_request_timed_out( void tracker_request_timed_out(
tracker_request const&) tracker_request const&)
{ {
debug_log("*** tracker timed out"); debug_log("*** tracker timed out");
} }
void tracker_request_error( void tracker_request_error(
tracker_request const& tracker_request const&
, int response_code , int response_code
, const std::string& str) , const std::string& str
, int retry_interval)
{ {
debug_log(std::string("*** tracker error: ") char msg[256];
+ boost::lexical_cast<std::string>(r snprintf(msg, sizeof(msg), "*** tracker erro
esponse_code) + ": " r: %d: %s", response_code, str.c_str());
+ str); debug_log(msg);
} }
void debug_log(const std::string& line) void debug_log(const std::string& line)
{ {
(*m_ses.m_logger) << time_now_string() << " " << line << "\n"; (*m_ses.m_logger) << time_now_string() << " " << line << "\n";
} }
session_impl& m_ses; session_impl& m_ses;
}; };
#endif #endif
 End of changes. 61 change blocks. 
61 lines changed or deleted 223 lines changed or added


 session_settings.hpp   session_settings.hpp 
skipping to change at line 92 skipping to change at line 92
{ {
session_settings(std::string const& user_agent_ = "libtorren t/" session_settings(std::string const& user_agent_ = "libtorren t/"
LIBTORRENT_VERSION) LIBTORRENT_VERSION)
: user_agent(user_agent_) : user_agent(user_agent_)
, tracker_completion_timeout(60) , tracker_completion_timeout(60)
, tracker_receive_timeout(40) , tracker_receive_timeout(40)
, stop_tracker_timeout(5) , stop_tracker_timeout(5)
, tracker_maximum_response_length(1024*1024) , tracker_maximum_response_length(1024*1024)
, piece_timeout(20) , piece_timeout(20)
, request_timeout(50) , request_timeout(50)
, request_queue_time(3.f) , request_queue_time(3)
, max_allowed_in_request_queue(250) , max_allowed_in_request_queue(250)
, max_out_request_queue(200) , max_out_request_queue(200)
, whole_pieces_threshold(20) , whole_pieces_threshold(20)
, peer_timeout(120) , peer_timeout(120)
, urlseed_timeout(20) , urlseed_timeout(20)
, urlseed_pipeline_size(5) , urlseed_pipeline_size(5)
, urlseed_wait_retry(30) , urlseed_wait_retry(30)
, file_pool_size(40) , file_pool_size(40)
, allow_multiple_connections_per_ip(false) , allow_multiple_connections_per_ip(false)
, max_failcount(3) , max_failcount(3)
, min_reconnect_time(60) , min_reconnect_time(60)
, peer_connect_timeout(7) , peer_connect_timeout(7)
, ignore_limits_on_local_network(true) , ignore_limits_on_local_network(true)
, connection_speed(10) , connection_speed(10)
, send_redundant_have(false) , send_redundant_have(false)
, lazy_bitfields(true) , lazy_bitfields(true)
, inactivity_timeout(600) , inactivity_timeout(600)
, unchoke_interval(15) , unchoke_interval(15)
, optimistic_unchoke_multiplier(4) , optimistic_unchoke_interval(30)
, num_want(200) , num_want(200)
, initial_picker_threshold(4) , initial_picker_threshold(4)
, allowed_fast_set_size(10) , allowed_fast_set_size(10)
, max_outstanding_disk_bytes_per_connection(64 * 102 4) , max_queued_disk_bytes(256 * 1024)
, handshake_timeout(10) , handshake_timeout(10)
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
, use_dht_as_fallback(false) , use_dht_as_fallback(false)
#endif #endif
, free_torrent_hashes(true) , free_torrent_hashes(true)
, upnp_ignore_nonrouters(false) , upnp_ignore_nonrouters(false)
, send_buffer_watermark(80 * 1024) , send_buffer_watermark(100 * 1024)
, auto_upload_slots(true) , auto_upload_slots(true)
, auto_upload_slots_rate_based(true)
, use_parole_mode(true) , use_parole_mode(true)
, cache_size(512) , cache_size(1024)
, cache_buffer_chunk_size(16)
, cache_expiry(60) , cache_expiry(60)
, use_read_cache(true)
, disk_io_write_mode(0)
, disk_io_read_mode(0)
, coalesce_reads(false)
, coalesce_writes(false)
, outgoing_ports(0,0) , outgoing_ports(0,0)
, peer_tos(0) , peer_tos(0)
, active_downloads(8) , active_downloads(8)
, active_seeds(5) , active_seeds(5)
, active_limit(15) , active_limit(15)
, auto_manage_prefer_seeds(false)
, dont_count_slow_torrents(true) , dont_count_slow_torrents(true)
, auto_manage_interval(30) , auto_manage_interval(30)
, share_ratio_limit(2.f) , share_ratio_limit(2.f)
, seed_time_ratio_limit(7.f) , seed_time_ratio_limit(7.f)
, seed_time_limit(24 * 60 * 60) // 24 hours , seed_time_limit(24 * 60 * 60) // 24 hours
, peer_turnover(1 / 100.f) , peer_turnover(1 / 100.f)
, peer_turnover_cutoff(1.1f) // disable until the cr ash is resolved , peer_turnover_cutoff(1.1f) // disable until the cr ash is resolved
, close_redundant_connections(true) , close_redundant_connections(true)
, auto_scrape_interval(1800) , auto_scrape_interval(1800)
, auto_scrape_min_interval(300) , auto_scrape_min_interval(300)
, max_peerlist_size(8000) , max_peerlist_size(4000)
, max_paused_peerlist_size(4000)
, min_announce_interval(5 * 60) , min_announce_interval(5 * 60)
, prioritize_partial_pieces(false) , prioritize_partial_pieces(false)
, auto_manage_startup(120) , auto_manage_startup(120)
, rate_limit_ip_overhead(true) , rate_limit_ip_overhead(true)
, announce_to_all_trackers(false)
, announce_to_all_tiers(false)
, prefer_udp_trackers(true)
, strict_super_seeding(false)
, seeding_piece_quota(3)
#ifdef TORRENT_WINDOWS
, max_sparse_regions(30000)
#else
, max_sparse_regions(0)
#endif
#ifndef TORRENT_DISABLE_MLOCK
, lock_disk_cache(true)
#endif
, max_rejects(50)
, recv_socket_buffer_size(0)
, send_socket_buffer_size(0)
, optimize_hashing_for_speed(true)
, file_checks_delay_per_block(0)
, disk_cache_algorithm(largest_contiguous)
, read_cache_line_size(16)
, write_cache_line_size(32)
, optimistic_disk_retry(10 * 60)
, disable_hash_checks(false)
, allow_reordered_disk_operations(true)
, max_suggest_pieces(10)
, drop_skipped_requests(false)
, low_prio_disk(true)
, local_service_announce_interval(5 * 60)
, udp_tracker_token_expiry(60)
, report_true_downloaded(false)
, strict_end_game_mode(true)
{} {}
// this is the user agent that will be sent to the tracker // this is the user agent that will be sent to the tracker
// when doing requests. It is used to identify the client. // when doing requests. It is used to identify the client.
// It cannot contain \r or \n // It cannot contain \r or \n
std::string user_agent; std::string user_agent;
// the number of seconds to wait until giving up on a // the number of seconds to wait until giving up on a
// tracker request if it hasn't finished // tracker request if it hasn't finished
int tracker_completion_timeout; int tracker_completion_timeout;
skipping to change at line 186 skipping to change at line 226
// the number of seconds one block (16kB) is expected // the number of seconds one block (16kB) is expected
// to be received within. If it's not, the block is // to be received within. If it's not, the block is
// requested from a different peer // requested from a different peer
int request_timeout; int request_timeout;
// the length of the request queue given in the number // the length of the request queue given in the number
// of seconds it should take for the other end to send // of seconds it should take for the other end to send
// all the pieces. i.e. the actual number of requests // all the pieces. i.e. the actual number of requests
// depends on the download rate and this number. // depends on the download rate and this number.
float request_queue_time; int request_queue_time;
// the number of outstanding block requests a peer is // the number of outstanding block requests a peer is
// allowed to queue up in the client. If a peer sends // allowed to queue up in the client. If a peer sends
// more requests than this (before the first one has // more requests than this (before the first one has
// been sent) the last request will be dropped. // been sent) the last request will be dropped.
// the higher this is, the faster upload speeds the // the higher this is, the faster upload speeds the
// client can get to a single peer. // client can get to a single peer.
int max_allowed_in_request_queue; int max_allowed_in_request_queue;
// the maximum number of outstanding requests to // the maximum number of outstanding requests to
skipping to change at line 284 skipping to change at line 324
bool lazy_bitfields; bool lazy_bitfields;
// if a peer is uninteresting and uninterested for longer // if a peer is uninteresting and uninterested for longer
// than this number of seconds, it will be disconnected. // than this number of seconds, it will be disconnected.
// default is 10 minutes // default is 10 minutes
int inactivity_timeout; int inactivity_timeout;
// the number of seconds between chokes/unchokes // the number of seconds between chokes/unchokes
int unchoke_interval; int unchoke_interval;
// the number of unchoke intervals between // the number of seconds between
// optimistic unchokes // optimistic unchokes
int optimistic_unchoke_multiplier; int optimistic_unchoke_interval;
// if this is set, this IP will be reported do the // if this is set, this IP will be reported do the
// tracker in the ip= parameter. // tracker in the ip= parameter.
address announce_ip; address announce_ip;
// the num want sent to trackers // the num want sent to trackers
int num_want; int num_want;
// while we have fewer pieces than this, pick // while we have fewer pieces than this, pick
// random pieces instead of rarest first. // random pieces instead of rarest first.
int initial_picker_threshold; int initial_picker_threshold;
// the number of allowed pieces to send to peers // the number of allowed pieces to send to peers
// that supports the fast extensions // that supports the fast extensions
int allowed_fast_set_size; int allowed_fast_set_size;
// the maximum number of bytes a connection may have // the maximum number of bytes a connection may have
// pending in the disk write queue before its download // pending in the disk write queue before its download
// rate is being throttled. This prevents fast downloads // rate is being throttled. This prevents fast downloads
// to slow medias to allocate more and more memory // to slow medias to allocate more and more memory
// indefinitely. This should be set to at least 32 kB // indefinitely. This should be set to at least 16 kB
// to not completely disrupt normal downloads. // to not completely disrupt normal downloads. If it's
int max_outstanding_disk_bytes_per_connection; // set to 0, you will be starving the disk thread and
// nothing will be written to disk.
// this is a per session setting.
int max_queued_disk_bytes;
// the number of seconds to wait for a handshake // the number of seconds to wait for a handshake
// response from a peer. If no response is received // response from a peer. If no response is received
// within this time, the peer is disconnected. // within this time, the peer is disconnected.
int handshake_timeout; int handshake_timeout;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
// while this is true, the dht will note be used unless the // while this is true, the dht will not be used unless the
// tracker is online // tracker is online
bool use_dht_as_fallback; bool use_dht_as_fallback;
#endif #endif
// if this is true, the piece hashes will be freed, in order // if this is true, the piece hashes will be freed, in order
// to save memory, once the torrent is seeding. This will // to save memory, once the torrent is seeding. This will
// make the get_torrent_info() function to return an incompl ete // make the get_torrent_info() function to return an incompl ete
// torrent object that cannot be passed back to add_torrent( ) // torrent object that cannot be passed back to add_torrent( )
bool free_torrent_hashes; bool free_torrent_hashes;
skipping to change at line 350 skipping to change at line 393
// if auto_upload_slots is true, and a global upload // if auto_upload_slots is true, and a global upload
// limit is set and the upload rate is less than 90% // limit is set and the upload rate is less than 90%
// of the upload limit, on new slot is opened up. If // of the upload limit, on new slot is opened up. If
// the upload rate is >= upload limit for an extended // the upload rate is >= upload limit for an extended
// period of time, one upload slot is closed. The // period of time, one upload slot is closed. The
// upload slots are never automatically decreased below // upload slots are never automatically decreased below
// the manual settings, through max_uploads. // the manual settings, through max_uploads.
bool auto_upload_slots; bool auto_upload_slots;
// this only affects the auto upload slots mechanism.
// if auto_upload_slots is false, this field is not
// considered.
bool auto_upload_slots_rate_based;
// if set to true, peers that participate in a failing // if set to true, peers that participate in a failing
// piece is put in parole mode. i.e. They will only // piece is put in parole mode. i.e. They will only
// download whole pieces until they either fail or pass. // download whole pieces until they either fail or pass.
// they are taken out of parole mode as soon as they // they are taken out of parole mode as soon as they
// participate in a piece that passes. // participate in a piece that passes.
bool use_parole_mode; bool use_parole_mode;
// the disk write cache, specified in 16 KiB blocks. // the disk write cache, specified in 16 KiB blocks.
// default is 512 (= 8 MB) // default is 1024 (= 16 MiB). -1 means automatic, which
// adjusts the cache size depending on the amount
// of physical RAM in the machine.
int cache_size; int cache_size;
// this is the number of disk buffer blocks (16 kiB)
// that should be allocated at a time. It must be
// at least 1. Lower number saves memory at the expense
// of more heap allocations
int cache_buffer_chunk_size;
// the number of seconds a write cache entry sits // the number of seconds a write cache entry sits
// idle in the cache before it's forcefully flushed // idle in the cache before it's forcefully flushed
// to disk. Default is 60 seconds. // to disk. Default is 60 seconds.
int cache_expiry; int cache_expiry;
// when true, the disk I/O thread uses the disk
// cache for caching blocks read from disk too
bool use_read_cache;
enum io_buffer_mode_t
{
enable_os_cache = 0,
disable_os_cache_for_aligned_files = 1,
disable_os_cache = 2
};
int disk_io_write_mode;
int disk_io_read_mode;
bool coalesce_reads;
bool coalesce_writes;
// if != (0, 0), this is the range of ports that // if != (0, 0), this is the range of ports that
// outgoing connections will be bound to. This // outgoing connections will be bound to. This
// is useful for users that have routers that // is useful for users that have routers that
// allow QoS settings based on local port. // allow QoS settings based on local port.
std::pair<int, int> outgoing_ports; std::pair<int, int> outgoing_ports;
// the TOS byte of all peer traffic (including // the TOS byte of all peer traffic (including
// web seeds) is set to this value. The default // web seeds) is set to this value. The default
// is the QBSS scavenger service // is the QBSS scavenger service
// http://qbone.internet2.edu/qbss/ // http://qbone.internet2.edu/qbss/
skipping to change at line 387 skipping to change at line 459
char peer_tos; char peer_tos;
// for auto managed torrents, these are the limits // for auto managed torrents, these are the limits
// they are subject to. If there are too many torrents // they are subject to. If there are too many torrents
// some of the auto managed ones will be paused until // some of the auto managed ones will be paused until
// some slots free up. // some slots free up.
int active_downloads; int active_downloads;
int active_seeds; int active_seeds;
int active_limit; int active_limit;
// prefer seeding torrents when determining which torrents t
o give
// active slots to, the default is false which gives prefere
nce to
// downloading torrents
bool auto_manage_prefer_seeds;
// if this is true, torrents that don't have any significant // if this is true, torrents that don't have any significant
// transfers are not counted as active when determining whic h // transfers are not counted as active when determining whic h
// auto managed torrents to pause and resume // auto managed torrents to pause and resume
bool dont_count_slow_torrents; bool dont_count_slow_torrents;
// the number of seconds in between recalculating which // the number of seconds in between recalculating which
// torrents to activate and which ones to queue // torrents to activate and which ones to queue
int auto_manage_interval; int auto_manage_interval;
// when a seeding torrent reaches eaither the share ratio // when a seeding torrent reaches eaither the share ratio
skipping to change at line 414 skipping to change at line 491
float share_ratio_limit; float share_ratio_limit;
float seed_time_ratio_limit; float seed_time_ratio_limit;
int seed_time_limit; int seed_time_limit;
// the percentage of peers to disconnect every // the percentage of peers to disconnect every
// 90 seconds (if we're at the peer limit) // 90 seconds (if we're at the peer limit)
// defaults to 1/50:th // defaults to 1/50:th
float peer_turnover; float peer_turnover;
// when we are connected to more than // when we are connected to more than
// limit * peer_turnover_enable peers // limit * peer_turnover_cutoff peers
// disconnect peer_turnover fraction // disconnect peer_turnover fraction
// of the peers // of the peers
float peer_turnover_cutoff; float peer_turnover_cutoff;
// if this is true (default) connections where both // if this is true (default) connections where both
// ends have no utility in keeping the connection open // ends have no utility in keeping the connection open
// are closed. for instance if both ends have completed // are closed. for instance if both ends have completed
// their downloads // their downloads
bool close_redundant_connections; bool close_redundant_connections;
skipping to change at line 438 skipping to change at line 515
// the minimum number of seconds between any // the minimum number of seconds between any
// automatic scrape (regardless of torrent) // automatic scrape (regardless of torrent)
int auto_scrape_min_interval; int auto_scrape_min_interval;
// the max number of peers in the peer list // the max number of peers in the peer list
// per torrent. This is the peers we know // per torrent. This is the peers we know
// about, not necessarily connected to. // about, not necessarily connected to.
int max_peerlist_size; int max_peerlist_size;
// when a torrent is paused, this is the max peer
// list size that's used
int max_paused_peerlist_size;
// any announce intervals reported from a tracker // any announce intervals reported from a tracker
// that is lower than this, will be clamped to this // that is lower than this, will be clamped to this
// value. It's specified in seconds // value. It's specified in seconds
int min_announce_interval; int min_announce_interval;
// if true, partial pieces are picked before pieces // if true, partial pieces are picked before pieces
// that are more rare // that are more rare
bool prioritize_partial_pieces; bool prioritize_partial_pieces;
// the number of seconds a torrent is considered // the number of seconds a torrent is considered
skipping to change at line 459 skipping to change at line 540
// upload and download speed. This is so that // upload and download speed. This is so that
// newly started torrents are not considered // newly started torrents are not considered
// inactive until they have a fair chance to // inactive until they have a fair chance to
// start downloading. // start downloading.
int auto_manage_startup; int auto_manage_startup;
// if set to true, the estimated TCP/IP overhead is // if set to true, the estimated TCP/IP overhead is
// drained from the rate limiters, to avoid exceeding // drained from the rate limiters, to avoid exceeding
// the limits with the total traffic // the limits with the total traffic
bool rate_limit_ip_overhead; bool rate_limit_ip_overhead;
// this announces to all trackers within the current
// tier. Trackers within a tier are supposed to share
// peers, this could be used for trackers that don't,
// and require the clients to announce to all of them.
bool announce_to_all_trackers;
// if set to true, multi tracker torrents are treated
// the same way uTorrent treats them. It defaults to
// false in order to comply with the extension definition.
// When this is enabled, one tracker from each tier is
// announced
bool announce_to_all_tiers;
// when this is set to true, if there is a tracker entry
// with udp:// protocol, it is preferred over the same
// tracker over http://.
bool prefer_udp_trackers;
// when set to true, a piece has to have been forwarded
// to a third peer before another one is handed out
bool strict_super_seeding;
// the number of pieces to send to each peer when seeding
// before rotating to a new peer
int seeding_piece_quota;
// the maximum number of sparse regions before starting
// to prioritize pieces close to other pieces (to maintain
// the number of sparse regions). This is set to 30000 on
// windows because windows vista has a new limit on the
// numbers of sparse regions one file may have
// if it is set to 0 this behavior is disabled
// this is a hack to avoid a terrible bug on windows
// don't use unless you have to, it screws with rarest-first
// piece selection, and reduces swarm performance
int max_sparse_regions;
#ifndef TORRENT_DISABLE_MLOCK
// if this is set to true, the memory allocated for the
// disk cache will be locked in physical RAM, never to
// be swapped out
bool lock_disk_cache;
#endif
// the number of times to reject requests while being
// choked before disconnecting a peer for being malicious
int max_rejects;
// sets the socket send and receive buffer sizes
// 0 means OS default
int recv_socket_buffer_size;
int send_socket_buffer_size;
// if this is set to false, the hashing will be
// optimized for memory usage instead of the
// number of read operations
bool optimize_hashing_for_speed;
// if > 0, file checks will have a short
// delay between disk operations, to make it
// less intrusive on the system as a whole
// blocking the disk. This delay is specified
// in milliseconds and the delay will be this
// long per 16kiB block
// the default of 10 ms/16kiB will limit
// the checking rate to 1.6 MiB per second
int file_checks_delay_per_block;
enum disk_cache_algo_t
{ lru, largest_contiguous };
disk_cache_algo_t disk_cache_algorithm;
// the number of blocks that will be read ahead
// when reading a block into the read cache
int read_cache_line_size;
// whenever a contiguous range of this many
// blocks is found in the write cache, it
// is flushed immediately
int write_cache_line_size;
// this is the number of seconds a disk failure
// occurs until libtorrent will re-try.
int optimistic_disk_retry;
// when set to true, all data downloaded from
// peers will be assumed to be correct, and not
// tested to match the hashes in the torrent
// this is only useful for simulation and
// testing purposes (typically combined with
// disabled_storage)
bool disable_hash_checks;
// if this is true, disk read operations may
// be re-ordered based on their physical disk
// read offset. This greatly improves throughput
// when uploading to many peers. This assumes
// a traditional hard drive with a read head
// and spinning platters. If your storage medium
// is a solid state drive, this optimization
// doesn't give you an benefits
bool allow_reordered_disk_operations;
// the max number of pieces that a peer can
// suggest to use before we start dropping
// previous suggested piece
int max_suggest_pieces;
// if set to true, requests that have have not been
// satisfied after the equivalence of the entire
// request queue has been received, will be considered lost
bool drop_skipped_requests;
// if this is set to true, the disk I/O will be
// run at lower-than-normal priority. This is
// intended to make the machine more responsive
// to foreground tasks, while bittorrent runs
// in the background
bool low_prio_disk;
// number of seconds between local service announces for
// torrents. Defaults to 5 minutes
int local_service_announce_interval;
// the number of seconds a connection ID received
// from a UDP tracker is valid for. This is specified
// as 60 seconds
int udp_tracker_token_expiry;
// when set to true, the downloaded counter sent to trackers
// will include the actual number of payload bytes donwnload
ed
// including redundant bytes. If set to false, it will not i
nclude
// any redundany bytes
bool report_true_downloaded;
// if set to true, libtorrent won't request a piece multiple
times
// until every piece is requested
bool strict_end_game_mode;
}; };
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
struct dht_settings struct dht_settings
{ {
dht_settings() dht_settings()
: max_peers_reply(100) : max_peers_reply(100)
, search_branching(5) , search_branching(5)
, service_port(0) , service_port(0)
, max_fail_count(20) , max_fail_count(20)
 End of changes. 23 change blocks. 
15 lines changed or deleted 241 lines changed or added


 session_status.hpp   session_status.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_SESSION_STATUS_HPP_INCLUDED #ifndef TORRENT_SESSION_STATUS_HPP_INCLUDED
#define TORRENT_SESSION_STATUS_HPP_INCLUDED #define TORRENT_SESSION_STATUS_HPP_INCLUDED
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT session_status #ifndef TORRENT_DISABLE_DHT
struct dht_lookup
{ {
bool has_incoming_connections; char const* type;
int outstanding_requests;
int timeouts;
int responses;
int branch_factor;
};
float upload_rate; #endif
float download_rate;
float payload_upload_rate; struct TORRENT_EXPORT session_status
float payload_download_rate; {
bool has_incoming_connections;
int upload_rate;
int download_rate;
size_type total_download; size_type total_download;
size_type total_upload; size_type total_upload;
int payload_upload_rate;
int payload_download_rate;
size_type total_payload_download; size_type total_payload_download;
size_type total_payload_upload; size_type total_payload_upload;
int ip_overhead_upload_rate;
int ip_overhead_download_rate;
size_type total_ip_overhead_download;
size_type total_ip_overhead_upload;
int dht_upload_rate;
int dht_download_rate;
size_type total_dht_download;
size_type total_dht_upload;
int tracker_upload_rate;
int tracker_download_rate;
size_type total_tracker_download;
size_type total_tracker_upload;
size_type total_redundant_bytes; size_type total_redundant_bytes;
size_type total_failed_bytes; size_type total_failed_bytes;
int num_peers; int num_peers;
int num_unchoked; int num_unchoked;
int allowed_upload_slots; int allowed_upload_slots;
int up_bandwidth_queue; int up_bandwidth_queue;
int down_bandwidth_queue; int down_bandwidth_queue;
int up_bandwidth_bytes_queue;
int down_bandwidth_bytes_queue;
int optimistic_unchoke_counter;
int unchoke_counter;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
int dht_nodes; int dht_nodes;
int dht_node_cache; int dht_node_cache;
int dht_torrents; int dht_torrents;
size_type dht_global_nodes; size_type dht_global_nodes;
std::vector<dht_lookup> active_requests;
#endif #endif
}; };
} }
#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED #endif // TORRENT_SESSION_STATUS_HPP_INCLUDED
 End of changes. 9 change blocks. 
6 lines changed or deleted 39 lines changed or added


 socket.hpp   socket.hpp 
skipping to change at line 77 skipping to change at line 77
#include <boost/asio/basic_deadline_timer.hpp> #include <boost/asio/basic_deadline_timer.hpp>
#endif #endif
#ifdef __OBJC__ #ifdef __OBJC__
#undef Protocol #undef Protocol
#endif #endif
#include "libtorrent/io.hpp" #include "libtorrent/io.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/error_code.hpp" #include "libtorrent/error_code.hpp"
#include "libtorrent/escape_string.hpp" // for to_string
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
namespace libtorrent namespace libtorrent
{ {
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
using asio::ip::tcp; using ::asio::ip::tcp;
using asio::ip::udp; using ::asio::ip::udp;
using asio::async_write; using ::asio::async_write;
using asio::async_read; using ::asio::async_read;
typedef asio::ip::tcp::socket stream_socket;
typedef asio::ip::address address;
typedef asio::ip::address_v4 address_v4;
typedef asio::ip::address_v6 address_v6;
typedef asio::ip::udp::socket datagram_socket;
typedef asio::ip::tcp::acceptor socket_acceptor;
typedef asio::io_service io_service;
namespace asio = ::asio; typedef ::asio::ip::tcp::socket stream_socket;
typedef asio::basic_deadline_timer<libtorrent::ptime> deadline_timer typedef ::asio::ip::address address;
; typedef ::asio::ip::address_v4 address_v4;
typedef ::asio::ip::address_v6 address_v6;
typedef ::asio::ip::udp::socket datagram_socket;
typedef ::asio::ip::tcp::acceptor socket_acceptor;
typedef ::asio::io_service io_service;
typedef ::asio::basic_deadline_timer<libtorrent::ptime> deadline_tim
er;
#else #else
using boost::asio::ip::tcp; using boost::asio::ip::tcp;
using boost::asio::ip::udp; using boost::asio::ip::udp;
using boost::asio::async_write; using boost::asio::async_write;
using boost::asio::async_read; using boost::asio::async_read;
typedef boost::asio::ip::tcp::socket stream_socket; typedef boost::asio::ip::tcp::socket stream_socket;
typedef boost::asio::ip::address address; typedef boost::asio::ip::address address;
typedef boost::asio::ip::address_v4 address_v4; typedef boost::asio::ip::address_v4 address_v4;
typedef boost::asio::ip::address_v6 address_v6; typedef boost::asio::ip::address_v6 address_v6;
typedef boost::asio::ip::udp::socket datagram_socket; typedef boost::asio::ip::udp::socket datagram_socket;
typedef boost::asio::ip::tcp::acceptor socket_acceptor; typedef boost::asio::ip::tcp::acceptor socket_acceptor;
typedef boost::asio::io_service io_service; typedef boost::asio::io_service io_service;
namespace asio = boost::asio; namespace asio = boost::asio;
typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadlin e_timer; typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadlin e_timer;
#endif #endif
inline std::ostream& print_address(std::ostream& os, address const& addr) inline std::string print_address(address const& addr)
{ {
error_code ec; error_code ec;
std::string a = addr.to_string(ec); return addr.to_string(ec);
if (ec) return os;
os << a;
return os;
} }
inline std::ostream& print_endpoint(std::ostream& os, tcp::endpoint const& ep) inline std::string print_endpoint(tcp::endpoint const& ep)
{ {
address const& addr = ep.address();
error_code ec; error_code ec;
std::string a = addr.to_string(ec); std::string ret;
if (ec) return os; address const& addr = ep.address();
#if TORRENT_USE_IPV6
if (addr.is_v6()) if (addr.is_v6())
os << "[" << a << "]:"; {
ret += '[';
ret += addr.to_string(ec);
ret += ']';
ret += ':';
ret += to_string(ep.port()).elems;
}
else else
os << a << ":"; #endif
os << ep.port(); {
return os; ret += addr.to_string(ec);
ret += ':';
ret += to_string(ep.port()).elems;
}
return ret;
}
inline std::string print_endpoint(udp::endpoint const& ep)
{
return print_endpoint(tcp::endpoint(ep.address(), ep.port())
);
} }
namespace detail namespace detail
{ {
template<class OutIt> template<class OutIt>
void write_address(address const& a, OutIt& out) void write_address(address const& a, OutIt& out)
{ {
#if TORRENT_USE_IPV6
if (a.is_v4()) if (a.is_v4())
{ {
#endif
write_uint32(a.to_v4().to_ulong(), out); write_uint32(a.to_v4().to_ulong(), out);
#if TORRENT_USE_IPV6
} }
else if (a.is_v6()) else if (a.is_v6())
{ {
address_v6::bytes_type bytes address_v6::bytes_type bytes
= a.to_v6().to_bytes(); = a.to_v6().to_bytes();
std::copy(bytes.begin(), bytes.end(), out); std::copy(bytes.begin(), bytes.end(), out);
} }
#endif
} }
template<class InIt> template<class InIt>
address read_v4_address(InIt& in) address read_v4_address(InIt& in)
{ {
unsigned long ip = read_uint32(in); unsigned long ip = read_uint32(in);
return address_v4(ip); return address_v4(ip);
} }
#if TORRENT_USE_IPV6
template<class InIt> template<class InIt>
address read_v6_address(InIt& in) address read_v6_address(InIt& in)
{ {
typedef address_v6::bytes_type bytes_t; typedef address_v6::bytes_type bytes_t;
bytes_t bytes; bytes_t bytes;
for (bytes_t::iterator i = bytes.begin() for (bytes_t::iterator i = bytes.begin()
, end(bytes.end()); i != end; ++i) , end(bytes.end()); i != end; ++i)
*i = read_uint8(in); *i = read_uint8(in);
return address_v6(bytes); return address_v6(bytes);
} }
#endif
template<class Endpoint, class OutIt> template<class Endpoint, class OutIt>
void write_endpoint(Endpoint const& e, OutIt& out) void write_endpoint(Endpoint const& e, OutIt& out)
{ {
write_address(e.address(), out); write_address(e.address(), out);
write_uint16(e.port(), out); write_uint16(e.port(), out);
} }
template<class Endpoint, class InIt> template<class Endpoint, class InIt>
Endpoint read_v4_endpoint(InIt& in) Endpoint read_v4_endpoint(InIt& in)
{ {
address addr = read_v4_address(in); address addr = read_v4_address(in);
int port = read_uint16(in); int port = read_uint16(in);
return Endpoint(addr, port); return Endpoint(addr, port);
} }
#if TORRENT_USE_IPV6
template<class Endpoint, class InIt> template<class Endpoint, class InIt>
Endpoint read_v6_endpoint(InIt& in) Endpoint read_v6_endpoint(InIt& in)
{ {
address addr = read_v6_address(in); address addr = read_v6_address(in);
int port = read_uint16(in); int port = read_uint16(in);
return Endpoint(addr, port); return Endpoint(addr, port);
} }
#endif
} }
#if TORRENT_USE_IPV6
struct v6only struct v6only
{ {
v6only(bool enable): m_value(enable) {} v6only(bool enable): m_value(enable) {}
template<class Protocol> template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IPV6; } int level(Protocol const&) const { return IPPROTO_IPV6; }
template<class Protocol> template<class Protocol>
int name(Protocol const&) const { return IPV6_V6ONLY; } int name(Protocol const&) const { return IPV6_V6ONLY; }
template<class Protocol> template<class Protocol>
int const* data(Protocol const&) const { return &m_value; } int const* data(Protocol const&) const { return &m_value; }
template<class Protocol> template<class Protocol>
size_t size(Protocol const&) const { return sizeof(m_value); } size_t size(Protocol const&) const { return sizeof(m_value); }
int m_value; int m_value;
}; };
#endif
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
#ifndef IPV6_PROTECTION_LEVEL #ifndef IPV6_PROTECTION_LEVEL
#define IPV6_PROTECTION_LEVEL 30 #define IPV6_PROTECTION_LEVEL 30
#endif #endif
struct v6_protection_level struct v6_protection_level
{ {
v6_protection_level(int level): m_value(level) {} v6_protection_level(int level): m_value(level) {}
template<class Protocol> template<class Protocol>
 End of changes. 20 change blocks. 
29 lines changed or deleted 50 lines changed or added


 socket_type.hpp   socket_type.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_SOCKET_TYPE #ifndef TORRENT_SOCKET_TYPE
#define TORRENT_SOCKET_TYPE #define TORRENT_SOCKET_TYPE
#include "libtorrent/socks5_stream.hpp" #include "libtorrent/socks5_stream.hpp"
#include "libtorrent/socks4_stream.hpp"
#include "libtorrent/http_stream.hpp" #include "libtorrent/http_stream.hpp"
#include "libtorrent/variant_stream.hpp" #include "libtorrent/variant_stream.hpp"
namespace libtorrent namespace libtorrent
{ {
typedef variant_stream< typedef variant_stream<
stream_socket stream_socket
, socks5_stream , socks5_stream
, socks4_stream
, http_stream> socket_type; , http_stream> socket_type;
} }
#endif #endif
 End of changes. 2 change blocks. 
2 lines changed or deleted 0 lines changed or added


 socks5_stream.hpp   socks5_stream.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#ifndef TORRENT_SOCKS5_STREAM_HPP_INCLUDED #ifndef TORRENT_SOCKS5_STREAM_HPP_INCLUDED
#define TORRENT_SOCKS5_STREAM_HPP_INCLUDED #define TORRENT_SOCKS5_STREAM_HPP_INCLUDED
#include "libtorrent/proxy_base.hpp" #include "libtorrent/proxy_base.hpp"
namespace libtorrent { namespace libtorrent {
namespace socks_error {
enum socks_error_code
{
no_error = 0,
unsupported_version,
unsupported_authentication_method,
unsupported_authentication_version,
authentication_error,
username_required,
general_failure,
command_not_supported,
no_identd,
identd_error,
num_errors
};
}
#if BOOST_VERSION < 103500
typedef asio::error::error_category socks_error_category;
#else
struct TORRENT_EXPORT socks_error_category : boost::system::error_category
{
virtual const char* name() const;
virtual std::string message(int ev) const;
virtual boost::system::error_condition default_error_condition(int e
v) const
{ return boost::system::error_condition(ev, *this); }
};
#endif
extern socks_error_category socks_category;
class socks5_stream : public proxy_base class socks5_stream : public proxy_base
{ {
public: public:
explicit socks5_stream(io_service& io_service) explicit socks5_stream(io_service& io_service)
: proxy_base(io_service) : proxy_base(io_service)
, m_version(5)
, m_command(1)
, m_listen(0)
{} {}
void set_version(int v) { m_version = v; }
void set_command(int c) { m_command = c; }
void set_username(std::string const& user void set_username(std::string const& user
, std::string const& password) , std::string const& password)
{ {
m_user = user; m_user = user;
m_password = password; m_password = password;
} }
typedef boost::function<void(error_code const&)> handler_type; typedef boost::function<void(error_code const&)> handler_type;
//#error fix error messages to use custom error_code category
//#error add async_connect() that takes a hostname and port as well
template <class Handler> template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& han dler) void async_connect(endpoint_type const& endpoint, Handler const& han dler)
{ {
m_remote_endpoint = endpoint; m_remote_endpoint = endpoint;
// the connect is split up in the following steps: // the connect is split up in the following steps:
// 1. resolve name of proxy server // 1. resolve name of proxy server
// 2. connect to proxy server // 2. connect to proxy server
// 3. send SOCKS5 authentication method message // 3. if version == 5:
// 4. read SOCKS5 authentication response // 3.1 send SOCKS5 authentication method message
// 5. send username+password // 3.2 read SOCKS5 authentication response
// 6. send SOCKS5 CONNECT message // 3.3 send username+password
// 4 send SOCKS command message
// to avoid unnecessary copying of the handler, // to avoid unnecessary copying of the handler,
// store it in a shaed_ptr // store it in a shaed_ptr
boost::shared_ptr<handler_type> h(new handler_type(handler)) ; boost::shared_ptr<handler_type> h(new handler_type(handler)) ;
tcp::resolver::query q(m_hostname tcp::resolver::query q(m_hostname, to_string(m_port).elems);
, boost::lexical_cast<std::string>(m_port));
m_resolver.async_resolve(q, boost::bind( m_resolver.async_resolve(q, boost::bind(
&socks5_stream::name_lookup, this, _1, _2, h)); &socks5_stream::name_lookup, this, _1, _2, h));
} }
private: private:
void name_lookup(error_code const& e, tcp::resolver::iterator i void name_lookup(error_code const& e, tcp::resolver::iterator i
, boost::shared_ptr<handler_type> h); , boost::shared_ptr<handler_type> h);
void connected(error_code const& e, boost::shared_ptr<handler_type> h); void connected(error_code const& e, boost::shared_ptr<handler_type> h);
void handshake1(error_code const& e, boost::shared_ptr<handler_type> h); void handshake1(error_code const& e, boost::shared_ptr<handler_type> h);
skipping to change at line 99 skipping to change at line 143
void socks_connect(boost::shared_ptr<handler_type> h); void socks_connect(boost::shared_ptr<handler_type> h);
void connect1(error_code const& e, boost::shared_ptr<handler_type> h ); void connect1(error_code const& e, boost::shared_ptr<handler_type> h );
void connect2(error_code const& e, boost::shared_ptr<handler_type> h ); void connect2(error_code const& e, boost::shared_ptr<handler_type> h );
void connect3(error_code const& e, boost::shared_ptr<handler_type> h ); void connect3(error_code const& e, boost::shared_ptr<handler_type> h );
// send and receive buffer // send and receive buffer
std::vector<char> m_buffer; std::vector<char> m_buffer;
// proxy authentication // proxy authentication
std::string m_user; std::string m_user;
std::string m_password; std::string m_password;
int m_version;
int m_command;
// set to one when we're waiting for the
// second message to accept an incoming connection
int m_listen;
}; };
} }
#endif #endif
 End of changes. 7 change blocks. 
6 lines changed or deleted 56 lines changed or added


 stat.hpp   stat.hpp 
skipping to change at line 64 skipping to change at line 64
stat_channel() stat_channel()
: m_counter(0) : m_counter(0)
, m_total_counter(0) , m_total_counter(0)
, m_rate_sum(0) , m_rate_sum(0)
{ {
std::memset(m_rate_history, 0, sizeof(m_rate_history )); std::memset(m_rate_history, 0, sizeof(m_rate_history ));
} }
void operator+=(stat_channel const& s) void operator+=(stat_channel const& s)
{ {
TORRENT_ASSERT(m_counter >= 0);
TORRENT_ASSERT(m_total_counter >= 0);
TORRENT_ASSERT(s.m_counter >= 0);
m_counter += s.m_counter; m_counter += s.m_counter;
m_total_counter += s.m_counter; m_total_counter += s.m_counter;
TORRENT_ASSERT(m_counter >= 0);
TORRENT_ASSERT(m_total_counter >= 0);
} }
void add(int count) void add(int count)
{ {
TORRENT_ASSERT(count >= 0); TORRENT_ASSERT(count >= 0);
m_counter += count; m_counter += count;
TORRENT_ASSERT(m_counter >= 0);
m_total_counter += count; m_total_counter += count;
TORRENT_ASSERT(m_total_counter >= 0);
} }
// should be called once every second // should be called once every second
void second_tick(float tick_interval); void second_tick(int tick_interval_ms);
float rate() const { return m_rate_sum / float(history); } int rate() const { return m_rate_sum / history; }
size_type rate_sum() const { return m_rate_sum; } size_type rate_sum() const { return m_rate_sum; }
size_type total() const { return m_total_counter; } size_type total() const { return m_total_counter; }
void offset(size_type counter) void offset(size_type c)
{ {
TORRENT_ASSERT(counter >= 0); TORRENT_ASSERT(c >= 0);
m_total_counter += counter; TORRENT_ASSERT(m_total_counter >= 0);
m_total_counter += c;
TORRENT_ASSERT(m_total_counter >= 0);
} }
size_type counter() const { return m_counter; } size_type counter() const { return m_counter; }
void clear() void clear()
{ {
std::memset(m_rate_history, 0, sizeof(m_rate_history )); std::memset(m_rate_history, 0, sizeof(m_rate_history ));
m_counter = 0; m_counter = 0;
m_total_counter = 0; m_total_counter = 0;
m_rate_sum = 0; m_rate_sum = 0;
} }
private: private:
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const void check_invariant() const
{ {
int sum = 0; size_type sum = 0;
for (int i = 0; i < history; ++i) sum += m_rate_hist ory[i]; for (int i = 0; i < history; ++i) sum += m_rate_hist ory[i];
TORRENT_ASSERT(m_rate_sum == sum); TORRENT_ASSERT(m_rate_sum == sum);
TORRENT_ASSERT(m_total_counter >= 0); TORRENT_ASSERT(m_total_counter >= 0);
} }
#endif #endif
// history of rates a few seconds back // history of rates a few seconds back
int m_rate_history[history]; int m_rate_history[history];
// the accumulator for this second. // the accumulator for this second.
skipping to change at line 133 skipping to change at line 142
class TORRENT_EXPORT stat class TORRENT_EXPORT stat
{ {
friend class invariant_access; friend class invariant_access;
public: public:
void operator+=(const stat& s) void operator+=(const stat& s)
{ {
for (int i = 0; i < num_channels; ++i) for (int i = 0; i < num_channels; ++i)
m_stat[i] += s.m_stat[i]; m_stat[i] += s.m_stat[i];
} }
void sent_syn(bool ipv6)
{
m_stat[upload_ip_protocol].add(ipv6 ? 60 : 40);
}
void received_synack(bool ipv6)
{
// we received SYN-ACK and also sent ACK back
m_stat[download_ip_protocol].add(ipv6 ? 60 : 40);
m_stat[upload_ip_protocol].add(ipv6 ? 60 : 40);
}
void received_dht_bytes(int bytes)
{
TORRENT_ASSERT(bytes >= 0);
m_stat[download_dht_protocol].add(bytes);
}
void sent_dht_bytes(int bytes)
{
TORRENT_ASSERT(bytes >= 0);
m_stat[upload_dht_protocol].add(bytes);
}
void received_tracker_bytes(int bytes)
{
TORRENT_ASSERT(bytes >= 0);
m_stat[download_tracker_protocol].add(bytes);
}
void sent_tracker_bytes(int bytes)
{
TORRENT_ASSERT(bytes >= 0);
m_stat[upload_tracker_protocol].add(bytes);
}
void received_bytes(int bytes_payload, int bytes_protocol) void received_bytes(int bytes_payload, int bytes_protocol)
{ {
TORRENT_ASSERT(bytes_payload >= 0); TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0); TORRENT_ASSERT(bytes_protocol >= 0);
m_stat[download_payload].add(bytes_payload); m_stat[download_payload].add(bytes_payload);
m_stat[download_protocol].add(bytes_protocol); m_stat[download_protocol].add(bytes_protocol);
} }
void sent_bytes(int bytes_payload, int bytes_protocol) void sent_bytes(int bytes_payload, int bytes_protocol)
{ {
TORRENT_ASSERT(bytes_payload >= 0); TORRENT_ASSERT(bytes_payload >= 0);
TORRENT_ASSERT(bytes_protocol >= 0); TORRENT_ASSERT(bytes_protocol >= 0);
m_stat[upload_payload].add(bytes_payload); m_stat[upload_payload].add(bytes_payload);
m_stat[upload_protocol].add(bytes_protocol); m_stat[upload_protocol].add(bytes_protocol);
} }
// calculate ip protocol overhead // and IP packet was received or sent
void calc_ip_overhead() // account for the overhead caused by it
void trancieve_ip_packet(int bytes_transferred, bool ipv6)
{ {
int uploaded = m_stat[upload_protocol].counter() // one TCP/IP packet header for the packet
+ m_stat[upload_payload].counter(); // sent or received, and one for the ACK
int downloaded = m_stat[download_protocol].counter() // The IPv4 header is 20 bytes
+ m_stat[download_payload].counter(); // and IPv6 header is 40 bytes
const int header = (ipv6 ? 40 : 20) + 20;
// IP + TCP headers are 40 bytes per MTU (1460) const int mtu = 1500;
// bytes of payload, but at least 40 bytes const int packet_size = mtu - header;
m_stat[upload_ip_protocol].add((std::max)(uploaded / const int overhead = (std::max)(1, (bytes_transferre
1460, uploaded>0?40:0)); d + packet_size - 1) / packet_size) * header;
m_stat[download_ip_protocol].add((std::max)(download m_stat[download_ip_protocol].add(overhead);
ed / 1460, downloaded>0?40:0)); m_stat[upload_ip_protocol].add(overhead);
// also account for ACK traffic. That adds to the tr
ansfers
// in the opposite direction. Even on connections wi
th symmetric
// transfer rates, it seems to add a penalty.
m_stat[upload_ip_protocol].add((std::max)(downloaded
* 40 / 1460, downloaded>0?40:0));
m_stat[download_ip_protocol].add((std::max)(uploaded
* 40 / 1460, uploaded>0?40:0));
} }
int upload_ip_overhead() const { return m_stat[upload_ip_pro tocol].counter(); } int upload_ip_overhead() const { return m_stat[upload_ip_pro tocol].counter(); }
int download_ip_overhead() const { return m_stat[download_ip _protocol].counter(); } int download_ip_overhead() const { return m_stat[download_ip _protocol].counter(); }
int upload_dht() const { return m_stat[upload_dht_protocol].
counter(); }
int download_dht() const { return m_stat[download_dht_protoc
ol].counter(); }
int download_tracker() const { return m_stat[download_tracke
r_protocol].counter(); }
int upload_tracker() const { return m_stat[upload_tracker_pr
otocol].counter(); }
// should be called once every second // should be called once every second
void second_tick(float tick_interval) void second_tick(int tick_interval_ms)
{ {
for (int i = 0; i < num_channels; ++i) for (int i = 0; i < num_channels; ++i)
m_stat[i].second_tick(tick_interval); m_stat[i].second_tick(tick_interval_ms);
} }
float upload_rate() const int upload_rate() const
{ {
return (m_stat[upload_payload].rate_sum() return (m_stat[upload_payload].rate_sum()
+ m_stat[upload_protocol].rate_sum() + m_stat[upload_protocol].rate_sum()
+ m_stat[upload_ip_protocol].rate_sum()) + m_stat[upload_ip_protocol].rate_sum()
/ float(stat_channel::history); + m_stat[upload_dht_protocol].rate_sum())
/ stat_channel::history;
} }
float download_rate() const int download_rate() const
{ {
return (m_stat[download_payload].rate_sum() return (m_stat[download_payload].rate_sum()
+ m_stat[download_protocol].rate_sum() + m_stat[download_protocol].rate_sum()
+ m_stat[download_ip_protocol].rate_sum()) + m_stat[download_ip_protocol].rate_sum()
/ float(stat_channel::history); + m_stat[download_dht_protocol].rate_sum())
/ stat_channel::history;
} }
float upload_payload_rate() const size_type total_upload() const
{ return m_stat[upload_payload].rate(); } {
return m_stat[upload_payload].total()
+ m_stat[upload_protocol].total()
+ m_stat[upload_ip_protocol].total()
+ m_stat[upload_dht_protocol].total()
+ m_stat[upload_tracker_protocol].total();
}
float download_payload_rate() const size_type total_download() const
{
return m_stat[download_payload].total()
+ m_stat[download_protocol].total()
+ m_stat[download_ip_protocol].total()
+ m_stat[download_dht_protocol].total()
+ m_stat[download_tracker_protocol].total();
}
int upload_payload_rate() const
{ return m_stat[upload_payload].rate(); }
int download_payload_rate() const
{ return m_stat[download_payload].rate(); } { return m_stat[download_payload].rate(); }
size_type total_payload_upload() const size_type total_payload_upload() const
{ return m_stat[upload_payload].total(); } { return m_stat[upload_payload].total(); }
size_type total_payload_download() const size_type total_payload_download() const
{ return m_stat[download_payload].total(); } { return m_stat[download_payload].total(); }
size_type total_protocol_upload() const size_type total_protocol_upload() const
{ return m_stat[upload_protocol].total(); } { return m_stat[upload_protocol].total(); }
size_type total_protocol_download() const size_type total_protocol_download() const
{ return m_stat[download_protocol].total(); } { return m_stat[download_protocol].total(); }
size_type total_transfer(int channel) const
{ return m_stat[channel].total(); }
int transfer_rate(int channel) const
{ return m_stat[channel].rate(); }
// this is used to offset the statistics when a // this is used to offset the statistics when a
// peer_connection is opened and have some previous // peer_connection is opened and have some previous
// transfers from earlier connections. // transfers from earlier connections.
void add_stat(size_type downloaded, size_type uploaded) void add_stat(size_type downloaded, size_type uploaded)
{ {
TORRENT_ASSERT(downloaded >= 0);
TORRENT_ASSERT(uploaded >= 0);
m_stat[download_payload].offset(downloaded); m_stat[download_payload].offset(downloaded);
m_stat[upload_payload].offset(uploaded); m_stat[upload_payload].offset(uploaded);
} }
size_type last_payload_downloaded() const size_type last_payload_downloaded() const
{ return m_stat[download_payload].counter(); } { return m_stat[download_payload].counter(); }
size_type last_payload_uploaded() const size_type last_payload_uploaded() const
{ return m_stat[upload_payload].counter(); } { return m_stat[upload_payload].counter(); }
size_type last_protocol_downloaded() const
void clear() { return m_stat[download_protocol].counter(); }
{ size_type last_protocol_uploaded() const
for (int i = 0; i < num_channels; ++i) { return m_stat[upload_protocol].counter(); }
m_stat[i].clear();
}
private:
// these are the channels we keep stats for // these are the channels we keep stats for
enum enum
{ {
upload_payload, upload_payload,
upload_protocol, upload_protocol,
upload_ip_protocol, upload_ip_protocol,
upload_dht_protocol,
upload_tracker_protocol,
download_payload, download_payload,
download_protocol, download_protocol,
download_ip_protocol, download_ip_protocol,
download_dht_protocol,
download_tracker_protocol,
num_channels num_channels
}; };
void clear()
{
for (int i = 0; i < num_channels; ++i)
m_stat[i].clear();
}
stat_channel const& operator[](int i) const
{
TORRENT_ASSERT(i >= 0 && i < num_channels);
return m_stat[i];
}
private:
stat_channel m_stat[num_channels]; stat_channel m_stat[num_channels];
}; };
} }
#endif // TORRENT_STAT_HPP_INCLUDED #endif // TORRENT_STAT_HPP_INCLUDED
 End of changes. 26 change blocks. 
50 lines changed or deleted 130 lines changed or added


 storage.hpp   storage.hpp 
skipping to change at line 60 skipping to change at line 60
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/torrent_info.hpp" #include "libtorrent/torrent_info.hpp"
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/hasher.hpp" #include "libtorrent/hasher.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp" #include "libtorrent/file.hpp"
#include "libtorrent/disk_buffer_holder.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace aux namespace aux
{ {
struct piece_checker_data; struct piece_checker_data;
} }
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
class session; class session;
struct file_pool; struct file_pool;
struct disk_io_job; struct disk_io_job;
struct disk_buffer_holder; struct disk_buffer_pool;
enum storage_mode_t enum storage_mode_t
{ {
storage_mode_allocate = 0, storage_mode_allocate = 0,
storage_mode_sparse, storage_mode_sparse,
storage_mode_compact storage_mode_compact
}; };
#if TORRENT_USE_WPATH
TORRENT_EXPORT std::wstring safe_convert(std::string const& s);
#endif
TORRENT_EXPORT std::vector<std::pair<size_type, std::time_t> > get_f ilesizes( TORRENT_EXPORT std::vector<std::pair<size_type, std::time_t> > get_f ilesizes(
file_storage const& t file_storage const& t
, fs::path p); , fs::path p);
TORRENT_EXPORT bool match_filesizes( TORRENT_EXPORT bool match_filesizes(
file_storage const& t file_storage const& t
, fs::path p , fs::path p
, std::vector<std::pair<size_type, std::time_t> > const& siz es , std::vector<std::pair<size_type, std::time_t> > const& siz es
, bool compact_mode , bool compact_mode
, std::string* error = 0); , std::string* error = 0);
skipping to change at line 119 skipping to change at line 114
{ {
partial_hash(): offset(0) {} partial_hash(): offset(0) {}
// the number of bytes in the piece that has been hashed // the number of bytes in the piece that has been hashed
int offset; int offset;
// the sha-1 context // the sha-1 context
hasher h; hasher h;
}; };
struct TORRENT_EXPORT storage_interface struct TORRENT_EXPORT storage_interface
{ {
storage_interface(): m_disk_pool(0), m_settings(0) {}
// create directories and set file sizes // create directories and set file sizes
// if allocate_files is true. // if allocate_files is true.
// allocate_files is true if allocation mode // allocate_files is true if allocation mode
// is set to full and sparse files are supported // is set to full and sparse files are supported
// false return value indicates an error // false return value indicates an error
virtual bool initialize(bool allocate_files) = 0; virtual bool initialize(bool allocate_files) = 0;
virtual bool has_any_file() = 0; virtual bool has_any_file() = 0;
virtual int readv(file::iovec_t const* bufs, int slot, int o
ffset, int num_bufs);
virtual int writev(file::iovec_t const* bufs, int slot, int
offset, int num_bufs);
// negative return value indicates an error // negative return value indicates an error
virtual int read(char* buf, int slot, int offset, int size) = 0; virtual int read(char* buf, int slot, int offset, int size) = 0;
// negative return value indicates an error // negative return value indicates an error
virtual int write(const char* buf, int slot, int offset, int size) = 0; virtual int write(const char* buf, int slot, int offset, int size) = 0;
virtual size_type physical_offset(int slot, int offset) = 0;
// returns the end of the sparse region the slot 'start'
// resides in i.e. the next slot with content. If start
// is not in a sparse region, start itself is returned
virtual int sparse_end(int start) const { return start; }
// non-zero return value indicates an error // non-zero return value indicates an error
virtual bool move_storage(fs::path save_path) = 0; virtual bool move_storage(fs::path save_path) = 0;
// verify storage dependent fast resume entries // verify storage dependent fast resume entries
virtual bool verify_resume_data(lazy_entry const& rd, std::s tring& error) = 0; virtual bool verify_resume_data(lazy_entry const& rd, error_ code& error) = 0;
// write storage dependent fast resume entries // write storage dependent fast resume entries
virtual bool write_resume_data(entry& rd) const = 0; virtual bool write_resume_data(entry& rd) const = 0;
// moves (or copies) the content in src_slot to dst_slot // moves (or copies) the content in src_slot to dst_slot
virtual bool move_slot(int src_slot, int dst_slot) = 0; virtual bool move_slot(int src_slot, int dst_slot) = 0;
// swaps the data in slot1 and slot2 // swaps the data in slot1 and slot2
virtual bool swap_slots(int slot1, int slot2) = 0; virtual bool swap_slots(int slot1, int slot2) = 0;
// swaps the puts the data in slot1 in slot2, the data in sl ot2 // swaps the puts the data in slot1 in slot2, the data in sl ot2
// in slot3 and the data in slot3 in slot1 // in slot3 and the data in slot3 in slot1
virtual bool swap_slots3(int slot1, int slot2, int slot3) = 0; virtual bool swap_slots3(int slot1, int slot2, int slot3) = 0;
// returns the sha1-hash for the data at the given slot
virtual sha1_hash hash_for_slot(int slot, partial_hash& h, i
nt piece_size) = 0;
// this will close all open files that are opened for // this will close all open files that are opened for
// writing. This is called when a torrent has finished // writing. This is called when a torrent has finished
// downloading. // downloading.
// non-zero return value indicates an error // non-zero return value indicates an error
virtual bool release_files() = 0; virtual bool release_files() = 0;
// this will rename the file specified by index. // this will rename the file specified by index.
virtual bool rename_file(int index, std::string const& new_f ilename) = 0; virtual bool rename_file(int index, std::string const& new_f ilename) = 0;
// this will close all open files and delete them // this will close all open files and delete them
// non-zero return value indicates an error // non-zero return value indicates an error
virtual bool delete_files() = 0; virtual bool delete_files() = 0;
disk_buffer_pool* disk_pool() { return m_disk_pool; }
session_settings const& settings() const { return *m_setting
s; }
void set_error(boost::filesystem::path const& file, error_co de const& ec) const void set_error(boost::filesystem::path const& file, error_co de const& ec) const
{ {
m_error_file = file.string(); m_error_file = file.string();
m_error = ec; m_error = ec;
} }
error_code const& error() const { return m_error; } error_code const& error() const { return m_error; }
std::string const& error_file() const { return m_error_file; } std::string const& error_file() const { return m_error_file; }
void clear_error() { m_error = error_code(); m_error_file.cl ear(); } void clear_error() { m_error = error_code(); m_error_file.cl ear(); }
mutable error_code m_error; mutable error_code m_error;
mutable std::string m_error_file; mutable std::string m_error_file;
virtual ~storage_interface() {} virtual ~storage_interface() {}
disk_buffer_pool* m_disk_pool;
session_settings* m_settings;
}; };
typedef storage_interface* (&storage_constructor_type)( typedef storage_interface* (*storage_constructor_type)(
file_storage const&, file_storage const*, fs::path const&, f ile_pool&); file_storage const&, file_storage const*, fs::path const&, f ile_pool&);
TORRENT_EXPORT storage_interface* default_storage_constructor( TORRENT_EXPORT storage_interface* default_storage_constructor(
file_storage const&, file_storage const* mapped, fs::path co nst&, file_pool&); file_storage const&, file_storage const* mapped, fs::path co nst&, file_pool&);
TORRENT_EXPORT storage_interface* disabled_storage_constructor(
file_storage const&, file_storage const* mapped, fs::path co
nst&, file_pool&);
struct disk_io_thread; struct disk_io_thread;
class TORRENT_EXPORT piece_manager class TORRENT_EXPORT piece_manager
: public intrusive_ptr_base<piece_manager> : public intrusive_ptr_base<piece_manager>
, boost::noncopyable , boost::noncopyable
{ {
friend class invariant_access; friend class invariant_access;
friend struct disk_io_thread; friend struct disk_io_thread;
public: public:
skipping to change at line 220 skipping to change at line 232
~piece_manager(); ~piece_manager();
boost::intrusive_ptr<torrent_info const> info() const { retu rn m_info; } boost::intrusive_ptr<torrent_info const> info() const { retu rn m_info; }
void write_resume_data(entry& rd) const; void write_resume_data(entry& rd) const;
void async_check_fastresume(lazy_entry const* resume_data void async_check_fastresume(lazy_entry const* resume_data
, boost::function<void(int, disk_io_job const&)> con st& handler); , boost::function<void(int, disk_io_job const&)> con st& handler);
void async_check_files(boost::function<void(int, disk_io_job const&)> const& handler); void async_check_files(boost::function<void(int, disk_io_job const&)> const& handler);
int queued_bytes() const;
void async_rename_file(int index, std::string const& name void async_rename_file(int index, std::string const& name
, boost::function<void(int, disk_io_job const&)> con st& handler); , boost::function<void(int, disk_io_job const&)> con st& handler);
void async_read( void async_read(
peer_request const& r peer_request const& r
, boost::function<void(int, disk_io_job const&)> con st& handler , boost::function<void(int, disk_io_job const&)> con st& handler
, int priority = 0); , int priority = 0);
void async_read_and_hash(
peer_request const& r
, boost::function<void(int, disk_io_job const&)> con
st& handler
, int priority = 0);
void async_write( void async_write(
peer_request const& r peer_request const& r
, disk_buffer_holder& buffer , disk_buffer_holder& buffer
, boost::function<void(int, disk_io_job const&)> con st& f); , boost::function<void(int, disk_io_job const&)> con st& f);
void async_hash(int piece, boost::function<void(int, disk_io _job const&)> const& f); void async_hash(int piece, boost::function<void(int, disk_io _job const&)> const& f);
void async_release_files( void async_release_files(
boost::function<void(int, disk_io_job const&)> const & handler boost::function<void(int, disk_io_job const&)> const & handler
= boost::function<void(int, disk_io_job const&)>()); = boost::function<void(int, disk_io_job const&)>());
skipping to change at line 270 skipping to change at line 289
fatal_disk_error = -2, fatal_disk_error = -2,
disk_check_aborted = -3 disk_check_aborted = -3
}; };
storage_interface* get_storage_impl() { return m_storage.get (); } storage_interface* get_storage_impl() { return m_storage.get (); }
private: private:
fs::path save_path() const; fs::path save_path() const;
bool verify_resume_data(lazy_entry const& rd, std::string& e bool verify_resume_data(lazy_entry const& rd, error_code& e)
rror) { return m_storage->verify_resume_data(rd, e); }
{ return m_storage->verify_resume_data(rd, error); }
bool is_allocating() const bool is_allocating() const
{ return m_state == state_expand_pieces; } { return m_state == state_expand_pieces; }
void mark_failed(int index); void mark_failed(int index);
error_code const& error() const { return m_storage->error(); } error_code const& error() const { return m_storage->error(); }
std::string const& error_file() const { return m_storage->er ror_file(); } std::string const& error_file() const { return m_storage->er ror_file(); }
int last_piece() const { return m_last_piece; }
int last_operation() const { return m_last_op; }
void clear_error() { m_storage->clear_error(); } void clear_error() { m_storage->clear_error(); }
int slot_for(int piece) const; int slot_for(int piece) const;
int piece_for(int slot) const; int piece_for(int slot) const;
// helper functions for check_dastresume // helper functions for check_dastresume
int check_no_fastresume(std::string& error); int check_no_fastresume(error_code& error);
int check_init_storage(std::string& error); int check_init_storage(error_code& error);
// if error is set and return value is 'no_error' or 'need_f ull_check' // if error is set and return value is 'no_error' or 'need_f ull_check'
// the error message indicates that the fast resume data was rejected // the error message indicates that the fast resume data was rejected
// if 'fatal_disk_error' is returned, the error message indi cates what // if 'fatal_disk_error' is returned, the error message indi cates what
// when wrong in the disk access // when wrong in the disk access
int check_fastresume(lazy_entry const& rd, std::string& erro r); int check_fastresume(lazy_entry const& rd, error_code& error );
// this function returns true if the checking is complete // this function returns true if the checking is complete
int check_files(int& current_slot, int& have_piece, std::str ing& error); int check_files(int& current_slot, int& have_piece, error_co de& error);
bool compact_allocation() const bool compact_allocation() const
{ return m_storage_mode == storage_mode_compact; } { return m_storage_mode == storage_mode_compact; }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
std::string name() const { return m_info->name(); } std::string name() const { return m_info->name(); }
#endif #endif
bool allocate_slots(int num_slots, bool abort_on_disk = fals e); bool allocate_slots(int num_slots, bool abort_on_disk = fals e);
// updates the ph.h hasher object with the data at the given
slot
// and optionally a 'small hash' as well, the hash for
// the partial slot. Returns the number of bytes read
int hash_for_slot(int slot, partial_hash& h, int piece_size
, int small_piece_size = 0, sha1_hash* small_hash =
0);
int read_impl( int read_impl(
char* buf file::iovec_t* bufs
, int piece_index , int piece_index
, int offset , int offset
, int size); , int num_bufs);
int write_impl( int write_impl(
const char* buf file::iovec_t* bufs
, int piece_index , int piece_index
, int offset , int offset
, int size); , int num_bufs);
// -1=error 0=ok 1=skip size_type physical_offset(int piece_index, int offset);
// returns the number of pieces left in the
// file currently being checked
int skip_file() const;
// -1=error 0=ok >0=skip this many pieces
int check_one_piece(int& have_piece); int check_one_piece(int& have_piece);
int identify_data( int identify_data(
const std::vector<char>& piece_data sha1_hash const& large_hash
, sha1_hash const& small_hash
, int current_slot); , int current_slot);
void switch_to_full_mode(); void switch_to_full_mode();
sha1_hash hash_for_piece_impl(int piece); sha1_hash hash_for_piece_impl(int piece);
int release_files_impl() { return m_storage->release_files() ; } int release_files_impl() { return m_storage->release_files() ; }
int delete_files_impl() { return m_storage->delete_files(); } int delete_files_impl() { return m_storage->delete_files(); }
int rename_file_impl(int index, std::string const& new_filen ame) int rename_file_impl(int index, std::string const& new_filen ame)
{ return m_storage->rename_file(index, new_filename); } { return m_storage->rename_file(index, new_filename); }
skipping to change at line 395 skipping to change at line 428
state_expand_pieces state_expand_pieces
} m_state; } m_state;
int m_current_slot; int m_current_slot;
// used during check. If any piece is found // used during check. If any piece is found
// that is not in its final position, this // that is not in its final position, this
// is set to true // is set to true
bool m_out_of_place; bool m_out_of_place;
// used to move pieces while expanding // used to move pieces while expanding
// the storage from compact allocation // the storage from compact allocation
// to full allocation // to full allocation
buffer m_scratch_buffer; disk_buffer_holder m_scratch_buffer;
buffer m_scratch_buffer2; disk_buffer_holder m_scratch_buffer2;
// the piece that is in the scratch buffer // the piece that is in the scratch buffer
int m_scratch_piece; int m_scratch_piece;
// the last piece we wrote to or read from
int m_last_piece;
// the last operation we did (read or write)
int m_last_op;
// this is saved in case we need to instantiate a new // this is saved in case we need to instantiate a new
// storage (osed when remapping files) // storage (osed when remapping files)
storage_constructor_type m_storage_constructor; storage_constructor_type m_storage_constructor;
// temporary buffer used while checking
std::vector<char> m_piece_data;
// this maps a piece hash to piece index. It will be // this maps a piece hash to piece index. It will be
// build the first time it is used (to save time if it // build the first time it is used (to save time if it
// isn't needed) // isn't needed)
std::multimap<sha1_hash, int> m_hash_to_piece; std::multimap<sha1_hash, int> m_hash_to_piece;
// this map contains partial hashes for downloading // this map contains partial hashes for downloading
// pieces. This is only accessed from within the // pieces. This is only accessed from within the
// disk-io thread. // disk-io thread.
std::map<int, partial_hash> m_piece_hasher; std::map<int, partial_hash> m_piece_hasher;
 End of changes. 29 change blocks. 
32 lines changed or deleted 73 lines changed or added


 time.hpp   time.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_TIME_HPP_INCLUDED #ifndef TORRENT_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED #define TORRENT_TIME_HPP_INCLUDED
#include <ctime> #include <ctime>
#include <boost/version.hpp> #include <boost/version.hpp>
#include "libtorrent/config.hpp"
#ifndef _WIN32 #ifndef _WIN32
#include <unistd.h> #include <unistd.h>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
inline char const* time_now_string() inline char const* time_now_string()
{ {
time_t t = std::time(0); time_t t = std::time(0);
tm* timeinfo = std::localtime(&t); tm* timeinfo = std::localtime(&t);
static char str[200]; static char str[200];
std::strftime(str, 200, "%b %d %X", timeinfo); std::strftime(str, 200, "%b %d %X", timeinfo);
return str; return str;
} }
std::string log_time(); std::string log_time();
} }
#if (!defined (__MACH__) && !defined (_WIN32) && (!defined(_POSIX_MONOTONIC #if defined TORRENT_USE_BOOST_DATE_TIME
_CLOCK) \
|| _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_T
IME)
#include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
typedef boost::posix_time::ptime ptime; typedef boost::posix_time::ptime ptime;
typedef boost::posix_time::time_duration time_duration; typedef boost::posix_time::time_duration time_duration;
inline ptime time_now() inline ptime time_now_hires()
{ return boost::posix_time::microsec_clock::universal_time(); } { return boost::posix_time::microsec_clock::universal_time(); }
inline ptime min_time() inline ptime min_time()
{ return boost::posix_time::ptime(boost::posix_time::min_date_time); } { return boost::posix_time::ptime(boost::posix_time::min_date_time); }
inline ptime max_time() inline ptime max_time()
{ return boost::posix_time::ptime(boost::posix_time::max_date_time); } { return boost::posix_time::ptime(boost::posix_time::max_date_time); }
inline time_duration seconds(int s) { return boost::posix_time::seco nds(s); } inline time_duration seconds(int s) { return boost::posix_time::seco nds(s); }
inline time_duration milliseconds(int s) { return boost::posix_time: :milliseconds(s); } inline time_duration milliseconds(int s) { return boost::posix_time: :milliseconds(s); }
inline time_duration microsec(int s) { return boost::posix_time::mic rosec(s); } inline time_duration microsec(int s) { return boost::posix_time::mic rosec(s); }
inline time_duration minutes(int s) { return boost::posix_time::minu tes(s); } inline time_duration minutes(int s) { return boost::posix_time::minu tes(s); }
inline time_duration hours(int s) { return boost::posix_time::hours( s); } inline time_duration hours(int s) { return boost::posix_time::hours( s); }
inline int total_seconds(time_duration td) inline int total_seconds(time_duration td)
{ return td.total_seconds(); } { return td.total_seconds(); }
inline int total_milliseconds(time_duration td) inline int total_milliseconds(time_duration td)
{ return td.total_milliseconds(); } { return td.total_milliseconds(); }
inline boost::int64_t total_microseconds(time_duration td) inline boost::int64_t total_microseconds(time_duration td)
{ return td.total_microseconds(); } { return td.total_microseconds(); }
} }
#else #else // TORRENT_USE_BOOST_DATE_TIME
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/time_traits.hpp> #include <asio/time_traits.hpp>
#else #else
#include <boost/asio/time_traits.hpp> #include <boost/asio/time_traits.hpp>
#endif #endif
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
// libtorrent time_duration type // libtorrent time_duration type
struct time_duration struct time_duration
{ {
time_duration() {} time_duration() {}
time_duration operator/(int rhs) const { return time_duratio n(diff / rhs); } time_duration operator/(int rhs) const { return time_duratio n(diff / rhs); }
explicit time_duration(boost::int64_t d) : diff(d) {} explicit time_duration(boost::int64_t d) : diff(d) {}
time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; } time_duration& operator-=(time_duration const& c) { diff -= c.diff; return *this; }
time_duration& operator+=(time_duration const& c) { diff += c.diff; return *this; } time_duration& operator+=(time_duration const& c) { diff += c.diff; return *this; }
time_duration operator+(time_duration const& c) { return tim e_duration(diff + c.diff); } time_duration operator+(time_duration const& c) { return tim e_duration(diff + c.diff); }
time_duration operator-(time_duration const& c) { return tim e_duration(diff - c.diff); }
boost::int64_t diff; boost::int64_t diff;
}; };
inline bool is_negative(time_duration dt) { return dt.diff < 0; } inline bool is_negative(time_duration dt) { return dt.diff < 0; }
inline bool operator==(time_duration lhs, time_duration rhs)
{ return lhs.diff == rhs.diff; }
inline bool operator<(time_duration lhs, time_duration rhs) inline bool operator<(time_duration lhs, time_duration rhs)
{ return lhs.diff < rhs.diff; } { return lhs.diff < rhs.diff; }
inline bool operator<=(time_duration lhs, time_duration rhs) inline bool operator<=(time_duration lhs, time_duration rhs)
{ return lhs.diff <= rhs.diff; } { return lhs.diff <= rhs.diff; }
inline bool operator>(time_duration lhs, time_duration rhs) inline bool operator>(time_duration lhs, time_duration rhs)
{ return lhs.diff > rhs.diff; } { return lhs.diff > rhs.diff; }
inline bool operator>=(time_duration lhs, time_duration rhs) inline bool operator>=(time_duration lhs, time_duration rhs)
{ return lhs.diff >= rhs.diff; } { return lhs.diff >= rhs.diff; }
inline time_duration operator*(time_duration lhs, int rhs)
{ return time_duration(boost::int64_t(lhs.diff * rhs)); }
inline time_duration operator*(int lhs, time_duration rhs)
{ return time_duration(boost::int64_t(lhs * rhs.diff)); }
// libtorrent time type // libtorrent time type
struct ptime struct ptime
{ {
ptime() {} ptime() {}
explicit ptime(boost::int64_t t): time(t) {} explicit ptime(boost::uint64_t t): time(t) {}
ptime& operator+=(time_duration rhs) { time += rhs.diff; ret urn *this; } ptime& operator+=(time_duration rhs) { time += rhs.diff; ret urn *this; }
ptime& operator-=(time_duration rhs) { time -= rhs.diff; ret urn *this; } ptime& operator-=(time_duration rhs) { time -= rhs.diff; ret urn *this; }
boost::int64_t time; boost::uint64_t time;
}; };
inline bool operator>(ptime lhs, ptime rhs) inline bool operator>(ptime lhs, ptime rhs)
{ return lhs.time > rhs.time; } { return lhs.time > rhs.time; }
inline bool operator>=(ptime lhs, ptime rhs) inline bool operator>=(ptime lhs, ptime rhs)
{ return lhs.time >= rhs.time; } { return lhs.time >= rhs.time; }
inline bool operator<=(ptime lhs, ptime rhs) inline bool operator<=(ptime lhs, ptime rhs)
{ return lhs.time <= rhs.time; } { return lhs.time <= rhs.time; }
inline bool operator<(ptime lhs, ptime rhs) inline bool operator<(ptime lhs, ptime rhs)
{ return lhs.time < rhs.time; } { return lhs.time < rhs.time; }
skipping to change at line 153 skipping to change at line 160
{ return lhs.time == rhs.time;} { return lhs.time == rhs.time;}
inline time_duration operator-(ptime lhs, ptime rhs) inline time_duration operator-(ptime lhs, ptime rhs)
{ return time_duration(lhs.time - rhs.time); } { return time_duration(lhs.time - rhs.time); }
inline ptime operator+(ptime lhs, time_duration rhs) inline ptime operator+(ptime lhs, time_duration rhs)
{ return ptime(lhs.time + rhs.diff); } { return ptime(lhs.time + rhs.diff); }
inline ptime operator+(time_duration lhs, ptime rhs) inline ptime operator+(time_duration lhs, ptime rhs)
{ return ptime(rhs.time + lhs.diff); } { return ptime(rhs.time + lhs.diff); }
inline ptime operator-(ptime lhs, time_duration rhs) inline ptime operator-(ptime lhs, time_duration rhs)
{ return ptime(lhs.time - rhs.diff); } { return ptime(lhs.time - rhs.diff); }
ptime time_now(); ptime time_now_hires();
inline ptime min_time() { return ptime(0); } inline ptime min_time() { return ptime(0); }
inline ptime max_time() { return ptime((std::numeric_limits<boost::i nt64_t>::max)()); } inline ptime max_time() { return ptime((std::numeric_limits<boost::u int64_t>::max)()); }
int total_seconds(time_duration td); int total_seconds(time_duration td);
int total_milliseconds(time_duration td); int total_milliseconds(time_duration td);
boost::int64_t total_microseconds(time_duration td); boost::int64_t total_microseconds(time_duration td);
} }
// asio time_traits // asio time_traits
#if BOOST_VERSION >= 103500 #if BOOST_VERSION >= 103500
namespace boost { namespace boost {
#endif #endif
namespace asio namespace asio
{ {
template<> template<>
struct time_traits<libtorrent::ptime> struct time_traits<libtorrent::ptime>
{ {
typedef libtorrent::ptime time_type; typedef libtorrent::ptime time_type;
typedef libtorrent::time_duration duration_type; typedef libtorrent::time_duration duration_type;
static time_type now() static time_type now()
{ return time_type(libtorrent::time_now()); } { return time_type(libtorrent::time_now_hires()); }
static time_type add(time_type t, duration_type d) static time_type add(time_type t, duration_type d)
{ return time_type(t.time + d.diff);} { return time_type(t.time + d.diff);}
static duration_type subtract(time_type t1, time_type t2) static duration_type subtract(time_type t1, time_type t2)
{ return duration_type(t1 - t2); } { return duration_type(t1 - t2); }
static bool less_than(time_type t1, time_type t2) static bool less_than(time_type t1, time_type t2)
{ return t1 < t2; } { return t1 < t2; }
static boost::posix_time::time_duration to_posix_duration( static boost::posix_time::time_duration to_posix_duration(
duration_type d) duration_type d)
{ return boost::posix_time::microseconds(libtorrent::total_m icroseconds(d)); } { return boost::posix_time::microseconds(libtorrent::total_m icroseconds(d)); }
}; };
} }
#if BOOST_VERSION >= 103500 #if BOOST_VERSION >= 103500
} }
#endif #endif
#if defined(__MACH__) #if defined TORRENT_USE_ABSOLUTE_TIME
#include <mach/mach_time.h> #include <mach/mach_time.h>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
// high precision timer for darwin intel and ppc // high precision timer for darwin intel and ppc
namespace libtorrent namespace libtorrent
{ {
namespace aux
{
inline boost::int64_t absolutetime_to_microseconds(boost::in
t64_t at)
{
static mach_timebase_info_data_t timebase_info = {0,
0};
if (timebase_info.denom == 0)
mach_timebase_info(&timebase_info);
// make sure we don't overflow
TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebas
e_info.numer / timebase_info.denom)
|| (at < 0 && at < at / 1000 * timebase_info
.numer / timebase_info.denom));
return at / 1000 * timebase_info.numer / timebase_in
fo.denom;
}
inline boost::int64_t microseconds_to_absolutetime(boost::in
t64_t ms)
{
static mach_timebase_info_data_t timebase_info = {0,
0};
if (timebase_info.denom == 0)
{
mach_timebase_info(&timebase_info);
TORRENT_ASSERT(timebase_info.numer > 0);
TORRENT_ASSERT(timebase_info.denom > 0);
}
// make sure we don't overflow
TORRENT_ASSERT((ms >= 0 && ms <= ms * timebase_info.
denom / timebase_info.numer * 1000)
|| (ms < 0 && ms > ms * timebase_info.denom
/ timebase_info.numer * 1000));
return ms * timebase_info.denom / timebase_info.nume
r * 1000;
}
}
inline int total_seconds(time_duration td) inline int total_seconds(time_duration td)
{ {
return aux::absolutetime_to_microseconds(td.diff) return td.diff / 1000000;
/ 1000000;
} }
inline int total_milliseconds(time_duration td) inline int total_milliseconds(time_duration td)
{ {
return aux::absolutetime_to_microseconds(td.diff) return td.diff / 1000;
/ 1000;
} }
inline boost::int64_t total_microseconds(time_duration td) inline boost::int64_t total_microseconds(time_duration td)
{ {
return aux::absolutetime_to_microseconds(td.diff); return td.diff;
} }
inline ptime time_now() { return ptime(mach_absolute_time()); } inline ptime time_now_hires()
{
static mach_timebase_info_data_t timebase_info = {0,0};
if (timebase_info.denom == 0)
mach_timebase_info(&timebase_info);
boost::uint64_t at = mach_absolute_time();
// make sure we don't overflow
TORRENT_ASSERT((at >= 0 && at >= at / 1000 * timebase_info.n
umer / timebase_info.denom)
|| (at < 0 && at < at / 1000 * timebase_info.numer /
timebase_info.denom));
return ptime(at / 1000 * timebase_info.numer / timebase_info
.denom);
}
inline time_duration microsec(boost::int64_t s) inline time_duration microsec(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_absolutetime(s)); return time_duration(s);
} }
inline time_duration milliseconds(boost::int64_t s) inline time_duration milliseconds(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_absolutetime(s * 1 000)); return time_duration(s * 1000);
} }
inline time_duration seconds(boost::int64_t s) inline time_duration seconds(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_absolutetime(s * 1 000000)); return time_duration(s * 1000000);
} }
inline time_duration minutes(boost::int64_t s) inline time_duration minutes(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_absolutetime(s * 1 000000 * 60)); return time_duration(s * 1000000 * 60);
} }
inline time_duration hours(boost::int64_t s) inline time_duration hours(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_absolutetime(s * 1 000000 * 60 * 60)); return time_duration(s * 1000000 * 60 * 60);
} }
} }
#elif defined(_WIN32) #elif defined TORRENT_USE_QUERY_PERFORMANCE_TIMER
#ifndef WIN32_LEAN_AND_MEAN #ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#endif #endif
#include <windows.h> #include <windows.h>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace aux namespace aux
skipping to change at line 323 skipping to change at line 309
inline int total_milliseconds(time_duration td) inline int total_milliseconds(time_duration td)
{ {
return int(aux::performance_counter_to_microseconds(td.diff) return int(aux::performance_counter_to_microseconds(td.diff)
/ 1000); / 1000);
} }
inline boost::int64_t total_microseconds(time_duration td) inline boost::int64_t total_microseconds(time_duration td)
{ {
return aux::performance_counter_to_microseconds(td.diff); return aux::performance_counter_to_microseconds(td.diff);
} }
inline ptime time_now() inline ptime time_now_hires()
{ {
LARGE_INTEGER now; LARGE_INTEGER now;
QueryPerformanceCounter(&now); QueryPerformanceCounter(&now);
return ptime(now.QuadPart); return ptime(now.QuadPart);
} }
inline time_duration microsec(boost::int64_t s) inline time_duration microsec(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_performance_counte r(s)); return time_duration(aux::microseconds_to_performance_counte r(s));
} }
skipping to change at line 357 skipping to change at line 343
s * 1000000 * 60)); s * 1000000 * 60));
} }
inline time_duration hours(boost::int64_t s) inline time_duration hours(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_performance_counte r( return time_duration(aux::microseconds_to_performance_counte r(
s * 1000000 * 60 * 60)); s * 1000000 * 60 * 60));
} }
} }
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 #elif defined TORRENT_USE_CLOCK_GETTIME
#include <time.h> #include <time.h>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
inline int total_seconds(time_duration td) inline int total_seconds(time_duration td)
{ {
return td.diff / 1000000; return td.diff / 1000000;
} }
inline int total_milliseconds(time_duration td) inline int total_milliseconds(time_duration td)
{ {
return td.diff / 1000; return td.diff / 1000;
} }
inline boost::int64_t total_microseconds(time_duration td) inline boost::int64_t total_microseconds(time_duration td)
{ {
return td.diff; return td.diff;
} }
inline ptime time_now() inline ptime time_now_hires()
{ {
timespec ts; timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts); clock_gettime(CLOCK_MONOTONIC, &ts);
return ptime(boost::int64_t(ts.tv_sec) * 1000000 + ts.tv_nse c / 1000); return ptime(boost::uint64_t(ts.tv_sec) * 1000000 + ts.tv_ns ec / 1000);
} }
inline time_duration microsec(boost::int64_t s) inline time_duration microsec(boost::int64_t s)
{ {
return time_duration(s); return time_duration(s);
} }
inline time_duration milliseconds(boost::int64_t s) inline time_duration milliseconds(boost::int64_t s)
{ {
return time_duration(s * 1000); return time_duration(s * 1000);
} }
skipping to change at line 407 skipping to change at line 393
{ {
return time_duration(s * 1000000 * 60); return time_duration(s * 1000000 * 60);
} }
inline time_duration hours(boost::int64_t s) inline time_duration hours(boost::int64_t s)
{ {
return time_duration(s * 1000000 * 60 * 60); return time_duration(s * 1000000 * 60 * 60);
} }
} }
#endif #endif // TORRENT_USE_CLOCK_GETTIME
#endif #endif // TORRENT_USE_BOOST_DATE_TIME
#endif namespace libtorrent
{
TORRENT_EXPORT ptime const& time_now();
}
#endif // TORRENT_TIME_HPP_INCLUDED
 End of changes. 31 change blocks. 
69 lines changed or deleted 46 lines changed or added


 torrent.hpp   torrent.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#ifndef TORRENT_TORRENT_HPP_INCLUDE #ifndef TORRENT_TORRENT_HPP_INCLUDE
#define TORRENT_TORRENT_HPP_INCLUDE #define TORRENT_TORRENT_HPP_INCLUDE
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <set> #include <set>
#include <list> #include <list>
#include <iostream>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <boost/enable_shared_from_this.hpp> #include <boost/enable_shared_from_this.hpp>
#include <boost/scoped_ptr.hpp> #include <boost/scoped_ptr.hpp>
skipping to change at line 74 skipping to change at line 73
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/escape_string.hpp" #include "libtorrent/escape_string.hpp"
#include "libtorrent/bandwidth_limit.hpp" #include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_queue_entry.hpp" #include "libtorrent/bandwidth_queue_entry.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/hasher.hpp" #include "libtorrent/hasher.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/bitfield.hpp" #include "libtorrent/bitfield.hpp"
#include "libtorrent/aux_/session_impl.hpp"
#if TORRENT_COMPLETE_TYPES_REQUIRED #if TORRENT_COMPLETE_TYPES_REQUIRED
#include "libtorrent/peer_connection.hpp" #include "libtorrent/peer_connection.hpp"
#endif #endif
namespace libtorrent namespace libtorrent
{ {
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
struct logger; struct logger;
#endif #endif
class piece_manager; class piece_manager;
struct torrent_plugin; struct torrent_plugin;
struct bitfield; struct bitfield;
struct announce_entry;
struct tracker_request;
struct add_torrent_params;
namespace aux namespace aux
{ {
struct session_impl;
struct piece_checker_data; struct piece_checker_data;
} }
struct web_seed_entry
{
std::string url;
// http seeds are different from url seeds in the
// protocol they use. http seeds follows the original
// http seed spec. by John Hoffman
enum type_t { url_seed, http_seed} type;
web_seed_entry(std::string const& url_, type_t type_)
: url(url_), type(type_) {}
bool operator==(web_seed_entry const& e) const
{ return url == e.url && type == e.type; }
bool operator<(web_seed_entry const& e) const
{
if (url < e.url) return true;
if (url > e.url) return false;
return type < e.type;
}
};
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
// a torrent is a class that holds information // a torrent is a class that holds information
// for a specific download. It updates itself against // for a specific download. It updates itself against
// the tracker // the tracker
class TORRENT_EXPORT torrent: public request_callback class TORRENT_EXPORT torrent: public request_callback
, public boost::enable_shared_from_this<torrent> , public boost::enable_shared_from_this<torrent>
{ {
public: public:
torrent( torrent(aux::session_impl& ses, tcp::endpoint const& net_int
aux::session_impl& ses erface
, boost::intrusive_ptr<torrent_info> tf , int block_size, int seq, add_torrent_params const&
, fs::path const& save_path p);
, tcp::endpoint const& net_interface
, storage_mode_t m_storage_mode
, int block_size
, storage_constructor_type sc
, bool paused
, std::vector<char>* resume_data
, int seq
, bool auto_managed);
// used with metadata-less torrents
// (the metadata is downloaded from the peers)
torrent(
aux::session_impl& ses
, char const* tracker_url
, sha1_hash const& info_hash
, char const* name
, fs::path const& save_path
, tcp::endpoint const& net_interface
, storage_mode_t m_storage_mode
, int block_size
, storage_constructor_type sc
, bool paused
, std::vector<char>* resume_data
, int seq
, bool auto_managed);
~torrent(); ~torrent();
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
sha1_hash const& obfuscated_hash() const sha1_hash const& obfuscated_hash() const
{ return m_obfuscated_hash; } { return m_obfuscated_hash; }
#endif #endif
sha1_hash const& info_hash() const sha1_hash const& info_hash() const
{ return m_torrent_file->info_hash(); } { return m_torrent_file->info_hash(); }
skipping to change at line 166 skipping to change at line 162
{ return m_connections.find(p) != m_connections.end(); } { return m_connections.find(p) != m_connections.end(); }
#endif #endif
// this is called when the torrent has metadata. // this is called when the torrent has metadata.
// it will initialize the storage and the piece-picker // it will initialize the storage and the piece-picker
void init(); void init();
void on_resume_data_checked(int ret, disk_io_job const& j); void on_resume_data_checked(int ret, disk_io_job const& j);
void on_force_recheck(int ret, disk_io_job const& j); void on_force_recheck(int ret, disk_io_job const& j);
void on_piece_checked(int ret, disk_io_job const& j); void on_piece_checked(int ret, disk_io_job const& j);
void files_checked(); void files_checked_lock();
void files_checked(aux::session_impl::mutex_t::scoped_lock c
onst&);
void start_checking(); void start_checking();
void start_announcing(); void start_announcing();
void stop_announcing(); void stop_announcing();
void send_upload_only();
void set_upload_mode(bool b);
bool upload_mode() const { return m_upload_mode; }
bool is_upload_only() const
{ return (is_finished() || upload_mode()) && !super_seeding(
); }
int seed_rank(session_settings const& s) const; int seed_rank(session_settings const& s) const;
enum flags_t { overwrite_existing = 1 };
void add_piece(int piece, char const* data, int flags = 0);
void on_disk_write_complete(int ret, disk_io_job const& j
, peer_request p);
struct read_piece_struct
{
boost::shared_array<char> piece_data;
int blocks_left;
bool fail;
};
void read_piece(int piece);
void on_disk_read_complete(int ret, disk_io_job const& j, pe
er_request r, read_piece_struct* rp);
storage_mode_t storage_mode() const { return m_storage_mode; } storage_mode_t storage_mode() const { return m_storage_mode; }
storage_interface* get_storage() storage_interface* get_storage()
{ {
if (!m_owning_storage) return 0; if (!m_owning_storage) return 0;
return m_owning_storage->get_storage_impl(); return m_owning_storage->get_storage_impl();
} }
// this will flag the torrent as aborted. The main // this will flag the torrent as aborted. The main
// loop in session_impl will check for this state // loop in session_impl will check for this state
// on all torrents once every second, and take // on all torrents once every second, and take
// the necessary actions then. // the necessary actions then.
void abort(); void abort();
bool is_aborted() const { return m_abort; } bool is_aborted() const { return m_abort; }
torrent_status::state_t state() const { return m_state; } torrent_status::state_t state() const { return m_state; }
void set_state(torrent_status::state_t s); void set_state(torrent_status::state_t s);
void clear_error();
session_settings const& settings() const; session_settings const& settings() const;
aux::session_impl& session() { return m_ses; } aux::session_impl& session() { return m_ses; }
void set_sequential_download(bool sd); void set_sequential_download(bool sd);
bool is_sequential_download() const bool is_sequential_download() const
{ return m_sequential_download; } { return m_sequential_download; }
void set_queue_position(int p); void set_queue_position(int p);
int queue_position() const { return m_sequence_number; } int queue_position() const { return m_sequence_number; }
void second_tick(stat& accumulator, float tick_interval); void second_tick(stat& accumulator, int tick_interval_ms);
// debug purpose only
void print(std::ostream& os) const;
std::string name() const; std::string name() const;
stat statistics() const { return m_stat; } stat statistics() const { return m_stat; }
void add_stats(stat const& s) { m_stat += s; } void add_stats(stat const& s);
size_type bytes_left() const; size_type bytes_left() const;
boost::tuples::tuple<size_type, size_type> bytes_done() cons int block_bytes_wanted(piece_block const& p) const;
t; void bytes_done(torrent_status& st) const;
size_type quantized_bytes_done() const; size_type quantized_bytes_done() const;
void ip_filter_updated() { m_policy.ip_filter_updated(); } void ip_filter_updated() { m_policy.ip_filter_updated(); }
void set_error(std::string const& msg); void handle_disk_error(disk_io_job const& j, peer_connection
bool has_error() const { return !m_error.empty(); } * c = 0);
void clear_error();
void set_error(error_code const& ec, std::string const& file
);
bool has_error() const { return m_error; }
void flush_cache();
void pause(); void pause();
void resume(); void resume();
ptime started() const { return m_started; } ptime started() const { return m_started; }
void do_pause(); void do_pause();
void do_resume(); void do_resume();
bool is_paused() const; bool is_paused() const;
bool is_torrent_paused() const { return m_paused; } bool is_torrent_paused() const { return m_paused; }
void force_recheck(); void force_recheck();
skipping to change at line 246 skipping to change at line 264
bool should_check_files() const; bool should_check_files() const;
void delete_files(); void delete_files();
// ============ start deprecation ============= // ============ start deprecation =============
void filter_piece(int index, bool filter); void filter_piece(int index, bool filter);
void filter_pieces(std::vector<bool> const& bitmask); void filter_pieces(std::vector<bool> const& bitmask);
bool is_piece_filtered(int index) const; bool is_piece_filtered(int index) const;
void filtered_pieces(std::vector<bool>& bitmask) const; void filtered_pieces(std::vector<bool>& bitmask) const;
void filter_files(std::vector<bool> const& files); void filter_files(std::vector<bool> const& files);
#if !TORRENT_NO_FPU
void file_progress(std::vector<float>& fp) const; void file_progress(std::vector<float>& fp) const;
#endif
// ============ end deprecation ============= // ============ end deprecation =============
void piece_availability(std::vector<int>& avail) const; void piece_availability(std::vector<int>& avail) const;
void set_piece_priority(int index, int priority); void set_piece_priority(int index, int priority);
int piece_priority(int index) const; int piece_priority(int index) const;
void prioritize_pieces(std::vector<int> const& pieces); void prioritize_pieces(std::vector<int> const& pieces);
void piece_priorities(std::vector<int>&) const; void piece_priorities(std::vector<int>&) const;
void set_file_priority(int index, int priority); void set_file_priority(int index, int priority);
int file_priority(int index) const; int file_priority(int index) const;
void prioritize_files(std::vector<int> const& files); void prioritize_files(std::vector<int> const& files);
void file_priorities(std::vector<int>&) const; void file_priorities(std::vector<int>&) const;
void set_piece_deadline(int piece, int t, int flags);
void update_piece_priorities(); void update_piece_priorities();
torrent_status status() const; torrent_status status() const;
void file_progress(std::vector<size_type>& fp) const; void file_progress(std::vector<size_type>& fp, int flags = 0 ) const;
void use_interface(const char* net_interface); void use_interface(const char* net_interface);
tcp::endpoint const& get_interface() const { return m_net_in terface; } tcp::endpoint const& get_interface() const { return m_net_in terface; }
void connect_to_url_seed(std::string const& url); void connect_to_url_seed(web_seed_entry const& url);
bool connect_to_peer(policy::peer* peerinfo); bool connect_to_peer(policy::peer* peerinfo);
void set_ratio(float ratio) void set_ratio(float r)
{ TORRENT_ASSERT(ratio >= 0.0f); m_ratio = ratio; } { TORRENT_ASSERT(r >= 0.0f); m_ratio = r; }
float ratio() const float ratio() const
{ return m_ratio; } { return m_ratio; }
int priority() const { return m_priority; }
void set_priority(int prio)
{
TORRENT_ASSERT(prio <= 255 && prio >= 0);
if (prio > 255) prio = 255;
else if (prio < 0) prio = 0;
m_priority = prio;
}
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void resolve_countries(bool r) void resolve_countries(bool r)
{ m_resolve_countries = r; } { m_resolve_countries = r; }
bool resolving_countries() const { return m_resolve_countrie s; } bool resolving_countries() const { return m_resolve_countrie s; }
#endif #endif
// -------------------------------------------- // --------------------------------------------
// BANDWIDTH MANAGEMENT // BANDWIDTH MANAGEMENT
bandwidth_limit m_bandwidth_limit[2]; bandwidth_channel m_bandwidth_channel[2];
void request_bandwidth(int channel
, boost::intrusive_ptr<peer_connection> const& p
, int max_block_size, int priority);
void perform_bandwidth_request(int channel
, boost::intrusive_ptr<peer_connection> const& p
, int block_size, int priority);
void expire_bandwidth(int channel, int amount);
void assign_bandwidth(int channel, int amount, int blk);
int bandwidth_throttle(int channel) const; int bandwidth_throttle(int channel) const;
int max_assignable_bandwidth(int channel) const
{ return m_bandwidth_limit[channel].max_assignable(); }
int bandwidth_queue_size(int channel) const;
// -------------------------------------------- // --------------------------------------------
// PEER MANAGEMENT // PEER MANAGEMENT
// add or remove a url that will be attempted for // add or remove a url that will be attempted for
// finding the file(s) in this torrent. // finding the file(s) in this torrent.
void add_url_seed(std::string const& url) void add_web_seed(std::string const& url, web_seed_entry::ty
{ m_web_seeds.insert(url); } pe_t type)
{ m_web_seeds.insert(web_seed_entry(url, type)); }
void remove_url_seed(std::string const& url) void remove_web_seed(std::string const& url, web_seed_entry:
{ m_web_seeds.erase(url); } :type_t type)
{ m_web_seeds.erase(web_seed_entry(url, type)); }
void retry_url_seed(std::string const& url); void retry_web_seed(std::string const& url, web_seed_entry:: type_t type, int retry = 0);
std::set<std::string> url_seeds() const std::set<web_seed_entry> web_seeds() const
{ return m_web_seeds; } { return m_web_seeds; }
std::set<std::string> web_seeds(web_seed_entry::type_t type)
const;
bool free_upload_slots() const bool free_upload_slots() const
{ return m_num_uploads < m_max_uploads; } { return m_num_uploads < m_max_uploads; }
void choke_peer(peer_connection& c); bool choke_peer(peer_connection& c);
bool unchoke_peer(peer_connection& c); bool unchoke_peer(peer_connection& c);
// 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.
// false means attach failed // false means attach failed
bool attach_peer(peer_connection* p); bool attach_peer(peer_connection* 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
skipping to change at line 378 skipping to change at line 394
// -------------------------------------------- // --------------------------------------------
// TRACKER MANAGEMENT // TRACKER MANAGEMENT
// these are callbacks called by the tracker_connection inst ance // these are callbacks called by the tracker_connection inst ance
// (either http_tracker_connection or udp_tracker_connection ) // (either http_tracker_connection or udp_tracker_connection )
// when this torrent got a response from its tracker request // when this torrent got a response from its tracker request
// or when a failure occured // or when a failure occured
virtual void tracker_response( virtual void tracker_response(
tracker_request const& r tracker_request const& r
, std::vector<peer_entry>& e, int interval , address const& tracker_ip
, std::list<address> const& ip_list
, std::vector<peer_entry>& e, int interval, int min_
interval
, int complete, int incomplete, address const& exter nal_ip); , int complete, int incomplete, address const& exter nal_ip);
virtual void tracker_request_timed_out( virtual void tracker_request_timed_out(
tracker_request const& r); tracker_request const& r);
virtual void tracker_request_error(tracker_request const& r virtual void tracker_request_error(tracker_request const& r
, int response_code, const std::string& str); , int response_code, const std::string& str, int ret ry_interval);
virtual void tracker_warning(tracker_request const& req virtual void tracker_warning(tracker_request const& req
, std::string const& msg); , std::string const& msg);
virtual void tracker_scrape_response(tracker_request const& req virtual void tracker_scrape_response(tracker_request const& req
, int complete, int incomplete, int downloaded); , int complete, int incomplete, int downloaded);
// if no password and username is set // if no password and username is set
// this will return an empty string, otherwise // this will return an empty string, otherwise
// it will concatenate the login and password // it will concatenate the login and password
// ready to be sent over http (but without // ready to be sent over http (but without
// base64 encoding). // base64 encoding).
skipping to change at line 405 skipping to change at line 423
// returns the absolute time when the next tracker // returns the absolute time when the next tracker
// announce will take place. // announce will take place.
ptime next_announce() const; ptime next_announce() const;
// forcefully sets next_announce to the current time // forcefully sets next_announce to the current time
void force_tracker_request(); void force_tracker_request();
void force_tracker_request(ptime); void force_tracker_request(ptime);
void scrape_tracker(); void scrape_tracker();
void announce_with_tracker(tracker_request::event_t e void announce_with_tracker(tracker_request::event_t e
= tracker_request::none); = tracker_request::none
, address const& bind_interface = address_v4::any())
;
ptime const& last_scrape() const { return m_last_scrape; } ptime const& last_scrape() const { return m_last_scrape; }
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void force_dht_announce(); void force_dht_announce();
#endif #endif
// sets the username and password that will be sent to // sets the username and password that will be sent to
// the tracker // the tracker
void set_tracker_login(std::string const& name, std::string const& pw); void set_tracker_login(std::string const& name, std::string const& pw);
// the tcp::endpoint of the tracker that we managed to // the tcp::endpoint of the tracker that we managed to
// announce ourself at the last time we tried to announce // announce ourself at the last time we tried to announce
const tcp::endpoint& current_tracker() const; const tcp::endpoint& current_tracker() const;
announce_entry* find_tracker(tracker_request const& r);
// -------------------------------------------- // --------------------------------------------
// PIECE MANAGEMENT // PIECE MANAGEMENT
void update_sparse_piece_prio(int piece, int cursor, int rev
erse_cursor);
bool super_seeding() const
{ return m_super_seeding; }
void super_seeding(bool on);
int get_piece_to_super_seed(bitfield const&);
// returns true if we have downloaded the given piece // returns true if we have downloaded the given piece
bool have_piece(int index) const bool have_piece(int index) const
{ {
return has_picker()?m_picker->have_piece(index):true ; return has_picker()?m_picker->have_piece(index):true ;
} }
// called when we learn that we have a piece
// only once per piece
void we_have(int index);
int num_have() const int num_have() const
{ {
return has_picker() return has_picker()
?m_picker->num_have() ?m_picker->num_have()
:m_torrent_file->num_pieces(); :m_torrent_file->num_pieces();
} }
// when we get a have message, this is called for that piece // when we get a have message, this is called for that piece
void peer_has(int index) void peer_has(int index)
{ {
skipping to change at line 501 skipping to change at line 534
else else
{ {
TORRENT_ASSERT(is_seed()); TORRENT_ASSERT(is_seed());
} }
#endif #endif
} }
int block_size() const { TORRENT_ASSERT(m_block_size > 0); r eturn m_block_size; } int block_size() const { TORRENT_ASSERT(m_block_size > 0); r eturn m_block_size; }
peer_request to_req(piece_block const& p) const; peer_request to_req(piece_block const& p) const;
void disconnect_all(); void disconnect_all(error_code const& ec);
int disconnect_peers(int num); int disconnect_peers(int num);
// this is called wheh the torrent has completed // this is called wheh the torrent has completed
// the download. It will post an event, disconnect // the download. It will post an event, disconnect
// all seeds and let the tracker know we're finished. // all seeds and let the tracker know we're finished.
void completed(); void completed();
// this is the asio callback that is called when a name // this is the asio callback that is called when a name
// lookup for a PEER is completed. // lookup for a PEER is completed.
void on_peer_name_lookup(error_code const& e, tcp::resolver: :iterator i void on_peer_name_lookup(error_code const& e, tcp::resolver: :iterator i
, peer_id pid); , peer_id pid);
// this is the asio callback that is called when a name // this is the asio callback that is called when a name
// lookup for a WEB SEED is completed. // lookup for a WEB SEED is completed.
void on_name_lookup(error_code const& e, tcp::resolver::iter ator i void on_name_lookup(error_code const& e, tcp::resolver::iter ator i
, std::string url, tcp::endpoint proxy); , web_seed_entry url, tcp::endpoint proxy);
// this is the asio callback that is called when a name // this is the asio callback that is called when a name
// lookup for a proxy for a web seed is completed. // lookup for a proxy for a web seed is completed.
void on_proxy_name_lookup(error_code const& e, tcp::resolver ::iterator i void on_proxy_name_lookup(error_code const& e, tcp::resolver ::iterator i
, std::string url); , web_seed_entry url);
// this is called when the torrent has finished. i.e. // this is called when the torrent has finished. i.e.
// all the pieces we have not filtered have been downloaded. // all the pieces we have not filtered have been downloaded.
// If no pieces are filtered, this is called first and then // If no pieces are filtered, this is called first and then
// completed() is called immediately after it. // completed() is called immediately after it.
void finished(); void finished();
// This is the opposite of finished. It is called if we used // This is the opposite of finished. It is called if we used
// to be finished but enabled some files for download so tha t // to be finished but enabled some files for download so tha t
// we wasn't finished anymore. // we wasn't finished anymore.
skipping to change at line 597 skipping to change at line 630
} }
policy& get_policy() { return m_policy; } policy& get_policy() { return m_policy; }
piece_manager& filesystem(); piece_manager& filesystem();
torrent_info const& torrent_file() const torrent_info const& torrent_file() const
{ return *m_torrent_file; } { return *m_torrent_file; }
std::vector<announce_entry> const& trackers() const std::vector<announce_entry> const& trackers() const
{ return m_trackers; } { return m_trackers; }
void replace_trackers(std::vector<announce_entry> const& url s); void replace_trackers(std::vector<announce_entry> const& url s);
void add_tracker(announce_entry const& url);
torrent_handle get_handle(); torrent_handle get_handle();
void write_resume_data(entry& rd) const; void write_resume_data(entry& rd) const;
void read_resume_data(lazy_entry const& rd); void read_resume_data(lazy_entry const& rd);
// LOGGING // LOGGING
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING
virtual void debug_log(const std::string& line); virtual void debug_log(const std::string& line);
#endif #endif
// DEBUG // DEBUG
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
// -------------------------------------------- // --------------------------------------------
// RESOURCE MANAGEMENT // RESOURCE MANAGEMENT
void add_free_upload(int diff) { m_available_free_upload +=
diff; }
void set_peer_upload_limit(tcp::endpoint ip, int limit); void set_peer_upload_limit(tcp::endpoint ip, int limit);
void set_peer_download_limit(tcp::endpoint ip, int limit); void set_peer_download_limit(tcp::endpoint ip, int limit);
void set_upload_limit(int limit); void set_upload_limit(int limit);
int upload_limit() const; int upload_limit() const;
void set_download_limit(int limit); void set_download_limit(int limit);
int download_limit() const; int download_limit() const;
void set_max_uploads(int limit); void set_max_uploads(int limit);
int max_uploads() const { return m_max_uploads; } int max_uploads() const { return m_max_uploads; }
skipping to change at line 650 skipping to change at line 686
bool valid_metadata() const bool valid_metadata() const
{ return m_torrent_file->is_valid(); } { return m_torrent_file->is_valid(); }
bool are_files_checked() const bool are_files_checked() const
{ return m_files_checked; } { return m_files_checked; }
// parses the info section from the given // parses the info section from the given
// bencoded tree and moves the torrent // bencoded tree and moves the torrent
// to the checker thread for initial checking // to the checker thread for initial checking
// of the storage. // of the storage.
// a return value of false indicates an error // a return value of false indicates an error
bool set_metadata(lazy_entry const& metadata, std::string& e rror); bool set_metadata(char const* metadata_buf, int metadata_siz e);
int sequence_number() const { return m_sequence_number; } int sequence_number() const { return m_sequence_number; }
bool seed_mode() const { return m_seed_mode; }
void leave_seed_mode(bool seed)
{
if (!m_seed_mode) return;
m_seed_mode = false;
// seed is false if we turned out not
// to be a seed after all
if (!seed) force_recheck();
m_num_verified = 0;
m_verified.free();
}
bool all_verified() const
{ return m_num_verified == m_torrent_file->num_pieces(); }
bool verified_piece(int piece) const
{
TORRENT_ASSERT(piece < int(m_verified.size()));
TORRENT_ASSERT(piece >= 0);
return m_verified.get_bit(piece);
}
void verified(int piece)
{
TORRENT_ASSERT(piece < int(m_verified.size()));
TORRENT_ASSERT(piece >= 0);
TORRENT_ASSERT(m_verified.get_bit(piece) == false);
++m_num_verified;
m_verified.set_bit(piece);
}
bool add_merkle_nodes(std::map<int, sha1_hash> const& n, int
piece);
// this is called once periodically for torrents
// that are not private
void lsd_announce();
private: private:
void on_files_deleted(int ret, disk_io_job const& j); void on_files_deleted(int ret, disk_io_job const& j);
void on_files_released(int ret, disk_io_job const& j); void on_files_released(int ret, disk_io_job const& j);
void on_torrent_aborted(int ret, disk_io_job const& j); void on_torrent_aborted(int ret, disk_io_job const& j);
void on_torrent_paused(int ret, disk_io_job const& j); void on_torrent_paused(int ret, disk_io_job const& j);
void on_storage_moved(int ret, disk_io_job const& j); void on_storage_moved(int ret, disk_io_job const& j);
void on_save_resume_data(int ret, disk_io_job const& j); void on_save_resume_data(int ret, disk_io_job const& j);
void on_file_renamed(int ret, disk_io_job const& j); void on_file_renamed(int ret, disk_io_job const& j);
void on_cache_flushed(int ret, disk_io_job const& j);
void on_piece_verified(int ret, disk_io_job const& j void on_piece_verified(int ret, disk_io_job const& j
, boost::function<void(int)> f); , boost::function<void(int)> f);
void try_next_tracker(tracker_request const& req);
int prioritize_tracker(int tracker_index); int prioritize_tracker(int tracker_index);
int deprioritize_tracker(int tracker_index);
void on_country_lookup(error_code const& error, tcp::resolve r::iterator i void on_country_lookup(error_code const& error, tcp::resolve r::iterator i
, boost::intrusive_ptr<peer_connection> p) const; , boost::intrusive_ptr<peer_connection> p) const;
bool request_bandwidth_from_session(int channel) const; bool request_bandwidth_from_session(int channel) const;
void update_peer_interest(bool was_finished); void update_peer_interest(bool was_finished);
void prioritize_udp_trackers();
void queue_torrent_check(); void queue_torrent_check();
void dequeue_torrent_check(); void dequeue_torrent_check();
policy m_policy; policy m_policy;
// total time we've been available on this torrent // total time we've been available on this torrent
// does not count when the torrent is stopped or paused // does not count when the torrent is stopped or paused
time_duration m_active_time; time_duration m_active_time;
// total time we've been finished with this torrent
// does not count when the torrent is stopped or paused
time_duration m_finished_time;
// total time we've been available as a seed on this torrent // total time we've been available as a seed on this torrent
// does not count when the torrent is stopped or paused // does not count when the torrent is stopped or paused
time_duration m_seeding_time; time_duration m_seeding_time;
// all time totals of uploaded and downloaded payload // all time totals of uploaded and downloaded payload
// stored in resume data // stored in resume data
size_type m_total_uploaded; size_type m_total_uploaded;
size_type m_total_downloaded; size_type m_total_downloaded;
// if this torrent is running, this was the time // if this torrent is running, this was the time
// when it was started. This is used to have a // when it was started. This is used to have a
// bias towards keeping seeding torrents that // bias towards keeping seeding torrents that
// recently was started, to avoid oscillation // recently was started, to avoid oscillation
ptime m_started; ptime m_started;
// the last time we initiated a scrape request to // the last time we initiated a scrape request to
// one of the trackers in this torrent // one of the trackers in this torrent
ptime m_last_scrape; ptime m_last_scrape;
// the time when we switched to upload mode
ptime m_upload_mode_time;
boost::intrusive_ptr<torrent_info> m_torrent_file; boost::intrusive_ptr<torrent_info> m_torrent_file;
void parse_response(const entry& e, std::vector<peer_entry>& peer_list); void parse_response(const entry& e, std::vector<peer_entry>& peer_list);
// if this pointer is 0, the torrent is in // if this pointer is 0, the torrent is in
// a state where the metadata hasn't been // a state where the metadata hasn't been
// received yet. // received yet.
// the piece_manager keeps the torrent object // the piece_manager keeps the torrent object
// alive by holding a shared_ptr to it and // alive by holding a shared_ptr to it and
// the torrent keeps the piece manager alive // the torrent keeps the piece manager alive
skipping to change at line 732 skipping to change at line 812
// torrent, so the torrent cannot destruct // torrent, so the torrent cannot destruct
// before the piece_manager. // before the piece_manager.
boost::intrusive_ptr<piece_manager> m_owning_storage; boost::intrusive_ptr<piece_manager> m_owning_storage;
// this is a weak (non owninig) pointer to // this is a weak (non owninig) pointer to
// the piece_manager. This is used after the torrent // the piece_manager. This is used after the torrent
// has been aborted, and it can no longer own // has been aborted, and it can no longer own
// the object. // the object.
piece_manager* m_storage; piece_manager* m_storage;
// the time of next tracker announce
ptime m_next_tracker_announce;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
public: public:
#endif #endif
std::set<peer_connection*> m_connections; std::set<peer_connection*> m_connections;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
private: private:
#endif #endif
// The list of web seeds in this torrent. Seeds // The list of web seeds in this torrent. Seeds
// with fatal errors are removed from the set // with fatal errors are removed from the set
std::set<std::string> m_web_seeds; std::set<web_seed_entry> m_web_seeds;
// a list of web seeds that have failed and are // a list of web seeds that have failed and are
// waiting to be retried // waiting to be retried
std::map<std::string, ptime> m_web_seeds_next_retry; std::map<web_seed_entry, ptime> m_web_seeds_next_retry;
// urls of the web seeds that we are currently // urls of the web seeds that we are currently
// resolving the address for // resolving the address for
std::set<std::string> m_resolving_web_seeds; std::set<web_seed_entry> m_resolving_web_seeds;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<torrent_plugin> > extens ion_list_t; typedef std::list<boost::shared_ptr<torrent_plugin> > extens ion_list_t;
extension_list_t m_extensions; extension_list_t m_extensions;
#endif #endif
// used to resolve the names of web seeds // used to resolve the names of web seeds
mutable tcp::resolver m_host_resolver; mutable tcp::resolver m_host_resolver;
#ifndef TORRENT_DISABLE_DHT
// this announce timer is used both // this announce timer is used both
// by Local service discovery and // by Local service discovery and
// by the DHT. // by the DHT.
deadline_timer m_lsd_announce_timer; deadline_timer m_dht_announce_timer;
#endif
// used for tracker announces // used for tracker announces
deadline_timer m_tracker_timer; deadline_timer m_tracker_timer;
void restart_tracker_timer(ptime announce_at); void update_tracker_timer();
static void on_tracker_announce_disp(boost::weak_ptr<torrent > p static void on_tracker_announce_disp(boost::weak_ptr<torrent > p
, error_code const& e); , error_code const& e);
void on_tracker_announce(); void on_tracker_announce();
static void on_lsd_announce_disp(boost::weak_ptr<torrent> p void dht_announce();
, error_code const& e);
// this is called once every 5 minutes for torrents
// that are not private
void on_lsd_announce();
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
static void on_dht_announce_post(boost::weak_ptr<libtorrent:
:torrent> t
, std::vector<tcp::endpoint> const& peers);
static void on_dht_announce_response_disp(boost::weak_ptr<to rrent> t static void on_dht_announce_response_disp(boost::weak_ptr<to rrent> t
, std::vector<tcp::endpoint> const& peers); , std::vector<tcp::endpoint> const& peers);
void on_dht_announce_response(std::vector<tcp::endpoint> con st& peers); void on_dht_announce_response(std::vector<tcp::endpoint> con st& peers);
bool should_announce_dht() const; bool should_announce_dht() const;
void on_dht_announce(error_code const& e);
// the time when the DHT was last announced of our // the time when the DHT was last announced of our
// presence on this torrent // presence on this torrent
ptime m_last_dht_announce; ptime m_last_dht_announce;
#endif #endif
// this is the upload and download statistics for the whole torrent. // this is the upload and download statistics for the whole torrent.
// it's updated from all its peers once every second. // it's updated from all its peers once every second.
libtorrent::stat m_stat; libtorrent::stat m_stat;
// ----------------------------- // -----------------------------
// a back reference to the session // a back reference to the session
// this torrent belongs to. // this torrent belongs to.
aux::session_impl& m_ses; aux::session_impl& m_ses;
std::vector<boost::uint8_t> m_file_priority; std::vector<boost::uint8_t> m_file_priority;
boost::scoped_ptr<piece_picker> m_picker; // this vector contains the number of bytes completely
// downloaded (as in passed-hash-check) in each file.
// this lets us trigger on individual files completing
std::vector<size_type> m_file_progress;
// the queue of peer_connections that want more bandwidth boost::scoped_ptr<piece_picker> m_picker;
typedef std::deque<bw_queue_entry<peer_connection, torrent>
> queue_t;
queue_t m_bandwidth_queue[2];
std::vector<announce_entry> m_trackers; std::vector<announce_entry> m_trackers;
// this is an index into m_trackers // this is an index into m_trackers
struct time_critical_piece
{
// when this piece was first requested
ptime first_requested;
// when this piece was last requested
ptime last_requested;
// by what time we want this piece
ptime deadline;
// 1 = send alert with piece data when available
int flags;
// how many peers it's been requested from
int peers;
// the piece index
int piece;
bool operator<(time_critical_piece const& rhs) const
{ return deadline < rhs.deadline; }
};
void remove_time_critical_piece(int piece, bool finished = f
alse);
void remove_time_critical_pieces(std::vector<int> const& pri
ority);
void request_time_critical_pieces();
// this list is sorted by time_critical_piece::deadline
std::list<time_critical_piece> m_time_critical_pieces;
// the average time it takes to download one time critical p
iece
time_duration m_average_piece_time;
// the average piece download time deviation
time_duration m_piece_time_deviation;
// the number of bytes that has been // the number of bytes that has been
// downloaded that failed the hash-test // downloaded that failed the hash-test
size_type m_total_failed_bytes; size_type m_total_failed_bytes;
size_type m_total_redundant_bytes; size_type m_total_redundant_bytes;
// the number of bytes of padding files
int m_padding;
std::string m_username; std::string m_username;
std::string m_password; std::string m_password;
// the network interface all outgoing connections // the network interface all outgoing connections
// are opened through // are opened through
tcp::endpoint m_net_interface; tcp::endpoint m_net_interface;
fs::path m_save_path; fs::path m_save_path;
// each bit represents a piece. a set bit means
// the piece has had its hash verified. This
// is only used in seed mode (when m_seed_mode
// is true)
bitfield m_verified;
// m_num_verified = m_verified.count()
int m_num_verified;
// free download we have got that hasn't
// been distributed yet.
size_type m_available_free_upload;
// determines the storage state for this torrent. // determines the storage state for this torrent.
storage_mode_t m_storage_mode; storage_mode_t m_storage_mode;
// the state of this torrent (queued, checking, downloading) // the state of this torrent (queued, checking, downloading, etc.)
torrent_status::state_t m_state; torrent_status::state_t m_state;
// if there's an error on this torrent, this is the // set if there's an error on this torrent
// error message error_code m_error;
std::string m_error; // if the error ocurred on a file, this is the file
std::string m_error_file;
// used if there is any resume data // used if there is any resume data
std::vector<char> m_resume_data; std::vector<char> m_resume_data;
lazy_entry m_resume_entry; lazy_entry m_resume_entry;
// if the torrent is started without metadata, it may // if the torrent is started without metadata, it may
// still be given a name until the metadata is received // still be given a name until the metadata is received
// once the metadata is received this field will no // once the metadata is received this field will no
// longer be used and will be reset // longer be used and will be reset
boost::scoped_ptr<std::string> m_name; boost::scoped_ptr<std::string> m_name;
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
// this is SHA1("req2" + info-hash), used for // this is SHA1("req2" + info-hash), used for
// encrypted hand shakes // encrypted hand shakes
sha1_hash m_obfuscated_hash; sha1_hash m_obfuscated_hash;
#endif #endif
session_settings const& m_settings; session_settings const& m_settings;
storage_constructor_type m_storage_constructor; storage_constructor_type m_storage_constructor;
float m_progress; int m_progress_ppm;
// the upload/download ratio that each peer // the upload/download ratio that each peer
// tries to maintain. // tries to maintain.
// 0 is infinite // 0 is infinite
float m_ratio; float m_ratio;
// the maximum number of uploads for this torrent // the maximum number of uploads for this torrent
int m_max_uploads; int m_max_uploads;
// the number of unchoked peers in this torrent // the number of unchoked peers in this torrent
skipping to change at line 911 skipping to change at line 1031
// The quanta assigned to each torrent depends on the torren ts // The quanta assigned to each torrent depends on the torren ts
// priority, whether it's seed and the number of connected // priority, whether it's seed and the number of connected
// peers it has. This has the effect that some torrents // peers it has. This has the effect that some torrents
// will have more connection attempts than other. Each // will have more connection attempts than other. Each
// connection attempt costs 100 points from the deficit // connection attempt costs 100 points from the deficit
// counter. points are deducted in try_connect_peer and // counter. points are deducted in try_connect_peer and
// increased in give_connect_points. Outside of the // increased in give_connect_points. Outside of the
// torrent object, these points are called connect_points. // torrent object, these points are called connect_points.
int m_deficit_counter; int m_deficit_counter;
// the number number of seconds between requests
// from the tracker
boost::int16_t m_duration;
// the sequence number for this torrent, this is a // the sequence number for this torrent, this is a
// monotonically increasing number for each added torrent // monotonically increasing number for each added torrent
boost::int16_t m_sequence_number; boost::int16_t m_sequence_number;
// the index to the last tracker that worked // the index to the last tracker that worked
boost::int8_t m_last_working_tracker; boost::int8_t m_last_working_tracker;
// the tracker that is currently (or was last)
// tried
boost::int8_t m_currently_trying_tracker;
// the number of connection attempts that has // the number of connection attempts that has
// failed in a row, this is currently used to // failed in a row, this is currently used to
// determine the timeout until next try. // determine the timeout until next try.
boost::int8_t m_failed_trackers; boost::int8_t m_failed_trackers;
// this is a counter that is decreased every // this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse() // second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10. // is called and the time scaler is reset to 10.
boost::int8_t m_time_scaler; boost::int8_t m_time_scaler;
// this is the priority of the torrent. The higher
// the value is, the more bandwidth is assigned to
// the torrent's peers
boost::uint8_t m_priority;
// is set to true when the torrent has // is set to true when the torrent has
// been aborted. // been aborted.
bool m_abort:1; bool m_abort:1;
// is true if this torrent has been paused // is true if this torrent has been paused
bool m_paused:1; bool m_paused:1;
// set to true when this torrent may not download anything
bool m_upload_mode:1;
// if this is true, libtorrent may pause and resume // if this is true, libtorrent may pause and resume
// this torrent depending on queuing rules. Torrents // this torrent depending on queuing rules. Torrents
// started with auto_managed flag set may be added in // started with auto_managed flag set may be added in
// a paused state in case there are no available // a paused state in case there are no available
// slots. // slots.
bool m_auto_managed:1; bool m_auto_managed:1;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// this is true while there is a country // this is true while there is a country
// resolution in progress. To avoid flodding // resolution in progress. To avoid flodding
skipping to change at line 983 skipping to change at line 1103
// of this torrent hasn't been initialized. If we // of this torrent hasn't been initialized. If we
// have metadata from the start, connections are // have metadata from the start, connections are
// initialized immediately, if we didn't have metadata, // initialized immediately, if we didn't have metadata,
// they are initialized right after files_checked(). // they are initialized right after files_checked().
// valid_resume_data() will return false as long as // valid_resume_data() will return false as long as
// the connections aren't initialized, to avoid // the connections aren't initialized, to avoid
// them from altering the piece-picker before it // them from altering the piece-picker before it
// has been initialized with files_checked(). // has been initialized with files_checked().
bool m_connections_initialized:1; bool m_connections_initialized:1;
// if this is true, we're currently super seeding this
// torrent.
bool m_super_seeding:1;
// is set to true every time there is an incoming // is set to true every time there is an incoming
// connection to this torrent // connection to this torrent
bool m_has_incoming:1; bool m_has_incoming:1;
// this is set to true when the files are checked // this is set to true when the files are checked
// before the files are checked, we don't try to // before the files are checked, we don't try to
// connect to peers // connect to peers
bool m_files_checked:1; bool m_files_checked:1;
// this is true if the torrent has been added to // this is true if the torrent has been added to
// checking queue in the session // checking queue in the session
bool m_queued_for_checking:1; bool m_queued_for_checking:1;
// this is true while tracker announcing is enabled // this is true while tracker announcing is enabled
// is is disabled while paused and checking files // is is disabled while paused and checking files
bool m_announcing:1; bool m_announcing:1;
// this is true if event start has been sent to the tracker // this is true while the tracker deadline timer
bool m_start_sent:1; // is in use. i.e. one or more trackers are waiting
// for a reannounce
// this is true if event completed has been sent to the trac bool m_waiting_tracker:1;
ker
bool m_complete_sent:1;
};
inline ptime torrent::next_announce() const
{
return m_next_tracker_announce;
}
inline void torrent::force_tracker_request()
{
if (!is_paused()) announce_with_tracker();
}
inline void torrent::force_tracker_request(ptime t)
{
if (!is_paused()) restart_tracker_timer(t);
}
inline void torrent::set_tracker_login( // this means we haven't verified the file content
std::string const& name // of the files we're seeding. the m_verified bitfield
, std::string const& pw) // indicates which pieces have been verified and which
{ // haven't
m_username = name; bool m_seed_mode:1;
m_password = pw;
}
// this is set when we don't want to load seed_mode,
// paused or auto_managed from the resume data
bool m_override_resume_data:1;
};
} }
#endif // TORRENT_TORRENT_HPP_INCLUDED #endif // TORRENT_TORRENT_HPP_INCLUDED
 End of changes. 74 change blocks. 
144 lines changed or deleted 267 lines changed or added


 torrent_handle.hpp   torrent_handle.hpp 
skipping to change at line 69 skipping to change at line 69
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
namespace aux namespace aux
{ {
struct session_impl; struct session_impl;
struct checker_impl; struct checker_impl;
} }
struct torrent_plugin; struct torrent_plugin;
struct TORRENT_EXPORT duplicate_torrent: std::exception #ifndef BOOST_NO_EXCEPTIONS
{ // for compatibility with 0.14
virtual const char* what() const throw() typedef libtorrent_exception duplicate_torrent;
{ return "torrent already exists in session"; } typedef libtorrent_exception invalid_handle;
}; void throw_invalid_handle();
#endif
struct TORRENT_EXPORT invalid_handle: std::exception
{
virtual const char* what() const throw()
{ return "invalid torrent handle used"; }
};
struct TORRENT_EXPORT torrent_status struct TORRENT_EXPORT torrent_status
{ {
torrent_status() torrent_status()
: state(checking_resume_data) : state(checking_resume_data)
, paused(false) , paused(false)
, progress(0.f) , progress(0.f)
, progress_ppm(0)
, total_download(0) , total_download(0)
, total_upload(0) , total_upload(0)
, total_payload_download(0) , total_payload_download(0)
, total_payload_upload(0) , total_payload_upload(0)
, total_failed_bytes(0) , total_failed_bytes(0)
, total_redundant_bytes(0) , total_redundant_bytes(0)
, download_rate(0) , download_rate(0)
, upload_rate(0) , upload_rate(0)
, download_payload_rate(0) , download_payload_rate(0)
, upload_payload_rate(0) , upload_payload_rate(0)
skipping to change at line 119 skipping to change at line 115
, num_uploads(0) , num_uploads(0)
, num_connections(0) , num_connections(0)
, uploads_limit(0) , uploads_limit(0)
, connections_limit(0) , connections_limit(0)
, storage_mode(storage_mode_sparse) , storage_mode(storage_mode_sparse)
, up_bandwidth_queue(0) , up_bandwidth_queue(0)
, down_bandwidth_queue(0) , down_bandwidth_queue(0)
, all_time_upload(0) , all_time_upload(0)
, all_time_download(0) , all_time_download(0)
, active_time(0) , active_time(0)
, finished_time(0)
, seeding_time(0) , seeding_time(0)
, seed_rank(0) , seed_rank(0)
, last_scrape(0) , last_scrape(0)
, has_incoming(false) , has_incoming(false)
, sparse_regions(0)
, seed_mode(false)
, upload_mode(false)
, priority(0)
{} {}
enum state_t enum state_t
{ {
queued_for_checking, queued_for_checking,
checking_files, checking_files,
downloading_metadata, downloading_metadata,
downloading, downloading,
finished, finished,
seeding, seeding,
allocating, allocating,
checking_resume_data checking_resume_data
}; };
state_t state; state_t state;
bool paused; bool paused;
float progress; float progress;
// progress parts per million (progress * 1000000)
// when disabling floating point operations, this is
// the only option to query progress
int progress_ppm;
std::string error; std::string error;
boost::posix_time::time_duration next_announce; boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval; boost::posix_time::time_duration announce_interval;
std::string current_tracker; std::string current_tracker;
// transferred this session! // transferred this session!
// total, payload plus protocol // total, payload plus protocol
size_type total_download; size_type total_download;
skipping to change at line 166 skipping to change at line 171
// the amount of payload bytes that // the amount of payload bytes that
// has failed their hash test // has failed their hash test
size_type total_failed_bytes; size_type total_failed_bytes;
// the number of payload bytes that // the number of payload bytes that
// has been received redundantly. // has been received redundantly.
size_type total_redundant_bytes; size_type total_redundant_bytes;
// current transfer rate // current transfer rate
// payload plus protocol // payload plus protocol
float download_rate; int download_rate;
float upload_rate; int upload_rate;
// the rate of payload that is // the rate of payload that is
// sent and received // sent and received
float download_payload_rate; int download_payload_rate;
float upload_payload_rate; int upload_payload_rate;
// the number of peers this torrent is connected to // the number of peers this torrent is connected to
// that are seeding. // that are seeding.
int num_seeds; int num_seeds;
// the number of peers this torrent // the number of peers this torrent
// is connected to (including seeds). // is connected to (including seeds).
int num_peers; int num_peers;
// if the tracker sends scrape info in its // if the tracker sends scrape info in its
skipping to change at line 233 skipping to change at line 238
size_type total_wanted; size_type total_wanted;
// the number of distributed copies of the file. // the number of distributed copies of the file.
// note that one copy may be spread out among many peers. // note that one copy may be spread out among many peers.
// //
// the integer part tells how many copies // the integer part tells how many copies
// there are of the rarest piece(s) // there are of the rarest piece(s)
// //
// the fractional part tells the fraction of pieces that // the fractional part tells the fraction of pieces that
// have more copies than the rarest piece(s). // have more copies than the rarest piece(s).
// the number of full distributed copies (i.e. the number
// of peers that have the rarest piece)
int distributed_full_copies;
// the fraction of pieces that more peers has than the
// rarest pieces. This indicates how close the swarm is
// to have one more full distributed copy
int distributed_fraction;
float distributed_copies; float distributed_copies;
// the block size that is used in this torrent. i.e. // the block size that is used in this torrent. i.e.
// the number of bytes each piece request asks for // the number of bytes each piece request asks for
// and each bit in the download queue bitfield represents // and each bit in the download queue bitfield represents
int block_size; int block_size;
int num_uploads; int num_uploads;
int num_connections; int num_connections;
int uploads_limit; int uploads_limit;
skipping to change at line 261 skipping to change at line 276
// number of bytes downloaded since torrent was started // number of bytes downloaded since torrent was started
// saved and restored from resume data // saved and restored from resume data
size_type all_time_upload; size_type all_time_upload;
size_type all_time_download; size_type all_time_download;
// the number of seconds of being active // the number of seconds of being active
// and as being a seed, saved and restored // and as being a seed, saved and restored
// from resume data // from resume data
int active_time; int active_time;
int finished_time;
int seeding_time; int seeding_time;
// higher value means more important to seed // higher value means more important to seed
int seed_rank; int seed_rank;
// number of seconds since last scrape, or -1 if // number of seconds since last scrape, or -1 if
// there hasn't been a scrape // there hasn't been a scrape
int last_scrape; int last_scrape;
// true if there are incoming connections to this // true if there are incoming connections to this
// torrent // torrent
bool has_incoming; bool has_incoming;
// the number of "holes" in the torrent
int sparse_regions;
// is true if this torrent is (still) in seed_mode
bool seed_mode;
// this is set to true when the torrent is blocked
// from downloading, typically caused by a file
// write operation failing
bool upload_mode;
// the priority of this torrent
int priority;
}; };
struct TORRENT_EXPORT block_info struct TORRENT_EXPORT block_info
{ {
enum block_state_t enum block_state_t
{ none, requested, writing, finished }; { none, requested, writing, finished };
tcp::endpoint peer; private:
#ifdef __SUNPRO_CC
// sunpro is strict about POD types in unions
struct
#else
union
#endif
{
address_v4::bytes_type v4;
address_v6::bytes_type v6;
} addr;
boost::uint16_t port;
public:
void set_peer(tcp::endpoint const& ep)
{
is_v6_addr = ep.address().is_v6();
if (is_v6_addr)
addr.v6 = ep.address().to_v6().to_bytes();
else
addr.v4 = ep.address().to_v4().to_bytes();
port = ep.port();
}
tcp::endpoint peer() const
{
if (is_v6_addr)
return tcp::endpoint(address_v6(addr.v6), po
rt);
else
return tcp::endpoint(address_v4(addr.v4), po
rt);
}
// number of bytes downloaded in this block // number of bytes downloaded in this block
unsigned bytes_progress:16; unsigned bytes_progress:15;
// the total number of bytes in this block // the total number of bytes in this block
unsigned block_size:16; unsigned block_size:15;
private:
// the type of the addr union
unsigned is_v6_addr:1;
unsigned unused:1;
public:
// the state this block is in (see block_state_t) // the state this block is in (see block_state_t)
unsigned state:2; unsigned state:2;
// the number of peers that has requested this block // the number of peers that has requested this block
// typically 0 or 1. If > 1, this block is in // typically 0 or 1. If > 1, this block is in
// end game mode // end game mode
unsigned num_peers:14; unsigned num_peers:14;
}; };
struct TORRENT_EXPORT partial_piece_info struct TORRENT_EXPORT partial_piece_info
{ {
enum { max_blocks_per_piece = 512 };
int piece_index; int piece_index;
int blocks_in_piece; int blocks_in_piece;
// the number of blocks in the finished state // the number of blocks in the finished state
int finished; int finished;
// the number of blocks in the writing state // the number of blocks in the writing state
int writing; int writing;
// the number of blocks in the requested state // the number of blocks in the requested state
int requested; int requested;
block_info blocks[max_blocks_per_piece]; block_info* blocks;
enum state_t { none, slow, medium, fast }; enum state_t { none, slow, medium, fast };
state_t piece_state; state_t piece_state;
}; };
struct TORRENT_EXPORT torrent_handle struct TORRENT_EXPORT torrent_handle
{ {
friend class invariant_access; friend class invariant_access;
friend struct aux::session_impl; friend struct aux::session_impl;
friend class torrent; friend class torrent;
torrent_handle() {} torrent_handle() {}
enum flags_t { overwrite_existing = 1 };
void add_piece(int piece, char const* data, int flags = 0) c
onst;
void read_piece(int piece) const;
void get_full_peer_list(std::vector<peer_list_entry>& v) con st; void get_full_peer_list(std::vector<peer_list_entry>& v) con st;
void get_peer_info(std::vector<peer_info>& v) const; void get_peer_info(std::vector<peer_info>& v) const;
torrent_status status() const; torrent_status status() const;
void get_download_queue(std::vector<partial_piece_info>& que ue) const; void get_download_queue(std::vector<partial_piece_info>& que ue) const;
enum deadline_flags { alert_when_available = 1 };
void set_piece_deadline(int index, int deadline, int flags =
0) const;
void set_priority(int prio) const;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
#if !TORRENT_NO_FPU
// fills the specified vector with the download progress [0, 1] // fills the specified vector with the download progress [0, 1]
// of each file in the torrent. The files are ordered as in // of each file in the torrent. The files are ordered as in
// the torrent_info. // the torrent_info.
TORRENT_DEPRECATED_PREFIX
void file_progress(std::vector<float>& progress) const TORRE NT_DEPRECATED; void file_progress(std::vector<float>& progress) const TORRE NT_DEPRECATED;
#endif #endif
void file_progress(std::vector<size_type>& progress) const; #endif
enum file_progress_flags_t
{
piece_granularity = 1
};
void file_progress(std::vector<size_type>& progress, int fla
gs = 0) const;
void clear_error() const; void clear_error() const;
std::vector<announce_entry> const& trackers() const; std::vector<announce_entry> trackers() const;
void replace_trackers(std::vector<announce_entry> const&) co nst; void replace_trackers(std::vector<announce_entry> const&) co nst;
void add_tracker(announce_entry const&) const;
void add_url_seed(std::string const& url) const; void add_url_seed(std::string const& url) const;
void remove_url_seed(std::string const& url) const; void remove_url_seed(std::string const& url) const;
std::set<std::string> url_seeds() const; std::set<std::string> url_seeds() const;
void add_http_seed(std::string const& url) const;
void remove_http_seed(std::string const& url) const;
std::set<std::string> http_seeds() const;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr<torrent _plugin>(torrent*, void*)> const& ext void add_extension(boost::function<boost::shared_ptr<torrent _plugin>(torrent*, void*)> const& ext
, void* userdata = 0); , void* userdata = 0);
#endif #endif
bool has_metadata() const; bool has_metadata() const;
bool set_metadata(char const* metadata, int size) const;
const torrent_info& get_torrent_info() const; const torrent_info& get_torrent_info() const;
bool is_valid() const; bool is_valid() const;
bool is_seed() const; bool is_seed() const;
bool is_finished() const; bool is_finished() const;
bool is_paused() const; bool is_paused() const;
void pause() const; void pause() const;
void resume() const; void resume() const;
void set_upload_mode(bool b) const;
void flush_cache() const;
void force_recheck() const; void force_recheck() const;
void save_resume_data() const; void save_resume_data() const;
bool is_auto_managed() const; bool is_auto_managed() const;
void auto_managed(bool m) const; void auto_managed(bool m) const;
int queue_position() const; int queue_position() const;
void queue_position_up() const; void queue_position_up() const;
void queue_position_down() const; void queue_position_down() const;
void queue_position_top() const; void queue_position_top() const;
skipping to change at line 381 skipping to change at line 473
// all these are deprecated, use piece // all these are deprecated, use piece
// priority functions instead // priority functions instead
// ================ start deprecation ============ // ================ start deprecation ============
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.13 // deprecated in 0.13
// marks the piece with the given index as filtered // marks the piece with the given index as filtered
// it will not be downloaded // it will not be downloaded
TORRENT_DEPRECATED_PREFIX
void filter_piece(int index, bool filter) const TORRENT_DEPR ECATED; void filter_piece(int index, bool filter) const TORRENT_DEPR ECATED;
TORRENT_DEPRECATED_PREFIX
void filter_pieces(std::vector<bool> const& pieces) const TO RRENT_DEPRECATED; void filter_pieces(std::vector<bool> const& pieces) const TO RRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool is_piece_filtered(int index) const TORRENT_DEPRECATED; bool is_piece_filtered(int index) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
std::vector<bool> filtered_pieces() const TORRENT_DEPRECATED ; std::vector<bool> filtered_pieces() const TORRENT_DEPRECATED ;
// marks the file with the given index as filtered // marks the file with the given index as filtered
// it will not be downloaded // it will not be downloaded
TORRENT_DEPRECATED_PREFIX
void filter_files(std::vector<bool> const& files) const TORR ENT_DEPRECATED; void filter_files(std::vector<bool> const& files) const TORR ENT_DEPRECATED;
// ================ end deprecation ============ // ================ end deprecation ============
#endif #endif
void piece_availability(std::vector<int>& avail) const; void piece_availability(std::vector<int>& avail) const;
// priority must be within the range [0, 7] // priority must be within the range [0, 7]
void piece_priority(int index, int priority) const; void piece_priority(int index, int priority) const;
int piece_priority(int index) const; int piece_priority(int index) const;
skipping to change at line 416 skipping to change at line 513
std::vector<int> file_priorities() const; std::vector<int> file_priorities() const;
// set the interface to bind outgoing connections // set the interface to bind outgoing connections
// to. // to.
void use_interface(const char* net_interface) const; void use_interface(const char* net_interface) const;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.14 // deprecated in 0.14
// use save_resume_data() instead. It is async. and // use save_resume_data() instead. It is async. and
// will return the resume data in an alert // will return the resume data in an alert
TORRENT_DEPRECATED_PREFIX
entry write_resume_data() const TORRENT_DEPRECATED; entry write_resume_data() const TORRENT_DEPRECATED;
#endif #endif
// forces this torrent to reannounce // forces this torrent to reannounce
// (make a rerequest from the tracker) // (make a rerequest from the tracker)
void force_reannounce() const; void force_reannounce() const;
#ifndef TORRENT_DISABLE_DHT
// announces this torrent to the DHT immediately
void force_dht_announce() const;
#endif
// forces a reannounce in the specified amount of time. // forces a reannounce in the specified amount of time.
// This overrides the default announce interval, and no // This overrides the default announce interval, and no
// announce will take place until the given time has // announce will take place until the given time has
// timed out. // timed out.
void force_reannounce(boost::posix_time::time_duration) cons t; void force_reannounce(boost::posix_time::time_duration) cons t;
// performs a scrape request // performs a scrape request
void scrape_tracker() const; void scrape_tracker() const;
skipping to change at line 463 skipping to change at line 565
void connect_peer(tcp::endpoint const& adr, int source = 0) const; void connect_peer(tcp::endpoint const& adr, int source = 0) const;
// valid ratios are 0 (infinite ratio) or [ 1.0 , inf ) // valid ratios are 0 (infinite ratio) or [ 1.0 , inf )
// the ratio is uploaded / downloaded. less than 1 is not al lowed // the ratio is uploaded / downloaded. less than 1 is not al lowed
void set_ratio(float up_down_ratio) const; void set_ratio(float up_down_ratio) const;
fs::path save_path() const; fs::path save_path() const;
// -1 means unlimited unchokes // -1 means unlimited unchokes
void set_max_uploads(int max_uploads) const; void set_max_uploads(int max_uploads) const;
int max_uploads() const;
// -1 means unlimited connections // -1 means unlimited connections
void set_max_connections(int max_connections) const; void set_max_connections(int max_connections) const;
int max_connections() const;
void set_tracker_login(std::string const& name void set_tracker_login(std::string const& name
, std::string const& password) const; , std::string const& password) const;
// post condition: save_path() == save_path if true is retur ned // post condition: save_path() == save_path if true is retur ned
void move_storage(fs::path const& save_path) const; void move_storage(fs::path const& save_path) const;
void rename_file(int index, fs::path const& new_name) const; void rename_file(int index, fs::path const& new_name) const;
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
void move_storage(fs::wpath const& save_path) const;
void rename_file(int index, fs::wpath const& new_name) const
;
#endif
bool super_seeding() const;
void super_seeding(bool on) const;
sha1_hash info_hash() const; sha1_hash info_hash() const;
bool operator==(const torrent_handle& h) const bool operator==(const torrent_handle& h) const
{ return m_torrent.lock() == h.m_torrent.lock(); } { return m_torrent.lock() == h.m_torrent.lock(); }
bool operator!=(const torrent_handle& h) const bool operator!=(const torrent_handle& h) const
{ return m_torrent.lock() != h.m_torrent.lock(); } { return m_torrent.lock() != h.m_torrent.lock(); }
bool operator<(const torrent_handle& h) const bool operator<(const torrent_handle& h) const
{ return m_torrent.lock() < h.m_torrent.lock(); } { return m_torrent.lock() < h.m_torrent.lock(); }
 End of changes. 35 change blocks. 
22 lines changed or deleted 140 lines changed or added


 torrent_info.hpp   torrent_info.hpp 
skipping to change at line 38 skipping to change at line 38
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED #ifndef TORRENT_TORRENT_INFO_HPP_INCLUDED
#define TORRENT_TORRENT_INFO_HPP_INCLUDED #define TORRENT_TORRENT_INFO_HPP_INCLUDED
#include <string> #include <string>
#include <vector> #include <vector>
#include <iosfwd> //#include <iosfwd>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/optional.hpp> #include <boost/optional.hpp>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
#include <boost/shared_array.hpp> #include <boost/shared_array.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
skipping to change at line 69 skipping to change at line 69
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/file_storage.hpp" #include "libtorrent/file_storage.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace pt = boost::posix_time; namespace pt = boost::posix_time;
namespace gr = boost::gregorian; namespace gr = boost::gregorian;
namespace fs = boost::filesystem; namespace fs = boost::filesystem;
enum
{
// wait 60 seconds before retrying a failed tracker
tracker_retry_delay_min = 10
// when tracker_failed_max trackers
// has failed, wait 60 minutes instead
, tracker_retry_delay_max = 60 * 60
};
struct TORRENT_EXPORT announce_entry struct TORRENT_EXPORT announce_entry
{ {
announce_entry(std::string const& u): url(u), tier(0) {} announce_entry(std::string const& u)
: url(u)
, tier(0)
, fail_limit(3)
, fails(0)
, source(0)
, verified(false)
, updating(false)
, start_sent(false)
, complete_sent(false)
, send_stats(true)
{}
std::string url; std::string url;
int tier;
int next_announce_in() const;
int min_announce_in() const;
// the time of next tracker announce
ptime next_announce;
// no announces before this time
ptime min_announce;
boost::uint8_t tier;
// the number of times this tracker can fail
// in a row before it's removed. 0 means unlimited
boost::uint8_t fail_limit;
// the number of times in a row this tracker has failed
boost::uint8_t fails;
enum tracker_source
{
source_torrent = 1,
source_client = 2,
source_magnet_link = 4,
source_tex = 8
};
// where did we get this tracker from
boost::uint8_t source;
// is set to true if we have ever received a response from
// this tracker
bool verified:1;
// true if we're currently trying to announce with
// this tracker
bool updating:1;
// this is true if event start has been sent to the tracker
bool start_sent:1;
// this is true if event completed has been sent to the trac
ker
bool complete_sent:1;
// this is false the stats sent to this tracker will be 0
bool send_stats:1;
void reset()
{
start_sent = false;
next_announce = min_time();
min_announce = min_time();
}
void failed(int retry_interval = 0)
{
++fails;
int delay = (std::min)(tracker_retry_delay_min + int
(fails) * int(fails)
* tracker_retry_delay_min, int(tracker_retry
_delay_max));
delay = (std::max)(delay, retry_interval);
next_announce = time_now() + seconds(delay);
updating = false;
}
bool can_announce(ptime now) const
{
return now >= next_announce
&& now >= min_announce
&& (fails < fail_limit || fail_limit == 0)
&& !updating;
}
bool is_working() const
{
return fails == 0;
}
void trim()
{
while (!url.empty() && is_space(url[0]))
url.erase(url.begin());
}
}; };
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
struct TORRENT_EXPORT invalid_torrent_file: std::exception // for backwards compatibility with 0.14
{ typedef libtorrent_exception invalid_torrent_file;
virtual const char* what() const throw() { return "invalid t
orrent file"; }
};
#endif #endif
int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<c har>& v); int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<c har>& v);
class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torren t_info> class TORRENT_EXPORT torrent_info : public intrusive_ptr_base<torren t_info>
{ {
public: public:
torrent_info(torrent_info const& t);
torrent_info(sha1_hash const& info_hash); #ifndef BOOST_NO_EXCEPTIONS
torrent_info(lazy_entry const& torrent_file); torrent_info(lazy_entry const& torrent_file);
torrent_info(char const* buffer, int size); torrent_info(char const* buffer, int size);
torrent_info(fs::path const& filename); torrent_info(fs::path const& filename);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
torrent_info(fs::wpath const& filename);
#endif
#endif
torrent_info(sha1_hash const& info_hash);
torrent_info(lazy_entry const& torrent_file, error_code& ec)
;
torrent_info(char const* buffer, int size, error_code& ec);
torrent_info(fs::path const& filename, error_code& ec);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
torrent_info(fs::wpath const& filename, error_code& ec);
#endif
~torrent_info(); ~torrent_info();
file_storage const& files() const { return m_files; } file_storage const& files() const { return m_files; }
file_storage const& orig_files() const { return m_orig_files ? *m_orig_files : m_files; } file_storage const& orig_files() const { return m_orig_files ? *m_orig_files : m_files; }
void rename_file(int index, std::string const& new_filename) void rename_file(int index, std::string const& new_filename)
{ {
copy_on_write(); copy_on_write();
m_files.rename_file(index, new_filename); m_files.rename_file(index, new_filename);
} }
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
void rename_file(int index, std::wstring const& new_filename
)
{
copy_on_write();
m_files.rename_file(index, new_filename);
}
#endif
void remap_files(file_storage const& f);
void add_tracker(std::string const& url, int tier = 0); void add_tracker(std::string const& url, int tier = 0);
std::vector<announce_entry> const& trackers() const { return m_urls; } std::vector<announce_entry> const& trackers() const { return m_urls; }
std::vector<std::string> const& url_seeds() const std::vector<std::string> const& url_seeds() const
{ return m_url_seeds; } { return m_url_seeds; }
void add_url_seed(std::string const& url) void add_url_seed(std::string const& url)
{ m_url_seeds.push_back(url); } { m_url_seeds.push_back(url); }
std::vector<std::string> const& http_seeds() const
{ return m_http_seeds; }
void add_http_seed(std::string const& url)
{ m_http_seeds.push_back(url); }
size_type total_size() const { return m_files.total_size(); } size_type total_size() const { return m_files.total_size(); }
int piece_length() const { return m_files.piece_length(); } int piece_length() const { return m_files.piece_length(); }
int num_pieces() const { return m_files.num_pieces(); } int num_pieces() const { return m_files.num_pieces(); }
const sha1_hash& info_hash() const { return m_info_hash; } const sha1_hash& info_hash() const { return m_info_hash; }
const std::string& name() const { return m_files.name(); } const std::string& name() const { return m_files.name(); }
typedef file_storage::iterator file_iterator; typedef file_storage::iterator file_iterator;
typedef file_storage::reverse_iterator reverse_file_iterator ; typedef file_storage::reverse_iterator reverse_file_iterator ;
file_iterator begin_files() const { return m_files.begin(); } file_iterator begin_files() const { return m_files.begin(); }
skipping to change at line 138 skipping to change at line 264
file_iterator file_at_offset(size_type offset) const file_iterator file_at_offset(size_type offset) const
{ return m_files.file_at_offset(offset); } { return m_files.file_at_offset(offset); }
std::vector<file_slice> map_block(int piece, size_type offse t, int size) const std::vector<file_slice> map_block(int piece, size_type offse t, int size) const
{ return m_files.map_block(piece, offset, size); } { return m_files.map_block(piece, offset, size); }
peer_request map_file(int file, size_type offset, int size) const peer_request map_file(int file, size_type offset, int size) const
{ return m_files.map_file(file, offset, size); } { return m_files.map_file(file, offset, size); }
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// ------- start deprecation ------- // ------- start deprecation -------
// these functions will be removed in a future version // these functions will be removed in a future version
TORRENT_DEPRECATED_PREFIX
torrent_info(entry const& torrent_file) TORRENT_DEPRECATED; torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void print(std::ostream& os) const TORRENT_DEPRECATED; void print(std::ostream& os) const TORRENT_DEPRECATED;
file_storage& files() TORRENT_DEPRECATED { return m_files; }
// ------- end deprecation ------- // ------- end deprecation -------
#endif #endif
bool is_valid() const { return m_files.is_valid(); } bool is_valid() const { return m_files.is_valid(); }
bool priv() const { return m_private; } bool priv() const { return m_private; }
int piece_size(int index) const { return m_files.piece_size( index); } int piece_size(int index) const { return m_files.piece_size( index); }
sha1_hash hash_for_piece(int index) const sha1_hash hash_for_piece(int index) const
{ return sha1_hash(hash_for_piece_ptr(index)); } { return sha1_hash(hash_for_piece_ptr(index)); }
std::vector<sha1_hash> const& merkle_tree() const { return m
_merkle_tree; }
void set_merkle_tree(std::vector<sha1_hash>& h)
{ TORRENT_ASSERT(h.size() == m_merkle_tree.size() ); m_merkl
e_tree.swap(h); }
char const* hash_for_piece_ptr(int index) const char const* hash_for_piece_ptr(int index) const
{ {
TORRENT_ASSERT(index >= 0); TORRENT_ASSERT(index >= 0);
TORRENT_ASSERT(index < m_files.num_pieces()); TORRENT_ASSERT(index < m_files.num_pieces());
TORRENT_ASSERT(m_piece_hashes); if (is_merkle_torrent())
TORRENT_ASSERT(m_piece_hashes >= m_info_section.get( {
)); TORRENT_ASSERT(index < int(m_merkle_tree.siz
TORRENT_ASSERT(m_piece_hashes < m_info_section.get() e()) - m_merkle_first_leaf);
+ m_info_section_size); return (const char*)&m_merkle_tree[m_merkle_
return &m_piece_hashes[index*20]; first_leaf + index][0];
}
else
{
TORRENT_ASSERT(m_piece_hashes);
TORRENT_ASSERT(m_piece_hashes >= m_info_sect
ion.get());
TORRENT_ASSERT(m_piece_hashes < m_info_secti
on.get() + m_info_section_size);
TORRENT_ASSERT(index < m_info_section_size /
20);
return &m_piece_hashes[index*20];
}
} }
boost::optional<pt::ptime> creation_date() const; boost::optional<pt::ptime> creation_date() const;
const std::string& creator() const const std::string& creator() const
{ return m_created_by; } { return m_created_by; }
const std::string& comment() const const std::string& comment() const
{ return m_comment; } { return m_comment; }
// dht nodes to add to the routing table/bootstrap from // dht nodes to add to the routing table/bootstrap from
typedef std::vector<std::pair<std::string, int> > nodes_t; typedef std::vector<std::pair<std::string, int> > nodes_t;
nodes_t const& nodes() const nodes_t const& nodes() const
{ return m_nodes; } { return m_nodes; }
void add_node(std::pair<std::string, int> const& node) void add_node(std::pair<std::string, int> const& node)
{ m_nodes.push_back(node); } { m_nodes.push_back(node); }
bool parse_info_section(lazy_entry const& e, std::string& er ror); bool parse_info_section(lazy_entry const& e, error_code& ex) ;
lazy_entry const* info(char const* key) const lazy_entry const* info(char const* key) const
{ {
if (m_info_dict.type() == lazy_entry::none_t) if (m_info_dict.type() == lazy_entry::none_t)
lazy_bdecode(m_info_section.get(), m_info_se ction.get() lazy_bdecode(m_info_section.get(), m_info_se ction.get()
+ m_info_section_size, m_info_dict); + m_info_section_size, m_info_dict);
return m_info_dict.dict_find(key); return m_info_dict.dict_find(key);
} }
void swap(torrent_info& ti); void swap(torrent_info& ti);
boost::shared_array<char> metadata() const boost::shared_array<char> metadata() const
{ return m_info_section; } { return m_info_section; }
int metadata_size() const { return m_info_section_size; } int metadata_size() const { return m_info_section_size; }
bool add_merkle_nodes(std::map<int, sha1_hash> const& subtre
e
, int piece);
std::map<int, sha1_hash> build_merkle_list(int piece) const;
bool is_merkle_torrent() const { return !m_merkle_tree.empty
(); }
private: private:
// not assignable
torrent_info const& operator=(torrent_info const&);
void copy_on_write(); void copy_on_write();
bool parse_torrent_file(lazy_entry const& libtorrent, std::s tring& error); bool parse_torrent_file(lazy_entry const& libtorrent, error_ code& ec);
file_storage m_files; file_storage m_files;
// if m_files is modified, it is first copied into // if m_files is modified, it is first copied into
// m_orig_files so that the original name and // m_orig_files so that the original name and
// filenames are preserved. // filenames are preserved.
boost::shared_ptr<const file_storage> m_orig_files; boost::shared_ptr<const file_storage> m_orig_files;
// the urls to the trackers // the urls to the trackers
std::vector<announce_entry> m_urls; std::vector<announce_entry> m_urls;
std::vector<std::string> m_url_seeds; std::vector<std::string> m_url_seeds;
std::vector<std::string> m_http_seeds;
nodes_t m_nodes; nodes_t m_nodes;
// the hash that identifies this torrent // the hash that identifies this torrent
sha1_hash m_info_hash; sha1_hash m_info_hash;
// if a creation date is found in the torrent file // if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be // this will be set to that, otherwise it'll be
// 1970, Jan 1 // 1970, Jan 1
pt::ptime m_creation_date; pt::ptime m_creation_date;
skipping to change at line 250 skipping to change at line 399
// this is a copy of the info section from the torrent. // this is a copy of the info section from the torrent.
// it use maintained in this flat format in order to // it use maintained in this flat format in order to
// make it available through the metadata extension // make it available through the metadata extension
boost::shared_array<char> m_info_section; boost::shared_array<char> m_info_section;
int m_info_section_size; int m_info_section_size;
// this is a pointer into the m_info_section buffer // this is a pointer into the m_info_section buffer
// pointing to the first byte of the first sha-1 hash // pointing to the first byte of the first sha-1 hash
char const* m_piece_hashes; char const* m_piece_hashes;
// if this is a merkle torrent, this is the merkle
// tree. It has space for merkle_num_nodes(merkle_num_leafs(
num_pieces))
// hashes
std::vector<sha1_hash> m_merkle_tree;
// the index to the first leaf. This is where the hash for t
he
// first piece is stored
int m_merkle_first_leaf;
// the info section parsed. points into m_info_section // the info section parsed. points into m_info_section
// parsed lazily // parsed lazily
mutable lazy_entry m_info_dict; mutable lazy_entry m_info_dict;
}; };
} }
#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED #endif // TORRENT_TORRENT_INFO_HPP_INCLUDED
 End of changes. 20 change blocks. 
19 lines changed or deleted 189 lines changed or added


 tracker_manager.hpp   tracker_manager.hpp 
skipping to change at line 73 skipping to change at line 73
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
namespace libtorrent namespace libtorrent
{ {
struct request_callback; struct request_callback;
class tracker_manager; class tracker_manager;
struct timeout_handler; struct timeout_handler;
struct tracker_connection; struct tracker_connection;
struct ip_filter; namespace aux { struct session_impl; }
// returns -1 if gzip header is invalid or the header size in bytes // returns -1 if gzip header is invalid or the header size in bytes
TORRENT_EXPORT int gzip_header(const char* buf, int size); TORRENT_EXPORT int gzip_header(const char* buf, int size);
struct TORRENT_EXPORT tracker_request struct TORRENT_EXPORT tracker_request
{ {
tracker_request() tracker_request()
: kind(announce_request) : kind(announce_request)
, event(none) , event(none)
, key(0) , key(0)
, num_want(0) , num_want(0)
, send_stats(true)
{} {}
enum enum
{ {
announce_request, announce_request,
scrape_request scrape_request
} kind; } kind;
enum event_t enum event_t
{ {
skipping to change at line 114 skipping to change at line 115
size_type uploaded; size_type uploaded;
size_type left; size_type left;
size_type corrupt; size_type corrupt;
unsigned short listen_port; unsigned short listen_port;
event_t event; event_t event;
std::string url; std::string url;
int key; int key;
int num_want; int num_want;
std::string ipv6; std::string ipv6;
std::string ipv4; std::string ipv4;
address bind_ip;
bool send_stats;
}; };
struct TORRENT_EXPORT request_callback struct TORRENT_EXPORT request_callback
{ {
friend class tracker_manager; friend class tracker_manager;
request_callback(): m_manager(0) {} request_callback(): m_manager(0) {}
virtual ~request_callback() {} virtual ~request_callback() {}
virtual void tracker_warning(tracker_request const& req virtual void tracker_warning(tracker_request const& req
, std::string const& msg) = 0; , std::string const& msg) = 0;
virtual void tracker_scrape_response(tracker_request const& virtual void tracker_scrape_response(tracker_request const&
req /*req*/
, int complete, int incomplete, int downloads) {} , int /*complete*/, int /*incomplete*/, int /*downlo
ads*/) {}
virtual void tracker_response( virtual void tracker_response(
tracker_request const& req tracker_request const& req
, address const& tracker_ip
, std::list<address> const& ip_list
, std::vector<peer_entry>& peers , std::vector<peer_entry>& peers
, int interval , int interval
, int min_interval
, int complete , int complete
, int incomplete , int incomplete
, address const& external_ip) = 0; , address const& external_ip) = 0;
virtual void tracker_request_timed_out( virtual void tracker_request_timed_out(
tracker_request const& req) = 0; tracker_request const& req) = 0;
virtual void tracker_request_error( virtual void tracker_request_error(
tracker_request const& req tracker_request const& req
, int response_code , int response_code
, const std::string& description) = 0; , const std::string& description
, int retry_interval) = 0;
tcp::endpoint m_tracker_address; tcp::endpoint m_tracker_address;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T ORRENT_ERROR_LOGGING
virtual void debug_log(const std::string& line) = 0; virtual void debug_log(const std::string& line) = 0;
#endif #endif
private: private:
tracker_manager* m_manager; tracker_manager* m_manager;
}; };
skipping to change at line 191 skipping to change at line 198
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
bool m_abort; bool m_abort;
}; };
struct TORRENT_EXPORT tracker_connection struct TORRENT_EXPORT tracker_connection
: timeout_handler : timeout_handler
{ {
tracker_connection(tracker_manager& man tracker_connection(tracker_manager& man
, tracker_request const& req , tracker_request const& req
, io_service& ios , io_service& ios
, address bind_interface
, boost::weak_ptr<request_callback> r); , boost::weak_ptr<request_callback> r);
boost::shared_ptr<request_callback> requester(); boost::shared_ptr<request_callback> requester();
virtual ~tracker_connection() {} virtual ~tracker_connection() {}
tracker_request const& tracker_req() const { return m_req; } tracker_request const& tracker_req() const { return m_req; }
void fail(int code, char const* msg); void fail_disp(int code, std::string const& msg) { fail(code
, msg.c_str()); }
void fail(int code, char const* msg, int interval = 0, int m
in_interval = 0);
void fail_timeout(); void fail_timeout();
virtual void start() = 0; virtual void start() = 0;
virtual void close(); virtual void close();
address const& bind_interface() const { return m_bind_interf address const& bind_interface() const { return m_req.bind_ip
ace; } ; }
void sent_bytes(int bytes);
void received_bytes(int bytes);
protected: protected:
boost::weak_ptr<request_callback> m_requester; boost::weak_ptr<request_callback> m_requester;
private: private:
address m_bind_interface;
tracker_manager& m_man; tracker_manager& m_man;
const tracker_request m_req; const tracker_request m_req;
}; };
class TORRENT_EXPORT tracker_manager: boost::noncopyable class TORRENT_EXPORT tracker_manager: boost::noncopyable
{ {
public: public:
tracker_manager(session_settings const& s, proxy_settings co tracker_manager(aux::session_impl& ses, proxy_settings const
nst& ps) & ps)
: m_settings(s) : m_ses(ses)
, m_proxy(ps) , m_proxy(ps)
, m_abort(false) {} , m_abort(false) {}
~tracker_manager();
void queue_request( void queue_request(
io_service& ios io_service& ios
, connection_queue& cc , connection_queue& cc
, tracker_request r , tracker_request r
, std::string const& auth , std::string const& auth
, address bind_infc
, boost::weak_ptr<request_callback> c , boost::weak_ptr<request_callback> c
= boost::weak_ptr<request_callback>() = boost::weak_ptr<request_callback>());
, ip_filter const* ipf = 0); void abort_all_requests(bool all = false);
void abort_all_requests();
void remove_request(tracker_connection const*); void remove_request(tracker_connection const*);
bool empty() const; bool empty() const;
int num_requests() const; int num_requests() const;
void sent_bytes(int bytes);
void received_bytes(int bytes);
private: private:
typedef boost::recursive_mutex mutex_t; typedef boost::recursive_mutex mutex_t;
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
typedef std::list<boost::intrusive_ptr<tracker_connection> > typedef std::list<boost::intrusive_ptr<tracker_connection> >
tracker_connections_t; tracker_connections_t;
tracker_connections_t m_connections; tracker_connections_t m_connections;
session_settings const& m_settings; aux::session_impl& m_ses;
proxy_settings const& m_proxy; proxy_settings const& m_proxy;
bool m_abort; bool m_abort;
}; };
} }
#endif // TORRENT_TRACKER_MANAGER_HPP_INCLUDED #endif // TORRENT_TRACKER_MANAGER_HPP_INCLUDED
 End of changes. 17 change blocks. 
19 lines changed or deleted 32 lines changed or added


 traversal_algorithm.hpp   traversal_algorithm.hpp 
skipping to change at line 48 skipping to change at line 48
#include <libtorrent/kademlia/node_id.hpp> #include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/routing_table.hpp> #include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/logging.hpp> #include <libtorrent/kademlia/logging.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/pool/pool.hpp> #include <boost/pool/pool.hpp>
namespace libtorrent { struct dht_lookup; }
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(traversal); TORRENT_DECLARE_LOG(traversal);
#endif #endif
class rpc_manager; class rpc_manager;
class node_impl;
// this class may not be instantiated as a stack object // this class may not be instantiated as a stack object
class traversal_algorithm : boost::noncopyable struct traversal_algorithm : boost::noncopyable
{ {
public:
void traverse(node_id const& id, udp::endpoint addr); void traverse(node_id const& id, udp::endpoint addr);
void finished(node_id const& id); void finished(node_id const& id);
void failed(node_id const& id, bool prevent_request = false); void failed(node_id const& id, bool prevent_request = false);
virtual ~traversal_algorithm() {} virtual ~traversal_algorithm();
boost::pool<>& allocator() const; boost::pool<>& allocator() const;
void status(dht_lookup& l);
virtual char const* name() const { return "traversal_algorithm"; }
node_id const& target() const { return m_target; }
protected: protected:
template<class InIt> template<class InIt>
traversal_algorithm( traversal_algorithm(node_impl& node, node_id target, InIt start, InI
node_id target t end);
, int branch_factor
, int max_results
, routing_table& table
, rpc_manager& rpc
, InIt start
, InIt end
);
void add_requests(); void add_requests();
void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags); void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags);
void add_router_entries();
void init();
virtual void done() = 0; virtual void done() = 0;
virtual void invoke(node_id const& id, udp::endpoint addr) = 0; virtual void invoke(node_id const& id, udp::endpoint addr) = 0;
struct result struct result
{ {
result(node_id const& id, udp::endpoint addr, unsigned char f = 0) result(node_id const& id, udp::endpoint addr, unsigned char f = 0)
: id(id), addr(addr), flags(f) {} : id(id), addr(addr), flags(f) {}
node_id id; node_id id;
skipping to change at line 110 skipping to change at line 111
} }
friend void intrusive_ptr_release(traversal_algorithm* p) friend void intrusive_ptr_release(traversal_algorithm* p)
{ {
if (--p->m_ref_count == 0) if (--p->m_ref_count == 0)
delete p; delete p;
} }
int m_ref_count; int m_ref_count;
node_impl& m_node;
node_id m_target; node_id m_target;
int m_branch_factor;
int m_max_results;
std::vector<result> m_results; std::vector<result> m_results;
std::set<udp::endpoint> m_failed; std::set<udp::endpoint> m_failed;
routing_table& m_table;
rpc_manager& m_rpc;
int m_invoke_count; int m_invoke_count;
int m_branch_factor;
int m_responses;
int m_timeouts;
}; };
template<class InIt> template<class InIt>
traversal_algorithm::traversal_algorithm( traversal_algorithm::traversal_algorithm(
node_id target node_impl& node
, int branch_factor , node_id target
, int max_results
, routing_table& table
, rpc_manager& rpc
, InIt start // <- nodes to initiate traversal with , InIt start // <- nodes to initiate traversal with
, InIt end , InIt end)
)
: m_ref_count(0) : m_ref_count(0)
, m_node(node)
, m_target(target) , m_target(target)
, m_branch_factor(branch_factor)
, m_max_results(max_results)
, m_table(table)
, m_rpc(rpc)
, m_invoke_count(0) , m_invoke_count(0)
, m_branch_factor(3)
, m_responses(0)
, m_timeouts(0)
{ {
using boost::bind; using boost::bind;
for (InIt i = start; i != end; ++i) for (InIt i = start; i != end; ++i)
{ {
add_entry(i->id, i->addr, result::initial); add_entry(i->id, udp::endpoint(i->addr, i->port), result::in itial);
} }
// in case the routing table is empty, use the // in case the routing table is empty, use the
// router nodes in the table // router nodes in the table
if (start == end) if (start == end) add_router_entries();
{ init();
for (routing_table::router_iterator i = table.router_begin()
, end(table.router_end()); i != end; ++i)
{
add_entry(node_id(0), *i, result::initial);
}
}
} }
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // TRAVERSAL_ALGORITHM_050324_HPP #endif // TRAVERSAL_ALGORITHM_050324_HPP
 End of changes. 20 change blocks. 
37 lines changed or deleted 28 lines changed or added


 udp_socket.hpp   udp_socket.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED #ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED
#define TORRENT_UDP_SOCKET_HPP_INCLUDED #define TORRENT_UDP_SOCKET_HPP_INCLUDED
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/buffer.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/buffer.hpp"
#include <vector> #include <vector>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
namespace libtorrent namespace libtorrent
{ {
class connection_queue; class connection_queue;
class udp_socket class udp_socket
{ {
public: public:
typedef boost::function<void(error_code const& ec typedef boost::function<void(error_code const& ec
, udp::endpoint const&, char const* buf, int size)> callback_t; , udp::endpoint const&, char const* buf, int size)> callback_t;
udp_socket(io_service& ios, callback_t const& c, connection_ queue& cc); udp_socket(io_service& ios, callback_t const& c, connection_ queue& cc);
~udp_socket(); ~udp_socket();
bool is_open() const { return m_ipv4_sock.is_open() || m_ipv bool is_open() const
6_sock.is_open(); } {
return m_ipv4_sock.is_open()
#if TORRENT_USE_IPV6
|| m_ipv6_sock.is_open()
#endif
;
}
io_service& get_io_service() { return m_ipv4_sock.get_io_ser vice(); } io_service& get_io_service() { return m_ipv4_sock.get_io_ser vice(); }
void send(udp::endpoint const& ep, char const* p, int len, e rror_code& ec); void send(udp::endpoint const& ep, char const* p, int len, e rror_code& ec);
void bind(udp::endpoint const& ep, error_code& ec); void bind(udp::endpoint const& ep, error_code& ec);
void bind(int port); void bind(int port);
void close(); void close();
int local_port() const { return m_bind_port; } int local_port() const { return m_bind_port; }
void set_proxy_settings(proxy_settings const& ps); void set_proxy_settings(proxy_settings const& ps);
proxy_settings const& get_proxy_settings() { return m_proxy_ settings; } proxy_settings const& get_proxy_settings() { return m_proxy_ settings; }
bool is_closed() const { return m_abort; }
protected: protected:
struct queued_packet struct queued_packet
{ {
udp::endpoint ep; udp::endpoint ep;
buffer buf; buffer buf;
}; };
private: private:
skipping to change at line 95 skipping to change at line 104
void on_timeout(); void on_timeout();
void on_connect(int ticket); void on_connect(int ticket);
void on_connected(error_code const& ec); void on_connected(error_code const& ec);
void handshake1(error_code const& e); void handshake1(error_code const& e);
void handshake2(error_code const& e); void handshake2(error_code const& e);
void handshake3(error_code const& e); void handshake3(error_code const& e);
void handshake4(error_code const& e); void handshake4(error_code const& e);
void socks_forward_udp(mutex_t::scoped_lock& l); void socks_forward_udp(mutex_t::scoped_lock& l);
void connect1(error_code const& e); void connect1(error_code const& e);
void connect2(error_code const& e); void connect2(error_code const& e);
void hung_up(error_code const& e);
void wrap(udp::endpoint const& ep, char const* p, int len, e rror_code& ec); void wrap(udp::endpoint const& ep, char const* p, int len, e rror_code& ec);
void unwrap(error_code const& e, char const* buf, int size); void unwrap(error_code const& e, char const* buf, int size);
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
udp::socket m_ipv4_sock; udp::socket m_ipv4_sock;
udp::socket m_ipv6_sock;
udp::endpoint m_v4_ep; udp::endpoint m_v4_ep;
udp::endpoint m_v6_ep;
char m_v4_buf[1600]; char m_v4_buf[1600];
#if TORRENT_USE_IPV6
udp::socket m_ipv6_sock;
udp::endpoint m_v6_ep;
char m_v6_buf[1600]; char m_v6_buf[1600];
#endif
int m_bind_port; int m_bind_port;
char m_outstanding; char m_outstanding;
tcp::socket m_socks5_sock; tcp::socket m_socks5_sock;
int m_connection_ticket; int m_connection_ticket;
proxy_settings m_proxy_settings; proxy_settings m_proxy_settings;
connection_queue& m_cc; connection_queue& m_cc;
tcp::resolver m_resolver; tcp::resolver m_resolver;
char m_tmp_buf[100]; char m_tmp_buf[100];
bool m_queue_packets; bool m_queue_packets;
bool m_tunnel_packets; bool m_tunnel_packets;
bool m_abort; bool m_abort;
udp::endpoint m_proxy_addr; udp::endpoint m_proxy_addr;
// while we're connecting to the proxy // while we're connecting to the proxy
// we have to queue the packets, we'll flush // we have to queue the packets, we'll flush
// them once we're connected // them once we're connected
std::list<queued_packet> m_queue; std::list<queued_packet> m_queue;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool m_started; bool m_started;
int m_magic; int m_magic;
int m_outstanding_when_aborted;
#endif #endif
}; };
struct rate_limited_udp_socket : public udp_socket
{
rate_limited_udp_socket(io_service& ios, callback_t const& c
, connection_queue& cc);
void set_rate_limit(int limit) { m_rate_limit = limit; }
bool can_send() const { return int(m_queue.size()) >= m_queu
e_size_limit; }
bool send(udp::endpoint const& ep, char const* p, int len, e
rror_code& ec, int flags = 0);
void close();
private:
void on_tick(error_code const& e);
deadline_timer m_timer;
int m_queue_size_limit;
int m_rate_limit;
int m_quota;
ptime m_last_tick;
std::list<queued_packet> m_queue;
};
} }
#endif #endif
 End of changes. 11 change blocks. 
6 lines changed or deleted 40 lines changed or added


 udp_tracker_connection.hpp   udp_tracker_connection.hpp 
skipping to change at line 62 skipping to change at line 62
#include "libtorrent/udp_socket.hpp" #include "libtorrent/udp_socket.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/peer.hpp" #include "libtorrent/peer.hpp"
#include "libtorrent/tracker_manager.hpp" #include "libtorrent/tracker_manager.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
namespace libtorrent namespace libtorrent
{ {
struct ip_filter; namespace aux { struct session_impl; }
class TORRENT_EXPORT udp_tracker_connection: public tracker_connecti on class TORRENT_EXPORT udp_tracker_connection: public tracker_connecti on
{ {
friend class tracker_manager; friend class tracker_manager;
public: public:
udp_tracker_connection( udp_tracker_connection(
io_service& ios io_service& ios
, connection_queue& cc , connection_queue& cc
, tracker_manager& man , tracker_manager& man
, tracker_request const& req , tracker_request const& req
, address bind_infc
, boost::weak_ptr<request_callback> c , boost::weak_ptr<request_callback> c
, session_settings const& stn , aux::session_impl const& ses
, proxy_settings const& ps , proxy_settings const& ps);
, ip_filter const* ipf);
void start(); void start();
void close(); void close();
private: private:
enum action_t enum action_t
{ {
action_connect, action_connect,
action_announce, action_announce,
skipping to change at line 116 skipping to change at line 114
void send_udp_announce(); void send_udp_announce();
void send_udp_scrape(); void send_udp_scrape();
virtual void on_timeout(); virtual void on_timeout();
tracker_manager& m_man; tracker_manager& m_man;
udp::resolver m_name_lookup; udp::resolver m_name_lookup;
udp_socket m_socket; udp_socket m_socket;
udp::endpoint m_target; udp::endpoint m_target;
std::list<udp::endpoint> m_endpoints;
int m_transaction_id; int m_transaction_id;
boost::int64_t m_connection_id; aux::session_impl const& m_ses;
session_settings const& m_settings;
int m_attempts; int m_attempts;
action_t m_state; struct connection_cache_entry
{
boost::int64_t connection_id;
ptime expires;
};
ip_filter const* m_ip_filter; static std::map<address, connection_cache_entry> m_connectio
n_cache;
static boost::mutex m_cache_mutex;
action_t m_state;
}; };
} }
#endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED #endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED
 End of changes. 7 change blocks. 
9 lines changed or deleted 15 lines changed or added


 upnp.hpp   upnp.hpp 
skipping to change at line 49 skipping to change at line 49
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/thread/mutex.hpp> #include <boost/thread/mutex.hpp>
#include <boost/thread/condition.hpp> #include <boost/thread/condition.hpp>
#include <set> #include <set>
#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defi
ned (TORRENT_UPNP_LOGGING)
#define TORRENT_UPNP_LOGGING
#endif
#if defined(TORRENT_UPNP_LOGGING) #if defined(TORRENT_UPNP_LOGGING)
#include <fstream> #include <fstream>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
namespace upnp_errors
{
enum error_code_enum
{
no_error = 0,
invalid_argument = 402,
action_failed = 501,
value_not_in_array = 714,
source_ip_cannot_be_wildcarded = 715,
external_port_cannot_be_wildcarded = 716,
port_mapping_conflict = 718,
internal_port_must_match_external = 724,
only_permanent_leases_supported = 725,
remote_host_must_be_wildcard = 726,
external_port_must_be_wildcard = 727
};
}
#if BOOST_VERSION < 103500
extern asio::error::error_category upnp_category;
#else
struct TORRENT_EXPORT upnp_error_category : boost::system::error_cat
egory
{
virtual const char* name() const;
virtual std::string message(int ev) const;
virtual boost::system::error_condition default_error_conditi
on(int ev) const
{ return boost::system::error_condition(ev, *this); }
};
extern TORRENT_EXPORT upnp_error_category upnp_category;
#endif
// int: port-mapping index // int: port-mapping index
// int: external port // int: external port
// std::string: error message // std::string: error message
// an empty string as error means success // an empty string as error means success
typedef boost::function<void(int, int, std::string const&)> portmap_callbac // a port-mapping index of -1 means it's
k_t; // an informational log message
typedef boost::function<void(int, int, error_code const&)> portmap_callback
_t;
typedef boost::function<void(char const*)> log_callback_t;
class upnp : public intrusive_ptr_base<upnp> class TORRENT_EXPORT upnp : public intrusive_ptr_base<upnp>
{ {
public: public:
upnp(io_service& ios, connection_queue& cc upnp(io_service& ios, connection_queue& cc
, address const& listen_interface, std::string const& user_a gent , address const& listen_interface, std::string const& user_a gent
, portmap_callback_t const& cb, bool ignore_nonrouters, void , portmap_callback_t const& cb, log_callback_t const& lcb
* state = 0); , bool ignore_nonrouters, void* state = 0);
~upnp(); ~upnp();
void* drain_state(); void* drain_state();
enum protocol_type { none = 0, udp = 1, tcp = 2 }; enum protocol_type { none = 0, udp = 1, tcp = 2 };
int add_mapping(protocol_type p, int external_port, int local_port); int add_mapping(protocol_type p, int external_port, int local_port);
void delete_mapping(int mapping_index); void delete_mapping(int mapping_index);
bool get_mapping(int mapping_index, int& local_port, int& external_p ort, int& protocol) const;
void discover_device(); void discover_device();
void close(); void close();
std::string router_model() std::string router_model()
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
return m_model; return m_model;
} }
private: private:
void discover_device_impl(); typedef boost::mutex mutex_t;
void discover_device_impl(mutex_t::scoped_lock& l);
static address_v4 upnp_multicast_address; static address_v4 upnp_multicast_address;
static udp::endpoint upnp_multicast_endpoint; static udp::endpoint upnp_multicast_endpoint;
// there are routers that's don't support timed // there are routers that's don't support timed
// port maps, without returning error 725. It seems // port maps, without returning error 725. It seems
// safer to always assume that we have to ask for // safer to always assume that we have to ask for
// permanent leases // permanent leases
enum { default_lease_time = 0 }; enum { default_lease_time = 0 };
void resend_request(error_code const& e); void resend_request(error_code const& e);
void on_reply(udp::endpoint const& from, char* buffer void on_reply(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
struct rootdevice; struct rootdevice;
void next(rootdevice& d, int i); void next(rootdevice& d, int i, mutex_t::scoped_lock& l);
void update_map(rootdevice& d, int i); void update_map(rootdevice& d, int i, mutex_t::scoped_lock& l);
void on_upnp_xml(error_code const& e void on_upnp_xml(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d , libtorrent::http_parser const& p, rootdevice& d
, http_connection& c); , http_connection& c);
void on_upnp_map_response(error_code const& e void on_upnp_map_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d , libtorrent::http_parser const& p, rootdevice& d
, int mapping, http_connection& c); , int mapping, http_connection& c);
void on_upnp_unmap_response(error_code const& e void on_upnp_unmap_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d , libtorrent::http_parser const& p, rootdevice& d
, int mapping, http_connection& c); , int mapping, http_connection& c);
void on_expire(error_code const& e); void on_expire(error_code const& e);
void disable(char const* msg); void disable(error_code const& ec, mutex_t::scoped_lock& l);
void return_error(int mapping, int code); void return_error(int mapping, int code, mutex_t::scoped_lock& l);
void log(char const* msg, mutex_t::scoped_lock& l);
void delete_port_mapping(rootdevice& d, int i); void delete_port_mapping(rootdevice& d, int i);
void create_port_mapping(http_connection& c, rootdevice& d, int i); void create_port_mapping(http_connection& c, rootdevice& d, int i);
void post(upnp::rootdevice const& d, std::string const& soap void post(upnp::rootdevice const& d, char const* soap
, std::string const& soap_action); , char const* soap_action, mutex_t::scoped_lock& l);
int num_mappings() const { return int(m_mappings.size()); } int num_mappings() const { return int(m_mappings.size()); }
struct global_mapping_t struct global_mapping_t
{ {
global_mapping_t() global_mapping_t()
: protocol(none) : protocol(none)
, external_port(0) , external_port(0)
, local_port(0) , local_port(0)
{} {}
skipping to change at line 250 skipping to change at line 287
}; };
std::vector<global_mapping_t> m_mappings; std::vector<global_mapping_t> m_mappings;
std::string const& m_user_agent; std::string const& m_user_agent;
// the set of devices we've found // the set of devices we've found
std::set<rootdevice> m_devices; std::set<rootdevice> m_devices;
portmap_callback_t m_callback; portmap_callback_t m_callback;
log_callback_t m_log_callback;
// current retry count // current retry count
int m_retry_count; int m_retry_count;
io_service& m_io_service; io_service& m_io_service;
// the udp socket used to send and receive // the udp socket used to send and receive
// multicast messages on the network // multicast messages on the network
broadcast_socket m_socket; broadcast_socket m_socket;
skipping to change at line 273 skipping to change at line 311
// timer used to refresh mappings // timer used to refresh mappings
deadline_timer m_refresh_timer; deadline_timer m_refresh_timer;
bool m_disabled; bool m_disabled;
bool m_closing; bool m_closing;
bool m_ignore_non_routers; bool m_ignore_non_routers;
connection_queue& m_cc; connection_queue& m_cc;
typedef boost::mutex mutex_t;
mutex_t m_mutex; mutex_t m_mutex;
std::string m_model; std::string m_model;
#ifdef TORRENT_UPNP_LOGGING
std::ofstream m_log;
#endif
}; };
} }
#endif #endif
 End of changes. 13 change blocks. 
22 lines changed or deleted 55 lines changed or added


 utf8.hpp   utf8.hpp 
/* /*
Copyright (C) 2004-2005 Cory Nelson
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damag
es
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose Copyright (c) 2006, Arvid Norberg
, All rights reserved.
including commercial applications, and to alter it and redistribute
it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not
claim that you wrote the original software. If you use this
software
in a product, an acknowledgment in the product documentation
would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must
not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distrib
ution.
*/
// namespaces added by Arvid Norberg
#ifndef __UTF8_H__ Redistribution and use in source and binary forms, with or without
#define __UTF8_H__ modification, are permitted provided that the following conditions
are met:
#include <string> * Redistributions of source code must retain the above copyright
#include <iterator> notice, this list of conditions and the following disclaimer.
#include <stdexcept> * Redistributions in binary form must reproduce the above copyright
#include <cwchar> notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the distributi
on.
* Neither the name of the author nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
namespace libtorrent { THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
namespace detail { AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
template<typename InputIterator> */
wchar_t decode_utf8_mb(InputIterator &iter, InputIterator last)
{
if (iter == last) throw std::runtime_error("incomplete UTF-8 sequenc
e");
if (((*iter) & 0xc0) != 0x80) throw std::runtime_error("invalid UTF-
8 sequence");
return (wchar_t)((*iter++) & 0x3f); #ifndef TORRENT_UTF8_HPP_INCLUDED
} #define TORRENT_UTF8_HPP_INCLUDED
template<typename InputIterator> #include "libtorrent/config.hpp"
wchar_t decode_utf8(InputIterator &iter, InputIterator last)
{
wchar_t ret;
if (((*iter) & 0x80) == 0) // one byte #if !defined BOOST_FILESYSTEM_NARROW_ONLY || defined TORRENT_WINDOWS
{
ret = *iter++;
}
else if (((*iter) & 0xe0) == 0xc0) // two bytes
{
wchar_t byte1 = (*iter++) & 0x1f;
wchar_t byte2 = decode_utf8_mb(iter, last);
ret = (byte1 << 6) | byte2;
}
else if (((*iter) & 0xf0) == 0xe0) // three bytes
{
wchar_t byte1 = (*iter++) & 0x0f;
wchar_t byte2 = decode_utf8_mb(iter, last);
wchar_t byte3 = decode_utf8_mb(iter, last);
ret = (byte1 << 12) | (byte2 << 6) | byte3;
}
// TODO: support surrogate pairs
else throw std::runtime_error("UTF-8 not convertable to UTF-16");
return ret; #include <string>
} #include <cwchar>
#include "libtorrent/ConvertUTF.h"
template<typename InputIterator, typename OutputIterator> namespace libtorrent
OutputIterator utf8_wchar(InputIterator first, InputIterator last, OutputIt
erator dest)
{ {
for(; first!=last; ++dest)
*dest = decode_utf8(first, last);
return dest;
}
template<typename InputIterator, typename OutputIterator> inline int utf8_wchar(const std::string &utf8, std::wstring &wide)
void encode_wchar(InputIterator iter, OutputIterator &dest)
{
if(*iter <= 0x007F)
{ {
*dest=(char)*iter; // allocate space for worst-case
++dest; wide.resize(utf8.size());
wchar_t const* dst_start = &wide[0];
char const* src_start = &utf8[0];
ConversionResult ret;
if (sizeof(wchar_t) == sizeof(UTF32))
{
ret = ConvertUTF8toUTF32((const UTF8**)&src_start, (
const UTF8*)src_start
+ utf8.size(), (UTF32**)&dst_start, (UTF32*)
dst_start + wide.size()
, lenientConversion);
wide.resize(dst_start - &wide[0]);
return ret;
}
else if (sizeof(wchar_t) == sizeof(UTF16))
{
ret = ConvertUTF8toUTF16((const UTF8**)&src_start, (
const UTF8*)src_start
+ utf8.size(), (UTF16**)&dst_start, (UTF16*)
dst_start + wide.size()
, lenientConversion);
wide.resize(dst_start - &wide[0]);
return ret;
}
else
{
return sourceIllegal;
}
} }
else if(*iter <= 0x07FF)
{
*dest = (char)(
0xC0 |
((*iter & 0x07C0) >> 6)
);
++dest;
*dest = (char)( inline int wchar_utf8(const std::wstring &wide, std::string &utf8)
0x80 |
(*iter & 0x003F)
);
++dest;
}
else if(*iter <= 0xFFFF)
{ {
*dest = (char)( // allocate space for worst-case
0xE0 | utf8.resize(wide.size() * 6);
((*iter & 0xF000) >> 12) char* dst_start = &utf8[0];
); wchar_t const* src_start = &wide[0];
++dest; ConversionResult ret;
if (sizeof(wchar_t) == sizeof(UTF32))
*dest = (char)( {
0x80 | ret = ConvertUTF32toUTF8((const UTF32**)&src_start,
((*iter & 0x0FC0) >> 6) (const UTF32*)src_start
); + wide.size(), (UTF8**)&dst_start, (UTF8*)ds
++dest; t_start + utf8.size()
, lenientConversion);
*dest = (char)( utf8.resize(dst_start - &utf8[0]);
0x80 | return ret;
(*iter & 0x003F) }
); else if (sizeof(wchar_t) == sizeof(UTF16))
++dest; {
ret = ConvertUTF16toUTF8((const UTF16**)&src_start,
(const UTF16*)src_start
+ wide.size(), (UTF8**)&dst_start, (UTF8*)ds
t_start + utf8.size()
, lenientConversion);
utf8.resize(dst_start - &utf8[0]);
return ret;
}
else
{
return sourceIllegal;
}
} }
} }
#endif
template<typename InputIterator, typename OutputIterator>
OutputIterator wchar_utf8(InputIterator first, InputIterator last, OutputIt
erator dest)
{
for(; first!=last; ++first)
encode_wchar(first, dest);
return dest;
}
}
inline void utf8_wchar(const std::string &utf8, std::wstring &wide)
{
wide.clear();
detail::utf8_wchar(utf8.begin(), utf8.end(), std::back_inserter(wide
));
}
inline std::wstring utf8_wchar(const std::string &str)
{
std::wstring ret;
utf8_wchar(str, ret);
return ret;
}
inline void wchar_utf8(const std::wstring &wide, std::string &utf8)
{
utf8.clear();
detail::wchar_utf8(wide.begin(), wide.end(), std::back_inserter(utf8
));
}
inline std::string wchar_utf8(const std::wstring &str)
{
std::string ret;
wchar_utf8(str, ret);
return ret;
}
}
#endif #endif
 End of changes. 18 change blocks. 
154 lines changed or deleted 95 lines changed or added


 variant_stream.hpp   variant_stream.hpp 
skipping to change at line 55 skipping to change at line 55
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
}; };
// -------------- io_control ----------- // -------------- io_control -----------
template<class IO_Control_Command> template<class IO_Control_Command>
struct io_control_visitor_ec: boost::static_visitor<> struct io_control_visitor_ec: boost::static_visitor<>
{ {
io_control_visitor_ec(IO_Control_Command& ioc, error_code& ec_) io_control_visitor_ec(IO_Control_Command& io, error_code& e)
: ioc(ioc), ec(ec_) {} : ioc(io), ec(e) {}
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ {
p->io_control(ioc, ec); p->io_control(ioc, ec);
} }
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
IO_Control_Command& ioc; IO_Control_Command& ioc;
error_code& ec; error_code& ec;
}; };
template<class IO_Control_Command> template<class IO_Control_Command>
struct io_control_visitor struct io_control_visitor
: boost::static_visitor<> : boost::static_visitor<>
{ {
io_control_visitor(IO_Control_Command& ioc) io_control_visitor(IO_Control_Command& io)
: ioc(ioc) {} : ioc(io) {}
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ {
p->io_control(ioc); p->io_control(ioc);
} }
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
IO_Control_Command& ioc; IO_Control_Command& ioc;
}; };
// -------------- async_connect ----------- // -------------- async_connect -----------
template <class EndpointType, class Handler> template <class EndpointType, class Handler>
struct async_connect_visitor struct async_connect_visitor
: boost::static_visitor<> : boost::static_visitor<>
{ {
async_connect_visitor(EndpointType const& endpoint, Handler const& ha async_connect_visitor(EndpointType const& ep, Handler const& h)
ndler) : endpoint(ep)
: endpoint(endpoint) , handler(h)
, handler(handler)
{} {}
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ {
p->async_connect(endpoint, handler); p->async_connect(endpoint, handler);
} }
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
skipping to change at line 221 skipping to change at line 221
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ p->close(ec); } { p->close(ec); }
void operator()(boost::blank) const {} void operator()(boost::blank) const {}
error_code& ec; error_code& ec;
}; };
#ifndef BOOST_NO_EXCEPTIONS
struct close_visitor struct close_visitor
: boost::static_visitor<> : boost::static_visitor<>
{ {
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ p->close(); } { p->close(); }
void operator()(boost::blank) const {} void operator()(boost::blank) const {}
}; };
#endif
// -------------- remote_endpoint ----------- // -------------- remote_endpoint -----------
template <class EndpointType> template <class EndpointType>
struct remote_endpoint_visitor_ec struct remote_endpoint_visitor_ec
: boost::static_visitor<EndpointType> : boost::static_visitor<EndpointType>
{ {
remote_endpoint_visitor_ec(error_code& ec_) remote_endpoint_visitor_ec(error_code& ec_)
: ec(ec_) : ec(ec_)
{} {}
skipping to change at line 251 skipping to change at line 253
template <class T> template <class T>
EndpointType operator()(T const* p) const EndpointType operator()(T const* p) const
{ return p->remote_endpoint(ec); } { return p->remote_endpoint(ec); }
EndpointType operator()(boost::blank) const EndpointType operator()(boost::blank) const
{ return EndpointType(); } { return EndpointType(); }
error_code& ec; error_code& ec;
}; };
#ifndef BOOST_NO_EXCEPTIONS
template <class EndpointType> template <class EndpointType>
struct remote_endpoint_visitor struct remote_endpoint_visitor
: boost::static_visitor<EndpointType> : boost::static_visitor<EndpointType>
{ {
template <class T> template <class T>
EndpointType operator()(T const* p) const EndpointType operator()(T const* p) const
{ return p->remote_endpoint(); } { return p->remote_endpoint(); }
EndpointType operator()(boost::blank) const EndpointType operator()(boost::blank) const
{ return EndpointType(); } { return EndpointType(); }
}; };
#endif
// -------------- set_option ----------- // -------------- set_option -----------
#ifndef BOOST_NO_EXCEPTIONS
template <class SettableSocketOption> template <class SettableSocketOption>
struct set_option_visitor struct set_option_visitor
: boost::static_visitor<> : boost::static_visitor<>
{ {
set_option_visitor(SettableSocketOption const& opt) set_option_visitor(SettableSocketOption const& opt)
: opt_(opt) : opt_(opt)
{} {}
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ p->set_option(opt_); } { p->set_option(opt_); }
void operator()(boost::blank) const {} void operator()(boost::blank) const {}
SettableSocketOption const& opt_; SettableSocketOption const& opt_;
}; };
#endif
template <class SettableSocketOption> template <class SettableSocketOption>
struct set_option_visitor_ec struct set_option_visitor_ec
: boost::static_visitor<error_code> : boost::static_visitor<error_code>
{ {
set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec ) set_option_visitor_ec(SettableSocketOption const& opt, error_code& ec )
: opt_(opt) : opt_(opt)
, ec_(ec) , ec_(ec)
{} {}
skipping to change at line 326 skipping to change at line 332
} }
EndpointType operator()(boost::blank) const EndpointType operator()(boost::blank) const
{ {
return EndpointType(); return EndpointType();
} }
error_code& ec; error_code& ec;
}; };
#ifndef BOOST_NO_EXCEPTIONS
template <class EndpointType> template <class EndpointType>
struct local_endpoint_visitor struct local_endpoint_visitor
: boost::static_visitor<EndpointType> : boost::static_visitor<EndpointType>
{ {
template <class T> template <class T>
EndpointType operator()(T const* p) const EndpointType operator()(T const* p) const
{ {
return p->local_endpoint(); return p->local_endpoint();
} }
EndpointType operator()(boost::blank) const EndpointType operator()(boost::blank) const
{ {
return EndpointType(); return EndpointType();
} }
}; };
#endif
// -------------- async_read_some ----------- // -------------- async_read_some -----------
template <class Mutable_Buffers, class Handler> template <class Mutable_Buffers, class Handler>
struct async_read_some_visitor struct async_read_some_visitor
: boost::static_visitor<> : boost::static_visitor<>
{ {
async_read_some_visitor(Mutable_Buffers const& buffers, Handler const async_read_some_visitor(Mutable_Buffers const& bufs, Handler const& h
& handler) )
: buffers(buffers) : buffers(bufs)
, handler(handler) , handler(h)
{} {}
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ {
p->async_read_some(buffers, handler); p->async_read_some(buffers, handler);
} }
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
Mutable_Buffers const& buffers; Mutable_Buffers const& buffers;
Handler const& handler; Handler const& handler;
}; };
// -------------- read_some ----------- // -------------- read_some -----------
#ifndef BOOST_NO_EXCEPTIONS
template <class Mutable_Buffers> template <class Mutable_Buffers>
struct read_some_visitor struct read_some_visitor
: boost::static_visitor<std::size_t> : boost::static_visitor<std::size_t>
{ {
read_some_visitor(Mutable_Buffers const& buffers) read_some_visitor(Mutable_Buffers const& bufs)
: buffers(buffers) : buffers(bufs)
{} {}
template <class T> template <class T>
std::size_t operator()(T* p) const std::size_t operator()(T* p) const
{ return p->read_some(buffers); } { return p->read_some(buffers); }
std::size_t operator()(boost::blank) const std::size_t operator()(boost::blank) const
{ return 0; } { return 0; }
Mutable_Buffers const& buffers; Mutable_Buffers const& buffers;
}; };
#endif
template <class Mutable_Buffers> template <class Mutable_Buffers>
struct read_some_visitor_ec struct read_some_visitor_ec
: boost::static_visitor<std::size_t> : boost::static_visitor<std::size_t>
{ {
read_some_visitor_ec(Mutable_Buffers const& buffers, error_code& ec_) read_some_visitor_ec(Mutable_Buffers const& bufs, error_code& e)
: buffers(buffers) : buffers(bufs)
, ec(ec_) , ec(e)
{} {}
template <class T> template <class T>
std::size_t operator()(T* p) const std::size_t operator()(T* p) const
{ return p->read_some(buffers, ec); } { return p->read_some(buffers, ec); }
std::size_t operator()(boost::blank) const std::size_t operator()(boost::blank) const
{ return 0; } { return 0; }
Mutable_Buffers const& buffers; Mutable_Buffers const& buffers;
error_code& ec; error_code& ec;
}; };
// -------------- async_write_some ----------- // -------------- async_write_some -----------
template <class Const_Buffers, class Handler> template <class Const_Buffers, class Handler>
struct async_write_some_visitor struct async_write_some_visitor
: boost::static_visitor<> : boost::static_visitor<>
{ {
async_write_some_visitor(Const_Buffers const& buffers, Handler const& async_write_some_visitor(Const_Buffers const& bufs, Handler const& h)
handler) : buffers(bufs)
: buffers(buffers) , handler(h)
, handler(handler)
{} {}
template <class T> template <class T>
void operator()(T* p) const void operator()(T* p) const
{ {
p->async_write_some(buffers, handler); p->async_write_some(buffers, handler);
} }
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
skipping to change at line 452 skipping to change at line 462
} }
std::size_t operator()(boost::blank) const std::size_t operator()(boost::blank) const
{ {
return 0; return 0;
} }
error_code& ec; error_code& ec;
}; };
#ifndef BOOST_NO_EXCEPTIONS
struct in_avail_visitor struct in_avail_visitor
: boost::static_visitor<std::size_t> : boost::static_visitor<std::size_t>
{ {
template <class T> template <class T>
std::size_t operator()(T const* p) const std::size_t operator()(T const* p) const
{ {
return p->in_avail(); return p->in_avail();
} }
void operator()(boost::blank) const void operator()(boost::blank) const
{} {}
}; };
#endif
// -------------- io_service ----------- // -------------- io_service -----------
template <class IOService> template <class IOService>
struct io_service_visitor struct io_service_visitor
: boost::static_visitor<IOService&> : boost::static_visitor<IOService&>
{ {
template <class T> template <class T>
IOService& operator()(T* p) const IOService& operator()(T* p) const
{ {
skipping to change at line 572 skipping to change at line 584
template <class Mutable_Buffers> template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec) std::size_t read_some(Mutable_Buffers const& buffers, error_code& ec)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor( return boost::apply_visitor(
aux::read_some_visitor_ec<Mutable_Buffers>(buffers, ec) aux::read_some_visitor_ec<Mutable_Buffers>(buffers, ec)
, m_variant , m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
template <class Mutable_Buffers> template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers) std::size_t read_some(Mutable_Buffers const& buffers)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor( return boost::apply_visitor(
aux::read_some_visitor<Mutable_Buffers>(buffers) aux::read_some_visitor<Mutable_Buffers>(buffers)
, m_variant , m_variant
); );
} }
#endif
template <class Mutable_Buffers, class Handler> template <class Mutable_Buffers, class Handler>
void async_read_some(Mutable_Buffers const& buffers, Handler const& han dler) void async_read_some(Mutable_Buffers const& buffers, Handler const& han dler)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor( boost::apply_visitor(
aux::async_read_some_visitor<Mutable_Buffers, Handler>(buffers, handler) aux::async_read_some_visitor<Mutable_Buffers, Handler>(buffers, handler)
, m_variant , m_variant
); );
} }
skipping to change at line 611 skipping to change at line 625
template <class Handler> template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler const& handle r) void async_connect(endpoint_type const& endpoint, Handler const& handle r)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor( boost::apply_visitor(
aux::async_connect_visitor<endpoint_type, Handler>(endpoint, ha ndler), m_variant aux::async_connect_visitor<endpoint_type, Handler>(endpoint, ha ndler), m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
template <class IO_Control_Command> template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc) void io_control(IO_Control_Command& ioc)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor( boost::apply_visitor(
aux::io_control_visitor<IO_Control_Command>(ioc), m_variant aux::io_control_visitor<IO_Control_Command>(ioc), m_variant
); );
} }
#endif
template <class IO_Control_Command> template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, error_code& ec) void io_control(IO_Control_Command& ioc, error_code& ec)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor( boost::apply_visitor(
aux::io_control_visitor_ec<IO_Control_Command>(ioc, ec) aux::io_control_visitor_ec<IO_Control_Command>(ioc, ec)
, m_variant , m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
void bind(endpoint_type const& endpoint) void bind(endpoint_type const& endpoint)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_ variant); boost::apply_visitor(aux::bind_visitor<endpoint_type>(endpoint), m_ variant);
} }
#endif
void bind(endpoint_type const& endpoint, error_code& ec) void bind(endpoint_type const& endpoint, error_code& ec)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor( boost::apply_visitor(
aux::bind_visitor_ec<endpoint_type>(endpoint, ec), m_variant aux::bind_visitor_ec<endpoint_type>(endpoint, ec), m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
void open(protocol_type const& p) void open(protocol_type const& p)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant ); boost::apply_visitor(aux::open_visitor<protocol_type>(p), m_variant );
} }
#endif
void open(protocol_type const& p, error_code& ec) void open(protocol_type const& p, error_code& ec)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor( boost::apply_visitor(
aux::open_visitor_ec<protocol_type>(p, ec), m_variant aux::open_visitor_ec<protocol_type>(p, ec), m_variant
); );
} }
bool is_open() const bool is_open() const
{ {
return boost::apply_visitor(aux::is_open_visitor(), m_variant); return boost::apply_visitor(aux::is_open_visitor(), m_variant);
} }
#ifndef BOOST_NO_EXCEPTIONS
void close() void close()
{ {
if (!instantiated()) return; if (!instantiated()) return;
boost::apply_visitor(aux::close_visitor(), m_variant); boost::apply_visitor(aux::close_visitor(), m_variant);
} }
#endif
void close(error_code& ec) void close(error_code& ec)
{ {
if (!instantiated()) return; if (!instantiated()) return;
boost::apply_visitor( boost::apply_visitor(
aux::close_visitor_ec(ec), m_variant aux::close_visitor_ec(ec), m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
std::size_t in_avail() const std::size_t in_avail() const
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::in_avail_visitor(), m_variant); return boost::apply_visitor(aux::in_avail_visitor(), m_variant);
} }
#endif
std::size_t in_avail(error_code& ec) const std::size_t in_avail(error_code& ec) const
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor( return boost::apply_visitor(
aux::in_avail_visitor_ec(ec), m_variant aux::in_avail_visitor_ec(ec), m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
endpoint_type remote_endpoint() const endpoint_type remote_endpoint() const
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_t ype>(), m_variant); return boost::apply_visitor(aux::remote_endpoint_visitor<endpoint_t ype>(), m_variant);
} }
#endif
endpoint_type remote_endpoint(error_code& ec) const endpoint_type remote_endpoint(error_code& ec) const
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor( return boost::apply_visitor(
aux::remote_endpoint_visitor_ec<endpoint_type>(ec), m_variant aux::remote_endpoint_visitor_ec<endpoint_type>(ec), m_variant
); );
} }
#ifndef BOOST_NO_EXCEPTIONS
template <class SettableSocketOption> template <class SettableSocketOption>
void set_option(SettableSocketOption const& opt) void set_option(SettableSocketOption const& opt)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
boost::apply_visitor(aux::set_option_visitor<SettableSocketOption>( opt) boost::apply_visitor(aux::set_option_visitor<SettableSocketOption>( opt)
, m_variant); , m_variant);
} }
#endif
template <class SettableSocketOption> template <class SettableSocketOption>
error_code set_option(SettableSocketOption const& opt, error_code& ec) error_code set_option(SettableSocketOption const& opt, error_code& ec)
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::set_option_visitor_ec<SettableSock etOption>(opt, ec) return boost::apply_visitor(aux::set_option_visitor_ec<SettableSock etOption>(opt, ec)
, m_variant); , m_variant);
} }
#ifndef BOOST_NO_EXCEPTIONS
endpoint_type local_endpoint() const endpoint_type local_endpoint() const
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_ty pe>(), m_variant); return boost::apply_visitor(aux::local_endpoint_visitor<endpoint_ty pe>(), m_variant);
} }
#endif
endpoint_type local_endpoint(error_code& ec) const endpoint_type local_endpoint(error_code& ec) const
{ {
TORRENT_ASSERT(instantiated()); TORRENT_ASSERT(instantiated());
return boost::apply_visitor( return boost::apply_visitor(
aux::local_endpoint_visitor_ec<endpoint_type>(ec), m_variant aux::local_endpoint_visitor_ec<endpoint_type>(ec), m_variant
); );
} }
io_service& get_io_service() io_service& get_io_service()
 End of changes. 37 change blocks. 
21 lines changed or deleted 49 lines changed or added


 version.hpp   version.hpp 
skipping to change at line 37 skipping to change at line 37
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_VERSION_HPP_INCLUDED #ifndef TORRENT_VERSION_HPP_INCLUDED
#define TORRENT_VERSION_HPP_INCLUDED #define TORRENT_VERSION_HPP_INCLUDED
#define LIBTORRENT_VERSION_MAJOR 0 #define LIBTORRENT_VERSION_MAJOR 0
#define LIBTORRENT_VERSION_MINOR 14 #define LIBTORRENT_VERSION_MINOR 15
#define LIBTORRENT_VERSION_TINY 12 #define LIBTORRENT_VERSION_TINY 0
#define LIBTORRENT_VERSION "0.14.12.0" #define LIBTORRENT_VERSION "0.15.0.0"
#define LIBTORRENT_REVISION "$Rev: 4828 $" #define LIBTORRENT_REVISION "$Rev: 3323 $"
#endif #endif
 End of changes. 2 change blocks. 
4 lines changed or deleted 4 lines changed or added


 web_peer_connection.hpp   web_peer_connection.hpp 
skipping to change at line 166 skipping to change at line 166
std::string m_path; std::string m_path;
std::string m_url; std::string m_url;
const std::string m_original_url; const std::string m_original_url;
// the first request will contain a little bit more data // the first request will contain a little bit more data
// than subsequent ones, things that aren't critical are lef t // than subsequent ones, things that aren't critical are lef t
// out to save bandwidth. // out to save bandwidth.
bool m_first_request; bool m_first_request;
// this is used for intermediate storage of pieces // this is used for intermediate storage of pieces
// that is received in more than on HTTP responses // that are received in more than one HTTP response
std::vector<char> m_piece; std::vector<char> m_piece;
// the mapping of the data in the m_piece buffer
peer_request m_intermediate_piece;
// the number of bytes into the receive buffer where // the number of bytes into the receive buffer where
// current read cursor is. // current read cursor is.
int m_body_start; int m_body_start;
// the number of bytes received in the current HTTP // the number of bytes received in the current HTTP
// response. used to know where in the buffer the // response. used to know where in the buffer the
// next response starts // next response starts
int m_received_body; int m_received_body;
// position in the current range response // position in the current range response
int m_range_pos; int m_range_pos;
// the position in the current block
int m_block_pos;
}; };
} }
#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 3 change blocks. 
3 lines changed or deleted 4 lines changed or added


 xml_parse.hpp   xml_parse.hpp 
skipping to change at line 53 skipping to change at line 53
xml_start_tag, xml_start_tag,
xml_end_tag, xml_end_tag,
xml_empty_tag, xml_empty_tag,
xml_declaration_tag, xml_declaration_tag,
xml_string, xml_string,
xml_attribute, xml_attribute,
xml_comment, xml_comment,
xml_parse_error xml_parse_error
}; };
inline bool isspace(char c)
{
const static char* ws = " \t\n\r\f\v";
return std::strchr(ws, c);
}
// callback(int type, char const* name, char const* val) // callback(int type, char const* name, char const* val)
// str2 is only used for attributes. name is element or attribute // str2 is only used for attributes. name is element or attribute
// name and val is attribute value // name and val is attribute value
template <class CallbackType> template <class CallbackType>
void xml_parse(char* p, char* end, CallbackType callback) void xml_parse(char* p, char* end, CallbackType callback)
{ {
for(;p != end; ++p) for(;p != end; ++p)
{ {
char const* start = p; char const* start = p;
 End of changes. 1 change blocks. 
6 lines changed or deleted 0 lines changed or added

This html diff was produced by rfcdiff 1.41. The latest version is available from http://tools.ietf.org/tools/rfcdiff/