ConvertUTF.h   ConvertUTF.h 
skipping to change at line 100 skipping to change at line 100
#ifdef __cplusplus #ifdef __cplusplus
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
// these are standard C types, but they might // these are standard C types, but they might
// not be available in c++ // not be available in c++
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
typedef boost::uint32_t UTF32; typedef boost::uint32_t UTF32;
typedef boost::uint16_t UTF16; typedef boost::uint16_t UTF16;
typedef boost::uint8_t UTF8; typedef boost::uint8_t UTF8;
extern "C" { extern "C" {
#else #else
#define TORRENT_EXPORT
#ifdef _MSC_VER #ifdef _MSC_VER
// msvc doesn't seem to have stdint.h // msvc doesn't seem to have stdint.h
typedef unsigned __int32 UTF32; typedef unsigned __int32 UTF32;
typedef unsigned __int16 UTF16; typedef unsigned __int16 UTF16;
typedef unsigned __int8 UTF8; typedef unsigned __int8 UTF8;
#else #else
#include <stdint.h> #include <stdint.h>
typedef uint32_t UTF32; typedef uint32_t UTF32;
typedef uint16_t UTF16; typedef uint16_t UTF16;
typedef uint8_t UTF8; typedef uint8_t UTF8;
skipping to change at line 135 skipping to change at line 134
sourceExhausted, /* partial character in source, but hit end */ sourceExhausted, /* partial character in source, but hit end */
targetExhausted, /* insuff. room in target for conversion */ targetExhausted, /* insuff. room in target for conversion */
sourceIllegal /* source sequence is illegal/malformed */ sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult; } ConversionResult;
typedef enum { typedef enum {
strictConversion = 0, strictConversion = 0,
lenientConversion lenientConversion
} ConversionFlags; } ConversionFlags;
TORRENT_EXPORT ConversionResult ConvertUTF8toUTF16 ( ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd, const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags ); UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags );
TORRENT_EXPORT ConversionResult ConvertUTF16toUTF8 ( ConversionResult ConvertUTF16toUTF8 (
const UTF16** sourceStart, const UTF16* sourceEnd, const UTF16** sourceStart, const UTF16* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
TORRENT_EXPORT ConversionResult ConvertUTF8toUTF32 ( ConversionResult ConvertUTF8toUTF32 (
const UTF8** sourceStart, const UTF8* sourceEnd, const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags ); UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags );
TORRENT_EXPORT ConversionResult ConvertUTF32toUTF8 ( ConversionResult ConvertUTF32toUTF8 (
const UTF32** sourceStart, const UTF32* sourceEnd, const UTF32** sourceStart, const UTF32* sourceEnd,
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags); UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF32 ( ConversionResult ConvertUTF16toUTF32 (
const UTF16** sourceStart, const UTF16* sourceEnd, const UTF16** sourceStart, const UTF16* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags ); UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags );
ConversionResult ConvertUTF32toUTF16 ( ConversionResult ConvertUTF32toUTF16 (
const UTF32** sourceStart, const UTF32* sourceEnd, const UTF32** sourceStart, const UTF32* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags ); UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags );
 End of changes. 5 change blocks. 
5 lines changed or deleted 4 lines changed or added


 alert.hpp   alert.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_ALERT_HPP_INCLUDED #ifndef TORRENT_ALERT_HPP_INCLUDED
#define TORRENT_ALERT_HPP_INCLUDED #define TORRENT_ALERT_HPP_INCLUDED
#include <memory> #include <memory>
#include <queue> #include <deque>
#include <string> #include <string>
#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/function/function1.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> #include <boost/preprocessor/repetition/enum_shifted_binary_params.hpp>
#ifndef TORRENT_DISABLE_EXTENSIONS
#include <boost/shared_ptr.hpp>
#include <list>
#endif
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/time.hpp" #include "libtorrent/ptime.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/socket.hpp" // for io_service #include "libtorrent/thread.hpp"
#include "libtorrent/io_service_fwd.hpp"
#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 {
#ifndef TORRENT_DISABLE_EXTENSIONS
struct plugin;
#endif
class TORRENT_EXPORT alert class TORRENT_EXPORT alert
{ {
public: public:
#ifndef TORRENT_NO_DEPRECATE
// only here for backwards compatibility // only here for backwards compatibility
enum severity_t { debug, info, warning, critical, fatal, non e }; enum severity_t { debug, info, warning, critical, fatal, non e };
#endif
enum category_t enum category_t
{ {
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, dht_notification = 0x400,
stats_notification = 0x800, stats_notification = 0x800,
rss_notification = 0x1000,
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 int type() const = 0;
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;
virtual bool discardable() const { return true; }
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX 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> class TORRENT_EXTRA_EXPORT alert_manager
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
{ {
public: public:
enum { queue_size_limit_default = 1000 }; alert_manager(io_service& ios, int queue_limit
, boost::uint32_t alert_mask = alert::error_notifica
alert_manager(io_service& ios); tion);
~alert_manager(); ~alert_manager();
void post_alert(const alert& alert_); void post_alert(const alert& alert_);
void post_alert_ptr(alert* alert_);
bool pending() const; bool pending() const;
std::auto_ptr<alert> get(); std::auto_ptr<alert> get();
void get_all(std::deque<alert*>* alerts);
template <class T> template <class T>
bool should_post() const bool should_post() const
{ {
boost::mutex::scoped_lock lock(m_mutex); mutex::scoped_lock lock(m_mutex);
if (m_alerts.size() >= m_queue_size_limit) return fa lse; if (m_alerts.size() >= m_queue_size_limit) return fa lse;
return (m_alert_mask & T::static_category) != 0; 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(boost::uint32_t m) void set_alert_mask(boost::uint32_t m)
{ {
boost::mutex::scoped_lock lock(m_mutex); mutex::scoped_lock lock(m_mutex);
m_alert_mask = m; m_alert_mask = m;
} }
int alert_mask() const { return m_alert_mask; }
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& void set_dispatch_function(boost::function<void(std::auto_pt
)> const&); r<alert>)> const&);
#ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<plugin> ext);
#endif
private: private:
std::queue<alert*> m_alerts; void post_impl(std::auto_ptr<alert>& alert_);
mutable boost::mutex m_mutex;
boost::condition m_condition; std::deque<alert*> m_alerts;
mutable mutex m_mutex;
// event m_condition;
boost::uint32_t m_alert_mask; boost::uint32_t m_alert_mask;
size_t m_queue_size_limit; size_t m_queue_size_limit;
boost::function<void(alert const&;)> m_dispatch; boost::function<void(std::auto_ptr<alert>;)> m_dispatch;
io_service& m_ios; io_service& m_ios;
#ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<plugin> > ses_extension_
list_t;
ses_extension_list_t m_ses_extensions;
#endif
}; };
struct TORRENT_EXPORT unhandled_alert : std::exception struct TORRENT_EXPORT unhandled_alert : std::exception
{ {
unhandled_alert() {} unhandled_alert() {}
}; };
#ifndef BOOST_NO_TYPEID
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_
, T0*, BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(TORRENT_M AX_ALERT_TYPES, T, *p)) , T0*, BOOST_PP_ENUM_SHIFTED_BINARY_PARAMS(TORRENT_M AX_ALERT_TYPES, T, *p))
skipping to change at line 224 skipping to change at line 240
{ {
#define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT (T, n)*)0 #define ALERT_POINTER_TYPE(z, n, text) (BOOST_PP_CAT (T, n)*)0
detail::handle_alert_dispatch(alert_, handler, typei d(*alert_) detail::handle_alert_dispatch(alert_, handler, typei d(*alert_)
, BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALE RT_POINTER_TYPE, _)); , BOOST_PP_ENUM(TORRENT_MAX_ALERT_TYPES, ALE RT_POINTER_TYPE, _));
#undef ALERT_POINTER_TYPE #undef ALERT_POINTER_TYPE
} }
}; };
#endif // BOOST_NO_TYPEID
template <class T>
T* alert_cast(alert* a)
{
if (a == 0) return 0;
if (a->type() == T::alert_type) return static_cast<T*>(a);
return 0;
}
template <class T>
T const* alert_cast(alert const* a)
{
if (a == 0) return 0;
if (a->type() == T::alert_type) return static_cast<T const*>(a);
return 0;
}
} // namespace libtorrent } // namespace libtorrent
#endif // TORRENT_ALERT_HPP_INCLUDED #endif // TORRENT_ALERT_HPP_INCLUDED
 End of changes. 25 change blocks. 
31 lines changed or deleted 67 lines changed or added


 alert_types.hpp   alert_types.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#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/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/address.hpp"
#include "libtorrent/stat.hpp" #include "libtorrent/stat.hpp"
#include "libtorrent/rss.hpp" // for feed_handle
// lines reserved for future includes
// the type-ids of the alert types
// are derived from the line on which
// they are declared
namespace libtorrent namespace libtorrent
{ {
// user defined alerts should use IDs greater than this
const static int user_alert_id = 10000;
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 const static int alert_type = 1;
{ return handle.is_valid()?handle.name():" - "; } virtual std::string message() const;
torrent_handle handle; torrent_handle handle;
}; };
struct TORRENT_EXPORT peer_alert: torrent_alert struct TORRENT_EXPORT peer_alert: torrent_alert
{ {
peer_alert(torrent_handle const& h, tcp::endpoint const& ip_ peer_alert(torrent_handle const& h, tcp::endpoint const& ip_
, peer_id const& pid_) , peer_id const& pid_)
: torrent_alert(h) : torrent_alert(h)
, ip(ip_) , ip(ip_)
, pid(pid_) , pid(pid_)
{} {}
const static int alert_type = 2;
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;
return torrent_alert::message() + " peer (" + ip.add
ress().to_string(ec)
+ ", " + identify_client(pid) + ")";
}
tcp::endpoint ip; tcp::endpoint ip;
peer_id pid; peer_id pid;
}; };
struct TORRENT_EXPORT tracker_alert: torrent_alert struct TORRENT_EXPORT tracker_alert: torrent_alert
{ {
tracker_alert(torrent_handle const& h tracker_alert(torrent_handle const& h
, std::string const& url_) , std::string const& url_)
: torrent_alert(h) : torrent_alert(h)
, url(url_) , url(url_)
{} {}
const static int alert_type = 3;
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 + ")";
}
std::string url; std::string url;
}; };
#define TORRENT_DEFINE_ALERT(name) \
const static int alert_type = __LINE__; \
virtual int type() const { return alert_type; } \
virtual std::auto_ptr<alert> clone() const \
{ return std::auto_ptr<alert>(new name(*this)); } \
virtual int category() const { return static_category; } \
virtual char const* what() const { return #name; }
struct TORRENT_EXPORT torrent_added_alert: torrent_alert
{
torrent_added_alert(torrent_handle const& h)
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_added_alert);
const static int static_category = alert::status_notificatio
n;
virtual std::string message() const;
};
struct TORRENT_EXPORT torrent_removed_alert: torrent_alert
{
torrent_removed_alert(torrent_handle const& h, sha1_hash con
st& ih)
: torrent_alert(h)
, info_hash(ih)
{}
TORRENT_DEFINE_ALERT(torrent_removed_alert);
const static int static_category = alert::status_notificatio
n;
virtual std::string message() const;
sha1_hash info_hash;
};
struct TORRENT_EXPORT read_piece_alert: torrent_alert struct TORRENT_EXPORT read_piece_alert: torrent_alert
{ {
read_piece_alert(torrent_handle const& h read_piece_alert(torrent_handle const& h
, int p, boost::shared_array<char> d, int s) , int p, boost::shared_array<char> d, int s)
: torrent_alert(h) : torrent_alert(h)
, buffer(d) , buffer(d)
, piece(p) , piece(p)
, size(s) , size(s)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(read_piece_alert);
{ return std::auto_ptr<alert>(new read_piece_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 std::string message() const;
virtual char const* what() const { return "read piece"; } virtual bool discardable() const { return false; }
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; boost::shared_array<char> buffer;
int piece; int piece;
int size; int size;
}; };
struct TORRENT_EXPORT file_completed_alert: torrent_alert struct TORRENT_EXPORT file_completed_alert: torrent_alert
{ {
file_completed_alert(torrent_handle const& h file_completed_alert(torrent_handle const& h
, int index_) , int index_)
: torrent_alert(h) : torrent_alert(h)
, index(index_) , index(index_)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(file_completed_alert);
{ return std::auto_ptr<alert>(new file_completed_alert(*this
)); }
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 std::string message() const;
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; 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 TORRENT_DEFINE_ALERT(file_renamed_alert);
{ 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 std::string message() const;
virtual char const* what() const { return "file renamed"; } virtual bool discardable() const { return false; }
virtual std::string message() const
{
char msg[200 + NAME_MAX];
snprintf(msg, sizeof(msg), "%s: file %d renamed to %
s", torrent_alert::message().c_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
, int index_ , int index_
, error_code ec_) , error_code ec_)
: torrent_alert(h) : torrent_alert(h)
, index(index_) , index(index_)
, error(ec_) , error(ec_)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(file_rename_failed_alert);
{ return std::auto_ptr<alert>(new file_rename_failed_alert(*
this)); }
virtual char const* what() const { return "file rename faile
d"; }
virtual std::string message() const
{
char ret[200 + NAME_MAX];
snprintf(ret, sizeof(ret), "%s: failed to rename fil
e %d: %s"
, torrent_alert::message().c_str(), index, e
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 std::string message() const;
virtual bool discardable() const { return false; }
int index; int index;
error_code error; 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, upload_limit_too_low,
download_limit_too_low, download_limit_too_low,
send_buffer_watermark_too_low, send_buffer_watermark_too_low,
too_many_optimistic_unchoke_slots,
bittyrant_with_no_uplimit,
too_high_disk_queue_limit,
too_few_outgoing_ports,
too_few_file_descriptors,
num_warnings 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 TORRENT_DEFINE_ALERT(performance_alert);
{ return std::auto_ptr<alert>(new performance_alert(*this));
}
virtual char const* what() const { return "performance warni
ng"; }
virtual std::string message() const
{
static char const* warning_str[] =
{
"max outstanding disk writes 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: "
+ 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 std::string message() const;
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 state_ , torrent_status::state_t state_
, torrent_status::state_t prev_state_) , torrent_status::state_t prev_state_)
: torrent_alert(h) : torrent_alert(h)
, state(state_) , state(state_)
, prev_state(prev_state_) , prev_state(prev_state_)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(state_changed_alert);
{ return std::auto_ptr<alert>(new state_changed_alert(*this)
); }
virtual char const* what() const { return "torrent state cha
nged"; }
virtual std::string message() const
{
static char const* state_str[] =
{"checking (q)", "checking", "dl metadata"
, "downloading", "finished", "seeding", "all
ocating"
, "checking (r)"};
return torrent_alert::message() + ": state changed t
o: "
+ 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 std::string message() const;
torrent_status::state_t state; torrent_status::state_t state;
torrent_status::state_t prev_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) , error_code const& e
, std::string const& m)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, times_in_row(times) , times_in_row(times)
, status_code(status) , status_code(status)
, msg(e.message()) , error(e)
, msg(m)
{ {
TORRENT_ASSERT(!url.empty()); TORRENT_ASSERT(!url.empty());
} }
tracker_error_alert(torrent_handle const& h TORRENT_DEFINE_ALERT(tracker_error_alert);
, int times
, int status
, std::string const& url_
, std::string const& msg_)
: tracker_alert(h, url_)
, times_in_row(times)
, status_code(status)
, msg(msg_)
{
TORRENT_ASSERT(!url.empty());
}
virtual std::auto_ptr<alert> clone() const
{ 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 std::string message() const;
virtual char const* what() const { return "tracker error"; }
virtual std::string message() const
{
char ret[400];
snprintf(ret, sizeof(ret), "%s (%d) %s (%d)"
, tracker_alert::message().c_str(), status_c
ode
, msg.c_str(), times_in_row);
return ret;
}
int times_in_row; int times_in_row;
int status_code; int status_code;
error_code error;
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
, std::string const& url_ , 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; TORRENT_DEFINE_ALERT(tracker_warning_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new tracker_warning_alert(*thi
s)); }
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 std::string message() const;
virtual char const* what() const { return "tracker warning";
} std::string msg;
virtual std::string message() const
{
return tracker_alert::message() + " warning: " + msg
;
}
}; };
struct TORRENT_EXPORT scrape_reply_alert: tracker_alert struct TORRENT_EXPORT scrape_reply_alert: tracker_alert
{ {
scrape_reply_alert(torrent_handle const& h scrape_reply_alert(torrent_handle const& h
, int incomplete_ , int incomplete_
, int complete_ , int complete_
, std::string const& url_) , std::string const& url_)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, incomplete(incomplete_) , incomplete(incomplete_)
, complete(complete_) , complete(complete_)
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
TORRENT_DEFINE_ALERT(scrape_reply_alert);
virtual std::string message() const;
int incomplete; int incomplete;
int complete; int complete;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new scrape_reply_alert(*this))
; }
virtual char const* what() const { return "tracker scrape re
ply"; }
virtual std::string message() const
{
char ret[400];
snprintf(ret, sizeof(ret), "%s scrape reply: %u %u"
, tracker_alert::message().c_str(), incomple
te, complete);
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) , error_code const& e)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, msg(e.message()) , msg(e.message())
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
scrape_failed_alert(torrent_handle const& h scrape_failed_alert(torrent_handle const& h
, std::string const& url_ , 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; TORRENT_DEFINE_ALERT(scrape_failed_alert);
virtual std::auto_ptr<alert> clone() const
{ 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;
virtual int category() const { return static_category; } virtual std::string message() const;
virtual char const* what() const { return "tracker scrape fa
iled"; } std::string msg;
virtual std::string message() const
{
return tracker_alert::message() + " scrape failed: "
+ msg;
}
}; };
struct TORRENT_EXPORT tracker_reply_alert: tracker_alert struct TORRENT_EXPORT tracker_reply_alert: tracker_alert
{ {
tracker_reply_alert(torrent_handle const& h tracker_reply_alert(torrent_handle const& h
, int np , int np
, std::string const& url_) , std::string const& url_)
: tracker_alert(h, url_) : tracker_alert(h, url_)
, num_peers(np) , num_peers(np)
{ TORRENT_ASSERT(!url.empty()); } { TORRENT_ASSERT(!url.empty()); }
int num_peers; TORRENT_DEFINE_ALERT(tracker_reply_alert);
virtual std::auto_ptr<alert> clone() const virtual std::string message() const;
{ return std::auto_ptr<alert>(new tracker_reply_alert(*this)
); } int num_peers;
virtual char const* what() const { return "tracker reply"; }
virtual std::string message() const
{
char ret[400];
snprintf(ret, sizeof(ret), "%s received peers: %u"
, tracker_alert::message().c_str(), num_peer
s);
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; TORRENT_DEFINE_ALERT(dht_reply_alert);
virtual std::auto_ptr<alert> clone() const virtual std::string message() const;
{ return std::auto_ptr<alert>(new dht_reply_alert(*this)); }
virtual char const* what() const { return "DHT reply"; } int num_peers;
virtual std::string message() const
{
char ret[400];
snprintf(ret, sizeof(ret), "%s received DHT peers: %
u"
, tracker_alert::message().c_str(), num_peer
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()); }
int event; TORRENT_DEFINE_ALERT(tracker_announce_alert);
virtual std::auto_ptr<alert> clone() const virtual std::string message() const;
{ return std::auto_ptr<alert>(new tracker_announce_alert(*th
is)); } int event;
virtual char const* what() const { return "tracker announce
sent"; }
virtual std::string message() const
{
const static char* event_str[] = {"none", "completed
", "started", "stopped", "paused"};
TORRENT_ASSERT(event < int(sizeof(event_str)/sizeof(
event_str[0])));
return tracker_alert::message() + " sending announce
(" + event_str[event] + ")";
}
}; };
struct TORRENT_EXPORT hash_failed_alert: torrent_alert struct TORRENT_EXPORT hash_failed_alert: torrent_alert
{ {
hash_failed_alert( hash_failed_alert(
torrent_handle const& h torrent_handle const& h
, int index) , int index)
: torrent_alert(h) : torrent_alert(h)
, piece_index(index) , piece_index(index)
{ TORRENT_ASSERT(index >= 0);} { TORRENT_ASSERT(index >= 0);}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(hash_failed_alert);
{ return std::auto_ptr<alert>(new hash_failed_alert(*this));
}
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 std::string message() const;
virtual std::string message() const
{
char ret[400];
snprintf(ret, sizeof(ret), "%s hash for piece %u fai
led"
, torrent_alert::message().c_str(), piece_in
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& ep peer_ban_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& peer_id) , peer_id const& peer_id)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(peer_ban_alert);
{ return std::auto_ptr<alert>(new peer_ban_alert(*this)); }
virtual char const* what() const { return "peer banned"; } virtual std::string message() const;
virtual std::string message() const
{
error_code ec;
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& ep peer_unsnubbed_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& peer_id) , peer_id const& peer_id)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(peer_unsnubbed_alert);
{ return std::auto_ptr<alert>(new peer_unsnubbed_alert(*this
)); } virtual std::string message() const;
virtual char const* what() const { return "peer unsnubbed";
}
virtual std::string message() const
{
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& ep peer_snubbed_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& peer_id) , peer_id const& peer_id)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(peer_snubbed_alert);
{ return std::auto_ptr<alert>(new peer_snubbed_alert(*this))
; } virtual std::string message() const;
virtual char const* what() const { return "peer snubbed"; }
virtual std::string message() const
{
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 t& ep peer_error_alert(torrent_handle const& h, tcp::endpoint cons t& ep
, peer_id const& peer_id, error_code const& e) , peer_id const& peer_id, error_code const& e)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
, error(e) , error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(peer_error_alert);
{ return std::auto_ptr<alert>(new peer_error_alert(*this));
}
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 std::string message() const virtual std::string message() const
{ {
error_code ec;
return peer_alert::message() + " peer error: " + err or.message(); return peer_alert::message() + " peer error: " + err or.message();
} }
error_code error; error_code error;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif #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& ep peer_connect_alert(torrent_handle h, tcp::endpoint const& ep
, peer_id const& peer_id) , peer_id const& peer_id)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(peer_connect_alert);
{ return std::auto_ptr<alert>(new peer_connect_alert(*this))
; }
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 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 nt const& ep peer_disconnected_alert(torrent_handle const& h, tcp::endpoi nt const& ep
, peer_id const& peer_id, error_code const& e) , peer_id const& peer_id, error_code const& e)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
, error(e) , error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(peer_disconnected_alert);
{ return std::auto_ptr<alert>(new peer_disconnected_alert(*t
his)); }
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 std::string message() const virtual std::string message() const
{ { return peer_alert::message() + " disconnecting: " + error.
return peer_alert::message() + " disconnecting: " + message(); }
error.message();
}
error_code error; error_code error;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif #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 const& ep invalid_request_alert(torrent_handle const& h, tcp::endpoint const& ep
, peer_id const& peer_id, peer_request const& r) , peer_id const& peer_id, peer_request const& r)
: peer_alert(h, ep, peer_id) : peer_alert(h, ep, peer_id)
, request(r) , request(r)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(invalid_request_alert);
{ return std::auto_ptr<alert>(new invalid_request_alert(*thi
s)); } virtual std::string message() const;
virtual char const* what() const { return "invalid piece req
uest"; }
virtual std::string message() const
{
char ret[200];
snprintf(ret, sizeof(ret), "%s peer sent an invalid
piece request (piece: %u start: %u len: %u)"
, torrent_alert::message().c_str(), request.
piece, request.start, request.length);
return ret;
}
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)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(torrent_finished_alert);
{ return std::auto_ptr<alert>(new torrent_finished_alert(*th
is)); }
virtual char const* what() const { return "torrent finished"
; }
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 std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " torrent finished downl
return torrent_alert::message() + " torrent finished oading"; }
downloading";
}
}; };
struct TORRENT_EXPORT piece_finished_alert: torrent_alert struct TORRENT_EXPORT piece_finished_alert: torrent_alert
{ {
piece_finished_alert( piece_finished_alert(
const torrent_handle& h const torrent_handle& h
, int piece_num) , int piece_num)
: torrent_alert(h) : torrent_alert(h)
, piece_index(piece_num) , piece_index(piece_num)
{ TORRENT_ASSERT(piece_index >= 0);} { TORRENT_ASSERT(piece_index >= 0);}
int piece_index; TORRENT_DEFINE_ALERT(piece_finished_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new piece_finished_alert(*this
)); }
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 std::string message() const;
virtual std::string message() const
{ int piece_index;
char ret[200];
snprintf(ret, sizeof(ret), "%s piece: %u finished do
wnloading"
, torrent_alert::message().c_str(), piece_in
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 const& ep request_dropped_alert(const torrent_handle& h, tcp::endpoint const& ep
, peer_id const& peer_id, int block_num, int piece_n um) , peer_id const& peer_id, int block_num, int piece_n um)
: peer_alert(h, ep, peer_id) : 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; TORRENT_DEFINE_ALERT(request_dropped_alert);
int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new request_dropped_alert(*thi
s)); }
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 std::string message() const;
virtual std::string message() const
{ int block_index;
char ret[200]; int piece_index;
snprintf(ret, sizeof(ret), "%s peer dropped block (
piece: %u block: %u)"
, torrent_alert::message().c_str(), piece_in
dex, block_index);
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 onst& ep block_timeout_alert(const torrent_handle& h, tcp::endpoint c onst& ep
, peer_id const& peer_id, int block_num, int piece_n um) , peer_id const& peer_id, int block_num, int piece_n um)
: peer_alert(h, ep, peer_id) : 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; TORRENT_DEFINE_ALERT(block_timeout_alert);
int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_timeout_alert(*this)
); }
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 std::string message() const;
virtual std::string message() const
{ int block_index;
char ret[200]; int piece_index;
snprintf(ret, sizeof(ret), "%s peer timed out reques
t ( piece: %u block: %u)"
, torrent_alert::message().c_str(), piece_in
dex, block_index);
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 const& ep block_finished_alert(const torrent_handle& h, tcp::endpoint const& ep
, peer_id const& peer_id, int block_num, int piece_n um) , peer_id const& peer_id, int block_num, int piece_n um)
: peer_alert(h, ep, peer_id) : 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; TORRENT_DEFINE_ALERT(block_finished_alert);
int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new block_finished_alert(*this
)); }
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 std::string message() const;
virtual std::string message() const
{ int block_index;
char ret[200]; int piece_index;
snprintf(ret, sizeof(ret), "%s block finished downlo
ading (piece: %u block: %u)"
, torrent_alert::message().c_str(), piece_in
dex, block_index);
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 nt const& ep block_downloading_alert(const torrent_handle& h, tcp::endpoi nt const& ep
, peer_id const& peer_id, char const* speedmsg, int block_num, int piece_num) , peer_id const& peer_id, char const* speedmsg, int block_num, int piece_num)
: peer_alert(h, ep, peer_id) : 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); }
TORRENT_DEFINE_ALERT(block_downloading_alert);
const static int static_category = alert::progress_notificat
ion;
virtual std::string message() const;
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
{ return std::auto_ptr<alert>(new block_downloading_alert(*t
his)); }
virtual char const* what() const { return "block requested";
}
const static int static_category = alert::progress_notificat
ion;
virtual int category() const { return static_category; }
virtual std::string message() const
{
char ret[200];
snprintf(ret, sizeof(ret), "%s requested block (piec
e: %u block: %u) %s"
, torrent_alert::message().c_str(), piece_in
dex, block_index, peer_speedmsg);
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 const& ep unwanted_block_alert(const torrent_handle& h, tcp::endpoint const& ep
, peer_id const& peer_id, int block_num, int piece_n um) , peer_id const& peer_id, int block_num, int piece_n um)
: peer_alert(h, ep, peer_id) : 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);}
TORRENT_DEFINE_ALERT(unwanted_block_alert);
virtual std::string message() const;
int block_index; int block_index;
int piece_index; int piece_index;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new unwanted_block_alert(*this
)); }
virtual char const* what() const { return "unwanted block re
ceived"; }
virtual std::string message() const
{
char ret[200];
snprintf(ret, sizeof(ret), "%s received block not in
download queue (piece: %u block: %u)"
, torrent_alert::message().c_str(), piece_in
dex, block_index);
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_)
{} {}
std::string path; TORRENT_DEFINE_ALERT(storage_moved_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new storage_moved_alert(*this)
); }
virtual char const* what() const { return "storage moved"; }
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 std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " moved storage to : " return torrent_alert::message() + " moved storage to : "
+ path; + path;
} }
std::string path;
}; };
struct TORRENT_EXPORT storage_moved_failed_alert: torrent_alert struct TORRENT_EXPORT storage_moved_failed_alert: torrent_alert
{ {
storage_moved_failed_alert(torrent_handle const& h, error_co de const& ec_) storage_moved_failed_alert(torrent_handle const& h, error_co de const& ec_)
: torrent_alert(h) : torrent_alert(h)
, error(ec_) , error(ec_)
{} {}
error_code error; TORRENT_DEFINE_ALERT(storage_moved_failed_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new storage_moved_failed_alert
(*this)); }
virtual char const* what() const { return "storage moved fai
led"; }
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 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();
} }
error_code error;
}; };
struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert struct TORRENT_EXPORT torrent_deleted_alert: torrent_alert
{ {
torrent_deleted_alert(torrent_handle const& h, sha1_hash con st& ih) torrent_deleted_alert(torrent_handle const& h, sha1_hash con st& ih)
: torrent_alert(h) : torrent_alert(h)
{ info_hash = ih; } { info_hash = ih; }
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(torrent_deleted_alert);
{ return std::auto_ptr<alert>(new torrent_deleted_alert(*thi
s)); }
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 std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " deleted"; }
return torrent_alert::message() + " deleted";
}
sha1_hash info_hash; 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, error_c ode const& e) torrent_delete_failed_alert(torrent_handle const& h, error_c ode const& e)
: torrent_alert(h) : torrent_alert(h)
, error(e) , error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
error_code error; TORRENT_DEFINE_ALERT(torrent_delete_failed_alert);
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new torrent_delete_failed_aler
t(*this)); }
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 std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " torrent deletion failed: " return torrent_alert::message() + " torrent deletion failed: "
+ error.message(); + error.message();
} }
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
}; };
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)
{} {}
boost::shared_ptr<entry> resume_data; TORRENT_DEFINE_ALERT(save_resume_data_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new save_resume_data_alert(*th
is)); }
virtual char const* what() const { return "save resume data
complete"; }
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 std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " resume data generated"
return torrent_alert::message() + " resume data gene ; }
rated"; virtual bool discardable() const { return false; }
}
boost::shared_ptr<entry> resume_data;
}; };
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
, error_code const& e) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, error(e) , error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
error_code error; TORRENT_DEFINE_ALERT(save_resume_data_failed_alert);
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new save_resume_data_failed_al
ert(*this)); }
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 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: "
+ error.message(); + error.message();
} }
virtual bool discardable() const { return false; }
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
}; };
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 TORRENT_DEFINE_ALERT(torrent_paused_alert);
{ return std::auto_ptr<alert>(new torrent_paused_alert(*this
)); }
virtual char const* what() const { return "torrent paused";
}
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 std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " paused"; }
return torrent_alert::message() + " paused";
}
}; };
struct TORRENT_EXPORT torrent_resumed_alert: torrent_alert struct TORRENT_EXPORT torrent_resumed_alert: torrent_alert
{ {
torrent_resumed_alert(torrent_handle const& h) torrent_resumed_alert(torrent_handle const& h)
: torrent_alert(h) {} : torrent_alert(h) {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(torrent_resumed_alert);
{ return std::auto_ptr<alert>(new torrent_resumed_alert(*thi
s)); }
virtual char const* what() const { return "torrent resumed";
}
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 std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " resumed"; }
return torrent_alert::message() + " resumed";
}
}; };
struct TORRENT_EXPORT torrent_checked_alert: torrent_alert struct TORRENT_EXPORT torrent_checked_alert: torrent_alert
{ {
torrent_checked_alert(torrent_handle const& h) torrent_checked_alert(torrent_handle const& h)
: torrent_alert(h) : torrent_alert(h)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(torrent_checked_alert);
{ return std::auto_ptr<alert>(new torrent_checked_alert(*thi
s)); }
virtual char const* what() const { return "torrent checked";
}
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 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
, std::string const& url_ , std::string const& url_
, error_code const& e) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, url(url_) , url(url_)
, msg(e.message()) , msg(e.message())
skipping to change at line 1034 skipping to change at line 845
url_seed_alert( url_seed_alert(
torrent_handle const& h torrent_handle const& h
, std::string const& url_ , std::string const& url_
, std::string const& msg_) , 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 TORRENT_DEFINE_ALERT(url_seed_alert);
{ return std::auto_ptr<alert>(new url_seed_alert(*this)); }
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 std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " url seed (" return torrent_alert::message() + " url seed ("
+ url + ") failed: " + msg; + url + ") failed: " + msg;
} }
std::string url; std::string url;
std::string msg; std::string msg;
}; };
skipping to change at line 1064 skipping to change at line 873
, error_code const& e) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, file(f) , file(f)
, error(e) , error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
std::string file; TORRENT_DEFINE_ALERT(file_error_alert);
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new file_error_alert(*this));
}
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 std::string message() const virtual std::string message() const
{ {
return torrent_alert::message() + " file (" + file + ") error: " return torrent_alert::message() + " file (" + file + ") error: "
+ error.message(); + error.message();
} }
std::string file;
error_code error;
#ifndef TORRENT_NO_DEPRECATE
std::string msg;
#endif
}; };
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 TORRENT_DEFINE_ALERT(metadata_failed_alert);
{ return std::auto_ptr<alert>(new metadata_failed_alert(*thi
s)); }
virtual char const* what() const { return "metadata failed";
}
const static int static_category = alert::error_notification ; const static int static_category = alert::error_notification ;
virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " invalid metadata recei
return torrent_alert::message() + " invalid metadata ved"; }
received";
}
}; };
struct TORRENT_EXPORT metadata_received_alert: torrent_alert struct TORRENT_EXPORT metadata_received_alert: torrent_alert
{ {
metadata_received_alert( metadata_received_alert(
const torrent_handle& h) const torrent_handle& h)
: torrent_alert(h) : torrent_alert(h)
{} {}
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(metadata_received_alert);
{ return std::auto_ptr<alert>(new metadata_received_alert(*t
his)); }
virtual char const* what() const { return "metadata received
"; }
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 std::string message() const virtual std::string message() const
{ { return torrent_alert::message() + " metadata successfully
return torrent_alert::message() + " metadata success received"; }
fully received";
}
}; };
struct TORRENT_EXPORT udp_error_alert: alert struct TORRENT_EXPORT udp_error_alert: alert
{ {
udp_error_alert( udp_error_alert(
udp::endpoint const& ep udp::endpoint const& ep
, error_code const& ec) , error_code const& ec)
: endpoint(ep) : endpoint(ep)
, error(ec) , error(ec)
{} {}
udp::endpoint endpoint; TORRENT_DEFINE_ALERT(udp_error_alert);
error_code error;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new udp_error_alert(*this)); }
virtual char const* what() const { return "udp error"; }
const static int static_category = alert::error_notification ; const static int static_category = alert::error_notification ;
virtual int category() const { return static_category; }
virtual std::string message() const virtual std::string message() const
{ {
error_code ec; error_code ec;
return "UDP error: " + error.message() + " from: " + endpoint.address().to_string(ec); return "UDP error: " + error.message() + " from: " + endpoint.address().to_string(ec);
} }
udp::endpoint endpoint;
error_code error;
}; };
struct TORRENT_EXPORT external_ip_alert: alert struct TORRENT_EXPORT external_ip_alert: alert
{ {
external_ip_alert(address const& ip) external_ip_alert(address const& ip)
: external_address(ip) : external_address(ip)
{} {}
address external_address; TORRENT_DEFINE_ALERT(external_ip_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new external_ip_alert(*this));
}
virtual char const* what() const { return "external IP recei
ved"; }
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 std::string message() const virtual std::string message() const
{ {
error_code ec; error_code ec;
return "external IP received: " + external_address.t o_string(ec); return "external IP received: " + external_address.t o_string(ec);
} }
address external_address;
}; };
struct TORRENT_EXPORT listen_failed_alert: alert struct TORRENT_EXPORT listen_failed_alert: alert
{ {
listen_failed_alert( listen_failed_alert(
tcp::endpoint const& ep tcp::endpoint const& ep
, error_code const& ec) , error_code const& ec)
: endpoint(ep) : endpoint(ep)
, error(ec) , error(ec)
{} {}
tcp::endpoint endpoint; TORRENT_DEFINE_ALERT(listen_failed_alert);
error_code error;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_failed_alert(*this)
); }
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 std::string message() const;
virtual std::string message() const virtual bool discardable() const { return false; }
{
char ret[200]; tcp::endpoint endpoint;
snprintf(ret, sizeof(ret), "listening on %s failed: error_code error;
%s"
, print_endpoint(endpoint).c_str(), error.me
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; TORRENT_DEFINE_ALERT(listen_succeeded_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new listen_succeeded_alert(*th
is)); }
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 std::string message() const;
virtual std::string message() const virtual bool discardable() const { return false; }
{
char ret[200]; tcp::endpoint endpoint;
snprintf(ret, sizeof(ret), "successfully listening o
n %s", print_endpoint(endpoint).c_str());
return ret;
}
}; };
struct TORRENT_EXPORT portmap_error_alert: alert struct TORRENT_EXPORT portmap_error_alert: alert
{ {
portmap_error_alert(int i, int t, error_code const& e) portmap_error_alert(int i, int t, error_code const& e)
: mapping(i), type(t), error(e) : mapping(i), map_type(t), error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
TORRENT_DEFINE_ALERT(portmap_error_alert);
const static int static_category = alert::port_mapping_notif
ication
| alert::error_notification;
virtual std::string message() const;
int mapping; int mapping;
int type; int map_type;
error_code error; error_code error;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif #endif
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_error_alert(*this)
); }
virtual char const* what() const { return "port map error";
}
const static int static_category = alert::port_mapping_notif
ication
| alert::error_notification;
virtual int category() const { return static_category; }
virtual std::string message() const
{
static char const* type_str[] = {"NAT-PMP", "UPnP"};
return std::string("could not map port using ") + ty
pe_str[type]
+ ": " + 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), map_type(t)
{} {}
int mapping; TORRENT_DEFINE_ALERT(portmap_alert);
int external_port;
int type;
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new portmap_alert(*this)); }
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 std::string message() const;
virtual std::string message() const
{ int mapping;
static char const* type_str[] = {"NAT-PMP", "UPnP"}; int external_port;
char ret[200]; int map_type;
snprintf(ret, sizeof(ret), "successfully mapped port
using %s. external port: %u"
, type_str[type], external_port);
return ret;
}
}; };
struct TORRENT_EXPORT portmap_log_alert: alert struct TORRENT_EXPORT portmap_log_alert: alert
{ {
portmap_log_alert(int t, std::string const& m) portmap_log_alert(int t, std::string const& m)
: type(t), msg(m) : map_type(t), msg(m)
{} {}
int type; TORRENT_DEFINE_ALERT(portmap_log_alert);
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; const static int static_category = alert::port_mapping_notif ication;
virtual int category() const { return static_category; } virtual std::string message() const;
virtual std::string message() const
{ int map_type;
static char const* type_str[] = {"NAT-PMP", "UPnP"}; std::string msg;
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
, error_code const& e) , error_code const& e)
: torrent_alert(h) : torrent_alert(h)
, error(e) , error(e)
{ {
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
msg = error.message(); msg = error.message();
#endif #endif
} }
TORRENT_DEFINE_ALERT(fastresume_rejected_alert);
const static int static_category = alert::status_notificatio
n
| alert::error_notification;
virtual std::string message() const
{ return torrent_alert::message() + " fast resume rejected:
" + error.message(); }
error_code error; error_code error;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
std::string msg; std::string msg;
#endif #endif
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new fastresume_rejected_alert(
*this)); }
virtual char const* what() const { return "resume data rejec
ted"; }
const static int static_category = alert::status_notificatio
n
| alert::error_notification;
virtual int category() const { return static_category; }
virtual std::string message() const
{
return torrent_alert::message() + " fast resume reje
cted: " + error.message();
}
}; };
struct TORRENT_EXPORT peer_blocked_alert: alert struct TORRENT_EXPORT peer_blocked_alert: torrent_alert
{ {
peer_blocked_alert(address const& ip_) peer_blocked_alert(torrent_handle const& h, address const& i
: ip(ip_) p_)
: torrent_alert(h)
, ip(ip_)
{} {}
address ip; TORRENT_DEFINE_ALERT(peer_blocked_alert);
virtual std::auto_ptr<alert> clone() const
{ return std::auto_ptr<alert>(new peer_blocked_alert(*this))
; }
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 std::string message() const virtual std::string message() const
{ {
error_code ec; error_code ec;
return "blocked peer: " + ip.to_string(ec); return torrent_alert::message() + ": blocked peer: " + ip.to_string(ec);
} }
address ip;
}; };
struct TORRENT_EXPORT dht_announce_alert: alert struct TORRENT_EXPORT dht_announce_alert: alert
{ {
dht_announce_alert(address const& ip_, int port_ dht_announce_alert(address const& ip_, int port_
, sha1_hash const& info_hash_) , sha1_hash const& info_hash_)
: ip(ip_) : ip(ip_)
, port(port_) , port(port_)
, info_hash(info_hash_) , info_hash(info_hash_)
{} {}
TORRENT_DEFINE_ALERT(dht_announce_alert);
const static int static_category = alert::dht_notification;
virtual std::string message() const;
address ip; address ip;
int port; int port;
sha1_hash info_hash; 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 struct TORRENT_EXPORT dht_get_peers_alert: alert
{ {
dht_get_peers_alert(sha1_hash const& info_hash_) dht_get_peers_alert(sha1_hash const& info_hash_)
: info_hash(info_hash_) : info_hash(info_hash_)
{} {}
sha1_hash info_hash; TORRENT_DEFINE_ALERT(dht_get_peers_alert);
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; const static int static_category = alert::dht_notification;
virtual int category() const { return static_category; } virtual std::string message() const;
virtual std::string message() const
{ sha1_hash info_hash;
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 struct TORRENT_EXPORT stats_alert: torrent_alert
{ {
stats_alert(torrent_handle const& h, int interval stats_alert(torrent_handle const& h, int interval
, stat const& s); , stat const& s);
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(stats_alert);
{ 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"; }
const static int static_category = alert::stats_notification ;
virtual std::string message() const; virtual std::string message() const;
enum stats_channel enum stats_channel
{ {
upload_payload, upload_payload,
upload_protocol, upload_protocol,
download_payload,
download_protocol,
#ifndef TORRENT_DISABLE_FULL_STATS
upload_ip_protocol, upload_ip_protocol,
upload_dht_protocol, upload_dht_protocol,
upload_tracker_protocol, upload_tracker_protocol,
download_payload,
download_protocol,
download_ip_protocol, download_ip_protocol,
download_dht_protocol, download_dht_protocol,
download_tracker_protocol, download_tracker_protocol,
#endif
num_channels num_channels
}; };
int transferred[num_channels]; int transferred[num_channels];
int interval; int interval;
}; };
struct TORRENT_EXPORT cache_flushed_alert: torrent_alert struct TORRENT_EXPORT cache_flushed_alert: torrent_alert
{ {
cache_flushed_alert(torrent_handle const& h); cache_flushed_alert(torrent_handle const& h);
virtual std::auto_ptr<alert> clone() const TORRENT_DEFINE_ALERT(cache_flushed_alert);
{ return std::auto_ptr<alert>(new cache_flushed_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 char const* what() const { return "cache_flushed_ale
rt"; }
}; };
struct TORRENT_EXPORT anonymous_mode_alert: torrent_alert
{
anonymous_mode_alert(torrent_handle const& h
, int kind_, std::string const& str_)
: torrent_alert(h)
, kind(kind_)
, str(str_)
{}
TORRENT_DEFINE_ALERT(anonymous_mode_alert);
const static int static_category = alert::error_notification
;
virtual std::string message() const;
enum kind_t
{
tracker_not_anonymous = 0
};
int kind;
std::string str;
};
struct TORRENT_EXPORT lsd_peer_alert: peer_alert
{
lsd_peer_alert(torrent_handle const& h
, tcp::endpoint const& ip_)
: peer_alert(h, ip_, peer_id(0))
{}
TORRENT_DEFINE_ALERT(lsd_peer_alert);
const static int static_category = alert::peer_notification;
virtual std::string message() const;
};
struct TORRENT_EXPORT trackerid_alert: tracker_alert
{
trackerid_alert(torrent_handle const& h
, std::string const& url_
, const std::string& id)
: tracker_alert(h, url_)
, trackerid(id)
{}
TORRENT_DEFINE_ALERT(trackerid_alert);
const static int static_category = alert::status_notificatio
n;
virtual std::string message() const;
std::string trackerid;
};
struct TORRENT_EXPORT dht_bootstrap_alert: alert
{
dht_bootstrap_alert() {}
TORRENT_DEFINE_ALERT(dht_bootstrap_alert);
const static int static_category = alert::dht_notification;
virtual std::string message() const;
};
struct TORRENT_EXPORT rss_alert: alert
{
rss_alert(feed_handle h, std::string const& url_, int state_
, error_code const& ec)
: handle(h), url(url_), state(state_), error(ec)
{}
TORRENT_DEFINE_ALERT(rss_alert);
const static int static_category = alert::rss_notification;
virtual std::string message() const;
enum state_t
{
state_updating, state_updated, state_error
};
feed_handle handle;
std::string url;
int state;
error_code error;
};
struct TORRENT_EXPORT torrent_error_alert: torrent_alert
{
torrent_error_alert(torrent_handle const& h
, error_code const& e)
: torrent_alert(h)
, error(e)
{}
TORRENT_DEFINE_ALERT(torrent_error_alert);
const static int static_category = alert::error_notification
| alert::status_notification;
virtual std::string message() const;
error_code error;
};
struct TORRENT_EXPORT torrent_need_cert_alert: torrent_alert
{
torrent_need_cert_alert(torrent_handle const& h)
: torrent_alert(h)
{}
TORRENT_DEFINE_ALERT(torrent_need_cert_alert);
const static int static_category = alert::status_notificatio
n;
virtual std::string message() const;
virtual bool discardable() const { return false; }
error_code error;
};
struct TORRENT_EXPORT incoming_connection_alert: alert
{
incoming_connection_alert(int type_, tcp::endpoint const& ip
_)
: socket_type(type_)
, ip(ip_)
{}
TORRENT_DEFINE_ALERT(incoming_connection_alert);
const static int static_category = alert::peer_notification;
virtual std::string message() const;
int socket_type;
tcp::endpoint ip;
};
struct TORRENT_EXPORT add_torrent_alert : torrent_alert
{
add_torrent_alert(torrent_handle h, add_torrent_params const
& p, error_code ec)
: torrent_alert(h)
, params(p)
, error(ec)
{}
TORRENT_DEFINE_ALERT(add_torrent_alert);
const static int static_category = alert::status_notificatio
n;
virtual std::string message() const;
virtual bool discardable() const { return false; }
add_torrent_params params;
error_code error;
};
struct TORRENT_EXPORT state_update_alert : alert
{
TORRENT_DEFINE_ALERT(state_update_alert);
const static int static_category = alert::status_notificatio
n;
virtual std::string message() const;
virtual bool discardable() const { return false; }
std::vector<torrent_status> status;
};
#undef TORRENT_DEFINE_ALERT
} }
#endif #endif
 End of changes. 169 change blocks. 
701 lines changed or deleted 473 lines changed or added


 alloca.hpp   alloca.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_ALLOCA #ifndef TORRENT_ALLOCA
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#ifdef TORRENT_WINDOWS #if defined TORRENT_WINDOWS
#include <malloc.h> #include <malloc.h>
#define TORRENT_ALLOCA(t, n) static_cast<t*>(_alloca(sizeof(t) * (n))) #define TORRENT_ALLOCA(t, n) static_cast<t*>(_alloca(sizeof(t) * (n)))
#elif defined TORRENT_BSD
#include <stdlib.h>
#define TORRENT_ALLOCA(t, n) static_cast<t*>(alloca(sizeof(t) * (n)))
#else #else
#include <alloca.h> #include <alloca.h>
#define TORRENT_ALLOCA(t, n) static_cast<t*>(alloca(sizeof(t) * (n))) #define TORRENT_ALLOCA(t, n) static_cast<t*>(alloca(sizeof(t) * (n)))
#endif #endif
#endif #endif
 End of changes. 3 change blocks. 
2 lines changed or deleted 6 lines changed or added


 allocator.hpp   allocator.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_ALLOCATOR_HPP_INCLUDED #ifndef TORRENT_ALLOCATOR_HPP_INCLUDED
#define TORRENT_ALLOCATOR_HPP_INCLUDED #define TORRENT_ALLOCATOR_HPP_INCLUDED
#include <cstddef> #include <cstddef>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
namespace libtorrent namespace libtorrent
{ {
TORRENT_EXPORT int page_size(); TORRENT_EXTRA_EXPORT int page_size();
struct TORRENT_EXPORT page_aligned_allocator struct TORRENT_EXTRA_EXPORT page_aligned_allocator
{ {
typedef std::size_t size_type; typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
static char* malloc(const size_type bytes); static char* malloc(const size_type bytes);
static void free(char* const block); static void free(char* const block);
}; };
struct TORRENT_EXTRA_EXPORT aligned_holder
{
aligned_holder(): m_buf(0) {}
aligned_holder(int size): m_buf(page_aligned_allocator::mall
oc(size)) {}
~aligned_holder() { if (m_buf) page_aligned_allocator::free(
m_buf); }
char* get() const { return m_buf; }
void reset(char* buf = 0)
{
if (m_buf) page_aligned_allocator::free(m_buf);
m_buf = buf;
}
void swap(aligned_holder& h)
{
char* tmp = m_buf;
m_buf = h.m_buf;
h.m_buf = tmp;
}
private:
char* m_buf;
};
} }
#endif #endif
 End of changes. 3 change blocks. 
2 lines changed or deleted 25 lines changed or added


 assert.hpp   assert.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_ASSERT #ifndef TORRENT_ASSERT
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#if !defined TORRENT_DEBUG #if (!defined TORRENT_DEBUG && !TORRENT_RELEASE_ASSERTS) \
|| TORRENT_NO_ASSERTS
#define TORRENT_ASSERT(a) do {} while(false) #define TORRENT_ASSERT(a) do {} while(false)
#define TORRENT_ASSERT_VAL(a, b) do {} while(false)
#else #else
#if TORRENT_PRODUCTION_ASSERTS
extern char const* libtorrent_assert_log;
#endif
#include <string> #include <string>
#ifdef __GNUC__
std::string demangle(char const* name); std::string demangle(char const* name);
void print_backtrace(char* out, int len, int max_depth = 0);
#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !TORRENT
_USE_SYSTEM_ASSERT
#if TORRENT_USE_IOSTREAM
#include <sstream>
#endif #endif
#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && defined TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* fil
TORRENT_DEBUG e
, char const* function, char const* val);
TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* fil #define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __F
e, char const* function); ILE__, __PRETTY_FUNCTION__, 0); } while (false)
#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __F #if TORRENT_USE_IOSTREAM
ILE__, __PRETTY_FUNCTION__); } while (false) #define TORRENT_ASSERT_VAL(x, y) do { if (x) {} else { std::stringstream __
s__; __s__ << #y ": " << y; assert_fail(#x, __LINE__, __FILE__, __PRETTY_FU
NCTION__, __s__.str().c_str()); } } while (false)
#else
#define TORRENT_ASSERT_VAL(x, y) TORRENT_ASSERT(x)
#endif
#else #else
#include <cassert> #include <cassert>
#define TORRENT_ASSERT(x) assert(x) #define TORRENT_ASSERT(x) assert(x)
#define TORRENT_ASSERT_VAL(x, y) assert(x)
#endif #endif
#endif #endif
#endif #endif
 End of changes. 8 change blocks. 
8 lines changed or deleted 27 lines changed or added


 bandwidth_limit.hpp   bandwidth_limit.hpp 
skipping to change at line 44 skipping to change at line 44
#define TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED #define TORRENT_BANDWIDTH_CHANNEL_HPP_INCLUDED
#include <boost/integer_traits.hpp> #include <boost/integer_traits.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent { namespace libtorrent {
// member of peer_connection // member of peer_connection
struct TORRENT_EXPORT bandwidth_channel struct TORRENT_EXTRA_EXPORT bandwidth_channel
{ {
static const int inf = boost::integer_traits<int>::const_max; static const int inf = boost::integer_traits<int>::const_max;
bandwidth_channel() bandwidth_channel();
: tmp(0)
, distribute_quota(0)
, m_quota_left(0)
, m_limit(0)
{}
// 0 means infinite // 0 means infinite
void throttle(int limit) void throttle(int limit);
{
TORRENT_ASSERT(limit >= 0);
// 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_limit; TORRENT_ASSERT_VAL(m_limit < INT_MAX, m_limit);
} return int(m_limit);
int quota_left() const
{
if (m_limit == 0) return inf;
return (std::max)(m_quota_left, boost::int64_t(0));
} }
void update_quota(int dt_milliseconds) int quota_left() const;
{ void update_quota(int dt_milliseconds);
if (m_limit == 0) return;
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, boost::int64_t(0
));
// fprintf(stderr, "%p: [%d]: + %"PRId64" limit: %"PRId64" quot
a_left: %"PRId64"\n", this
// , dt_milliseconds, (m_limit * dt_milliseconds + 500)
/ 1000, m_limit
// , m_quota_left);
}
// this is used when connections disconnect with // this is used when connections disconnect with
// some quota left. It's returned to its bandwidth // some quota left. It's returned to its bandwidth
// channels. // channels.
void return_quota(int amount) void return_quota(int amount);
{ void use_quota(int amount);
TORRENT_ASSERT(amount >= 0);
if (m_limit == 0) return;
TORRENT_ASSERT(m_quota_left <= m_quota_left + amount);
m_quota_left += amount;
}
void use_quota(int amount)
{
TORRENT_ASSERT(amount >= 0);
TORRENT_ASSERT(m_limit >= 0);
if (m_limit == 0) return;
// fprintf(stderr, "%p: - %"PRId64" limit: %"PRId64" quota_left
: %"PRId64"\n", this
// , amount, m_limit, m_quota_left);
m_quota_left -= amount;
}
// used as temporary storage while distributing // used as temporary storage while distributing
// bandwidth // bandwidth
int tmp; int tmp;
// this is the number of bytes to distribute this round // this is the number of bytes to distribute this round
int distribute_quota; int distribute_quota;
private: private:
 End of changes. 6 change blocks. 
54 lines changed or deleted 9 lines changed or added


 bandwidth_manager.hpp   bandwidth_manager.hpp 
skipping to change at line 43 skipping to change at line 43
#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/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#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/error_code.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"
#include "libtorrent/thread.hpp"
#include "libtorrent/bandwidth_socket.hpp"
#include "libtorrent/ptime.hpp"
using boost::intrusive_ptr; using boost::intrusive_ptr;
namespace libtorrent { namespace libtorrent {
template<class PeerConnection> struct TORRENT_EXTRA_EXPORT bandwidth_manager
struct bandwidth_manager
{ {
bandwidth_manager(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_queued_bytes(0)
, m_channel(channel)
, m_abort(false)
{
#ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT
if (log)
m_log.open("bandwidth_limiter.log", std::ios::trunc)
;
m_start = time_now();
#endif
}
void close() void close();
{
m_abort = true;
m_queue.clear();
m_queued_bytes = 0;
error_code ec;
}
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool is_queued(PeerConnection const* peer) const bool is_queued(bandwidth_socket const* peer) const;
{
for (typename queue_t::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
if (i->peer.get() == peer) return true;
}
return false;
}
#endif #endif
int queue_size() const int queue_size() const;
{ int queued_bytes() const;
return int(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 // returns the number of bytes to assign to the peer, or 0
// if the peer's 'assign_bandwidth' callback will be called later
int request_bandwidth(intrusive_ptr<bandwidth_socket> const& peer
, int blk, int priority , int blk, int priority
, bandwidth_channel* chan1 = 0 , bandwidth_channel* chan1 = 0
, bandwidth_channel* chan2 = 0 , bandwidth_channel* chan2 = 0
, bandwidth_channel* chan3 = 0 , bandwidth_channel* chan3 = 0
, bandwidth_channel* chan4 = 0 , bandwidth_channel* chan4 = 0
, bandwidth_channel* chan5 = 0 , bandwidth_channel* chan5 = 0);
)
{
INVARIANT_CHECK;
if (m_abort) return;
TORRENT_ASSERT(blk > 0);
TORRENT_ASSERT(priority > 0);
TORRENT_ASSERT(!is_queued(peer.get()));
bw_request<PeerConnection> bwr(peer, blk, 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)
{
// the connection is not rate limited by any of its
// 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_queued_bytes += blk;
m_queue.push_back(bwr);
}
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const void check_invariant() const;
{
int queued = 0;
for (typename queue_t::const_iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
queued += i->request_size - i->assigned;
}
TORRENT_ASSERT(queued == m_queued_bytes);
}
#endif #endif
void update_quotas(time_duration const& dt) void update_quotas(time_duration const& dt);
{
if (m_abort) return;
if (m_queue.empty()) return;
INVARIANT_CHECK;
int dt_milliseconds = total_milliseconds(dt);
if (dt_milliseconds > 3000) dt_milliseconds = 3000;
// for each bandwidth channel, call update_quota(dt)
std::vector<bandwidth_channel*> channels;
for (typename queue_t::iterator i = m_queue.begin();
i != m_queue.end();)
{
if (i->peer->is_disconnecting())
{
m_queued_bytes -= i->request_size - i->assig
ned;
// return all assigned quota to all the
// bandwidth channels this peer belongs to
for (int j = 0; j < 5 && i->channel[j]; ++j)
{
bandwidth_channel* bwc = i->channel[
j];
bwc->return_quota(i->assigned);
}
i = m_queue.erase(i);
continue;
}
for (int j = 0; j < 5 && i->channel[j]; ++j)
{
bandwidth_channel* bwc = i->channel[j];
bwc->tmp = 0;
}
++i;
}
for (typename queue_t::iterator i = m_queue.begin()
, end(m_queue.end()); i != end; ++i)
{
for (int j = 0; j < 5 && i->channel[j]; ++j)
{
bandwidth_channel* bwc = i->channel[j];
if (bwc->tmp == 0) channels.push_back(bwc);
bwc->tmp += i->priority;
TORRENT_ASSERT(i->priority > 0);
}
}
for (std::vector<bandwidth_channel*>::iterator i = channels.
begin()
, end(channels.end()); i != end; ++i)
{
(*i)->update_quota(dt_milliseconds);
}
queue_t tm;
for (typename queue_t::iterator i = m_queue.begin();
i != m_queue.end();)
{
int a = i->assign_bandwidth();
if (i->assigned == i->request_size
|| (i->ttl <= 0 && i->assigned > 0))
{
a += i->request_size - i->assigned;
TORRENT_ASSERT(i->assigned <= i->request_siz
e);
tm.push_back(*i);
i = m_queue.erase(i);
}
else
{
++i;
}
m_queued_bytes -= a;
}
while (!tm.empty())
{
bw_request<PeerConnection>& bwr = tm.back();
bwr.peer->assign_bandwidth(m_channel, bwr.assigned);
tm.pop_back();
}
}
// these are the consumers that want bandwidth // these are the consumers that want bandwidth
typedef std::vector<bw_request<PeerConnection> &gt; queue_t; typedef std::vector<bw_request> queue_t;
queue_t m_queue; queue_t m_queue;
// the number of bytes all the requests in queue are for // the number of bytes all the requests in queue are for
int m_queued_bytes; int m_queued_bytes;
// 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;
bool m_abort; bool m_abort;
 End of changes. 12 change blocks. 
176 lines changed or deleted 18 lines changed or added


 bandwidth_queue_entry.hpp   bandwidth_queue_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_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" #include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/bandwidth_socket.hpp"
namespace libtorrent { namespace libtorrent {
template<class PeerConnection> struct TORRENT_EXTRA_EXPORT bw_request
struct bw_request
{ {
bw_request(boost::intrusive_ptr<PeerConnection> const& pe bw_request(boost::intrusive_ptr<bandwidth_socket> const& pe
, int blk, int prio) , int blk, int prio);
: peer(pe)
, 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<bandwidth_socket> peer;
// 1 is normal prio // 1 is normal prio
int priority; int priority;
// the number of bytes assigned to this request so far // the number of bytes assigned to this request so far
int assigned; int assigned;
// once assigned reaches this, we dispatch the request function // once assigned reaches this, we dispatch the request function
int request_size; int request_size;
// the max number of rounds for this request to survive // the max number of rounds for this request to survive
// this ensures that requests gets responses at very low // this ensures that requests gets responses at very low
// rate limits, when the requested size would take a long // rate limits, when the requested size would take a long
// time to satisfy // time to satisfy
int ttl; int ttl;
// loops over the bandwidth channels and assigns bandwidth // loops over the bandwidth channels and assigns bandwidth
// from the most limiting one // from the most limiting one
int assign_bandwidth() 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]; bandwidth_channel* channel[5];
}; };
} }
#endif #endif
 End of changes. 5 change blocks. 
34 lines changed or deleted 6 lines changed or added


 bencode.hpp   bencode.hpp 
skipping to change at line 97 skipping to change at line 97
{ {
template <class OutIt> template <class OutIt>
int write_string(OutIt& out, const std::string& val) int write_string(OutIt& out, const std::string& val)
{ {
for (std::string::const_iterator i = val.begin() for (std::string::const_iterator i = val.begin()
, end(val.end()); i != end; ++i) , end(val.end()); i != end; ++i)
*out++ = *i; *out++ = *i;
return int(val.length()); return int(val.length());
} }
TORRENT_EXPORT char const* integer_to_str(char* buf, int siz e, entry::integer_type val); TORRENT_EXTRA_EXPORT char const* integer_to_str(char* buf, i nt size, entry::integer_type val);
template <class OutIt> template <class OutIt>
int write_integer(OutIt& out, entry::integer_type val) int write_integer(OutIt& out, entry::integer_type val)
{ {
// the stack allocated buffer for keeping the // the stack allocated buffer for keeping the
// decimal representation of the number can // decimal representation of the number can
// not hold number bigger than this: // not hold number bigger than this:
BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8 ); BOOST_STATIC_ASSERT(sizeof(entry::integer_type) <= 8 );
char buf[21]; char buf[21];
int ret = 0; int ret = 0;
skipping to change at line 206 skipping to change at line 206
write_char(out, ':'); write_char(out, ':');
ret += write_string(out, i->first); ret += write_string(out, i->first);
// write value // write value
ret += bencode_recursive(out, i->sec ond); ret += bencode_recursive(out, i->sec ond);
ret += 1; ret += 1;
} }
write_char(out, 'e'); write_char(out, 'e');
ret += 2; ret += 2;
break; break;
default: default:
// trying to encode a structure with uniniti
alized values!
TORRENT_ASSERT_VAL(false, e.type());
// do nothing // do nothing
break; break;
} }
return ret; return ret;
} }
template<class InIt> template<class InIt>
void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth) void bdecode_recursive(InIt& in, InIt end, entry& ret, bool& err, int depth)
{ {
if (depth >= 100) if (depth >= 100)
 End of changes. 2 change blocks. 
1 lines changed or deleted 4 lines changed or added


 bitfield.hpp   bitfield.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#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 #include <cstdlib> // for malloc, free and realloc
#include <boost/cstdint.hpp> // uint32_t
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), m_own(false) bitfield(int bits): m_bytes(0), m_size(0), m_own(false)
{ resize(bits); } { resize(bits); }
bitfield(int bits, bool val): m_bytes(0), m_size(0), m_own(f alse) bitfield(int bits, bool val): m_bytes(0), m_size(0), m_own(f alse)
{ resize(bits, val); } { resize(bits, val); }
skipping to change at line 225 skipping to change at line 226
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)
{ {
TORRENT_ASSERT(bits >= 0);
const int b = (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, b); 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)
{ {
 End of changes. 2 change blocks. 
0 lines changed or deleted 2 lines changed or added


 broadcast_socket.hpp   broadcast_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_BROADCAST_SOCKET_HPP_INCLUDED #ifndef TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED #define TORRENT_BROADCAST_SOCKET_HPP_INCLUDED
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/io_service_fwd.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/error_code.hpp"
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/function.hpp> #include <boost/function/function3.hpp>
#include <list> #include <list>
namespace libtorrent namespace libtorrent
{ {
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 TORRENT_EXPORT bool is_teredo(address const& addr);
2); TORRENT_EXTRA_EXPORT int cidr_distance(address const& a1, address co
nst& a2);
// determines if the operating system supports IPv6 // determines if the operating system supports IPv6
TORRENT_EXPORT bool supports_ipv6(); TORRENT_EXPORT bool supports_ipv6();
TORRENT_EXPORT int common_bits(unsigned char const* b1 TORRENT_EXTRA_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_EXTRA_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); enum flags_t { broadcast = 1 };
void send(char const* buffer, int size, error_code& ec, int
flags = 0);
void close(); void close();
int num_send_sockets() const { return m_unicast_sockets.size (); } int num_send_sockets() const { return m_unicast_sockets.size (); }
void enable_ip_broadcast(bool e); void enable_ip_broadcast(bool e);
private: private:
struct socket_entry struct socket_entry
{ {
socket_entry(boost::shared_ptr<datagram_socket> cons t& s) socket_entry(boost::shared_ptr<datagram_socket> cons t& s)
: socket(s) {} : socket(s), broadcast(false) {}
socket_entry(boost::shared_ptr<datagram_socket> cons t& s socket_entry(boost::shared_ptr<datagram_socket> cons t& s
, address_v4 const& mask): socket(s), netmas k(mask) {} , address_v4 const& mask): socket(s), netmas k(mask), broadcast(false) {}
boost::shared_ptr<datagram_socket> socket; boost::shared_ptr<datagram_socket> socket;
char buffer[1024]; char buffer[1500];
udp::endpoint remote; udp::endpoint remote;
address_v4 netmask; address_v4 netmask;
bool broadcast;
void close() void close()
{ {
if (!socket) return; if (!socket) return;
error_code ec; error_code ec;
socket->close(ec); socket->close(ec);
} }
bool can_broadcast() const
{
error_code ec;
return broadcast
&& netmask != address_v4()
&& socket->local_endpoint(ec).addres
s().is_v4();
}
address_v4 broadcast_address() const address_v4 broadcast_address() const
{ {
error_code ec; error_code ec;
#if BOOST_VERSION < 104700
return address_v4(socket->local_endpoint(ec)
.address().to_v4().to_ulong() | ((~netmask.to_ulong()) & 0xffffffff));
#else
return address_v4::broadcast(socket->local_e ndpoint(ec).address().to_v4(), netmask); return address_v4::broadcast(socket->local_e ndpoint(ec).address().to_v4(), netmask);
#endif
} }
}; };
void on_receive(socket_entry* s, error_code const& ec void on_receive(socket_entry* s, error_code const& ec
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void open_unicast_socket(io_service& ios, address const& add r void open_unicast_socket(io_service& ios, address const& add r
, address_v4 const& mask); , address_v4 const& mask);
void open_multicast_socket(io_service& ios, address const& a ddr void open_multicast_socket(io_service& ios, address const& a ddr
, bool loopback, error_code& ec); , bool loopback, error_code& ec);
// if we're aborting, destruct the handler and return true
bool maybe_abort();
// these sockets are used to // these sockets are used to
// join the multicast group (on each interface) // join the multicast group (on each interface)
// and receive multicast messages // and receive multicast messages
std::list<socket_entry> m_sockets; std::list<socket_entry> m_sockets;
// these sockets are not bound to any // these sockets are not bound to any
// specific port and are used to // specific port and are used to
// send messages to the multicast group // send messages to the multicast group
// and receive unicast responses // and receive unicast responses
std::list<socket_entry> m_unicast_sockets; std::list<socket_entry> m_unicast_sockets;
udp::endpoint m_multicast_endpoint; udp::endpoint m_multicast_endpoint;
receive_handler_t m_on_receive; receive_handler_t m_on_receive;
// if set, use IP broadcast as well as IP multicast // the number of outstanding async operations
// this is off by default because it's expensive in // we have on these sockets. The m_on_receive
// terms of bandwidth usage // handler may not be destructed until this reaches
bool m_ip_broadcast; // 0, since it may be holding references to
// the broadcast_socket itself.
int m_outstanding_operations;
// when set to true, we're trying to shut down
// don't initiate new operations and once the
// outstanding counter reaches 0, destruct
// the handler object
bool m_abort;
}; };
} }
#endif #endif
 End of changes. 16 change blocks. 
14 lines changed or deleted 44 lines changed or added


 bt_peer_connection.hpp   bt_peer_connection.hpp 
skipping to change at line 62 skipping to change at line 62
#include <boost/cstdint.hpp> #include <boost/cstdint.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/peer_connection.hpp" #include "libtorrent/peer_connection.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/stat.hpp" #include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/pe_crypto.hpp" #include "libtorrent/pe_crypto.hpp"
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
namespace detail namespace detail
{ {
struct session_impl; struct session_impl;
} }
class TORRENT_EXPORT bt_peer_connection class TORRENT_EXTRA_EXPORT bt_peer_connection
: public peer_connection : public peer_connection
{ {
friend class invariant_access; friend class invariant_access;
public: public:
// this is the constructor where the we are the active part. // this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the // The peer_conenction should handshake and verify that the
// other end has the correct id // other end has the correct id
bt_peer_connection( bt_peer_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::weak_ptr<torrent> t , boost::weak_ptr<torrent> t
, 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
, bool outgoing = true);
// 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 { enum
{
upload_only_msg = 2, upload_only_msg = 2,
dont_have_msg = 5 holepunch_msg = 3,
share_mode_msg = 4,
dont_have_msg = 5,
}; };
~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; }
bool rc4_encrypted() const
{ return m_rc4_encrypted; }
#endif #endif
virtual int type() const { return peer_connection::bittorren
t_connection; }
enum message_type enum message_type
{ {
// standard messages // standard messages
msg_choke = 0, msg_choke = 0,
msg_unchoke, msg_unchoke,
msg_interested, msg_interested,
msg_not_interested, msg_not_interested,
msg_have, msg_have,
msg_bitfield, msg_bitfield,
msg_request, msg_request,
skipping to change at line 146 skipping to change at line 152
msg_have_none, msg_have_none,
msg_reject_request, msg_reject_request,
msg_allowed_fast, msg_allowed_fast,
// extension protocol message // extension protocol message
msg_extended = 20, msg_extended = 20,
num_supported_messages num_supported_messages
}; };
enum hp_message_t
{
// msg_types
hp_rendezvous = 0,
hp_connect = 1,
hp_failed = 2,
// error codes
hp_no_such_peer = 1,
hp_not_connected = 2,
hp_no_support = 3,
hp_no_self = 4
};
// called from the main loop when this connection has any // called from the main loop when this connection has any
// work to do. // work to do.
void on_sent(error_code const& error void on_sent(error_code const& error
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void on_receive(error_code const& error void on_receive(error_code const& error
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
virtual void get_specific_peer_info(peer_info& p) const; virtual void get_specific_peer_info(peer_info& p) const;
virtual bool in_handshake() const; virtual bool in_handshake() const;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
bool support_extensions() const { return m_supports_extensio bool supports_holepunch() const { return m_holepunch_id != 0
ns; } ; }
template <class T>
T* supports_extension() const
{
for (extension_list_t::const_iterator i = m_extensio
ns.begin()
, end(m_extensions.end()); i != end; ++i)
{
T* ret = dynamic_cast<T*>(i->get());
if (ret) return ret;
}
return 0;
}
#endif #endif
bool support_extensions() const { return m_supports_extensio
ns; }
// the message handlers are called // the message handlers are called
// each time a recv() returns some new // each time a recv() returns some new
// data, the last time it will be called // data, the last time it will be called
// is when the entire packet has been // is when the entire packet has been
// received, then it will no longer // received, then it will no longer
// be called. i.e. most handlers need // be called. i.e. most handlers need
// to check how much of the packet they // to check how much of the packet they
// have received before any processing // have received before any processing
void on_keepalive(); void on_keepalive();
void on_choke(int received); void on_choke(int received);
skipping to change at line 201 skipping to change at line 211
// DHT extension // DHT extension
void on_dht_port(int received); void on_dht_port(int received);
// FAST extension // FAST extension
void on_suggest_piece(int received); void on_suggest_piece(int received);
void on_have_all(int received); void on_have_all(int received);
void on_have_none(int received); void on_have_none(int received);
void on_reject_request(int received); void on_reject_request(int received);
void on_allowed_fast(int received); void on_allowed_fast(int received);
#ifndef TORRENT_DISABLE_EXTENSIONS
void on_holepunch();
#endif
void on_extended(int received); void on_extended(int received);
void on_extended_handshake(); void on_extended_handshake();
typedef void (bt_peer_connection::*message_handler)(int rece ived); typedef void (bt_peer_connection::*message_handler)(int rece ived);
// the following functions appends messages // the following functions appends messages
// to the send buffer // to the send buffer
void write_choke(); void write_choke();
skipping to change at line 223 skipping to change at line 236
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(); void write_upload_only();
void write_share_mode();
void write_holepunch_msg(int type, tcp::endpoint const& ep,
int error);
#endif #endif
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();
void write_reject_request(peer_request const&); void write_reject_request(peer_request const&);
void write_allow_fast(int piece); void write_allow_fast(int piece);
void write_suggest(int piece);
void on_connected(); void on_connected();
void on_metadata(); void on_metadata();
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
ptime m_last_choke; ptime m_last_choke;
#endif #endif
private: private:
skipping to change at line 269 skipping to change at line 285
// 1. a -> b dhkey, pad // 1. a -> b dhkey, pad
// 2. b -> a dhkey, pad // 2. b -> a dhkey, pad
// 3. a -> b sync, payload // 3. a -> b sync, payload
// 4. b -> a sync, payload // 4. b -> a sync, payload
// 5. a -> b payload // 5. a -> b payload
void write_pe1_2_dhkey(); void write_pe1_2_dhkey();
void write_pe3_sync(); void write_pe3_sync();
void write_pe4_sync(int crypto_select); void write_pe4_sync(int crypto_select);
void write_pe_vc_cryptofield(buffer::interval& write_buf void write_pe_vc_cryptofield(char* write_buf, int len
, int crypto_field, int pad_size); , int crypto_field, int pad_size);
// 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_enc_handler
void init_pe_RC4_handler(char const* secret, sha1_hash const void init_pe_rc4_handler(char const* secret, sha1_hash const
& stream_key); & 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); virtual void append_const_send_buffer(char const* buffer, in t size);
void send_buffer(char const* buf, int size, int flags = 0); virtual void send_buffer(char const* begin, int size, int fl
buffer::interval allocate_send_buffer(int size); ags = 0
, void (*fun)(char*, int, void*) = 0, void* userdata
= 0);
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)
{ m_enc_handler->encrypt(buffer, size);
TORRENT_ASSERT(send_buffer_size() == m_encry
pted_bytes);
m_RC4_handler->encrypt(buffer, size);
#ifdef TORRENT_DEBUG
m_encrypted_bytes += size;
TORRENT_ASSERT(m_encrypted_bytes == send_buf
fer_size() + size);
#endif
}
#endif #endif
peer_connection::append_send_buffer(buffer, size, de structor); peer_connection::append_send_buffer(buffer, size, de structor, true);
} }
void setup_send();
private: private:
void encrypt_pending_buffer();
// Returns offset at which bytestream (src, src + src_size) // Returns offset at which bytestream (src, src + src_size)
// matches bytestream(target, target + target_size). // matches bytestream(target, target + target_size).
// If no sync found, return -1 // If no sync found, return -1
int get_syncoffset(char const* src, int src_size int get_syncoffset(char const* src, int src_size
, char const* target, int target_size) const; , char const* target, int target_size) const;
#endif #endif
enum state enum state
{ {
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
skipping to change at line 373 skipping to change at line 379
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::vector<range> m_payloads; std::vector<range> m_payloads;
// we have suggested these pieces to the peer
// don't suggest it again
bitfield m_sent_suggested_pieces;
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
// the message ID for upload only message // the message ID for upload only message
// 0 if not supported // 0 if not supported
int m_upload_only_id; boost::uint8_t m_upload_only_id;
// the message ID for holepunch messages
boost::uint8_t m_holepunch_id;
// the message ID for don't-have message // the message ID for don't-have message
boost::uint8_t m_dont_have_id; boost::uint8_t m_dont_have_id;
// the message ID for share mode message
// 0 if not supported
boost::uint8_t m_share_mode_id;
char m_reserved_bits[8]; char m_reserved_bits[8];
#endif
// 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:1; bool m_supports_extensions:1;
#endif
bool m_supports_dht_port:1; bool m_supports_dht_port:1;
bool m_supports_fast:1; 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;
// used to disconnect peer if sync points are not found with in // used to disconnect peer if sync points are not found with in
// the maximum number of bytes // the maximum number of bytes
int m_sync_bytes_read; int m_sync_bytes_read;
// hold information about latest allocated send buffer
// need to check for non zero (begin, end) for operations wi
th this
buffer::interval m_enc_send_buffer;
// initialized during write_pe1_2_dhkey, and destroyed on // initialized during write_pe1_2_dhkey, and destroyed on
// creation of m_RC4_handler. Cannot reinitialize once // creation of m_enc_handler. Cannot reinitialize once
// initialized. // initialized.
boost::scoped_ptr<dh_key_exchange> m_dh_key_exchange; boost::scoped_ptr<dh_key_exchange> m_dh_key_exchange;
// if RC4 is negotiated, this is used for // if encryption is negotiated, this is used for
// encryption/decryption during the entire session. Destroye d // encryption/decryption during the entire session. Destroye d
// if plaintext is selected // if plaintext is selected
boost::scoped_ptr<RC4_handler> m_RC4_handler; boost::scoped_ptr<encryption_handler> m_enc_handler;
// (outgoing only) synchronize verification constant with // (outgoing only) synchronize verification constant with
// remote peer, this will hold RC4_decrypt(vc). Destroyed // remote peer, this will hold rc4_decrypt(vc). Destroyed
// after the sync step. // after the sync step.
boost::scoped_array<char> m_sync_vc; boost::scoped_array<char> m_sync_vc;
// (incoming only) synchronize hash with remote peer, holds // (incoming only) synchronize hash with remote peer, holds
// the sync hash (hash("req1",secret)). Destroyed after the // the sync hash (hash("req1",secret)). Destroyed after the
// sync step. // sync step.
boost::scoped_ptr<sha1_hash> m_sync_hash; boost::scoped_ptr<sha1_hash> m_sync_hash;
#endif // #ifndef TORRENT_DISABLE_ENCRYPTION #endif // #ifndef TORRENT_DISABLE_ENCRYPTION
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
// this is set to true when the client's // this is set to true when the client's
// 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
// that have been encrypted (only used for
// encrypted connections)
public:
int m_encrypted_bytes;
#endif #endif
}; };
} }
#endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_BT_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 33 change blocks. 
59 lines changed or deleted 67 lines changed or added


 buffer.hpp   buffer.hpp 
skipping to change at line 35 skipping to change at line 35
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 LIBTORRENT_BUFFER_HPP #ifndef LIBTORRENT_BUFFER_HPP
#define LIBTORRENT_BUFFER_HPP #define LIBTORRENT_BUFFER_HPP
#include <memory>
#include <cstring> #include <cstring>
#include "libtorrent/invariant_check.hpp" #include "libtorrent/invariant_check.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include <cstdlib> // malloc/free/realloc
namespace libtorrent { namespace libtorrent {
class buffer class buffer
{ {
public: public:
struct interval struct interval
{ {
interval() interval()
: begin(0) : begin(0)
 End of changes. 2 change blocks. 
1 lines changed or deleted 1 lines changed or added


 chained_buffer.hpp   chained_buffer.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_CHAINED_BUFFER_HPP_INCLUDED #ifndef TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#define TORRENT_CHAINED_BUFFER_HPP_INCLUDED #define TORRENT_CHAINED_BUFFER_HPP_INCLUDED
#include <boost/function.hpp> #include "libtorrent/config.hpp"
#include <boost/function/function1.hpp>
#include <boost/version.hpp> #include <boost/version.hpp>
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/buffer.hpp> #include <asio/buffer.hpp>
#else #else
#include <boost/asio/buffer.hpp> #include <boost/asio/buffer.hpp>
#endif #endif
#include <list> #include <list>
#include <string.h> // for memcpy #include <string.h> // for memcpy
namespace libtorrent namespace libtorrent
{ {
#if BOOST_VERSION >= 103500 #if BOOST_VERSION >= 103500
namespace asio = boost::asio; namespace asio = boost::asio;
#endif #endif
struct chained_buffer struct TORRENT_EXTRA_EXPORT chained_buffer
{ {
chained_buffer(): m_bytes(0), m_capacity(0) {} chained_buffer(): m_bytes(0), m_capacity(0)
{
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
m_destructed = false;
#endif
}
struct buffer_t struct buffer_t
{ {
boost::function<void(char*)> free; // destructs the buffer boost::function<void(char*)> free; // destructs the buffer
char* buf; // the first byte of the buffer char* buf; // the first byte of the buffer
int size; // the total size of the buffer int size; // the total size of the buffer
char* start; // the first byte to send/receive in th e buffer char* start; // the first byte to send/receive in th e buffer
int used_size; // this is the number of bytes to sen d/receive int used_size; // this is the number of bytes to sen d/receive
}; };
bool empty() const { return m_bytes == 0; } bool empty() const { return m_bytes == 0; }
int size() const { return m_bytes; } int size() const { return m_bytes; }
int capacity() const { return m_capacity; } int capacity() const { return m_capacity; }
void pop_front(int bytes_to_pop) void pop_front(int bytes_to_pop);
{
TORRENT_ASSERT(bytes_to_pop <= m_bytes);
while (bytes_to_pop > 0 && !m_vec.empty())
{
buffer_t& b = m_vec.front();
if (b.used_size > bytes_to_pop)
{
b.start += bytes_to_pop;
b.used_size -= bytes_to_pop;
m_bytes -= bytes_to_pop;
TORRENT_ASSERT(m_bytes <= m_capacity
);
TORRENT_ASSERT(m_bytes >= 0);
TORRENT_ASSERT(m_capacity >= 0);
break;
}
b.free(b.buf);
m_bytes -= b.used_size;
m_capacity -= b.size;
bytes_to_pop -= b.used_size;
TORRENT_ASSERT(m_bytes >= 0);
TORRENT_ASSERT(m_capacity >= 0);
TORRENT_ASSERT(m_bytes <= m_capacity);
m_vec.pop_front();
}
}
template <class D>
void append_buffer(char* buffer, int s, int used_size, D con
st& destructor)
{
TORRENT_ASSERT(s >= used_size);
buffer_t b;
b.buf = buffer;
b.size = s;
b.start = buffer;
b.used_size = used_size;
b.free = destructor;
m_vec.push_back(b);
m_bytes += used_size; void append_buffer(char* buffer, int s, int used_size
m_capacity += s; , boost::function<void(char*)> const& destructor);
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;
buffer_t& b = m_vec.back();
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 s) char* append(char const* buf, int s);
{
char* insert = allocate_appendix(s);
if (insert == 0) return false;
memcpy(insert, buf, s);
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 s) char* allocate_appendix(int s);
{
if (m_vec.empty()) return 0;
buffer_t& b = m_vec.back();
char* insert = b.start + b.used_size;
if (insert + s > b.buf + b.size) return 0;
b.used_size += s;
m_bytes += s;
TORRENT_ASSERT(m_bytes <= m_capacity);
return insert;
}
std::list<asio::const_buffer> const& build_iovec(int to_send
)
{
m_tmp_vec.clear();
for (std::list<buffer_t>::iterator i = m_vec.begin() std::list<asio::const_buffer> const& build_iovec(int to_send
, end(m_vec.end()); to_send > 0 && i != end; );
++i)
{
if (i->used_size > to_send)
{
TORRENT_ASSERT(to_send > 0);
m_tmp_vec.push_back(asio::const_buff
er(i->start, to_send));
break;
}
TORRENT_ASSERT(i->used_size > 0);
m_tmp_vec.push_back(asio::const_buffer(i->st
art, i->used_size));
to_send -= i->used_size;
}
return m_tmp_vec;
}
~chained_buffer() ~chained_buffer();
{
for (std::list<buffer_t>::iterator i = m_vec.begin()
, end(m_vec.end()); i != end; ++i)
{
i->free(i->buf);
}
}
private: private:
// this is the list of all the buffers we want to // this is the list of all the buffers we want to
// send // send
std::list<buffer_t> m_vec; std::list<buffer_t> m_vec;
// this is the number of bytes in the send buf. // this is the number of bytes in the send buf.
// this will always be equal to the sum of the // this will always be equal to the sum of the
// size of all buffers in vec // size of all buffers in vec
int m_bytes; int m_bytes;
// the total size of all buffers in the chain // the total size of all buffers in the chain
// including unused space // including unused space
int m_capacity; int m_capacity;
// this is the vector of buffers used when // this is the vector of buffers used when
// invoking the async write call // invoking the async write call
std::list<asio::const_buffer> m_tmp_vec; std::list<asio::const_buffer> m_tmp_vec;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool m_destructed;
#endif
}; };
} }
#endif #endif
 End of changes. 11 change blocks. 
103 lines changed or deleted 23 lines changed or added


 config.hpp   config.hpp 
skipping to change at line 41 skipping to change at line 41
*/ */
#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 #include <stdio.h> // for snprintf
#include <limits.h> // for IOV_MAX #include <limits.h> // for IOV_MAX
#ifndef WIN32 #if defined TORRENT_DEBUG_BUFFERS && !defined TORRENT_DISABLE_POOL_ALLOCATO
R
#error TORRENT_DEBUG_BUFFERS only works if you also disable pool allocators
with TORRENT_DISABLE_POOL_ALLOCATOR
#endif
#if !defined BOOST_ASIO_SEPARATE_COMPILATION && !defined BOOST_ASIO_DYN_LIN
K
#error you must define either BOOST_ASIO_SEPARATE_COMPILATION or BOOST_ASIO
_DYN_LINK in your project in \
order for asio's declarations to be correct. If you're linking dynam
ically against libtorrent, define \
BOOST_ASIO_DYN_LINK otherwise BOOST_ASIO_SEPARATE_COMPILATION. You c
an also use pkg-config or boost \
build, to automatically apply these defines
#endif
#ifndef _MSC_VER
#define __STDC_FORMAT_MACROS #define __STDC_FORMAT_MACROS
#include <inttypes.h> #include <inttypes.h>
#endif #endif
#ifndef PRId64 #ifndef PRId64
// MinGW uses microsofts runtime // MinGW uses microsofts runtime
#if defined _MSC_VER || defined __MINGW32__ #if defined _MSC_VER || defined __MINGW32__
#define PRId64 "I64d" #define PRId64 "I64d"
#define PRIu64 "I64u"
#define PRIu32 "u"
#else #else
#define PRId64 "lld" #define PRId64 "lld"
#define PRIu64 "llu"
#define PRIu32 "u"
#endif #endif
#endif #endif
// backwards compatibility with older versions of boost
#if !defined BOOST_SYMBOL_EXPORT && !defined BOOST_SYMBOL_IMPORT
# if defined _MSC_VER || defined __MINGW32__
# define BOOST_SYMBOL_EXPORT __declspec(dllexport)
# define BOOST_SYMBOL_IMPORT __declspec(dllimport)
# elif __GNU__ >= 4
# define BOOST_SYMBOL_EXPORT __attribute__((visibility("default")))
# define BOOST_SYMBOL_IMPORT __attribute__((visibility("default")))
# else
# define BOOST_SYMBOL_EXPORT
# define BOOST_SYMBOL_IMPORT
# endif
#endif
#if defined TORRENT_BUILDING_SHARED
# define TORRENT_EXPORT BOOST_SYMBOL_EXPORT
#elif defined TORRENT_LINKING_SHARED
# define TORRENT_EXPORT BOOST_SYMBOL_IMPORT
#endif
// when this is specified, export a bunch of extra
// symbols, mostly for the unit tests to reach
#if TORRENT_EXPORT_EXTRA
# if defined TORRENT_BUILDING_SHARED
# define TORRENT_EXTRA_EXPORT BOOST_SYMBOL_EXPORT
# elif defined TORRENT_LINKING_SHARED
# define TORRENT_EXTRA_EXPORT BOOST_SYMBOL_IMPORT
# endif
#endif
#ifndef TORRENT_EXTRA_EXPORT
# define TORRENT_EXTRA_EXPORT
#endif
// ======= GCC ========= // ======= GCC =========
#if defined __GNUC__ #if defined __GNUC__
# define TORRENT_DEPRECATED __attribute__ ((deprecated)) # if __GNUC__ >= 3
# 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
# define TORRENT_EXPORT
# endif # endif
// ======= SUNPRO ========= // ======= SUNPRO =========
#elif defined __SUNPRO_CC #elif defined __SUNPRO_CC
# if __SUNPRO_CC >= 0x550 // SunPRO seems to have an overly-strict
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED) // definition of POD types and doesn't
# define TORRENT_EXPORT __global // seem to allow boost::array in unions
# else #define TORRENT_BROKEN_UNIONS 1
# define TORRENT_EXPORT
# endif
# else
# define TORRENT_EXPORT
# endif
// ======= MSVC ========= // ======= MSVC =========
#elif defined BOOST_MSVC #elif defined BOOST_MSVC
#pragma warning(disable: 4258) #pragma warning(disable: 4258)
#pragma warning(disable: 4251) #pragma warning(disable: 4251)
# if defined(TORRENT_BUILDING_SHARED) // class X needs to have dll-interface to be used by clients of class Y
# define TORRENT_EXPORT __declspec(dllexport) #pragma warning(disable:4251)
# elif defined(TORRENT_LINKING_SHARED) // '_vsnprintf': This function or variable may be unsafe
# define TORRENT_EXPORT __declspec(dllimport) #pragma warning(disable:4996)
# else // 'strdup': The POSIX name for this item is deprecated. Instead, use the I
# define TORRENT_EXPORT SO C++ conformant name: _strdup
# endif #pragma warning(disable: 4996)
#define strdup _strdup
#define TORRENT_DEPRECATED_PREFIX __declspec(deprecated) #define TORRENT_DEPRECATED_PREFIX __declspec(deprecated)
// ======= GENERIC COMPILER =========
#else
# define TORRENT_EXPORT
#endif #endif
#ifndef TORRENT_DEPRECATED_PREFIX // ======= PLATFORMS =========
#define TORRENT_DEPRECATED_PREFIX
#endif
#ifndef TORRENT_DEPRECATED // set up defines for target environments
#define TORRENT_DEPRECATED // ==== AMIGA ===
#if defined __AMIGA__ || defined __amigaos__ || defined __AROS__
#define TORRENT_AMIGA
#define TORRENT_USE_MLOCK 0
#define TORRENT_USE_WRITEV 0
#define TORRENT_USE_READV 0
#define TORRENT_USE_IPV6 0
#define TORRENT_USE_BOOST_THREAD 0
#define TORRENT_USE_IOSTREAM 0
// set this to 1 to disable all floating point operations
// (disables some float-dependent APIs)
#define TORRENT_NO_FPU 1
#define TORRENT_USE_I2P 0
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#endif #endif
// set up defines for target environments // ==== Darwin/BSD ===
#if (defined __APPLE__ && __MACH__) || defined __FreeBSD__ || defined __Net #elif (defined __APPLE__ && defined __MACH__) || defined __FreeBSD__ || def
BSD__ \ ined __NetBSD__ \
|| defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \ || defined __OpenBSD__ || defined __bsdi__ || defined __DragonFly__ \
|| defined __FreeBSD_kernel__ || defined __FreeBSD_kernel__
#define TORRENT_BSD #define TORRENT_BSD
// we don't need iconv on mac, because
// the locale is always utf-8
#if defined __APPLE__
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#define TORRENT_USE_LOCALE 0
#define TORRENT_CLOSE_MAY_BLOCK 1
#endif
#else
// FreeBSD has a reasonable iconv signature
#define TORRENT_ICONV_ARG (const char**)
#endif
#define TORRENT_HAS_FALLOCATE 0 #define TORRENT_HAS_FALLOCATE 0
#define TORRENT_USE_IFADDRS 1
#define TORRENT_USE_SYSCTL 1
#define TORRENT_USE_IFCONF 1
// ==== LINUX ===
#elif defined __linux__ #elif defined __linux__
#define TORRENT_LINUX #define TORRENT_LINUX
#define TORRENT_USE_IFADDRS 1
#define TORRENT_USE_NETLINK 1
#define TORRENT_USE_IFCONF 1
#define TORRENT_HAS_SALEN 0
// ==== MINGW ===
#elif defined __MINGW32__ #elif defined __MINGW32__
#define TORRENT_MINGW #define TORRENT_MINGW
#define TORRENT_WINDOWS #define TORRENT_WINDOWS
#define TORRENT_HAS_FALLOCATE 0 #ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#define TORRENT_USE_LOCALE 1
#endif
#define TORRENT_USE_RLIMIT 0
#define TORRENT_USE_NETLINK 0
#define TORRENT_USE_GETADAPTERSADDRESSES 1
#define TORRENT_HAS_SALEN 0
#define TORRENT_USE_GETIPFORWARDTABLE 1
#ifndef TORRENT_USE_UNC_PATHS
#define TORRENT_USE_UNC_PATHS 1
#endif
// ==== WINDOWS ===
#elif defined WIN32 #elif defined WIN32
#define TORRENT_WINDOWS #define TORRENT_WINDOWS
#ifndef TORRENT_USE_GETIPFORWARDTABLE
#define TORRENT_USE_GETIPFORWARDTABLE 1
#endif
#define TORRENT_USE_GETADAPTERSADDRESSES 1
#define TORRENT_HAS_SALEN 0
// windows has its own functions to convert
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#define TORRENT_USE_LOCALE 1
#endif
#define TORRENT_USE_RLIMIT 0
#define TORRENT_HAS_FALLOCATE 0 #define TORRENT_HAS_FALLOCATE 0
#ifndef TORRENT_USE_UNC_PATHS
#define TORRENT_USE_UNC_PATHS 1
#endif
// ==== SOLARIS ===
#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
#define TORRENT_USE_IFCONF 1
#define TORRENT_HAS_SALEN 0
// ==== BEOS ===
#elif defined __BEOS__ || defined __HAIKU__
#define TORRENT_BEOS
#include <storage/StorageDefs.h> // B_PATH_NAME_LENGTH
#define TORRENT_HAS_FALLOCATE 0
#define TORRENT_USE_MLOCK 0
#ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 0
#endif
// ==== GNU/Hurd ===
#elif defined __GNU__
#define TORRENT_HURD
#define TORRENT_USE_IFADDRS 1
#define TORRENT_USE_IFCONF 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 // on windows, NAME_MAX refers to Unicode characters
#define TORRENT_USE_MLOCK 1 // on linux it refers to bytes (utf-8 encoded)
#define TORRENT_USE_READV 1 // TODO: Make this count Unicode characters instead of bytes on windows
#define TORRENT_USE_WRITEV 1
#define TORRENT_USE_IOSTREAM 1
#if defined TORRENT_BSD || defined TORRENT_LINUX || defined TORRENT_SOLARIS // windows
#define TORRENT_USE_RLIMIT 1 #if defined FILENAME_MAX
#else #define TORRENT_MAX_PATH FILENAME_MAX
#define TORRENT_USE_RLIMIT 0
#endif
#ifndef TORRENT_HAS_FALLOCATE // beos
#define TORRENT_HAS_FALLOCATE 1 #elif defined B_PATH_NAME_LENGTH
#endif #define TORRENT_MAX_PATH B_PATH_NAME_LENGTH
// should wpath or path be used? // solaris
#if defined UNICODE && !defined BOOST_FILESYSTEM_NARROW_ONLY \ #elif defined MAXPATH
&& BOOST_VERSION >= 103400 && !defined __APPLE__ \ #define TORRENT_MAX_PATH MAXPATH
&& !defined TORRENT_MINGW \
&& !defined TORRENT_SOLARIS
#define TORRENT_USE_WPATH 1
#else
#define TORRENT_USE_WPATH 0
#endif
// set this to 1 to disable all floating point operations // posix
// (disables some float-dependent APIs) #elif defined NAME_MAX
#define TORRENT_NO_FPU 0 #define TORRENT_MAX_PATH NAME_MAX
// make sure NAME_MAX is defined // none of the above
#ifndef NAME_MAX
#ifdef MAXPATH
#define NAME_MAX MAXPATH
#else #else
// this is the maximum number of characters in a // this is the maximum number of characters in a
// path element / filename on windows // path element / filename on windows
#define NAME_MAX 255 #define TORRENT_MAX_PATH 255
#endif // MAXPATH #warning unknown platform, assuming the longest path is 255
#endif // NAME_MAX
#if defined TORRENT_WINDOWS && !defined TORRENT_MINGW #endif
#pragma warning(disable:4251) // class X needs to have dll-interface to be used by clients of class Y #if defined TORRENT_WINDOWS && !defined TORRENT_MINGW
#include <stdarg.h> #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, ...) inline int snprintf(char* buf, int len, char const* fmt, ...)
{ {
va_list lp; va_list lp;
va_start(lp, fmt); va_start(lp, fmt);
int ret = _vsnprintf(buf, len, fmt, lp); int ret = _vsnprintf(buf, len, fmt, lp);
va_end(lp); va_end(lp);
if (ret < 0) { buf[len-1] = 0; ret = len-1; } if (ret < 0) { buf[len-1] = 0; ret = len-1; }
return ret; return ret;
} }
#define strtoll _strtoi64 #define strtoll _strtoi64
#else #else
#include <limits.h> #include <limits.h>
#endif #endif
#if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) && !defi #if (defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)) \
ned (TORRENT_UPNP_LOGGING) && !defined (TORRENT_UPNP_LOGGING) && TORRENT_USE_IOSTREAM
#define TORRENT_UPNP_LOGGING #define TORRENT_UPNP_LOGGING
#endif #endif
#if !TORRENT_USE_WPATH && (defined TORRENT_LINUX || defined TORRENT_MINGW) #ifndef TORRENT_ICONV_ARG
#define TORRENT_ICONV_ARG (char**)
#endif
// libiconv presence, not implemented yet // libiconv presence, not implemented yet
#define TORRENT_USE_LOCALE_FILENAMES 1 #ifndef TORRENT_USE_ICONV
#define TORRENT_USE_ICONV 1
#endif
#ifndef TORRENT_HAS_SALEN
#define TORRENT_HAS_SALEN 1
#endif
#ifndef TORRENT_USE_GETADAPTERSADDRESSES
#define TORRENT_USE_GETADAPTERSADDRESSES 0
#endif
#ifndef TORRENT_USE_NETLINK
#define TORRENT_USE_NETLINK 0
#endif
#ifndef TORRENT_USE_SYSCTL
#define TORRENT_USE_SYSCTL 0
#endif
#ifndef TORRENT_USE_GETIPFORWARDTABLE
#define TORRENT_USE_GETIPFORWARDTABLE 0
#endif
#ifndef TORRENT_USE_LOCALE
#define TORRENT_USE_LOCALE 0
#endif
// set this to true if close() may block on your system
// Mac OS X does this if the file being closed is not fully
// allocated on disk yet for instance. When defined, the disk
// I/O subsytem will use a separate thread for closing files
#ifndef TORRENT_CLOSE_MAY_BLOCK
#define TORRENT_CLOSE_MAY_BLOCK 0
#endif
#ifndef TORRENT_BROKEN_UNIONS
#define TORRENT_BROKEN_UNIONS 0
#endif
#ifndef TORRENT_USE_WSTRING
#if defined UNICODE && !defined BOOST_NO_STD_WSTRING
#define TORRENT_USE_WSTRING 1
#else #else
#define TORRENT_USE_LOCALE_FILENAMES 0 #define TORRENT_USE_WSTRING 0
#endif // UNICODE
#endif // TORRENT_USE_WSTRING
#ifndef TORRENT_HAS_FALLOCATE
#define TORRENT_HAS_FALLOCATE 1
#endif
#ifndef TORRENT_EXPORT
# define TORRENT_EXPORT
#endif
#ifndef TORRENT_DEPRECATED_PREFIX
#define TORRENT_DEPRECATED_PREFIX
#endif
#ifndef TORRENT_DEPRECATED
#define TORRENT_DEPRECATED
#endif
#ifndef TORRENT_COMPLETE_TYPES_REQUIRED
#define TORRENT_COMPLETE_TYPES_REQUIRED 0
#endif
#ifndef TORRENT_USE_UNC_PATHS
#define TORRENT_USE_UNC_PATHS 0
#endif
#ifndef TORRENT_USE_RLIMIT
#define TORRENT_USE_RLIMIT 1
#endif
#ifndef TORRENT_USE_IFADDRS
#define TORRENT_USE_IFADDRS 0
#endif
#ifndef TORRENT_USE_IPV6
#define TORRENT_USE_IPV6 1
#endif
#ifndef TORRENT_USE_MLOCK
#define TORRENT_USE_MLOCK 1
#endif
#ifndef TORRENT_USE_WRITEV
#define TORRENT_USE_WRITEV 1
#endif
#ifndef TORRENT_USE_READV
#define TORRENT_USE_READV 1
#endif
#ifndef TORRENT_NO_FPU
#define TORRENT_NO_FPU 0
#endif
#ifndef TORRENT_USE_IOSTREAM
#ifndef BOOST_NO_IOSTREAM
#define TORRENT_USE_IOSTREAM 1
#else
#define TORRENT_USE_IOSTREAM 0
#endif
#endif
// if set to true, piece picker will use less RAM
// but only support up to ~260000 pieces in a torrent
#ifndef TORRENT_COMPACT_PICKER
#define TORRENT_COMPACT_PICKER 0
#endif
#ifndef TORRENT_USE_I2P
#define TORRENT_USE_I2P 1
#endif
#ifndef TORRENT_HAS_STRDUP
#define TORRENT_HAS_STRDUP 1
#endif #endif
#if !defined TORRENT_IOV_MAX #if !defined TORRENT_IOV_MAX
#ifdef IOV_MAX #ifdef IOV_MAX
#define TORRENT_IOV_MAX IOV_MAX #define TORRENT_IOV_MAX IOV_MAX
#else #else
#define TORRENT_IOV_MAX INT_MAX #define TORRENT_IOV_MAX INT_MAX
#endif #endif
#endif #endif
#if !defined(TORRENT_READ_HANDLER_MAX_SIZE) #if !defined(TORRENT_READ_HANDLER_MAX_SIZE)
# define TORRENT_READ_HANDLER_MAX_SIZE 256 # define TORRENT_READ_HANDLER_MAX_SIZE 300
#endif #endif
#if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE) #if !defined(TORRENT_WRITE_HANDLER_MAX_SIZE)
# define TORRENT_WRITE_HANDLER_MAX_SIZE 256 # define TORRENT_WRITE_HANDLER_MAX_SIZE 300
#endif
#ifndef TORRENT_ICONV_ARG
#define TORRENT_ICONV_ARG (char**)
#endif #endif
#if defined _MSC_VER && _MSC_VER <= 1200 #if defined _MSC_VER && _MSC_VER <= 1200
#define for if (false) {} else for #define for if (false) {} else for
#endif #endif
#if TORRENT_BROKEN_UNIONS
#define TORRENT_UNION struct
#else
#define TORRENT_UNION union
#endif
// determine what timer implementation we can use // determine what timer implementation we can use
// if one is already defined, don't pick one
// autmatically. This lets the user control this
// from the Jamfile
#if !defined TORRENT_USE_ABSOLUTE_TIME \
&& !defined TORRENT_USE_QUERY_PERFORMANCE_TIMER \
&& !defined TORRENT_USE_CLOCK_GETTIME \
&& !defined TORRENT_USE_BOOST_DATE_TIME \
&& !defined TORRENT_USE_ECLOCK \
&& !defined TORRENT_USE_SYSTEM_TIME
#if defined(__MACH__) #if defined __APPLE__ && defined __MACH__
#define TORRENT_USE_ABSOLUTE_TIME 1 #define TORRENT_USE_ABSOLUTE_TIME 1
#elif defined(_WIN32) #elif defined(_WIN32) || defined TORRENT_MINGW
#define TORRENT_USE_QUERY_PERFORMANCE_TIMER 1 #define TORRENT_USE_QUERY_PERFORMANCE_TIMER 1
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 #elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
#define TORRENT_USE_CLOCK_GETTIME 1 #define TORRENT_USE_CLOCK_GETTIME 1
#elif defined(TORRENT_AMIGA)
#define TORRENT_USE_ECLOCK 1
#elif defined(TORRENT_BEOS)
#define TORRENT_USE_SYSTEM_TIME 1
#else #else
#define TORRENT_USE_BOOST_DATE_TIME 1 #define TORRENT_USE_BOOST_DATE_TIME 1
#endif #endif
#endif
#if !TORRENT_HAS_STRDUP
inline char* strdup(char const* str)
{
if (str == 0) return 0;
char* tmp = (char*)malloc(strlen(str) + 1);
if (tmp == 0) return 0;
strcpy(tmp, str);
return tmp;
}
#endif
// for non-exception builds
#ifdef BOOST_NO_EXCEPTIONS
#define TORRENT_TRY if (true)
#define TORRENT_CATCH(x) else if (false)
#define TORRENT_DECLARE_DUMMY(x, y) x y
#else
#define TORRENT_TRY try
#define TORRENT_CATCH(x) catch(x)
#define TORRENT_DECLARE_DUMMY(x, y)
#endif // BOOST_NO_EXCEPTIONS
#endif // TORRENT_CONFIG_HPP_INCLUDED #endif // TORRENT_CONFIG_HPP_INCLUDED
 End of changes. 40 change blocks. 
90 lines changed or deleted 354 lines changed or added


 connection_queue.hpp   connection_queue.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_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/function1.hpp>
#include <boost/function/function0.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/thread/mutex.hpp> #include "libtorrent/io_service.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/error_code.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/deadline_timer.hpp"
#ifdef TORRENT_CONNECTION_LOGGING #ifdef TORRENT_CONNECTION_LOGGING
#include <fstream> #include <fstream>
#endif #endif
#include "libtorrent/thread.hpp"
namespace libtorrent namespace libtorrent
{ {
class TORRENT_EXPORT connection_queue : public boost::noncopyable class TORRENT_EXTRA_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 77
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:
typedef boost::mutex mutex_t; typedef mutex mutex_t;
void try_connect(mutex_t::scoped_lock& l); 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(); 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
// this is when the timeout countdown starts // this is when the timeout countdown starts
 End of changes. 5 change blocks. 
6 lines changed or deleted 9 lines changed or added


 create_torrent.hpp   create_torrent.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#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/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/utf8.hpp"
#include "libtorrent/allocator.hpp" #include "libtorrent/allocator.hpp"
#include "libtorrent/file.hpp" // for combine_path etc.
#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/operations.hpp>
#include <boost/optional.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> #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 pt = boost::posix_time;
class torrent_info; class torrent_info;
struct TORRENT_EXPORT create_torrent struct TORRENT_EXPORT create_torrent
{ {
enum flags_t enum flags_t
{ {
optimize = 1 optimize = 1
, merkle = 2 , merkle = 2
, modification_time = 4 , modification_time = 4
, symlinks = 8 , symlinks = 8
, calculate_file_hashes = 16
}; };
create_torrent(file_storage& fs, int piece_size = 0 create_torrent(file_storage& fs, int piece_size = 0
, int pad_file_limit = -1, int flags = optimize); , int pad_file_limit = -1, int flags = optimize);
create_torrent(torrent_info const& ti); create_torrent(torrent_info const& ti);
~create_torrent();
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 set_file_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_http_seed(std::string const& url); void add_http_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_root_cert(std::string const& pem);
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; }
bool should_add_file_hashes() const { return m_calculate_fil e_hashes; }
std::vector<sha1_hash> const& merkle_tree() const { return m _merkle_tree; } std::vector<sha1_hash> const& merkle_tree() const { return m _merkle_tree; }
private: private:
file_storage& m_files; file_storage& m_files;
// if m_info_dict is initialized, it is // if m_info_dict is initialized, it is
// used instead of m_files to generate // used instead of m_files to generate
// the info dictionary // the info dictionary
entry m_info_dict; 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<std::string> m_http_seeds;
std::vector<sha1_hash> m_piece_hash; std::vector<sha1_hash> m_piece_hash;
std::vector<sha1_hash> m_filehashes;
// if we're generating a merkle torrent, this is the // if we're generating a merkle torrent, this is the
// merkle tree we got. This should be saved in fast-resume // merkle tree we got. This should be saved in fast-resume
// in order to start seeding the torrent // in order to start seeding the torrent
mutable std::vector<sha1_hash> m_merkle_tree; mutable std::vector<sha1_hash> m_merkle_tree;
// 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 m_nodes; nodes_t m_nodes;
// the hash that identifies this torrent // the hash that identifies this torrent
// is mutable because it's calculated // is mutable because it's calculated
// lazily // lazily
mutable sha1_hash m_info_hash; mutable 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; time_t m_creation_date;
// if a comment is found in the torrent file // if a comment is found in the torrent file
// this will be set to that comment // this will be set to that comment
std::string m_comment; std::string m_comment;
// 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 the root cert for SSL torrents
std::string m_root_cert;
// 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:1; 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:1; bool m_private:1;
skipping to change at line 170 skipping to change at line 175
// if set, include the 'mtime' modification time in the // if set, include the 'mtime' modification time in the
// torrent file // torrent file
bool m_include_mtime:1; bool m_include_mtime:1;
// if set, symbolic links are declared as such in // if set, symbolic links are declared as such in
// the torrent file. The full data of the pointed-to // the torrent file. The full data of the pointed-to
// file is still included // file is still included
bool m_include_symlinks:1; bool m_include_symlinks:1;
// this is added at the end in order to maintain binary // this is only used by set_piece_hashes(). It will
// compatibility with previous 0.15.x releases. In the // calculate sha1 hashes for each file and add it
// next full version release this member has been moved // to the file list
// to a more reasonable location bool m_calculate_file_hashes:1;
std::vector<std::string> m_http_seeds;
}; };
namespace detail namespace detail
{ {
inline bool default_pred(boost::filesystem::path const&) { r inline bool default_pred(std::string const&) { return true;
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) inline bool ignore_subdir(std::string const& leaf)
{ return leaf == ".." || 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) {}
int TORRENT_EXPORT get_file_attributes(boost::filesystem::pa int get_file_attributes(std::string const& p);
th const& p); std::string get_symlink_path(std::string const& p);
#if TORRENT_USE_WPATH
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, boost::uint32_t flags)
{
using boost::filesystem::basic_path;
using boost::filesystem::basic_directory_iterator;
basic_path<Str, PathTraits> f(p / l);
if (!pred(f)) return;
bool recurse = is_directory(f);
// if the file is not a link or we're following link
s, and it's a directory
// only then should we recurse
if ((is_symlink(f)) && (flags & create_torrent::syml
inks))
recurse = false;
if (recurse) TORRENT_EXPORT void add_files_impl(file_storage& fs, std::st
{ ring const& p
for (basic_directory_iterator<basic_path<Str , std::string const& l, boost::function<bool(std::st
, PathTraits> > i(f), end; i != end; ++i) ring)> pred
{ , boost::uint32_t flags);
#if BOOST_VERSION < 103600
Str const& leaf = i->path().leaf();
#else
Str const& leaf = i->path().filename
();
#endif
if (ignore_subdir(leaf)) continue;
add_files_impl(fs, p, l / leaf, pred
, flags);
}
}
else
{
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_sy
mlink)
&& (flags & create_torrent::symlinks
))
{
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 void add_files(file_storage& fs, std::string const& file, Pred p, bo
, Pred p ost::uint32_t flags = 0)
, boost::uint32_t flags = 0)
{ {
using boost::filesystem::path; detail::add_files_impl(fs, parent_path(complete(file)), file
boost::filesystem::path f = file; name(file), p, flags);
#if BOOST_VERSION < 103600
if (f.leaf() == ".") f = f.branch_path();
detail::add_files_impl(fs, complete(f).branch_path(), path(f
.leaf()), p, flags);
#else
if (f.filename() == ".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), path(f
.filename()), p, flags);
#endif
} }
inline void add_files(file_storage& fs, boost::filesystem::path cons inline void add_files(file_storage& fs, std::string const& file, boo
t& file st::uint32_t flags = 0)
, boost::uint32_t flags = 0)
{ {
using boost::filesystem::path; detail::add_files_impl(fs, parent_path(complete(file)), file
boost::filesystem::path f = file; name(file)
#if BOOST_VERSION < 103600
if (f.leaf() == ".") f = f.branch_path();
detail::add_files_impl(fs, complete(f).branch_path(), path(f
.leaf())
, detail::default_pred, flags);
#else
if (f.filename() == ".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), path(f
.filename())
, detail::default_pred, flags); , detail::default_pred, flags);
#endif
} }
struct piece_holder TORRENT_EXPORT void set_piece_hashes(create_torrent& t, std::string
{ const& p
piece_holder(int bytes): m_piece(page_aligned_allocator::mal , boost::function<void(int)> f, error_code& ec);
loc(bytes)) {}
~piece_holder() { page_aligned_allocator::free(m_piece); }
char* bytes() { return m_piece; }
private:
char* m_piece;
};
template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::path con
st& p, Fun f
, error_code& ec)
{
file_pool fp;
boost::scoped_ptr<storage_interface> st(
default_storage_constructor(const_cast<file_storage&
>(t.files()), 0, p, fp));
// calculate the hash for all pieces
int num = t.num_pieces();
piece_holder 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.bytes(), i, 0, t.piece_size(i));
if (st->error())
{
ec = st->error();
return;
}
hasher h(buf.bytes(), t.piece_size(i));
t.set_hash(i, h.final());
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, std::string const& p, Fun f )
{ {
error_code ec; error_code ec;
set_piece_hashes(t, p, f, ec); set_piece_hashes(t, p, f, ec);
if (ec) throw libtorrent_exception(ec); if (ec) throw libtorrent_exception(ec);
} }
inline void set_piece_hashes(create_torrent& t, boost::filesystem::p ath const& p) inline void set_piece_hashes(create_torrent& t, std::string const& p )
{ {
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, std::string 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 #if TORRENT_USE_WSTRING
// wpath versions // wstring versions
template <class Pred> template <class Pred>
void add_files(file_storage& fs, boost::filesystem::wpath const& fil void add_files(file_storage& fs, std::wstring const& wfile, Pred p,
e, Pred p boost::uint32_t flags = 0)
, boost::uint32_t flags = 0)
{
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, flags);
#else
if (f.filename() == L".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), wpath(
f.filename()), p, flags);
#endif
}
inline void add_files(file_storage& fs, boost::filesystem::wpath con
st& file
, boost::uint32_t flags = 0)
{ {
using boost::filesystem::wpath; std::string utf8;
wpath f = file; wchar_utf8(wfile, utf8);
#if BOOST_VERSION < 103600 detail::add_files_impl(fs, parent_path(complete(utf8))
if (f.leaf() == L".") f = f.branch_path(); , filename(utf8), p, flags);
detail::add_files_impl(fs, complete(f).branch_path(), wpath(
f.leaf()), detail::wdefault_pred
, flags);
#else
if (f.filename() == L".") f = f.parent_path();
detail::add_files_impl(fs, complete(f).parent_path(), wpath(
f.filename())
, detail::wdefault_pred, flags);
#endif
} }
template <class Fun> inline void add_files(file_storage& fs, std::wstring const& wfile, b
void set_piece_hashes(create_torrent& t, boost::filesystem::wpath co oost::uint32_t flags = 0)
nst& p, Fun f
, error_code& ec)
{ {
file_pool fp;
std::string utf8; std::string utf8;
wchar_utf8(p.string(), utf8); wchar_utf8(wfile, utf8);
boost::scoped_ptr<storage_interface> st( detail::add_files_impl(fs, parent_path(complete(utf8))
default_storage_constructor(const_cast<file_storage& , filename(utf8), detail::default_pred, flags);
>(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);
}
} }
void TORRENT_EXPORT set_piece_hashes(create_torrent& t, std::wstring
const& p
, boost::function<void(int)> const& f, error_code& ec);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
template <class Fun> template <class Fun>
void set_piece_hashes(create_torrent& t, boost::filesystem::wpath co nst& p, Fun f) void set_piece_hashes(create_torrent& t, std::wstring const& p, Fun f)
{ {
error_code ec; error_code ec;
set_piece_hashes(t, p, f, ec); set_piece_hashes(t, p, f, ec);
if (ec) throw libtorrent_exception(ec); if (ec) throw libtorrent_exception(ec);
} }
inline void set_piece_hashes(create_torrent& t, boost::filesystem::w path const& p) inline void set_piece_hashes(create_torrent& t, std::wstring const& p)
{ {
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::w path const& p, error_code& ec) inline void set_piece_hashes(create_torrent& t, std::wstring const& p, error_code& ec)
{ {
set_piece_hashes(t, p, detail::nop, ec); set_piece_hashes(t, p, detail::nop, ec);
} }
#endif // TORRENT_USE_WPATH #endif // TORRENT_USE_WPATH
} }
#endif #endif
 End of changes. 38 change blocks. 
239 lines changed or deleted 60 lines changed or added


 debug.hpp   debug.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_DEBUG_HPP_INCLUDED #ifndef TORRENT_DEBUG_HPP_INCLUDED
#define TORRENT_DEBUG_HPP_INCLUDED #define TORRENT_DEBUG_HPP_INCLUDED
#if defined TORRENT_ASIO_DEBUGGING
#include "libtorrent/assert.hpp"
#include "libtorrent/thread.hpp"
#include <map>
std::string demangle(char const* name);
namespace libtorrent
{
struct async_t
{
async_t() : refs(0) {}
std::string stack;
int refs;
};
extern std::map<std::string, async_t> _async_ops;
extern int _async_ops_nthreads;
extern mutex _async_ops_mutex;
inline void add_outstanding_async(char const* name)
{
mutex::scoped_lock l(_async_ops_mutex);
async_t& a = _async_ops[name];
if (a.stack.empty())
{
char stack_text[10000];
print_backtrace(stack_text, sizeof(stack_text), 9);
a.stack = stack_text;
}
++a.refs;
}
inline void complete_async(char const* name)
{
mutex::scoped_lock l(_async_ops_mutex);
async_t& a = _async_ops[name];
TORRENT_ASSERT(a.refs > 0);
--a.refs;
}
inline void async_inc_threads()
{
mutex::scoped_lock l(_async_ops_mutex);
++_async_ops_nthreads;
}
inline void async_dec_threads()
{
mutex::scoped_lock l(_async_ops_mutex);
--_async_ops_nthreads;
}
inline int log_async()
{
mutex::scoped_lock l(_async_ops_mutex);
int ret = 0;
for (std::map<std::string, async_t>::iterator i = _async_ops
.begin()
, end(_async_ops.end()); i != end; ++i)
{
if (i->second.refs <= _async_ops_nthreads - 1) conti
nue;
ret += i->second.refs;
printf("%s: (%d)\n%s\n", i->first.c_str(), i->second
.refs, i->second.stack.c_str());
}
return ret;
}
}
#endif
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T
ORRENT_ERROR_LOGGING
#include <string> #include <string>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/file.hpp"
#include "libtorrent/thread.hpp"
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#endif #endif
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/convenience.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
namespace libtorrent namespace libtorrent
{ {
// DEBUG API // DEBUG API
namespace fs = boost::filesystem;
struct logger struct logger
{ {
logger(fs::path const& logpath, fs::path const& filename, in
t instance, bool append = true)
{
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
// all log streams share a single file descriptor
#ifndef BOOST_NO_EXCEPTIONS // and re-opens the file for each log line
try // these members are defined in session_impl.cpp
{ static std::ofstream log_file;
#endif static std::string open_filename;
char log_name[256]; static mutex file_mutex;
snprintf(log_name, sizeof(log_name), "libtor
rent_logs%d", instance);
fs::path dir(fs::complete(logpath / log_name
));
if (!fs::exists(dir)) fs::create_directories
(dir);
m_file.open((dir / filename).string().c_str(
), std::ios_base::out | (append ? std::ios_base::app : std::ios_base::out))
;
*this << "\n\n\n*** starting log ***\n";
#ifndef BOOST_NO_EXCEPTIONS
}
catch (std::exception& e)
{
std::cerr << "failed to create log '" << fil
ename.string() << "': " << e.what() << std::endl;
}
#endif
#endif #endif
~logger()
{
mutex::scoped_lock l(file_mutex);
log_file.close();
open_filename.clear();
}
logger(std::string const& logpath, std::string const& filena
me
, int instance, bool append)
{
char log_name[512];
snprintf(log_name, sizeof(log_name), "libtorrent_log
s%d", instance);
std::string dir(complete(combine_path(logpath, log_n
ame)));
error_code ec;
if (!exists(dir)) create_directories(dir, ec);
m_filename = combine_path(dir, filename);
mutex::scoped_lock l(file_mutex);
open(!append);
log_file << "\n\n\n*** starting log ***\n";
} }
#if TORRENT_USE_IOSTREAM
void open(bool truncate)
{
if (open_filename == m_filename) return;
log_file.close();
log_file.clear();
log_file.open(m_filename.c_str(), truncate ? std::io
s_base::trunc : std::ios_base::app);
open_filename = m_filename;
if (!log_file.good())
fprintf(stderr, "Failed to open logfile %s:
%s\n", m_filename.c_str(), strerror(errno));
}
#endif
template <class T> template <class T>
logger& operator<<(T const& v) logger& operator<<(T const& v)
{ {
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
m_file << v; mutex::scoped_lock l(file_mutex);
m_file.flush(); open(false);
log_file << v;
#endif #endif
return *this; return *this;
} }
#if TORRENT_USE_IOSTREAM std::string m_filename;
std::ofstream m_file;
#endif
}; };
} }
#endif // TORRENT_VERBOSE_LOGGING || TORRENT_LOGGING || TORRENT_ERROR_LOGGI NG
#endif // TORRENT_DEBUG_HPP_INCLUDED #endif // TORRENT_DEBUG_HPP_INCLUDED
 End of changes. 11 change blocks. 
45 lines changed or deleted 130 lines changed or added


 dht_tracker.hpp   dht_tracker.hpp 
skipping to change at line 43 skipping to change at line 43
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
#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/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 "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"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace aux { struct session_impl; } namespace aux { struct session_impl; }
struct lazy_entry; 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_EXTRA_EXPORT void intrusive_ptr_add_ref(dht_tracker const*);
TORRENT_EXPORT void intrusive_ptr_release(dht_tracker const*); TORRENT_EXTRA_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*);
friend bool send_callback(void* userdata, entry& e, udp::end point const& addr, int flags);
dht_tracker(libtorrent::aux::session_impl& ses, rate_limited _udp_socket& sock dht_tracker(libtorrent::aux::session_impl& ses, rate_limited _udp_socket& sock
, dht_settings const& settings, entry const* state = 0); , 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, bool see d
, boost::function<void(std::vector<tcp::endpoint> co nst&)> f); , boost::function<void(std::vector<tcp::endpoint> co nst&)> f);
void dht_status(session_status& s); void dht_status(session_status& s);
void network_stats(int& sent, int& received); 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);
skipping to change at line 115 skipping to change at line 115
{ return boost::intrusive_ptr<dht_tracker>(this); } { return boost::intrusive_ptr<dht_tracker>(this); }
void on_name_lookup(error_code const& e void on_name_lookup(error_code const& e
, 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 send_packet(msg const& m); bool send_packet(libtorrent::entry& e, udp::endpoint const&
addr, int send_flags);
void incoming_error(char const* msg, lazy_entry const& e, ud
p::endpoint const& ep);
node_impl m_dht; node_impl m_dht;
libtorrent::aux::session_impl& m_ses; libtorrent::aux::session_impl& m_ses;
rate_limited_udp_socket& m_sock; 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
// it's only used to set m_abort to true
typedef boost::mutex mutex_t;
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 // sent and received bytes since queried last time
int m_sent_bytes; int m_sent_bytes;
int m_received_bytes; int m_received_bytes;
// used to ignore abusive dht nodes // used to ignore abusive dht nodes
skipping to change at line 167 skipping to change at line 161
// reference counter for intrusive_ptr // reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs; mutable boost::detail::atomic_count m_refs;
#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_failed_announces;
int m_total_message_input; int m_total_message_input;
int m_az_message_input;
int m_ut_message_input;
int m_lt_message_input;
int m_mp_message_input;
int m_gr_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;
#endif #endif
}; };
}} }}
#endif #endif
#endif #endif
 End of changes. 10 change blocks. 
23 lines changed or deleted 8 lines changed or added


 disk_buffer_holder.hpp   disk_buffer_holder.hpp 
skipping to change at line 46 skipping to change at line 46
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include <algorithm> #include <algorithm>
namespace libtorrent namespace libtorrent
{ {
namespace aux { struct session_impl; } namespace aux { struct session_impl; }
struct disk_buffer_pool; struct disk_buffer_pool;
struct TORRENT_EXPORT disk_buffer_holder struct TORRENT_EXTRA_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_buffer_pool& disk_pool, 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, int num_blocks = 1); void reset(char* buf = 0);
void swap(disk_buffer_holder& h) void swap(disk_buffer_holder& h)
{ {
TORRENT_ASSERT(&h.m_disk_pool == &m_disk_pool); TORRENT_ASSERT(&h.m_disk_pool == &m_disk_pool);
std::swap(h.m_buf, m_buf); 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_buffer_pool& m_disk_pool; disk_buffer_pool& m_disk_pool;
char* m_buf; char* m_buf;
int m_num_blocks;
}; };
} }
#endif #endif
 End of changes. 4 change blocks. 
4 lines changed or deleted 2 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
#if defined TORRENT_DISK_STATS || defined TORRENT_STATS
#include <fstream>
#endif
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/allocator.hpp" #include "libtorrent/allocator.hpp"
#include <boost/thread/thread.hpp> #include "libtorrent/io_service.hpp"
#include <boost/thread/mutex.hpp> #include "libtorrent/sliding_average.hpp"
#include <boost/thread/condition.hpp>
#include <boost/function.hpp> #include <boost/function/function0.hpp>
#include <boost/bind.hpp> #include <boost/function/function2.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <boost/shared_array.hpp> #include <boost/shared_array.hpp>
#include <list> #include <deque>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR #include "libtorrent/thread.hpp"
#include <boost/pool/pool.hpp> #include "libtorrent/disk_buffer_pool.hpp"
#endif
#include "libtorrent/session_settings.hpp" #include <boost/multi_index_container.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/mem_fun.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;
using boost::multi_index::const_mem_fun;
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;
int next_to_hash;
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
{ {
disk_io_job() disk_io_job()
: action(read) : action(read)
, buffer(0) , buffer(0)
, buffer_size(0) , buffer_size(0)
, piece(0) , piece(0)
, offset(0) , offset(0)
, priority(0) , max_cache_line(0)
, cache_min_time(0)
{} {}
enum action_t enum action_t
{ {
read read
, write , write
, hash , hash
, 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 , update_settings
, read_and_hash , read_and_hash
, cache_piece
, finalize_file
}; };
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
// to the error message // to the error message
std::string str; std::string str;
// on error, this is set to the path of the // on error, this is set to the path of the
// file the disk operation failed on // file the disk operation failed on
std::string error_file; std::string error_file;
// priority decides whether or not this // if this is > 0, it specifies the max number of blocks to
// job will skip entries in the queue or read
// not. It always skips in front of entries // ahead in the read cache for this access. This is only val
// with lower priority id
int priority; // for 'read' actions
int max_cache_line;
// if this is > 0, it may increase the minimum time the cach
e
// line caused by this operation stays in the cache
int cache_min_time;
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;
// the time when this job was issued. This is used to
// keep track of disk I/O congestion
ptime start_time;
}; };
// returns true if the fundamental operation // returns true if the fundamental operation
// of the given disk job is a read operation // of the given disk job is a read operation
bool is_read_operation(disk_io_job const& j); bool is_read_operation(disk_io_job const& j);
// this is true if the buffer field in the disk_io_job // this is true if the buffer field in the disk_io_job
// points to a disk buffer // points to a disk buffer
bool operation_has_buffer(disk_io_job const& j); bool operation_has_buffer(disk_io_job const& j);
skipping to change at line 147 skipping to change at line 164
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)
, queued_bytes(0) , queued_bytes(0)
, cache_size(0) , cache_size(0)
, read_cache_size(0) , read_cache_size(0)
, total_used_buffers(0) , total_used_buffers(0)
, average_queue_time(0)
, average_read_time(0)
, average_write_time(0)
, average_hash_time(0)
, average_job_time(0)
, average_sort_time(0)
, job_queue_length(0)
, cumulative_job_time(0)
, cumulative_read_time(0)
, cumulative_write_time(0)
, cumulative_hash_time(0)
, cumulative_sort_time(0)
, total_read_back(0)
, read_queue_size(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
skipping to change at line 175 skipping to change at line 206
// 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 // the total number of blocks that are currently in use
// this includes send and receive buffers // this includes send and receive buffers
mutable int total_used_buffers; mutable int total_used_buffers;
};
struct TORRENT_EXPORT disk_buffer_pool : boost::noncopyable
{
disk_buffer_pool(int block_size);
#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
int disk_allocations() const
{ return m_allocations; }
#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; // times in microseconds
int average_queue_time;
private: int average_read_time;
int average_write_time;
// this only protects the pool allocator int average_hash_time;
typedef boost::mutex mutex_t; int average_job_time;
mutable mutex_t m_pool_mutex; int average_sort_time;
#ifndef TORRENT_DISABLE_POOL_ALLOCATOR int job_queue_length;
// 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 boost::uint32_t cumulative_job_time;
int m_allocations; boost::uint32_t cumulative_read_time;
#endif boost::uint32_t cumulative_write_time;
#ifdef TORRENT_DISK_STATS boost::uint32_t cumulative_hash_time;
public: boost::uint32_t cumulative_sort_time;
void rename_buffer(char* buf, char const* category); int total_read_back;
protected: int read_queue_size;
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 // this is a singleton consisting of the thread and a queue
// of disk io jobs // of disk io jobs
struct TORRENT_EXPORT disk_io_thread : disk_buffer_pool struct TORRENT_EXTRA_EXPORT disk_io_thread : disk_buffer_pool
{ {
disk_io_thread(io_service& ios disk_io_thread(io_service& ios
, boost::function<void()> const& queue_callback , boost::function<void()> const& queue_callback
, file_pool& fp , file_pool& fp
, int block_size = 16 * 1024); , int block_size = 16 * 1024);
~disk_io_thread(); ~disk_io_thread();
void abort();
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
// returns the disk write queue size
int 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;
bool can_write() 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;
cache_status status() const; cache_status status() const;
void operator()(); void thread_fun();
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
struct cached_block_entry struct cached_block_entry
{ {
cached_block_entry(): buf(0) {} cached_block_entry(): buf(0) {}
// the buffer pointer (this is a disk_pool buffer) // the buffer pointer (this is a disk_pool buffer)
// or 0 // or 0
skipping to change at line 301 skipping to change at line 280
// callback for when this block is flushed to disk // callback for when this block is flushed to disk
boost::function<void(int, disk_io_job const&)> callb ack; 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 pointers to the block data
boost::shared_array<cached_block_entry> blocks;
// the last time a block was writting to this piece // the last time a block was writting to this piece
ptime last_use; // plus the minimum amount of time the block is guar
anteed
// to stay in the cache
ptime expire;
// 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 // used to determine if this piece should be flushed
boost::shared_array<cached_block_entry> blocks; int num_contiguous_blocks;
// this is the first block that has not yet been has
hed
// by the partial hasher. When minimizing read-back,
this
// is used to determine if flushing a range would fo
rce us
// to read it back later when hashing
int next_block_to_hash;
std::pair<void*, int> storage_piece_pair() const
{ return std::pair<void*, int>(storage.get(), piece)
; }
}; };
typedef boost::recursive_mutex mutex_t; typedef multi_index_container<
cached_piece_entry, indexed_by<
ordered_unique<const_mem_fun<cached_piece_en
try, std::pair<void*, int>
, &cached_piece_entry::storage_piece_pair> >
, ordered_non_unique<member<cached_piece_ent
ry, ptime
, &cached_piece_entry::expire> >
>
> cache_t;
// TODO: turn this into a multi-index list typedef cache_t::nth_index<0>::type cache_piece_index_t;
// sorted by piece and last use time typedef cache_t::nth_index<1>::type cache_lru_index_t;
typedef std::list<cached_piece_entry> cache_t;
private: private:
int add_job(disk_io_job const& j
, mutex::scoped_lock& l
, boost::function<void(int, disk_io_job const&)> con
st& f
= boost::function<void(int, disk_io_job const&)>());
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 void post_callback(disk_io_job const& j, int ret);
st&)> const& handler
, disk_io_job const& j, int ret);
// cache operations // cache operations
cache_t::iterator find_cached_piece( cache_piece_index_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::scoped_lock& l);
bool is_cache_hit(cache_t::iterator p bool is_cache_hit(cached_piece_entry& p
, disk_io_job const& j, mutex_t::scoped_lock& l); , disk_io_job const& j, mutex::scoped_lock& l);
int copy_from_piece(cache_t::iterator p, bool& hit int copy_from_piece(cached_piece_entry& p, bool& hit
, disk_io_job const& j, mutex_t::scoped_lock& l); , disk_io_job const& j, mutex::scoped_lock& l);
struct ignore_t
{
ignore_t(): piece(-1), storage(0) {}
ignore_t(int idx, piece_manager* st): piece(idx), st
orage(st) {}
int piece;
piece_manager* storage;
};
// write cache operations // write cache operations
enum options_t { dont_flush_write_blocks = 1, ignore_cache_s ize = 2 }; enum options_t { dont_flush_write_blocks = 1, ignore_cache_s ize = 2 };
int flush_cache_blocks(mutex_t::scoped_lock& l int flush_cache_blocks(mutex::scoped_lock& l
, int blocks, cache_t::iterator ignore , int blocks, ignore_t ignore = ignore_t(), int opti
, int options = 0); ons = 0);
void flush_expired_pieces(); void flush_expired_pieces();
int flush_and_remove(cache_t::iterator i, mutex_t::scoped_lo int flush_contiguous_blocks(cached_piece_entry& p
ck& l); , mutex::scoped_lock& l, int lower_limit = 0, bool a
int flush_contiguous_blocks(disk_io_thread::cache_t::iterato void_readback = false);
r e int flush_range(cached_piece_entry& p, int start, int end, m
, mutex_t::scoped_lock& l, int lower_limit = 0); utex::scoped_lock& l);
int flush_range(cache_t::iterator i, int start, int end, mut
ex_t::scoped_lock& l);
int cache_block(disk_io_job& j int cache_block(disk_io_job& j
, boost::function<void(int,disk_io_job const&)>& han dler , boost::function<void(int,disk_io_job const&)>& han dler
, mutex_t::scoped_lock& l); , int cache_expire
, mutex::scoped_lock& l);
// read cache operations // read cache operations
int clear_oldest_read_piece(int num_blocks, cache_t::iterato int clear_oldest_read_piece(int num_blocks, ignore_t ignore
r ignore , mutex::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
, int options, int num_blocks, mutex_t::scoped_lock& , int options, int num_blocks, mutex::scoped_lock& l
l); );
int cache_read_block(disk_io_job const& j, mutex_t::scoped_l int cache_read_block(disk_io_job const& j, mutex::scoped_loc
ock& l); k& l);
int cache_read_piece(disk_io_job const& j, mutex_t::scoped_l int free_piece(cached_piece_entry& p, mutex::scoped_lock& l)
ock& l); ;
int free_piece(cached_piece_entry& p, mutex_t::scoped_lock& int drain_piece_bufs(cached_piece_entry& p, std::vector<char
l); *>& buf
int try_read_from_cache(disk_io_job const& j); , mutex::scoped_lock& l);
enum cache_flags_t {
cache_only = 1
};
int try_read_from_cache(disk_io_job const& j, bool& hit, int
flags = 0);
int read_piece_from_cache_and_hash(disk_io_job const& j, sha 1_hash& h); int read_piece_from_cache_and_hash(disk_io_job const& j, sha 1_hash& h);
int cache_piece(disk_io_job const& j, cache_piece_index_t::i
terator& p
, bool& hit, int options, mutex::scoped_lock& l);
// this mutex only protects m_jobs, m_queue_buffer_size // this mutex only protects m_jobs, m_queue_buffer_size,
// and m_abort // m_exceeded_write_queue and m_abort
mutable mutex_t m_queue_mutex; mutable mutex m_queue_mutex;
boost::condition m_signal; event m_signal;
bool m_abort; bool m_abort;
bool m_waiting_to_shutdown; bool m_waiting_to_shutdown;
std::list<disk_io_job> m_jobs; std::deque<disk_io_job> m_jobs;
size_type m_queue_buffer_size; size_type m_queue_buffer_size;
ptime m_last_file_check; 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 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;
void flip_stats(ptime now);
// 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;
// keeps average queue time for disk jobs (in microseconds)
average_accumulator m_queue_time;
// average read time for cache misses (in microseconds)
average_accumulator m_read_time;
// average write time (in microseconds)
average_accumulator m_write_time;
// average hash time (in microseconds)
average_accumulator m_hash_time;
// average time to serve a job (any job) in microseconds
average_accumulator m_job_time;
// average time to ask for physical offset on disk
// and insert into queue
average_accumulator m_sort_time;
// the last time we reset the average time and store the
// latest value in m_cache_stats
ptime m_last_stats_flip;
typedef std::multimap<size_type, disk_io_job> read_jobs_t;
read_jobs_t m_sorted_read_jobs;
#ifdef TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
std::ofstream m_log; std::ofstream m_log;
#endif #endif
// the amount of physical ram in the machine
boost::uint64_t m_physical_ram;
// if we exceeded the max queue disk write size
// this is set to true. It remains true until the
// queue is smaller than the low watermark
bool m_exceeded_write_queue;
io_service& m_ios; io_service& m_ios;
boost::function<void()> m_queue_callback; 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<io_service::work> m_work;
// reference to the file_pool which is a member of // reference to the file_pool which is a member of
// the session_impl object // the session_impl object
file_pool& m_file_pool; file_pool& m_file_pool;
// when completion notifications are queued, they're stuck
// in this list
std::list<std::pair<disk_io_job, int> > m_queued_completions
;
// thread for performing blocking disk io operations // thread for performing blocking disk io operations
boost::thread m_disk_io_thread; thread m_disk_io_thread;
}; };
} }
#endif #endif
 End of changes. 43 change blocks. 
141 lines changed or deleted 209 lines changed or added


 entry.hpp   entry.hpp 
skipping to change at line 70 skipping to change at line 70
#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" #include "libtorrent/error_code.hpp"
#include "libtorrent/max.hpp"
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include <iosfwd> #include <iosfwd>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
struct lazy_entry; 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
{
template<int v1, int v2>
struct max2 { enum { value = v1>v2?v1:v2 }; };
template<int v1, int v2, int v3>
struct max3
{
enum
{
temp = max2<v1,v2>::value,
value = temp>v3?temp:v3
};
};
template<int v1, int v2, int v3, int v4>
struct max4
{
enum
{
temp = max3<v1,v2, v3>::value,
value = temp>v4?temp:v4
};
};
}
class entry; class entry;
class TORRENT_EXPORT entry class TORRENT_EXPORT entry
{ {
public: public:
// the key is always a string. If a generic entry would be a llowed // the key is always a string. If a generic entry would be a llowed
// as a key, sorting would become a problem (e.g. to compare a string // as a key, sorting would become a problem (e.g. to compare a string
// to a list). The definition doesn't mention such a limit t hough. // to a list). The definition doesn't mention such a limit t hough.
typedef std::map<std::string, entry> dictionary_type; typedef std::map<std::string, entry> dictionary_type;
skipping to change at line 216 skipping to change at line 191
// exceptions are used. // exceptions are used.
mutable bool m_type_queried:1; mutable bool m_type_queried:1;
protected: protected:
#endif // TORRENT_DEBUG #endif // TORRENT_DEBUG
#if (defined(_MSC_VER) && _MSC_VER < 1310) || TORRENT_COMPLETE_TYPES_REQUIR ED #if (defined(_MSC_VER) && _MSC_VER < 1310) || TORRENT_COMPLETE_TYPES_REQUIR ED
// workaround for msvc-bug. // workaround for msvc-bug.
// assumes sizeof(map<string, char>) == sizeof(map<string, e ntry>) // assumes sizeof(map<string, char>) == sizeof(map<string, e ntry>)
// and sizeof(list<char>) == sizeof(list<entry>) // and sizeof(list<char>) == sizeof(list<entry>)
enum { union_size enum { union_size
= detail::max4<sizeof(std::list<char>) = max4<sizeof(std::list<char>)
, sizeof(std::map<std::string, char>) , sizeof(std::map<std::string, char>)
, sizeof(string_type) , sizeof(string_type)
, sizeof(integer_type)>::value , sizeof(integer_type)>::value
}; };
#else #else
enum { union_size enum { union_size
= detail::max4<sizeof(list_type) = max4<sizeof(list_type)
, sizeof(dictionary_type) , sizeof(dictionary_type)
, sizeof(string_type) , sizeof(string_type)
, sizeof(integer_type)>::value , sizeof(integer_type)>::value
}; };
#endif #endif
integer_type data[(union_size + sizeof(integer_type) - 1) integer_type data[(union_size + sizeof(integer_type) - 1)
/ sizeof(integer_type)]; / sizeof(integer_type)];
}; };
#if defined TORRENT_DEBUG && TORRENT_USE_IOSTREAM #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;
} }
 End of changes. 5 change blocks. 
29 lines changed or deleted 3 lines changed or added


 enum_net.hpp   enum_net.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_ENUM_NET_HPP_INCLUDED #ifndef TORRENT_ENUM_NET_HPP_INCLUDED
#define TORRENT_ENUM_NET_HPP_INCLUDED #define TORRENT_ENUM_NET_HPP_INCLUDED
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp" #include <vector>
#include "libtorrent/io_service_fwd.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/error_code.hpp"
namespace libtorrent namespace libtorrent
{ {
// the interface should not have a netmask
struct ip_interface struct ip_interface
{ {
address interface_address; address interface_address;
address netmask; address netmask;
char name[64]; char name[64];
int mtu;
}; };
struct ip_route struct ip_route
{ {
address destination; address destination;
address netmask; address netmask;
address gateway; address gateway;
char name[64]; char name[64];
int mtu;
}; };
// returns a list of the configured IP interfaces // returns a list of the configured IP interfaces
// on the machine // on the machine
TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(io_serv ice& ios TORRENT_EXPORT std::vector<ip_interface> enum_net_interfaces(io_serv ice& ios
, error_code& ec); , error_code& ec);
TORRENT_EXPORT std::vector<ip_route> enum_routes(io_service& ios, er ror_code& ec); TORRENT_EXPORT std::vector<ip_route> enum_routes(io_service& ios, er ror_code& ec);
// returns true if the specified address is on the same // return (a1 & mask) == (a2 & mask)
// local network as the specified interface TORRENT_EXPORT bool match_addr_mask(address const& a1, address const
TORRENT_EXPORT bool in_subnet(address const& addr, ip_interface cons & a2, address const& mask);
t& iface);
// returns true if the specified address is on the same // returns true if the specified address is on the same
// local network as us // local network as us
TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr TORRENT_EXPORT bool in_local_network(io_service& ios, address const& addr
, error_code& ec); , error_code& ec);
TORRENT_EXPORT address get_default_gateway(io_service& ios TORRENT_EXPORT address get_default_gateway(io_service& ios
, error_code& ec); , error_code& ec);
} }
 End of changes. 5 change blocks. 
5 lines changed or deleted 10 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> #include "libtorrent/config.hpp"
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN #if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already // asio assumes that the windows error codes are defined already
#include <winsock2.h> #include <winsock2.h>
#endif #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 <string.h> // strdup
#include <stdlib.h> // free
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,
skipping to change at line 167 skipping to change at line 168
torrent_finished, torrent_finished,
no_router, no_router,
metadata_too_large, metadata_too_large,
invalid_metadata_request, invalid_metadata_request,
invalid_metadata_size, invalid_metadata_size,
invalid_metadata_offset, invalid_metadata_offset,
invalid_metadata_message, invalid_metadata_message,
pex_message_too_large, pex_message_too_large,
invalid_pex_message, invalid_pex_message,
invalid_lt_tracker_message, invalid_lt_tracker_message,
reserved108, too_frequent_pex,
reserved109, no_metadata,
invalid_dont_have, invalid_dont_have,
reserved111, requires_ssl_connection,
reserved112, invalid_ssl_cert,
reserved113, reserved113,
reserved114, reserved114,
reserved115, reserved115,
reserved116, reserved116,
reserved117, reserved117,
reserved118, reserved118,
reserved119, reserved119,
// natpmp errors // natpmp errors
unsupported_protocol_version, // 120 unsupported_protocol_version, // 120
skipping to change at line 226 skipping to change at line 227
http_missing_location, http_missing_location,
http_failed_decompress, http_failed_decompress,
reserved153, reserved153,
reserved154, reserved154,
reserved155, reserved155,
reserved156, reserved156,
reserved157, reserved157,
reserved158, reserved158,
reserved159, reserved159,
// i2p errors
no_i2p_router, // 160
reserved161,
reserved162,
reserved163,
reserved164,
reserved165,
reserved166,
reserved167,
reserved168,
reserved169,
// tracker errors
scrape_not_available, // 170
invalid_tracker_response,
invalid_peer_dict,
tracker_failure,
invalid_files_entry,
invalid_hash_entry,
invalid_peers_entry,
invalid_tracker_response_length,
invalid_tracker_transaction_id,
invalid_tracker_action,
reserved180,
reserved181,
reserved182,
reserved183,
reserved184,
reserved185,
reserved186,
reserved187,
reserved188,
reserved189,
// bdecode errors
expected_string, // 190
expected_colon,
unexpected_eof,
expected_value,
depth_exceeded,
limit_exceeded,
error_code_max error_code_max
}; };
enum http_errors
{
cont = 100,
ok = 200,
created = 201,
accepted = 202,
no_content = 204,
multiple_choices = 300,
moved_permanently = 301,
moved_temporarily = 302,
not_modified = 304,
bad_request = 400,
unauthorized = 401,
forbidden = 403,
not_found = 404,
internal_server_error = 500,
not_implemented = 501,
bad_gateway = 502,
service_unavailable = 503
};
} }
} }
#if BOOST_VERSION >= 103500 #if BOOST_VERSION >= 103500
namespace boost { namespace system { namespace boost { namespace system {
template<> struct is_error_code_enum<libtorrent::errors::error_code_ enum> template<> struct is_error_code_enum<libtorrent::errors::error_code_ enum>
{ static const bool value = true; }; { static const bool value = true; };
skipping to change at line 258 skipping to change at line 322
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() boost::system::error_category const& get_libtorrent_category()
{ {
static ::asio::error::error_category libtorrent_category(20) ; static ::asio::error::error_category libtorrent_category(20) ;
return libtorrent_category; return libtorrent_category;
} }
boost::system::error_category const& get_http_category()
{
static ::asio::error::error_category http_category(21);
return http_category;
}
#else #else
struct TORRENT_EXPORT libtorrent_error_category : boost::system::err or_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); }
}; };
inline boost::system::error_category& get_libtorrent_category() inline boost::system::error_category& get_libtorrent_category()
{ {
static libtorrent_error_category libtorrent_category; static libtorrent_error_category libtorrent_category;
return libtorrent_category; return libtorrent_category;
} }
struct TORRENT_EXPORT http_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); }
};
inline boost::system::error_category& get_http_category()
{
static http_error_category http_category;
return http_category;
}
namespace errors namespace errors
{ {
inline boost::system::error_code make_error_code(error_code_ enum e) inline boost::system::error_code make_error_code(error_code_ enum e)
{ {
return boost::system::error_code(e, get_libtorrent_c ategory()); 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()
skipping to change at line 296 skipping to change at line 380
#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 // BOOST_VERSION < 103600 #endif // BOOST_VERSION < 103600
#endif // BOOST_VERSION < 103500 #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), m_msg (0) {}
virtual const char* what() const throw() virtual const char* what() const throw()
{ {
if (!m_msg) m_msg.reset(new std::string(m_error.mess if (!m_msg)
age())); {
return m_msg->c_str(); std::string msg = m_error.message();
m_msg = strdup(msg.c_str());
}
return m_msg;
} }
virtual ~libtorrent_exception() throw() {} virtual ~libtorrent_exception() throw() { free(m_msg); }
error_code error() const { return m_error; } error_code error() const { return m_error; }
private: private:
error_code m_error; error_code m_error;
mutable boost::shared_ptr<std::string> m_msg; mutable char* m_msg;
}; };
#endif #endif
} }
#endif #endif
 End of changes. 12 change blocks. 
12 lines changed or deleted 102 lines changed or added


 escape_string.hpp   escape_string.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_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 <boost/limits.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" #include "libtorrent/error_code.hpp"
namespace libtorrent namespace libtorrent
{ {
TORRENT_EXPORT boost::array<char, 3 + std::numeric_limits<size_type> TORRENT_EXTRA_EXPORT boost::array<char, 4 + std::numeric_limits<size
::digits10> to_string(size_type n); _type>::digits10> to_string(size_type n);
TORRENT_EXTRA_EXPORT bool is_alpha(char c);
TORRENT_EXPORT bool is_digit(char c); TORRENT_EXPORT bool is_digit(char c);
TORRENT_EXPORT bool is_print(char c); TORRENT_EXTRA_EXPORT bool is_print(char c);
TORRENT_EXPORT bool is_space(char c); TORRENT_EXTRA_EXPORT bool is_space(char c);
TORRENT_EXPORT char to_lower(char c); TORRENT_EXTRA_EXPORT char to_lower(char c);
TORRENT_EXPORT bool string_begins_no_case(char const* s1, char const TORRENT_EXTRA_EXPORT int split_string(char const** tags, int buf_siz
* s2); e, char* in);
TORRENT_EXPORT bool string_equal_no_case(char const* s1, char const* TORRENT_EXTRA_EXPORT bool string_begins_no_case(char const* s1, char
s2); const* s2);
TORRENT_EXTRA_EXPORT bool string_equal_no_case(char const* s1, char
const* s2);
TORRENT_EXPORT std::string unescape_string(std::string const& s, err TORRENT_EXTRA_EXPORT void url_random(char* begin, char* end);
or_code& ec);
TORRENT_EXTRA_EXPORT std::string unescape_string(std::string const&
s, error_code& ec);
// replaces all disallowed URL characters by their %-encoding // replaces all disallowed URL characters by their %-encoding
TORRENT_EXPORT std::string escape_string(const char* str, int len); TORRENT_EXTRA_EXPORT std::string escape_string(const char* str, int len);
// same as escape_string but does not encode '/' // same as escape_string but does not encode '/'
TORRENT_EXPORT std::string escape_path(const char* str, int len); TORRENT_EXTRA_EXPORT std::string escape_path(const char* str, int le n);
// if the url does not appear to be encoded, and it contains illegal url characters // if the url does not appear to be encoded, and it contains illegal url characters
// it will be encoded // it will be encoded
TORRENT_EXPORT std::string maybe_url_encode(std::string const& url); TORRENT_EXTRA_EXPORT std::string maybe_url_encode(std::string const& url);
TORRENT_EXPORT bool need_encoding(char const* str, int len); TORRENT_EXTRA_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_EXTRA_EXPORT std::string base64encode(std::string const& s);
TORRENT_EXTRA_EXPORT std::string base64decode(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_EXTRA_EXPORT std::string base32encode(std::string const& s);
TORRENT_EXPORT std::string base32decode(std::string const& s); TORRENT_EXTRA_EXPORT std::string base32decode(std::string const& s);
TORRENT_EXPORT boost::optional<std::string> url_has_argument( TORRENT_EXTRA_EXPORT std::string url_has_argument(
std::string const& url, std::string argument, size_t* out_po std::string const& url, std::string argument, std::string::s
s = 0); ize_type* out_pos = 0);
// replaces \ with / // replaces \ with /
TORRENT_EXPORT void convert_path_to_posix(std::string& path); TORRENT_EXTRA_EXPORT void convert_path_to_posix(std::string& path);
TORRENT_EXPORT std::string read_until(char const*& str, char delim, char const* end); TORRENT_EXTRA_EXPORT std::string read_until(char const*& str, char d elim, 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 bool is_hex(char const *in, int len);
TORRENT_EXPORT void to_hex(char const *in, int len, char* out); TORRENT_EXPORT void to_hex(char const *in, int len, char* out);
TORRENT_EXPORT bool from_hex(char const *in, int len, char* out); TORRENT_EXPORT bool from_hex(char const *in, int len, char* out);
#if TORRENT_USE_WPATH #if defined TORRENT_WINDOWS && TORRENT_USE_WSTRING
TORRENT_EXPORT std::wstring convert_to_wstring(std::string const& s) TORRENT_EXTRA_EXPORT std::wstring convert_to_wstring(std::string con
; st& s);
TORRENT_EXTRA_EXPORT std::string convert_from_wstring(std::wstring c
onst& s);
#endif #endif
#if defined TORRENT_WINDOWS || TORRENT_USE_LOCALE_FILENAMES #if TORRENT_USE_ICONV || TORRENT_USE_LOCALE
TORRENT_EXPORT std::string convert_to_native(std::string const& s); TORRENT_EXTRA_EXPORT std::string convert_to_native(std::string const
& s);
TORRENT_EXTRA_EXPORT std::string convert_from_native(std::string con
st& s);
#else #else
inline std::string const& convert_to_native(std::string const& s) { return s; } inline std::string const& convert_to_native(std::string const& s) { return s; }
inline std::string const& convert_from_native(std::string const& s) { return s; }
#endif #endif
} }
#endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED #endif // TORRENT_ESCAPE_STRING_HPP_INCLUDED
 End of changes. 18 change blocks. 
31 lines changed or deleted 41 lines changed or added


 extensions.hpp   extensions.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_EXTENSIONS_HPP_INCLUDED #ifndef TORRENT_EXTENSIONS_HPP_INCLUDED
#define TORRENT_EXTENSIONS_HPP_INCLUDED #define TORRENT_EXTENSIONS_HPP_INCLUDED
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/shared_ptr.hpp> #include <boost/weak_ptr.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include <vector> #include <vector>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/buffer.hpp" #include "libtorrent/buffer.hpp"
#include "libtorrent/socket.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace aux { struct session_impl; }
struct peer_plugin; struct peer_plugin;
class bt_peer_connection; class bt_peer_connection;
struct peer_request; struct peer_request;
class peer_connection; class peer_connection;
class entry; class entry;
struct lazy_entry; struct lazy_entry;
struct disk_buffer_holder; struct disk_buffer_holder;
struct bitfield; struct bitfield;
class alert;
struct torrent_plugin;
class torrent;
struct TORRENT_EXPORT plugin
{
virtual ~plugin() {}
virtual boost::shared_ptr<torrent_plugin> new_torrent(torren
t* t, void* user)
{ return boost::shared_ptr<torrent_plugin>(); }
// called when plugin is added to a session
virtual void added(boost::weak_ptr<aux::session_impl> s) {}
// called when an alert is posted
// alerts that are filtered are not
// posted
virtual void on_alert(alert const* a) {}
// called once per second
virtual void on_tick() {}
// called when saving settings state
virtual void save_state(entry& ent) const {}
// called when loading settings state
virtual void load_state(lazy_entry const& ent) {}
};
struct TORRENT_EXPORT torrent_plugin struct TORRENT_EXPORT torrent_plugin
{ {
virtual ~torrent_plugin() {} virtual ~torrent_plugin() {}
// throwing an exception closes the connection // throwing an exception closes the connection
// returning a 0 pointer is valid and will not add // returning a 0 pointer is valid and will not add
// the peer_plugin to the peer_connection // the peer_plugin to the peer_connection
virtual boost::shared_ptr<peer_plugin> new_connection(peer_c onnection*) virtual boost::shared_ptr<peer_plugin> new_connection(peer_c onnection*)
{ return boost::shared_ptr<peer_plugin>(); } { return boost::shared_ptr<peer_plugin>(); }
virtual void on_piece_pass(int index) {} virtual void on_piece_pass(int index) {}
virtual void on_piece_failed(int index) {} virtual void on_piece_failed(int index) {}
// called aproximately once every second // called aproximately once every second
virtual void tick() {} virtual void tick() {}
// if true is returned, it means the handler handled the eve nt, // if true is returned, it means the handler handled the eve nt,
// and no other plugins will have their handlers called, and the // and no other plugins will have their handlers called, and the
// default behavior will be skipped // default behavior will be skipped
virtual bool on_pause() { return false; } virtual bool on_pause() { return false; }
virtual bool on_resume() { return false;} virtual bool on_resume() { return false; }
// this is called when the initial checking of // this is called when the initial checking of
// files is completed. // files is completed.
virtual void on_files_checked() {} virtual void on_files_checked() {}
// called when the torrent changes state
// the state is one of torrent_status::state_t
// enum members
virtual void on_state(int s) {}
// called every time policy::add_peer is called
// src is a bitmask of which sources this peer
// has been seen from. flags is a bitmask of:
enum flags_t {
// this is the first time we see this peer
first_time = 1,
// this peer was not added because it was
// filtered by the IP filter
filtered = 2
};
virtual void on_add_peer(tcp::endpoint const& ip
, int src, int flags) {}
}; };
struct TORRENT_EXPORT peer_plugin struct TORRENT_EXPORT peer_plugin
{ {
virtual ~peer_plugin() {} virtual ~peer_plugin() {}
virtual char const* type() const { return ""; }
// can add entries to the extension handshake // can add entries to the extension handshake
// this is not called for web seeds // this is not called for web seeds
virtual void add_handshake(entry&) {} virtual void add_handshake(entry&) {}
// throwing an exception from any of the handlers (except ad d_handshake) // throwing an exception from any of the handlers (except ad d_handshake)
// closes the connection // closes the connection
// this is called when the initial BT handshake is received. Returning false // this is called when the initial BT handshake is received. Returning false
// means that the other end doesn't support this extension a nd will remove // means that the other end doesn't support this extension a nd will remove
// it from the list of plugins. // it from the list of plugins.
 End of changes. 7 change blocks. 
2 lines changed or deleted 56 lines changed or added


 file.hpp   file.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_HPP_INCLUDED #ifndef TORRENT_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED #define TORRENT_FILE_HPP_INCLUDED
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/noncopyable.hpp> #include <boost/noncopyable.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"
#include "libtorrent/intrusive_ptr_base.hpp"
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
// windows part // windows part
#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 <winioctl.h> #include <winioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#else #else
// posix part // posix part
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
#ifndef _GNU_SOURCE #ifndef _GNU_SOURCE
#define _GNU_SOURCE #define _GNU_SOURCE
#endif #endif
#ifndef _XOPEN_SOURCE #ifndef _XOPEN_SOURCE
#define _XOPEN_SOURCE 600 #define _XOPEN_SOURCE 600
#endif #endif
#include <unistd.h> #include <unistd.h>
#include <sys/uio.h> #include <sys/uio.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <dirent.h> // for DIR
#undef _FILE_OFFSET_BITS #undef _FILE_OFFSET_BITS
#endif #endif
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; struct file_status
{
size_type file_size;
time_t atime;
time_t mtime;
time_t ctime;
enum {
#if defined TORRENT_WINDOWS
directory = _S_IFDIR,
regular_file = _S_IFREG
#else
fifo = S_IFIFO,
character_special = S_IFCHR,
directory = S_IFDIR,
block_special = S_IFBLK,
regular_file = S_IFREG,
link = S_IFLNK,
socket = S_IFSOCK
#endif
} modes_t;
int mode;
};
class TORRENT_EXPORT file: public boost::noncopyable enum stat_flags_t { dont_follow_links = 1 };
TORRENT_EXPORT void stat_file(std::string f, file_status* s
, error_code& ec, int flags = 0);
TORRENT_EXPORT void rename(std::string const& f
, std::string const& newf, error_code& ec);
TORRENT_EXPORT void create_directories(std::string const& f
, error_code& ec);
TORRENT_EXPORT void create_directory(std::string const& f
, error_code& ec);
TORRENT_EXPORT void remove_all(std::string const& f
, error_code& ec);
TORRENT_EXPORT void remove(std::string const& f, error_code& ec);
TORRENT_EXPORT bool exists(std::string const& f);
TORRENT_EXPORT size_type file_size(std::string const& f);
TORRENT_EXPORT bool is_directory(std::string const& f
, error_code& ec);
TORRENT_EXPORT void copy_file(std::string const& f
, std::string const& newf, error_code& ec);
TORRENT_EXPORT std::string split_path(std::string const& f);
TORRENT_EXPORT char const* next_path_element(char const* p);
TORRENT_EXPORT std::string extension(std::string const& f);
TORRENT_EXPORT void replace_extension(std::string& f, std::string co
nst& ext);
TORRENT_EXPORT bool is_root_path(std::string const& f);
TORRENT_EXPORT std::string parent_path(std::string const& f);
TORRENT_EXPORT bool has_parent_path(std::string const& f);
TORRENT_EXPORT std::string filename(std::string const& f);
TORRENT_EXPORT std::string combine_path(std::string const& lhs
, std::string const& rhs);
TORRENT_EXPORT std::string complete(std::string const& f);
TORRENT_EXPORT bool is_complete(std::string const& f);
TORRENT_EXPORT std::string current_working_directory();
#if TORRENT_USE_UNC_PATHS
TORRENT_EXTRA_EXPORT std::string canonicalize_path(std::string const
& f);
#endif
class TORRENT_EXPORT directory : public boost::noncopyable
{ {
public: public:
directory(std::string const& path, error_code& ec);
~directory();
void next(error_code& ec);
std::string file() const;
bool done() const { return m_done; }
private:
#ifdef TORRENT_WINDOWS
HANDLE m_handle;
#if TORRENT_USE_WSTRING
WIN32_FIND_DATAW m_fd;
#else
WIN32_FIND_DATAA m_fd;
#endif
#else
DIR* m_handle;
// the dirent struct contains a zero-sized
// array at the end, it will end up referring
// to the m_name field
struct dirent m_dirent;
char m_name[TORRENT_MAX_PATH + 1]; // +1 to make room for nu
ll
#endif
bool m_done;
};
struct TORRENT_EXPORT file: boost::noncopyable, intrusive_ptr_base<f
ile>
{
enum enum
{ {
// when a file is opened with no_buffer // when a file is opened with no_buffer
// file offsets have to be aligned to // file offsets have to be aligned to
// pos_alignment() and buffer addresses // pos_alignment() and buffer addresses
// to buf_alignment() and read/write sizes // to buf_alignment() and read/write sizes
// to size_alignment() // to size_alignment()
read_only = 0, read_only = 0,
write_only = 1, write_only = 1,
read_write = 2, read_write = 2,
rw_mask = read_only | write_only | read_write, rw_mask = read_only | write_only | read_write,
no_buffer = 4, no_buffer = 4,
mode_mask = rw_mask | no_buffer,
sparse = 8, sparse = 8,
no_atime = 16,
random_access = 32, random_access = 32,
lock_file = 64,
attribute_hidden = 0x1000, attribute_hidden = 0x1000,
attribute_executable = 0x2000, attribute_executable = 0x2000,
attribute_mask = attribute_hidden | attribute_execut able attribute_mask = attribute_hidden | attribute_execut able
}; };
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
struct iovec_t struct iovec_t
{ {
void* iov_base; void* iov_base;
skipping to change at line 129 skipping to change at line 217
// use a typedef for the type of iovec_t::iov_base // use a typedef for the type of iovec_t::iov_base
// since it may differ // since it may differ
#ifdef TORRENT_SOLARIS #ifdef TORRENT_SOLARIS
typedef char* iovec_base_t; typedef char* iovec_base_t;
#else #else
typedef void* iovec_base_t; typedef void* iovec_base_t;
#endif #endif
file(); file();
file(fs::path const& p, int m, error_code& ec); file(std::string const& p, int m, error_code& ec);
~file(); ~file();
bool open(fs::path const& p, int m, error_code& ec); bool open(std::string 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);
// called when we're done writing to the file.
// On windows this will clear the sparse bit
void finalize();
int open_mode() const { return m_open_mode; } int open_mode() const { return m_open_mode; }
// when opened in unbuffered mode, this is the // when opened in unbuffered mode, this is the
// required alignment of file_offsets. i.e. // required alignment of file_offsets. i.e.
// any (file_offset & (pos_alignment()-1)) == 0 // any (file_offset & (pos_alignment()-1)) == 0
// is a precondition to read and write operations // is a precondition to read and write operations
int pos_alignment() const; int pos_alignment() const;
// when opened in unbuffered mode, this is the // when opened in unbuffered mode, this is the
// required alignment of buffer addresses // required alignment of buffer addresses
int buf_alignment() const; int buf_alignment() const;
// read/write buffer sizes needs to be aligned to // read/write buffer sizes needs to be aligned to
// this when in unbuffered mode // this when in unbuffered mode
int size_alignment() const; int size_alignment() const;
size_type writev(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec); 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 readv(size_type file_offset, iovec_t const* bufs, int num_bufs, error_code& ec);
void hint_read(size_type file_offset, int len);
size_type get_size(error_code& ec) const; size_type get_size(error_code& ec) const;
// return the offset of the first byte that // return the offset of the first byte that
// belongs to a data-region // belongs to a data-region
size_type sparse_end(size_type start) const; size_type sparse_end(size_type start) const;
size_type phys_offset(size_type offset); size_type phys_offset(size_type offset);
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
HANDLE native_handle() const { return m_file_handle; } HANDLE native_handle() const { return m_file_handle; }
#else #else
int native_handle() const { return m_fd; } int native_handle() const { return m_fd; }
#endif #endif
private: private:
#ifdef TORRENT_WINDOWS #ifdef TORRENT_WINDOWS
HANDLE m_file_handle; HANDLE m_file_handle;
#if TORRENT_USE_WPATH #if TORRENT_USE_WSTRING
std::wstring m_path; std::wstring m_path;
#else #else
std::string m_path; std::string m_path;
#endif #endif // TORRENT_USE_WSTRING
#else #else // TORRENT_WINDOWS
int m_fd; int m_fd;
#endif #endif // TORRENT_WINDOWS
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX || defined TORRENT_DEB UG #if defined TORRENT_WINDOWS || defined TORRENT_LINUX || defined TORRENT_DEB UG
static void init_file(); static void init_file();
static int m_page_size; static int m_page_size;
#endif #endif
int m_open_mode; int m_open_mode;
#if defined TORRENT_WINDOWS || defined TORRENT_LINUX #if defined TORRENT_WINDOWS || defined TORRENT_LINUX
mutable int m_sector_size; mutable int m_sector_size;
#endif #endif
#if defined TORRENT_WINDOWS #if defined TORRENT_WINDOWS
mutable int m_cluster_size; mutable int m_cluster_size;
 End of changes. 21 change blocks. 
11 lines changed or deleted 109 lines changed or added


 file_pool.hpp   file_pool.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#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/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include <map>
#include "libtorrent/file.hpp" #include "libtorrent/file.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/ptime.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/file_storage.hpp"
namespace libtorrent namespace libtorrent
{ {
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), m_low_prio_io(true) file_pool(int size = 40);
{} ~file_pool();
boost::shared_ptr<file> open_file(void* st, fs::path const& boost::intrusive_ptr<file> open_file(void* st, std::string c
p onst& p
, int m, error_code& ec); , file_storage::iterator fe, file_storage const& fs,
int m, error_code& ec);
void release(void* st); void release(void* st);
void release(fs::path const& p); void release(void* st, int file_index);
void resize(int size); void resize(int size);
int size_limit() const { return m_size; } int size_limit() const { return m_size; }
void set_low_prio_io(bool b) { m_low_prio_io = b; } void set_low_prio_io(bool b) { m_low_prio_io = b; }
private: private:
file_pool(file_pool const&);
void remove_oldest(); void remove_oldest();
int m_size; int m_size;
bool m_low_prio_io; bool m_low_prio_io;
struct lru_file_entry struct lru_file_entry
{ {
lru_file_entry(): last_use(time_now()) {} lru_file_entry(): key(0), last_use(time_now()), mode
mutable boost::shared_ptr<file> file_ptr; (0) {}
mutable boost::intrusive_ptr<file> file_ptr;
void* key; void* key;
ptime last_use; ptime last_use;
int mode; int mode;
}; };
typedef std::map<std::string, lru_file_entry> file_set; // maps storage pointer, file index pairs to the
// lru entry for the file
typedef std::map<std::pair<void*, int>, lru_file_entry> file
_set;
file_set m_files; file_set m_files;
boost::mutex m_mutex; mutex m_mutex;
#if TORRENT_CLOSE_MAY_BLOCK
void closer_thread_fun();
mutex m_closer_mutex;
std::vector<boost::intrusive_ptr<file> > m_queued_for_close;
bool m_stop_thread;
// used to close files
thread m_closer_thread;
#endif
}; };
} }
#endif #endif
 End of changes. 11 change blocks. 
17 lines changed or deleted 30 lines changed or added


 file_storage.hpp   file_storage.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#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> #include <ctime>
#ifdef _MSC_VER
#pragma warning(push, 1)
#endif
#include <boost/filesystem/path.hpp>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#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"
#include "libtorrent/peer_id.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; struct file;
struct TORRENT_EXPORT file_entry struct TORRENT_EXPORT file_entry
{ {
file_entry(): offset(0), size(0), file_base(0) file_entry();
, mtime(0), pad_file(false), hidden_attribute(false) ~file_entry();
, executable_attribute(false)
, symlink_attribute(false)
{}
fs::path path; std::string 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; std::time_t mtime;
sha1_hash filehash;
bool pad_file:1; bool pad_file:1;
bool hidden_attribute:1; bool hidden_attribute:1;
bool executable_attribute:1; bool executable_attribute:1;
bool symlink_attribute:1; bool symlink_attribute:1;
fs::path symlink_path; std::string symlink_path;
};
// this is used internally to hold the file entry
// it's smaller and optimized for smaller memory
// footprint, as opposed to file_entry, which is
// optimized for convenience
struct TORRENT_EXPORT internal_file_entry
{
friend class file_storage;
#ifdef TORRENT_DEBUG
// for torrent_info::invariant_check
friend class torrent_info;
#endif
internal_file_entry()
: name(0)
, offset(0)
, symlink_index(-1)
, size(0)
, name_len(0)
, pad_file(false)
, hidden_attribute(false)
, executable_attribute(false)
, symlink_attribute(false)
, path_index(-1)
{}
internal_file_entry(file_entry const& e)
: name(0)
, offset(e.offset)
, symlink_index(-1)
, size(e.size)
, name_len(0)
, pad_file(e.pad_file)
, hidden_attribute(e.hidden_attribute)
, executable_attribute(e.executable_attribute)
, symlink_attribute(e.symlink_attribute)
, path_index(-1)
{
set_name(e.path.c_str());
}
internal_file_entry(internal_file_entry const& fe);
internal_file_entry& operator=(internal_file_entry const& fe
);
~internal_file_entry();
void set_name(char const* n, int borrow_chars = 0);
std::string filename() const;
// make it available for logging
#if !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
private:
#endif
// This string is not necessarily null terminated!
// that's why it's private, to keep people away from it
char const* name;
public:
// the offset of this file inside the torrent
size_type offset:48;
// index into file_storage::m_symlinks or -1
// if this is not a symlink
size_type symlink_index:16;
// the size of this file
size_type size:48;
// the number of characters in the name. If this is
// 0, name is null terminated and owned by this object
// (i.e. it should be freed in the destructor). If
// the len is > 0, the name pointer doesn not belong
// to this object, and it's not null terminated
size_type name_len:10;
bool pad_file:1;
bool hidden_attribute:1;
bool executable_attribute:1;
bool symlink_attribute:1;
// the index into file_storage::m_paths. To get
// the full path to this file, concatenate the path
// from that array with the 'name' field in
// this struct
int path_index;
}; };
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
skipping to change at line 105 skipping to change at line 179
bool is_valid() const { return m_piece_length > 0; } bool is_valid() const { return m_piece_length > 0; }
enum flags_t enum flags_t
{ {
pad_file = 1, pad_file = 1,
attribute_hidden = 2, attribute_hidden = 2,
attribute_executable = 4, attribute_executable = 4,
attribute_symlink = 8 attribute_symlink = 8
}; };
void add_file(file_entry const& e); void reserve(int num_files);
void add_file(fs::path const& p, size_type size, int flags =
0, std::time_t mtime = 0, fs::path const& s_p = ""); void add_file(file_entry const& e, char const* filehash = 0)
;
void add_file(std::string const& p, size_type size, int flag
s = 0
, std::time_t mtime = 0, std::string 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 #if TORRENT_USE_WSTRING
void add_file(fs::wpath const& p, size_type size, int flags void add_file(std::wstring const& p, size_type size, int fla
= 0, std::time_t mtime = 0, fs::path const& s_p = ""); gs = 0
, std::time_t mtime = 0, std::string const& s_p = ""
);
void rename_file(int index, std::wstring const& new_filename ); void rename_file(int index, std::wstring const& new_filename );
void set_name(std::wstring const& n); void set_name(std::wstring const& n);
#endif #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<internal_file_entry>::const_iterator ite
typedef std::vector<file_entry>::const_reverse_iterator reve rator;
rse_iterator; typedef std::vector<internal_file_entry>::const_reverse_iter
ator reverse_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(); }
reverse_iterator rbegin() const { return m_files.rbegin(); } reverse_iterator rbegin() const { return m_files.rbegin(); }
reverse_iterator rend() const { return m_files.rend(); } reverse_iterator rend() const { return m_files.rend(); }
int num_files() const int num_files() const
{ return int(m_files.size()); } { return int(m_files.size()); }
file_entry const& at(int index) const file_entry at(int index) const;
file_entry at(iterator i) const;
internal_file_entry const& internal_at(int index) const
{ {
TORRENT_ASSERT(index >= 0 && index < int(m_files.siz TORRENT_ASSERT(index >= 0);
e())); TORRENT_ASSERT(index < int(m_files.size()));
return m_files[index]; return m_files[index];
} }
size_type total_size() const { return m_total_size; } size_type total_size() const { return m_total_size; }
void set_num_pieces(int n) { m_num_pieces = n; } void set_num_pieces(int n) { m_num_pieces = n; }
int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; } int num_pieces() const { TORRENT_ASSERT(m_piece_length > 0); return m_num_pieces; }
void set_piece_length(int l) { m_piece_length = l; } void set_piece_length(int l) { m_piece_length = l; }
int piece_length() const { TORRENT_ASSERT(m_piece_length > 0 ); return m_piece_length; } int piece_length() const { TORRENT_ASSERT(m_piece_length > 0 ); return m_piece_length; }
int piece_size(int index) const; int piece_size(int index) const;
void set_name(std::string const& n) { m_name = n; } void set_name(std::string const& n) { m_name = n; }
const std::string& name() const { return m_name; } const std::string& name() const { return m_name; }
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_files, m_files); swap(ti.m_files, m_files);
swap(ti.m_file_hashes, m_file_hashes);
swap(ti.m_symlinks, m_symlinks);
swap(ti.m_mtime, m_mtime);
swap(ti.m_file_base, m_file_base);
swap(ti.m_paths, m_paths);
swap(ti.m_name, m_name);
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_piece_length, m_piece_length);
} }
// if pad_file_limit >= 0, files larger than // if pad_file_limit >= 0, files larger than
// that limit will be padded, default is to // that limit will be padded, default is to
// not add any padding // not add any padding
void optimize(int pad_file_limit = -1); void optimize(int pad_file_limit = -1);
sha1_hash hash(int index) const;
std::string const& symlink(int index) const;
time_t mtime(int index) const;
int file_index(int index) const;
size_type file_base(int index) const;
void set_file_base(int index, size_type off);
std::string file_path(int index) const;
size_type file_size(int index) const;
sha1_hash hash(internal_file_entry const& fe) const;
std::string const& symlink(internal_file_entry const& fe) co
nst;
time_t mtime(internal_file_entry const& fe) const;
int file_index(internal_file_entry const& fe) const;
size_type file_base(internal_file_entry const& fe) const;
void set_file_base(internal_file_entry const& fe, size_type
off);
std::string file_path(internal_file_entry const& fe) const;
size_type file_size(internal_file_entry const& fe) const;
#if !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
private: private:
int m_piece_length; #endif
void update_path_index(internal_file_entry& e);
void reorder_file(int index, int dst);
// 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<internal_file_entry> m_files;
// if there are sha1 hashes for each individual file
// there are as many entries in this array as the
// m_files array. Each entry in m_files has a corresponding
// hash pointer in this array. The reason to split it up
// in separate arrays is to save memory in case the torrent
// doesn't have file hashes
std::vector<char const*> m_file_hashes;
// for files that are symlinks, the symlink
// path_index in the internal_file_entry indexes
// this vector of strings
std::vector<std::string> m_symlinks;
// the modification times of each file. This vector
// is empty if no file have a modification time.
// each element corresponds to the file with the same
// index in m_files
std::vector<time_t> m_mtime;
// if any file has a non-zero file base (i.e. multiple
// files residing in the same physical file at different
// offsets)
std::vector<size_type> m_file_base;
// all unique paths files have. The internal_file_entry::pat
h_index
// points into this array
std::vector<std::string> m_paths;
// name of torrent. For multi-file torrents
// this is always the root directory
std::string m_name;
// 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
int m_num_pieces; int m_num_pieces;
std::string m_name;
int m_piece_length;
}; };
} }
#endif // TORRENT_FILE_STORAGE_HPP_INCLUDED #endif // TORRENT_FILE_STORAGE_HPP_INCLUDED
 End of changes. 19 change blocks. 
35 lines changed or deleted 187 lines changed or added


 find_data.hpp   find_data.hpp 
skipping to change at line 47 skipping to change at line 47
#include <map> #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/function1.hpp>
#include <boost/function/function2.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; class node_impl;
// -------- find data ----------- // -------- find data -----------
//TODO: rename this to find_peers
class find_data : public traversal_algorithm class find_data : public traversal_algorithm
{ {
public: public:
typedef boost::function<void(std::vector<tcp::endpoint> const&)> dat a_callback; typedef boost::function<void(std::vector<tcp::endpoint> const&)> dat a_callback;
typedef boost::function<void(std::vector<std::pair<node_entry, std:: string> > const&)> nodes_callback; typedef boost::function<void(std::vector<std::pair<node_entry, std:: string> > const&, bool)> nodes_callback;
void got_data(msg const* m); void got_peers(std::vector<tcp::endpoint> const& peers);
void got_write_token(node_id const& n, std::string const& write_toke n) void got_write_token(node_id const& n, std::string const& write_toke n)
{ m_write_tokens[n] = write_token; } { m_write_tokens[n] = write_token; }
find_data(node_impl& node, node_id target find_data(node_impl& node, node_id target
, data_callback const& dcallback , data_callback const& dcallback
, nodes_callback const& ncallback); , nodes_callback const& ncallback
, bool noseeds);
virtual char const* name() const { return "get_peers"; } virtual char const* name() const { return "get_peers"; }
node_id const target() const { return m_target; } node_id const target() const { return m_target; }
private: protected:
void done(); void done();
void invoke(node_id const& id, udp::endpoint addr); observer_ptr new_observer(void* ptr, udp::endpoint const& ep, node_i
d const& id);
virtual bool invoke(observer_ptr o);
private:
data_callback m_data_callback; data_callback m_data_callback;
nodes_callback m_nodes_callback; nodes_callback m_nodes_callback;
std::map<node_id, std::string> m_write_tokens; std::map<node_id, std::string> m_write_tokens;
node_id const m_target; node_id const m_target;
bool m_done; bool m_done:1;
bool m_got_peers:1;
bool m_noseeds:1;
}; };
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<traversal_algorithm> const& algorithm
, node_id self) , udp::endpoint const& ep, node_id const& id)
: observer(algorithm->allocator()) : observer(algorithm, ep, id)
, m_algorithm(algorithm)
, m_self(self)
{} {}
~find_data_observer();
void send(msg& m)
{
m.reply = false;
m.message_id = messages::get_peers;
m.info_hash = m_algorithm->target();
}
void timeout();
void reply(msg const&); void reply(msg const&);
void abort() { m_algorithm = 0; }
private:
boost::intrusive_ptr<find_data> m_algorithm;
node_id const m_self;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // FIND_DATA_050323_HPP #endif // FIND_DATA_050323_HPP
 End of changes. 12 change blocks. 
27 lines changed or deleted 20 lines changed or added


 gzip.hpp   gzip.hpp 
skipping to change at line 43 skipping to change at line 43
#ifndef TORRENT_GZIP_HPP_INCLUDED #ifndef TORRENT_GZIP_HPP_INCLUDED
#define TORRENT_GZIP_HPP_INCLUDED #define TORRENT_GZIP_HPP_INCLUDED
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
namespace libtorrent namespace libtorrent
{ {
TORRENT_EXPORT bool inflate_gzip( TORRENT_EXTRA_EXPORT bool inflate_gzip(
char const* in, int size char const* in, int size
, std::vector<char>& buffer , std::vector<char>& buffer
, int maximum_size , int maximum_size
, std::string& error); , std::string& error);
} }
#endif #endif
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 hasher.hpp   hasher.hpp 
skipping to change at line 41 skipping to change at line 41
*/ */
#ifndef TORRENT_HASHER_HPP_INCLUDED #ifndef TORRENT_HASHER_HPP_INCLUDED
#define TORRENT_HASHER_HPP_INCLUDED #define TORRENT_HASHER_HPP_INCLUDED
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "zlib.h"
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>
#elif defined TORRENT_USE_OPENSSL
extern "C" extern "C"
{ {
#include <openssl/sha.h> #include <openssl/sha.h>
} }
#else #else
// from sha1.cpp // from sha1.cpp
struct TORRENT_EXPORT SHA_CTX struct TORRENT_EXTRA_EXPORT SHA_CTX
{ {
boost::uint32_t state[5]; boost::uint32_t state[5];
boost::uint32_t count[2]; boost::uint32_t count[2];
boost::uint8_t buffer[64]; boost::uint8_t buffer[64];
}; };
TORRENT_EXPORT void SHA1_Init(SHA_CTX* context); TORRENT_EXTRA_EXPORT void SHA1_Init(SHA_CTX* context);
TORRENT_EXPORT void SHA1_Update(SHA_CTX* context, boost::uint8_t const* dat TORRENT_EXTRA_EXPORT void SHA1_Update(SHA_CTX* context, boost::uint8_t cons
a, boost::uint32_t len); t* data, boost::uint32_t len);
TORRENT_EXPORT void SHA1_Final(boost::uint8_t* digest, SHA_CTX* context); TORRENT_EXTRA_EXPORT void SHA1_Final(boost::uint8_t* digest, SHA_CTX* conte
xt);
#endif #endif
namespace libtorrent namespace libtorrent
{ {
class hasher
class adler32_crc
{ {
public: public:
adler32_crc(): m_adler(adler32(0, 0, 0)) {}
void update(const char* data, int len) hasher()
{ {
TORRENT_ASSERT(data != 0); #ifdef TORRENT_USE_GCRYPT
TORRENT_ASSERT(len > 0); gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
m_adler = adler32(m_adler, (const Bytef*)data, len); #else
SHA1_Init(&m_context);
#endif
} }
unsigned long final() const { return m_adler; }
void reset() { m_adler = adler32(0, 0, 0); }
private:
unsigned long m_adler;
};
class hasher
{
public:
hasher() { SHA1_Init(&m_context); }
hasher(const char* data, int len) hasher(const char* data, int len)
{ {
SHA1_Init(&m_context);
TORRENT_ASSERT(data != 0); TORRENT_ASSERT(data != 0);
TORRENT_ASSERT(len > 0); TORRENT_ASSERT(len > 0);
#ifdef TORRENT_USE_GCRYPT
gcry_md_open(&m_context, GCRY_MD_SHA1, 0);
gcry_md_write(m_context, data, len);
#else
SHA1_Init(&m_context);
SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len); SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len);
#endif
} }
void update(std::string const& data) { update(&data[0], data
.size()); } #ifdef TORRENT_USE_GCRYPT
hasher(hasher const& h)
{
gcry_md_copy(&m_context, h.m_context);
}
hasher& operator=(hasher const& h)
{
gcry_md_close(m_context);
gcry_md_copy(&m_context, h.m_context);
return *this;
}
#endif
void update(std::string const& data) { update(data.c_str(),
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);
#ifdef TORRENT_USE_GCRYPT
gcry_md_write(m_context, data, len);
#else
SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len); SHA1_Update(&m_context, reinterpret_cast<unsigned ch ar const*>(data), len);
#endif
} }
sha1_hash final() sha1_hash final()
{ {
sha1_hash digest; sha1_hash digest;
#ifdef TORRENT_USE_GCRYPT
gcry_md_final(m_context);
digest.assign((const char*)gcry_md_read(m_context, 0
));
#else
SHA1_Final(digest.begin(), &m_context); SHA1_Final(digest.begin(), &m_context);
#endif
return digest; return digest;
} }
void reset() { SHA1_Init(&m_context); } void reset()
{
#ifdef TORRENT_USE_GCRYPT
gcry_md_reset(m_context);
#else
SHA1_Init(&m_context);
#endif
}
#ifdef TORRENT_USE_GCRYPT
~hasher()
{
gcry_md_close(m_context);
}
#endif
private: private:
#ifdef TORRENT_USE_GCRYPT
gcry_md_hd_t m_context;
#else
SHA_CTX m_context; SHA_CTX m_context;
#endif
}; };
} }
#endif // TORRENT_HASHER_HPP_INCLUDED #endif // TORRENT_HASHER_HPP_INCLUDED
 End of changes. 20 change blocks. 
33 lines changed or deleted 68 lines changed or added


 http_connection.hpp   http_connection.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_HTTP_CONNECTION #ifndef TORRENT_HTTP_CONNECTION
#define TORRENT_HTTP_CONNECTION #define TORRENT_HTTP_CONNECTION
#include <boost/function.hpp> #include <boost/function/function1.hpp>
#include <boost/function/function2.hpp>
#include <boost/function/function5.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/enable_shared_from_this.hpp> #include <boost/enable_shared_from_this.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
#include <vector> #include <vector>
#include <list> #include <list>
#include <string> #include <string>
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/http_parser.hpp" #include "libtorrent/http_parser.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/deadline_timer.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/i2p_stream.hpp"
#ifdef TORRENT_USE_OPENSSL #ifdef TORRENT_USE_OPENSSL
#include "libtorrent/ssl_stream.hpp" #include <boost/asio/ssl/context.hpp>
#include "libtorrent/variant_stream.hpp"
#endif #endif
namespace libtorrent namespace libtorrent
{ {
struct http_connection; struct http_connection;
class connection_queue; class connection_queue;
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;
typedef boost::function<void(http_connection&, std::list<tcp::endpoint>&)> http_filter_handler; 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 TORRENT_EXPORT http_connection : boost::enable_shared_from_this<http _connection>, boost::noncopyable struct TORRENT_EXTRA_EXPORT http_connection : boost::enable_shared_from_thi s<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()
, http_filter_handler const& fh = http_filter_handler()) , http_filter_handler const& fh = http_filter_handler()
: m_sock(ios) #ifdef TORRENT_USE_OPENSSL
#if TORRENT_USE_I2P , boost::asio::ssl::context* ssl_ctx = 0
, m_i2p_conn(0)
#endif #endif
, m_read_pos(0) );
, m_resolver(ios)
, m_handler(handler) ~http_connection();
, m_connect_handler(ch)
, m_filter_handler(fh)
, m_timer(ios)
, m_last_receive(time_now())
, m_bottled(bottled)
, m_called(false)
, m_rate_limit(0)
, m_download_quota(0)
, m_limiter_timer_active(false)
, m_limiter_timer(ios)
, m_redirects(5)
, m_connection_ticket(-1)
, m_cc(cc)
, m_ssl(false)
, m_priority(0)
, m_abort(false)
{
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;
void get(std::string const& url, time_duration timeout = seconds(30) void get(std::string const& url, time_duration timeout = seconds(30)
, int prio = 0, proxy_settings const* ps = 0, int handle_red irects = 5 , int prio = 0, proxy_settings const* ps = 0, int handle_red irects = 5
, std::string const& user_agent = "", address const& bind_ad , std::string const& user_agent = "", address const& bind_ad
dr = address_v4::any()); dr = address_v4::any()
#if TORRENT_USE_I2P
, i2p_connection* i2p_conn = 0
#endif
);
void start(std::string const& hostname, std::string const& port void start(std::string const& hostname, std::string const& port
, time_duration timeout, int prio = 0, proxy_settings const* ps = 0 , time_duration timeout, int prio = 0, proxy_settings const* ps = 0
, bool ssl = false, int handle_redirect = 5 , bool ssl = false, int handle_redirect = 5
, address const& bind_addr = address_v4::any()); , address const& bind_addr = address_v4::any()
#if TORRENT_USE_I2P
, i2p_connection* i2p_conn = 0
#endif
);
void close(); void close();
#ifdef TORRENT_USE_OPENSSL
variant_stream<socket_type, ssl_stream<socket_type> > const& socket(
) const { return m_sock; }
#else
socket_type const& socket() const { return m_sock; } socket_type const& socket() const { return m_sock; }
#endif
std::list<tcp::endpoint> const& endpoints() const { return m_endpoin ts; } std::list<tcp::endpoint> const& endpoints() const { return m_endpoin ts; }
private: private:
#if TORRENT_USE_I2P
void on_i2p_resolve(error_code const& e
, char const* destination);
#endif
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);
static void on_timeout(boost::weak_ptr<http_connection> p static void on_timeout(boost::weak_ptr<http_connection> p
, error_code const& e); , error_code const& e);
void on_assign_bandwidth(error_code const& e); void on_assign_bandwidth(error_code const& e);
void callback(error_code const& e, char const* data = 0, int size = 0); void callback(error_code e, char const* data = 0, int size = 0);
std::vector<char> m_recvbuffer; std::vector<char> m_recvbuffer;
#ifdef TORRENT_USE_OPENSSL
variant_stream<socket_type, ssl_stream<socket_type> > m_sock;
#else
socket_type m_sock; socket_type m_sock;
#if TORRENT_USE_I2P
i2p_connection* m_i2p_conn;
#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; http_filter_handler m_filter_handler;
deadline_timer m_timer; deadline_timer m_timer;
time_duration m_timeout; time_duration m_read_timeout;
time_duration m_completion_timeout;
ptime m_last_receive; ptime m_last_receive;
ptime m_start_time;
// 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;
std::string m_hostname; std::string m_hostname;
std::string m_port; std::string m_port;
std::string m_url; std::string m_url;
std::string m_user_agent;
std::list<tcp::endpoint> m_endpoints; std::list<tcp::endpoint> m_endpoints;
#ifdef TORRENT_USE_OPENSSL
asio::ssl::context* m_ssl_ctx;
bool m_own_ssl_context;
#endif
// the current download limit, in bytes per second // the current download limit, in bytes per second
// 0 is unlimited. // 0 is unlimited.
int m_rate_limit; int m_rate_limit;
// the number of bytes we are allowed to receive // the number of bytes we are allowed to receive
int m_download_quota; int m_download_quota;
// only hand out new quota 4 times a second if the // only hand out new quota 4 times a second if the
// quota is 0. If it isn't 0 wait for it to reach // quota is 0. If it isn't 0 wait for it to reach
 End of changes. 20 change blocks. 
44 lines changed or deleted 41 lines changed or added


 http_parser.hpp   http_parser.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_HTTP_PARSER_HPP_INCLUDED #ifndef TORRENT_HTTP_PARSER_HPP_INCLUDED
#define TORRENT_HTTP_PARSER_HPP_INCLUDED #define TORRENT_HTTP_PARSER_HPP_INCLUDED
#include <map> #include <map>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#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>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
skipping to change at line 64 skipping to change at line 65
namespace libtorrent namespace libtorrent
{ {
// return true if the status code is 200, 206, or in the 300-400 ran ge // return true if the status code is 200, 206, or in the 300-400 ran ge
bool is_ok_status(int http_status); bool is_ok_status(int http_status);
// return true if the status code is a redirect // return true if the status code is a redirect
bool is_redirect(int http_status); bool is_redirect(int http_status);
class TORRENT_EXPORT http_parser class TORRENT_EXTRA_EXPORT http_parser
{ {
public: public:
http_parser(); enum flags_t { dont_parse_chunks = 1 };
http_parser(int flags = 0);
~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::multimap<std::string, std::string>::const_itera tor 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;
} }
std::string const& protocol() const { return m_protocol; } std::string const& protocol() const { return m_protocol; }
int status_code() const { return m_status_code; } int status_code() const { return m_status_code; }
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 std::pair<size_type, size_type> content_range() const
{ return std::make_pair(m_range_start, m_range_end); } { return std::make_pair(m_range_start, m_range_end); }
// returns true if this response is using chunked encoding.
// in this case the body is split up into chunks. You need
// to call parse_chunk_header() for each chunk, starting wit
h
// the start of the body.
bool chunked_encoding() const { return m_chunked_encoding; }
// removes the chunk headers from the supplied buffer. The b
uffer
// must be the stream received from the http server this par
ser
// instanced parsed. It will use the internal chunk list to
determine
// where the chunks are in the buffer. It returns the new le
ngth of
// the buffer
int collapse_chunk_headers(char* buffer, int size) const;
// returns false if the buffer doesn't contain a complete
// chunk header. In this case, call the function again with
// a bigger buffer once more bytes have been received.
// chunk_size is filled in with the number of bytes in the
// chunk that follows. 0 means the response terminated. In
// this case there might be additional headers in the parser
// object.
// header_size is filled in with the number of bytes the hea
der
// itself was. Skip this number of bytes to get to the actua
l
// chunk data.
// if the function returns false, the chunk size and header
// size may still have been modified, but their values are
// undefined
bool parse_chunk_header(buffer::const_interval buf
, size_type* chunk_size, int* header_size);
// reset the whole state and start over
void reset(); void reset();
std::map<std::string, std::string> const& headers() const { std::multimap<std::string, std::string> const& headers() con
return m_header; } st { return m_header; }
std::vector<std::pair<size_type, size_type> > const& chunks(
) const { return m_chunked_ranges; }
private: private:
int m_recv_pos; size_type 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_start;
size_type m_range_end; 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::multimap<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_chunked_encoding;
bool m_finished; bool m_finished;
// contains offsets of the first and one-past-end of
// each chunked range in the response
std::vector<std::pair<size_type, size_type> > m_chunked_rang
es;
// while reading a chunk, this is the offset where the
// current chunk will end (it refers to the first character
// in the chunk tail header or the next chunk header)
size_type m_cur_chunk_end;
// the sum of all chunk headers read so far
int m_chunk_header_size;
int m_partial_chunk_header;
// controls some behaviors of the parser
int m_flags;
}; };
} }
#endif // TORRENT_HTTP_PARSER_HPP_INCLUDED #endif // TORRENT_HTTP_PARSER_HPP_INCLUDED
 End of changes. 10 change blocks. 
7 lines changed or deleted 68 lines changed or added


 http_seed_connection.hpp   http_seed_connection.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_HTTP_SEED_CONNECTION_HPP_INCLUDED #ifndef TORRENT_HTTP_SEED_CONNECTION_HPP_INCLUDED
#define TORRENT_HTTP_SEED_CONNECTION_HPP_INCLUDED #define TORRENT_HTTP_SEED_CONNECTION_HPP_INCLUDED
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <vector>
#include <deque> #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>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/buffer.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/peer_connection.hpp" #include "libtorrent/web_connection_base.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
// parse_url
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_parser.hpp" #include "libtorrent/http_parser.hpp"
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
struct peer_request;
namespace detail namespace detail
{ {
struct session_impl; struct session_impl;
} }
class TORRENT_EXPORT http_seed_connection class TORRENT_EXTRA_EXPORT http_seed_connection
: public peer_connection : public web_connection_base
{ {
friend class invariant_access; friend class invariant_access;
public: public:
// this is the constructor where the we are the active part. // this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the // The peer_conenction should handshake and verify that the
// other end has the correct id // other end has the correct id
http_seed_connection( http_seed_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::weak_ptr<torrent> t , boost::weak_ptr<torrent> t
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote , tcp::endpoint const& remote
, std::string const& url , std::string const& url
, policy::peer* peerinfo); , policy::peer* peerinfo
void start(); , std::string const& ext_auth
, web_seed_entry::headers_t const& ext_headers);
~http_seed_connection(); virtual int type() const { return peer_connection::http_seed _connection; }
// called from the main loop when this connection has any // called from the main loop when this connection has any
// work to do. // work to do.
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(error_code const& error void on_receive(error_code const& error
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
std::string const& url() const { return m_url; } std::string const& url() const { return m_url; }
virtual void get_specific_peer_info(peer_info& p) const; virtual void get_specific_peer_info(peer_info& p) const;
virtual bool in_handshake() const; virtual void disconnect(error_code const& ec, int error = 0) ;
// the following functions appends messages
// to the send buffer
void write_choke() {}
void write_unchoke() {}
void write_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)
{ incoming_reject_request(r); }
void write_have(int index) {}
void write_piece(peer_request const& r, disk_buffer_holder&
buffer) { TORRENT_ASSERT(false); }
void write_keepalive() {}
void on_connected();
void write_reject_request(peer_request const&) {}
void write_allow_fast(int) {}
#ifdef TORRENT_DEBUG
void check_invariant() const;
#endif
private: private:
// returns the block currently being // returns the block currently being
// downloaded. And the progress of that // downloaded. And the progress of that
// block. If the peer isn't downloading // block. If the peer isn't downloading
// a piece for the moment, the boost::optional // a piece for the moment, the boost::optional
// will be invalid. // will be invalid.
boost::optional<piece_block_progress> downloading_piece_prog ress() const; boost::optional<piece_block_progress> downloading_piece_prog ress() const;
// this has one entry per bittorrent request
std::deque<peer_request> m_requests;
std::string m_server_string;
http_parser m_parser;
std::string m_auth;
std::string m_host;
int m_port;
std::string m_path;
// this is const since it's used as a key in the web seed li st in the torrent // this is const since it's used as a key in the web seed li st in the torrent
// if it's changed referencing back into that list will fail // if it's changed referencing back into that list will fail
const std::string m_url; const std::string m_url;
// the first request will contain a little bit more data
// than subsequent ones, things that aren't critical are lef
t
// out to save bandwidth.
bool m_first_request;
// the number of bytes left to receive of the response we're // the number of bytes left to receive of the response we're
// currently parsing // currently parsing
int m_response_left; size_type m_response_left;
// the number of bytes in the start of the receive buffer // this is the offset inside the current receive
// that's http header // buffer where the next chunk header will be.
int m_body_start; // this is updated for each chunk header that's
// parsed. It does not necessarily point to a valid
// offset in the receive buffer, if we haven't received
// it yet. This offset never includes the HTTP header
size_type m_chunk_pos;
// this is the number of bytes we've already received
// from the next chunk header we're waiting for
int m_partial_chunk_header;
}; };
} }
#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 16 change blocks. 
60 lines changed or deleted 23 lines changed or added


 http_stream.hpp   http_stream.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_HTTP_STREAM_HPP_INCLUDED #ifndef TORRENT_HTTP_STREAM_HPP_INCLUDED
#define TORRENT_HTTP_STREAM_HPP_INCLUDED #define TORRENT_HTTP_STREAM_HPP_INCLUDED
#include <boost/function/function1.hpp>
#include "libtorrent/proxy_base.hpp" #include "libtorrent/proxy_base.hpp"
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
namespace libtorrent { namespace libtorrent {
class http_stream : public proxy_base class http_stream : public proxy_base
{ {
public: public:
explicit http_stream(io_service& io_service) explicit http_stream(io_service& io_service)
: proxy_base(io_service) : proxy_base(io_service)
, m_no_connect(false) , m_no_connect(false)
skipping to change at line 58 skipping to change at line 61
void set_no_connect(bool c) { m_no_connect = c; } void set_no_connect(bool c) { m_no_connect = 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;
} }
void set_dst_name(std::string const& host)
{
m_dst_name = host;
}
void close(error_code& ec)
{
m_dst_name.clear();
proxy_base::close(ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void close()
{
m_dst_name.clear();
proxy_base::close();
}
#endif
typedef boost::function<void(error_code const&)> handler_type; typedef boost::function<void(error_code const&)> handler_type;
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
skipping to change at line 93 skipping to change at line 115
, 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);
void handshake2(error_code const& e, boost::shared_ptr<handler_type> h); void handshake2(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;
std::string m_dst_name;
// this is true if the connection is HTTP based and // this is true if the connection is HTTP based and
// want to talk directly to the proxy // want to talk directly to the proxy
bool m_no_connect; bool m_no_connect;
}; };
} }
#endif #endif
 End of changes. 4 change blocks. 
0 lines changed or deleted 23 lines changed or added


 http_tracker_connection.hpp   http_tracker_connection.hpp 
skipping to change at line 52 skipping to change at line 52
#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/config.hpp"
#include "libtorrent/lazy_entry.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/i2p_stream.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;
namespace aux { struct session_impl; } namespace aux { struct session_impl; }
class TORRENT_EXPORT http_tracker_connection class TORRENT_EXTRA_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
, boost::weak_ptr<request_callback> c , boost::weak_ptr<request_callback> c
, aux::session_impl const& ses , aux::session_impl const& ses
, proxy_settings const& ps , proxy_settings const& ps
, std::string const& password = ""); , std::string const& password = ""
#if TORRENT_USE_I2P
, i2p_connection* i2p_conn = 0
#endif
);
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_filter(http_connection& c, std::list<tcp::endpoint>& endpoints);
skipping to change at line 105 skipping to change at line 109
void parse(int status_code, lazy_entry const& e); void parse(int status_code, lazy_entry const& e);
bool extract_peer_info(lazy_entry const& 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;
aux::session_impl const& m_ses; aux::session_impl const& m_ses;
address m_tracker_ip; 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;
#if TORRENT_USE_I2P
i2p_connection* m_i2p_conn;
#endif
}; };
} }
#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED #endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
 End of changes. 4 change blocks. 
3 lines changed or deleted 10 lines changed or added


 instantiate_connection.hpp   instantiate_connection.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_INSTANTIATE_CONNECTION #ifndef TORRENT_INSTANTIATE_CONNECTION
#define TORRENT_INSTANTIATE_CONNECTION #define TORRENT_INSTANTIATE_CONNECTION
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type.hpp"
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
namespace libtorrent namespace libtorrent
{ {
struct proxy_settings; struct proxy_settings;
struct utp_socket_manager;
struct socket_type;
bool instantiate_connection(io_service& ios // instantiate a socket_type (s) according to the specified criteria
, proxy_settings const& ps, socket_type& s); TORRENT_EXTRA_EXPORT bool instantiate_connection(io_service& ios
, proxy_settings const& ps, socket_type& s
, void* ssl_context = 0
, utp_socket_manager* sm = 0
, bool peer_connection = false);
} }
#endif #endif
 End of changes. 2 change blocks. 
2 lines changed or deleted 8 lines changed or added


 intrusive_ptr_base.hpp   intrusive_ptr_base.hpp 
skipping to change at line 55 skipping to change at line 55
struct intrusive_ptr_base struct intrusive_ptr_base
{ {
intrusive_ptr_base(intrusive_ptr_base<T> const&) intrusive_ptr_base(intrusive_ptr_base<T> const&)
: m_refs(0) {} : m_refs(0) {}
intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs) intrusive_ptr_base& operator=(intrusive_ptr_base const& rhs)
{ return *this; } { return *this; }
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> cons t* s) friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> cons t* s)
{ {
TORRENT_ASSERT(s->m_refs >= 0);
TORRENT_ASSERT(s != 0); TORRENT_ASSERT(s != 0);
TORRENT_ASSERT(s->m_refs >= 0);
++s->m_refs; ++s->m_refs;
} }
friend void intrusive_ptr_release(intrusive_ptr_base<T> cons t* s) friend void intrusive_ptr_release(intrusive_ptr_base<T> cons t* s)
{ {
TORRENT_ASSERT(s->m_refs > 0);
TORRENT_ASSERT(s != 0); TORRENT_ASSERT(s != 0);
TORRENT_ASSERT(s->m_refs > 0);
if (--s->m_refs == 0) if (--s->m_refs == 0)
boost::checked_delete(static_cast<T const*>( s)); boost::checked_delete(static_cast<T const*>( s));
} }
boost::intrusive_ptr<T> self() boost::intrusive_ptr<T> self()
{ return boost::intrusive_ptr<T>((T*)this); } { return boost::intrusive_ptr<T>((T*)this); }
boost::intrusive_ptr<const T> self() const boost::intrusive_ptr<const T> self() const
{ return boost::intrusive_ptr<const T>((T const*)this); } { return boost::intrusive_ptr<const T>((T const*)this); }
int refcount() const { return m_refs; } int refcount() const { return m_refs; }
intrusive_ptr_base(): m_refs(0) {} intrusive_ptr_base(): m_refs(0) {}
// so that we can access this when logging
#if !defined TORRENT_LOGGING \
&& !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
private: private:
#endif
// reference counter for intrusive_ptr // reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs; mutable boost::detail::atomic_count m_refs;
}; };
} }
#endif #endif
 End of changes. 6 change blocks. 
2 lines changed or deleted 8 lines changed or added


 io.hpp   io.hpp 
skipping to change at line 57 skipping to change at line 57
// 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
template <class T, class InIt> template <class T, class InIt>
inline T read_impl(InIt& start, type<T>) inline T read_impl(InIt& start, type<T>)
{ {
T ret = 0; T ret = 0;
for (int i = 0; i < (int)sizeof(T); ++i) for (int i = 0; i < (int)sizeof(T); ++i)
{ {
ret <<= 8; ret <<= 8;
ret |= static_cast<unsigned char>(*start); ret |= static_cast<boost::uint8_t>(*start);
++start; ++start;
} }
return ret; return ret;
} }
template <class InIt>
boost::uint8_t read_impl(InIt& start, type<boost::uint8_t>)
{
return static_cast<boost::uint8_t>(*start++);
}
template <class InIt>
boost::int8_t read_impl(InIt& start, type<boost::int8_t>)
{
return static_cast<boost::int8_t>(*start++);
}
template <class T, class OutIt> template <class T, class OutIt>
inline void write_impl(T val, OutIt& start) inline void write_impl(T val, OutIt& start)
{ {
for (int i = (int)sizeof(T)-1; i >= 0; --i) for (int i = (int)sizeof(T)-1; i >= 0; --i)
{ {
*start = static_cast<unsigned char>((val >> (i * 8)) & 0xff); *start = static_cast<unsigned char>((val >> (i * 8)) & 0xff);
++start; ++start;
} }
} }
skipping to change at line 141 skipping to change at line 153
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::memcpy((void*)start, &str[0], str.size()); std::memcpy((void*)start, str.c_str(), 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. 3 change blocks. 
2 lines changed or deleted 14 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 <vector>
#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
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/address.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
namespace libtorrent namespace libtorrent
{ {
inline bool operator<=(address const& lhs inline bool operator<=(address const& lhs
, address const& rhs) , address const& rhs)
{ {
return lhs < rhs || lhs == rhs; return lhs < rhs || lhs == rhs;
} }
skipping to change at line 150 skipping to change at line 151
public: public:
filter_impl() filter_impl()
{ {
// make the entire ip-range non-blocked // make the entire ip-range non-blocked
m_access_list.insert(range(zero<Addr>(), 0)); m_access_list.insert(range(zero<Addr>(), 0));
} }
void add_rule(Addr first, Addr last, int flags) void add_rule(Addr first, Addr last, int flags)
{ {
using boost::next;
using boost::prior;
TORRENT_ASSERT(!m_access_list.empty()); TORRENT_ASSERT(!m_access_list.empty());
TORRENT_ASSERT(first < last || first == last); TORRENT_ASSERT(first < last || first == last);
typename range_t::iterator i = m_access_list.upper_b ound(first); typename range_t::iterator i = m_access_list.upper_b ound(first);
typename range_t::iterator j = m_access_list.upper_b ound(last); typename range_t::iterator j = m_access_list.upper_b ound(last);
if (i != m_access_list.begin()) --i; if (i != m_access_list.begin()) --i;
TORRENT_ASSERT(j != m_access_list.begin()); TORRENT_ASSERT(j != m_access_list.begin());
TORRENT_ASSERT(j != i); TORRENT_ASSERT(j != i);
int first_access = i->access; int first_access = i->access;
int last_access = prior(j)->access; int last_access = boost::prior(j)->access;
if (i->start != first && first_access != flags) if (i->start != first && first_access != flags)
{ {
i = m_access_list.insert(i, range(first, fla gs)); i = m_access_list.insert(i, range(first, fla gs));
} }
else if (i != m_access_list.begin() && prior(i)->acc ess == flags) else if (i != m_access_list.begin() && boost::prior( i)->access == flags)
{ {
--i; --i;
first_access = i->access; first_access = i->access;
} }
TORRENT_ASSERT(!m_access_list.empty()); TORRENT_ASSERT(!m_access_list.empty());
TORRENT_ASSERT(i != m_access_list.end()); TORRENT_ASSERT(i != m_access_list.end());
if (i != j) m_access_list.erase(boost::next(i), j); if (i != j) m_access_list.erase(boost::next(i), j);
if (i->start == first) if (i->start == first)
{ {
skipping to change at line 275 skipping to change at line 273
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;
#if TORRENT_USE_IPV6
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;
#else
typedef std::vector<ip_range<address_v4> > filter_tuple_t;
#endif
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 #if TORRENT_USE_IPV6
detail::filter_impl<address_v6::bytes_type> m_filter6; detail::filter_impl<address_v6::bytes_type> m_filter6;
 End of changes. 7 change blocks. 
6 lines changed or deleted 8 lines changed or added


 lazy_entry.hpp   lazy_entry.hpp 
skipping to change at line 39 skipping to change at line 39
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 <string> #include <string>
#include <cstring>
#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"
#include "libtorrent/error_code.hpp"
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include <iosfwd> #include <iosfwd>
#endif #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
skipping to change at line 53 skipping to change at line 55
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include <iosfwd> #include <iosfwd>
#endif #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, TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end
lazy_entry& ret, int depth_limit = 1000); , lazy_entry& ret, error_code& ec, int* error_pos = 0
, int depth_limit = 1000, int item_limit = 1000000);
#ifndef TORRENT_NO_DEPRECATE
// for backwards compatibility, does not report error code
// deprecated in 0.16
TORRENT_DEPRECATED_PREFIX
TORRENT_EXPORT int lazy_bdecode(char const* start, char const* end
, lazy_entry& ret, int depth_limit = 1000, int item_limit =
1000000) TORRENT_DEPRECATED;
#endif
struct pascal_string
{
pascal_string(char const* p, int l): len(l), ptr(p) {}
int len;
char const* ptr;
bool operator<(pascal_string const& rhs) const
{
return std::memcmp(ptr, rhs.ptr, (std::min)(len, rhs
.len)) < 0
|| len < rhs.len;
}
};
struct lazy_dict_entry; 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_size(0), m_capacity(0), m_b egin(0), m_end(0) lazy_entry() : m_begin(0), m_len(0), m_size(0), m_capacity(0 ), m_type(none_t)
{ m_data.start = 0; } { m_data.start = 0; }
entry_type_t type() const { return m_type; } entry_type_t type() const { return (entry_type_t)m_type; }
// start points to the first decimal digit // start points to the first decimal digit
// length is the number of digits // length is the number of digits
void construct_int(char const* start, int length) void construct_int(char const* start, int length)
{ {
TORRENT_ASSERT(m_type == none_t); TORRENT_ASSERT(m_type == none_t);
m_type = int_t; m_type = int_t;
m_data.start = start; m_data.start = start;
m_size = length; m_size = length;
m_begin = start - 1; // include 'i' m_begin = start - 1; // include 'i'
m_end = start + length + 1; // include 'e' m_len = length + 2; // include 'e'
} }
size_type int_value() const; size_type int_value() const;
// string functions // string functions
// ================ // ================
void construct_string(char const* start, int length); void construct_string(char const* start, int length);
// the string is not null-terminated! // the string is not null-terminated!
skipping to change at line 105 skipping to change at line 130
// this will return a null terminated string // this will return a null terminated string
// it will write to the source buffer! // it will write to the source buffer!
char const* string_cstr() const char const* string_cstr() const
{ {
TORRENT_ASSERT(m_type == string_t); TORRENT_ASSERT(m_type == string_t);
const_cast<char*>(m_data.start)[m_size] = 0; const_cast<char*>(m_data.start)[m_size] = 0;
return m_data.start; return m_data.start;
} }
pascal_string string_pstr() const
{
TORRENT_ASSERT(m_type == string_t);
return pascal_string(m_data.start, m_size);
}
std::string string_value() const std::string string_value() const
{ {
TORRENT_ASSERT(m_type == string_t); TORRENT_ASSERT(m_type == string_t);
return std::string(m_data.start, m_size); return std::string(m_data.start, m_size);
} }
int string_length() const int string_length() const
{ return m_size; } { return m_size; }
// dictionary functions // dictionary functions
skipping to change at line 127 skipping to change at line 158
void construct_dict(char const* begin) void construct_dict(char const* begin)
{ {
TORRENT_ASSERT(m_type == none_t); TORRENT_ASSERT(m_type == none_t);
m_type = dict_t; m_type = dict_t;
m_size = 0; m_size = 0;
m_capacity = 0; m_capacity = 0;
m_begin = begin; m_begin = begin;
} }
lazy_entry* dict_append(char const* name); lazy_entry* dict_append(char const* name);
void pop();
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;
pascal_string dict_find_pstr(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; lazy_entry const* dict_find_int(char const* name) const;
std::pair<std::string, lazy_entry const*> dict_at(int i) con st; std::pair<std::string, lazy_entry const*> dict_at(int i) con st;
int dict_size() const int dict_size() const
{ {
skipping to change at line 162 skipping to change at line 195
m_type = list_t; m_type = list_t;
m_size = 0; m_size = 0;
m_capacity = 0; m_capacity = 0;
m_begin = begin; m_begin = begin;
} }
lazy_entry* list_append(); lazy_entry* list_append();
lazy_entry* list_at(int i) lazy_entry* list_at(int i)
{ {
TORRENT_ASSERT(m_type == list_t); TORRENT_ASSERT(m_type == list_t);
TORRENT_ASSERT(i < m_size); TORRENT_ASSERT(i < int(m_size));
return &m_data.list[i]; return &m_data.list[i];
} }
lazy_entry const* list_at(int i) const lazy_entry const* list_at(int i) const
{ return const_cast<lazy_entry*>(this)->list_at(i); } { return const_cast<lazy_entry*>(this)->list_at(i); }
std::string list_string_value_at(int i) const; std::string list_string_value_at(int i) const;
pascal_string list_pstr_at(int i) const;
size_type list_int_value_at(int i, size_type default_val = 0 ) const; size_type list_int_value_at(int i, size_type default_val = 0 ) const;
int list_size() const int list_size() const
{ {
TORRENT_ASSERT(m_type == list_t); TORRENT_ASSERT(m_type == list_t);
return m_size; return int(m_size);
} }
// end points one byte passed last byte // end points one byte passed last byte
void set_end(char const* end) void set_end(char const* end)
{ {
TORRENT_ASSERT(end > m_begin); TORRENT_ASSERT(end > m_begin);
m_end = end; m_len = end - m_begin;
} }
void clear(); void clear();
// releases ownership of any memory allocated // releases ownership of any memory allocated
void release() void release()
{ {
m_data.start = 0; m_data.start = 0;
m_size = 0; m_size = 0;
m_capacity = 0; m_capacity = 0;
skipping to change at line 205 skipping to change at line 239
~lazy_entry() ~lazy_entry()
{ clear(); } { clear(); }
// returns pointers into the source buffer where // returns pointers into the source buffer where
// this entry has its bencoded data // this entry has its bencoded data
std::pair<char const*, int> data_section() const; std::pair<char const*, int> data_section() const;
void swap(lazy_entry& e) void swap(lazy_entry& e)
{ {
using std::swap; using std::swap;
swap(m_type, e.m_type); boost::uint32_t tmp = e.m_type;
e.m_type = m_type;
m_type = tmp;
tmp = e.m_capacity;
e.m_capacity = m_capacity;
m_capacity = tmp;
swap(m_data.start, e.m_data.start); swap(m_data.start, e.m_data.start);
swap(m_size, e.m_size); swap(m_size, e.m_size);
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_len, e.m_len);
} }
private: private:
entry_type_t m_type;
union data_t union data_t
{ {
lazy_dict_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_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; // the number of bytes this entry extends in the
// bencoded byffer
boost::uint32_t m_len;
// if list or dictionary, the number of items
boost::uint32_t m_size;
// if list or dictionary, allocated number of items
boost::uint32_t m_capacity:29;
// element type (dict, list, int, string)
boost::uint32_t m_type:3;
// non-copyable // non-copyable
lazy_entry(lazy_entry const&); lazy_entry(lazy_entry const&);
lazy_entry const& operator=(lazy_entry const&); lazy_entry const& operator=(lazy_entry const&);
}; };
struct lazy_dict_entry struct lazy_dict_entry
{ {
char const* name; char const* name;
lazy_entry val; lazy_entry val;
}; };
TORRENT_EXPORT std::string print_entry(lazy_entry const& e); TORRENT_EXPORT std::string print_entry(lazy_entry const& e
, bool single_line = false, int indent = 0);
#if TORRENT_USE_IOSTREAM #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 #endif
 End of changes. 21 change blocks. 
17 lines changed or deleted 62 lines changed or added


 logging.hpp   logging.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_LOGGING_HPP #ifndef TORRENT_LOGGING_HPP
#define TORRENT_LOGGING_HPP #define TORRENT_LOGGING_HPP
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include <iostream> #include <iostream>
#include <fstream> #include <fstream>
#include "libtorrent/time.hpp" #include "libtorrent/ptime.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)
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 lsd.hpp   lsd.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#ifndef TORRENT_LSD_HPP #ifndef TORRENT_LSD_HPP
#define TORRENT_LSD_HPP #define TORRENT_LSD_HPP
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/broadcast_socket.hpp" #include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/deadline_timer.hpp"
#include <boost/function.hpp> #include <boost/function/function2.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/condition.hpp>
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
#include <fstream> #include <fstream>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
typedef boost::function<void(tcp::endpoint, sha1_hash)> peer_callback_t; typedef boost::function<void(tcp::endpoint, sha1_hash)> peer_callback_t;
class lsd : public intrusive_ptr_base<lsd> class lsd : public intrusive_ptr_base<lsd>
{ {
public: public:
lsd(io_service& ios, address const& listen_interface lsd(io_service& ios, address const& listen_interface
, peer_callback_t const& cb); , peer_callback_t const& cb);
~lsd(); ~lsd();
// void rebind(address const& listen_interface); // void rebind(address const& listen_interface);
void announce(sha1_hash const& ih, int listen_port); void announce(sha1_hash const& ih, int listen_port, bool broadcast = false);
void close(); void close();
void use_broadcast(bool b);
private: private:
void resend_announce(error_code const& e, std::string msg); void resend_announce(error_code const& e, std::string msg);
void on_announce(udp::endpoint const& from, char* buffer void on_announce(udp::endpoint const& from, char* buffer
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
// void setup_receive(); // void setup_receive();
peer_callback_t m_callback; peer_callback_t m_callback;
// current retry count // current retry count
 End of changes. 5 change blocks. 
6 lines changed or deleted 3 lines changed or added


 magnet_uri.hpp   magnet_uri.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_MAGNET_URI_HPP_INCLUDED #ifndef TORRENT_MAGNET_URI_HPP_INCLUDED
#define TORRENT_MAGNET_URI_HPP_INCLUDED #define TORRENT_MAGNET_URI_HPP_INCLUDED
#include <string> #include <string>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/torrent_handle.hpp" #include "libtorrent/torrent_handle.hpp"
#include "libtorrent/session.hpp" #include "libtorrent/add_torrent_params.hpp"
#include <boost/filesystem/path.hpp>
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem;
struct torrent_handle; struct torrent_handle;
class session;
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
#ifndef BOOST_NO_EXCEPTIONS
// deprecated in 0.14 // deprecated in 0.14
TORRENT_DEPRECATED_PREFIX
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 , std::string 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
// deprecated in 0.16. Instead, pass in the magnet link as add_torre
nt_params::url
TORRENT_DEPRECATED_PREFIX
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) TORRENT_DEPRECATED;
#endif #endif
// deprecated in 0.16. Instead, pass in the magnet link as add_torre
nt_params::url
TORRENT_DEPRECATED_PREFIX
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, error_code& ec); , add_torrent_params p, error_code& ec) TORRENT_DEPRECATED;
#endif
TORRENT_EXPORT void parse_magnet_uri(std::string const& uri, add_tor
rent_params& p, error_code& ec);
} }
#endif #endif
 End of changes. 12 change blocks. 
9 lines changed or deleted 18 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/lazy_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() msg()
: reply(false) : reply(false)
skipping to change at line 77 skipping to change at line 78
// 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;
// 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;
nodes_t nodes; nodes_t nodes;
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.
std::string write_token; std::string write_token;
// if non-empty, include the "ip" key in the response
std::string ip;
// 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;
std::string error_msg; std::string error_msg;
}; };
*/
typedef std::vector<node_entry> nodes_t;
typedef std::vector<tcp::endpoint> peers_t;
struct msg
{
msg(lazy_entry const& m, udp::endpoint const& ep): message(m), addr(
ep) {}
// the message
lazy_entry const& message;
// the address of the process sending or receiving
// the message.
udp::endpoint addr;
};
} } } }
#endif #endif
 End of changes. 6 change blocks. 
6 lines changed or deleted 18 lines changed or added


 natpmp.hpp   natpmp.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_NATPMP_HPP #ifndef TORRENT_NATPMP_HPP
#define TORRENT_NATPMP_HPP #define TORRENT_NATPMP_HPP
#include "libtorrent/io_service_fwd.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/deadline_timer.hpp"
#include <boost/function.hpp> #include <boost/function/function1.hpp>
#include <boost/thread/mutex.hpp> #include <boost/function/function4.hpp>
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, error_code const&)> portmap_callback _t; typedef boost::function<void(int, address, int, error_code const&)> portmap _callback_t;
typedef boost::function<void(char const*)> log_callback_t; typedef boost::function<void(char const*)> log_callback_t;
class TORRENT_EXPORT 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 natpmp(io_service& ios, address const& listen_interface
, portmap_callback_t const& cb , portmap_callback_t const& cb
, log_callback_t const& lcb); , log_callback_t const& lcb);
void rebind(address const& listen_interface); void rebind(address const& listen_interface);
skipping to change at line 71 skipping to change at line 76
// 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; bool get_mapping(int mapping_index, int& local_port, int& external_p ort, int& protocol) const;
void close(); void close();
private: private:
typedef boost::mutex mutex_t; void update_mapping(int i, mutex::scoped_lock& l);
void send_map_request(int i, mutex::scoped_lock& l);
void update_mapping(int i, mutex_t::scoped_lock& l); void send_get_ip_address_request(mutex::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, mutex_t::scoped_lock& l); void try_next_mapping(int i, mutex::scoped_lock& l);
void update_expiration_timer(boost::mutex::scoped_lock& l); void update_expiration_timer(mutex::scoped_lock& l);
void mapping_expired(error_code const& e, int i); void mapping_expired(error_code const& e, int i);
void close_impl(mutex_t::scoped_lock& l); void close_impl(mutex::scoped_lock& l);
void log(char const* msg, mutex_t::scoped_lock& l); void log(char const* msg, mutex::scoped_lock& l);
void disable(error_code const& ec, mutex_t::scoped_lock& l); void disable(error_code const& ec, mutex::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) , map_sent(false)
skipping to change at line 142 skipping to change at line 146
// 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;
// current retry count // current retry count
int m_retry_count; int m_retry_count;
// used to receive responses in // used to receive responses in
char m_response_buffer[16]; char m_response_buffer[16];
// router external IP address
address m_external_ip;
// the endpoint we received the message from // the endpoint we received the message from
udp::endpoint m_remote; udp::endpoint m_remote;
// the udp socket used to communicate // the udp socket used to communicate
// with the NAT router // with the NAT router
datagram_socket m_socket; datagram_socket m_socket;
// used to resend udp packets in case // used to resend udp packets in case
// they time out // they time out
deadline_timer m_send_timer; deadline_timer m_send_timer;
skipping to change at line 163 skipping to change at line 170
// 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;
mutable mutex_t m_mutex; mutable mutex m_mutex;
}; };
} }
#endif #endif
 End of changes. 11 change blocks. 
13 lines changed or deleted 20 lines changed or added


 node.hpp   node.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#ifndef NODE_HPP #ifndef NODE_HPP
#define NODE_HPP #define NODE_HPP
#include <algorithm> #include <algorithm>
#include <map> #include <map>
#include <set> #include <set>
#include <libtorrent/config.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/node_id.hpp> #include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/msg.hpp> #include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/kademlia/find_data.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 <libtorrent/thread.hpp>
#include <libtorrent/bloom_filter.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/optional.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 libtorrent {
class alert_manager;
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; struct traversal_algorithm;
struct key_desc_t
{
char const* name;
int type;
int size;
int flags;
enum {
// this argument is optional, parsing will not
// fail if it's not present
optional = 1,
// for dictionaries, the following entries refer
// to child nodes to this node, up until and including
// the next item that has the last_child flag set.
// these flags are nestable
parse_children = 2,
// this is the last item in a child dictionary
last_child = 4,
// the size argument refers to that the size
// has to be divisible by the number, instead
// of having that exact size
size_divisible = 8
};
};
bool TORRENT_EXTRA_EXPORT verify_message(lazy_entry const* msg, key_desc_t
const desc[]
, lazy_entry const* ret[], int size , char* error, int error_size);
// 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;
bool seed;
}; };
// this is a group. It contains a set of group members // this is a group. It contains a set of group members
struct torrent_entry struct torrent_entry
{ {
std::string name;
std::set<peer_entry> peers; std::set<peer_entry> peers;
}; };
struct dht_immutable_item
{
dht_immutable_item() : value(0), num_announcers(0), size(0) {}
// malloced space for the actual value
char* value;
// this counts the number of IPs we have seen
// announcing this item, this is used to determine
// popularity if we reach the limit of items to store
bloom_filter<128> ips;
// the last time we heard about this
ptime last_seen;
// number of IPs in the bloom filter
int num_announcers;
// size of malloced space pointed to by value
int size;
};
struct dht_mutable_item : dht_immutable_item
{
char sig[256];
int seq;
};
struct rsa_key { char bytes[268]; };
inline bool operator<(rsa_key const& lhs, rsa_key const& rhs)
{
return memcmp(lhs.bytes, rhs.bytes, sizeof(lhs.bytes)) < 0;
}
inline bool operator<(peer_entry const& lhs, peer_entry const& rhs) inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
{ {
return lhs.addr.address() == rhs.addr.address() return lhs.addr.address() == rhs.addr.address()
? lhs.addr.port() < rhs.addr.port() ? lhs.addr.port() < rhs.addr.port()
: lhs.addr.address() < rhs.addr.address(); : lhs.addr.address() < rhs.addr.address();
} }
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::intrusive_ptr<traversal_algorithm> const& a
, sha1_hash const& info_hash lgo
, int listen_port , udp::endpoint const& ep, node_id const& id)
, std::string const& write_token) : observer(algo, ep, id)
: observer(allocator)
, m_info_hash(info_hash)
, m_listen_port(listen_port)
, m_token(write_token)
{} {}
void send(msg& m) void reply(msg const&) { flags |= flag_done; }
};
struct count_peers
{
int& count;
count_peers(int& c): count(c) {}
void operator()(std::pair<libtorrent::dht::node_id
, libtorrent::dht::torrent_entry> const& t)
{ {
m.port = m_listen_port; count += t.second.peers.size();
m.info_hash = m_info_hash;
m.write_token = m_token;
} }
void timeout() {}
void reply(msg const&) {}
void abort() {}
private:
sha1_hash m_info_hash;
int m_listen_port;
std::string m_token;
}; };
class node_impl : boost::noncopyable class TORRENT_EXTRA_EXPORT node_impl : boost::noncopyable
{ {
typedef std::map<node_id, torrent_entry> table_t; typedef std::map<node_id, torrent_entry> table_t;
typedef std::map<node_id, dht_immutable_item> dht_immutable_table_t;
typedef std::map<rsa_key, dht_mutable_item> dht_mutable_table_t;
public: public:
node_impl(libtorrent::aux::session_impl& ses, boost::function<void(m typedef boost::function3<void, address, int, address> external_ip_fu
sg const&)> const& f n;
, dht_settings const& settings, boost::optional<node_id> nid
); node_impl(libtorrent::alert_manager& alerts
, bool (*f)(void*, entry&, udp::endpoint const&, int)
, dht_settings const& settings, node_id nid, address const&
external_address
, external_ip_fun ext_ip, void* userdata);
virtual ~node_impl() {} virtual ~node_impl() {}
void refresh(node_id const& id, boost::function0<void> f); void tick();
void refresh(node_id const& id, find_data::nodes_callback const& f);
void bootstrap(std::vector<udp::endpoint> const& nodes void bootstrap(std::vector<udp::endpoint> const& nodes
, boost::function0<void> f); , find_data::nodes_callback const& f);
void find_node(node_id const& id, boost::function<
void(std::vector<node_entry> const&)> f);
void add_router_node(udp::endpoint router); void add_router_node(udp::endpoint router);
void unreachable(udp::endpoint const& ep); void unreachable(udp::endpoint const& ep);
void incoming(msg const& m); void incoming(msg const& m);
void refresh(); int num_torrents() const { return m_map.size(); }
void refresh_bucket(int bucket); int num_peers() const
int bucket_size(int bucket); {
int ret = 0;
typedef routing_table::iterator iterator; std::for_each(m_map.begin(), m_map.end(), count_peers(ret));
return ret;
iterator begin() const { return m_table.begin(); } }
iterator end() const { return m_table.end(); }
typedef table_t::iterator data_iterator; int bucket_size(int bucket);
node_id const& nid() const { return m_id; } node_id const& nid() const { return m_id; }
boost::tuple<int, int> size() const{ return m_table.size(); } boost::tuple<int, int> size() const{ return m_table.size(); }
size_type num_global_nodes() const size_type num_global_nodes() const
{ return m_table.num_global_nodes(); } { return m_table.num_global_nodes(); }
data_iterator begin_data() { return m_map.begin(); }
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, bool seed
, boost::function<void(std::vector<tcp::endpoint> const&)> f ); , boost::function<void(std::vector<tcp::endpoint> const&)> f );
bool verify_token(msg const& m); bool verify_token(std::string const& token, char const* info_hash
std::string generate_token(msg const& m); , udp::endpoint const& addr);
std::string generate_token(udp::endpoint const& addr, char const* in
fo_hash);
// 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();
// 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
skipping to change at line 211 skipping to change at line 264
} }
void remove_traversal_algorithm(traversal_algorithm* a) void remove_traversal_algorithm(traversal_algorithm* a)
{ {
mutex_t::scoped_lock l(m_mutex); mutex_t::scoped_lock l(m_mutex);
m_running_requests.erase(a); m_running_requests.erase(a);
} }
void status(libtorrent::session_status& s); void status(libtorrent::session_status& s);
dht_settings const& settings() const { return m_settings; }
protected: protected:
// is called when a find data request is received. Should
// return false if the data is not stored on this node. If
// the data is stored, it should be serialized into 'data'.
bool on_find(msg const& m, std::vector<tcp::endpoint>& peers) const;
// this is called when a store request is received. The data void lookup_peers(sha1_hash const& info_hash, int prefix, entry& rep
// is store-parameters and the data to be stored. ly
void on_announce(msg const& m, msg& reply); , bool noseed, bool scrape) const;
bool lookup_torrents(sha1_hash const& target, entry& reply
, char* tags) const;
dht_settings const& m_settings; dht_settings const& m_settings;
private: private:
typedef boost::mutex mutex_t; typedef libtorrent::mutex mutex_t;
mutex_t m_mutex; mutex_t m_mutex;
// this list must be destructed after the rpc manager // this list must be destructed after the rpc manager
// since it might have references to it // since it might have references to it
std::set<traversal_algorithm*> m_running_requests; std::set<traversal_algorithm*> m_running_requests;
void incoming_request(msg const& h); void incoming_request(msg const& h, entry& e);
node_id m_id; node_id m_id;
public: public:
routing_table m_table; routing_table m_table;
rpc_manager m_rpc; rpc_manager m_rpc;
private: private:
table_t m_map; table_t m_map;
dht_immutable_table_t m_immutable_table;
dht_mutable_table_t m_mutable_table;
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; libtorrent::alert_manager& m_alerts;
bool (*m_send)(void*, entry&, udp::endpoint const&, int);
void* m_userdata;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // NODE_HPP #endif // NODE_HPP
 End of changes. 32 change blocks. 
63 lines changed or deleted 123 lines changed or added


 node_entry.hpp   node_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 KADEMLIA_NODE_ENTRY_HPP #ifndef KADEMLIA_NODE_ENTRY_HPP
#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"
#include "libtorrent/address.hpp"
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
struct node_entry struct node_entry
{ {
node_entry(node_id const& id_, udp::endpoint ep, bool pinged = false ) node_entry(node_id const& id_, udp::endpoint ep, bool pinged = false )
: addr(ep.address()) : addr(ep.address())
, port(ep.port()) , port(ep.port())
, timeout_count(pinged ? 0 : 0xffff) , timeout_count(pinged ? 0 : 0xffff)
skipping to change at line 82 skipping to change at line 84
} }
bool pinged() const { return timeout_count != 0xffff; } bool pinged() const { return timeout_count != 0xffff; }
void set_pinged() { if (timeout_count == 0xffff) timeout_count = 0; } void set_pinged() { if (timeout_count == 0xffff) timeout_count = 0; }
void timed_out() { if (pinged()) ++timeout_count; } void timed_out() { if (pinged()) ++timeout_count; }
int fail_count() const { return pinged() ? timeout_count : 0; } int fail_count() const { return pinged() ? timeout_count : 0; }
void reset_fail_count() { if (pinged()) timeout_count = 0; } void reset_fail_count() { if (pinged()) timeout_count = 0; }
udp::endpoint ep() const { return udp::endpoint(addr, port); } udp::endpoint ep() const { return udp::endpoint(addr, port); }
bool confirmed() const { return timeout_count == 0; } bool confirmed() const { return timeout_count == 0; }
// TODO: replace with a union of address_v4 and address_v6
address addr; address addr;
boost::uint16_t port; 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
boost::uint16_t timeout_count; boost::uint16_t timeout_count;
node_id id; node_id id;
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
ptime first_seen; ptime first_seen;
#endif #endif
}; };
 End of changes. 2 change blocks. 
0 lines changed or deleted 2 lines changed or added


 node_id.hpp   node_id.hpp 
skipping to change at line 41 skipping to change at line 41
*/ */
#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/config.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/address.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 TORRENT_EXPORT distance(node_id const& n1, node_id const& n2); node_id TORRENT_EXTRA_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 TORRENT_EXPORT compare_ref(node_id const& n1, node_id const& n2, node_ id const& ref); bool TORRENT_EXTRA_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 TORRENT_EXPORT distance_exp(node_id const& n1, node_id const& n2); int TORRENT_EXTRA_EXPORT distance_exp(node_id const& n1, node_id const& n2) ;
node_id TORRENT_EXPORT generate_id(); node_id TORRENT_EXTRA_EXPORT generate_id(address const& external_ip);
node_id TORRENT_EXTRA_EXPORT generate_random_id();
bool TORRENT_EXPORT verify_id(node_id const& nid, address const& source_ip) ; bool TORRENT_EXTRA_EXPORT verify_id(node_id const& nid, address const& sour ce_ip);
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // NODE_ID_HPP #endif // NODE_ID_HPP
 End of changes. 6 change blocks. 
6 lines changed or deleted 7 lines changed or added


 observer.hpp   observer.hpp 
skipping to change at line 40 skipping to change at line 40
*/ */
#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> #include <boost/cstdint.hpp>
#include <libtorrent/ptime.hpp>
#include <libtorrent/address.hpp>
namespace libtorrent { namespace libtorrent {
namespace dht { namespace dht {
struct observer; struct observer;
struct msg; struct msg;
struct traversal_algorithm;
// defined in rpc_manager.cpp // defined in rpc_manager.cpp
TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*); TORRENT_EXTRA_EXPORT void intrusive_ptr_add_ref(observer const*);
TORRENT_EXPORT void intrusive_ptr_release(observer const*); TORRENT_EXTRA_EXPORT void intrusive_ptr_release(observer const*);
// intended struct layout (on 32 bit architectures)
// offset size alignment field
// 0 8 8 sent
// 8 8 4 m_refs
// 16 4 4 pool_allocator
// 20 16 4 m_addr
// 36 2 2 m_port
// 38 1 1 flags
// 39 1 1 <padding>
// 40
struct observer : boost::noncopyable struct observer : boost::noncopyable
{ {
friend TORRENT_EXPORT void intrusive_ptr_add_ref(observer const*); friend TORRENT_EXTRA_EXPORT void intrusive_ptr_add_ref(observer cons
friend TORRENT_EXPORT void intrusive_ptr_release(observer const*); t*);
friend TORRENT_EXTRA_EXPORT void intrusive_ptr_release(observer cons
t*);
observer(boost::pool<>& p) observer(boost::intrusive_ptr<traversal_algorithm> const& a
: sent(time_now()) , udp::endpoint const& ep, node_id const& id)
, pool_allocator(p) : m_sent()
, m_refs(0) , m_refs(0)
, m_algorithm(a)
, m_id(id)
, m_port(0)
, m_transaction_id()
, flags(0)
{ {
#ifdef TORRENT_DEBUG TORRENT_ASSERT(a);
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
m_in_constructor = true; m_in_constructor = true;
m_was_sent = false;
#endif #endif
set_target(ep);
} }
virtual ~observer() virtual ~observer();
{
TORRENT_ASSERT(!m_in_constructor);
}
// these two callbacks lets the observer add
// information to the message before it's sent
virtual void send(msg& m) = 0;
// this is called when a reply is received // this is called when a reply is received
virtual void reply(msg const& m) = 0; virtual void reply(msg const& m) = 0;
// this is called if no response has been received after
// a few seconds, before the request has timed out
void short_timeout();
bool has_short_timeout() const { return (flags & flag_short_timeout)
!= 0; }
// 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; void timeout();
// 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; void abort();
#if TORRENT_USE_IPV6 ptime sent() const { return m_sent; }
address target_addr;
#else void set_target(udp::endpoint const& ep);
address_v4 target_addr; address target_addr() const;
#endif udp::endpoint target_ep() const;
boost::uint16_t port;
udp::endpoint target_ep() const { return udp::endpoint(target_addr, void set_id(node_id const& id) { m_id = id; }
port); } node_id const& id() const { return m_id; }
ptime sent;
#ifdef TORRENT_DEBUG void set_transaction_id(boost::uint16_t tid)
bool m_in_constructor; { m_transaction_id = tid; }
boost::uint16_t transaction_id() const
{ return m_transaction_id; }
enum {
flag_queried = 1,
flag_initial = 2,
flag_no_id = 4,
flag_short_timeout = 8,
flag_failed = 16,
flag_ipv6_address = 32,
flag_alive = 64,
flag_done = 128
};
#ifndef TORRENT_DHT_VERBOSE_LOGGING
protected:
#endif #endif
private:
boost::pool<>& pool_allocator; void done();
ptime m_sent;
// reference counter for intrusive_ptr // reference counter for intrusive_ptr
mutable boost::detail::atomic_count m_refs; mutable boost::detail::atomic_count m_refs;
const boost::intrusive_ptr<traversal_algorithm> m_algorithm;
node_id m_id;
TORRENT_UNION addr_t
{
#if TORRENT_USE_IPV6
address_v6::bytes_type v6;
#endif
address_v4::bytes_type v4;
} m_addr;
boost::uint16_t m_port;
// the transaction ID for this call
boost::uint16_t m_transaction_id;
public:
unsigned char flags;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool m_in_constructor:1;
bool m_was_sent:1;
#endif
}; };
typedef boost::intrusive_ptr<observer> observer_ptr; typedef boost::intrusive_ptr<observer> observer_ptr;
} } } }
#endif #endif
 End of changes. 16 change blocks. 
31 lines changed or deleted 99 lines changed or added


 parse_url.hpp   parse_url.hpp 
skipping to change at line 53 skipping to change at line 53
#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" #include "libtorrent/error_code.hpp"
namespace libtorrent namespace libtorrent
{ {
TORRENT_EXPORT boost::tuple<std::string, std::string TORRENT_EXTRA_EXPORT boost::tuple<std::string, std::string
, std::string, int, std::string> , std::string, int, std::string>
parse_url_components(std::string url, error_code& ec); parse_url_components(std::string url, error_code& ec);
} }
#endif #endif
 End of changes. 1 change blocks. 
1 lines changed or deleted 1 lines changed or added


 pch.hpp   pch.hpp 
skipping to change at line 49 skipping to change at line 49
#include <boost/array.hpp> #include <boost/array.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/date_time/gregorian/gregorian_types.hpp> #include <boost/date_time/gregorian/gregorian_types.hpp>
#include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/date_time/posix_time/posix_time_types.hpp>
#include <boost/date_time/posix_time/ptime.hpp> #include <boost/date_time/posix_time/ptime.hpp>
#include <boost/detail/atomic_count.hpp> #include <boost/detail/atomic_count.hpp>
#include <boost/enable_shared_from_this.hpp> #include <boost/enable_shared_from_this.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/exception.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/filesystem/operations.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/limits.hpp> #include <boost/limits.hpp>
#include <boost/next_prior.hpp> #include <boost/next_prior.hpp>
#include <boost/noncopyable.hpp> #include <boost/noncopyable.hpp>
skipping to change at line 106 skipping to change at line 101
#include <memory> #include <memory>
#include <numeric> #include <numeric>
#include <queue> #include <queue>
#include <set> #include <set>
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
#include <typeinfo> #include <typeinfo>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <zlib.h> #include "libtorrent/puff.h"
#ifdef __OBJC__ #ifdef __OBJC__
#define Protocol Protocol_ #define Protocol Protocol_
#endif #endif
#include <asio/ip/tcp.hpp> #include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp> #include <asio/ip/udp.hpp>
#include <asio/io_service.hpp> #include <asio/io_service.hpp>
#include <asio/deadline_timer.hpp> #include <asio/deadline_timer.hpp>
#include <asio/write.hpp> #include <asio/write.hpp>
 End of changes. 2 change blocks. 
6 lines changed or deleted 1 lines changed or added


 pe_crypto.hpp   pe_crypto.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_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
#ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED #ifndef TORRENT_PE_CRYPTO_HPP_INCLUDED
#define TORRENT_PE_CRYPTO_HPP_INCLUDED #define TORRENT_PE_CRYPTO_HPP_INCLUDED
#include <openssl/dh.h> #include "libtorrent/config.hpp"
#include <openssl/engine.h>
#ifdef TORRENT_USE_GCRYPT
#include <gcrypt.h>
#elif defined TORRENT_USE_OPENSSL
#include <openssl/rc4.h> #include <openssl/rc4.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#else
// RC4 state from libtomcrypt
struct rc4 {
int x, y;
unsigned char buf[256];
};
void TORRENT_EXTRA_EXPORT rc4_init(const unsigned char* in, unsigned long l
en, rc4 *state);
unsigned long TORRENT_EXTRA_EXPORT rc4_encrypt(unsigned char *out, unsigned
long outlen, rc4 *state);
#endif
#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 TORRENT_EXPORT dh_key_exchange class TORRENT_EXTRA_EXPORT dh_key_exchange
{ {
public: public:
dh_key_exchange(); dh_key_exchange();
~dh_key_exchange(); bool good() const { return true; }
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
// m_dh_secret. // m_dh_shared_secret.
int compute_secret(const char* remote_pubkey); int compute_secret(const char* remote_pubkey);
char const* get_secret() const { return m_dh_secret; } char const* get_secret() const { return m_dh_shared_secret; }
sha1_hash const& get_hash_xor_mask() const { return m_xor_ma sk; } sha1_hash const& get_hash_xor_mask() const { return m_xor_ma sk; }
private: private:
int get_local_key_size() const
{
TORRENT_ASSERT(m_dh);
return BN_num_bytes(m_dh->pub_key);
}
DH* m_dh; int get_local_key_size() const
{ return sizeof(m_dh_local_key); }
char m_dh_local_key[96]; char m_dh_local_key[96];
char m_dh_secret[96]; char m_dh_local_secret[96];
char m_dh_shared_secret[96];
sha1_hash m_xor_mask; sha1_hash m_xor_mask;
}; };
class RC4_handler // Non copyable struct encryption_handler
{
virtual void set_incoming_key(unsigned char const* key, int
len) = 0;
virtual void set_outgoing_key(unsigned char const* key, int
len) = 0;
virtual void encrypt(char* pos, int len) = 0;
virtual void decrypt(char* pos, int len) = 0;
virtual ~encryption_handler() {}
};
struct rc4_handler : encryption_handler
{ {
public: public:
// Input longkeys must be 20 bytes // Input longkeys must be 20 bytes
RC4_handler(const sha1_hash& rc4_local_longkey, rc4_handler()
const sha1_hash& rc4_remote_longkey) : m_encrypt(false)
, m_decrypt(false)
{ {
RC4_set_key(&m_local_key, 20, #ifdef TORRENT_USE_GCRYPT
reinterpret_cast<unsigned char const*>(rc4_l gcry_cipher_open(&m_rc4_incoming, GCRY_CIPHER_ARCFOU
ocal_longkey.begin())); R, GCRY_CIPHER_MODE_STREAM, 0);
RC4_set_key(&m_remote_key, 20, gcry_cipher_open(&m_rc4_outgoing, GCRY_CIPHER_ARCFOU
reinterpret_cast<unsigned char const*>(rc4_r R, GCRY_CIPHER_MODE_STREAM, 0);
emote_longkey.begin())); #endif
};
void set_incoming_key(unsigned char const* key, int len)
{
m_decrypt = true;
#ifdef TORRENT_USE_GCRYPT
gcry_cipher_close(m_rc4_incoming);
gcry_cipher_open(&m_rc4_incoming, GCRY_CIPHER_ARCFOU
R, GCRY_CIPHER_MODE_STREAM, 0);
gcry_cipher_setkey(m_rc4_incoming, key, len);
#elif defined TORRENT_USE_OPENSSL
RC4_set_key(&m_remote_key, len, key);
#else
rc4_init(key, len, &m_rc4_incoming);
#endif
// Discard first 1024 bytes // Discard first 1024 bytes
char buf[1024]; char buf[1024];
encrypt(buf, 1024);
decrypt(buf, 1024); decrypt(buf, 1024);
}; }
~RC4_handler() {}; void set_outgoing_key(unsigned char const* key, int len)
{
m_encrypt = true;
#ifdef TORRENT_USE_GCRYPT
gcry_cipher_close(m_rc4_outgoing);
gcry_cipher_open(&m_rc4_outgoing, GCRY_CIPHER_ARCFOU
R, GCRY_CIPHER_MODE_STREAM, 0);
gcry_cipher_setkey(m_rc4_outgoing, key, len);
#elif defined TORRENT_USE_OPENSSL
RC4_set_key(&m_local_key, len, key);
#else
rc4_init(key, len, &m_rc4_outgoing);
#endif
// Discard first 1024 bytes
char buf[1024];
encrypt(buf, 1024);
}
~rc4_handler()
{
#ifdef TORRENT_USE_GCRYPT
gcry_cipher_close(m_rc4_incoming);
gcry_cipher_close(m_rc4_outgoing);
#endif
};
void encrypt(char* pos, int len) void encrypt(char* pos, int len)
{ {
if (!m_encrypt) return;
TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos); TORRENT_ASSERT(pos);
RC4(&m_local_key, len, reinterpret_cast<unsigned cha #ifdef TORRENT_USE_GCRYPT
r const*>(pos), gcry_cipher_encrypt(m_rc4_outgoing, pos, len, 0, 0);
reinterpret_cast<unsigned char*>(pos)); #elif defined TORRENT_USE_OPENSSL
RC4(&m_local_key, len, (const unsigned char*)pos, (u
nsigned char*)pos);
#else
rc4_encrypt((unsigned char*)pos, len, &m_rc4_outgoin
g);
#endif
} }
void decrypt(char* pos, int len) void decrypt(char* pos, int len)
{ {
if (!m_decrypt) return;
TORRENT_ASSERT(len >= 0); TORRENT_ASSERT(len >= 0);
TORRENT_ASSERT(pos); TORRENT_ASSERT(pos);
RC4(&m_remote_key, len, reinterpret_cast<unsigned ch #ifdef TORRENT_USE_GCRYPT
ar const*>(pos), gcry_cipher_decrypt(m_rc4_incoming, pos, len, 0, 0);
reinterpret_cast<unsigned char*>(pos)); #elif defined TORRENT_USE_OPENSSL
RC4(&m_remote_key, len, (const unsigned char*)pos, (
unsigned char*)pos);
#else
rc4_encrypt((unsigned char*)pos, len, &m_rc4_incomin
g);
#endif
} }
private: private:
#ifdef TORRENT_USE_GCRYPT
gcry_cipher_hd_t m_rc4_incoming;
gcry_cipher_hd_t m_rc4_outgoing;
#elif defined TORRENT_USE_OPENSSL
RC4_KEY m_local_key; // Key to encrypt outgoing data RC4_KEY m_local_key; // Key to encrypt outgoing data
RC4_KEY m_remote_key; // Key to decrypt incoming data RC4_KEY m_remote_key; // Key to decrypt incoming data
#else
rc4 m_rc4_incoming;
rc4 m_rc4_outgoing;
#endif
// determines whether or not encryption and decryption is en
abled
bool m_encrypt;
bool m_decrypt;
}; };
#ifdef TORRENT_USE_OPENSSL
struct aes256_handler : encryption_handler
{
aes256_handler() : m_enc_pos(0), m_dec_pos(0)
{
EVP_CIPHER_CTX_init(&m_enc);
EVP_CIPHER_CTX_init(&m_dec);
}
~aes256_handler()
{
EVP_CIPHER_CTX_cleanup(&m_enc);
EVP_CIPHER_CTX_cleanup(&m_dec);
}
void set_incoming_key(unsigned char const* in_key, int len)
{
const int nrounds = 5;
boost::uint8_t salt[8] = { 0xf1, 0x03, 0x46, 0xe2, 0
xb1, 0xa8, 0x29, 0x63 };
boost::uint8_t key[32];
boost::uint8_t iv[32];
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), salt,
in_key, len, nrounds, key, iv);
TORRENT_ASSERT(len == 32);
EVP_EncryptInit_ex(&m_enc, EVP_aes_256_cbc(), NULL,
key, iv);
// since we're using the AES as a stream cipher, bot
h the encrypt and
// decrypt context will in fact only _encrypt_ stuff
, so initializing
// this as encrypt is not a typo
EVP_EncryptInit_ex(&m_dec, EVP_aes_256_cbc(), NULL,
key, iv);
m_enc_pos = 0;
m_dec_pos = 0;
std::memcpy(m_enc_state, iv, sizeof(m_enc_state));
std::memcpy(m_dec_state, iv, sizeof(m_enc_state));
}
void set_outgoing_key(unsigned char const* key, int len) { /
* no-op */ }
void encrypt(char* pos, int len)
{
while (len > 0)
{
while (m_enc_pos < AES_BLOCK_SIZE && len > 0
)
{
*pos ^= m_enc_state[m_enc_pos];
++m_enc_pos;
++pos;
--len;
}
if (m_enc_pos == AES_BLOCK_SIZE)
{
next_block(&m_enc, m_enc_state);
m_enc_pos = 0;
}
}
}
void decrypt(char* pos, int len)
{
while (len > 0)
{
while (m_dec_pos < AES_BLOCK_SIZE && len > 0
)
{
*pos ^= m_dec_state[m_dec_pos];
++m_dec_pos;
++pos;
--len;
}
if (m_dec_pos == AES_BLOCK_SIZE)
{
next_block(&m_dec, m_dec_state);
m_dec_pos = 0;
}
}
}
private:
// we're turning the AES block-cipher into a stream cipher.
This
// function will produce the next block in the sequence of
// block-sized buffers. We're using "Output feedback" (OFB)
mode.
void next_block(EVP_CIPHER_CTX* ctx, boost::uint8_t* pad)
{
int outlen = AES_BLOCK_SIZE;
EVP_EncryptUpdate(ctx, pad, &outlen, pad, AES_BLOCK_
SIZE);
TORRENT_ASSERT(outlen == AES_BLOCK_SIZE);
}
EVP_CIPHER_CTX m_enc;
EVP_CIPHER_CTX m_dec;
boost::uint8_t m_enc_state[AES_BLOCK_SIZE];
boost::uint8_t m_dec_state[AES_BLOCK_SIZE];
int m_enc_pos;
int m_dec_pos;
};
#endif // TORRENT_USE_OPENSSL
} // namespace libtorrent } // namespace libtorrent
#endif // TORRENT_PE_CRYPTO_HPP_INCLUDED #endif // TORRENT_PE_CRYPTO_HPP_INCLUDED
#endif // TORRENT_DISABLE_ENCRYPTION #endif // TORRENT_DISABLE_ENCRYPTION
 End of changes. 23 change blocks. 
32 lines changed or deleted 232 lines changed or added


 peer.hpp   peer.hpp 
skipping to change at line 43 skipping to change at line 43
#ifndef TORRENT_PEER_HPP_INCLUDED #ifndef TORRENT_PEER_HPP_INCLUDED
#define TORRENT_PEER_HPP_INCLUDED #define TORRENT_PEER_HPP_INCLUDED
#include <string> #include <string>
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT peer_entry struct TORRENT_EXTRA_EXPORT peer_entry
{ {
std::string ip; std::string ip;
int port; int port;
peer_id pid; peer_id pid;
bool operator==(const peer_entry& p) const bool operator==(const peer_entry& p) const
{ {
return pid == p.pid; return pid == p.pid;
} }
 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 41 skipping to change at line 41
*/ */
#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 <string> #include <string>
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
#include "libtorrent/debug.hpp" #include "libtorrent/debug.hpp"
#endif
#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/intrusive_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> #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/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp" #include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp" #include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp" #include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/session.hpp"
#include "libtorrent/bandwidth_limit.hpp" #include "libtorrent/bandwidth_limit.hpp"
#include "libtorrent/policy.hpp" #include "libtorrent/policy.hpp"
#include "libtorrent/socket_type.hpp" #include "libtorrent/socket_type_fwd.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/chained_buffer.hpp" #include "libtorrent/chained_buffer.hpp"
#include "libtorrent/disk_buffer_holder.hpp" #include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/bitfield.hpp" #include "libtorrent/bitfield.hpp"
#include "libtorrent/bandwidth_socket.hpp"
#include "libtorrent/socket_type_fwd.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/sliding_average.hpp"
#ifdef TORRENT_STATS #ifdef TORRENT_STATS
#include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/aux_/session_impl.hpp"
#endif #endif
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
struct peer_info;
struct disk_io_job;
#ifndef TORRENT_DISABLE_EXTENSIONS
struct peer_plugin; struct peer_plugin;
#endif
namespace detail namespace detail
{ {
struct session_impl; struct session_impl;
} }
struct pending_block struct pending_block
{ {
pending_block(piece_block const& b) pending_block(piece_block const& b)
: skipped(0), not_wanted(false), timed_out(false) : block(b), skipped(0), not_wanted(false)
, busy(false), block(b) {} , timed_out(false), busy(false) {}
piece_block block;
// 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; boost::uint16_t skipped:13;
// if any of these are set to true, this block // if any of these are set to true, this block
// is not allocated // is not allocated
// in the piece picker anymore, and open for // in the piece picker anymore, and open for
// other peers to pick. This may be caused by // other peers to pick. This may be caused by
// it either timing out or being received // it either timing out or being received
// unexpectedly from the peer // unexpectedly from the peer
bool not_wanted:1; bool not_wanted:1;
bool timed_out:1; bool timed_out:1;
// the busy flag is set if the block was // the busy flag is set if the block was
// requested from another peer when this // requested from another peer when this
// request was queued. We only allow a single // request was queued. We only allow a single
// busy request at a time in each peer's queue // busy request at a time in each peer's queue
bool busy:1; bool busy:1;
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; && 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; }
}; };
class TORRENT_EXPORT peer_connection class TORRENT_EXTRA_EXPORT peer_connection
: public intrusive_ptr_base<peer_connection> : public bandwidth_socket
, public boost::noncopyable , public boost::noncopyable
{ {
friend class invariant_access; friend class invariant_access;
public: public:
enum connection_type
{
bittorrent_connection = 0,
url_seed_connection = 1,
http_seed_connection = 2
};
virtual int type() const = 0;
enum channels enum channels
{ {
upload_channel, upload_channel,
download_channel, download_channel,
num_channels num_channels
}; };
// this is the constructor where the we are the active part. // this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the // The peer_conenction should handshake and verify that the
// other end has the correct id // other end has the correct id
peer_connection( peer_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::weak_ptr<torrent> t , boost::weak_ptr<torrent> t
, 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
, bool outgoing = true);
// 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
peer_connection( 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);
// this function is called after it has been constructed and properly // this function is called after it has been constructed and properly
skipping to change at line 193 skipping to change at line 209
policy::peer* peer_info_struct() const policy::peer* peer_info_struct() const
{ return m_peer_info; } { return m_peer_info; }
enum peer_speed_t { slow = 1, medium, fast }; enum peer_speed_t { slow = 1, medium, fast };
peer_speed_t peer_speed(); peer_speed_t peer_speed();
void send_allowed_set(); void send_allowed_set();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<peer_plugin>); void add_extension(boost::shared_ptr<peer_plugin>);
peer_plugin const* find_plugin(char const* type);
#endif #endif
// this function is called once the torrent associated // this function is called once the torrent associated
// with this peer connection has retrieved the meta- // with this peer connection has retrieved the meta-
// data. If the torrent was spawned with metadata // data. If the torrent was spawned with metadata
// this is called from the constructor. // this is called from the constructor.
void init(); void init();
// this is called when the metadata is retrieved // this is called when the metadata is retrieved
// and the files has been checked // and the files has been checked
virtual void on_metadata() {}; virtual void on_metadata() {};
void on_metadata_impl(); void on_metadata_impl();
int get_upload_limit() const;
int get_download_limit() const;
void set_upload_limit(int limit); void set_upload_limit(int limit);
void set_download_limit(int limit); void set_download_limit(int limit);
int upload_limit() const { return m_upload_limit; } int upload_limit() const { return m_upload_limit; }
int download_limit() const { return m_download_limit; } int download_limit() const { return m_download_limit; }
int prefer_whole_pieces() const int prefer_whole_pieces() const
{ {
if (on_parole()) return 1; if (on_parole()) return 1;
return m_prefer_whole_pieces; return m_prefer_whole_pieces;
skipping to change at line 239 skipping to change at line 258
void request_large_blocks(bool b) void request_large_blocks(bool b)
{ m_request_large_blocks = b; } { m_request_large_blocks = b; }
void set_endgame(bool b) { m_endgame_mode = b; } void set_endgame(bool b) { m_endgame_mode = b; }
bool endgame() const { return m_endgame_mode; } bool endgame() const { return m_endgame_mode; }
bool no_download() const { return m_no_download; } bool no_download() const { return m_no_download; }
void no_download(bool b) { m_no_download = b; } void no_download(bool b) { m_no_download = b; }
bool ignore_stats() const { return m_ignore_stats; }
void ignore_stats(bool b) { m_ignore_stats = b; }
void set_priority(int p) void set_priority(int p)
{ {
TORRENT_ASSERT(p > 0); TORRENT_ASSERT(p > 0);
TORRENT_ASSERT(m_priority <= 255); TORRENT_ASSERT(m_priority <= 255);
if (p > 255) p = 255; if (p > 255) p = 255;
m_priority = p; 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; }
skipping to change at line 265 skipping to change at line 287
// and only allow it to request that piece // and only allow it to request that piece
void superseed_piece(int index); void superseed_piece(int index);
int superseed_piece() const { return m_superseed_piece; } 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(char* state = 0) const; bool can_read(char* state = 0) const;
bool is_seed() const; bool is_seed() const;
int num_have_pieces() const { return m_num_pieces; }
void set_share_mode(bool m);
bool share_mode() const { return m_share_mode; }
void set_upload_only(bool u); void set_upload_only(bool u);
bool upload_only() const { return m_upload_only; } bool upload_only() const { return m_upload_only; }
void set_holepunch_mode()
{
m_holepunch_mode = true;
#ifdef TORRENT_VERBOSE_LOGGING
peer_log("*** HOLEPUNCH MODE ***");
#endif
}
// 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& peer_id) { m_peer_id = peer_id; } 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::vector<pending_block> const& download_queue() const; std::vector<pending_block> const& download_queue() const;
std::vector<pending_block> const& request_queue() const; std::vector<pending_block> const& request_queue() const;
std::vector<peer_request> const& upload_queue() const; std::vector<peer_request> const& upload_queue() const;
void clear_request_queue();
// estimate of how long it will take until we have // estimate of how long it will take until we have
// received all piece requests that we have sent // received all piece requests that we have sent
// if extra_bytes is specified, it will include those // if extra_bytes is specified, it will include those
// bytes as if they've been requested // bytes as if they've been requested
time_duration download_queue_time(int extra_bytes = 0) const ; 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; }
skipping to change at line 323 skipping to change at line 359
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 on_timeout(); void on_timeout();
// this will cause this peer_connection to be disconnected. // this will cause this peer_connection to be disconnected.
void disconnect(error_code const& ec, int error = 0); virtual void disconnect(error_code const& ec, int error = 0)
;
// called when a connect attempt fails (not when an
// established connection fails)
void connect_failed(error_code const& e);
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; }
skipping to change at line 363 skipping to change at line 402
void add_free_upload(size_type free_upload); void add_free_upload(size_type free_upload);
// trust management. // trust management.
void received_valid_data(int index); void received_valid_data(int index);
void received_invalid_data(int index); void received_invalid_data(int index);
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_outgoing() const { return m_outgoing; }
bool received_listen_port() const { return m_received_listen
_port; }
void received_listen_port()
{ m_received_listen_port = true; }
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) void ignore_bandwidth_limits(bool i)
{ m_ignore_bandwidth_limits = i; } { m_ignore_bandwidth_limits = i; }
bool ignore_unchoke_slots() const; bool ignore_unchoke_slots() const;
void ignore_unchoke_slots(bool i) void ignore_unchoke_slots(bool i)
{ m_ignore_unchoke_slots = i; } { m_ignore_unchoke_slots = i; }
bool failed() const { return m_failed; } bool failed() const { return m_failed; }
int desired_queue_size() const int desired_queue_size() const
{ {
// this peer is in end-game mode we only want // this peer is in end-game mode we only want
// one outstanding request // one outstanding request
return m_endgame_mode ? 1: m_desired_queue_size; return m_endgame_mode ? 1: m_desired_queue_size;
} }
bool bittyrant_unchoke_compare(
boost::intrusive_ptr<peer_connection const> const& p
) const;
// 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; 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();
void increase_est_reciprocation_rate();
void decrease_est_reciprocation_rate();
int est_reciprocation_rate() const { return m_est_reciprocat
ion_rate; }
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING
void peer_log(char const* fmt, ...) const;
boost::shared_ptr<logger> m_logger; boost::shared_ptr<logger> m_logger;
#endif #endif
// the message handlers are called // the message handlers are called
// each time a recv() returns some new // each time a recv() returns some new
// data, the last time it will be called // data, the last time it will be called
// is when the entire packet has been // is when the entire packet has been
// received, then it will no longer // received, then it will no longer
// be called. i.e. most handlers need // be called. i.e. most handlers need
// to check how much of the packet they // to check how much of the packet they
skipping to change at line 433 skipping to change at line 483
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);
void set_has_metadata(bool m) { m_has_metadata = m; }
bool has_metadata() const { return m_has_metadata; }
// the following functions appends messages // the following functions appends messages
// to the send buffer // to the send buffer
bool 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 send_suggest(int piece);
void snub_peer(); void snub_peer();
bool can_request_time_critical() const; bool can_request_time_critical() const;
void make_time_critical(piece_block const& block); void make_time_critical(piece_block const& block);
// adds a block to the request queue // adds a block to the request queue
// returns true if successful, false otherwise // returns true if successful, false otherwise
enum flags_t { req_time_critical = 1, req_busy = 2 }; enum flags_t { req_time_critical = 1, req_busy = 2 };
bool add_request(piece_block const& b, int flags = 0); bool add_request(piece_block const& b, int flags = 0);
// clears the request queue and sends cancels for all messag es // clears the request queue and sends cancels for all messag es
// in the download queue // in the download queue
void cancel_all_requests(); 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); // if force is true, the blocks is also freed from the piece
// picker, allowing another peer to request it immediately
void cancel_request(piece_block const& b, bool force = false
);
void send_block_requests(); void send_block_requests();
int bandwidth_throttle(int channel) const int bandwidth_throttle(int channel) const
{ return m_bandwidth_channel[channel].throttle(); } { return m_bandwidth_channel[channel].throttle(); }
void assign_bandwidth(int channel, int amount); void assign_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;
skipping to change at line 485 skipping to change at line 541
// returns the block currently being // returns the block currently being
// downloaded. And the progress of that // downloaded. And the progress of that
// block. If the peer isn't downloading // block. If the peer isn't downloading
// a piece for the moment, the boost::optional // a piece for the moment, the boost::optional
// will be invalid. // will be invalid.
virtual boost::optional<piece_block_progress> virtual boost::optional<piece_block_progress>
downloading_piece_progress() const downloading_piece_progress() const
{ {
#ifdef TORRENT_VERBOSE_LOGGING #ifdef TORRENT_VERBOSE_LOGGING
(*m_logger) << "downloading_piece_progress() dispatc hed to the base class!\n"; peer_log("*** downloading_piece_progress() dispatche d to the base class!");
#endif #endif
return boost::optional<piece_block_progress>(); return boost::optional<piece_block_progress>();
} }
// 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 virtual void send_buffer(char const* begin, int size, int fl
ags = 0); ags = 0
virtual buffer::interval allocate_send_buffer(int size); , void (*fun)(char*, int, void*) = 0, void* userdata
= 0);
virtual void setup_send(); virtual void setup_send();
void cork_socket() { TORRENT_ASSERT(!m_corked); m_corked = t
rue; }
void uncork_socket();
#ifdef TORRENT_DISK_STATS
void log_buffer_usage(char* buffer, int size, char const* la
bel);
#endif
template <class Destructor> template <class Destructor>
void append_send_buffer(char* buffer, int size, Destructor c void append_send_buffer(char* buffer, int size, Destructor c
onst& destructor) onst& destructor
, bool encrypted = false)
{ {
#if TORRENT_DISK_STATS #if defined TORRENT_DISK_STATS
if (m_ses.m_disk_thread.is_disk_buffer(buffer)) log_buffer_usage(buffer, size, "queued send buffer")
m_ses.m_disk_thread.rename_buffer(buffer, "q ;
ueued send buffer");
#endif #endif
// bittorrent connections should never use this func
tion, since
// they might be encrypted and this would circumvent
the actual
// encryption. bt_peer_connection overrides this fun
ction with
// its own version.
TORRENT_ASSERT(encrypted || type() != bittorrent_con
nection);
m_send_buffer.append_buffer(buffer, size, size, dest ructor); m_send_buffer.append_buffer(buffer, size, size, dest ructor);
#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.log_buffer_usage();
#endif
} }
virtual void append_const_send_buffer(char const* buffer, in t size); 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
int outstanding_bytes() const { return m_outstanding_bytes;
}
int send_buffer_size() const int send_buffer_size() const
{ return m_send_buffer.size(); } { return m_send_buffer.size(); }
int send_buffer_capacity() const int send_buffer_capacity() const
{ return m_send_buffer.capacity(); } { return m_send_buffer.capacity(); }
int packet_size() const { return m_packet_size; } int packet_size() const { return m_packet_size; }
bool packet_finished() const bool packet_finished() const
{ return m_packet_size <= m_recv_pos; } { return m_packet_size <= m_recv_pos; }
int receive_pos() const { return m_recv_pos; }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool piece_failed; bool piece_failed;
#endif #endif
time_t last_seen_complete() const { return m_last_seen_compl
ete; }
void set_last_seen_complete(int ago) { m_last_seen_complete
= time(0) - ago; }
// 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 size_type uploaded_since_unchoke() const
{ return m_statistics.total_payload_upload() - m_uploaded_at _last_unchoke; } { return m_statistics.total_payload_upload() - m_uploaded_at _last_unchoke; }
size_type downloaded_since_unchoke() const size_type downloaded_since_unchoke() const
{ return m_statistics.total_payload_download() - m_downloade d_at_last_unchoke; } { return m_statistics.total_payload_download() - m_downloade d_at_last_unchoke; }
// called when the disk write buffer is drained again, and w
e can
// start downloading payload again
void on_disk();
int num_reading_bytes() const { return m_reading_bytes; }
enum sync_t { read_async, read_sync }; enum sync_t { read_async, read_sync };
void setup_receive(sync_t sync = read_sync); void setup_receive(sync_t sync = read_sync);
protected: protected:
size_t try_read(sync_t s, error_code& ec); size_t try_read(sync_t s, error_code& ec);
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;
virtual void write_have(int index) = 0; virtual void write_have(int index) = 0;
virtual void write_keepalive() = 0; virtual void write_keepalive() = 0;
virtual void write_piece(peer_request const& r, disk_buffer_ holder& buffer) = 0; virtual void write_piece(peer_request const& r, disk_buffer_ holder& buffer) = 0;
virtual void write_suggest(int piece) = 0;
virtual void write_reject_request(peer_request const& r) = 0 ; virtual void write_reject_request(peer_request const& r) = 0 ;
virtual void write_allow_fast(int piece) = 0; virtual void write_allow_fast(int piece) = 0;
virtual void on_connected() = 0; virtual void on_connected() = 0;
virtual void on_tick() {} virtual void on_tick() {}
virtual void on_receive(error_code const& error virtual void on_receive(error_code const& error
, std::size_t bytes_transferred) = 0; , std::size_t bytes_transferred) = 0;
virtual void on_sent(error_code const& error virtual void on_sent(error_code const& error
, std::size_t bytes_transferred) = 0; , std::size_t bytes_transferred) = 0;
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
buffer::interval wr_recv_buffer() buffer::interval wr_recv_buffer()
{ {
if (m_recv_buffer.empty())
{
TORRENT_ASSERT(m_recv_pos == 0);
return buffer::interval(0,0);
}
TORRENT_ASSERT(!m_disk_recv_buffer); TORRENT_ASSERT(!m_disk_recv_buffer);
TORRENT_ASSERT(m_disk_recv_buffer_size == 0); TORRENT_ASSERT(m_disk_recv_buffer_size == 0);
if (m_recv_buffer.empty()) return buffer::interval(0 ,0); int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buff er.size()));
return buffer::interval(&m_recv_buffer[0] return buffer::interval(&m_recv_buffer[0]
, &m_recv_buffer[0] + m_recv_pos); , &m_recv_buffer[0] + rcv_pos);
} }
std::pair<buffer::interval, buffer::interval> wr_recv_buffer s(int bytes); std::pair<buffer::interval, buffer::interval> wr_recv_buffer s(int bytes);
#endif #endif
buffer::const_interval receive_buffer() const buffer::const_interval receive_buffer() const
{ {
if (m_recv_buffer.empty()) return buffer::const_inte if (m_recv_buffer.empty())
rval(0,0); {
TORRENT_ASSERT(m_recv_pos == 0);
return buffer::interval(0,0);
}
int rcv_pos = (std::min)(m_recv_pos, int(m_recv_buff
er.size()));
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] + rcv_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, int offse t = 0);
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 ize; } void set_soft_packet_size(int size) { m_soft_packet_size = s ize; }
void attach_to_torrent(sha1_hash const& ih); // if allow_encrypted is false, and the torrent 'ih' turns o
ut
// to be an encrypted torrent (AES-256 encrypted) the peer w
ill
// be disconnected. This is to prevent non-encrypted peers t
o
// attach to an encrypted torrent
void attach_to_torrent(sha1_hash const& ih, bool allow_encry
pted);
bool verify_piece(peer_request const& p) const; bool verify_piece(peer_request const& p) const;
void update_desired_queue_size();
// 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_channel m_bandwidth_channel[num_channels]; bandwidth_channel m_bandwidth_channel[num_channels];
// number of bytes this peer can send and receive // number of bytes this peer can send and receive
int m_quota[2]; 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
skipping to change at line 631 skipping to change at line 725
// 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;
// called from the main loop when this connection has any // called from the main loop when this connection has any
// work to do. // work to do.
void on_send_data(error_code const& error void on_send_data(error_code const& error
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void on_receive_data(error_code const& error void on_receive_data(error_code const& error
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
void on_receive_data_nolock(error_code const& error
, std::size_t bytes_transferred);
// this is the limit on the number of outstanding requests // this is the limit on the number of outstanding requests
// we have to this peer. This is initialized to the settings // we have to this peer. This is initialized to the settings
// in the session_settings structure. But it may be lowered // in the session_settings structure. But it may be lowered
// if the peer is known to require a smaller limit (like Bit Comet). // if the peer is known to require a smaller limit (like Bit Comet).
// or if the extended handshake sets a limit. // or if the extended handshake sets a limit.
// web seeds also has a limit on the queue size. // web seeds also has a limit on the queue size.
int m_max_out_request_queue; int m_max_out_request_queue;
// the average rate of receiving complete piece messages
sliding_average<20> m_piece_rate;
sliding_average<20> m_send_rate;
void set_timeout(int s) { m_timeout = s; } void set_timeout(int s) { m_timeout = s; }
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
typedef std::list<boost::shared_ptr<peer_plugin> > extension _list_t; typedef std::list<boost::shared_ptr<peer_plugin> > extension _list_t;
extension_list_t m_extensions; extension_list_t m_extensions;
#endif #endif
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// in case the session settings is set // in case the session settings is set
// to resolve countries, this is set to // to resolve countries, this is set to
// the two character country code this // the two character country code this
// peer resides in. // peer resides in.
char m_country[2]; char m_country[2];
#endif #endif
#ifdef TORRENT_DEBUG
boost::intrusive_ptr<peer_connection> self() boost::intrusive_ptr<peer_connection> self()
{ {
TORRENT_ASSERT(!m_in_constructor); TORRENT_ASSERT(!m_in_constructor);
return intrusive_ptr_base<peer_connection>::self(); return boost::intrusive_ptr<peer_connection>(this);
} }
#endif
private: private:
std::pair<int, int> preferred_caching() const;
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( int request_upload_bandwidth(
bandwidth_channel* bwc1 bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0 , bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0 , bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 0); , bandwidth_channel* bwc4 = 0);
void request_download_bandwidth( int request_download_bandwidth(
bandwidth_channel* bwc1 bandwidth_channel* bwc1
, bandwidth_channel* bwc2 = 0 , bandwidth_channel* bwc2 = 0
, bandwidth_channel* bwc3 = 0 , bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 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
skipping to change at line 689 skipping to change at line 784
, bandwidth_channel* bwc3 = 0 , bandwidth_channel* bwc3 = 0
, bandwidth_channel* bwc4 = 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
ptime m_last_request; ptime m_last_request;
// the time we received the last // the time we received the last
// piece request from the peer // piece request from the peer
ptime m_last_incoming_request; ptime m_last_incoming_request;
// the time when we unchoked this peer // the time when we unchoked this peer
ptime m_last_unchoke; ptime m_last_unchoke;
// if we're unchoked by this peer, this
// was the time
ptime m_last_unchoked;
// timeouts // timeouts
ptime m_last_receive; ptime m_last_receive;
ptime m_last_sent; ptime m_last_sent;
// the time when the first entry in the // the time when the first entry in the
// request queue was requested, increased // request queue was requested, increased
// for each entry that is popped from the // for each entry that is popped from the
// download queue. Used for request timeout // download queue. Used for request timeout
ptime m_requested; ptime m_requested;
// if the timeout is extended for the outstanding
// requests, this is the number of seconds it was
// extended.
int m_timeout_extend;
// a timestamp when the remote download rate // a timestamp when the remote download rate
// was last updated // was last updated
ptime m_remote_dl_update; ptime m_remote_dl_update;
// the time when async_connect was called // the time when async_connect was called
// or when the incoming connection was established // or when the incoming connection was established
ptime m_connect; ptime m_connect;
// the time when this peer sent us a not_interested message // the time when this peer sent us a not_interested message
// the last time. // the last time.
skipping to change at line 779 skipping to change at line 874
// 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 that haven't been issued
// to the disk thread yet
std::vector<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::vector<pending_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::vector<pending_block> m_download_queue; std::vector<pending_block> m_download_queue;
skipping to change at line 810 skipping to change at line 906
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 // the block we're currently receiving. Or
// (-1, -1) if we're not receiving one // (-1, -1) if we're not receiving one
piece_block m_receiving_block; piece_block m_receiving_block;
// the time when this peer last saw a complete copy
// of this torrent
time_t m_last_seen_complete;
// if the timeout is extended for the outstanding
// requests, this is the number of seconds it was
// extended.
int m_timeout_extend;
// the number of bytes that the other // the number of bytes that the other
// end has to send us in order to respond // end has to send us in order to respond
// to all outstanding piece requests we // to all outstanding piece requests we
// have sent to it // have sent to it
int m_outstanding_bytes; int m_outstanding_bytes;
// the number of outstanding bytes expected // the number of outstanding bytes expected
// to be received by extensions // to be received by extensions
int m_extension_outstanding_bytes; int m_extension_outstanding_bytes;
skipping to change at line 915 skipping to change at line 1020
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.
int m_outstanding_writing_bytes; int m_outstanding_writing_bytes;
// max transfer rates seen on this peer // max transfer rates seen on this peer
int m_download_rate_peak; int m_download_rate_peak;
int m_upload_rate_peak; int m_upload_rate_peak;
// when using the BitTyrant choker, this is our
// estimated reciprocation rate. i.e. the rate
// we need to send to this peer for it to unchoke
// us
int m_est_reciprocation_rate;
// estimated round trip time to this peer // estimated round trip time to this peer
// based on the time from when async_connect // based on the time from when async_connect
// was called to when on_connection_complete // was called to when on_connection_complete
// was called. The rtt is specified in milliseconds // was called. The rtt is specified in milliseconds
boost::uint16_t m_rtt; boost::uint16_t m_rtt;
// if set to non-zero, this peer will always prefer // if set to non-zero, this peer will always prefer
// to request entire n pieces, rather than blocks. // to request entire n pieces, rather than blocks.
// 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
skipping to change at line 941 skipping to change at line 1052
boost::uint8_t m_desired_queue_size; boost::uint8_t m_desired_queue_size;
// the number of piece requests we have rejected // the number of piece requests we have rejected
// in a row because the peer is choked. This is // in a row because the peer is choked. This is
// used to re-send the choked message in case the // used to re-send the choked message in case the
// other end keeps requesting pieces while being // other end keeps requesting pieces while being
// choked, and eventuelly disconnect if it keeps // choked, and eventuelly disconnect if it keeps
// requesting too many pieces while being choked // requesting too many pieces while being choked
boost::uint8_t m_choke_rejects; boost::uint8_t m_choke_rejects;
// counts the number of recursive calls to on_receive_data
// used to limit recursion
boost::uint8_t m_read_recurse:5;
// 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
bool m_active:1; bool m_outgoing:1;
// is true if we learn the incoming connections listening
// during the extended handshake
bool m_received_listen_port:1;
// other side says that it's interested in downloading // other side says that it's interested in downloading
// from us. // from us.
bool m_peer_interested:1; bool m_peer_interested:1;
// the other side has told us that it won't send anymore // the other side has told us that it won't send anymore
// data to us for a while // data to us for a while
bool m_peer_choked:1; bool m_peer_choked:1;
// the peer has pieces we are interested in // the peer has pieces we are interested in
skipping to change at line 1019 skipping to change at line 1130
bool m_queued:1; bool m_queued:1;
// if this is true, the blocks picked by the piece // if this is true, the blocks picked by the piece
// picker will be merged before passed to the // picker will be merged before passed to the
// request function. i.e. subsequent blocks are // request function. i.e. subsequent blocks are
// merged into larger blocks. This is used by // merged into larger blocks. This is used by
// the http-downloader, to request whole pieces // the http-downloader, to request whole pieces
// at a time. // at a time.
bool m_request_large_blocks:1; bool m_request_large_blocks:1;
// set to true if this peer is in share mode
bool m_share_mode:1;
// set to true when this peer is only uploading // set to true when this peer is only uploading
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;
skipping to change at line 1041 skipping to change at line 1155
// pick any pieces from this peer // pick any pieces from this peer
bool m_no_download:1; bool m_no_download:1;
// this is set to true if the last time we tried to // this is set to true if the last time we tried to
// pick a piece to download, we could only find // pick a piece to download, we could only find
// blocks that were already requested from other // blocks that were already requested from other
// peers. In this case, we should not try to pick // peers. In this case, we should not try to pick
// another piece until the last one we requested is done // another piece until the last one we requested is done
bool m_endgame_mode:1; bool m_endgame_mode:1;
// set to true when we've sent the first round of suggests
bool m_sent_suggests:1;
// set to true while we're trying to holepunch
bool m_holepunch_mode:1;
// when this is set, the transfer stats for this connection
// is not included in the torrent or session stats
bool m_ignore_stats:1;
// when this is set, the peer_connection socket is
// corked, similar to the linux TCP feature TCP_CORK.
// we won't send anything to the actual socket, just
// buffer messages up in the application layer send
// buffer, and send it once we're uncorked.
bool m_corked:1;
// set to true if this peer has metadata, and false
// otherwise.
bool m_has_metadata:1;
template <std::size_t Size> template <std::size_t Size>
struct handler_storage struct handler_storage
{ {
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
handler_storage() handler_storage()
: used(false) : used(false)
{} {}
bool used; bool used;
#endif #endif
skipping to change at line 1126 skipping to change at line 1261
template <class Handler> template <class Handler>
allocating_handler<Handler, TORRENT_WRITE_HANDLER_MAX_SIZE> allocating_handler<Handler, TORRENT_WRITE_HANDLER_MAX_SIZE>
make_write_handler(Handler const& handler) make_write_handler(Handler const& handler)
{ {
return allocating_handler<Handler, TORRENT_WRITE_HAN DLER_MAX_SIZE>( return allocating_handler<Handler, TORRENT_WRITE_HAN DLER_MAX_SIZE>(
handler, m_write_handler_storage handler, m_write_handler_storage
); );
} }
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
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_in_use;
int m_received_in_piece; int m_received_in_piece;
#endif #endif
}; };
struct cork
{
cork(peer_connection& p): m_pc(p) { m_pc.cork_socket(); }
~cork() { m_pc.uncork_socket(); }
peer_connection& m_pc;
};
} }
#endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 72 change blocks. 
58 lines changed or deleted 221 lines changed or added


 peer_id.hpp   peer_id.hpp 
skipping to change at line 43 skipping to change at line 43
#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 <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"
#if TORRENT_USE_IOSTREAM #if TORRENT_USE_IOSTREAM
#include "libtorrent/escape_string.hpp" // to_hex, from_hex
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#endif #endif
#ifdef max #ifdef max
#undef max #undef max
#endif #endif
#ifdef min #ifdef min
#undef min #undef min
skipping to change at line 70 skipping to change at line 70
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 };
big_number() { clear(); } big_number() { clear(); }
static big_number max()
{
big_number ret;
memset(ret.m_number, 0xff, size);
return ret;
}
static big_number min()
{
big_number ret;
memset(ret.m_number, 0, size);
return ret;
}
explicit big_number(char const* s) explicit big_number(char const* s)
{ {
if (s == 0) clear(); if (s == 0) clear();
else std::memcpy(m_number, s, size); else std::memcpy(m_number, s, size);
} }
explicit big_number(std::string const& s) explicit big_number(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.c_str(), 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.c_str(), sl);
} }
void assign(char const* str) { std::memcpy(m_number, str, si ze); } void assign(char const* str) { std::memcpy(m_number, str, si ze); }
void clear() { std::memset(m_number, 0, number_size); } void clear() { std::memset(m_number, 0, number_size); }
bool is_all_zeros() const bool is_all_zeros() const
{ {
for (const unsigned char* i = m_number; i < m_number +number_size; ++i) for (const unsigned char* i = m_number; i < m_number +number_size; ++i)
if (*i != 0) return false; if (*i != 0) return false;
return true; return true;
} }
big_number& operator<<=(int n)
{
TORRENT_ASSERT(n >= 0);
int num_bytes = n / 8;
if (num_bytes >= number_size)
{
std::memset(m_number, 0, number_size);
return *this;
}
if (num_bytes > 0)
{
std::memmove(m_number, m_number + num_bytes,
number_size - num_bytes);
std::memset(m_number + number_size - num_byt
es, 0, num_bytes);
n -= num_bytes * 8;
}
if (n > 0)
{
for (int i = 0; i < number_size - 1; ++i)
{
m_number[i] <<= n;
m_number[i] |= m_number[i+1] >> (8 -
n);
}
}
return *this;
}
big_number& operator>>=(int n)
{
TORRENT_ASSERT(n >= 0);
int num_bytes = n / 8;
if (num_bytes >= number_size)
{
std::memset(m_number, 0, number_size);
return *this;
}
if (num_bytes > 0)
{
std::memmove(m_number + num_bytes, m_number,
number_size - num_bytes);
std::memset(m_number, 0, num_bytes);
n -= num_bytes * 8;
}
if (n > 0)
{
for (int i = number_size - 1; i > 0; --i)
{
m_number[i] >>= n;
m_number[i] |= m_number[i-1] << (8 -
n);
}
}
return *this;
}
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 128 skipping to change at line 195
} }
big_number operator~() big_number operator~()
{ {
big_number ret; big_number ret;
for (int i = 0; i< number_size; ++i) for (int i = 0; i< number_size; ++i)
ret.m_number[i] = ~m_number[i]; ret.m_number[i] = ~m_number[i];
return ret; return ret;
} }
big_number operator^ (big_number const& n) const
{
big_number ret = *this;
ret ^= n;
return ret;
}
big_number operator& (big_number const& n) const
{
big_number ret = *this;
ret &= n;
return ret;
}
big_number& operator &= (big_number const& n) big_number& operator &= (big_number const& n)
{ {
for (int i = 0; i< number_size; ++i) for (int i = 0; i< number_size; ++i)
m_number[i] &= n.m_number[i]; m_number[i] &= n.m_number[i];
return *this; return *this;
} }
big_number& operator |= (big_number const& n) big_number& operator |= (big_number const& n)
{ {
for (int i = 0; i< number_size; ++i) for (int i = 0; i< number_size; ++i)
 End of changes. 7 change blocks. 
3 lines changed or deleted 89 lines changed or added


 peer_info.hpp   peer_info.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_PEER_INFO_HPP_INCLUDED #ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED #define TORRENT_PEER_INFO_HPP_INCLUDED
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/deadline_timer.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/bitfield.hpp" #include "libtorrent/bitfield.hpp"
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT peer_info struct TORRENT_EXPORT peer_info
{ {
enum enum
skipping to change at line 62 skipping to change at line 63
supports_extensions = 0x10, supports_extensions = 0x10,
local_connection = 0x20, local_connection = 0x20,
handshake = 0x40, handshake = 0x40,
connecting = 0x80, connecting = 0x80,
queued = 0x100, queued = 0x100,
on_parole = 0x200, on_parole = 0x200,
seed = 0x400, seed = 0x400,
optimistic_unchoke = 0x800, optimistic_unchoke = 0x800,
snubbed = 0x1000, snubbed = 0x1000,
upload_only = 0x2000, upload_only = 0x2000,
endgame_mode = 0x4000 endgame_mode = 0x4000,
holepunched = 0x8000
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
, rc4_encrypted = 0x100000, , rc4_encrypted = 0x100000,
plaintext_encrypted = 0x200000 plaintext_encrypted = 0x200000
#endif #endif
}; };
unsigned int flags; unsigned int flags;
enum peer_source_flags enum peer_source_flags
{ {
skipping to change at line 88 skipping to change at line 90
incoming = 0x20 incoming = 0x20
}; };
int source; int source;
// bw_idle: the channel is not used // bw_idle: the channel is not used
// bw_limit: the channel is waiting for quota // bw_limit: the channel is waiting for 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
// bw_disk: the peer is waiting for the disk io thread // bw_disk: the peer is waiting for the disk io thread
// to catch up // this is a bitmask, a peer can wait for network and
enum bw_state { bw_idle, bw_limit, bw_network, bw_disk }; // disk at the same time!
enum bw_state { bw_idle = 0, bw_limit = 1, bw_network = 2, b
w_disk = 4 };
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
enum bw_state_deprecated { bw_torrent = bw_limit, bw_global = bw_limit }; enum bw_state_deprecated { bw_torrent = bw_limit, bw_global = bw_limit };
#endif #endif
char read_state; char read_state;
char write_state; char write_state;
tcp::endpoint ip; tcp::endpoint ip;
int up_speed; int up_speed;
int down_speed; int down_speed;
skipping to change at line 157 skipping to change at line 160
#endif #endif
size_type load_balancing; size_type load_balancing;
// this is the number of requests // this is the number of requests
// we have sent to this peer // we have sent to this peer
// that we haven't got a response // that we haven't got a response
// for yet // for yet
int download_queue_length; int download_queue_length;
// the number of block requests that have
// timed out, and are still in the download
// queue
int timed_out_requests;
// the number of busy requests in the download
// queue. A budy request is a request for a block
// we've also requested from a different peer
int busy_requests;
// the number of request messages // the number of request messages
// waiting to be sent inside the send buffer // waiting to be sent inside the send buffer
int requests_in_buffer; int requests_in_buffer;
// the number of requests that is // the number of requests that is
// tried to be maintained (this is // tried to be maintained (this is
// typically a function of download speed) // typically a function of download speed)
int target_dl_queue_length; int target_dl_queue_length;
// this is the number of requests // this is the number of requests
skipping to change at line 189 skipping to change at line 202
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 http_seed = 2,
bittorrent_utp = 3
}; };
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;
skipping to change at line 217 skipping to change at line 231
// the number of pieces this peer has // the number of pieces this peer has
int num_pieces; 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; // [0, 1] float progress; // [0, 1]
int progress_ppm; // [0, 1000000] int progress_ppm; // [0, 1000000]
int estimated_reciprocation_rate;
tcp::endpoint local_endpoint;
}; };
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;
 End of changes. 6 change blocks. 
4 lines changed or deleted 23 lines changed or added


 peer_request.hpp   peer_request.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_PEER_REQUEST_HPP_INCLUDED #ifndef TORRENT_PEER_REQUEST_HPP_INCLUDED
#define TORRENT_PEER_REQUEST_HPP_INCLUDED #define TORRENT_PEER_REQUEST_HPP_INCLUDED
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT peer_request struct TORRENT_EXTRA_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 45 skipping to change at line 45
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <bitset> #include <bitset>
#include <utility> #include <utility>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/static_assert.hpp> #include <boost/static_assert.hpp>
#include <boost/cstdint.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/time.hpp"
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_EXTRA_EXPORT piece_block
{ {
const static piece_block invalid; const static piece_block invalid;
piece_block() {} piece_block() {}
piece_block(int p_index, int b_index) piece_block(boost::uint32_t p_index, boost::uint16_t b_index )
: piece_index(p_index) : piece_index(p_index)
, block_index(b_index) , block_index(b_index)
{} {
int piece_index; TORRENT_ASSERT(p_index < (1 << 19));
int block_index; TORRENT_ASSERT(b_index < (1 << 13));
}
boost::uint32_t piece_index:19;
boost::uint32_t block_index:13;
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;
if (piece_index == b.piece_index) return block_index < b.block_index; if (piece_index == b.piece_index) return block_index < b.block_index;
return false; return false;
} }
bool operator==(piece_block const& b) const bool operator==(piece_block const& b) const
{ return piece_index == b.piece_index && block_index == b.bl ock_index; } { return piece_index == b.piece_index && block_index == b.bl ock_index; }
bool operator!=(piece_block const& b) const bool operator!=(piece_block const& b) const
{ return piece_index != b.piece_index || block_index != b.bl ock_index; } { return piece_index != b.piece_index || block_index != b.bl ock_index; }
}; };
class TORRENT_EXPORT piece_picker class TORRENT_EXTRA_EXPORT piece_picker
{ {
public: public:
struct piece_pos;
enum enum
{ {
// the number of priority levels // the number of priority levels
priority_levels = 8, priority_levels = 8,
// priority factor // priority factor
prio_factor = priority_levels - 4 prio_factor = priority_levels - 4
}; };
struct block_info struct block_info
{ {
skipping to change at line 115 skipping to change at line 120
// the peer this block was requested or // the peer this block was requested or
// downloaded from. This is a pointer to // downloaded from. This is a pointer to
// a policy::peer object // a policy::peer object
void* peer; void* peer;
// the number of peers that has this block in their // the number of peers that has this block in their
// download or request queues // download or request queues
unsigned num_peers:14; unsigned num_peers:14;
// the state of this block // the state of this block
enum { state_none, state_requested, state_writing, s tate_finished }; enum { state_none, state_requested, state_writing, s tate_finished };
unsigned state:2; unsigned state:2;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
// to allow verifying the invariant of blocks belong
ing to the right piece
int piece_index;
#endif
}; };
// the peers that are downloading this piece // the peers that are downloading this piece
// are considered fast peers or slow peers. // are considered fast peers or slow peers.
// none is set if the blocks were downloaded // none is set if the blocks were downloaded
// in a previous session // in a previous session
enum piece_state_t enum piece_state_t
{ none, slow, medium, fast }; { none, slow, medium, fast };
enum options_t enum options_t
skipping to change at line 147 skipping to change at line 156
speed_affinity = 32, speed_affinity = 32,
// ignore the prefer_whole_pieces parameter // ignore the prefer_whole_pieces parameter
ignore_whole_pieces = 64 ignore_whole_pieces = 64
}; };
struct downloading_piece struct downloading_piece
{ {
downloading_piece(): state(none), index(-1), info(0) downloading_piece(): state(none), index(-1), info(0)
, finished(0), writing(0), requested(0) {} , finished(0), writing(0), requested(0) {}
bool operator<(downloading_piece const& rhs) const {
return index < rhs.index; }
piece_state_t state; piece_state_t state;
// the index of the piece // the index of the piece
int index; int index;
// info about each block // info about each block
// this is a pointer into the m_block_info // this is a pointer into the m_block_info
// vector owned by the piece_picker // vector owned by the piece_picker
block_info* info; block_info* info;
// the number of blocks in the finished state // the number of blocks in the finished state
boost::int16_t finished; boost::int16_t finished;
skipping to change at line 239 skipping to change at line 250
// The user of this function must lookup if any piece is // The user of this function must lookup if any piece is
// marked as being downloaded. If the user of this function // marked as being downloaded. If the user of this function
// decides to download a piece, it must mark it as being dow nloaded // decides to download a piece, it must mark it as being dow nloaded
// itself, by using the mark_as_downloading() member functio n. // itself, by using the mark_as_downloading() member functio n.
// THIS IS DONE BY THE peer_connection::send_request() MEMBE R FUNCTION! // THIS IS DONE BY THE peer_connection::send_request() MEMBE R FUNCTION!
// The last argument is the policy::peer pointer for the pee r that // The last argument is the policy::peer pointer for the pee r that
// we'll download from. // we'll download from.
void pick_pieces(bitfield const& pieces void pick_pieces(bitfield const& pieces
, std::vector<piece_block>& interesting_blocks, int num_blocks , std::vector<piece_block>& interesting_blocks, int num_blocks
, int prefer_whole_pieces, void* peer, piece_state_t speed , int prefer_whole_pieces, void* peer, piece_state_t speed
, int options, std::vector<int> const& suggested_pie , int options, std::vector<int> const& suggested_pie
ces) const; ces
, int num_peers) const;
// picks blocks from each of the pieces in the piece_list // picks blocks from each of the pieces in the piece_list
// vector that is also in the piece bitmask. The blocks // vector that is also in the piece bitmask. The blocks
// are added to interesting_blocks, and busy blocks are // are added to interesting_blocks, and busy blocks are
// added to backup_blocks. num blocks is the number of // added to backup_blocks. num blocks is the number of
// blocks to be picked. Blocks are not picked from pieces // blocks to be picked. Blocks are not picked from pieces
// that are being downloaded // that are being downloaded
int add_blocks(int piece, bitfield const& pieces int add_blocks(int piece, bitfield const& pieces
, std::vector<piece_block>& interesting_blocks , std::vector<piece_block>& interesting_blocks
, std::vector<piece_block>& backup_blocks , std::vector<piece_block>& backup_blocks
skipping to change at line 292 skipping to change at line 304
// and false if the block is already finished or writing // and false if the block is already finished or writing
bool mark_as_writing(piece_block block, void* peer); bool mark_as_writing(piece_block block, void* peer);
void mark_as_finished(piece_block block, void* peer); void mark_as_finished(piece_block block, void* peer);
void write_failed(piece_block block); void write_failed(piece_block block);
int num_peers(piece_block block) const; int num_peers(piece_block block) const;
// returns information about the given piece // returns information about the given piece
void piece_info(int index, piece_picker::downloading_piece& st) const; void piece_info(int index, piece_picker::downloading_piece& st) const;
piece_pos const& piece_stats(int index) const
{
TORRENT_ASSERT(index >= 0 && index < int(m_piece_map
.size()));
return m_piece_map[index];
}
// if a piece had a hash-failure, it must be restored and // if a piece had a hash-failure, it must be restored and
// made available for redownloading // made available for redownloading
void restore_piece(int index); void restore_piece(int index);
// clears the given piece's download flag // clears the given piece's download flag
// this means that this piece-block can be picked again // this means that this piece-block can be picked again
void abort_download(piece_block block); void abort_download(piece_block block, void* peer = 0);
bool is_piece_finished(int index) const; bool is_piece_finished(int index) const;
// returns the number of blocks there is in the given piece // returns the number of blocks there is in the given piece
int blocks_in_piece(int index) const; int blocks_in_piece(int index) const;
// the number of downloaded blocks that hasn't passed // the number of downloaded blocks that hasn't passed
// the hash-check yet // the hash-check yet
int unverified_blocks() const; int unverified_blocks() const;
skipping to change at line 358 skipping to change at line 376
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;
public:
struct piece_pos struct piece_pos
{ {
piece_pos() {} piece_pos() {}
piece_pos(int peer_count_, int index_) piece_pos(int peer_count_, int index_)
: peer_count(peer_count_) : peer_count(peer_count_)
, downloading(0) , downloading(0)
, full(0)
, piece_priority(1) , piece_priority(1)
, index(index_) , index(index_)
{ {
TORRENT_ASSERT(peer_count_ >= 0); TORRENT_ASSERT(peer_count_ >= 0);
TORRENT_ASSERT(index_ >= 0); TORRENT_ASSERT(index_ >= 0);
} }
// the number of peers that has this piece // the number of peers that has this piece
// (availability) // (availability)
unsigned peer_count : 10; #if TORRENT_COMPACT_PICKER
boost::uint32_t peer_count : 9;
#else
boost::uint32_t peer_count : 16;
#endif
// is 1 if the piece is marked as being downloaded // is 1 if the piece is marked as being downloaded
unsigned downloading : 1; boost::uint32_t downloading : 1;
// set when downloading, but no free blocks to reque
st left
boost::uint32_t full : 1;
// is 0 if the piece is filtered (not to be download ed) // is 0 if the piece is filtered (not to be download ed)
// 1 is normal priority (default) // 1 is normal priority (default)
// 2 is higher priority than pieces at the same avai lability level // 2 is higher priority than pieces at the same avai lability level
// 3 is same priority as partial pieces // 3 is same priority as partial pieces
// 4 is higher priority than partial pieces // 4 is higher priority than partial pieces
// 5 and 6 same priority as availability 1 (ignores availability) // 5 and 6 same priority as availability 1 (ignores availability)
// 7 is maximum priority (ignores availability) // 7 is maximum priority (ignores availability)
unsigned piece_priority : 3; boost::uint32_t piece_priority : 3;
// index in to the piece_info vector // index in to the piece_info vector
unsigned index : 18; #if TORRENT_COMPACT_PICKER
boost::uint32_t index : 18;
#else
boost::uint32_t index;
#endif
enum enum
{ {
// index is set to this to indicate that we have the // index is set to this to indicate that we have the
// piece. There is no entry for the piece in the // piece. There is no entry for the piece in the
// buckets if this is the case. // buckets if this is the case.
#if TORRENT_COMPACT_PICKER
we_have_index = 0x3ffff, we_have_index = 0x3ffff,
#else
we_have_index = 0xffffffff,
#endif
// the priority value that means the piece i s filtered // the priority value that means the piece i s filtered
filter_priority = 0, filter_priority = 0,
// the max number the peer count can hold // the max number the peer count can hold
max_peer_count = 0x3ff #if TORRENT_COMPACT_PICKER
max_peer_count = 0x1ff
#else
max_peer_count = 0xffff
#endif
}; };
bool have() const { return index == we_have_index; } bool have() const { return index == we_have_index; }
void set_have() { index = we_have_index; TORRENT_ASS ERT(have()); } void set_have() { index = we_have_index; TORRENT_ASS ERT(have()); }
void set_not_have() { index = 0; TORRENT_ASSERT(!hav e()); } void set_not_have() { index = 0; TORRENT_ASSERT(!hav e()); }
bool filtered() const { return piece_priority == fil ter_priority; } bool filtered() const { return piece_priority == fil ter_priority; }
void filtered(bool f) { piece_priority = f ? filter_ priority : 0; } void filtered(bool f) { piece_priority = f ? filter_ priority : 0; }
// prio 7 is always top priority // prio 7 is always top priority
skipping to change at line 451 skipping to change at line 490
} }
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; }
}; };
private:
#if TORRENT_COMPACT_PICKER
BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4); BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 4);
#else
BOOST_STATIC_ASSERT(sizeof(piece_pos) == sizeof(char) * 8);
#endif
void update_pieces() const; void update_pieces() const;
// fills in the range [start, end) of pieces in // fills in the range [start, end) of pieces in
// m_pieces that have priority 'prio' // m_pieces that have priority 'prio'
void priority_range(int prio, int* start, int* end); void priority_range(int prio, int* start, int* end);
// adds the piece 'index' to m_pieces // adds the piece 'index' to m_pieces
void add(int index); void add(int index);
// removes the piece with the given priority and the // removes the piece with the given priority and the
// elem_index in the m_pieces vector // elem_index in the m_pieces vector
void remove(int priority, int elem_index); void remove(int priority, int elem_index);
// updates the position of the piece with the given // updates the position of the piece with the given
// priority and the elem_index in the m_pieces vector // priority and the elem_index in the m_pieces vector
void update(int priority, int elem_index); void update(int priority, int elem_index);
// shuffles the given piece inside it's priority range // shuffles the given piece inside it's priority range
void shuffle(int priority, int elem_index); void shuffle(int priority, int elem_index);
void sort_piece(std::vector<downloading_piece>::iterator dp) ; // void sort_piece(std::vector<downloading_piece>::iterator dp) ;
downloading_piece& add_download_piece(); downloading_piece& add_download_piece(int index);
void erase_download_piece(std::vector<downloading_piece>::it erator i); void erase_download_piece(std::vector<downloading_piece>::it erator i);
std::vector<downloading_piece>::const_iterator find_dl_piece
(int index) const;
std::vector<downloading_piece>::iterator find_dl_piece(int i
ndex);
void update_full(downloading_piece& dp);
// some compilers (e.g. gcc 2.95, does not inherit access
// privileges to nested classes)
public:
// the number of seeds. These are not added to // the number of seeds. These are not added to
// the availability counters of the pieces // the availability counters of the pieces
int m_seeds; int m_seeds;
private:
// the following vectors are mutable because they sometimes may // the following vectors are mutable because they sometimes may
// be updated lazily, triggered by const functions // be updated lazily, triggered by const functions
// this vector contains all piece indices that are pickable // this vector contains all piece indices that are pickable
// sorted by priority. Pieces are in random random order // sorted by priority. Pieces are in random random order
// among pieces with the same priority // among pieces with the same priority
mutable std::vector<int> m_pieces; mutable std::vector<int> m_pieces;
// these are indices to the priority boundries inside // these are indices to the priority boundries inside
skipping to change at line 503 skipping to change at line 557
// index into the m_piece_info vectors. // index into the m_piece_info vectors.
// piece_pos::we_have_index means that we have the piece, so it // piece_pos::we_have_index means that we have the piece, so it
// doesn't exist in the piece_info buckets // doesn't exist in the piece_info buckets
// pieces with the filtered flag set doesn't have entries in // pieces with the filtered flag set doesn't have entries in
// the m_piece_info buckets either // the m_piece_info buckets either
mutable std::vector<piece_pos> m_piece_map; mutable std::vector<piece_pos> m_piece_map;
// each piece that's currently being downloaded // each piece that's currently being downloaded
// has an entry in this list with block allocations. // has an entry in this list with block allocations.
// i.e. it says wich parts of the piece that // i.e. it says wich parts of the piece that
// is being downloaded // is being downloaded. This list is ordered
// by piece index to make lookups efficient
std::vector<downloading_piece> m_downloads; std::vector<downloading_piece> m_downloads;
// this holds the information of the // this holds the information of the
// blocks in partially downloaded pieces. // blocks in partially downloaded pieces.
// the first m_blocks_per_piece entries // the first m_blocks_per_piece entries
// in the vector belongs to the first // in the vector belongs to the first
// entry in m_downloads, the second // entry in m_downloads, the second
// m_blocks_per_piece entries to the // m_blocks_per_piece entries to the
// second entry in m_downloads and so on. // second entry in m_downloads and so on.
std::vector<block_info> m_block_info; std::vector<block_info> m_block_info;
skipping to change at line 547 skipping to change at line 602
int m_reverse_cursor; int m_reverse_cursor;
// the number of regions of pieces we don't have. // the number of regions of pieces we don't have.
int m_sparse_regions; 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:
#if TORRENT_COMPACT_PICKER
enum { max_pieces = piece_pos::we_have_index - 1 }; enum { max_pieces = piece_pos::we_have_index - 1 };
#else
// still limited by piece_block
enum { max_pieces = (1 << 19) - 2 };
#endif
}; };
} }
#endif // TORRENT_PIECE_PICKER_HPP_INCLUDED #endif // TORRENT_PIECE_PICKER_HPP_INCLUDED
 End of changes. 30 change blocks. 
18 lines changed or deleted 84 lines changed or added


 policy.hpp   policy.hpp 
skipping to change at line 42 skipping to change at line 42
#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 <deque> #include <deque>
#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/address.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"
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
class peer_connection; class peer_connection;
// this is compressed as an unsigned floating point value // this is compressed as an unsigned floating point value
// the top 13 bits are the mantissa and the low // the top 13 bits are the mantissa and the low
// 3 bits is the unsigned exponent. The exponent // 3 bits is the unsigned exponent. The exponent
// has an implicit + 4 as well. // has an implicit + 4 as well.
// This means that the resolution is no less than 16 // This means that the resolution is no less than 16
// The actual rate is: (upload_rate >> 4) << ((upload_rate & 0xf) + 4) // The actual rate is: (upload_rate >> 4) << ((upload_rate & 0xf) + 4)
// the resolution gets worse the higher the value is // the resolution gets worse the higher the value is
// min value is 0, max value is 16775168 // min value is 0, max value is 16775168
struct ufloat16 struct ufloat16
{ {
ufloat16() {} ufloat16():m_val(0) {}
ufloat16(int v) ufloat16(int v)
{ *this = v; } { *this = v; }
operator int() operator int()
{ {
return (m_val >> 3) << ((m_val & 7) + 4); return (m_val >> 3) << ((m_val & 7) + 4);
} }
ufloat16& operator=(int v) ufloat16& operator=(int v)
{ {
if (v > 0x1fff << (7 + 4)) m_val = 0xffff; if (v > 0x1fff << (7 + 4)) m_val = 0xffff;
skipping to change at line 90 skipping to change at line 90
{ {
v >>= 1; v >>= 1;
++exp; ++exp;
} }
TORRENT_ASSERT(exp <= 7); TORRENT_ASSERT(exp <= 7);
m_val = (v << 3) || (exp & 7); m_val = (v << 3) || (exp & 7);
} }
return *this; return *this;
} }
private: private:
unsigned int m_val; boost::uint16_t 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
}; };
void request_a_block(torrent& t, peer_connection& c); void request_a_block(torrent& t, peer_connection& c);
class TORRENT_EXPORT policy class TORRENT_EXTRA_EXPORT policy
{ {
public: public:
policy(torrent* t); policy(torrent* t);
// this is called every 10 seconds to allow
// for peer choking management
void pulse();
struct peer; struct peer;
#if TORRENT_USE_I2P
policy::peer* add_i2p_peer(char const* destination, int sour
ce, char flags);
#endif
// 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* add_peer(const tcp::endpoint& remote, const pe er_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
skipping to change at line 142 skipping to change at line 143
void set_connection(policy::peer* p, peer_connection* c); void set_connection(policy::peer* p, peer_connection* c);
void set_failcount(policy::peer* p, int f); 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);
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 #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool has_connection(const peer_connection* p); bool has_connection(const peer_connection* p);
#endif
#ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
// intended struct layout (on 32 bit architectures) // intended struct layout (on 32 bit architectures)
// offset size alignment field // offset size alignment field
// 0 12 1 prev_amount_upload, prev_amount_download // 0 8 4 prev_amount_upload, prev_amount_download
// 12 4 4 connection // 8 4 4 connection
// 16 2 2 last_optimistically_unchoked // 12 2 2 last_optimistically_unchoked
// 18 2 2 last_connected // 14 2 2 last_connected
// 20 16 1 addr // 16 16 1 addr
// 36 2 2 port // 32 2 2 port
// 38 2 2 upload_rate_limit // 34 2 2 upload_rate_limit
// 40 2 2 download_rate_limit // 36 2 2 download_rate_limit
// 42 1 1 hashfails // 38 1 1 hashfails
// 43 1 1 failcount, connectable, optimistically_unchoked, // 39 1 1 failcount, connectable, optimistically_unchoked,
seed seed
// 44 1 1 fast_reconnects, trust_points // 40 1 1 fast_reconnects, trust_points
// 45 1 1 source, pe_support, is_v6_addr // 41 1 1 source, pe_support, is_v6_addr
// 46 1 1 on_parole, banned, added_to_dht // 42 1 1 on_parole, banned, added_to_dht, supports_utp,
// 47 1 1 <padding> // supports_holepunch, web_seed
// 48 // 43 1 1 <padding>
struct TORRENT_EXPORT peer // 44
struct TORRENT_EXTRA_EXPORT peer
{ {
peer();
peer(boost::uint16_t port, bool connectable, int src ); peer(boost::uint16_t port, bool connectable, int src );
size_type total_download() const; size_type total_download() const;
size_type total_upload() const; size_type total_upload() const;
libtorrent::address address() const; libtorrent::address address() const;
char const* dest() const;
tcp::endpoint ip() const { return tcp::endpoint(addr ess(), port); } tcp::endpoint ip() const { return tcp::endpoint(addr 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.
// 48 bits can fit 256 Terabytes // since these values don't need to be stored
#ifdef __SUNPRO_CC // with byte-precision, they specify the number
unsigned prev_amount_upload:48; // of kiB. i.e. shift left 10 bits to compare to
unsigned prev_amount_download:48; // byte counters.
#else boost::uint32_t prev_amount_upload;
boost::uint64_t prev_amount_upload:48; boost::uint32_t prev_amount_download;
boost::uint64_t prev_amount_download:48;
#endif
// 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;
skipping to change at line 286 skipping to change at line 287
// 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
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
// this is true if the v6 union member in addr is // this is true if the v6 union member in addr is
// the one to use, false if it's the v4 one // the one to use, false if it's the v4 one
bool is_v6_addr:1; bool is_v6_addr:1;
#endif #endif
#if TORRENT_USE_I2P
// set if the i2p_destination is in use in the addr
union
bool is_i2p_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
#ifdef TORRENT_DEBUG // we think this peer supports uTP
bool supports_utp:1;
// we have been connected via uTP at least once
bool confirmed_supports_utp:1;
bool supports_holepunch:1;
// this is set to one for web seeds. Web seeds
// are not stored in the policy m_peers list,
// and are excempt from connect candidate bookkeepin
g
// so, any peer with the web_seed bit set, is
// never considered a connect candidate
bool web_seed:1;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool in_use:1; bool in_use:1;
#endif #endif
}; };
struct TORRENT_EXPORT ipv4_peer : peer struct TORRENT_EXTRA_EXPORT ipv4_peer : peer
{ {
ipv4_peer(tcp::endpoint const& ip, bool connectable, int src); ipv4_peer(tcp::endpoint const& ip, bool connectable, int src);
ipv4_peer(libtorrent::address const& a);
address_v4 addr; const address_v4 addr;
}; };
#if TORRENT_USE_I2P
struct TORRENT_EXTRA_EXPORT i2p_peer : peer
{
i2p_peer(char const* destination, bool connectable,
int src);
~i2p_peer();
char* destination;
};
#endif
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
struct TORRENT_EXPORT ipv6_peer : peer struct TORRENT_EXTRA_EXPORT ipv6_peer : peer
{ {
ipv6_peer(tcp::endpoint const& ip, bool connectable, int src); ipv6_peer(tcp::endpoint const& ip, bool connectable, int src);
ipv6_peer(libtorrent::address const& a);
address_v6::bytes_type addr; const address_v6::bytes_type addr;
}; };
#endif #endif
int num_peers() const { return m_peers.size(); } int num_peers() const { return m_peers.size(); }
struct peer_address_compare struct peer_address_compare
{ {
bool operator()( bool operator()(
peer const* lhs, libtorrent::address const& rhs) const peer const* lhs, libtorrent::address const& rhs) const
{ {
return lhs->address() < rhs; return lhs->address() < rhs;
} }
bool operator()( bool operator()(
libtorrent::address const& lhs, peer const* rhs) const libtorrent::address const& lhs, peer const* rhs) const
{ {
return lhs < rhs->address(); return lhs < rhs->address();
} }
#if TORRENT_USE_I2P
bool operator()(
peer const* lhs, char const* rhs) const
{
return strcmp(lhs->dest(), rhs) < 0;
}
bool operator()(
char const* lhs, peer const* rhs) const
{
return strcmp(lhs, rhs->dest()) < 0;
}
#endif
bool operator()( bool operator()(
peer const* lhs, peer const* rhs) const peer const* lhs, peer const* rhs) const
{ {
#if TORRENT_USE_I2P
if (rhs->is_i2p_addr == lhs->is_i2p_addr)
return strcmp(lhs->dest(), rhs->dest
()) < 0;
#endif
return lhs->address() < rhs->address(); return lhs->address() < rhs->address();
} }
}; };
typedef std::deque<peer*> peers_t; typedef std::deque<peer*> peers_t;
typedef peers_t::iterator iterator; typedef peers_t::iterator iterator;
typedef peers_t::const_iterator const_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(); }
skipping to change at line 384 skipping to change at line 426
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(policy::peer* p);
void erase_peer(iterator i); void erase_peer(iterator i);
private: private:
void update_peer(policy::peer* p, int src, int flags
, tcp::endpoint const& remote, char const* destination);
bool insert_peer(policy::peer* p, iterator iter, int flags);
bool compare_peer_erase(policy::peer const& lhs, policy::pee r const& rhs) const; 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(int session_time); 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 is_erase_candidate(peer const& p, bool finished) const;
bool is_force_erase_candidate(peer const& pe) const;
bool should_erase_immediately(peer const& p) const; bool should_erase_immediately(peer const& p) const;
void erase_peers(); enum flags_t { force_erase = 1 };
void erase_peers(int flags = 0);
peers_t m_peers; peers_t m_peers;
torrent* m_torrent;
// 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
int m_round_robin; int m_round_robin;
torrent* m_torrent;
// 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;
// this was the state of the torrent the // this was the state of the torrent the
// 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:1;
}; };
inline policy::ipv4_peer::ipv4_peer( inline policy::ipv4_peer::ipv4_peer(
tcp::endpoint const& ep, bool c, int src tcp::endpoint const& ep, bool c, int src
) )
: peer(ep.port(), c, src) : peer(ep.port(), c, src)
, addr(ep.address().to_v4()) , addr(ep.address().to_v4())
{ {
#if TORRENT_USE_IPV6
is_v6_addr = false; is_v6_addr = false;
#endif
#if TORRENT_USE_I2P
is_i2p_addr = false;
#endif
} }
inline policy::ipv4_peer::ipv4_peer(libtorrent::address const& a) #if TORRENT_USE_I2P
: addr(a.to_v4()) inline policy::i2p_peer::i2p_peer(char const* dest, bool connectable
, int src)
: peer(0, connectable, src), destination(strdup(dest))
{ {
#if TORRENT_USE_IPV6
is_v6_addr = false; is_v6_addr = false;
#endif
is_i2p_addr = true;
} }
inline policy::i2p_peer::~i2p_peer()
{ free(destination); }
#endif // TORRENT_USE_I2P
#if TORRENT_USE_IPV6
inline policy::ipv6_peer::ipv6_peer( inline policy::ipv6_peer::ipv6_peer(
tcp::endpoint const& ep, bool c, int src tcp::endpoint const& ep, bool c, int src
) )
: peer(ep.port(), c, src) : peer(ep.port(), c, src)
, addr(ep.address().to_v6().to_bytes()) , addr(ep.address().to_v6().to_bytes())
{ {
is_v6_addr = true; is_v6_addr = true;
#if TORRENT_USE_I2P
is_i2p_addr = false;
#endif
} }
inline policy::ipv6_peer::ipv6_peer(libtorrent::address const& a) #endif // TORRENT_USE_IPV6
: addr(a.to_v6().to_bytes())
#if TORRENT_USE_I2P
inline char const* policy::peer::dest() const
{ {
is_v6_addr = true; if (is_i2p_addr)
return static_cast<policy::i2p_peer const*>(this)->d
estination;
return "";
} }
#endif
inline libtorrent::address policy::peer::address() const inline libtorrent::address policy::peer::address() const
{ {
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
if (is_v6_addr) if (is_v6_addr)
return libtorrent::address_v6( return libtorrent::address_v6(
static_cast<policy::ipv6_peer const*>(this)- >addr); static_cast<policy::ipv6_peer const*>(this)- >addr);
else
#endif
#if TORRENT_USE_I2P
if (is_i2p_addr) return libtorrent::address();
else
#endif #endif
return static_cast<policy::ipv4_peer const*>(this)->addr; return static_cast<policy::ipv4_peer const*>(this)->addr;
} }
} }
#endif // TORRENT_POLICY_HPP_INCLUDED #endif // TORRENT_POLICY_HPP_INCLUDED
 End of changes. 43 change blocks. 
56 lines changed or deleted 138 lines changed or added


 proxy_base.hpp   proxy_base.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_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/io_service_fwd.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include <boost/bind.hpp> #include "libtorrent/address.hpp"
#include <boost/function.hpp> #include "libtorrent/escape_string.hpp"
#if BOOST_VERSION < 103500 #include "libtorrent/error_code.hpp"
#include <asio/read.hpp>
#include <asio/write.hpp>
#else
#include <boost/asio/read.hpp>
#include <boost/asio/write.hpp>
#endif
namespace libtorrent { namespace libtorrent {
class proxy_base : boost::noncopyable class proxy_base : boost::noncopyable
{ {
public: public:
typedef stream_socket next_layer_type;
typedef stream_socket::lowest_layer_type lowest_layer_type; typedef stream_socket::lowest_layer_type lowest_layer_type;
typedef stream_socket::endpoint_type endpoint_type; typedef stream_socket::endpoint_type endpoint_type;
typedef stream_socket::protocol_type protocol_type; typedef stream_socket::protocol_type protocol_type;
explicit proxy_base(io_service& io_service) explicit proxy_base(io_service& io_service)
: m_sock(io_service) : m_sock(io_service)
, m_port(0) , m_port(0)
, m_resolver(io_service) , m_resolver(io_service)
{} {}
skipping to change at line 82 skipping to change at line 78
{ {
m_sock.async_read_some(buffers, handler); m_sock.async_read_some(buffers, handler);
} }
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 )
{ {
return m_sock.read_some(buffers, ec); return m_sock.read_some(buffers, ec);
} }
template <class Const_Buffers>
std::size_t write_some(Const_Buffers const& buffers, error_code& ec)
{
return m_sock.write_some(buffers, ec);
}
std::size_t available(error_code& ec) const
{ return m_sock.available(ec); }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
std::size_t available() const
{ return m_sock.available(); }
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)
{ {
return m_sock.read_some(buffers); return m_sock.read_some(buffers);
} }
template <class Const_Buffers>
std::size_t write_some(Const_Buffers const& buffers)
{
return m_sock.write_some(buffers);
}
template <class IO_Control_Command> template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc) void io_control(IO_Control_Command& ioc)
{ {
m_sock.io_control(ioc); m_sock.io_control(ioc);
} }
#endif #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)
{ {
skipping to change at line 125 skipping to change at line 139
template <class SettableSocketOption> template <class SettableSocketOption>
error_code set_option(SettableSocketOption const& opt, error_code& e c) error_code set_option(SettableSocketOption const& opt, error_code& e c)
{ {
return m_sock.set_option(opt, ec); return m_sock.set_option(opt, ec);
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
void bind(endpoint_type const& endpoint) void bind(endpoint_type const& endpoint)
{ {
m_sock.bind(endpoint); // m_sock.bind(endpoint);
} }
#endif #endif
void bind(endpoint_type const& endpoint, error_code& ec) void bind(endpoint_type const& endpoint, error_code& ec)
{ {
m_sock.bind(endpoint, ec); // the reason why we ignore binds here is because we don't
// (necessarily) yet know what address family the proxy
// will resolve to, and binding to the wrong one would
// break our connection attempt later. The caller here
// doesn't necessarily know that we're proxying, so this
// bind address is based on the final endpoint, not the
// proxy.
// TODO: it would be nice to remember the bind port and bind
once we know where the proxy is
// m_sock.bind(endpoint, ec);
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
void open(protocol_type const& p) void open(protocol_type const& p)
{ {
m_sock.open(p); // m_sock.open(p);
} }
#endif #endif
void open(protocol_type const& p, error_code& ec) void open(protocol_type const& p, error_code& ec)
{ {
m_sock.open(p, ec); // we need to ignore this for the same reason as stated
// for ignoring bind()
// m_sock.open(p, ec);
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
void close() void close()
{ {
m_remote_endpoint = endpoint_type(); m_remote_endpoint = endpoint_type();
m_sock.close(); m_sock.close();
m_resolver.cancel(); m_resolver.cancel();
} }
#endif #endif
void close(error_code& ec) void close(error_code& ec)
{ {
m_remote_endpoint = endpoint_type();
m_sock.close(ec); m_sock.close(ec);
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
skipping to change at line 196 skipping to change at line 221
io_service& get_io_service() io_service& get_io_service()
{ {
return m_sock.get_io_service(); return m_sock.get_io_service();
} }
lowest_layer_type& lowest_layer() lowest_layer_type& lowest_layer()
{ {
return m_sock.lowest_layer(); return m_sock.lowest_layer();
} }
next_layer_type& next_layer()
{
return m_sock;
}
bool is_open() const { return m_sock.is_open(); } bool is_open() const { return m_sock.is_open(); }
protected: protected:
stream_socket m_sock; stream_socket m_sock;
std::string m_hostname; std::string m_hostname;
int m_port; int m_port;
endpoint_type m_remote_endpoint; endpoint_type m_remote_endpoint;
 End of changes. 12 change blocks. 
13 lines changed or deleted 44 lines changed or added


 refresh.hpp   refresh.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 REFRESH_050324_HPP #ifndef REFRESH_050324_HPP
#define REFRESH_050324_HPP #define REFRESH_050324_HPP
#include <vector>
#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/observer.hpp> #include <libtorrent/kademlia/find_data.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <boost/function.hpp>
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(refresh);
#endif
class routing_table; class routing_table;
class rpc_manager; class rpc_manager;
class refresh : public traversal_algorithm class refresh : public find_data
{ {
public: public:
typedef std::vector<node_entry>::iterator InIt; typedef find_data::nodes_callback done_callback;
typedef boost::function<void()> done_callback;
void ping_reply(node_id id);
void ping_timeout(node_id id, bool prevent_request = false);
refresh(node_impl& node, node_id target, InIt first, InIt last refresh(node_impl& node, node_id target
, done_callback const& callback); , done_callback const& callback);
virtual char const* name() const { return "refresh"; } virtual char const* name() const;
private:
void done();
void invoke(node_id const& id, udp::endpoint addr);
void invoke_pings_or_finish(bool prevent_request = false);
int m_max_active_pings;
int m_active_pings;
done_callback m_done_callback; protected:
std::vector<result>::iterator m_leftover_nodes_iterator; observer_ptr new_observer(void* ptr, udp::endpoint const& ep, node_i
d const& id);
virtual bool invoke(observer_ptr o);
}; };
class refresh_observer : public observer class bootstrap : public refresh
{ {
public: public:
refresh_observer( bootstrap(node_impl& node, node_id target
boost::intrusive_ptr<refresh> const& algorithm , done_callback const& callback);
, node_id self)
: observer(algorithm->allocator())
, m_algorithm(algorithm)
, m_self(self)
{}
~refresh_observer();
void send(msg& m)
{
m.info_hash = m_algorithm->target();
}
void timeout();
void reply(msg const& m);
void abort() { m_algorithm = 0; }
private: virtual char const* name() const;
boost::intrusive_ptr<refresh> m_algorithm;
node_id const m_self;
};
class ping_observer : public observer protected:
{
public:
ping_observer(
boost::intrusive_ptr<refresh> const& algorithm
, node_id self)
: observer(algorithm->allocator())
, m_self(self)
, m_algorithm(algorithm)
{}
~ping_observer();
void send(msg& p) {} virtual void done();
void timeout();
void reply(msg const& m);
void abort() { m_algorithm = 0; }
private:
node_id const m_self;
boost::intrusive_ptr<refresh> m_algorithm;
}; };
inline refresh::refresh(
node_impl& node
, node_id target
, refresh::InIt first
, refresh::InIt last
, done_callback const& callback)
: traversal_algorithm(node, target, first, last)
, m_max_active_pings(10)
, m_active_pings(0)
, m_done_callback(callback)
{
boost::intrusive_ptr<refresh> self(this);
add_requests();
}
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // REFRESH_050324_HPP #endif // REFRESH_050324_HPP
 End of changes. 16 change blocks. 
85 lines changed or deleted 15 lines changed or added


 routing_table.hpp   routing_table.hpp 
skipping to change at line 39 skipping to change at line 39
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 <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/iterator/iterator_facade.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 <list>
#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>
#include <libtorrent/ptime.hpp>
namespace libtorrent namespace libtorrent
{ {
struct session_status; 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;
struct routing_table_node
{
bucket_t replacements;
bucket_t live_nodes;
ptime last_active;
};
// differences in the implementation from the description in // differences in the implementation from the description in
// the paper: // the paper:
// //
// * The routing table tree is not allocated dynamically, there
// are always 160 buckets.
// * Nodes are not marked as being stale, they keep a counter // * Nodes are not marked as being stale, they keep a counter
// that tells how many times in a row they have failed. When // that tells how many times in a row they have failed. When
// a new node is to be inserted, the node that has failed // a new node is to be inserted, the node that has failed
// the most times is replaced. If none of the nodes in the // the most times is replaced. If none of the nodes in the
// bucket has failed, then it is put in the replacement // bucket has failed, then it is put in the replacement
// cache (just like in the paper). // cache (just like in the paper).
class routing_table; class TORRENT_EXTRA_EXPORT routing_table
namespace aux
{
// Iterates over a flattened routing_table structure.
class routing_table_iterator
: public boost::iterator_facade<
routing_table_iterator
, node_entry const
, boost::forward_traversal_tag
>
{
public:
routing_table_iterator()
{
}
private:
friend class libtorrent::dht::routing_table;
friend class boost::iterator_core_access;
typedef boost::array<std::pair<bucket_t, bucket_t>, 160>::co
nst_iterator
bucket_iterator_t;
routing_table_iterator(
bucket_iterator_t begin
, bucket_iterator_t end)
: m_bucket_iterator(begin)
, m_bucket_end(end)
{
if (m_bucket_iterator == m_bucket_end) return;
m_iterator = begin->first.begin();
while (m_iterator == m_bucket_iterator->first.end())
{
if (++m_bucket_iterator == m_bucket_end)
break;
m_iterator = m_bucket_iterator->first.begin(
);
}
}
bool equal(routing_table_iterator const& other) const
{
return m_bucket_iterator == other.m_bucket_iterator
&& (m_bucket_iterator == m_bucket_end
|| *m_iterator == other.m_iterator);
}
void increment()
{
TORRENT_ASSERT(m_bucket_iterator != m_bucket_end);
++*m_iterator;
while (*m_iterator == m_bucket_iterator->first.end()
)
{
if (++m_bucket_iterator == m_bucket_end)
break;
m_iterator = m_bucket_iterator->first.begin(
);
}
}
node_entry const& dereference() const
{
TORRENT_ASSERT(m_bucket_iterator != m_bucket_end);
return **m_iterator;
}
bucket_iterator_t m_bucket_iterator;
bucket_iterator_t m_bucket_end;
// when debug iterators are enabled, default constructed
// iterators are not allowed to be copied. In the case
// where the routing table is empty, m_iterator would be
// default constructed and not copyable.
boost::optional<bucket_t::const_iterator> m_iterator;
};
} // namespace aux
class TORRENT_EXPORT routing_table
{ {
public: public:
typedef aux::routing_table_iterator 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 status(session_status& s) const;
void node_failed(node_id const& id); void node_failed(node_id const& id, udp::endpoint const& ep);
// 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(); }
bool add_node(node_entry const& e);
// this function is called every time the node sees // this function is called every time the node sees
// a sign of a node being alive. This node will either // a sign of a node being alive. This node will either
// 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 ep);
// returns time when the given bucket needs another refresh. // this may add a node to the routing table and mark it as
// if the given bucket is empty but there are nodes // not pinged. If the bucket the node falls into is full,
// in a bucket closer to us, or if the bucket is non-empty and // the node will be ignored.
// the time from the last activity is more than 15 minutes void heard_about(node_id const& id, udp::endpoint const& ep);
ptime next_refresh(int bucket);
// if any bucket in the routing table needs to be refreshed
// this function will return true and set the target to an
// appropriate target inside that bucket
bool need_refresh(node_id& target) const;
enum enum
{ {
include_self = 1, include_failed = 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
, int options, int count = 0); , int options, int count = 0);
// this may add a node to the routing table and mark it as
// not pinged. If the bucket the node falls into is full,
// the node will be ignored.
void heard_about(node_id const& id, udp::endpoint const& ep);
// this will set the given bucket's latest activity
// to the current time
void touch_bucket(int bucket);
int bucket_size(int bucket) int bucket_size(int bucket)
{ {
TORRENT_ASSERT(bucket >= 0 && bucket < 160); int num_buckets = m_buckets.size();
return (int)m_buckets[bucket].first.size(); if (num_buckets == 0) return 0;
if (bucket < num_buckets) bucket = num_buckets - 1;
table_t::iterator i = m_buckets.begin();
std::advance(i, bucket);
return (int)i->live_nodes.size();
} }
int bucket_size() const { return m_bucket_size; }
iterator begin() const; void for_each_node(void (*)(void*, node_entry const&)
iterator end() const; , void (*)(void*, node_entry const&), void* userdata) const;
int bucket_size() const { return m_bucket_size; }
boost::tuple<int, int> size() const; boost::tuple<int, int> size() const;
size_type num_global_nodes() const; size_type num_global_nodes() const;
// returns true if there are no working nodes // returns true if there are no working nodes
// in the routing table // in the routing table
bool need_bootstrap() const; bool need_bootstrap() const;
int num_active_buckets() const int num_active_buckets() const { return m_buckets.size(); }
{ return 160 - m_lowest_active_bucket + 1; }
void replacement_cache(bucket_t& nodes) const; void replacement_cache(bucket_t& nodes) const;
#ifdef TORRENT_DHT_VERBOSE_LOGGING
#if defined TORRENT_DHT_VERBOSE_LOGGING || defined TORRENT_DEBUG
// used for debug and monitoring purposes. This will print out // used for debug and monitoring purposes. This will print out
// the state of the routing table to the given stream // the state of the routing table to the given stream
void print_state(std::ostream& os) const; void print_state(std::ostream& os) const;
#endif #endif
void touch_bucket(node_id const& target);
private: private:
typedef std::list<routing_table_node> table_t;
table_t::iterator find_bucket(node_id const& id);
// return a pointer the node_entry with the given endpoint
// or 0 if we don't have such a node. Both the address and the
// port has to match
node_entry* find_node(udp::endpoint const& ep, routing_table::table_
t::iterator* bucket);
// constant called k in paper // constant called k in paper
int m_bucket_size; int m_bucket_size;
dht_settings const& m_settings; dht_settings const& m_settings;
// 160 (k-bucket, replacement cache) pairs // (k-bucket, replacement cache) pairs
typedef boost::array<std::pair<bucket_t, bucket_t>, 160> table_t; // the first entry is the bucket the furthest
// away from our own ID. Each time the bucket
// closest to us (m_buckets.back()) has more than
// bucket size nodes in it, another bucket is
// added to the end and it's split up between them
table_t m_buckets; table_t m_buckets;
// timestamps of the last activity in each bucket
typedef boost::array<ptime, 160> table_activity_t;
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 // the last time need_bootstrap() returned true
mutable ptime m_last_bootstrap; mutable ptime m_last_bootstrap;
// the last time the routing table was refreshed.
// this is used to stagger buckets needing refresh
// to be at least 45 seconds apart.
mutable ptime m_last_refresh;
// the last time we refreshed our own bucket
// refreshed every 15 minutes
mutable ptime m_last_self_refresh;
// 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 // these are all the IPs that are in the routing
int m_lowest_active_bucket; // table. It's used to only allow a single entry
// per IP in the whole table. Currently only for
// IPv4
std::set<address_v4::bytes_type> m_ips;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // ROUTING_TABLE_HPP #endif // ROUTING_TABLE_HPP
 End of changes. 24 change blocks. 
122 lines changed or deleted 70 lines changed or added


 rpc_manager.hpp   rpc_manager.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 RPC_MANAGER_HPP #ifndef RPC_MANAGER_HPP
#define RPC_MANAGER_HPP #define RPC_MANAGER_HPP
#include <vector> #include <vector>
#include <map> #include <map>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/array.hpp>
#include <boost/pool/pool.hpp> #include <boost/pool/pool.hpp>
#include <boost/function/function3.hpp>
#include <libtorrent/socket.hpp> #include <libtorrent/socket.hpp>
#include <libtorrent/entry.hpp> #include <libtorrent/entry.hpp>
#include <libtorrent/kademlia/node_id.hpp> #include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/logging.hpp> #include <libtorrent/kademlia/logging.hpp>
#include <libtorrent/kademlia/node_entry.hpp>
#include <libtorrent/kademlia/observer.hpp> #include <libtorrent/kademlia/observer.hpp>
#include "libtorrent/time.hpp" #include "libtorrent/ptime.hpp"
namespace libtorrent { namespace aux { struct session_impl; } }
namespace libtorrent { namespace dht namespace libtorrent { namespace dht
{ {
struct observer;
#ifdef TORRENT_DHT_VERBOSE_LOGGING #ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(rpc); TORRENT_DECLARE_LOG(rpc);
#endif #endif
struct null_observer : public observer struct null_observer : public observer
{ {
null_observer(boost::pool<>& allocator): observer(allocator) {} null_observer(boost::intrusive_ptr<traversal_algorithm> const& a
virtual void reply(msg const&) {} , udp::endpoint const& ep, node_id const& id): observer(a, e
virtual void timeout() {} p, id) {}
virtual void send(msg&) {} virtual void reply(msg const&) { flags |= flag_done; }
void abort() {}
}; };
class routing_table; class routing_table;
class rpc_manager class TORRENT_EXTRA_EXPORT rpc_manager
{ {
public: public:
typedef boost::function1<void, msg const&> fun; typedef bool (*send_fun)(void* userdata, entry&, udp::endpoint const
typedef boost::function1<void, msg const&> send_fun; &, int);
typedef boost::function3<void, address, int, address> external_ip_fu
n;
rpc_manager(fun const& incoming_fun, node_id const& our_id rpc_manager(node_id const& our_id
, routing_table& table, send_fun const& sf); , routing_table& table, send_fun const& sf
, void* userdata, external_ip_fun ext_ip);
~rpc_manager(); ~rpc_manager();
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&); // if so, id is assigned the node id to refresh
bool incoming(msg const&, node_id* id);
time_duration tick(); time_duration tick();
void invoke(int message_id, udp::endpoint target bool invoke(entry& e, udp::endpoint target
, observer_ptr o); , observer_ptr o);
void reply(msg& m); void add_our_id(entry& e);
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
size_t allocation_size() const; size_t allocation_size() const;
#endif
#ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
boost::pool<>& allocator() const void* allocate_observer();
{ return m_pool_allocator; } void free_observer(void* ptr);
private:
enum { max_transactions = 2048 }; int num_allocated_observers() const { return m_allocated_observers; }
unsigned int new_transaction_id(observer_ptr o); private:
void update_oldest_transaction_id();
boost::uint32_t calc_connection_id(udp::endpoint addr); boost::uint32_t calc_connection_id(udp::endpoint addr);
mutable boost::pool<> m_pool_allocator; mutable boost::pool<> m_pool_allocator;
typedef boost::array<observer_ptr, max_transactions> typedef std::list<observer_ptr> transactions_t;
transactions_t;
transactions_t m_transactions; transactions_t m_transactions;
std::vector<observer_ptr> m_aborted_transactions;
// this is the next transaction id to be used
int m_next_transaction_id;
// this is the oldest transaction id still
// (possibly) in use. This is the transaction
// that will time out first, the one we are
// waiting for to time out
int m_oldest_transaction_id;
fun m_incoming;
send_fun m_send; send_fun m_send;
void* m_userdata;
node_id m_our_id; node_id m_our_id;
routing_table& m_table; routing_table& m_table;
ptime m_timer; ptime m_timer;
node_id m_random_number; node_id m_random_number;
int m_allocated_observers;
bool m_destructing; bool m_destructing;
external_ip_fun m_ext_ip;
}; };
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif #endif
 End of changes. 24 change blocks. 
41 lines changed or deleted 31 lines changed or added


 session.hpp   session.hpp 
skipping to change at line 44 skipping to change at line 44
#define TORRENT_SESSION_HPP_INCLUDED #define TORRENT_SESSION_HPP_INCLUDED
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#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/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/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/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/alert.hpp" // alert::error_notification
#include "libtorrent/add_torrent_params.hpp"
#include "libtorrent/rss.hpp"
#include "libtorrent/build_config.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
#ifdef TORRENT_USE_OPENSSL
// this is a nasty openssl macro
#ifdef set_key
#undef set_key
#endif
#endif
namespace libtorrent namespace libtorrent
{ {
struct plugin;
struct torrent_plugin; struct torrent_plugin;
class torrent; class torrent;
struct ip_filter; struct ip_filter;
class port_filter; class port_filter;
class connection_queue; class connection_queue;
class natpmp; class natpmp;
class upnp; class upnp;
class alert; class alert;
// this is used to create linker errors when trying to link to TORRENT_EXPORT session_settings min_memory_usage();
// a library with a conflicting build configuration than the applica TORRENT_EXPORT session_settings high_performance_seed();
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 #ifndef TORRENT_CFG
#define P _nopoolalloc #error TORRENT_CFG is not defined!
#else
#define P _poolalloc
#endif #endif
#define TORRENT_LINK_TEST_PREFIX libtorrent_build_config void TORRENT_EXPORT TORRENT_CFG();
#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;
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 TORRENT_EXPORT eh_initializer
{ {
eh_initializer() eh_initializer();
{
::_set_se_translator(straight_to_debugger);
}
static void straight_to_debugger(unsigned int, _EXCE PTION_POINTERS*) static void straight_to_debugger(unsigned int, _EXCE PTION_POINTERS*)
{ throw; } { throw; }
}; };
#else #else
struct eh_initializer {}; struct eh_initializer {};
#endif #endif
struct session_impl; struct session_impl;
struct filesystem_init
{
filesystem_init();
};
} }
class TORRENT_EXPORT session_proxy class TORRENT_EXPORT session_proxy
{ {
friend class session; friend class session;
public: public:
session_proxy() {} session_proxy() {}
private: private:
session_proxy(boost::shared_ptr<aux::session_impl> impl) session_proxy(boost::shared_ptr<aux::session_impl> impl)
: m_impl(impl) {} : m_impl(impl) {}
boost::shared_ptr<aux::session_impl> m_impl; boost::shared_ptr<aux::session_impl> m_impl;
}; };
struct add_torrent_params #if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T
{ ORRENT_ERROR_LOGGING
add_torrent_params(storage_constructor_type sc = default_sto #define TORRENT_LOGPATH_ARG_DEFAULT , std::string logpath = "."
rage_constructor) #define TORRENT_LOGPATH_ARG , std::string logpath
: tracker_url(0) #define TORRENT_LOGPATH , logpath
, name(0) #else
, resume_data(0) #define TORRENT_LOGPATH_ARG_DEFAULT
, storage_mode(storage_mode_sparse) #define TORRENT_LOGPATH_ARG
, paused(true) #define TORRENT_LOGPATH
, auto_managed(true) #endif
, duplicate_is_error(false)
, storage(sc)
, userdata(0)
, seed_mode(false)
, override_resume_data(false)
, upload_mode(false)
{}
boost::intrusive_ptr<torrent_info> ti;
char const* tracker_url;
sha1_hash info_hash;
char const* name;
fs::path save_path;
std::vector<char>* resume_data;
storage_mode_t storage_mode;
bool paused;
bool auto_managed;
bool duplicate_is_error;
storage_constructor_type storage;
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 , boost::uint32_t alert_mask = alert::error_notifica
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T tion
ORRENT_ERROR_LOGGING TORRENT_LOGPATH_ARG_DEFAULT)
, fs::path logpath = "." {
#endif TORRENT_CFG();
); init(std::make_pair(0, 0), "0.0.0.0", print, flags,
alert_mask TORRENT_LOGPATH);
}
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 , int alert_mask = alert::error_notification
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T TORRENT_LOGPATH_ARG_DEFAULT)
ORRENT_ERROR_LOGGING {
, fs::path logpath = "." TORRENT_CFG();
#endif TORRENT_ASSERT(listen_port_range.first > 0);
); TORRENT_ASSERT(listen_port_range.first < listen_port
_range.second);
init(listen_port_range, listen_interface, print, fla
gs, alert_mask TORRENT_LOGPATH);
}
~session(); ~session();
enum save_state_flags_t enum save_state_flags_t
{ {
save_settings = 0x001, save_settings = 0x001,
save_dht_settings = 0x002, save_dht_settings = 0x002,
#ifndef TORRENT_NO_DEPRECATE save_dht_state = 0x004,
save_dht_proxy = 0x004, save_proxy = 0x008,
#endif save_i2p_proxy = 0x010,
save_dht_state = 0x008,
save_i2p_proxy = 0x010,
save_encryption_settings = 0x020, save_encryption_settings = 0x020,
save_as_map = 0x040,
save_feeds = 0x080
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
save_peer_proxy = 0x040, ,
save_web_proxy = 0x080, save_dht_proxy = save_proxy,
save_tracker_proxy = 0x100, save_peer_proxy = save_proxy,
save_web_proxy = save_proxy,
save_tracker_proxy = save_proxy
#endif #endif
save_as_map = 0x200,
save_proxy = 0x1c4
}; };
void save_state(entry& e, boost::uint32_t flags = 0xffffffff ) const; void save_state(entry& e, boost::uint32_t flags = 0xffffffff ) const;
void load_state(lazy_entry const& e); void load_state(lazy_entry const& e);
void get_torrent_status(std::vector<torrent_status>* ret
, boost::function<bool(torrent_status const&)> const
& pred
, boost::uint32_t flags = 0) const;
void refresh_torrent_status(std::vector<torrent_status>* ret
, boost::uint32_t flags = 0) const;
void post_torrent_updates();
// 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(); 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!
#ifndef BOOST_NO_EXCEPTIONS
torrent_handle add_torrent(add_torrent_params const& params) ; torrent_handle add_torrent(add_torrent_params const& params) ;
#endif
torrent_handle add_torrent(add_torrent_params const& params, error_code& ec); torrent_handle add_torrent(add_torrent_params const& params, error_code& ec);
void async_add_torrent(add_torrent_params const& params);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.14 // deprecated in 0.14
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
torrent_handle add_torrent( torrent_handle add_torrent(
torrent_info const& ti torrent_info const& ti
, fs::path const& save_path , std::string 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_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 , std::string 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_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 , std::string 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 #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;
feed_handle add_feed(feed_settings const& feed);
void remove_feed(feed_handle h);
void get_feeds(std::vector<feed_handle>& f) const;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void start_dht(); 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);
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.15 // deprecated in 0.15
// use save_state and load_state instead // use save_state and load_state instead
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
entry dht_state() const TORRENT_DEPRECATED; entry dht_state() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void start_dht(entry const& startup_state) TORRENT_DEPRECATE D; void start_dht(entry const& startup_state) TORRENT_DEPRECATE D;
#endif #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; 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 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);
void add_extension(boost::shared_ptr<plugin> 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); void load_asnum_db(char const* file);
bool load_country_db(char const* file); void load_country_db(char const* file);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY #if TORRENT_USE_WSTRING
bool load_country_db(wchar_t const* file); void load_country_db(wchar_t const* file);
bool load_asnum_db(wchar_t const* file); void load_asnum_db(wchar_t const* file);
#endif #endif
#endif #endif
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.15 // deprecated in 0.15
// use load_state and save_state instead // use load_state and save_state instead
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void load_state(entry const& ses_state) TORRENT_DEPRECATED; void load_state(entry const& ses_state) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
entry state() const TORRENT_DEPRECATED; entry state() const TORRENT_DEPRECATED;
#endif #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 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;
// if the listen port failed in some way // if the listen port failed in some way
// you can retry to listen on another port- // you can retry to listen on another port-
// range with this function. If the listener // range with this function. If the listener
// succeeded and is currently listening, // succeeded and is currently listening,
// a call to this function will shut down the // a call to this function will shut down the
// listen port and reopen it using these new // listen port and reopen it using these new
// properties (the given interface and port range). // properties (the given interface and port range).
// As usual, if the interface is left as 0 // As usual, if the interface is left as 0
// this function will return false on failure. // this function will return false on failure.
// If it fails, it will also generate alerts describing // If it fails, it will also generate alerts describing
// the error. It will return true on success. // the error. It will return true on success.
enum listen_on_flags_t
{
listen_reuse_address = 0x01,
listen_no_system_port = 0x02
};
#ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.16
TORRENT_DEPRECATED_PREFIX
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
, int flags = 0) TORRENT_DEPRECATED;
#endif
void listen_on(
std::pair<int, int> const& port_range
, error_code& ec
, const char* net_interface = 0
, int flags = 0);
// returns the port we ended up listening on // returns the port we ended up listening on
unsigned short listen_port() const; unsigned short listen_port() const;
// Get the number of uploads.
int num_uploads() const;
// Get the number of connections. This number also contains
the
// number of half open connections.
int num_connections() const;
enum options_t enum options_t
{ {
none = 0, none = 0,
delete_files = 1 delete_files = 1
}; };
enum session_flags_t enum session_flags_t
{ {
add_default_plugins = 1, add_default_plugins = 1,
start_default_features = 2 start_default_features = 2
}; };
void remove_torrent(const torrent_handle& h, int options = n one); void remove_torrent(const torrent_handle& h, int options = n one);
void set_settings(session_settings const& s); void set_settings(session_settings const& s);
session_settings const& settings(); session_settings settings() const;
void set_proxy(proxy_settings const& s); void set_proxy(proxy_settings const& s);
proxy_settings const& proxy() const; proxy_settings proxy() const;
#ifdef TORRENT_STATS
void enable_stats_logging(bool s);
#endif
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
// deprecated in 0.16
// Get the number of uploads.
TORRENT_DEPRECATED_PREFIX
int num_uploads() const TORRENT_DEPRECATED;
// Get the number of connections. This number also contains
the
// number of half open connections.
TORRENT_DEPRECATED_PREFIX
int num_connections() const TORRENT_DEPRECATED;
// deprecated in 0.15. // deprecated in 0.15.
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void set_peer_proxy(proxy_settings const& s) TORRENT_DEPRECA TED; void set_peer_proxy(proxy_settings const& s) TORRENT_DEPRECA TED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void set_web_seed_proxy(proxy_settings const& s) TORRENT_DEP RECATED; void set_web_seed_proxy(proxy_settings const& s) TORRENT_DEP RECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void set_tracker_proxy(proxy_settings const& s) TORRENT_DEPR ECATED; void set_tracker_proxy(proxy_settings const& s) TORRENT_DEPR ECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
proxy_settings const& peer_proxy() const TORRENT_DEPRECATED; proxy_settings peer_proxy() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
proxy_settings const& web_seed_proxy() const TORRENT_DEPRECA TED; proxy_settings web_seed_proxy() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
proxy_settings const& tracker_proxy() const TORRENT_DEPRECAT ED; proxy_settings tracker_proxy() const TORRENT_DEPRECATED;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void set_dht_proxy(proxy_settings const& s) TORRENT_DEPRECAT ED; void set_dht_proxy(proxy_settings const& s) TORRENT_DEPRECAT ED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
proxy_settings const& dht_proxy() const TORRENT_DEPRECATED; proxy_settings dht_proxy() const TORRENT_DEPRECATED;
#endif #endif
#endif // TORRENT_NO_DEPRECATE #endif // TORRENT_NO_DEPRECATE
int upload_rate_limit() const; #if TORRENT_USE_I2P
int download_rate_limit() const; void set_i2p_proxy(proxy_settings const& s);
int local_upload_rate_limit() const; proxy_settings i2p_proxy() const;
int local_download_rate_limit() const; #endif
int max_half_open_connections() const;
void set_local_upload_rate_limit(int bytes_per_second); #ifndef TORRENT_NO_DEPRECATE
void set_local_download_rate_limit(int bytes_per_second); // deprecated in 0.16
void set_upload_rate_limit(int bytes_per_second); TORRENT_DEPRECATED_PREFIX
void set_download_rate_limit(int bytes_per_second); int upload_rate_limit() const TORRENT_DEPRECATED;
void set_max_uploads(int limit); TORRENT_DEPRECATED_PREFIX
void set_max_connections(int limit); int download_rate_limit() const TORRENT_DEPRECATED;
void set_max_half_open_connections(int limit); TORRENT_DEPRECATED_PREFIX
int local_upload_rate_limit() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
int local_download_rate_limit() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
int max_half_open_connections() const TORRENT_DEPRECATED;
int max_connections() const; TORRENT_DEPRECATED_PREFIX
int max_uploads() const; void set_local_upload_rate_limit(int bytes_per_second) TORRE
NT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_local_download_rate_limit(int bytes_per_second) TOR
RENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_upload_rate_limit(int bytes_per_second) TORRENT_DEP
RECATED;
TORRENT_DEPRECATED_PREFIX
void set_download_rate_limit(int bytes_per_second) TORRENT_D
EPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_max_uploads(int limit) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_max_connections(int limit) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_max_half_open_connections(int limit) TORRENT_DEPREC
ATED;
TORRENT_DEPRECATED_PREFIX
int max_connections() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
int max_uploads() const TORRENT_DEPRECATED;
#endif
// pop one alert from the alert queue, or do nothing
// and return a NULL pointer if there are no alerts
// in the queue
std::auto_ptr<alert> pop_alert(); std::auto_ptr<alert> pop_alert();
// pop all alerts in the alert queue and returns them
// in the supplied dequeue 'alerts'. The passed in
// queue must be empty when passed in.
// the responsibility of individual alerts returned
// in the dequeue is passed on to the caller of this functio
n.
// when you're done with reacting to the alerts, you need to
// delete them all.
void pop_alerts(std::deque<alert*>* alerts);
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
TORRENT_DEPRECATED_PREFIX 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;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void set_alert_mask(int m) TORRENT_DEPRECATED; size_t set_alert_queue_size_limit(size_t queue_size_limit_) TORRENT_DEPRECATED;
#endif #endif
void set_alert_mask(boost::uint32_t m); void set_alert_mask(boost::uint32_t m);
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); void set_alert_dispatch(boost::function<void(std::auto_ptr<a lert>)> 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();
void stop_natpmp(); void stop_natpmp();
void stop_upnp(); void stop_upnp();
private: private:
// just a way to initialize boost.filesystem void init(std::pair<int, int> listen_range, char const* list
// before the session_impl is created en_interface
aux::filesystem_init m_dummy; , fingerprint const& id, int flags, boost::uint32_t
alert_mask TORRENT_LOGPATH_ARG);
// data shared between the main thread // data shared between the main thread
// and the working thread // and the working thread
boost::shared_ptr<aux::session_impl> m_impl; boost::shared_ptr<aux::session_impl> m_impl;
}; };
} }
#endif // TORRENT_SESSION_HPP_INCLUDED #endif // TORRENT_SESSION_HPP_INCLUDED
 End of changes. 51 change blocks. 
159 lines changed or deleted 186 lines changed or added


 session_impl.hpp   session_impl.hpp 
skipping to change at line 53 skipping to change at line 53
#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/filesystem/path.hpp>
#include <boost/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/pool/object_pool.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/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/add_torrent_params.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/udp_socket.hpp" #include "libtorrent/udp_socket.hpp"
#include "libtorrent/assert.hpp" #include "libtorrent/assert.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/policy.hpp" // for policy::peer #include "libtorrent/policy.hpp" // for policy::peer
#include "libtorrent/alert.hpp" // for alert_manager #include "libtorrent/alert.hpp" // for alert_manager
#include "libtorrent/deadline_timer.hpp"
#include "libtorrent/socket_io.hpp" // for print_address
#include "libtorrent/address.hpp"
#include "libtorrent/utp_socket_manager.hpp"
#include "libtorrent/bloom_filter.hpp"
#include "libtorrent/rss.hpp"
#if TORRENT_COMPLETE_TYPES_REQUIRED #if TORRENT_COMPLETE_TYPES_REQUIRED
#include "libtorrent/peer_connection.hpp" #include "libtorrent/peer_connection.hpp"
#endif #endif
#ifdef TORRENT_USE_OPENSSL
#include <boost/asio/ssl/context.hpp>
#endif
#if defined TORRENT_STATS && defined __MACH__
#include <mach/vm_statistics.h>
#include <mach/mach_init.h>
#include <mach/host_info.h>
#include <mach/mach_host.h>
#endif
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem; struct plugin;
class peer_connection;
class upnp; class upnp;
class natpmp; class natpmp;
class lsd; class lsd;
struct fingerprint; struct fingerprint;
class torrent; class torrent;
class alert; class alert;
namespace dht namespace dht
{ {
struct dht_tracker; struct dht_tracker;
} }
struct bencode_map_entry;
struct listen_socket_t
{
listen_socket_t(): external_port(0), ssl(false) {}
// this is typically empty but can be set
// to the WAN IP address of NAT-PMP or UPnP router
address external_address;
// this is typically set to the same as the local
// listen port. In case a NAT port forward was
// successfully opened, this will be set to the
// port that is open on the external (NAT) interface
// on the NAT box itself. This is the port that has
// to be published to peers, since this is the port
// the client is reachable through.
int external_port;
// set to true if this is an SSL listen socket
bool ssl;
// the actual socket
boost::shared_ptr<socket_acceptor> sock;
};
namespace aux namespace aux
{ {
struct session_impl; struct session_impl;
#if defined TORRENT_STATS && !defined __MACH__
struct vm_statistics_data_t
{
boost::uint64_t active_count;
boost::uint64_t inactive_count;
boost::uint64_t wire_count;
boost::uint64_t free_count;
boost::uint64_t pageins;
boost::uint64_t pageouts;
boost::uint64_t faults;
};
#endif
struct thread_cpu_usage
{
ptime user_time;
ptime system_time;
};
#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 // used to initialize the g_current_time before
// anything else // anything else
struct initialize_timer struct initialize_timer
{ {
initialize_timer(); initialize_timer();
}; };
TORRENT_EXPORT std::pair<bencode_map_entry*, int> settings_m
ap();
// 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, initialize_timer struct TORRENT_EXTRA_EXPORT session_impl: boost::noncopyable
, initialize_timer
, boost::enable_shared_from_this<session_impl>
{ {
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T
ORRENT_ERROR_LOGGING
// this needs to be destructed last, since other com
ponents may log
// things as they are being destructed. That's why i
t's declared at
// the top of session_impl
boost::shared_ptr<logger> m_logger;
#endif
// 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 = 128 }; 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(
std::pair<int, int> listen_port_range std::pair<int, int> listen_port_range
, fingerprint const& cl_fprint , fingerprint const& cl_fprint
, char const* listen_interface , char const* listen_interface
, boost::uint32_t alert_mask
#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 const& logpath , std::string const& logpath
#endif #endif
); );
~session_impl(); ~session_impl();
void init();
void start_session();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::function<boost::shared_ptr <torrent_plugin>( void add_extension(boost::function<boost::shared_ptr <torrent_plugin>(
torrent*, void*)> ext); torrent*, void*)> ext);
void add_ses_extension(boost::shared_ptr<plugin> ext );
#endif #endif
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
bool has_peer(peer_connection const* p) const bool has_peer(peer_connection const* p) const
{ {
TORRENT_ASSERT(is_network_thread());
return std::find_if(m_connections.begin(), m _connections.end() return std::find_if(m_connections.begin(), m _connections.end()
, boost::bind(&boost::intrusive_ptr< peer_connection>::get, _1) == p) , boost::bind(&boost::intrusive_ptr< peer_connection>::get, _1) == p)
!= m_connections.end(); != m_connections.end();
} }
#endif #endif
void operator()(); void main_thread();
void open_listen_port(); void open_listen_port(int flags, error_code& ec);
// 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, bool ssl);
void on_accept_connection(boost::shared_ptr<socket_t ype> 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, bool ssl);
void on_socks_accept(boost::shared_ptr<socket_type> const& s void on_socks_accept(boost::shared_ptr<socket_type> const& s
, error_code const& e); , error_code const& e);
void incoming_connection(boost::shared_ptr<socket_ty pe> const& s); void incoming_connection(boost::shared_ptr<socket_ty pe> const& s);
// must be locked to access the data #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
// in this struct bool is_network_thread() const
typedef boost::mutex mutex_t; {
mutable mutex_t m_mutex; #if defined BOOST_HAS_PTHREADS
if (m_network_thread == 0) return true;
return m_network_thread == pthread_self();
#endif
return true;
}
#endif
feed_handle add_feed(feed_settings const& feed);
void remove_feed(feed_handle h);
void get_feeds(std::vector<feed_handle>* f) const;
boost::weak_ptr<torrent> find_torrent(sha1_hash cons
t& info_hash);
boost::weak_ptr<torrent> find_torrent(std::string co
nst& uuid);
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, erro r_code const& ec); void close_connection(peer_connection const* p, erro 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_name(std::pair<std::string, int> c onst& 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(); void start_dht();
void stop_dht(); void stop_dht();
void start_dht(entry const& startup_state); void start_dht(entry const& startup_state);
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
entry dht_state(session_impl::mutex_t::scoped_lock& l) const; entry dht_state() const;
#endif #endif
void maybe_update_udp_mapping(int nat, int local_por t, int external_port); void on_dht_announce(error_code const& e);
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
void maybe_update_udp_mapping(int nat, int local_por
t, int external_port);
#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_port_map_log(char const* msg, int map_transp ort);
void on_lsd_announce(error_code const& e); 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, error_co void on_port_mapping(int mapping, address const& ip,
de const& ec int port
, int nat_transport); , error_code const& ec, 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( void listen_on(
std::pair<int, int> const& port_range std::pair<int, int> const& port_range
, const char* net_interface = 0); , error_code& ec
, const char* net_interface = 0
, int flags = 0);
bool is_listening() const; bool is_listening() const;
torrent_handle add_torrent(add_torrent_params const& , error_code& ec); torrent_handle add_torrent(add_torrent_params const& , error_code& ec);
void async_add_torrent(add_torrent_params* params);
void remove_torrent(torrent_handle const& h, int opt ions); void remove_torrent(torrent_handle const& h, int opt ions);
void remove_torrent_impl(boost::shared_ptr<torrent> tptr, int options);
std::vector<torrent_handle> get_torrents(); void get_torrent_status(std::vector<torrent_status>*
ret
, boost::function<bool(torrent_status const&
)> const& pred
, boost::uint32_t flags) const;
void refresh_torrent_status(std::vector<torrent_stat
us>* ret
, boost::uint32_t flags) const;
void post_torrent_updates();
std::vector<torrent_handle> get_torrents() const;
void queue_check_torrent(boost::shared_ptr<torrent> const& t); void queue_check_torrent(boost::shared_ptr<torrent> const& t);
void dequeue_check_torrent(boost::shared_ptr<torrent > const& t); void dequeue_check_torrent(boost::shared_ptr<torrent > const& t);
void set_alert_mask(boost::uint32_t m); void set_alert_mask(boost::uint32_t 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 void pop_alerts(std::deque<alert*>* alerts);
onst&)> const&); void set_alert_dispatch(boost::function<void(std::au
to_ptr<alert>)> const&);
void post_alert(const alert& alert_);
alert const* wait_for_alert(time_duration max_wait); alert const* wait_for_alert(time_duration max_wait);
#ifndef TORRENT_NO_DEPRECATE
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_upload_rate_limit() const;
int local_download_rate_limit() const; int local_download_rate_limit() const;
void set_local_download_rate_limit(int bytes_per_sec ond); void set_local_download_rate_limit(int bytes_per_sec ond);
void set_local_upload_rate_limit(int bytes_per_secon d); 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 int max_connections() const;
ns; } int max_uploads() const;
int max_uploads() const { return m_max_uploads; } int max_half_open_connections() const;
int max_half_open_connections() const { return m_hal
f_open.limit(); } #endif
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); 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; address listen_address() const;
boost::uint16_t listen_port() const;
boost::uint16_t ssl_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, int port, boo l broadcast = false);
void save_state(entry& e, boost::uint32_t flags, ses void save_state(entry* e, boost::uint32_t flags) con
sion_impl::mutex_t::scoped_lock& l) const; st;
void load_state(lazy_entry const& e); void load_state(lazy_entry const* e);
void set_proxy(proxy_settings const& s); void set_proxy(proxy_settings const& s);
proxy_settings const& proxy() const { return m_peer_ proxy; } proxy_settings const& proxy() const { return m_proxy ; }
void set_peer_proxy(proxy_settings const& s) #ifndef TORRENT_NO_DEPRECATE
{ void set_peer_proxy(proxy_settings const& s) { set_p
m_peer_proxy = s; roxy(s); }
// in case we just set a socks proxy, we mig void set_web_seed_proxy(proxy_settings const& s) { s
ht have to et_proxy(s); }
// open the socks incoming connection void set_tracker_proxy(proxy_settings const& s) { se
if (!m_socks_listen_socket) open_new_incomin t_proxy(s); }
g_socks_connection(); proxy_settings const& peer_proxy() const { return pr
} oxy(); }
void set_web_seed_proxy(proxy_settings const& s) proxy_settings const& web_seed_proxy() const { retur
{ m_web_seed_proxy = s; } n proxy(); }
void set_tracker_proxy(proxy_settings const& s) proxy_settings const& tracker_proxy() const { return
{ m_tracker_proxy = s; } proxy(); }
proxy_settings const& peer_proxy() const
{ return m_peer_proxy; }
proxy_settings const& web_seed_proxy() const
{ return m_web_seed_proxy; }
proxy_settings const& tracker_proxy() const
{ return m_tracker_proxy; }
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void set_dht_proxy(proxy_settings const& s) void set_dht_proxy(proxy_settings const& s) { set_pr
oxy(s); }
proxy_settings const& dht_proxy() const { return pro
xy(); }
#endif
#endif // TORRENT_NO_DEPRECATE
#ifndef TORRENT_DISABLE_DHT
bool is_dht_running() const { return m_dht; }
#endif
#if TORRENT_USE_I2P
void set_i2p_proxy(proxy_settings const& s)
{ {
m_dht_proxy = s; m_i2p_conn.open(s, boost::bind(&session_impl
m_dht_socket->set_proxy_settings(s); ::on_i2p_open, this, _1));
open_new_incoming_i2p_connection();
} }
proxy_settings const& dht_proxy() const void on_i2p_open(error_code const& ec);
{ return m_dht_proxy; } proxy_settings const& i2p_proxy() const
{ return m_i2p_conn.proxy(); }
void open_new_incoming_i2p_connection();
void on_i2p_accept(boost::shared_ptr<socket_type> co
nst& s
, error_code const& e);
#endif #endif
#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); void load_asnum_db(std::string 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); void load_country_db(std::string 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 #if TORRENT_USE_WSTRING
bool load_asnum_db(wchar_t const* file); void load_asnum_dbw(std::wstring file);
bool load_country_db(wchar_t const* file); void load_country_dbw(std::wstring file);
#endif #endif // TORRENT_USE_WSTRING
#endif #endif // TORRENT_DISABLE_GEO_IP
void start_lsd(); void start_lsd();
void start_natpmp(natpmp* n); natpmp* start_natpmp();
void start_upnp(upnp* u); upnp* start_upnp();
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, int reason)
{ {
TORRENT_ASSERT(b > 0); TORRENT_ASSERT(b > 0);
m_total_redundant_bytes += b; m_total_redundant_bytes += b;
m_redundant_bytes[reason] += 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;
} }
std::pair<char*, int> allocate_buffer(int size); char* allocate_buffer();
void free_buffer(char* buf, int size); void free_buffer(char* buf);
char* allocate_disk_buffer(char const* category); 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); enum
{
source_dht = 1,
source_peer = 2,
source_tracker = 4,
source_router = 8
};
void set_external_address(address const& ip
, int source_type, address const& source);
address const& external_address() const { return m_e xternal_address; } address const& external_address() const { return m_e xternal_address; }
bool can_write_to_disk() const
{ return m_disk_thread.can_write(); }
// used when posting synchronous function
// calls to session_impl and torrent objects
mutable libtorrent::mutex mut;
mutable libtorrent::condition cond;
void inc_disk_queue(int channel)
{
TORRENT_ASSERT(channel >= 0 && channel < 2);
++m_disk_queues[channel];
}
void dec_disk_queue(int channel)
{
TORRENT_ASSERT(channel >= 0 && channel < 2);
TORRENT_ASSERT(m_disk_queues[channel] > 0);
--m_disk_queues[channel];
}
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool in_state_updates(boost::shared_ptr<torrent> t)
{
return std::find_if(m_state_updates.begin(),
m_state_updates.end()
, boost::bind(&boost::weak_ptr<torre
nt>::lock, _1) == t) != m_state_updates.end();
}
#endif
void add_to_update_queue(boost::weak_ptr<torrent> t)
{
TORRENT_ASSERT(std::find_if(m_state_updates.
begin(), m_state_updates.end()
, boost::bind(&boost::weak_ptr<torre
nt>::lock, _1) == t.lock()) == m_state_updates.end());
m_state_updates.push_back(t);
}
// private: // private:
void update_connections_limit();
void update_unchoke_limit();
void update_rate_settings();
void update_disk_thread_settings(); void update_disk_thread_settings();
void on_dht_state_callback(boost::condition& c
, 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); void setup_socket_buffers(socket_type& s);
// the settings for the client
session_settings m_settings;
// this is a shared pool where policy_peer objects // this is a shared pool where policy_peer objects
// are allocated. It's a pool since we're likely // are allocated. It's a pool since we're likely
// to have tens of thousands of peers, and a pool // to have tens of thousands of peers, and a pool
// saves significant overhead // saves significant overhead
#ifdef TORRENT_STATS #ifdef TORRENT_STATS
struct logging_allocator struct logging_allocator
{ {
typedef std::size_t size_type; typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type; typedef std::ptrdiff_t difference_type;
skipping to change at line 408 skipping to change at line 567
{ {
--allocations; --allocations;
return ::free(block); return ::free(block);
} }
static int allocations; static int allocations;
static int allocated_bytes; static int allocated_bytes;
}; };
boost::object_pool< boost::object_pool<
policy::ipv4_peer, logging_allocator> m_ipv4 _peer_pool; policy::ipv4_peer, logging_allocator> m_ipv4 _peer_pool;
# if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
boost::object_pool< boost::object_pool<
policy::ipv6_peer, logging_allocator> m_ipv6 _peer_pool; policy::ipv6_peer, logging_allocator> m_ipv6 _peer_pool;
# endif #endif
#if TORRENT_USE_I2P
boost::object_pool<
policy::i2p_peer, logging_allocator> m_i2p_p
eer_pool;
#endif
#else #else
boost::object_pool<policy::ipv4_peer> m_ipv4_peer_po ol; boost::object_pool<policy::ipv4_peer> m_ipv4_peer_po ol;
# if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
boost::object_pool<policy::ipv6_peer> m_ipv6_peer_po ol; boost::object_pool<policy::ipv6_peer> m_ipv6_peer_po ol;
# endif #endif
#if TORRENT_USE_I2P
boost::object_pool<policy::i2p_peer> m_i2p_peer_pool
;
#endif
#endif #endif
// this vector is used to store the block_info // this vector is used to store the block_info
// objects pointed to by partial_piece_info returned // objects pointed to by partial_piece_info returned
// by torrent::get_download_queue. // by torrent::get_download_queue.
std::vector<block_info> m_block_info_storage; 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;
// 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
// open files by this session. // open files by this session.
// file pool must be destructed after the torrents // file pool must be destructed after the torrents
// since they will still have references to it // since they will still have references to it
// 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; #ifdef TORRENT_USE_OPENSSL
// this is a generic SSL context used when talking t
o
// unauthenticated HTTPS servers
asio::ssl::context m_ssl_ctx;
#endif
// handles delayed alerts // handles delayed alerts
alert_manager m_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
skipping to change at line 469 skipping to change at line 638
// 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> m_download_rate; bandwidth_manager m_download_rate;
bandwidth_manager<peer_connection> m_upload_rate; bandwidth_manager m_upload_rate;
// the global rate limiter bandwidth channels // the global rate limiter bandwidth channels
bandwidth_channel m_download_channel; bandwidth_channel m_download_channel;
bandwidth_channel m_upload_channel; bandwidth_channel m_upload_channel;
// bandwidth channels for local peers when // bandwidth channels for local peers when
// rate limits are ignored. They are only // rate limits are ignored. They are only
// throttled by these global rate limiters // throttled by these global rate limiters
// and they don't have a rate limit set by // and they don't have a rate limit set by
// default // default
bandwidth_channel m_local_download_channel; bandwidth_channel m_local_download_channel;
bandwidth_channel m_local_upload_channel; bandwidth_channel m_local_upload_channel;
// all tcp peer connections are subject to these
// bandwidth limits. Local peers are excempted
// from this limit. The purpose is to be able to
// throttle TCP that passes over the internet
// bottleneck (i.e. modem) to avoid starving out
// uTP connections.
bandwidth_channel m_tcp_download_channel;
bandwidth_channel m_tcp_upload_channel;
bandwidth_channel* m_bandwidth_channel[2]; bandwidth_channel* m_bandwidth_channel[2];
// the number of peer connections that are waiting
// for the disk. one for each channel.
// upload_channel means waiting to read from disk
// and download_channel is waiting to write to disk
int m_disk_queues[2];
tracker_manager m_tracker_manager; tracker_manager m_tracker_manager;
torrent_map m_torrents; torrent_map m_torrents;
std::map<std::string, boost::shared_ptr<torrent> > m
_uuids;
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 // 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;
skipping to change at line 530 skipping to change at line 716
// that we should let the os decide which // that we should let the os decide which
// interface to listen on // interface to listen on
tcp::endpoint m_listen_interface; tcp::endpoint m_listen_interface;
// if we're listening on an IPv6 interface // if we're listening on an IPv6 interface
// this is one of the non local IPv6 interfaces // this is one of the non local IPv6 interfaces
// on this machine // on this machine
tcp::endpoint m_ipv6_interface; tcp::endpoint m_ipv6_interface;
tcp::endpoint m_ipv4_interface; tcp::endpoint m_ipv4_interface;
struct listen_socket_t
{
listen_socket_t(): external_port(0) {}
// this is typically set to the same as the
local
// listen port. In case a NAT port forward w
as
// successfully opened, this will be set to
the
// port that is open on the external (NAT) i
nterface
// on the NAT box itself. This is the port t
hat has
// to be published to peers, since this is t
he port
// the client is reachable through.
int external_port;
// the actual socket
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;
#ifdef TORRENT_USE_OPENSSL
void ssl_handshake(error_code const& ec, boost::shar
ed_ptr<socket_type> s);
#endif
// when as a socks proxy is used for peers, also // when as a socks proxy is used for peers, also
// listen for incoming connections on a socks connec tion // listen for incoming connections on a socks connec tion
boost::shared_ptr<socket_type> m_socks_listen_socket ; boost::shared_ptr<socket_type> m_socks_listen_socket ;
boost::uint16_t m_socks_listen_port;
void open_new_incoming_socks_connection(); void open_new_incoming_socks_connection();
listen_socket_t setup_listener(tcp::endpoint ep, int #if TORRENT_USE_I2P
retries, bool v6_only = false); i2p_connection m_i2p_conn;
boost::shared_ptr<socket_type> m_i2p_listen_socket;
// the settings for the client
session_settings m_settings;
// the proxy settings for different
// kinds of connections
proxy_settings m_peer_proxy;
proxy_settings m_web_seed_proxy;
proxy_settings m_tracker_proxy;
#ifndef TORRENT_DISABLE_DHT
proxy_settings m_dht_proxy;
#endif #endif
void setup_listener(listen_socket_t* s, tcp::endpoin
t ep, int retries
, bool v6_only, int flags, error_code& ec);
// the proxy used for bittorrent
proxy_settings m_proxy;
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
entry m_dht_state; entry m_dht_state;
#endif #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; 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
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;
// the max number of connections, as set by the user
int m_max_connections;
// the number of unchoked peers // the number of unchoked peers
int m_num_unchoked; int m_num_unchoked;
// this is initialized to the unchoke_interval // this is initialized to the unchoke_interval
// session_setting and decreased every second. // session_setting and decreased every second.
// when it reaches zero, it is reset to the // when it reaches zero, it is reset to the
// unchoke_interval and the unchoke set is // unchoke_interval and the unchoke set is
// recomputed. // recomputed.
int m_unchoke_time_scaler; int m_unchoke_time_scaler;
skipping to change at line 620 skipping to change at line 788
// it reaches 0, and all the connections are // it reaches 0, and all the connections are
// used, the worst connection will be disconnected // used, the worst connection will be disconnected
// from the torrent with the most peers // from the torrent with the most peers
int m_disconnect_time_scaler; int m_disconnect_time_scaler;
// when this scaler reaches zero, it will // when this scaler reaches zero, it will
// scrape one of the auto managed, paused, // scrape one of the auto managed, paused,
// torrents. // torrents.
int m_auto_scrape_time_scaler; int m_auto_scrape_time_scaler;
// the index of the torrent that we'll
// refresh the next time
int m_next_explicit_cache_torrent;
// this is a counter of the number of seconds until
// the next time the read cache is rotated, if we're
// using an explicit read read cache.
int m_cache_rotation_timer;
// statistics gathered from all torrents. // statistics gathered from all torrents.
stat m_stat; stat m_stat;
int m_peak_up_rate;
int m_peak_down_rate;
// 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 on_disk_queue(); void on_disk_queue();
void on_tick(error_code const& e); void on_tick(error_code const& e);
int auto_manage_torrents(std::vector<torrent*>& list void auto_manage_torrents(std::vector<torrent*>& lis
, int hard_limit, int type_limit); t
, int& dht_limit, int& tracker_limit, int& l
sd_limit
, 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(); void recalculate_optimistic_unchoke_slots();
ptime m_created; ptime m_created;
int session_time() const { return total_seconds(time _now() - 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; ptime m_last_second_tick;
// used to limit how often disk warnings are generat
ed
ptime m_last_disk_performance_warning;
ptime m_last_disk_queue_performance_warning;
// the last time we went through the peers // the last time we went through the peers
// to decide which ones to choke/unchoke // to decide which ones to choke/unchoke
ptime m_last_choke; ptime m_last_choke;
// the time when the next rss feed needs updating
ptime m_next_rss_update;
// update any rss feeds that need updating and
// recalculate m_next_rss_update
void update_rss_feeds();
// 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
// will be set to the same as the tcp listen port
// and will be synchronlized with it as it changes
// it defaults to true
bool m_dht_same_port;
// see m_external_listen_port. This is the same
// but for the udp port used by the DHT.
int m_external_udp_port;
boost::intrusive_ptr<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;
// this announce timer is used
// by the DHT.
deadline_timer m_dht_announce_timer;
#endif
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
void on_receive_udp_hostname(error_code const& e
, char const* hostname, char const* buf, int
len);
// see m_external_listen_port. This is the same
// but for the udp port used by the DHT.
int m_external_udp_port;
rate_limited_udp_socket m_udp_socket;
utp_socket_manager m_utp_socket_manager;
// the number of torrent connection boosts
// connections that have been made this second
// this is deducted from the connect speed
int m_boost_connections;
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
pe_settings m_pe_settings; pe_settings m_pe_settings;
#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;
// mask is a bitmask of which protocols to remap on:
// 1: NAT-PMP
// 2: UPnP
void remap_tcp_ports(boost::uint32_t mask, int tcp_p
ort, int ssl_port);
// 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];
#ifdef TORRENT_USE_OPENSSL
int m_ssl_mapping[2];
#endif
// the timer used to fire the 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 // torrents are announced on the local network in a
// round-robin fashion. All torrents are cycled thro ugh // round-robin fashion. All torrents are cycled thro ugh
// within the LSD announce interval (which defaults to // within the LSD announce interval (which defaults to
// 5 minutes) // 5 minutes)
torrent_map::iterator m_next_lsd_torrent; torrent_map::iterator m_next_lsd_torrent;
#ifndef TORRENT_DISABLE_DHT
// torrents are announced on the DHT in a
// round-robin fashion. All torrents are cycled thro
ugh
// within the DHT announce interval (which defaults
to
// 15 minutes)
torrent_map::iterator m_next_dht_torrent;
#endif
// this announce timer is used // this announce timer is used
// by Local service discovery // by Local service discovery
deadline_timer m_lsd_announce_timer; deadline_timer m_lsd_announce_timer;
tcp::resolver m_host_resolver;
// 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 on_tick is called. // connect to a peer next time on_tick is called.
// This implements a round robin. // This implements a round robin.
torrent_map::iterator m_next_connect_torrent; torrent_map::iterator m_next_connect_torrent;
// this is the round-robin cursor for peers that
// get to download again after the disk has been
// blocked
connection_map::iterator m_next_disk_peer;
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
#if defined TORRENT_STATS && defined TORRENT_DISK_STATS #ifdef TORRENT_DISK_STATS
void log_buffer_usage(); void log_buffer_usage();
#endif
#if defined TORRENT_STATS
// logger used to write bandwidth usage statistics
std::ofstream m_stats_logger;
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
#ifdef TORRENT_REQUEST_LOGGING
// used to log all requests from peers
FILE* m_request_log;
#endif
#ifdef TORRENT_STATS
void rotate_stats_log();
void print_log_line(int tick_interval_ms, ptime now)
;
void reset_stat_counters();
void enable_stats_logging(bool s);
bool m_stats_logging_enabled;
// the last time we rotated the log file
ptime m_last_log_rotation;
// logger used to write bandwidth usage statistics
FILE* m_stats_logger;
// sequence number for log file. Log files are
// rotated every hour and the sequence number is
// incremented by one
int m_log_seq;
// the number of peers that were disconnected this
// tick due to protocol error
int m_error_peers;
int m_disconnected_peers;
int m_eof_peers;
int m_connreset_peers;
int m_connrefused_peers;
int m_connaborted_peers;
int m_perm_peers;
int m_buffer_peers;
int m_unreachable_peers;
int m_broken_pipe_peers;
int m_addrinuse_peers;
int m_no_access_peers;
int m_invalid_arg_peers;
int m_aborted_peers;
int m_piece_requests;
int m_max_piece_requests;
int m_invalid_piece_requests;
int m_choked_piece_requests;
int m_cancelled_piece_requests;
int m_piece_rejects;
int m_error_incoming_peers;
int m_error_outgoing_peers;
int m_error_rc4_peers;
int m_error_encrypted_peers;
int m_error_tcp_peers;
int m_error_utp_peers;
// the number of times the piece picker fell through
// to the end-game mode
int m_end_game_piece_picker_blocks;
int m_piece_picker_blocks;
int m_piece_picks;
int m_reject_piece_picks;
int m_unchoke_piece_picks;
int m_incoming_redundant_piece_picks;
int m_incoming_piece_picks;
int m_end_game_piece_picks;
int m_snubbed_piece_picks;
int m_connect_timeouts;
int m_uninteresting_peers;
int m_timeout_peers;
int m_no_memory_peers;
int m_too_many_peers;
int m_transport_timeout_peers;
cache_status m_last_cache_status;
size_type m_last_failed;
size_type m_last_redundant;
size_type m_last_uploaded;
size_type m_last_downloaded;
int m_connection_attempts;
int m_num_banned_peers;
int m_banned_for_hash_failure;
vm_statistics_data_t m_last_vm_stat;
thread_cpu_usage m_network_thread_cpu_usage;
sliding_average<20> m_read_ops;
sliding_average<20> m_write_ops;;
enum enum
{ {
on_read_counter, on_read_counter,
on_write_counter, on_write_counter,
on_tick_counter, on_tick_counter,
on_lsd_counter, on_lsd_counter,
on_lsd_peer_counter, on_lsd_peer_counter,
on_udp_counter, on_udp_counter,
on_accept_counter, on_accept_counter,
on_disk_queue_counter, on_disk_queue_counter,
on_disk_read_counter, on_disk_read_counter,
on_disk_write_counter, on_disk_write_counter,
max_messages max_messages
}; };
int m_num_messages[max_messages]; int m_num_messages[max_messages];
// 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8 192, // 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8 192,
// 16384, 32768, 65536, 131072, 262144, 524288, 1048 576 // 16384, 32768, 65536, 131072, 262144, 524288, 1048 576
int m_send_buffer_sizes[18]; int m_send_buffer_sizes[18];
int m_recv_buffer_sizes[18]; int m_recv_buffer_sizes[18];
#endif #endif
// each second tick the timer takes a little
// bit longer than one second to trigger. The
// extra time it took is accumulated into this
// counter. Every time it exceeds 1000, torrents
// will tick their timers 2 seconds instead of one.
// this keeps the timers more accurate over time
// as a kind of "leap second" to adjust for the
// accumulated error
boost::uint16_t m_tick_residual;
// the number of torrents that have apply_ip_filter
// set to false. This is typically 0
int m_non_filtered_torrents;
#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
, int instance, bool append = true); , int instance, bool append = true);
// this list of tracker loggers serves as tracker_ca llbacks when // this list of tracker loggers serves as tracker_ca llbacks when
// 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; std::string m_logpath;
public:
boost::shared_ptr<logger> m_logger;
private: private:
#endif #endif
#ifdef TORRENT_UPNP_LOGGING #ifdef TORRENT_UPNP_LOGGING
std::ofstream m_upnp_log; std::ofstream m_upnp_log;
#endif #endif
struct external_ip_t
{
external_ip_t(): sources(0), num_votes(0) {}
bool add_vote(sha1_hash const& k, int type);
bool operator<(external_ip_t const& rhs) con
st
{
if (num_votes < rhs.num_votes) retur
n true;
if (num_votes > rhs.num_votes) retur
n false;
return sources < rhs.sources;
}
// this is a bloom filter of the IPs that ha
ve
// reported this address
bloom_filter<16> voters;
// this is the actual external address
address addr;
// a bitmask of sources the reporters have c
ome from
boost::uint16_t sources;
// the total number of votes for this IP
boost::uint16_t num_votes;
};
// this is a bloom filter of all the IPs that have
// been the first to report an external address. Eac
h
// IP only gets to add a new item once.
bloom_filter<32> m_external_address_voters;
std::vector<external_ip_t> m_external_addresses;
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;
typedef std::list<boost::shared_ptr<plugin> > ses_ex
tension_list_t;
ses_extension_list_t m_ses_extensions;
#endif #endif
#ifndef TORRENT_DISABLE_GEO_IP #ifndef TORRENT_DISABLE_GEO_IP
GeoIP* m_asnum_db; GeoIP* m_asnum_db;
GeoIP* m_country_db; GeoIP* m_country_db;
// maps AS number to the peak download rate // maps AS number to the peak download rate
// we've seen from it. Entries are never removed // we've seen from it. Entries are never removed
// from this map. Pointers to its elements // from this map. Pointers to its elements
// are kept in the policy::peer structures. // are kept in the policy::peer structures.
std::map<int, int> m_as_peak; std::map<int, int> m_as_peak;
#endif #endif
// total redundant and failed bytes // total redundant and failed bytes
size_type m_total_failed_bytes; size_type m_total_failed_bytes;
size_type m_total_redundant_bytes; size_type m_total_redundant_bytes;
// redundant bytes per category
size_type m_redundant_bytes[7];
std::vector<boost::shared_ptr<feed> > m_feeds;
// this is the set of (subscribed) torrents that hav
e changed
// their states since the last time the user request
ed updates.
std::vector<boost::weak_ptr<torrent> > m_state_updat
es;
// the main working thread // the main working thread
boost::scoped_ptr<boost::thread> m_thread; boost::scoped_ptr<thread> m_thread;
#if (defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS) && defined BOOST_HAS
_PTHREADS
pthread_t m_network_thread;
#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
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 , libtorrent::address const& tracker_ip
, std::list<address> const& ip_list , std::list<address> const& ip_list
, std::vector<peer_entry>& peers , std::vector<peer_entry>& peers
, int interval , int interval
, int min_interval , int min_interval
, int complete , int complete
, int incomplete , int incomplete
, address const& external_ip) , address const& external_ip
, std::string const& tracker_id)
{ {
std::string s; std::string s;
s = "TRACKER RESPONSE:\n"; s = "TRACKER RESPONSE:\n";
char tmp[200]; char tmp[200];
snprintf(tmp, 200, "interval: %d\nmin_interv al: %d\npeers:\n", interval, min_interval); snprintf(tmp, 200, "interval: %d\nmin_interv al: %d\npeers:\n", interval, min_interval);
s += tmp; 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)
{ {
char pid[41]; char pid[41];
skipping to change at line 834 skipping to change at line 1192
s += tmp; s += tmp;
debug_log(s); 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& r
tracker_request const& , int response_code, error_code const& ec, c
, int response_code onst std::string& str
, const std::string& str
, int retry_interval) , int retry_interval)
{ {
char msg[256]; char msg[256];
snprintf(msg, sizeof(msg), "*** tracker erro snprintf(msg, sizeof(msg), "*** tracker erro
r: %d: %s", response_code, str.c_str()); r: %d: %s %s"
, response_code, ec.message().c_str(
), str.c_str());
debug_log(msg); 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. 100 change blocks. 
161 lines changed or deleted 557 lines changed or added


 session_settings.hpp   session_settings.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_SESSION_SETTINGS_HPP_INCLUDED #ifndef TORRENT_SESSION_SETTINGS_HPP_INCLUDED
#define TORRENT_SESSION_SETTINGS_HPP_INCLUDED #define TORRENT_SESSION_SETTINGS_HPP_INCLUDED
#include "libtorrent/version.hpp" #include "libtorrent/version.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/version.hpp"
#include <string>
namespace libtorrent namespace libtorrent
{ {
struct TORRENT_EXPORT proxy_settings struct TORRENT_EXPORT proxy_settings
{ {
proxy_settings() : port(0), type(none) {} proxy_settings() : port(0), type(none)
, proxy_hostnames(true)
, proxy_peer_connections(true)
{}
std::string hostname; std::string hostname;
int port; int port;
std::string username; std::string username;
std::string password; std::string password;
enum proxy_type enum proxy_type
{ {
// a plain tcp socket is used, and // a plain tcp socket is used, and
skipping to change at line 74 skipping to change at line 80
// connect to the proxy. the username // connect to the proxy. the username
// and password are used to authenticate // and password are used to authenticate
// with the proxy server. // with the proxy server.
socks5_pw, socks5_pw,
// the http proxy is only available for // the http proxy is only available for
// tracker and web seed traffic // tracker and web seed traffic
// assumes anonymous access to proxy // assumes anonymous access to proxy
http, http,
// http proxy with basic authentication // http proxy with basic authentication
// uses username and password // uses username and password
http_pw http_pw,
// route through a i2p SAM proxy
i2p_proxy
}; };
proxy_type type; proxy_type type;
// when set to true, hostname are resolved
// through the proxy (if supported)
bool proxy_hostnames;
// if true, use this proxy for peers too
bool proxy_peer_connections;
}; };
struct TORRENT_EXPORT session_settings struct TORRENT_EXPORT session_settings
{ {
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_) ~session_settings();
, tracker_completion_timeout(60)
, tracker_receive_timeout(40) // libtorrent version. Used for forward binary compatibility
, stop_tracker_timeout(5) int version;
, tracker_maximum_response_length(1024*1024)
, piece_timeout(20)
, request_timeout(50)
, request_queue_time(3)
, max_allowed_in_request_queue(250)
, max_out_request_queue(200)
, whole_pieces_threshold(20)
, peer_timeout(120)
, urlseed_timeout(20)
, urlseed_pipeline_size(5)
, urlseed_wait_retry(30)
, file_pool_size(40)
, allow_multiple_connections_per_ip(false)
, max_failcount(3)
, min_reconnect_time(60)
, peer_connect_timeout(7)
, ignore_limits_on_local_network(true)
, connection_speed(10)
, send_redundant_have(false)
, lazy_bitfields(true)
, inactivity_timeout(600)
, unchoke_interval(15)
, optimistic_unchoke_interval(30)
, num_want(200)
, initial_picker_threshold(4)
, allowed_fast_set_size(10)
, max_queued_disk_bytes(256 * 1024)
, handshake_timeout(10)
#ifndef TORRENT_DISABLE_DHT
, use_dht_as_fallback(false)
#endif
, free_torrent_hashes(true)
, upnp_ignore_nonrouters(false)
, send_buffer_watermark(100 * 1024)
, auto_upload_slots(true)
, auto_upload_slots_rate_based(false)
, use_parole_mode(true)
, cache_size(1024)
, cache_buffer_chunk_size(16)
, 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)
, peer_tos(0)
, active_downloads(8)
, active_seeds(5)
, active_limit(15)
, auto_manage_prefer_seeds(false)
, dont_count_slow_torrents(true)
, auto_manage_interval(30)
, share_ratio_limit(2.f)
, seed_time_ratio_limit(7.f)
, seed_time_limit(24 * 60 * 60) // 24 hours
, peer_turnover(2 / 50.f)
, peer_turnover_cutoff(.9f)
, close_redundant_connections(true)
, auto_scrape_interval(1800)
, auto_scrape_min_interval(300)
, max_peerlist_size(4000)
, max_paused_peerlist_size(4000)
, min_announce_interval(5 * 60)
, prioritize_partial_pieces(false)
, auto_manage_startup(120)
, 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(20)
#ifdef TORRENT_WINDOWS
, max_sparse_regions(30000)
#else
, max_sparse_regions(0)
#endif
#ifndef TORRENT_DISABLE_MLOCK
, lock_disk_cache(false)
#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)
, broadcast_lsd(false)
{}
// 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 331 skipping to change at line 245
// the number of seconds between chokes/unchokes // the number of seconds between chokes/unchokes
int unchoke_interval; int unchoke_interval;
// the number of seconds between // the number of seconds between
// optimistic unchokes // optimistic unchokes
int optimistic_unchoke_interval; 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; std::string 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;
// this determines which pieces will be suggested to peers
// suggest read cache will make libtorrent suggest pieces
// that are fresh in the disk read cache, to potentially
// lower disk access and increase the cache hit ratio
enum { no_piece_suggestions = 0, suggest_read_cache = 1 };
int suggest_mode;
// 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 16 kB // indefinitely. This should be set to at least 16 kB
// to not completely disrupt normal downloads. If it's // to not completely disrupt normal downloads. If it's
// set to 0, you will be starving the disk thread and // set to 0, you will be starving the disk thread and
// nothing will be written to disk. // nothing will be written to disk.
// this is a per session setting. // this is a per session setting.
int max_queued_disk_bytes; int max_queued_disk_bytes;
// this is the low watermark for the disk buffer queue.
// whenever the number of queued bytes exceed the
// max_queued_disk_bytes, libtorrent will wait for
// it to drop below this value before issuing more
// reads from the sockets. If set to 0, the
// low watermark will be half of the max queued disk bytes
int max_queued_disk_bytes_low_watermark;
// 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 not 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
skipping to change at line 377 skipping to change at line 306
// 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;
// when this is true, the upnp port mapper will ignore // when this is true, the upnp port mapper will ignore
// any upnp devices that don't have an address that matches // any upnp devices that don't have an address that matches
// our currently configured router. // our currently configured router.
bool upnp_ignore_nonrouters; bool upnp_ignore_nonrouters;
// This is the minimum send buffer target size (send buffer
// includes bytes pending being read from disk). For good
// and snappy seeding performance, set this fairly high, to
// at least fit a few blocks. This is essentially the initia
l
// window size which will determine how fast we can ramp up
// the send rate
int send_buffer_low_watermark;
// if the send buffer has fewer bytes than this, we'll // if the send buffer has fewer bytes than this, we'll
// read another 16kB block onto it. If set too small, // read another 16kB block onto it. If set too small,
// upload rate capacity will suffer. If set too high, // upload rate capacity will suffer. If set too high,
// memory will be wasted. // memory will be wasted.
// The actual watermark may be lower than this in case // The actual watermark may be lower than this in case
// the upload rate is low, this is the upper limit. // the upload rate is low, this is the upper limit.
int send_buffer_watermark; int send_buffer_watermark;
// if auto_upload_slots is true, and a global upload // the current upload rate to a peer is multiplied by
// limit is set and the upload rate is less than 90% // this factor to get the send buffer watermark. The
// of the upload limit, on new slot is opened up. If // factor is specified as a percentage. i.e. 50 -> 0.5
// the upload rate is >= upload limit for an extended // This product is clamped to the send_buffer_watermark
// period of time, one upload slot is closed. The // setting to not exceed the max. For high speed
// upload slots are never automatically decreased below // upload, this should be set to a greater value than
// the manual settings, through max_uploads. // 100. The default is 50.
bool auto_upload_slots; int send_buffer_watermark_factor;
// this only affects the auto upload slots mechanism. #ifndef TORRENT_NO_DEPRECATE
// if auto_upload_slots is false, this field is not // deprecated in 0.16
// considered. bool auto_upload_slots;
bool auto_upload_slots_rate_based; bool auto_upload_slots_rate_based;
#endif
enum choking_algorithm_t
{
fixed_slots_choker,
auto_expand_choker,
rate_based_choker,
bittyrant_choker
};
int choking_algorithm;
enum seed_choking_algorithm_t
{
round_robin,
fastest_upload,
anti_leech
};
// the choking algorithm to use for seeding torrents
int seed_choking_algorithm;
// 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 1024 (= 16 MiB). -1 means automatic, which // default is 1024 (= 16 MiB). -1 means automatic, which
skipping to change at line 420 skipping to change at line 378
int cache_size; int cache_size;
// this is the number of disk buffer blocks (16 kiB) // this is the number of disk buffer blocks (16 kiB)
// that should be allocated at a time. It must be // that should be allocated at a time. It must be
// at least 1. Lower number saves memory at the expense // at least 1. Lower number saves memory at the expense
// of more heap allocations // of more heap allocations
int cache_buffer_chunk_size; 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 5 minutes.
int cache_expiry; int cache_expiry;
// when true, the disk I/O thread uses the disk // when true, the disk I/O thread uses the disk
// cache for caching blocks read from disk too // cache for caching blocks read from disk too
bool use_read_cache; bool use_read_cache;
// don't implicitly cache pieces in the read cache,
// only cache pieces that are explicitly asked to be
// cached.
bool explicit_read_cache;
// the number of seconds between refreshes of
// explicit caches
int explicit_cache_interval;
enum io_buffer_mode_t enum io_buffer_mode_t
{ {
enable_os_cache = 0, enable_os_cache = 0,
disable_os_cache_for_aligned_files = 1, disable_os_cache_for_aligned_files = 1,
disable_os_cache = 2 disable_os_cache = 2
}; };
int disk_io_write_mode; int disk_io_write_mode;
int disk_io_read_mode; int disk_io_read_mode;
bool coalesce_reads; bool coalesce_reads;
skipping to change at line 456 skipping to change at line 423
// 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/
// For unmarked packets, set to 0 // For unmarked packets, set to 0
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.
// active_dht_limit and active_tracker_limit limits the
// number of torrents that will be active on the DHT
// versus the tracker. If the active limit is set higher
// than these numbers, some torrents will be "active" in
// the sense that they will accept incoming connections,
// but not announce on the DHT or the tracker
int active_downloads; int active_downloads;
int active_seeds; int active_seeds;
int active_dht_limit;
int active_tracker_limit;
int active_lsd_limit;
int active_limit; int active_limit;
// prefer seeding torrents when determining which torrents t o give // prefer seeding torrents when determining which torrents t o give
// active slots to, the default is false which gives prefere nce to // active slots to, the default is false which gives prefere nce to
// downloading torrents // downloading torrents
bool auto_manage_prefer_seeds; 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
skipping to change at line 486 skipping to change at line 462
// (seconds as seed / seconds as downloader) or the seed // (seconds as seed / seconds as downloader) or the seed
// time limit (seconds as seed) it is considered // time limit (seconds as seed) it is considered
// done, and it will leave room for other torrents // done, and it will leave room for other torrents
// the default value for share ratio is 2 // the default value for share ratio is 2
// the default seed time ratio is 7, because that's a common // the default seed time ratio is 7, because that's a common
// asymmetry ratio on connections // asymmetry ratio on connections
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 interval (in seconds) between optimistic disconnects
// if the disconnects happen and how many peers are disconne
cted
// is controlled by peer_turnover and peer_turnover_cutoff
int peer_turnover_interval;
// the percentage of peers to disconnect every // the percentage of peers to disconnect every
// 90 seconds (if we're at the peer limit) // turnoever interval (if we're at the peer limit)
// defaults to 1/50:th // defaults to 2/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_cutoff 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
skipping to change at line 611 skipping to change at line 592
// delay between disk operations, to make it // delay between disk operations, to make it
// less intrusive on the system as a whole // less intrusive on the system as a whole
// blocking the disk. This delay is specified // blocking the disk. This delay is specified
// in milliseconds and the delay will be this // in milliseconds and the delay will be this
// long per 16kiB block // long per 16kiB block
// the default of 10 ms/16kiB will limit // the default of 10 ms/16kiB will limit
// the checking rate to 1.6 MiB per second // the checking rate to 1.6 MiB per second
int file_checks_delay_per_block; int file_checks_delay_per_block;
enum disk_cache_algo_t enum disk_cache_algo_t
{ lru, largest_contiguous }; { lru, largest_contiguous, avoid_readback };
disk_cache_algo_t disk_cache_algorithm; disk_cache_algo_t disk_cache_algorithm;
// the number of blocks that will be read ahead // the number of blocks that will be read ahead
// when reading a block into the read cache // when reading a block into the read cache
int read_cache_line_size; int read_cache_line_size;
// whenever a contiguous range of this many // whenever a contiguous range of this many
// blocks is found in the write cache, it // blocks is found in the write cache, it
// is flushed immediately // is flushed immediately
skipping to change at line 646 skipping to change at line 627
// if this is true, disk read operations may // if this is true, disk read operations may
// be re-ordered based on their physical disk // be re-ordered based on their physical disk
// read offset. This greatly improves throughput // read offset. This greatly improves throughput
// when uploading to many peers. This assumes // when uploading to many peers. This assumes
// a traditional hard drive with a read head // a traditional hard drive with a read head
// and spinning platters. If your storage medium // and spinning platters. If your storage medium
// is a solid state drive, this optimization // is a solid state drive, this optimization
// doesn't give you an benefits // doesn't give you an benefits
bool allow_reordered_disk_operations; bool allow_reordered_disk_operations;
// if this is true, i2p torrents are allowed
// to also get peers from other sources than
// the tracker, and connect to regular IPs,
// not providing any anonymization. This may
// be useful if the user is not interested in
// the anonymization of i2p, but still wants to
// be able to connect to i2p peers.
bool allow_i2p_mixed;
// the max number of pieces that a peer can // the max number of pieces that a peer can
// suggest to use before we start dropping // suggest to use before we start dropping
// previous suggested piece // previous suggested piece
int max_suggest_pieces; int max_suggest_pieces;
// if set to true, requests that have have not been // if set to true, requests that have have not been
// satisfied after the equivalence of the entire // satisfied after the equivalence of the entire
// request queue has been received, will be considered lost // request queue has been received, will be considered lost
bool drop_skipped_requests; bool drop_skipped_requests;
skipping to change at line 667 skipping to change at line 657
// run at lower-than-normal priority. This is // run at lower-than-normal priority. This is
// intended to make the machine more responsive // intended to make the machine more responsive
// to foreground tasks, while bittorrent runs // to foreground tasks, while bittorrent runs
// in the background // in the background
bool low_prio_disk; bool low_prio_disk;
// number of seconds between local service announces for // number of seconds between local service announces for
// torrents. Defaults to 5 minutes // torrents. Defaults to 5 minutes
int local_service_announce_interval; int local_service_announce_interval;
// number of seconds between DHT announces for
// torrents. Defaults to 15 minutes
int dht_announce_interval;
// the number of seconds a connection ID received // the number of seconds a connection ID received
// from a UDP tracker is valid for. This is specified // from a UDP tracker is valid for. This is specified
// as 60 seconds // as 60 seconds
int udp_tracker_token_expiry; int udp_tracker_token_expiry;
// if this is set to true, any block read from the
// disk cache will be dropped from the cache immediately
// following. This may be useful if the block is not
// expected to be hit again. It would save some memory
bool volatile_read_cache;
// if this is set to true, the size of the cache line
// generated by a particular read request depends on the
// rate you're sending to that peer. This optimizes the
// memory usage of the disk read cache by reading
// further ahead for peers that you're uploading at high
// rates to
bool guided_read_cache;
// this is the default minimum time any read cache line
// is kept in the cache.
int default_cache_min_age;
// the global number of optimistic unchokes
// 0 means automatic
int num_optimistic_unchoke_slots;
// if set to true, files won't have their atime updated
// on disk reads. This works on linux
bool no_atime_storage;
// === BitTyrant unchoker settings ==
// when using BitTyrant choker, this is the default
// assumed reciprocation rate. This is where each peer start
s
int default_est_reciprocation_rate;
// this is the increase of the estimated reciprocation rate
// in percent. We increase by this amount once every unchoke
// interval that we are choked by the other peer and we have
// unchoked them
int increase_est_reciprocation_rate;
// each unchoke interval that we stay unchoked by the other
// peer, and we have unchoked this peer as well, we decrease
// our estimate of the reciprocation rate, since we might ha
ve
// over-estimated it
int decrease_est_reciprocation_rate;
// if set to true, an incoming connection to a torrent that'
s
// paused and auto-managed will make the torrent start.
bool incoming_starts_queued_torrents;
// when set to true, the downloaded counter sent to trackers // when set to true, the downloaded counter sent to trackers
// will include the actual number of payload bytes donwnload ed // will include the actual number of payload bytes donwnload ed
// including redundant bytes. If set to false, it will not i nclude // including redundant bytes. If set to false, it will not i nclude
// any redundany bytes // any redundany bytes
bool report_true_downloaded; bool report_true_downloaded;
// if set to true, libtorrent won't request a piece multiple times // if set to true, libtorrent won't request a piece multiple times
// until every piece is requested // until every piece is requested
bool strict_end_game_mode; bool strict_end_game_mode;
// if this is true, the broadcast socket will not only use I P multicast // if this is true, the broadcast socket will not only use I P multicast
// but also send the messages on the broadcast address. This is false by // but also send the messages on the broadcast address. This is false by
// default in order to avoid flooding networks for no good r eason. If // default in order to avoid flooding networks for no good r eason. If
// a network is known not to support multicast, this can be enabled // a network is known not to support multicast, this can be enabled
bool broadcast_lsd; bool broadcast_lsd;
// when set to true, libtorrent will try to make outgoing ut
p connections
bool enable_outgoing_utp;
// if set to false, libtorrent will reject incoming utp conn
ections
bool enable_incoming_utp;
// when set to false, no outgoing TCP connections will be ma
de
bool enable_outgoing_tcp;
// if set to false, libtorrent will reject incoming tcp conn
ections
bool enable_incoming_tcp;
// the max number of peers we accept from pex messages from
a single peer.
// this limits the number of concurrent peers any of our pee
rs claims to
// be connected to. If they clain to be connected to more th
an this, we'll
// ignore any peer that exceeds this limit
int max_pex_peers;
// when set to true, the file modification time is ignored w
hen loading
// resume data. The resume data includes the expected timest
amp of each
// file and is typically compared to make sure the files hav
en't changed
// since the last session
bool ignore_resume_timestamps;
// normally, if a resume file is incomplete (typically there
's no
// "file sizes" field) the torrent is queued for a full chec
k. If
// this settings is set to true, instead libtorrent will ass
ume
// we have none of the files and go straight to download
bool no_recheck_incomplete_resume;
// when this is true, libtorrent will take actions to make s
ure any
// privacy sensitive information is leaked out from the clie
nt. This
// mode is assumed to be combined with using a proxy for all
your
// traffic. With this option, your true IP address will not
be exposed
bool anonymous_mode;
// the number of milliseconds between internal ticks. Should
be no
// more than one second (i.e. 1000).
int tick_interval;
// specifies whether downloads from web seeds is reported to
the
// tracker or not. Defaults to on
bool report_web_seed_downloads;
// this is the target share ratio for share-mode torrents
int share_mode_target;
// max upload rate in bytes per second for the session
int upload_rate_limit;
// max download rate in bytes per second for the session
int download_rate_limit;
// max upload rate in bytes per second for peers on the loca
l
// network, in the session
int local_upload_rate_limit;
// max download rate in bytes per second for peers on the lo
cal
// network, in the session
int local_download_rate_limit;
// max upload rate used by the DHT in bytes per second
int dht_upload_rate_limit;
// the max number of unchoke slots in the session (might be
// overridden by unchoke algorithm)
int unchoke_slots_limit;
// the max number of half-open TCP connections
int half_open_limit;
// the max number of connections in the session
int connections_limit;
// target delay, milliseconds
int utp_target_delay;
// max number of bytes to increase cwnd per rtt in uTP
// congestion controller
int utp_gain_factor;
// the shortest allowed uTP connection timeout in millisecon
ds
// defaults to 500 milliseconds. The shorter timeout, the
// faster the connection recovers from a loss of an entire w
indow
int utp_min_timeout;
// the number of SYN packets that are sent before giving up
int utp_syn_resends;
// the number of resent packets sent on a closed socket befo
re giving up
int utp_fin_resends;
// the number of times to send a packet before giving up
int utp_num_resends;
// initial timeout for uTP SYN packets
int utp_connect_timeout;
// number of milliseconds of delaying ACKing packets the mos
t
int utp_delayed_ack;
// set to true if the uTP socket buffer size is allowed to i
ncrease
// dynamically based on the NIC MTU setting. This is true by
default
// and improves uTP performance for networks with larger fra
me sizes
// including loopback
bool utp_dynamic_sock_buf;
// what to multiply the congestion window by on packet loss.
// it's specified as a percent. The default is 50, i.e. cut
// in half
int utp_loss_multiplier;
enum bandwidth_mixed_algo_t
{
// disables the mixed mode bandwidth balancing
prefer_tcp = 0,
// does not throttle uTP, throttles TCP to the same
proportion
// of throughput as there are TCP connections
peer_proportional = 1
};
// the algorithm to use to balance bandwidth between tcp
// connections and uTP connections
int mixed_mode_algorithm;
// set to true if uTP connections should be rate limited
// defaults to false
bool rate_limit_utp;
// this is the number passed in to listen(). i.e.
// the number of connections to accept while we're
// not waiting in an accept() call.
int listen_queue_size;
// if this is true, the &ip= argument in tracker requests
// (unless otherwise specified) will be set to the intermedi
ate
// IP address if the user is double NATed. If ther user is n
ot
// double NATed, this option does not have an affect
bool announce_double_nat;
// the first tracker response after a torrent is started
// will cause this many connections to be made immediately.
// instead of waiting for the connection scheduler which
// triggeres every second
int torrent_connect_boost;
// this controls whether or not seeding (and complete) torre
nts
// attempt to make outgoing connections or not. It defaults
to
// true, but can be set to zero for specific applications wh
ere
// making outgoing connections is costly and known to not
// add any benefits
bool seeding_outgoing_connections;
// when this is true, libtorrent will not attempt to make ou
tgoing
// connections to peers whose port is < 1024. This is a safe
ty
// precaution to avoid being part of a DDoS attack
bool no_connect_privileged_ports;
// the max alert queue size
int alert_queue_size;
// the max allowed size for metadata received by the
// ut_metadata extension (i.e. magnet links)
int max_metadata_size;
// attempt to smooth out connects to avoid getting spikes in
// opening connections and timing out connections
bool smooth_connects;
// always send user-agent
bool always_send_user_agent;
// if true, trackers will also be filtered by the IP
// filter, otherwise they are exempt
bool apply_ip_filter_to_trackers;
// to avoid write jobs starving read jobs, if this many
// write jobs have been taking priority in a row, service
// one read job
int read_job_every;
// issue posix_fadvise() or fcntl(F_RDADVISE) for disk reads
// ahead of time
bool use_disk_read_ahead;
// if set to true, files will be locked when opened.
// preventing any other process from modifying them
bool lock_files;
// open an ssl listen socket for ssl torrents on this port
int ssl_listen;
// this is the factor X in the formula to calculate the
// next tracker timeout:
// delay = 5 + X/100 * fails^2
// so, it's an exponential back-off, and this factor
// determines how fast the back-off happens. Default
// is 250
int tracker_backoff;
// when true, web seeds sending bad data will be banned
bool ban_web_seeds;
}; };
#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)
#ifndef TORRENT_NO_DEPRECATE
, service_port(0) , service_port(0)
#endif
, max_fail_count(20) , max_fail_count(20)
, max_torrents(2000)
, max_dht_items(700)
, max_torrent_search_reply(20)
, restrict_routing_ips(true)
, restrict_search_ips(true)
{} {}
// the maximum number of peers to send in a // the maximum number of peers to send in a
// reply to get_peers // reply to get_peers
int max_peers_reply; int max_peers_reply;
// the number of simultanous "connections" when // the number of simultanous "connections" when
// searching the DHT. // searching the DHT.
int search_branching; int search_branching;
#ifndef TORRENT_NO_DEPRECATE
// the listen port for the dht. This is a UDP port. // the listen port for the dht. This is a UDP port.
// zero means use the same as the tcp interface // zero means use the same as the tcp interface
int service_port; int service_port;
#endif
// the maximum number of times a node can fail // the maximum number of times a node can fail
// in a row before it is removed from the table. // in a row before it is removed from the table.
int max_fail_count; int max_fail_count;
// this is the max number of torrents the DHT will track
int max_torrents;
// max number of items the DHT will store
int max_dht_items;
// the max number of torrents to return in a
// torrent search query to the DHT
int max_torrent_search_reply;
// when set, nodes whose IP address that's in
// the same /24 (or /64 for IPv6) range in the
// same routing table bucket. This is an attempt
// to mitigate node ID spoofing attacks
// also restrict any IP to only have a single
// entry in the whole routing table
bool restrict_routing_ips;
// applies the same IP restrictions on nodes
// received during a DHT search (traversal algorithm)
bool restrict_search_ips;
}; };
#endif #endif
#ifndef TORRENT_DISABLE_ENCRYPTION #ifndef TORRENT_DISABLE_ENCRYPTION
struct pe_settings struct pe_settings
{ {
pe_settings() pe_settings()
: out_enc_policy(enabled) : out_enc_policy(enabled)
, in_enc_policy(enabled) , in_enc_policy(enabled)
skipping to change at line 737 skipping to change at line 1014
enum enc_policy enum enc_policy
{ {
forced, // disallow non encrypted connections forced, // disallow non encrypted connections
enabled, // allow encrypted and non encrypted connec tions enabled, // allow encrypted and non encrypted connec tions
disabled // disallow encrypted connections disabled // disallow encrypted connections
}; };
enum enc_level enum enc_level
{ {
plaintext, // use only plaintext encryption plaintext = 1, // use only plaintext encryption
rc4, // use only rc4 encryption rc4 = 2, // use only rc4 encryption
both // allow both both = 3 // allow both
}; };
enc_policy out_enc_policy; enc_policy out_enc_policy;
enc_policy in_enc_policy; enc_policy in_enc_policy;
enc_level allowed_enc_level; enc_level allowed_enc_level;
// if the allowed encryption level is both, setting this to // if the allowed encryption level is both, setting this to
// true will prefer rc4 if both methods are offered, plainte xt // true will prefer rc4 if both methods are offered, plainte xt
// otherwise // otherwise
bool prefer_rc4; bool prefer_rc4;
 End of changes. 30 change blocks. 
126 lines changed or deleted 444 lines changed or added


 session_status.hpp   session_status.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_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"
#include <vector>
namespace libtorrent namespace libtorrent
{ {
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
struct dht_lookup struct dht_lookup
{ {
char const* type; char const* type;
int outstanding_requests; int outstanding_requests;
int timeouts; int timeouts;
int responses; int responses;
int branch_factor; int branch_factor;
int nodes_left;
// the number of seconds ago the
// last message was sent that's still
// outstanding
int last_sent;
// the number of outstanding requests
// that have exceeded the short timeout
// and are considered timed out in the
// sense that they increased the branch
// factor
int first_timeout;
};
struct dht_routing_bucket
{
int num_nodes;
int num_replacements;
// number of seconds since last activity
int last_active;
}; };
#endif #endif
struct utp_status
{
int num_idle;
int num_syn_sent;
int num_connected;
int num_fin_sent;
int num_close_wait;
};
struct TORRENT_EXPORT session_status struct TORRENT_EXPORT session_status
{ {
bool has_incoming_connections; bool has_incoming_connections;
int upload_rate; int upload_rate;
int download_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_upload_rate;
skipping to change at line 100 skipping to change at line 129
int up_bandwidth_queue; int up_bandwidth_queue;
int down_bandwidth_queue; int down_bandwidth_queue;
int up_bandwidth_bytes_queue; int up_bandwidth_bytes_queue;
int down_bandwidth_bytes_queue; int down_bandwidth_bytes_queue;
int optimistic_unchoke_counter; int optimistic_unchoke_counter;
int unchoke_counter; int unchoke_counter;
int disk_write_queue;
int disk_read_queue;
#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; std::vector<dht_lookup> active_requests;
std::vector<dht_routing_bucket> dht_routing_table;
int dht_total_allocations;
#endif #endif
utp_status utp_stats;
int peerlist_size;
}; };
} }
#endif // TORRENT_SESSION_STATUS_HPP_INCLUDED #endif // TORRENT_SESSION_STATUS_HPP_INCLUDED
 End of changes. 6 change blocks. 
0 lines changed or deleted 38 lines changed or added


 socket.hpp   socket.hpp 
skipping to change at line 48 skipping to change at line 48
#endif #endif
// if building as Objective C++, asio's template // if building as Objective C++, asio's template
// parameters Protocol has to be renamed to avoid // parameters Protocol has to be renamed to avoid
// colliding with keywords // colliding with keywords
#ifdef __OBJC__ #ifdef __OBJC__
#define Protocol Protocol_ #define Protocol Protocol_
#endif #endif
#if defined TORRENT_WINDOWS || defined TORRENT_CYGWIN
// asio assumes that the windows error codes are defined already
#include <winsock2.h>
#endif
#include <boost/version.hpp> #include <boost/version.hpp>
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/ip/tcp.hpp> #include <asio/ip/tcp.hpp>
#include <asio/ip/udp.hpp> #include <asio/ip/udp.hpp>
#include <asio/io_service.hpp>
#include <asio/deadline_timer.hpp>
#include <asio/write.hpp> #include <asio/write.hpp>
#include <asio/read.hpp> #include <asio/read.hpp>
#include <asio/time_traits.hpp>
#include <asio/basic_deadline_timer.hpp>
#else #else
#include <boost/asio/ip/tcp.hpp> #include <boost/asio/ip/tcp.hpp>
#include <boost/asio/ip/udp.hpp> #include <boost/asio/ip/udp.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/deadline_timer.hpp>
#include <boost/asio/write.hpp> #include <boost/asio/write.hpp>
#include <boost/asio/read.hpp> #include <boost/asio/read.hpp>
#include <boost/asio/time_traits.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/time.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::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::udp::socket datagram_socket;
typedef ::asio::ip::tcp::acceptor socket_acceptor; 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_v4 address_v4;
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;
namespace asio = boost::asio; namespace asio = boost::asio;
typedef boost::asio::basic_deadline_timer<libtorrent::ptime> deadlin
e_timer;
#endif
inline std::string print_address(address const& addr)
{
error_code ec;
return addr.to_string(ec);
}
inline std::string print_endpoint(tcp::endpoint const& ep)
{
error_code ec;
std::string ret;
address const& addr = ep.address();
#if TORRENT_USE_IPV6
if (addr.is_v6())
{
ret += '[';
ret += addr.to_string(ec);
ret += ']';
ret += ':';
ret += to_string(ep.port()).elems;
}
else
#endif
{
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
{
template<class OutIt>
void write_address(address const& a, OutIt& out)
{
#if TORRENT_USE_IPV6
if (a.is_v4())
{
#endif
write_uint32(a.to_v4().to_ulong(), out);
#if TORRENT_USE_IPV6
}
else if (a.is_v6())
{
typedef address_v6::bytes_type bytes_t;
bytes_t bytes = a.to_v6().to_bytes();
for (bytes_t::iterator i = bytes.begin()
, end(bytes.end()); i != end; ++i)
write_uint8(*i, out);
}
#endif
}
template<class InIt>
address read_v4_address(InIt& in)
{
unsigned long ip = read_uint32(in);
return address_v4(ip);
}
#if TORRENT_USE_IPV6
template<class InIt>
address read_v6_address(InIt& in)
{
typedef address_v6::bytes_type bytes_t;
bytes_t bytes;
for (bytes_t::iterator i = bytes.begin()
, end(bytes.end()); i != end; ++i)
*i = read_uint8(in);
return address_v6(bytes);
}
#endif #endif
template<class Endpoint, class OutIt>
void write_endpoint(Endpoint const& e, OutIt& out)
{
write_address(e.address(), out);
write_uint16(e.port(), out);
}
template<class Endpoint, class InIt>
Endpoint read_v4_endpoint(InIt& in)
{
address addr = read_v4_address(in);
int port = read_uint16(in);
return Endpoint(addr, port);
}
#if TORRENT_USE_IPV6
template<class Endpoint, class InIt>
Endpoint read_v6_endpoint(InIt& in)
{
address addr = read_v6_address(in);
int port = read_uint16(in);
return Endpoint(addr, port);
}
#endif
}
#if TORRENT_USE_IPV6 #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; }
skipping to change at line 276 skipping to change at line 154
template<class Protocol> template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IP; } int level(Protocol const&) const { return IPPROTO_IP; }
template<class Protocol> template<class Protocol>
int name(Protocol const&) const { return IP_TOS; } int name(Protocol const&) const { return IP_TOS; }
template<class Protocol> template<class Protocol>
tos_t const* data(Protocol const&) const { return &m_value; } tos_t 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); }
tos_t m_value; tos_t m_value;
}; };
#if defined IP_DONTFRAG || defined IP_MTU_DISCOVER || defined IP_DONTFRAGME
NT
#define TORRENT_HAS_DONT_FRAGMENT
#endif
#ifdef TORRENT_HAS_DONT_FRAGMENT
struct dont_fragment
{
dont_fragment(bool val)
#ifdef IP_PMTUDISCOVER_DO
: m_value(val ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT) {
}
#else
: m_value(val) {}
#endif
template<class Protocol>
int level(Protocol const&) const { return IPPROTO_IP; }
template<class Protocol>
int name(Protocol const&) const
#if defined IP_DONTFRAG
{ return IP_DONTFRAG; }
#elif defined IP_MTU_DISCOVER
{ return IP_MTU_DISCOVER; }
#elif defined IP_DONTFRAGMENT
{ return IP_DONTFRAGMENT; }
#else
{}
#endif
template<class Protocol>
int const* data(Protocol const&) const { return &m_value; }
template<class Protocol>
size_t size(Protocol const&) const { return sizeof(m_value);
}
int m_value;
};
#endif // TORRENT_HAS_DONT_FRAGMENT
} }
#endif // TORRENT_SOCKET_HPP_INCLUDED #endif // TORRENT_SOCKET_HPP_INCLUDED
 End of changes. 13 change blocks. 
130 lines changed or deleted 42 lines changed or added


 socket_type.hpp   socket_type.hpp 
/* /*
Copyright (c) 2007, Arvid Norberg Copyright (c) 2009, Arvid Norberg
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions modification, are permitted provided that the following conditions
are met: are met:
* Redistributions of source code must retain the above copyright * Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer. notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright * Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in notice, this list of conditions and the following disclaimer in
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_SOCKET_TYPE #ifndef TORRENT_SOCKET_TYPE
#define TORRENT_SOCKET_TYPE #define TORRENT_SOCKET_TYPE
#include "libtorrent/config.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/socks5_stream.hpp" #include "libtorrent/socks5_stream.hpp"
#include "libtorrent/http_stream.hpp" #include "libtorrent/http_stream.hpp"
#include "libtorrent/variant_stream.hpp" #include "libtorrent/i2p_stream.hpp"
#include "libtorrent/utp_stream.hpp"
#include "libtorrent/io_service.hpp"
#include "libtorrent/max.hpp"
#include "libtorrent/assert.hpp"
#ifdef TORRENT_USE_OPENSSL
#include "libtorrent/ssl_stream.hpp"
#endif
#if defined TORRENT_ASIO_DEBUGGING
#include "libtorrent/debug.hpp"
#endif
#if TORRENT_USE_I2P
#define TORRENT_SOCKTYPE_I2P_FORWARD(x) \
case socket_type_int_impl<i2p_stream>::value: \
get<i2p_stream>()->x; break;
#define TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def) \
case socket_type_int_impl<i2p_stream>::value: \
return get<i2p_stream>()->x;
#else // TORRENT_USE_I2P
#define TORRENT_SOCKTYPE_I2P_FORWARD(x)
#define TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def)
#endif
#ifdef TORRENT_USE_OPENSSL
#define TORRENT_SOCKTYPE_SSL_FORWARD(x) \
case socket_type_int_impl<ssl_stream<stream_socket> >::value
: \
get<ssl_stream<stream_socket> >()->x; break; \
case socket_type_int_impl<ssl_stream<socks5_stream> >::value
: \
get<ssl_stream<socks5_stream> >()->x; break; \
case socket_type_int_impl<ssl_stream<http_stream> >::value:
\
get<ssl_stream<http_stream> >()->x; break; \
case socket_type_int_impl<ssl_stream<utp_stream> >::value: \
get<ssl_stream<utp_stream> >()->x; break;
#define TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def) \
case socket_type_int_impl<ssl_stream<stream_socket> >::value
: \
return get<ssl_stream<stream_socket> >()->x; \
case socket_type_int_impl<ssl_stream<socks5_stream> >::value
: \
return get<ssl_stream<socks5_stream> >()->x; \
case socket_type_int_impl<ssl_stream<http_stream> >::value:
\
return get<ssl_stream<http_stream> >()->x; \
case socket_type_int_impl<ssl_stream<utp_stream> >::value: \
return get<ssl_stream<utp_stream> >()->x;
#else
#define TORRENT_SOCKTYPE_SSL_FORWARD(x)
#define TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def)
#endif
#define TORRENT_SOCKTYPE_FORWARD(x) \
switch (m_type) { \
case socket_type_int_impl<stream_socket>::value: \
get<stream_socket>()->x; break; \
case socket_type_int_impl<socks5_stream>::value: \
get<socks5_stream>()->x; break; \
case socket_type_int_impl<http_stream>::value: \
get<http_stream>()->x; break; \
case socket_type_int_impl<utp_stream>::value: \
get<utp_stream>()->x; break; \
TORRENT_SOCKTYPE_I2P_FORWARD(x) \
TORRENT_SOCKTYPE_SSL_FORWARD(x) \
default: TORRENT_ASSERT(false); \
}
#define TORRENT_SOCKTYPE_FORWARD_RET(x, def) \
switch (m_type) { \
case socket_type_int_impl<stream_socket>::value: \
return get<stream_socket>()->x; \
case socket_type_int_impl<socks5_stream>::value: \
return get<socks5_stream>()->x; \
case socket_type_int_impl<http_stream>::value: \
return get<http_stream>()->x; \
case socket_type_int_impl<utp_stream>::value: \
return get<utp_stream>()->x; \
TORRENT_SOCKTYPE_I2P_FORWARD_RET(x, def) \
TORRENT_SOCKTYPE_SSL_FORWARD_RET(x, def) \
default: TORRENT_ASSERT(false); return def; \
}
namespace libtorrent namespace libtorrent
{ {
typedef variant_stream<
stream_socket template <class S>
, socks5_stream struct socket_type_int_impl
, http_stream> socket_type; { enum { value = 0 }; };
template <>
struct socket_type_int_impl<stream_socket>
{ enum { value = 1 }; };
template <>
struct socket_type_int_impl<socks5_stream>
{ enum { value = 2 }; };
template <>
struct socket_type_int_impl<http_stream>
{ enum { value = 3 }; };
template <>
struct socket_type_int_impl<utp_stream>
{ enum { value = 4 }; };
#if TORRENT_USE_I2P
template <>
struct socket_type_int_impl<i2p_stream>
{ enum { value = 5 }; };
#endif
#ifdef TORRENT_USE_OPENSSL
template <>
struct socket_type_int_impl<ssl_stream<stream_socket> >
{ enum { value = 6 }; };
template <>
struct socket_type_int_impl<ssl_stream<socks5_stream> >
{ enum { value = 7 }; };
template <>
struct socket_type_int_impl<ssl_stream<http_stream> >
{ enum { value = 8 }; };
template <>
struct socket_type_int_impl<ssl_stream<utp_stream> >
{ enum { value = 9 }; };
#endif
struct TORRENT_EXTRA_EXPORT socket_type
{
typedef stream_socket::endpoint_type endpoint_type;
typedef stream_socket::protocol_type protocol_type;
explicit socket_type(io_service& ios): m_io_service(ios), m_
type(0) {}
~socket_type();
io_service& get_io_service() const;
bool is_open() const;
char const* type_name() const;
#ifndef BOOST_NO_EXCEPTIONS
void open(protocol_type const& p);
void close();
endpoint_type local_endpoint() const;
endpoint_type remote_endpoint() const;
void bind(endpoint_type const& endpoint);
std::size_t available() const;
#endif
void open(protocol_type const& p, error_code& ec);
void close(error_code& ec);
endpoint_type local_endpoint(error_code& ec) const;
endpoint_type remote_endpoint(error_code& ec) const;
void bind(endpoint_type const& endpoint, error_code& ec);
std::size_t available(error_code& ec) const;
int type() const;
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers, error_
code& ec)
{ TORRENT_SOCKTYPE_FORWARD_RET(read_some(buffers, ec), 0) }
template <class Mutable_Buffers, class Handler>
void async_read_some(Mutable_Buffers const& buffers, Handler
const& handler)
{ TORRENT_SOCKTYPE_FORWARD(async_read_some(buffers, handler)
) }
template <class Const_Buffers>
std::size_t write_some(Const_Buffers const& buffers, error_c
ode& ec)
{ TORRENT_SOCKTYPE_FORWARD_RET(write_some(buffers, ec), 0) }
template <class Const_Buffers, class Handler>
void async_write_some(Const_Buffers const& buffers, Handler
const& handler)
{ TORRENT_SOCKTYPE_FORWARD(async_write_some(buffers, handler
)) }
template <class Handler>
void async_connect(endpoint_type const& endpoint, Handler co
nst& handler)
{ TORRENT_SOCKTYPE_FORWARD(async_connect(endpoint, handler))
}
#ifndef BOOST_NO_EXCEPTIONS
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc)
{ TORRENT_SOCKTYPE_FORWARD(io_control(ioc)) }
template <class Mutable_Buffers>
std::size_t read_some(Mutable_Buffers const& buffers)
{ TORRENT_SOCKTYPE_FORWARD_RET(read_some(buffers), 0) }
#endif
template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc, error_code& ec)
{ TORRENT_SOCKTYPE_FORWARD(io_control(ioc, ec)) }
#ifndef BOOST_NO_EXCEPTIONS
template <class SettableSocketOption>
void set_option(SettableSocketOption const& opt)
{ TORRENT_SOCKTYPE_FORWARD(set_option(opt)) }
#endif
template <class SettableSocketOption>
error_code set_option(SettableSocketOption const& opt, error
_code& ec)
{ TORRENT_SOCKTYPE_FORWARD_RET(set_option(opt, ec), ec) }
template <class S>
void instantiate(io_service& ios, void* userdata = 0)
{
TORRENT_ASSERT(&ios == &m_io_service);
construct(socket_type_int_impl<S>::value, userdata);
}
template <class S> S* get()
{
if (m_type != socket_type_int_impl<S>::value) return
0;
return (S*)m_data;
}
template <class S> S const* get() const
{
if (m_type != socket_type_int_impl<S>::value) return
0;
return (S const*)m_data;
}
private:
void destruct();
void construct(int type, void* userdata);
io_service& m_io_service;
int m_type;
enum { storage_size = max9<
sizeof(stream_socket)
, sizeof(socks5_stream)
, sizeof(http_stream)
, sizeof(utp_stream)
#if TORRENT_USE_I2P
, sizeof(i2p_stream)
#else
, 0
#endif
#ifdef TORRENT_USE_OPENSSL
, sizeof(ssl_stream<stream_socket>)
, sizeof(ssl_stream<socks5_stream>)
, sizeof(ssl_stream<http_stream>)
, sizeof(ssl_stream<utp_stream>)
#else
, 0, 0, 0, 0
#endif
>::value
};
size_type m_data[(storage_size + sizeof(size_type) - 1) / si
zeof(size_type)];
};
// returns true if this socket is an SSL socket
bool is_ssl(socket_type const& s);
// assuming the socket_type s is an ssl socket, make sure it
// verifies the hostname in its SSL handshake
void setup_ssl_hostname(socket_type& s, std::string const& hostname,
error_code& ec);
// properly shuts down SSL sockets. holder keeps s alive
void async_shutdown(socket_type& s, boost::shared_ptr<void> holder);
} }
#endif #endif
 End of changes. 4 change blocks. 
6 lines changed or deleted 290 lines changed or added


 socks5_stream.hpp   socks5_stream.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_SOCKS5_STREAM_HPP_INCLUDED #ifndef TORRENT_SOCKS5_STREAM_HPP_INCLUDED
#define TORRENT_SOCKS5_STREAM_HPP_INCLUDED #define TORRENT_SOCKS5_STREAM_HPP_INCLUDED
#include <boost/function/function1.hpp>
#include <boost/bind.hpp>
#include <boost/shared_ptr.hpp>
#include "libtorrent/proxy_base.hpp" #include "libtorrent/proxy_base.hpp"
namespace libtorrent { namespace libtorrent {
namespace socks_error { namespace socks_error {
enum socks_error_code enum socks_error_code
{ {
no_error = 0, no_error = 0,
unsupported_version, unsupported_version,
skipping to change at line 63 skipping to change at line 66
identd_error, identd_error,
num_errors num_errors
}; };
} }
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
typedef asio::error::error_category socks_error_category; typedef asio::error::error_category socks_error_category;
#else #else
struct TORRENT_EXPORT socks_error_category : boost::system::error_category struct TORRENT_EXTRA_EXPORT socks_error_category : boost::system::error_cat egory
{ {
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_condition(int e v) const virtual boost::system::error_condition default_error_condition(int e v) const
{ return boost::system::error_condition(ev, *this); } { return boost::system::error_condition(ev, *this); }
}; };
#endif #endif
extern socks_error_category socks_category; extern socks_error_category socks_category;
skipping to change at line 97 skipping to change at line 100
void set_command(int c) { m_command = c; } 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;
} }
void set_dst_name(std::string const& host)
{
m_dst_name = host;
if (m_dst_name.size() > 255)
m_dst_name.resize(255);
}
void close(error_code& ec)
{
m_hostname.clear();
m_dst_name.clear();
proxy_base::close(ec);
}
#ifndef BOOST_NO_EXCEPTIONS
void close()
{
m_hostname.clear();
m_dst_name.clear();
proxy_base::close();
}
#endif
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 fix error messages to use custom error_code category
//#error add async_connect() that takes a hostname and port as well //#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. if version == 5: // 3. if version == 5:
// 3.1 send SOCKS5 authentication method message // 3.1 send SOCKS5 authentication method message
// 3.2 read SOCKS5 authentication response // 3.2 read SOCKS5 authentication response
// 3.3 send username+password // 3.3 send username+password
// 4 send SOCKS command message // 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, to_string(m_port).elems); tcp::resolver::query q(m_hostname, to_string(m_port).elems);
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));
} }
skipping to change at line 143 skipping to change at line 169
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;
std::string m_dst_name;
int m_version; int m_version;
int m_command; int m_command;
// set to one when we're waiting for the // set to one when we're waiting for the
// second message to accept an incoming connection // second message to accept an incoming connection
int m_listen; int m_listen;
}; };
} }
#endif #endif
 End of changes. 5 change blocks. 
2 lines changed or deleted 29 lines changed or added


 ssl_stream.hpp   ssl_stream.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_SSL_STREAM_HPP_INCLUDED #ifndef TORRENT_SSL_STREAM_HPP_INCLUDED
#define TORRENT_SSL_STREAM_HPP_INCLUDED #define TORRENT_SSL_STREAM_HPP_INCLUDED
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include <boost/bind.hpp>
#if BOOST_VERSION < 103500 #if BOOST_VERSION < 103500
#include <asio/ssl.hpp> #include <asio/ssl.hpp>
#else #else
#include <boost/asio/ssl.hpp> #include <boost/asio/ssl.hpp>
#endif #endif
// openssl seems to believe it owns // openssl seems to believe it owns
// this name in every single scope // this name in every single scope
#undef set_key #undef set_key
namespace libtorrent { namespace libtorrent {
template <class Stream> template <class Stream>
class ssl_stream class ssl_stream
{ {
public: public:
explicit ssl_stream(io_service& io_service) explicit ssl_stream(io_service& io_service, asio::ssl::context& ctx)
: m_context(io_service, asio::ssl::context::sslv23_client) : m_sock(io_service, ctx)
, m_sock(io_service, m_context)
{ {
error_code ec;
m_context.set_verify_mode(asio::ssl::context::verify_none, e
c);
} }
typedef Stream next_layer_type; typedef typename asio::ssl::stream<Stream> sock_type;
typedef typename sock_type::next_layer_type next_layer_type;
typedef typename Stream::lowest_layer_type lowest_layer_type; typedef typename Stream::lowest_layer_type lowest_layer_type;
typedef typename Stream::endpoint_type endpoint_type; typedef typename Stream::endpoint_type endpoint_type;
typedef typename Stream::protocol_type protocol_type; typedef typename Stream::protocol_type protocol_type;
typedef typename asio::ssl::stream<Stream> sock_type;
void set_host_name(std::string name)
{
#if OPENSSL_VERSION_NUMBER >= 0x90812f
SSL_set_tlsext_host_name(m_sock.native_handle(), name.c_str(
));
#endif
}
template <class T>
void set_verify_callback(T const& fun, error_code& ec)
{ m_sock.set_verify_callback(fun, ec); }
#if BOOST_VERSION >= 104700
SSL* native_handle() { return m_sock.native_handle(); }
#endif
typedef boost::function<void(error_code const&)> handler_type; typedef boost::function<void(error_code const&)> handler_type;
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)
{ {
// the connect is split up in the following steps: // the connect is split up in the following steps:
// 1. connect to peer // 1. connect to peer
// 2. perform SSL client handshake // 2. perform SSL client handshake
// to avoid unnecessary copying of the handler, // to avoid unnecessary copying of the handler,
// store it in a shared_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)) ;
m_sock.next_layer().async_connect(endpoint m_sock.next_layer().async_connect(endpoint
, boost::bind(&ssl_stream::connected, this, _1, h)); , boost::bind(&ssl_stream::connected, this, _1, h));
} }
template <class Handler>
void async_accept_handshake(Handler const& handler)
{
// this is used for accepting SSL connections
boost::shared_ptr<handler_type> h(new handler_type(handler))
;
m_sock.async_handshake(asio::ssl::stream_base::server
, boost::bind(&ssl_stream::handshake, this, _1, h));
}
void accept_handshake(error_code& ec)
{
// this is used for accepting SSL connections
m_sock.handshake(asio::ssl::stream_base::server, ec);
}
template <class Handler>
void async_shutdown(Handler const& handler)
{
m_sock.async_shutdown(handler);
}
void shutdown(error_code& ec)
{
m_sock.shutdown(ec);
}
template <class Mutable_Buffers, class Handler> template <class Mutable_Buffers, class Handler>
void async_read_some(Mutable_Buffers const& buffers, Handler const& handler) void async_read_some(Mutable_Buffers const& buffers, Handler const& handler)
{ {
m_sock.async_read_some(buffers, handler); m_sock.async_read_some(buffers, handler);
} }
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 )
{ {
return m_sock.read_some(buffers, ec); return m_sock.read_some(buffers, ec);
} }
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
template <class SettableSocketOption>
void set_option(SettableSocketOption const& opt)
{
m_sock.next_layer().set_option(opt);
}
#endif
template <class SettableSocketOption>
error_code set_option(SettableSocketOption const& opt, error_code& e
c)
{
return m_sock.next_layer().set_option(opt, ec);
}
#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)
{ {
return m_sock.read_some(buffers); return m_sock.read_some(buffers);
} }
template <class IO_Control_Command> template <class IO_Control_Command>
void io_control(IO_Control_Command& ioc) void io_control(IO_Control_Command& ioc)
{ {
m_sock.next_layer().io_control(ioc); m_sock.next_layer().io_control(ioc);
skipping to change at line 122 skipping to change at line 175
{ {
m_sock.next_layer().io_control(ioc, ec); m_sock.next_layer().io_control(ioc, ec);
} }
template <class Const_Buffers, class Handler> template <class Const_Buffers, class Handler>
void async_write_some(Const_Buffers const& buffers, Handler const& h andler) void async_write_some(Const_Buffers const& buffers, Handler const& h andler)
{ {
m_sock.async_write_some(buffers, handler); m_sock.async_write_some(buffers, handler);
} }
template <class Const_Buffers>
std::size_t write_some(Const_Buffers const& buffers, error_code& ec)
{
return m_sock.write_some(buffers, ec);
}
#ifndef BOOST_NO_EXCEPTIONS
std::size_t available() const
{ return const_cast<sock_type&>(m_sock).next_layer().available(); }
#endif
std::size_t available(error_code& ec) const
{ return const_cast<sock_type&>(m_sock).next_layer().available(ec);
}
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
void bind(endpoint_type const& endpoint) void bind(endpoint_type const& endpoint)
{ {
m_sock.next_layer().bind(endpoint); m_sock.next_layer().bind(endpoint);
} }
#endif #endif
void bind(endpoint_type const& endpoint, error_code& ec) void bind(endpoint_type const& endpoint, error_code& ec)
{ {
m_sock.next_layer().bind(endpoint, ec); m_sock.next_layer().bind(endpoint, ec);
skipping to change at line 221 skipping to change at line 288
m_sock.async_handshake(asio::ssl::stream_base::client m_sock.async_handshake(asio::ssl::stream_base::client
, boost::bind(&ssl_stream::handshake, this, _1, h)); , boost::bind(&ssl_stream::handshake, this, _1, h));
} }
void handshake(error_code const& e, boost::shared_ptr<handler_type> h) void handshake(error_code const& e, boost::shared_ptr<handler_type> h)
{ {
(*h)(e); (*h)(e);
} }
asio::ssl::context m_context;
asio::ssl::stream<Stream> m_sock; asio::ssl::stream<Stream> m_sock;
}; };
} }
#endif #endif
 End of changes. 9 change blocks. 
9 lines changed or deleted 78 lines changed or added


 stat.hpp   stat.hpp 
skipping to change at line 46 skipping to change at line 46
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <assert.h> #include <assert.h>
#include <cstring> #include <cstring>
#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/assert.hpp" #include "libtorrent/assert.hpp"
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T
ORRENT_ERROR_LOGGING
#include "libtorrent/debug.hpp" // for logger
#endif
namespace libtorrent namespace libtorrent
{ {
class TORRENT_EXPORT stat_channel class TORRENT_EXTRA_EXPORT stat_channel
{ {
friend class invariant_access;
public: public:
enum { history = 10 };
stat_channel() stat_channel()
: m_counter(0) : m_counter(0)
, m_5_sec_average(0)
, m_30_sec_average(0)
, m_total_counter(0) , m_total_counter(0)
, m_rate_sum(0) {}
{
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_counter >= 0);
TORRENT_ASSERT(m_total_counter >= 0); TORRENT_ASSERT(m_total_counter >= 0);
TORRENT_ASSERT(s.m_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_counter >= 0);
TORRENT_ASSERT(m_total_counter >= 0); TORRENT_ASSERT(m_total_counter >= 0);
skipping to change at line 85 skipping to change at line 86
TORRENT_ASSERT(count >= 0); TORRENT_ASSERT(count >= 0);
m_counter += count; m_counter += count;
TORRENT_ASSERT(m_counter >= 0); TORRENT_ASSERT(m_counter >= 0);
m_total_counter += count; m_total_counter += count;
TORRENT_ASSERT(m_total_counter >= 0); TORRENT_ASSERT(m_total_counter >= 0);
} }
// should be called once every second // should be called once every second
void second_tick(int tick_interval_ms); void second_tick(int tick_interval_ms);
int rate() const { return m_rate_sum / history; } int rate() const { return m_5_sec_average; }
size_type rate_sum() const { return m_rate_sum; } int low_pass_rate() const { return m_30_sec_average; }
size_type total() const { return m_total_counter; } size_type total() const { return m_total_counter; }
void offset(size_type c) void offset(size_type c)
{ {
TORRENT_ASSERT(c >= 0); TORRENT_ASSERT(c >= 0);
TORRENT_ASSERT(m_total_counter >= 0); TORRENT_ASSERT(m_total_counter >= 0);
m_total_counter += c; m_total_counter += c;
TORRENT_ASSERT(m_total_counter >= 0); TORRENT_ASSERT(m_total_counter >= 0);
} }
size_type counter() const { return m_counter; } int counter() const { return m_counter; }
void clear() void clear()
{ {
std::memset(m_rate_history, 0, sizeof(m_rate_history ));
m_counter = 0; m_counter = 0;
m_5_sec_average = 0;
m_30_sec_average = 0;
m_total_counter = 0; m_total_counter = 0;
m_rate_sum = 0;
} }
private: private:
#ifdef TORRENT_DEBUG
void check_invariant() const
{
size_type sum = 0;
for (int i = 0; i < history; ++i) sum += m_rate_hist
ory[i];
TORRENT_ASSERT(m_rate_sum == sum);
TORRENT_ASSERT(m_total_counter >= 0);
}
#endif
// history of rates a few seconds back
int m_rate_history[history];
// the accumulator for this second. // the accumulator for this second.
int m_counter; int m_counter;
// sliding average
int m_5_sec_average;
int m_30_sec_average;
// total counters // total counters
size_type m_total_counter; size_type m_total_counter;
// sum of all elements in m_rate_history
size_type m_rate_sum;
}; };
class TORRENT_EXPORT stat class TORRENT_EXTRA_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) void sent_syn(bool ipv6)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
m_stat[upload_ip_protocol].add(ipv6 ? 60 : 40); m_stat[upload_ip_protocol].add(ipv6 ? 60 : 40);
#endif
} }
void received_synack(bool ipv6) void received_synack(bool ipv6)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
// we received SYN-ACK and also sent ACK back // we received SYN-ACK and also sent ACK back
m_stat[download_ip_protocol].add(ipv6 ? 60 : 40); m_stat[download_ip_protocol].add(ipv6 ? 60 : 40);
m_stat[upload_ip_protocol].add(ipv6 ? 60 : 40); m_stat[upload_ip_protocol].add(ipv6 ? 60 : 40);
#endif
} }
void received_dht_bytes(int bytes) void received_dht_bytes(int bytes)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
TORRENT_ASSERT(bytes >= 0); TORRENT_ASSERT(bytes >= 0);
m_stat[download_dht_protocol].add(bytes); m_stat[download_dht_protocol].add(bytes);
#endif
} }
void sent_dht_bytes(int bytes) void sent_dht_bytes(int bytes)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
TORRENT_ASSERT(bytes >= 0); TORRENT_ASSERT(bytes >= 0);
m_stat[upload_dht_protocol].add(bytes); m_stat[upload_dht_protocol].add(bytes);
#endif
} }
void received_tracker_bytes(int bytes) void received_tracker_bytes(int bytes)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
TORRENT_ASSERT(bytes >= 0); TORRENT_ASSERT(bytes >= 0);
m_stat[download_tracker_protocol].add(bytes); m_stat[download_tracker_protocol].add(bytes);
#endif
} }
void sent_tracker_bytes(int bytes) void sent_tracker_bytes(int bytes)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
TORRENT_ASSERT(bytes >= 0); TORRENT_ASSERT(bytes >= 0);
m_stat[upload_tracker_protocol].add(bytes); m_stat[upload_tracker_protocol].add(bytes);
#endif
} }
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);
} }
skipping to change at line 200 skipping to change at line 201
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);
} }
// and IP packet was received or sent // and IP packet was received or sent
// account for the overhead caused by it // account for the overhead caused by it
void trancieve_ip_packet(int bytes_transferred, bool ipv6) void trancieve_ip_packet(int bytes_transferred, bool ipv6)
{ {
#ifndef TORRENT_DISABLE_FULL_STATS
// one TCP/IP packet header for the packet // one TCP/IP packet header for the packet
// sent or received, and one for the ACK // sent or received, and one for the ACK
// The IPv4 header is 20 bytes // The IPv4 header is 20 bytes
// and IPv6 header is 40 bytes // and IPv6 header is 40 bytes
const int header = (ipv6 ? 40 : 20) + 20; const int header = (ipv6 ? 40 : 20) + 20;
const int mtu = 1500; const int mtu = 1500;
const int packet_size = mtu - header; const int packet_size = mtu - header;
const int overhead = (std::max)(1, (bytes_transferre d + packet_size - 1) / packet_size) * header; const int overhead = (std::max)(1, (bytes_transferre d + packet_size - 1) / packet_size) * header;
m_stat[download_ip_protocol].add(overhead); m_stat[download_ip_protocol].add(overhead);
m_stat[upload_ip_protocol].add(overhead); m_stat[upload_ip_protocol].add(overhead);
#endif
} }
#ifndef TORRENT_DISABLE_FULL_STATS
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 upload_dht() const { return m_stat[upload_dht_protocol]. counter(); }
int download_dht() const { return m_stat[download_dht_protoc ol].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 download_tracker() const { return m_stat[download_tracke r_protocol].counter(); }
int upload_tracker() const { return m_stat[upload_tracker_pr otocol].counter(); } int upload_tracker() const { return m_stat[upload_tracker_pr otocol].counter(); }
#else
int upload_ip_overhead() const { return 0; }
int download_ip_overhead() const { return 0; }
int upload_dht() const { return 0; }
int download_dht() const { return 0; }
int download_tracker() const { return 0; }
int upload_tracker() const { return 0; }
#endif
// should be called once every second // should be called once every second
void second_tick(int tick_interval_ms) 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_ms); m_stat[i].second_tick(tick_interval_ms);
} }
int low_pass_upload_rate() const
{
return m_stat[upload_payload].low_pass_rate()
+ m_stat[upload_protocol].low_pass_rate()
#ifndef TORRENT_DISABLE_FULL_STATS
+ m_stat[upload_ip_protocol].low_pass_rate()
+ m_stat[upload_dht_protocol].low_pass_rate(
)
+ m_stat[upload_tracker_protocol].low_pass_r
ate()
#endif
;
}
int low_pass_download_rate() const
{
return m_stat[download_payload].low_pass_rate()
+ m_stat[download_protocol].low_pass_rate()
#ifndef TORRENT_DISABLE_FULL_STATS
+ m_stat[download_ip_protocol].low_pass_rate
()
+ m_stat[download_dht_protocol].low_pass_rat
e()
+ m_stat[download_tracker_protocol].low_pass
_rate()
#endif
;
}
int upload_rate() const int upload_rate() const
{ {
return (m_stat[upload_payload].rate_sum() return m_stat[upload_payload].rate()
+ m_stat[upload_protocol].rate_sum() + m_stat[upload_protocol].rate()
+ m_stat[upload_ip_protocol].rate_sum() #ifndef TORRENT_DISABLE_FULL_STATS
+ m_stat[upload_dht_protocol].rate_sum()) + m_stat[upload_ip_protocol].rate()
/ stat_channel::history; + m_stat[upload_dht_protocol].rate()
+ m_stat[upload_tracker_protocol].rate()
#endif
;
} }
int download_rate() const int download_rate() const
{ {
return (m_stat[download_payload].rate_sum() return m_stat[download_payload].rate()
+ m_stat[download_protocol].rate_sum() + m_stat[download_protocol].rate()
+ m_stat[download_ip_protocol].rate_sum() #ifndef TORRENT_DISABLE_FULL_STATS
+ m_stat[download_dht_protocol].rate_sum()) + m_stat[download_ip_protocol].rate()
/ stat_channel::history; + m_stat[download_dht_protocol].rate()
+ m_stat[download_tracker_protocol].rate()
#endif
;
} }
size_type total_upload() const size_type total_upload() const
{ {
return m_stat[upload_payload].total() return m_stat[upload_payload].total()
+ m_stat[upload_protocol].total() + m_stat[upload_protocol].total()
#ifndef TORRENT_DISABLE_FULL_STATS
+ m_stat[upload_ip_protocol].total() + m_stat[upload_ip_protocol].total()
+ m_stat[upload_dht_protocol].total() + m_stat[upload_dht_protocol].total()
+ m_stat[upload_tracker_protocol].total(); + m_stat[upload_tracker_protocol].total()
#endif
;
} }
size_type total_download() const size_type total_download() const
{ {
return m_stat[download_payload].total() return m_stat[download_payload].total()
+ m_stat[download_protocol].total() + m_stat[download_protocol].total()
#ifndef TORRENT_DISABLE_FULL_STATS
+ m_stat[download_ip_protocol].total() + m_stat[download_ip_protocol].total()
+ m_stat[download_dht_protocol].total() + m_stat[download_dht_protocol].total()
+ m_stat[download_tracker_protocol].total(); + m_stat[download_tracker_protocol].total()
#endif
;
} }
int upload_payload_rate() const int upload_payload_rate() const
{ return m_stat[upload_payload].rate(); } { return m_stat[upload_payload].rate(); }
int download_payload_rate() const 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
skipping to change at line 291 skipping to change at line 339
// 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)
{ {
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 int last_payload_downloaded() const
{ return m_stat[download_payload].counter(); } { return m_stat[download_payload].counter(); }
size_type last_payload_uploaded() const int last_payload_uploaded() const
{ return m_stat[upload_payload].counter(); } { return m_stat[upload_payload].counter(); }
size_type last_protocol_downloaded() const int last_protocol_downloaded() const
{ return m_stat[download_protocol].counter(); } { return m_stat[download_protocol].counter(); }
size_type last_protocol_uploaded() const int last_protocol_uploaded() const
{ return m_stat[upload_protocol].counter(); } { return m_stat[upload_protocol].counter(); }
// 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,
download_payload,
download_protocol,
#ifndef TORRENT_DISABLE_FULL_STATS
upload_ip_protocol, upload_ip_protocol,
upload_dht_protocol, upload_dht_protocol,
upload_tracker_protocol, upload_tracker_protocol,
download_payload,
download_protocol,
download_ip_protocol, download_ip_protocol,
download_dht_protocol, download_dht_protocol,
download_tracker_protocol, download_tracker_protocol,
#endif
num_channels num_channels
}; };
void clear() void clear()
{ {
for (int i = 0; i < num_channels; ++i) for (int i = 0; i < num_channels; ++i)
m_stat[i].clear(); m_stat[i].clear();
} }
stat_channel const& operator[](int i) const stat_channel const& operator[](int i) const
 End of changes. 45 change blocks. 
49 lines changed or deleted 103 lines changed or added


 storage.hpp   storage.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_STORAGE_HPP_INCLUDE #ifndef TORRENT_STORAGE_HPP_INCLUDE
#define TORRENT_STORAGE_HPP_INCLUDE #define TORRENT_STORAGE_HPP_INCLUDE
#include <vector> #include <vector>
#include <bitset> #include <sys/types.h>
#include <sys/stat.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/function.hpp> #include <boost/function/function2.hpp>
#include <boost/limits.hpp> #include <boost/limits.hpp>
#include <boost/thread.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/filesystem/path.hpp>
#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/file.hpp" #include "libtorrent/file.hpp"
#include "libtorrent/disk_buffer_holder.hpp" #include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/storage_defs.hpp"
#include "libtorrent/allocator.hpp"
namespace libtorrent namespace libtorrent
{ {
namespace aux
{
struct piece_checker_data;
}
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_pool; struct disk_buffer_pool;
struct session_settings; struct session_settings;
enum storage_mode_t TORRENT_EXTRA_EXPORT std::vector<std::pair<size_type, std::time_t> >
{ get_filesizes(
storage_mode_allocate = 0,
storage_mode_sparse,
storage_mode_compact
};
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); , std::string const& p);
TORRENT_EXPORT bool match_filesizes( TORRENT_EXTRA_EXPORT bool match_filesizes(
file_storage const& t file_storage const& t
, fs::path p , std::string const& 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);
/*
struct TORRENT_EXPORT file_allocation_failed: std::exception struct TORRENT_EXTRA_EXPORT file_allocation_failed: std::exception
{ {
file_allocation_failed(const char* error_msg): m_msg(error_m sg) {} file_allocation_failed(const char* error_msg): m_msg(error_m sg) {}
virtual const char* what() const throw() { return m_msg.c_st r(); } virtual const char* what() const throw() { return m_msg.c_st r(); }
virtual ~file_allocation_failed() throw() {} virtual ~file_allocation_failed() throw() {}
std::string m_msg; std::string m_msg;
}; };
*/
struct TORRENT_EXPORT partial_hash struct TORRENT_EXTRA_EXPORT partial_hash
{ {
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
{ {
skipping to change at line 128 skipping to change at line 117
// 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 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); virtual int writev(file::iovec_t const* bufs, int slot, int offset, int num_bufs);
virtual void hint_read(int slot, int offset, int len) {}
// 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; virtual size_type physical_offset(int slot, int offset) = 0;
// returns the end of the sparse region the slot 'start' // returns the end of the sparse region the slot 'start'
// resides in i.e. the next slot with content. If start // resides in i.e. the next slot with content. If start
// is not in a sparse region, start itself is returned // is not in a sparse region, start itself is returned
virtual int sparse_end(int start) const { return start; } 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(std::string const& save_path) = 0;
// verify storage dependent fast resume entries // verify storage dependent fast resume entries
virtual bool verify_resume_data(lazy_entry const& rd, error_ code& 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;
skipping to change at line 173 skipping to change at line 163
// 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;
virtual void finalize_file(int file) {}
disk_buffer_pool* disk_pool() { return m_disk_pool; } disk_buffer_pool* disk_pool() { return m_disk_pool; }
session_settings const& settings() const { return *m_setting s; } session_settings const& settings() const { return *m_setting s; }
void set_error(boost::filesystem::path const& file, error_co void set_error(std::string const& file, error_code const& ec
de const& ec) const ) const;
{
m_error_file = file.string();
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(); } virtual void clear_error() { m_error = error_code(); m_error _file.resize(0); }
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; disk_buffer_pool* m_disk_pool;
session_settings* m_settings; session_settings* m_settings;
}; };
typedef storage_interface* (*storage_constructor_type)( class TORRENT_EXPORT default_storage : public storage_interface, boo
file_storage const&, file_storage const*, fs::path const&, f st::noncopyable
ile_pool&); {
public:
default_storage(file_storage const& fs, file_storage const*
mapped, std::string const& path
, file_pool& fp, std::vector<boost::uint8_t> const&
file_prio);
~default_storage();
TORRENT_EXPORT storage_interface* default_storage_constructor( void finalize_file(int file);
file_storage const&, file_storage const* mapped, fs::path co bool has_any_file();
nst&, file_pool&); bool rename_file(int index, std::string const& new_filename)
;
bool release_files();
bool delete_files();
bool initialize(bool allocate_files);
bool move_storage(std::string const& save_path);
int read(char* buf, int slot, int offset, int size);
int write(char const* buf, int slot, int offset, int size);
int sparse_end(int start) const;
void hint_read(int slot, int offset, int len);
int readv(file::iovec_t const* bufs, int slot, int offset, i
nt num_bufs);
int writev(file::iovec_t const* buf, int slot, int offset, i
nt num_bufs);
size_type physical_offset(int slot, int offset);
bool move_slot(int src_slot, int dst_slot);
bool swap_slots(int slot1, int slot2);
bool swap_slots3(int slot1, int slot2, int slot3);
bool verify_resume_data(lazy_entry const& rd, error_code& er
ror);
bool write_resume_data(entry& rd) const;
TORRENT_EXPORT storage_interface* disabled_storage_constructor( // this identifies a read or write operation
file_storage const&, file_storage const* mapped, fs::path co // so that default_storage::readwritev() knows what to
nst&, file_pool&); // do when it's actually touching the file
struct fileop
{
size_type (file::*regular_op)(size_type file_offset
, file::iovec_t const* bufs, int num_bufs, e
rror_code& ec);
size_type (default_storage::*unaligned_op)(boost::in
trusive_ptr<file> const& f
, size_type file_offset, file::iovec_t const
* bufs, int num_bufs
, error_code& ec);
int cache_setting;
int mode;
};
void delete_one_file(std::string const& p);
int readwritev(file::iovec_t const* bufs, int slot, int offs
et
, int num_bufs, fileop const&);
size_type read_unaligned(boost::intrusive_ptr<file> const& f
ile_handle
, size_type file_offset, file::iovec_t const* bufs,
int num_bufs, error_code& ec);
size_type write_unaligned(boost::intrusive_ptr<file> const&
file_handle
, size_type file_offset, file::iovec_t const* bufs,
int num_bufs, error_code& ec);
file_storage const& files() const { return m_mapped_files?*m
_mapped_files:m_files; }
boost::scoped_ptr<file_storage> m_mapped_files;
file_storage const& m_files;
// helper function to open a file in the file pool with the
right mode
boost::intrusive_ptr<file> open_file(file_storage::iterator
fe, int mode
, error_code& ec) const;
std::vector<boost::uint8_t> m_file_priority;
std::string m_save_path;
// the file pool is typically stored in
// the session, to make all storage
// instances use the same pool
file_pool& m_pool;
int m_page_size;
bool m_allocate_files;
};
// this storage implementation does not write anything to disk
// and it pretends to read, and just leaves garbage in the buffers
// this is useful when simulating many clients on the same machine
// or when running stress tests and want to take the cost of the
// disk I/O out of the picture. This cannot be used for any kind
// of normal bittorrent operation, since it will just send garbage
// to peers and throw away all the data it downloads. It would end
// up being banned immediately
class disabled_storage : public storage_interface, boost::noncopyabl
e
{
public:
disabled_storage(int piece_size) : m_piece_size(piece_size)
{}
bool has_any_file() { return false; }
bool rename_file(int index, std::string const& new_filename)
{ return false; }
bool release_files() { return false; }
bool delete_files() { return false; }
bool initialize(bool allocate_files) { return false; }
bool move_storage(std::string const& save_path) { return tru
e; }
int read(char* buf, int slot, int offset, int size) { return
size; }
int write(char const* buf, int slot, int offset, int size) {
return size; }
size_type physical_offset(int slot, int offset) { return 0;
}
int readv(file::iovec_t const* bufs, int slot, int offset, i
nt num_bufs);
int writev(file::iovec_t const* bufs, int slot, int offset,
int num_bufs);
bool move_slot(int src_slot, int dst_slot) { return false; }
bool swap_slots(int slot1, int slot2) { return false; }
bool swap_slots3(int slot1, int slot2, int slot3) { return f
alse; }
bool verify_resume_data(lazy_entry const& rd, error_code& er
ror) { return false; }
bool write_resume_data(entry& rd) const { return false; }
int m_piece_size;
};
struct disk_io_thread; struct disk_io_thread;
class TORRENT_EXPORT piece_manager class TORRENT_EXTRA_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:
piece_manager( piece_manager(
boost::shared_ptr<void> const& torrent boost::shared_ptr<void> const& torrent
, boost::intrusive_ptr<torrent_info const> info , boost::intrusive_ptr<torrent_info const> info
, fs::path const& path , std::string const& path
, file_pool& fp , file_pool& fp
, disk_io_thread& io , disk_io_thread& io
, storage_constructor_type sc , storage_constructor_type sc
, storage_mode_t sm); , storage_mode_t sm
, std::vector<boost::uint8_t> const& file_prio);
~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_finalize_file(int file);
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 cache_line_size = 0
, int cache_expiry = 0);
void async_read_and_hash( void async_read_and_hash(
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 cache_expiry = 0);
void async_write( void async_cache(int piece
, boost::function<void(int, disk_io_job const&)> con
st& handler
, int cache_expiry = 0);
// returns the write queue size
int 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&)>());
void abort_disk_io(); void abort_disk_io();
void async_clear_read_cache( void async_clear_read_cache(
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&)>());
void async_delete_files( void async_delete_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&)>());
void async_move_storage(fs::path const& p void async_move_storage(std::string const& p
, boost::function<void(int, disk_io_job const&)> con st& handler); , boost::function<void(int, disk_io_job const&)> con st& handler);
void async_save_resume_data( void async_save_resume_data(
boost::function<void(int, disk_io_job const&)> const & handler); boost::function<void(int, disk_io_job const&)> const & handler);
enum return_t enum return_t
{ {
// return values from check_fastresume and check_fil es // return values from check_fastresume and check_fil es
no_error = 0, no_error = 0,
need_full_check = -1, need_full_check = -1,
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; std::string save_path() const;
bool verify_resume_data(lazy_entry const& rd, error_code& e) bool verify_resume_data(lazy_entry const& rd, error_code& e)
{ return m_storage->verify_resume_data(rd, e); } { return m_storage->verify_resume_data(rd, e); }
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(); }
skipping to change at line 319 skipping to change at line 407
// 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, error_code& error ); 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, error_co de& error); int check_files(int& current_slot, int& have_piece, error_co de& error);
#ifndef TORRENT_NO_DEPRECATE
bool compact_allocation() const bool compact_allocation() const
{ return m_storage_mode == storage_mode_compact; } { return m_storage_mode == storage_mode_compact; }
#endif
#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_impl(int num_slots, mutex::scoped_lock& l, bool abort_on_disk = false);
// updates the ph.h hasher object with the data at the given slot // updates the ph.h hasher object with the data at the given slot
// and optionally a 'small hash' as well, the hash for // and optionally a 'small hash' as well, the hash for
// the partial slot. Returns the number of bytes read // the partial slot. Returns the number of bytes read
int hash_for_slot(int slot, partial_hash& h, int piece_size int hash_for_slot(int slot, partial_hash& h, int piece_size
, int small_piece_size = 0, sha1_hash* small_hash = 0); , int small_piece_size = 0, sha1_hash* small_hash = 0);
void hint_read_impl(int piece_index, int offset, int size);
int read_impl( int read_impl(
file::iovec_t* bufs file::iovec_t* bufs
, int piece_index , int piece_index
, int offset , int offset
, int num_bufs); , int num_bufs);
int write_impl( int write_impl(
file::iovec_t* bufs file::iovec_t* bufs
, int piece_index , int piece_index
, int offset , int offset
, int num_bufs); , int num_bufs);
size_type physical_offset(int piece_index, int offset); size_type physical_offset(int piece_index, int offset);
void finalize_file(int index);
// returns the number of pieces left in the // returns the number of pieces left in the
// file currently being checked // file currently being checked
int skip_file() const; int skip_file() const;
// -1=error 0=ok >0=skip this many pieces // -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(
sha1_hash const& large_hash sha1_hash const& large_hash
, sha1_hash const& small_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* readback = 0);
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); }
int move_storage_impl(fs::path const& save_path); int move_storage_impl(std::string const& save_path);
int allocate_slot_for_piece(int piece_index); int allocate_slot_for_piece(int piece_index);
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#ifdef TORRENT_STORAGE_DEBUG #ifdef TORRENT_STORAGE_DEBUG
void debug_log() const; void debug_log() const;
#endif #endif
#endif #endif
boost::intrusive_ptr<torrent_info const> m_info; boost::intrusive_ptr<torrent_info const> m_info;
file_storage const& m_files; file_storage const& m_files;
skipping to change at line 406 skipping to change at line 500
enum enum
{ {
unallocated = -1, // the slot is unallocated unallocated = -1, // the slot is unallocated
unassigned = -2 // the slot is allocated but not a ssigned to a piece unassigned = -2 // the slot is allocated but not a ssigned to a piece
}; };
// maps slots to piece indices, if a slot doesn't have a pie ce // maps slots to piece indices, if a slot doesn't have a pie ce
// it can either be 'unassigned' or 'unallocated' // it can either be 'unassigned' or 'unallocated'
std::vector<int> m_slot_to_piece; std::vector<int> m_slot_to_piece;
fs::path m_save_path; std::string m_save_path;
mutable boost::recursive_mutex m_mutex; mutable mutex m_mutex;
enum { enum {
// the default initial state // the default initial state
state_none, state_none,
// the file checking is complete // the file checking is complete
state_finished, state_finished,
// checking the files // checking the files
state_full_check, state_full_check,
// move pieces to their final position // move pieces to their final position
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
disk_buffer_holder m_scratch_buffer; aligned_holder m_scratch_buffer;
disk_buffer_holder m_scratch_buffer2; aligned_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 // the last piece we wrote to or read from
int m_last_piece; int m_last_piece;
// 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;
 End of changes. 41 change blocks. 
61 lines changed or deleted 182 lines changed or added


 time.hpp   time.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_TIME_HPP_INCLUDED #ifndef TORRENT_TIME_HPP_INCLUDED
#define TORRENT_TIME_HPP_INCLUDED #define TORRENT_TIME_HPP_INCLUDED
#include <ctime>
#include <boost/version.hpp> #include <boost/version.hpp>
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/ptime.hpp"
#ifndef _WIN32
#include <unistd.h>
#endif
namespace libtorrent
{
inline char const* time_now_string()
{
time_t t = std::time(0);
tm* timeinfo = std::localtime(&t);
static char str[200];
std::strftime(str, 200, "%b %d %X", timeinfo);
return str;
}
std::string log_time();
}
#if defined TORRENT_USE_BOOST_DATE_TIME
#include <boost/date_time/posix_time/posix_time_types.hpp>
#include "libtorrent/assert.hpp"
namespace libtorrent
{
typedef boost::posix_time::ptime ptime;
typedef boost::posix_time::time_duration time_duration;
inline ptime time_now_hires()
{ return boost::posix_time::microsec_clock::universal_time(); }
inline ptime min_time()
{ return boost::posix_time::ptime(boost::posix_time::min_date_time);
}
inline ptime max_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 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 minutes(int s) { return boost::posix_time::minu
tes(s); }
inline time_duration hours(int s) { return boost::posix_time::hours(
s); }
inline int total_seconds(time_duration td)
{ return td.total_seconds(); }
inline int total_milliseconds(time_duration td)
{ return td.total_milliseconds(); }
inline boost::int64_t total_microseconds(time_duration td)
{ return td.total_microseconds(); }
}
#else // TORRENT_USE_BOOST_DATE_TIME
#if BOOST_VERSION < 103500
#include <asio/time_traits.hpp>
#else
#include <boost/asio/time_traits.hpp>
#endif
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp" #include <string>
namespace libtorrent namespace libtorrent
{ {
// libtorrent time_duration type TORRENT_EXPORT char const* time_now_string();
struct time_duration TORRENT_EXPORT std::string log_time();
{
time_duration() {}
time_duration operator/(int rhs) const { return time_duratio
n(diff / rhs); }
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) { 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;
};
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)
{ return lhs.diff < rhs.diff; }
inline bool operator<=(time_duration lhs, time_duration rhs)
{ return lhs.diff <= rhs.diff; }
inline bool operator>(time_duration lhs, time_duration rhs)
{ return lhs.diff > rhs.diff; }
inline bool operator>=(time_duration lhs, time_duration rhs)
{ 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
struct ptime
{
ptime() {}
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; }
boost::uint64_t time;
};
inline bool operator>(ptime lhs, ptime rhs)
{ return lhs.time > rhs.time; }
inline bool operator>=(ptime lhs, ptime rhs)
{ return lhs.time >= rhs.time; }
inline bool operator<=(ptime lhs, ptime rhs)
{ return lhs.time <= rhs.time; }
inline bool operator<(ptime lhs, ptime rhs)
{ return lhs.time < rhs.time; }
inline bool operator!=(ptime lhs, ptime rhs)
{ return lhs.time != rhs.time;}
inline bool operator==(ptime lhs, ptime rhs)
{ return lhs.time == rhs.time;}
inline time_duration operator-(ptime lhs, ptime rhs)
{ return time_duration(lhs.time - rhs.time); }
inline ptime operator+(ptime lhs, time_duration rhs)
{ return ptime(lhs.time + rhs.diff); }
inline ptime operator+(time_duration lhs, ptime rhs)
{ return ptime(rhs.time + lhs.diff); }
inline ptime operator-(ptime lhs, time_duration rhs)
{ return ptime(lhs.time - rhs.diff); }
ptime time_now_hires();
inline ptime min_time() { return ptime(0); }
inline ptime max_time() { return ptime((std::numeric_limits<boost::u
int64_t>::max)()); }
int total_seconds(time_duration td);
int total_milliseconds(time_duration td);
boost::int64_t total_microseconds(time_duration td);
}
// asio time_traits
#if BOOST_VERSION >= 103500
namespace boost {
#endif
namespace asio
{
template<>
struct time_traits<libtorrent::ptime>
{
typedef libtorrent::ptime time_type;
typedef libtorrent::time_duration duration_type;
static time_type now()
{ return time_type(libtorrent::time_now_hires()); }
static time_type add(time_type t, duration_type d)
{ return time_type(t.time + d.diff);}
static duration_type subtract(time_type t1, time_type t2)
{ return duration_type(t1 - t2); }
static bool less_than(time_type t1, time_type t2)
{ return t1 < t2; }
static boost::posix_time::time_duration to_posix_duration(
duration_type d)
{ return boost::posix_time::microseconds(libtorrent::total_m
icroseconds(d)); }
};
}
#if BOOST_VERSION >= 103500
}
#endif
#if defined TORRENT_USE_ABSOLUTE_TIME
#include <mach/mach_time.h>
#include <boost/cstdint.hpp>
#include "libtorrent/assert.hpp"
// high precision timer for darwin intel and ppc TORRENT_EXPORT ptime time_now_hires();
TORRENT_EXPORT ptime min_time();
TORRENT_EXPORT ptime max_time();
namespace libtorrent #if defined TORRENT_USE_BOOST_DATE_TIME
{
inline int total_seconds(time_duration td)
{
return td.diff / 1000000;
}
inline int total_milliseconds(time_duration td)
{
return td.diff / 1000;
}
inline boost::int64_t total_microseconds(time_duration td)
{
return td.diff;
}
inline ptime time_now_hires() TORRENT_EXPORT time_duration seconds(int s);
{ TORRENT_EXPORT time_duration milliseconds(int s);
static mach_timebase_info_data_t timebase_info = {0,0}; TORRENT_EXPORT time_duration microsec(int s);
if (timebase_info.denom == 0) TORRENT_EXPORT time_duration minutes(int s);
mach_timebase_info(&timebase_info); TORRENT_EXPORT time_duration hours(int s);
boost::uint64_t at = mach_absolute_time();
// make sure we don't overflow
TORRENT_ASSERT((at >= at / 1000 * timebase_info.numer / time
base_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) TORRENT_EXPORT int total_seconds(time_duration td);
{ TORRENT_EXPORT int total_milliseconds(time_duration td);
return time_duration(s); TORRENT_EXPORT boost::int64_t total_microseconds(time_duration td);
}
inline time_duration milliseconds(boost::int64_t s)
{
return time_duration(s * 1000);
}
inline time_duration seconds(boost::int64_t s)
{
return time_duration(s * 1000000);
}
inline time_duration minutes(boost::int64_t s)
{
return time_duration(s * 1000000 * 60);
}
inline time_duration hours(boost::int64_t s)
{
return time_duration(s * 1000000 * 60 * 60);
}
}
#elif defined TORRENT_USE_QUERY_PERFORMANCE_TIMER #elif defined TORRENT_USE_QUERY_PERFORMANCE_TIMER
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include "libtorrent/assert.hpp"
namespace libtorrent
{
namespace aux namespace aux
{ {
inline boost::int64_t performance_counter_to_microseconds(bo TORRENT_EXPORT boost::int64_t performance_counter_to_microse
ost::int64_t pc) conds(boost::int64_t pc);
{ TORRENT_EXPORT boost::int64_t microseconds_to_performance_co
static LARGE_INTEGER performace_counter_frequency = unter(boost::int64_t ms);
{0,0};
if (performace_counter_frequency.QuadPart == 0)
QueryPerformanceFrequency(&performace_counte
r_frequency);
#ifdef TORRENT_DEBUG
// make sure we don't overflow
boost::int64_t ret = (pc * 1000 / performace_counter
_frequency.QuadPart) * 1000;
TORRENT_ASSERT((pc >= 0 && pc >= ret) || (pc < 0 &&
pc < ret));
#endif
return (pc * 1000 / performace_counter_frequency.Qua
dPart) * 1000;
}
inline boost::int64_t microseconds_to_performance_counter(bo
ost::int64_t ms)
{
static LARGE_INTEGER performace_counter_frequency =
{0,0};
if (performace_counter_frequency.QuadPart == 0)
QueryPerformanceFrequency(&performace_counte
r_frequency);
#ifdef TORRENT_DEBUG
// make sure we don't overflow
boost::int64_t ret = (ms / 1000) * performace_counte
r_frequency.QuadPart / 1000;
TORRENT_ASSERT((ms >= 0 && ms <= ret)
|| (ms < 0 && ms > ret));
#endif
return (ms / 1000) * performace_counter_frequency.Qu
adPart / 1000;
}
} }
inline int total_seconds(time_duration td) inline int total_seconds(time_duration td)
{ {
return int(aux::performance_counter_to_microseconds(td.diff) return int(aux::performance_counter_to_microseconds(td.diff)
/ 1000000); / 1000000);
} }
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_hires()
{
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
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));
} }
inline time_duration milliseconds(boost::int64_t s) inline time_duration milliseconds(boost::int64_t s)
{ {
return time_duration(aux::microseconds_to_performance_counte r( return time_duration(aux::microseconds_to_performance_counte r(
s * 1000)); s * 1000));
} }
inline time_duration seconds(boost::int64_t s) inline time_duration seconds(boost::int64_t s)
skipping to change at line 341 skipping to change at line 111
{ {
return time_duration(aux::microseconds_to_performance_counte r( return time_duration(aux::microseconds_to_performance_counte r(
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 TORRENT_USE_CLOCK_GETTIME || TORRENT_USE_SYSTEM_TIME || TORRENT_USE_A
BSOLUTE_TIME
#elif defined TORRENT_USE_CLOCK_GETTIME
#include <time.h>
#include "libtorrent/assert.hpp"
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_hires()
{
timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
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);
}
inline time_duration seconds(boost::int64_t s) inline time_duration seconds(boost::int64_t s)
{ { return time_duration(s * 1000000); }
return time_duration(s * 1000000);
}
inline time_duration minutes(boost::int64_t s) inline time_duration minutes(boost::int64_t s)
{ { 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 // TORRENT_USE_CLOCK_GETTIME #endif // TORRENT_USE_CLOCK_GETTIME
#endif // TORRENT_USE_BOOST_DATE_TIME
namespace libtorrent
{
TORRENT_EXPORT ptime const& time_now();
} }
#endif // TORRENT_TIME_HPP_INCLUDED #endif // TORRENT_TIME_HPP_INCLUDED
 End of changes. 23 change blocks. 
325 lines changed or deleted 30 lines changed or added


 torrent.hpp   torrent.hpp 
skipping to change at line 46 skipping to change at line 46
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <set> #include <set>
#include <list> #include <list>
#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/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>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/version.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/torrent_info.hpp" #include "libtorrent/torrent_info.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/policy.hpp" #include "libtorrent/policy.hpp"
#include "libtorrent/tracker_manager.hpp" #include "libtorrent/tracker_manager.hpp"
#include "libtorrent/stat.hpp" #include "libtorrent/stat.hpp"
#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_defs.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" #include "libtorrent/aux_/session_impl.hpp"
#include "libtorrent/deadline_timer.hpp"
#include "libtorrent/union_endpoint.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) class http_parser;
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T
ORRENT_ERROR_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 announce_entry;
struct tracker_request; struct tracker_request;
struct add_torrent_params; struct add_torrent_params;
struct storage_interface;
class bt_peer_connection;
struct listen_socket_t;
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;
// 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_EXTRA_EXPORT torrent: public request_callback
, public boost::enable_shared_from_this<torrent> , public boost::enable_shared_from_this<torrent>
{ {
public: public:
torrent(aux::session_impl& ses, tcp::endpoint const& net_int erface torrent(aux::session_impl& ses, tcp::endpoint const& net_int erface
, int block_size, int seq, add_torrent_params const& , int block_size, int seq, add_torrent_params const&
p); p
, sha1_hash const& info_hash);
~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(); }
// starts the announce timer // starts the announce timer
void start(); void start();
void start_download_url();
#ifndef TORRENT_DISABLE_EXTENSIONS #ifndef TORRENT_DISABLE_EXTENSIONS
void add_extension(boost::shared_ptr<torrent_plugin>); void add_extension(boost::shared_ptr<torrent_plugin>);
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); , void* userdata);
void notify_extension_add_peer(tcp::endpoint const& ip, int src, int flags);
#endif #endif
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool has_peer(peer_connection* p) const bool has_peer(peer_connection* p) const
{ 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();
// find the peer that introduced us to the given endpoint. T
his is
// used when trying to holepunch. We need the introducer so
that we
// can send a rendezvous connect message
bt_peer_connection* find_introducer(tcp::endpoint const& ep)
const;
// if we're connected to a peer at ep, return its peer conne
ction
// only count BitTorrent peers
bt_peer_connection* find_peer(tcp::endpoint const& ep) const
;
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_lock(); void files_checked();
void files_checked(boost::mutex::scoped_lock const&);
void start_checking(); void start_checking();
void start_announcing(); void start_announcing();
void stop_announcing(); void stop_announcing();
void send_share_mode();
void send_upload_only(); void send_upload_only();
void set_share_mode(bool s);
bool share_mode() const { return m_share_mode; }
bool graceful_pause() const { return m_graceful_pause_mode;
}
void set_upload_mode(bool b); void set_upload_mode(bool b);
bool upload_mode() const { return m_upload_mode; } bool upload_mode() const { return m_upload_mode || m_gracefu
bool is_upload_only() const l_pause_mode; }
{ return (is_finished() || upload_mode()) && !super_seeding( bool is_upload_only() const { return is_finished() || upload
); } _mode(); }
int seed_rank(session_settings const& s) const; int seed_rank(session_settings const& s) const;
enum flags_t { overwrite_existing = 1 }; enum flags_t { overwrite_existing = 1 };
void add_piece(int piece, char const* data, int flags = 0); void add_piece(int piece, char const* data, int flags = 0);
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 p); , peer_request p);
void on_disk_cache_complete(int ret, disk_io_job const& j);
void set_progress_ppm(int p) { m_progress_ppm = p; }
struct read_piece_struct struct read_piece_struct
{ {
boost::shared_array<char> piece_data; boost::shared_array<char> piece_data;
int blocks_left; int blocks_left;
bool fail; bool fail;
}; };
void read_piece(int piece); 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); 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 (storage_mode_t )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 (torrent_stat us::state_t)m_state; }
void set_state(torrent_status::state_t s); void set_state(torrent_status::state_t s);
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 queue_up();
void queue_down();
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, int tick_interval_ms); void second_tick(stat& accumulator, int tick_interval_ms);
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); void add_stats(stat const& s);
size_type bytes_left() const; size_type bytes_left() const;
int block_bytes_wanted(piece_block const& p) const; int block_bytes_wanted(piece_block const& p) const;
void bytes_done(torrent_status& st) const; void bytes_done(torrent_status& st, bool accurate) 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 handle_disk_error(disk_io_job const& j, peer_connection * c = 0); void handle_disk_error(disk_io_job const& j, peer_connection * c = 0);
void clear_error(); void clear_error();
void set_error(error_code const& ec, std::string const& file ); void set_error(error_code const& ec, std::string const& file );
bool has_error() const { return m_error; } bool has_error() const { return !!m_error; }
error_code error() const { return m_error; }
void flush_cache(); void flush_cache();
void pause(); void pause(bool graceful = false);
void resume(); void resume();
void set_allow_peers(bool b, bool graceful_pause = false);
void set_announce_to_dht(bool b) { m_announce_to_dht = b; }
void set_announce_to_trackers(bool b) { m_announce_to_tracke
rs = b; }
void set_announce_to_lsd(bool b) { m_announce_to_lsd = b; }
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 allows_peers() const { return m_allow_peers; }
bool is_torrent_paused() const { return !m_allow_peers || m_
graceful_pause_mode; }
void force_recheck(); void force_recheck();
void save_resume_data(); void save_resume_data(int flags);
bool need_save_resume_data() const
{
// save resume data every 15 minutes regardless, jus
t to
// keep stats up to date
return m_need_save_resume_data || time(0) - m_last_s
aved_resume > 15 * 60;
}
bool is_auto_managed() const { return m_auto_managed; } bool is_auto_managed() const { return m_auto_managed; }
void auto_managed(bool a); void auto_managed(bool a);
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);
skipping to change at line 275 skipping to change at line 294
void file_progress(std::vector<float>& fp) const; void file_progress(std::vector<float>& fp) const;
#endif #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 set_piece_deadline(int piece, int t, int flags);
void reset_piece_deadline(int piece); void reset_piece_deadline(int piece);
void update_piece_priorities(); void update_piece_priorities();
torrent_status status() const; void status(torrent_status* st, boost::uint32_t flags);
// this torrent changed state, if the user is subscribing to
// it, add it to the m_state_updates list in session_impl
void state_updated();
void file_progress(std::vector<size_type>& fp, int flags = 0 ) const; void file_progress(std::vector<size_type>& fp, int flags = 0 ) const;
void use_interface(const char* net_interface); void use_interface(std::string net_interface);
tcp::endpoint const& get_interface() const { return m_net_in tcp::endpoint get_interface() const;
terface; }
void connect_to_url_seed(web_seed_entry const& url); void connect_to_url_seed(std::list<web_seed_entry>::iterator
bool connect_to_peer(policy::peer* peerinfo); url);
bool connect_to_peer(policy::peer* peerinfo, bool ignore_lim
it = false);
void set_ratio(float r) void set_ratio(float r)
{ TORRENT_ASSERT(r >= 0.0f); m_ratio = r; } { 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; } int priority() const { return m_priority; }
void set_priority(int prio) void set_priority(int prio)
{ {
TORRENT_ASSERT(prio <= 255 && prio >= 0); TORRENT_ASSERT(prio <= 255 && prio >= 0);
if (prio > 255) prio = 255; if (prio > 255) prio = 255;
else if (prio < 0) prio = 0; else if (prio < 0) prio = 0;
m_priority = prio; m_priority = prio;
state_updated();
} }
#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 bool resolving_countries() const
s; } {
return m_resolve_countries && !m_ses.settings().anon
ymous_mode;
}
#endif #endif
// -------------------------------------------- // --------------------------------------------
// BANDWIDTH MANAGEMENT // BANDWIDTH MANAGEMENT
bandwidth_channel m_bandwidth_channel[2]; bandwidth_channel m_bandwidth_channel[2];
int bandwidth_throttle(int channel) const; int bandwidth_throttle(int channel) const;
// -------------------------------------------- // --------------------------------------------
// PEER MANAGEMENT // PEER MANAGEMENT
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_ERROR_LOGGING || def
ined TORRENT_LOGGING
void log_to_all_peers(char const* message);
#endif
// 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_web_seed(std::string const& url, web_seed_entry::ty pe_t type) void add_web_seed(std::string const& url, web_seed_entry::ty pe_t type)
{ m_web_seeds.insert(web_seed_entry(url, type)); } {
m_web_seeds.push_back(web_seed_entry(url, type));
}
void remove_web_seed(std::string const& url, web_seed_entry: void add_web_seed(std::string const& url, web_seed_entry::ty
:type_t type) pe_t type
{ m_web_seeds.erase(web_seed_entry(url, type)); } , std::string const& auth, web_seed_entry::headers_t
const& extra_headers)
{
m_web_seeds.push_back(web_seed_entry(url, type, auth
, extra_headers));
}
void retry_web_seed(std::string const& url, web_seed_entry:: void remove_web_seed(std::string const& url, web_seed_entry:
type_t type, int retry = 0); :type_t type);
void disconnect_web_seed(peer_connection* p);
std::set<web_seed_entry> web_seeds() const void retry_web_seed(peer_connection* p, int retry = 0);
void remove_web_seed(peer_connection* p);
std::list<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; 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; }
bool choke_peer(peer_connection& c); bool choke_peer(peer_connection& c);
bool unchoke_peer(peer_connection& c, bool optimistic = fals e); bool unchoke_peer(peer_connection& c, bool optimistic = fals e);
skipping to change at line 365 skipping to change at line 406
// 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
// decreased in the piece_picker // decreased in the piece_picker
void remove_peer(peer_connection* p); void remove_peer(peer_connection* p);
void cancel_block(piece_block block); void cancel_block(piece_block block);
bool want_more_peers() const; bool want_more_peers() const;
bool try_connect_peer(); bool try_connect_peer();
void give_connect_points(int points); void add_peer(tcp::endpoint const& adr, int source);
// the number of peers that belong to this torrent // the number of peers that belong to this torrent
int num_peers() const { return (int)m_connections.size(); } int num_peers() const { return (int)m_connections.size(); }
int num_seeds() const; int num_seeds() const;
typedef std::set<peer_connection*>::iterator peer_iterator; typedef std::set<peer_connection*>::iterator peer_iterator;
typedef std::set<peer_connection*>::const_iterator const_pee r_iterator; typedef std::set<peer_connection*>::const_iterator const_pee r_iterator;
const_peer_iterator begin() const { return m_connections.beg in(); } const_peer_iterator begin() const { return m_connections.beg in(); }
const_peer_iterator end() const { return m_connections.end() ; } const_peer_iterator end() const { return m_connections.end() ; }
peer_iterator begin() { return m_connections.begin(); } peer_iterator begin() { return m_connections.begin(); }
peer_iterator end() { return m_connections.end(); } peer_iterator end() { return m_connections.end(); }
void resolve_peer_country(boost::intrusive_ptr<peer_connecti on> const& p) const; void resolve_peer_country(boost::intrusive_ptr<peer_connecti on> const& p) 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); void get_peer_info(std::vector<peer_info>& v);
void get_download_queue(std::vector<partial_piece_info>& que void get_download_queue(std::vector<partial_piece_info>* que
ue); ue);
void refresh_explicit_cache(int cache_size);
// -------------------------------------------- // --------------------------------------------
// 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
, address const& tracker_ip , address const& tracker_ip
, std::list<address> const& ip_list , std::list<address> const& ip_list
, std::vector<peer_entry>& e, int interval, int min_ interval , std::vector<peer_entry>& e, int interval, int min_ interval
, int complete, int incomplete, address const& exter , int complete, int incomplete, address const& exter
nal_ip); nal_ip
virtual void tracker_request_timed_out( , std::string const& trackerid);
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 ret , int response_code, error_code const& ec, const std
ry_interval); ::string& msg
, int retry_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, int downloaders);
// 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).
std::string tracker_login() const; std::string tracker_login() const;
// 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()) ; , address const& bind_interface = address_v4::any()) ;
ptime const& last_scrape() const { return m_last_scrape; } int seconds_since_last_scrape() const { return m_last_scrape ; }
#ifndef TORRENT_DISABLE_DHT #ifndef TORRENT_DISABLE_DHT
void force_dht_announce(); void 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; tcp::endpoint current_tracker() const;
announce_entry* find_tracker(tracker_request const& r); announce_entry* find_tracker(tracker_request const& r);
// -------------------------------------------- // --------------------------------------------
// PIECE MANAGEMENT // PIECE MANAGEMENT
void recalc_share_mode();
void update_sparse_piece_prio(int piece, int cursor, int rev erse_cursor); void update_sparse_piece_prio(int piece, int cursor, int rev erse_cursor);
void get_suggested_pieces(std::vector<int>& s) const;
bool super_seeding() const bool super_seeding() const
{ return m_super_seeding; } { return m_super_seeding; }
void super_seeding(bool on); void super_seeding(bool on);
int get_piece_to_super_seed(bitfield const&); 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 if (!valid_metadata()) return false;
; if (!has_picker()) return true;
return m_picker->have_piece(index);
} }
// called when we learn that we have a piece // called when we learn that we have a piece
// only once per piece // only once per piece
void we_have(int index); 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)
{ {
if (m_picker.get()) if (m_picker.get())
{ {
TORRENT_ASSERT(!is_seed()); TORRENT_ASSERT(!is_seed());
m_picker->inc_refcount(index); m_picker->inc_refcount(index);
} }
skipping to change at line 532 skipping to change at line 581
m_picker->dec_refcount(index); m_picker->dec_refcount(index);
} }
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
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_shift > 0); return 1 << m_block_size_shift; }
peer_request to_req(piece_block const& p) const; peer_request to_req(piece_block const& p) const;
void disconnect_all(error_code const& ec); void disconnect_all(error_code const& ec);
int disconnect_peers(int num); int disconnect_peers(int num, error_code const& ec);
// 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();
#if TORRENT_USE_I2P
void on_i2p_resolve(error_code const& ec, char const* dest);
#endif
// 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
, web_seed_entry url, tcp::endpoint proxy); , std::list<web_seed_entry>::iterator url, tcp::endp
oint proxy);
void connect_web_seed(std::list<web_seed_entry>::iterator we
b, tcp::endpoint a);
// 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
, web_seed_entry url); , std::list<web_seed_entry>::iterator url);
// remove a web seed, or schedule it for removal in case the
re
// are outstanding operations on it
void remove_web_seed(std::list<web_seed_entry>::iterator web
);
// 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 591 skipping to change at line 650
// piece_failed is called when a piece fails the hash check // piece_failed is called when a piece fails the hash check
void piece_failed(int index); void piece_failed(int index);
// this will restore the piece picker state for a piece // this will restore the piece picker state for a piece
// by re marking all the requests to blocks in this piece // by re marking all the requests to blocks in this piece
// that are still outstanding in peers' download queues. // that are still outstanding in peers' download queues.
// this is done when a piece fails // this is done when a piece fails
void restore_piece_state(int index); void restore_piece_state(int index);
void add_redundant_bytes(int b); enum wasted_reason_t
{
piece_timed_out, piece_cancelled, piece_unknown, pie
ce_seed, piece_end_game, piece_closing
, waste_reason_max
};
void add_redundant_bytes(int b, wasted_reason_t reason);
void add_failed_bytes(int b); void add_failed_bytes(int b);
// this is true if we have all the pieces // this is true if we have all the pieces
bool is_seed() const bool is_seed() const
{ {
return valid_metadata() return valid_metadata()
&& (!m_picker && (!m_picker
|| m_state == torrent_status::seeding || m_state == torrent_status::seeding
|| m_picker->num_have() == m_picker->num_pie ces()); || m_picker->num_have() == m_picker->num_pie ces());
} }
// this is true if we have all the pieces that we want // this is true if we have all the pieces that we want
bool is_finished() const bool is_finished() const
{ {
if (is_seed()) return true; if (is_seed()) return true;
return valid_metadata() && m_torrent_file->num_piece s() return valid_metadata() && m_torrent_file->num_piece s()
- m_picker->num_have() - m_picker->num_filte red() == 0; - m_picker->num_have() - m_picker->num_filte red() == 0;
} }
fs::path save_path() const; std::string save_path() const;
alert_manager& alerts() const; alert_manager& alerts() const;
piece_picker& picker() piece_picker& picker()
{ {
TORRENT_ASSERT(m_picker.get()); TORRENT_ASSERT(m_picker.get());
return *m_picker; return *m_picker;
} }
bool has_picker() const bool has_picker() const
{ {
return m_picker.get() != 0; return m_picker.get() != 0;
} }
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::string const& uuid() const { return m_uuid; }
void set_uuid(std::string const& s) { m_uuid = s; }
std::string const& url() const { return m_url; }
void set_url(std::string const& s) { m_url = s; }
std::string const& source_feed_url() const { return m_source
_feed_url; }
void set_source_feed_url(std::string const& s) { m_source_fe
ed_url = s; }
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); 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);
void seen_complete() { m_last_seen_complete = time(0); }
int time_since_complete() const { return int(time(0) - m_las
t_seen_complete); }
time_t last_seen_complete() const { return m_last_seen_compl
ete; }
// 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 += void add_free_upload(size_type diff)
diff; } {
TORRENT_ASSERT(diff >= 0);
if (UINT_MAX - m_available_free_upload > diff)
m_available_free_upload += boost::uint32_t(d
iff);
else
m_available_free_upload = UINT_MAX;
}
int get_peer_upload_limit(tcp::endpoint ip) const;
int get_peer_download_limit(tcp::endpoint ip) const;
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; }
void set_max_connections(int limit); void set_max_connections(int limit);
int max_connections() const { return m_max_connections; } int max_connections() const { return m_max_connections; }
void move_storage(fs::path const& save_path); void move_storage(std::string const& save_path);
// renames the file with the given index to the new name // renames the file with the given index to the new name
// the name may include a directory path // the name may include a directory path
// returns false on failure // returns false on failure
bool rename_file(int index, std::string const& name); bool rename_file(int index, std::string const& name);
// unless this returns true, new connections must wait // unless this returns true, new connections must wait
// with their initialization. // with their initialization.
bool ready_for_connections() const bool ready_for_connections() const
{ return m_connections_initialized; } { return m_connections_initialized; }
skipping to change at line 689 skipping to change at line 773
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(char const* metadata_buf, int metadata_siz e); bool set_metadata(char const* metadata_buf, int metadata_siz e);
void on_torrent_download(error_code const& ec, http_parser c
onst& parser
, char const* data, int size);
int sequence_number() const { return m_sequence_number; } int sequence_number() const { return m_sequence_number; }
bool seed_mode() const { return m_seed_mode; } bool seed_mode() const { return m_seed_mode; }
void leave_seed_mode(bool seed) void leave_seed_mode(bool seed)
{ {
if (!m_seed_mode) return; if (!m_seed_mode) return;
m_seed_mode = false; m_seed_mode = false;
// seed is false if we turned out not // seed is false if we turned out not
// to be a seed after all // to be a seed after all
if (!seed) force_recheck(); if (!seed) force_recheck();
skipping to change at line 725 skipping to change at line 812
++m_num_verified; ++m_num_verified;
m_verified.set_bit(piece); m_verified.set_bit(piece);
} }
bool add_merkle_nodes(std::map<int, sha1_hash> const& n, int piece); bool add_merkle_nodes(std::map<int, sha1_hash> const& n, int piece);
// this is called once periodically for torrents // this is called once periodically for torrents
// that are not private // that are not private
void lsd_announce(); void lsd_announce();
#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined T
ORRENT_ERROR_LOGGING
static void print_size(logger& l);
#endif
void update_last_upload() { m_last_upload = 0; }
void set_apply_ip_filter(bool b);
bool apply_ip_filter() const { return m_apply_ip_filter; }
void queue_torrent_check();
void dequeue_torrent_check();
void clear_in_state_update()
{ m_in_state_updates = false; }
void inc_num_connecting()
{ ++m_num_connecting; }
void dec_num_connecting()
{
TORRENT_ASSERT(m_num_connecting > 0);
--m_num_connecting;
}
#ifdef TORRENT_USE_OPENSSL
void set_ssl_cert(std::string const& certificate
, std::string const& private_key
, std::string const& dh_params
, std::string const& passphrase);
bool is_ssl_torrent() const { return m_ssl_ctx; }
boost::asio::ssl::context* ssl_ctx() const { return m_ssl_ct
x.get(); }
#endif
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_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_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);
int prioritize_tracker(int tracker_index); int prioritize_tracker(int tracker_index);
int deprioritize_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 prioritize_udp_trackers();
void queue_torrent_check(); void parse_response(const entry& e, std::vector<peer_entry>&
void dequeue_torrent_check(); peer_list);
policy m_policy; void update_tracker_timer(ptime now);
// total time we've been available on this torrent static void on_tracker_announce_disp(boost::weak_ptr<torrent
// does not count when the torrent is stopped or paused > p
time_duration m_active_time; , error_code const& e);
// total time we've been finished with this torrent void on_tracker_announce();
// 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 #ifndef TORRENT_DISABLE_DHT
// does not count when the torrent is stopped or paused static void on_dht_announce_response_disp(boost::weak_ptr<to
time_duration m_seeding_time; rrent> t
, std::vector<tcp::endpoint> const& peers);
void on_dht_announce_response(std::vector<tcp::endpoint> con
st& peers);
bool should_announce_dht() const;
#endif
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();
policy m_policy;
// 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
// one of the trackers in this torrent
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);
// 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
// with this intrusive_ptr. This cycle is // with this intrusive_ptr. This cycle is
// broken when torrent::abort() is called // broken when torrent::abort() is called
// Then the torrent releases the piece_manager // Then the torrent releases the piece_manager
// and when the piece_manager is complete with all // and when the piece_manager is complete with all
skipping to change at line 813 skipping to change at line 926
// 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;
#ifdef TORRENT_USE_OPENSSL
boost::shared_ptr<asio::ssl::context> m_ssl_ctx;
#if BOOST_VERSION >= 104700
bool verify_peer_cert(bool preverified, boost::asio::ssl::ve
rify_context& ctx);
#endif
void init_ssl(std::string const& cert);
#endif
#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
// of all peers in m_connections, this is the number
// of peers that are outgoing and still waiting to
// complete the connection. This is used to possibly
// kick out these connections when we get incoming
// connections (if we've reached the connection limit)
int m_num_connecting;
// 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<web_seed_entry> m_web_seeds; std::list<web_seed_entry> m_web_seeds;
// a list of web seeds that have failed and are
// waiting to be retried
std::map<web_seed_entry, ptime> m_web_seeds_next_retry;
// urls of the web seeds that we are currently
// resolving the address for
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
mutable tcp::resolver m_host_resolver;
#ifndef TORRENT_DISABLE_DHT
// this announce timer is used both
// by Local service discovery and
// by the DHT.
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 update_tracker_timer(ptime now);
static void on_tracker_announce_disp(boost::weak_ptr<torrent
> p
, error_code const& e);
void on_tracker_announce();
void dht_announce();
#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
, std::vector<tcp::endpoint> const& peers);
void on_dht_announce_response(std::vector<tcp::endpoint> con
st& peers);
bool should_announce_dht() const;
void on_dht_announce(error_code const& e);
// the time when the DHT was last announced of our
// presence on this torrent
ptime m_last_dht_announce;
#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;
skipping to change at line 914 skipping to change at line 1003
// 1 = send alert with piece data when available // 1 = send alert with piece data when available
int flags; int flags;
// how many peers it's been requested from // how many peers it's been requested from
int peers; int peers;
// the piece index // the piece index
int piece; int piece;
bool operator<(time_critical_piece const& rhs) const bool operator<(time_critical_piece const& rhs) const
{ return deadline < rhs.deadline; } { 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 // this list is sorted by time_critical_piece::deadline
std::list<time_critical_piece> m_time_critical_pieces; std::list<time_critical_piece> m_time_critical_pieces;
// the average time it takes to download one time critical p std::string m_trackerid;
iece std::string m_username;
time_duration m_average_piece_time; std::string m_password;
// the average piece download time deviation
time_duration m_piece_time_deviation;
// the number of bytes that has been // the network interfaces outgoing connections
// downloaded that failed the hash-test // are opened through. If there is more then one,
size_type m_total_failed_bytes; // they are used in a round-robin fasion
size_type m_total_redundant_bytes; std::vector<union_endpoint> m_net_interfaces;
// the number of bytes of padding files std::string m_save_path;
int m_padding;
std::string m_username; // if we don't have the metadata, this is a url to
std::string m_password; // the torrent file
std::string m_url;
// the network interface all outgoing connections // if this was added from an RSS feed, this is the unique
// are opened through // identifier in the feed.
tcp::endpoint m_net_interface; std::string m_uuid;
fs::path m_save_path; // if this torrent was added by an RSS feed, this is the
// URL to that feed
std::string m_source_feed_url;
// this is used as temporary storage while downloading
// the .torrent file from m_url
std::vector<char> m_torrent_file_buf;
// each bit represents a piece. a set bit means // each bit represents a piece. a set bit means
// the piece has had its hash verified. This // the piece has had its hash verified. This
// is only used in seed mode (when m_seed_mode // is only used in seed mode (when m_seed_mode
// is true) // is true)
bitfield m_verified; 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.
storage_mode_t m_storage_mode;
// the state of this torrent (queued, checking, downloading,
etc.)
torrent_status::state_t m_state;
// set if there's an error on this torrent // set if there's an error on this torrent
error_code m_error; error_code m_error;
// if the error ocurred on a file, this is the file // if the error ocurred on a file, this is the file
std::string m_error_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;
storage_constructor_type m_storage_constructor;
// the posix time this torrent was added and when
// it was completed. If the torrent isn't yet
// completed, m_completed_time is 0
time_t m_added_time;
time_t m_completed_time;
time_t m_last_seen_complete;
time_t m_last_saved_resume;
#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;
storage_constructor_type m_storage_constructor;
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 // free download we have got that hasn't
int m_max_uploads; // been distributed yet.
boost::uint32_t m_available_free_upload;
// the number of unchoked peers in this torrent
int m_num_uploads;
// the maximum number of connections for this torrent
int m_max_connections;
// the size of a request block
// each piece is divided into these
// blocks when requested
int m_block_size;
// -----------------------------
// DATA FROM TRACKER RESPONSE
// the scrape data from the tracker response, this // the average time it takes to download one time critical p
// is optional and may be -1. iece
int m_complete; boost::uint32_t m_average_piece_time;
int m_incomplete; // the average piece download time deviation
boost::uint32_t m_piece_time_deviation;
#ifdef TORRENT_DEBUG // the number of bytes that has been
// this is the amount downloaded when this torrent // downloaded that failed the hash-test
// is started. i.e. boost::uint32_t m_total_failed_bytes;
// total_done - m_initial_done <= total_payload_download boost::uint32_t m_total_redundant_bytes;
size_type m_initial_done;
#endif
// this is the deficit counter in the Deficit Round Robin
// used to determine which torrent gets the next
// connection attempt. See:
// http://www.ecs.umass.edu/ece/wolf/courses/ECE697J/papers/
DRR.pdf
// The quanta assigned to each torrent depends on the torren
ts
// priority, whether it's seed and the number of connected
// peers it has. This has the effect that some torrents
// will have more connection attempts than other. Each
// connection attempt costs 100 points from the deficit
// counter. points are deducted in try_connect_peer and
// increased in give_connect_points. Outside of the
// torrent object, these points are called connect_points.
int m_deficit_counter;
// 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; int m_sequence_number;
// the index to the last tracker that worked // ==============================
boost::int8_t m_last_working_tracker; // The following members are specifically
// ordered to make the 24 bit members
// properly 32 bit aligned by inserting
// 8 bits after each one
// ==============================
// the number of connection attempts that has // the number of seconds we've been in upload mode
// failed in a row, this is currently used to unsigned int m_upload_mode_time:24;
// determine the timeout until next try.
boost::int8_t m_failed_trackers;
// this is a counter that is decreased every // the state of this torrent (queued, checking, downloading,
// second, and when it reaches 0, the policy::pulse() etc.)
// is called and the time scaler is reset to 10. unsigned int m_state:3;
boost::int8_t m_time_scaler;
// this is the priority of the torrent. The higher // determines the storage state for this torrent.
// the value is, the more bandwidth is assigned to unsigned int m_storage_mode:2;
// the torrent's peers
boost::uint8_t m_priority;
// is set to true when the torrent has // this is true while tracker announcing is enabled
// been aborted. // is is disabled while paused and checking files
bool m_abort:1; bool m_announcing:1;
// is true if this torrent has been paused // this is true while the tracker deadline timer
bool m_paused:1; // is in use. i.e. one or more trackers are waiting
// for a reannounce
bool m_waiting_tracker:1;
// set to true when this torrent may not download anything // this means we haven't verified the file content
bool m_upload_mode:1; // of the files we're seeding. the m_verified bitfield
// indicates which pieces have been verified and which
// haven't
bool m_seed_mode:1;
// if this is true, libtorrent may pause and resume // total time we've been available on this torrent
// this torrent depending on queuing rules. Torrents // does not count when the torrent is stopped or paused
// started with auto_managed flag set may be added in // in seconds
// a paused state in case there are no available unsigned int m_active_time:24;
// slots.
bool m_auto_managed:1;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES // the index to the last tracker that worked
// this is true while there is a country boost::int8_t m_last_working_tracker;
// resolution in progress. To avoid flodding
// the DNS request queue, only one ip is resolved
// at a time.
mutable bool m_resolving_country:1;
// this is true if the user has enabled // total time we've been finished with this torrent
// country resolution in this torrent // does not count when the torrent is stopped or paused
bool m_resolve_countries:1; unsigned int m_finished_time:24;
#endif
// in case the piece picker hasn't been constructed // in case the piece picker hasn't been constructed
// when this settings is set, this variable will keep // when this settings is set, this variable will keep
// its value until the piece picker is created // its value until the piece picker is created
bool m_sequential_download:1; bool m_sequential_download:1;
// is false by default and set to // is false by default and set to
// true when the first tracker reponse // true when the first tracker reponse
// is received // is received
bool m_got_tracker_response:1; bool m_got_tracker_response:1;
skipping to change at line 1110 skipping to change at line 1161
// 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 // if this is true, we're currently super seeding this
// torrent. // torrent.
bool m_super_seeding:1; bool m_super_seeding:1;
// 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;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
// this is true while there is a country
// resolution in progress. To avoid flodding
// the DNS request queue, only one ip is resolved
// at a time.
mutable bool m_resolving_country:1;
// this is true if the user has enabled
// country resolution in this torrent
bool m_resolve_countries:1;
#else
unsigned int m_dummy_padding_bits_to_align:2;
#endif
// set to false when saving resume data. Set to true
// whenever something is downloaded
bool m_need_save_resume_data:1;
// total time we've been available as a seed on this torrent
// does not count when the torrent is stopped or paused
unsigned int m_seeding_time:24;
// this is a counter that is decreased every
// second, and when it reaches 0, the policy::pulse()
// is called and the time scaler is reset to 10.
boost::int8_t m_time_scaler;
// the maximum number of uploads for this torrent
unsigned int m_max_uploads:24;
// these are the flags sent in on a call to save_resume_data
// we need to save them to check them in write_resume_data
boost::uint8_t m_save_resume_flags;
// the number of unchoked peers in this torrent
unsigned int m_num_uploads:24;
// the size of a request block
// each piece is divided into these
// blocks when requested. The block size is
// 1 << m_block_size_shift
unsigned int m_block_size_shift:5;
// 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 // the maximum number of connections for this torrent
// is is disabled while paused and checking files unsigned int m_max_connections:24;
bool m_announcing:1;
// this is true while the tracker deadline timer // the number of bytes of padding files
// is in use. i.e. one or more trackers are waiting unsigned int m_padding:24;
// for a reannounce
bool m_waiting_tracker:1;
// this means we haven't verified the file content // the scrape data from the tracker response, this
// of the files we're seeding. the m_verified bitfield // is optional and may be 0xffffff
// indicates which pieces have been verified and which unsigned int m_complete:24;
// haven't
bool m_seed_mode:1;
// this is set when we don't want to load seed_mode, // this is the priority of the torrent. The higher
// paused or auto_managed from the resume data // the value is, the more bandwidth is assigned to
bool m_override_resume_data:1; // the torrent's peers
boost::uint8_t m_priority;
// the scrape data from the tracker response, this
// is optional and may be 0xffffff
unsigned int m_incomplete:24;
// progress parts per million (the number of
// millionths of completeness)
unsigned int m_progress_ppm:20;
// is set to true when the torrent has
// been aborted.
bool m_abort:1;
// true when the torrent should announce to
// the DHT
bool m_announce_to_dht:1;
// true when this torrent should anncounce to
// trackers
bool m_announce_to_trackers:1;
// true when this torrent should anncounce to
// the local network
bool m_announce_to_lsd:1;
// is true if this torrent has allows having peers
bool m_allow_peers: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
// this torrent depending on queuing rules. Torrents
// started with auto_managed flag set may be added in
// a paused state in case there are no available
// slots.
bool m_auto_managed:1;
// this is set when the torrent is in share-mode
bool m_share_mode:1;
// m_num_verified = m_verified.count()
boost::uint16_t m_num_verified;
// the number of seconds since the last scrape request to
// one of the trackers in this torrent
boost::uint16_t m_last_scrape;
// the number of seconds since the last piece passed for
// this torrent
boost::uint16_t m_last_download;
// the number of seconds since the last byte was uploaded
// from this torrent
boost::uint16_t m_last_upload;
// the scrape data from the tracker response, this
// is optional and may be 0xffffff
unsigned int m_downloaders:24;
// round-robin index into m_interfaces
mutable boost::uint8_t m_interface_index;
// set to true when this torrent has been paused but
// is waiting to finish all current download requests
// before actually closing all connections
bool m_graceful_pause_mode:1;
// this is set to true when the torrent starts up
// The first tracker response, when this is true,
// will attempt to connect to a bunch of peers immediately
// and set this to false. We only do this once to get
// the torrent kick-started
bool m_need_connect_boost:1;
// rotating sequence number for LSD announces sent out.
// used to only use IP broadcast for every 8th lsd announce
boost::uint8_t m_lsd_seq:3;
// this is set to true if the torrent was started without
// metadata. It is used to save metadata in the resume file
// by default for such torrents. It does not necessarily
// have to be a magnet link.
bool m_magnet_link:1;
// set to true if the session IP filter applies to this
// torrent or not. Defaults to true.
bool m_apply_ip_filter:1;
// if set to true, add tracker URLs loaded from resume
// data into this torrent instead of replacing them
bool m_merge_resume_trackers:1;
// state subscription. If set, a pointer to this torrent
// will be added to the m_state_updates set in session_impl
// whenever this torrent's state changes (any state).
bool m_state_subscription:1;
// in state_updates list. When adding a torrent to the
// session_impl's m_state_update list, this bit is set
// to never add the same torrent twice
bool m_in_state_updates:1;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
public:
// set to false until we've loaded resume data
bool m_resume_data_loaded;
#endif
}; };
} }
#endif // TORRENT_TORRENT_HPP_INCLUDED #endif // TORRENT_TORRENT_HPP_INCLUDED
 End of changes. 110 change blocks. 
291 lines changed or deleted 518 lines changed or added


 torrent_handle.hpp   torrent_handle.hpp 
skipping to change at line 43 skipping to change at line 43
#ifndef TORRENT_TORRENT_HANDLE_HPP_INCLUDED #ifndef TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#define TORRENT_TORRENT_HANDLE_HPP_INCLUDED #define TORRENT_TORRENT_HANDLE_HPP_INCLUDED
#include <vector> #include <vector>
#include <set> #include <set>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(push, 1) #pragma warning(push, 1)
#endif #endif
#include <boost/date_time/posix_time/posix_time_types.hpp> #include <boost/assert.hpp>
#include <boost/date_time/posix_time/posix_time_duration.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/peer_info.hpp"
#include "libtorrent/piece_picker.hpp" #include "libtorrent/piece_picker.hpp"
#include "libtorrent/torrent_info.hpp" #include "libtorrent/torrent_info.hpp"
#include "libtorrent/time.hpp" #include "libtorrent/ptime.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/storage.hpp" #include "libtorrent/storage.hpp"
#include "libtorrent/address.hpp"
#include "libtorrent/bitfield.hpp"
#include "libtorrent/socket.hpp" // tcp::endpoint
namespace libtorrent namespace libtorrent
{ {
namespace fs = boost::filesystem;
namespace aux namespace aux
{ {
struct session_impl; struct session_impl;
struct checker_impl;
} }
struct torrent_plugin; struct torrent_plugin;
struct peer_info;
struct peer_list_entry;
struct torrent_status;
TORRENT_EXPORT std::size_t hash_value(torrent_status const& ts);
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
// for compatibility with 0.14 // for compatibility with 0.14
typedef libtorrent_exception duplicate_torrent; typedef libtorrent_exception duplicate_torrent;
typedef libtorrent_exception invalid_handle; typedef libtorrent_exception invalid_handle;
void throw_invalid_handle(); void throw_invalid_handle();
#endif #endif
struct TORRENT_EXPORT torrent_status
{
torrent_status()
: state(checking_resume_data)
, paused(false)
, progress(0.f)
, progress_ppm(0)
, total_download(0)
, total_upload(0)
, total_payload_download(0)
, total_payload_upload(0)
, total_failed_bytes(0)
, total_redundant_bytes(0)
, download_rate(0)
, upload_rate(0)
, download_payload_rate(0)
, upload_payload_rate(0)
, num_seeds(0)
, num_peers(0)
, num_complete(-1)
, num_incomplete(-1)
, list_seeds(0)
, list_peers(0)
, connect_candidates(0)
, num_pieces(0)
, total_done(0)
, total_wanted_done(0)
, total_wanted(0)
, distributed_full_copies(0)
, distributed_fraction(0)
, distributed_copies(0.f)
, block_size(0)
, num_uploads(0)
, num_connections(0)
, uploads_limit(0)
, connections_limit(0)
, storage_mode(storage_mode_sparse)
, up_bandwidth_queue(0)
, down_bandwidth_queue(0)
, all_time_upload(0)
, all_time_download(0)
, active_time(0)
, finished_time(0)
, seeding_time(0)
, seed_rank(0)
, last_scrape(0)
, has_incoming(false)
, sparse_regions(0)
, seed_mode(false)
, upload_mode(false)
, priority(0)
{}
enum state_t
{
queued_for_checking,
checking_files,
downloading_metadata,
downloading,
finished,
seeding,
allocating,
checking_resume_data
};
state_t state;
bool paused;
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;
boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval;
std::string current_tracker;
// transferred this session!
// total, payload plus protocol
size_type total_download;
size_type total_upload;
// payload only
size_type total_payload_download;
size_type total_payload_upload;
// the amount of payload bytes that
// has failed their hash test
size_type total_failed_bytes;
// the number of payload bytes that
// has been received redundantly.
size_type total_redundant_bytes;
// current transfer rate
// payload plus protocol
int download_rate;
int upload_rate;
// the rate of payload that is
// sent and received
int download_payload_rate;
int upload_payload_rate;
// the number of peers this torrent is connected to
// that are seeding.
int num_seeds;
// the number of peers this torrent
// is connected to (including seeds).
int num_peers;
// if the tracker sends scrape info in its
// announce reply, these fields will be
// set to the total number of peers that
// have the whole file and the total number
// of peers that are still downloading
int num_complete;
int num_incomplete;
// this is the number of seeds whose IP we know
// but are not necessarily connected to
int list_seeds;
// this is the number of peers whose IP we know
// (including seeds), but are not necessarily
// connected to
int list_peers;
// the number of peers in our peerlist that
// we potentially could connect to
int connect_candidates;
bitfield pieces;
// this is the number of pieces the client has
// downloaded. it is equal to:
// std::accumulate(pieces->begin(), pieces->end());
int num_pieces;
// the number of bytes of the file we have
// including pieces that may have been filtered
// after we downloaded them
size_type total_done;
// the number of bytes we have of those that we
// want. i.e. not counting bytes from pieces that
// are filtered as not wanted.
size_type total_wanted_done;
// the total number of bytes we want to download
// this may be smaller than the total torrent size
// in case any pieces are filtered as not wanted
size_type total_wanted;
// the number of distributed copies of the file.
// note that one copy may be spread out among many peers.
//
// the integer part tells how many copies
// there are of the rarest piece(s)
//
// the fractional part tells the fraction of pieces that
// 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;
// the block size that is used in this torrent. i.e.
// the number of bytes each piece request asks for
// and each bit in the download queue bitfield represents
int block_size;
int num_uploads;
int num_connections;
int uploads_limit;
int connections_limit;
// true if the torrent is saved in compact mode
// false if it is saved in full allocation mode
storage_mode_t storage_mode;
int up_bandwidth_queue;
int down_bandwidth_queue;
// number of bytes downloaded since torrent was started
// saved and restored from resume data
size_type all_time_upload;
size_type all_time_download;
// the number of seconds of being active
// and as being a seed, saved and restored
// from resume data
int active_time;
int finished_time;
int seeding_time;
// higher value means more important to seed
int seed_rank;
// number of seconds since last scrape, or -1 if
// there hasn't been a scrape
int last_scrape;
// true if there are incoming connections to this
// torrent
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 };
private: private:
#ifdef __SUNPRO_CC TORRENT_UNION addr_t
// sunpro is strict about POD types in unions
struct
#else
union
#endif
{ {
address_v4::bytes_type v4; address_v4::bytes_type v4;
#if TORRENT_USE_IPV6
address_v6::bytes_type v6; address_v6::bytes_type v6;
#endif
} addr; } addr;
boost::uint16_t port; boost::uint16_t port;
public: public:
void set_peer(tcp::endpoint const& ep) void set_peer(tcp::endpoint const& ep)
{ {
#if TORRENT_USE_IPV6
is_v6_addr = ep.address().is_v6(); is_v6_addr = ep.address().is_v6();
if (is_v6_addr) if (is_v6_addr)
addr.v6 = ep.address().to_v6().to_bytes(); addr.v6 = ep.address().to_v6().to_bytes();
else else
#endif
addr.v4 = ep.address().to_v4().to_bytes(); addr.v4 = ep.address().to_v4().to_bytes();
port = ep.port(); port = ep.port();
} }
tcp::endpoint peer() const tcp::endpoint peer() const
{ {
#if TORRENT_USE_IPV6
if (is_v6_addr) if (is_v6_addr)
return tcp::endpoint(address_v6(addr.v6), po rt); return tcp::endpoint(address_v6(addr.v6), po rt);
else else
#endif
return tcp::endpoint(address_v4(addr.v4), po rt); 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:15; unsigned bytes_progress:15;
// the total number of bytes in this block // the total number of bytes in this block
unsigned block_size:15; unsigned block_size:15;
private: private:
// the type of the addr union // the type of the addr union
unsigned is_v6_addr:1; unsigned is_v6_addr:1;
skipping to change at line 384 skipping to change at line 158
int requested; int requested;
block_info* blocks; 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 struct feed;
friend class torrent; friend class torrent;
friend std::size_t hash_value(torrent_handle const& th);
torrent_handle() {} torrent_handle() {}
enum flags_t { overwrite_existing = 1 }; enum flags_t { overwrite_existing = 1 };
void add_piece(int piece, char const* data, int flags = 0) c onst; void add_piece(int piece, char const* data, int flags = 0) c onst;
void read_piece(int piece) const; void read_piece(int piece) const;
bool have_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;
enum status_flags_t
{
query_distributed_copies = 1,
query_accurate_download_counters = 2,
query_last_seen_complete = 4,
query_pieces = 8,
query_verified_pieces = 16
};
// the flags specify which fields are calculated. By default
everything
// is included, you may save CPU by not querying fields you
don't need
torrent_status status(boost::uint32_t flags = 0xffffffff) co
nst;
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 }; enum deadline_flags { alert_when_available = 1 };
void set_piece_deadline(int index, int deadline, int flags = 0) const; void set_piece_deadline(int index, int deadline, int flags = 0) const;
void reset_piece_deadline(int index) const; void reset_piece_deadline(int index) const;
void set_priority(int prio) const; void set_priority(int prio) const;
#ifndef TORRENT_NO_DEPRECATE #ifndef TORRENT_NO_DEPRECATE
#if !TORRENT_NO_FPU #if !TORRENT_NO_FPU
skipping to change at line 438 skipping to change at line 227
void add_http_seed(std::string const& url) const; void add_http_seed(std::string const& url) const;
void remove_http_seed(std::string const& url) const; void remove_http_seed(std::string const& url) const;
std::set<std::string> http_seeds() 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 set_metadata(char const* metadata, int size) 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; enum pause_flags_t { graceful_pause = 1 };
bool is_finished() const; void pause(int flags = 0) const;
bool is_paused() const;
void pause() const;
void resume() const; void resume() const;
void set_upload_mode(bool b) const; void set_upload_mode(bool b) const;
void set_share_mode(bool b) const;
void flush_cache() const; void flush_cache() const;
void apply_ip_filter(bool b) const;
void force_recheck() const; void force_recheck() const;
void save_resume_data() const;
bool is_auto_managed() const; enum save_resume_flags_t { flush_disk_cache = 1, save_info_d
ict = 2 };
void save_resume_data(int flags = 0) const;
bool need_save_resume_data() 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;
void queue_position_bottom() const; void queue_position_bottom() const;
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES #ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
void resolve_countries(bool r); void resolve_countries(bool r);
bool resolve_countries() const; bool resolve_countries() const;
#endif #endif
void set_ssl_certificate(std::string const& certificate
, std::string const& private_key
, std::string const& dh_params
, std::string const& passphrase = "");
storage_interface* get_storage_impl() const; storage_interface* get_storage_impl() const;
// 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.16, feature will be removed
TORRENT_DEPRECATED_PREFIX
int get_peer_upload_limit(tcp::endpoint ip) const TORRENT_DE
PRECATED;
TORRENT_DEPRECATED_PREFIX
int get_peer_download_limit(tcp::endpoint ip) const TORRENT_
DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_peer_upload_limit(tcp::endpoint ip, int limit) cons
t TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
void set_peer_download_limit(tcp::endpoint ip, int limit) co
nst TORRENT_DEPRECATED;
// deprecated in 0.16, feature will be removed
TORRENT_DEPRECATED_PREFIX
void set_ratio(float up_down_ratio) const TORRENT_DEPRECATED
;
// deprecated in 0.16. use status() instead
TORRENT_DEPRECATED_PREFIX
bool is_seed() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool is_finished() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool is_paused() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool is_auto_managed() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool is_sequential_download() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool has_metadata() const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX
bool super_seeding() const TORRENT_DEPRECATED;
// 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 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 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 TORRENT_DEPRECATED_PREFIX
bool is_piece_filtered(int index) const TORRENT_DEPRECATED; bool is_piece_filtered(int index) const TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
skipping to change at line 555 skipping to change at line 381
// TODO: add a feature where the user can tell the torrent // TODO: add a feature where the user can tell the torrent
// to finish all pieces currently in the pipeline, and then // to finish all pieces currently in the pipeline, and then
// abort the torrent. // abort the torrent.
void set_upload_limit(int limit) const; void set_upload_limit(int limit) const;
int upload_limit() const; int upload_limit() const;
void set_download_limit(int limit) const; void set_download_limit(int limit) const;
int download_limit() const; int download_limit() const;
void set_sequential_download(bool sd) const; void set_sequential_download(bool sd) const;
bool is_sequential_download() const;
void set_peer_upload_limit(tcp::endpoint ip, int limit) cons
t;
void set_peer_download_limit(tcp::endpoint ip, int limit) co
nst;
// manually connect a peer // manually connect a peer
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 ) std::string save_path() const;
// the ratio is uploaded / downloaded. less than 1 is not al
lowed
void set_ratio(float up_down_ratio) 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; 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; 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(std::string const& save_path) const;
void rename_file(int index, fs::path const& new_name) const; void rename_file(int index, std::string const& new_name) con
st;
#ifndef BOOST_FILESYSTEM_NARROW_ONLY #if TORRENT_USE_WSTRING
void move_storage(fs::wpath const& save_path) const; void move_storage(std::wstring const& save_path) const;
void rename_file(int index, fs::wpath const& new_name) const void rename_file(int index, std::wstring const& new_name) co
; nst;
#endif #endif
bool super_seeding() const;
void super_seeding(bool on) 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(); }
skipping to change at line 617 skipping to change at line 434
{} {}
#ifdef TORRENT_DEBUG #ifdef TORRENT_DEBUG
void check_invariant() const; void check_invariant() const;
#endif #endif
boost::weak_ptr<torrent> m_torrent; boost::weak_ptr<torrent> m_torrent;
}; };
struct TORRENT_EXPORT torrent_status
{
torrent_status();
~torrent_status();
bool operator==(torrent_status const& st) const
{ return handle == st.handle; }
// handle to the torrent
torrent_handle handle;
enum state_t
{
queued_for_checking,
checking_files,
downloading_metadata,
downloading,
finished,
seeding,
allocating,
checking_resume_data
};
state_t state;
bool paused;
bool auto_managed;
bool sequential_download;
bool is_seeding;
bool is_finished;
bool has_metadata;
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;
boost::posix_time::time_duration next_announce;
boost::posix_time::time_duration announce_interval;
std::string current_tracker;
// transferred this session!
// total, payload plus protocol
size_type total_download;
size_type total_upload;
// payload only
size_type total_payload_download;
size_type total_payload_upload;
// the amount of payload bytes that
// has failed their hash test
size_type total_failed_bytes;
// the number of payload bytes that
// has been received redundantly.
size_type total_redundant_bytes;
// current transfer rate
// payload plus protocol
int download_rate;
int upload_rate;
// the rate of payload that is
// sent and received
int download_payload_rate;
int upload_payload_rate;
// the number of peers this torrent is connected to
// that are seeding.
int num_seeds;
// the number of peers this torrent
// is connected to (including seeds).
int num_peers;
// if the tracker sends scrape info in its
// announce reply, these fields will be
// set to the total number of peers that
// have the whole file and the total number
// of peers that are still downloading
int num_complete;
int num_incomplete;
// this is the number of seeds whose IP we know
// but are not necessarily connected to
int list_seeds;
// this is the number of peers whose IP we know
// (including seeds), but are not necessarily
// connected to
int list_peers;
// the number of peers in our peerlist that
// we potentially could connect to
int connect_candidates;
bitfield pieces;
bitfield verified_pieces;
// this is the number of pieces the client has
// downloaded. it is equal to:
// std::accumulate(pieces->begin(), pieces->end());
int num_pieces;
// the number of bytes of the file we have
// including pieces that may have been filtered
// after we downloaded them
size_type total_done;
// the number of bytes we have of those that we
// want. i.e. not counting bytes from pieces that
// are filtered as not wanted.
size_type total_wanted_done;
// the total number of bytes we want to download
// this may be smaller than the total torrent size
// in case any pieces are filtered as not wanted
size_type total_wanted;
// the number of distributed copies of the file.
// note that one copy may be spread out among many peers.
//
// the integer part tells how many copies
// there are of the rarest piece(s)
//
// the fractional part tells the fraction of pieces that
// 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;
// the block size that is used in this torrent. i.e.
// the number of bytes each piece request asks for
// and each bit in the download queue bitfield represents
int block_size;
int num_uploads;
int num_connections;
int uploads_limit;
int connections_limit;
// true if the torrent is saved in compact mode
// false if it is saved in full allocation mode
storage_mode_t storage_mode;
int up_bandwidth_queue;
int down_bandwidth_queue;
// number of bytes downloaded since torrent was started
// saved and restored from resume data
size_type all_time_upload;
size_type all_time_download;
// the number of seconds of being active
// and as being a seed, saved and restored
// from resume data
int active_time;
int finished_time;
int seeding_time;
// higher value means more important to seed
int seed_rank;
// number of seconds since last scrape, or -1 if
// there hasn't been a scrape
int last_scrape;
// true if there are incoming connections to this
// torrent
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;
// this is true if the torrent is in share-mode
bool share_mode;
// true if the torrent is in super seeding mode
bool super_seeding;
// the priority of this torrent
int priority;
// the time this torrent was added and completed
time_t added_time;
time_t completed_time;
time_t last_seen_complete;
// number of seconds since last upload or download activity
int time_since_upload;
int time_since_download;
// the position in the download queue where this torrent is
// this is -1 for seeds and finished torrents
int queue_position;
// true if this torrent has had changes since the last
// time resume data was saved
bool need_save_resume;
// defaults to true. Determines whether the session
// IP filter applies to this torrent or not
bool ip_filter_applies;
// the info-hash for this torrent
sha1_hash info_hash;
// if this torrent has its own listen socket, this is
// the port it's listening on. Otherwise it's 0
int listen_port;
};
} }
#endif // TORRENT_TORRENT_HANDLE_HPP_INCLUDED #endif // TORRENT_TORRENT_HANDLE_HPP_INCLUDED
 End of changes. 33 change blocks. 
271 lines changed or deleted 326 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>
#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/shared_array.hpp> #include <boost/shared_array.hpp>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/config.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/entry.hpp"
#include "libtorrent/lazy_entry.hpp" #include "libtorrent/lazy_entry.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/size_type.hpp" #include "libtorrent/size_type.hpp"
#include "libtorrent/config.hpp" #include "libtorrent/ptime.hpp"
#include "libtorrent/time.hpp"
#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"
#include "libtorrent/copy_ptr.hpp"
#include "libtorrent/socket.hpp"
#include "libtorrent/policy.hpp" // for policy::peer
namespace libtorrent namespace libtorrent
{ {
namespace pt = boost::posix_time; class peer_connection;
namespace gr = boost::gregorian; struct session_settings;
namespace fs = boost::filesystem;
enum enum
{ {
// wait 60 seconds before retrying a failed tracker // wait at least 5 seconds before retrying a failed tracker
tracker_retry_delay_min = 10 tracker_retry_delay_min = 5
// when tracker_failed_max trackers // when tracker_failed_max trackers
// has failed, wait 60 minutes instead // has failed, wait 60 minutes instead
, tracker_retry_delay_max = 60 * 60 , tracker_retry_delay_max = 60 * 60
}; };
struct TORRENT_EXPORT announce_entry struct TORRENT_EXPORT announce_entry
{ {
announce_entry(std::string const& u) announce_entry(std::string const& u);
: url(u) ~announce_entry();
, next_announce(min_time())
, min_announce(min_time())
, tier(0)
, fail_limit(0)
, fails(0)
, source(0)
, verified(false)
, updating(false)
, start_sent(false)
, complete_sent(false)
, send_stats(true)
{}
// tracker URL as it appeared in the torrent file
std::string url; std::string url;
std::string trackerid;
// if this tracker has returned an error or warning message
// that message is stored here
std::string message;
// if this tracker failed the last time it was contacted
// this error code specifies what error occurred
error_code last_error;
int next_announce_in() const; int next_announce_in() const;
int min_announce_in() const; int min_announce_in() const;
// the time of next tracker announce // the time of next tracker announce
ptime next_announce; ptime next_announce;
// no announces before this time // no announces before this time
ptime min_announce; ptime min_announce;
// the tier this tracker belongs to
boost::uint8_t tier; boost::uint8_t tier;
// the number of times this tracker can fail // the number of times this tracker can fail
// in a row before it's removed. 0 means unlimited // in a row before it's removed. 0 means unlimited
boost::uint8_t fail_limit; boost::uint8_t fail_limit;
// the number of times in a row this tracker has failed // the number of times in a row this tracker has failed
boost::uint8_t fails; boost::uint8_t fails:7;
// true if we're currently trying to announce with
// this tracker
bool updating:1;
enum tracker_source enum tracker_source
{ {
source_torrent = 1, source_torrent = 1,
source_client = 2, source_client = 2,
source_magnet_link = 4, source_magnet_link = 4,
source_tex = 8 source_tex = 8
}; };
// where did we get this tracker from // where did we get this tracker from
boost::uint8_t source; boost::uint8_t source:4;
// is set to true if we have ever received a response from // is set to true if we have ever received a response from
// this tracker // this tracker
bool verified:1; 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 // this is true if event start has been sent to the tracker
bool start_sent:1; bool start_sent:1;
// this is true if event completed has been sent to the trac ker // this is true if event completed has been sent to the trac ker
bool complete_sent:1; bool complete_sent:1;
// this is false the stats sent to this tracker will be 0 // this is false the stats sent to this tracker will be 0
bool send_stats:1; bool send_stats:1;
void reset() void reset()
{ {
start_sent = false; start_sent = false;
next_announce = min_time(); next_announce = min_time();
min_announce = min_time(); min_announce = min_time();
} }
void failed(int retry_interval = 0) void failed(session_settings const& sett, 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 will_announce(ptime now) const bool will_announce(ptime now) const
{ {
return now <= next_announce return now <= next_announce
&& (fails < fail_limit || fail_limit == 0) && (fails < fail_limit || fail_limit == 0)
&& !updating; && !updating;
} }
bool can_announce(ptime now, bool is_seed) const; bool can_announce(ptime now, bool is_seed) const;
bool is_working() const bool is_working() const
{ { return fails == 0; }
return fails == 0;
}
void trim() void trim();
};
struct web_seed_entry
{
// 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 };
typedef std::vector<std::pair<std::string, std::string> > he
aders_t;
web_seed_entry(std::string const& url_, type_t type_
, std::string const& auth_ = std::string()
, headers_t const& extra_headers_ = headers_t());
bool operator==(web_seed_entry const& e) const
{ return url == e.url && type == e.type; }
bool operator<(web_seed_entry const& e) const
{ {
while (!url.empty() && is_space(url[0])) if (url < e.url) return true;
url.erase(url.begin()); if (url > e.url) return false;
return type < e.type;
} }
std::string url;
type_t type;
std::string auth;
headers_t extra_headers;
// if this is > now, we can't reconnect yet
ptime retry;
// this indicates whether or not we're resolving the
// hostname of this URL
bool resolving;
// if the user wanted to remove this while
// we were resolving it. In this case, we set
// the removed flag to true, to make the resolver
// callback remove it
bool removed;
tcp::endpoint endpoint;
// this is the peer_info field used for the
// connection, just to count hash failures
// it's also used to hold the peer_connection
// pointer, when the web seed is connected
policy::peer peer_info;
}; };
#ifndef BOOST_NO_EXCEPTIONS #ifndef BOOST_NO_EXCEPTIONS
// for backwards compatibility with 0.14 // for backwards compatibility with 0.14
typedef libtorrent_exception invalid_torrent_file; typedef libtorrent_exception invalid_torrent_file;
#endif #endif
int TORRENT_EXPORT load_file(fs::path const& filename, std::vector<c int TORRENT_EXPORT load_file(std::string const& filename
har>& v, error_code& ec); , std::vector<char>& v, error_code& ec, int limit = 8000000)
;
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);
#ifndef BOOST_NO_EXCEPTIONS #ifdef TORRENT_DEBUG
torrent_info(lazy_entry const& torrent_file); void check_invariant() const;
torrent_info(char const* buffer, int size);
torrent_info(fs::path const& filename);
#ifndef BOOST_FILESYSTEM_NARROW_ONLY
torrent_info(fs::wpath const& filename);
#endif
#endif #endif
torrent_info(sha1_hash const& info_hash); #ifndef BOOST_NO_EXCEPTIONS
torrent_info(lazy_entry const& torrent_file, error_code& ec) torrent_info(lazy_entry const& torrent_file, int flags = 0);
; torrent_info(char const* buffer, int size, int flags = 0);
torrent_info(char const* buffer, int size, error_code& ec); torrent_info(std::string const& filename, int flags = 0);
torrent_info(fs::path const& filename, error_code& ec); #if TORRENT_USE_WSTRING
#ifndef BOOST_FILESYSTEM_NARROW_ONLY torrent_info(std::wstring const& filename, int flags = 0);
torrent_info(fs::wpath const& filename, error_code& ec); #endif // TORRENT_USE_WSTRING
#endif #endif
torrent_info(torrent_info const& t, int flags = 0);
torrent_info(sha1_hash const& info_hash, int flags = 0);
torrent_info(lazy_entry const& torrent_file, error_code& ec,
int flags = 0);
torrent_info(char const* buffer, int size, error_code& ec, i
nt flags = 0);
torrent_info(std::string const& filename, error_code& ec, in
t flags = 0);
#if TORRENT_USE_WSTRING
torrent_info(std::wstring const& filename, error_code& ec, i
nt flags = 0);
#endif // TORRENT_USE_WSTRING
~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 #if TORRENT_USE_WSTRING
void rename_file(int index, std::wstring const& new_filename ) void rename_file(int index, std::wstring const& new_filename )
{ {
copy_on_write(); copy_on_write();
m_files.rename_file(index, new_filename); m_files.rename_file(index, new_filename);
} }
#endif #endif // TORRENT_USE_WSTRING
void remap_files(file_storage const& f); 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 #ifndef TORRENT_NO_DEPRECATE
{ return m_url_seeds; } // deprecated in 0.16. Use web_seeds() instead
void add_url_seed(std::string const& url) TORRENT_DEPRECATED_PREFIX
{ m_url_seeds.push_back(url); } std::vector<std::string> url_seeds() const TORRENT_DEPRECATE
D;
TORRENT_DEPRECATED_PREFIX
std::vector<std::string> http_seeds() const TORRENT_DEPRECAT
ED;
#endif // TORRENT_NO_DEPRECATE
std::vector<std::string> const& http_seeds() const void add_url_seed(std::string const& url
{ return m_http_seeds; } , std::string const& extern_auth = std::string()
void add_http_seed(std::string const& url) , web_seed_entry::headers_t const& extra_headers = w
{ m_http_seeds.push_back(url); } eb_seed_entry::headers_t());
void add_http_seed(std::string const& url
, std::string const& extern_auth = std::string()
, web_seed_entry::headers_t const& extra_headers = w
eb_seed_entry::headers_t());
std::vector<web_seed_entry> const& web_seeds() const
{ return m_web_seeds; }
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(); }
file_iterator end_files() const { return m_files.end(); } file_iterator end_files() const { return m_files.end(); }
reverse_file_iterator rbegin_files() const { return m_files. rbegin(); } reverse_file_iterator rbegin_files() const { return m_files. rbegin(); }
reverse_file_iterator rend_files() const { return m_files.re nd(); } reverse_file_iterator rend_files() const { return m_files.re nd(); }
int num_files() const { return m_files.num_files(); } int num_files() const { return m_files.num_files(); }
file_entry const& file_at(int index) const { return m_files. at(index); } file_entry file_at(int index) const { return m_files.at(inde x); }
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_DEPRECATED_PREFIX
torrent_info(entry const& torrent_file) TORRENT_DEPRECATED; torrent_info(entry const& torrent_file) TORRENT_DEPRECATED;
TORRENT_DEPRECATED_PREFIX TORRENT_DEPRECATED_PREFIX
void print(std::ostream& os) const TORRENT_DEPRECATED; void print(std::ostream& os) const TORRENT_DEPRECATED;
// ------- end deprecation ------- // ------- end deprecation -------
#endif #endif
#ifdef TORRENT_USE_OPENSSL
std::string const& ssl_cert() const { return m_ssl_root_cert
; }
#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; }
bool is_i2p() const { return m_i2p; }
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; } std::vector<sha1_hash> const& merkle_tree() const { return m _merkle_tree; }
void set_merkle_tree(std::vector<sha1_hash>& h) void set_merkle_tree(std::vector<sha1_hash>& h)
{ TORRENT_ASSERT(h.size() == m_merkle_tree.size() ); m_merkl e_tree.swap(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());
if (is_merkle_torrent()) if (is_merkle_torrent())
{ {
TORRENT_ASSERT(index < int(m_merkle_tree.siz e()) - m_merkle_first_leaf); TORRENT_ASSERT(index < int(m_merkle_tree.siz e() - m_merkle_first_leaf));
return (const char*)&m_merkle_tree[m_merkle_ first_leaf + index][0]; return (const char*)&m_merkle_tree[m_merkle_ first_leaf + index][0];
} }
else else
{ {
TORRENT_ASSERT(m_piece_hashes); TORRENT_ASSERT(m_piece_hashes);
TORRENT_ASSERT(m_piece_hashes >= m_info_sect ion.get()); 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(m_piece_hashes < m_info_secti on.get() + m_info_section_size);
TORRENT_ASSERT(index < m_info_section_size / 20); TORRENT_ASSERT(index < int(m_info_section_si ze / 20));
return &m_piece_hashes[index*20]; return &m_piece_hashes[index*20];
} }
} }
boost::optional<pt::ptime> creation_date() const; boost::optional<time_t> 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, error_code& ex) ; bool parse_info_section(lazy_entry const& e, error_code& ec, int flags);
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)
{
error_code ec;
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,
ec);
}
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 bool add_merkle_nodes(std::map<int, sha1_hash> const& subtre e
, int piece); , int piece);
std::map<int, sha1_hash> build_merkle_list(int piece) const; std::map<int, sha1_hash> build_merkle_list(int piece) const;
bool is_merkle_torrent() const { return !m_merkle_tree.empty (); } bool is_merkle_torrent() const { return !m_merkle_tree.empty (); }
// if we're logging member offsets, we need access to them
#if defined TORRENT_DEBUG \
&& !defined TORRENT_LOGGING \
&& !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
private: private:
#endif
// not assignable // not assignable
torrent_info const& operator=(torrent_info const&); torrent_info const& operator=(torrent_info const&);
void copy_on_write(); void copy_on_write();
bool parse_torrent_file(lazy_entry const& libtorrent, error_ bool parse_torrent_file(lazy_entry const& libtorrent, error_
code& ec); code& ec, int flags);
// the index to the first leaf. This is where the hash for t
he
// first piece is stored
boost::uint32_t m_merkle_first_leaf;
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; copy_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<web_seed_entry> m_web_seeds;
std::vector<std::string> m_http_seeds;
nodes_t m_nodes; nodes_t m_nodes;
// the hash that identifies this torrent // if this is a merkle torrent, this is the merkle
sha1_hash m_info_hash; // tree. It has space for merkle_num_nodes(merkle_num_leafs(
num_pieces))
// hashes
std::vector<sha1_hash> m_merkle_tree;
// if a creation date is found in the torrent file // this is a copy of the info section from the torrent.
// this will be set to that, otherwise it'll be // it use maintained in this flat format in order to
// 1970, Jan 1 // make it available through the metadata extension
pt::ptime m_creation_date; boost::shared_array<char> m_info_section;
// this is a pointer into the m_info_section buffer
// pointing to the first byte of the first sha-1 hash
char const* m_piece_hashes;
// TODO: these strings could be lazy_entry* to save memory
// if a comment is found in the torrent file // if a comment is found in the torrent file
// this will be set to that comment // this will be set to that comment
std::string m_comment; std::string m_comment;
// 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;
#ifdef TORRENT_USE_OPENSSL
// for ssl-torrens, this contains the root
// certificate, in .pem format (i.e. ascii
// base64 encoded with head and tails)
std::string m_ssl_root_cert;
#endif
// the info section parsed. points into m_info_section
// parsed lazily
mutable lazy_entry m_info_dict;
// if a creation date is found in the torrent file
// this will be set to that, otherwise it'll be
// 1970, Jan 1
time_t m_creation_date;
// the hash that identifies this torrent
sha1_hash m_info_hash;
// the number of bytes in m_info_section
boost::uint32_t m_info_section_size:24;
// 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;
// this is a copy of the info section from the torrent.
// it use maintained in this flat format in order to
// make it available through the metadata extension
boost::shared_array<char> m_info_section;
int m_info_section_size;
// this is a pointer into the m_info_section buffer
// pointing to the first byte of the first sha-1 hash
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 // this is true if one of the trackers has an .i2p top
// parsed lazily // domain in its hostname. This means the DHT and LSD
mutable lazy_entry m_info_dict; // features are disabled for this torrent (unless the
// settings allows mixing i2p peers with regular peers)
bool m_i2p:1;
}; };
} }
#endif // TORRENT_TORRENT_INFO_HPP_INCLUDED #endif // TORRENT_TORRENT_INFO_HPP_INCLUDED
 End of changes. 50 change blocks. 
116 lines changed or deleted 208 lines changed or added


 tracker_manager.hpp   tracker_manager.hpp 
skipping to change at line 49 skipping to change at line 49
#include <ctime> #include <ctime>
#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>
#include <boost/cstdint.hpp> #include <boost/cstdint.hpp>
#include <boost/weak_ptr.hpp> #include <boost/weak_ptr.hpp>
#include <boost/intrusive_ptr.hpp> #include <boost/intrusive_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/thread/recursive_mutex.hpp>
#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 "libtorrent/config.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/entry.hpp" #include "libtorrent/address.hpp"
#include "libtorrent/session_settings.hpp"
#include "libtorrent/peer_id.hpp" #include "libtorrent/peer_id.hpp"
#include "libtorrent/peer.hpp" #include "libtorrent/peer.hpp" // peer_entry
#include "libtorrent/config.hpp" #include "libtorrent/session_settings.hpp" // proxy_settings
#include "libtorrent/time.hpp" #include "libtorrent/deadline_timer.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/size_type.hpp"
#include "libtorrent/union_endpoint.hpp"
#ifdef TORRENT_USE_OPENSSL
#include <boost/asio/ssl/context.hpp>
#endif
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;
namespace aux { struct session_impl; } 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_EXTRA_EXPORT int gzip_header(const char* buf, int size);
struct TORRENT_EXPORT tracker_request struct TORRENT_EXTRA_EXPORT tracker_request
{ {
tracker_request() tracker_request()
: kind(announce_request) : kind(announce_request)
, downloaded(-1) , downloaded(-1)
, uploaded(-1) , uploaded(-1)
, left(-1) , left(-1)
, corrupt(0) , corrupt(0)
, redundant(0) , redundant(0)
, listen_port(0) , listen_port(0)
, event(none) , event(none)
, key(0) , key(0)
, num_want(0) , num_want(0)
, send_stats(true) , send_stats(true)
, apply_ip_filter(true)
#ifdef TORRENT_USE_OPENSSL
, ssl_ctx(0)
#endif
{} {}
enum enum
{ {
announce_request, announce_request,
scrape_request scrape_request
} kind; } kind;
enum event_t enum event_t
{ {
none, none,
completed, completed,
started, started,
stopped stopped,
paused
}; };
sha1_hash info_hash; sha1_hash info_hash;
peer_id pid; peer_id pid;
size_type downloaded; size_type downloaded;
size_type uploaded; size_type uploaded;
size_type left; size_type left;
size_type corrupt; size_type corrupt;
size_type redundant; size_type redundant;
unsigned short listen_port; unsigned short listen_port;
event_t event; event_t event;
std::string url; std::string url;
std::string trackerid;
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; address bind_ip;
bool send_stats; bool send_stats;
bool apply_ip_filter;
#ifdef TORRENT_USE_OPENSSL
boost::asio::ssl::context* ssl_ctx;
#endif
}; };
struct TORRENT_EXPORT request_callback struct TORRENT_EXTRA_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& /*req*/ virtual void tracker_scrape_response(tracker_request const& /*req*/
, int /*complete*/, int /*incomplete*/, int /*downlo , int /*complete*/, int /*incomplete*/, int /*downlo
ads*/) {} ads*/
, int /*downloaders*/) {}
virtual void tracker_response( virtual void tracker_response(
tracker_request const& req tracker_request const& req
, address const& tracker_ip , address const& tracker_ip
, std::list<address> const& ip_list , std::list<address> const& ip_list
, std::vector<peer_entry>& peers , std::vector<peer_entry>& peers
, int interval , int interval
, int min_interval , int min_interval
, int complete , int complete
, int incomplete , int incomplete
, address const& external_ip) = 0; , address const& external_ip
virtual void tracker_request_timed_out( , std::string const& trackerid) = 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 , error_code const& ec
, const std::string& msg
, int retry_interval) = 0; , int retry_interval) = 0;
tcp::endpoint m_tracker_address; union_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 #else
private: private:
#endif
tracker_manager* m_manager; tracker_manager* m_manager;
}; };
struct TORRENT_EXPORT timeout_handler struct TORRENT_EXTRA_EXPORT timeout_handler
: intrusive_ptr_base<timeout_handler> : intrusive_ptr_base<timeout_handler>
, boost::noncopyable , boost::noncopyable
{ {
timeout_handler(io_service& str); timeout_handler(io_service& str);
void set_timeout(int completion_timeout, int read_timeout); void set_timeout(int completion_timeout, int read_timeout);
void restart_read_timeout(); void restart_read_timeout();
void cancel(); void cancel();
bool cancelled() const { return m_abort; } bool cancelled() const { return m_abort; }
virtual void on_timeout(error_code const& ec) = 0; virtual void on_timeout(error_code const& ec) = 0;
virtual ~timeout_handler() {} virtual ~timeout_handler() {}
#if !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
// necessary for logging member offsets
private: private:
#endif
void timeout_callback(error_code const&); void timeout_callback(error_code const&);
boost::intrusive_ptr<timeout_handler> self() boost::intrusive_ptr<timeout_handler> self()
{ return boost::intrusive_ptr<timeout_handler>(this); } { return boost::intrusive_ptr<timeout_handler>(this); }
// used for timeouts // used for timeouts
// this is set when the request has been sent // this is set when the request has been sent
ptime m_start_time; ptime m_start_time;
// this is set every time something is received // this is set every time something is received
ptime m_read_time; ptime m_read_time;
// the asio async operation // the asio async operation
deadline_timer m_timeout; deadline_timer m_timeout;
int m_completion_timeout; int m_completion_timeout;
int m_read_timeout; int m_read_timeout;
typedef boost::mutex mutex_t; typedef mutex mutex_t;
mutable mutex_t m_mutex; mutable mutex_t m_mutex;
bool m_abort; bool m_abort;
}; };
struct TORRENT_EXPORT tracker_connection struct TORRENT_EXTRA_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
, 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_disp(int code, std::string const& msg) { fail(code void fail_disp(error_code ec) { fail(ec); }
, msg.c_str()); } void fail(error_code const& ec, int code = -1, char const* m
void fail(int code, char const* msg, int interval = 0, int m sg = ""
in_interval = 0); , int interval = 0, int min_interval = 0);
void fail_timeout();
virtual void start() = 0; virtual void start() = 0;
virtual void close(); virtual void close();
address const& bind_interface() const { return m_req.bind_ip ; } address const& bind_interface() const { return m_req.bind_ip ; }
void sent_bytes(int bytes); void sent_bytes(int bytes);
void received_bytes(int bytes); void received_bytes(int bytes);
virtual bool on_receive(error_code const& ec, udp::endpoint
const& ep
, char const* buf, int size) { return false; }
virtual bool on_receive_hostname(error_code const& ec, char
const* hostname
, char const* buf, int size) { return false; }
#if !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
// necessary for logging member offsets
protected: protected:
#endif
boost::weak_ptr<request_callback> m_requester; boost::weak_ptr<request_callback> m_requester;
private:
tracker_manager& m_man; tracker_manager& m_man;
#if !defined TORRENT_VERBOSE_LOGGING \
&& !defined TORRENT_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
// necessary for logging member offsets
private:
#endif
const tracker_request m_req; const tracker_request m_req;
}; };
class TORRENT_EXPORT tracker_manager: boost::noncopyable class TORRENT_EXTRA_EXPORT tracker_manager: boost::noncopyable
{ {
public: public:
tracker_manager(aux::session_impl& ses, proxy_settings const & ps) tracker_manager(aux::session_impl& ses, proxy_settings const & ps)
: m_ses(ses) : m_ses(ses)
, m_proxy(ps) , m_proxy(ps)
, m_abort(false) {} , m_abort(false) {}
~tracker_manager(); ~tracker_manager();
void queue_request( void queue_request(
skipping to change at line 254 skipping to change at line 292
= boost::weak_ptr<request_callback>()); = boost::weak_ptr<request_callback>());
void abort_all_requests(bool all = false); void abort_all_requests(bool all = false);
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 sent_bytes(int bytes);
void received_bytes(int bytes); void received_bytes(int bytes);
bool incoming_udp(error_code const& e, udp::endpoint const&
ep, char const* buf, int size);
// this is only used for SOCKS packets, since
// they may be addressed to hostname
bool incoming_udp(error_code const& e, char const* hostname,
char const* buf, int size);
private: private:
typedef boost::recursive_mutex mutex_t; typedef 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;
aux::session_impl& m_ses; aux::session_impl& m_ses;
proxy_settings const& m_proxy; proxy_settings const& m_proxy;
bool m_abort; bool m_abort;
}; };
} }
 End of changes. 32 change blocks. 
30 lines changed or deleted 77 lines changed or added


 traversal_algorithm.hpp   traversal_algorithm.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TRAVERSAL_ALGORITHM_050324_HPP #ifndef TRAVERSAL_ALGORITHM_050324_HPP
#define TRAVERSAL_ALGORITHM_050324_HPP #define TRAVERSAL_ALGORITHM_050324_HPP
#include <vector> #include <vector>
#include <set> #include <set>
#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 <libtorrent/kademlia/observer.hpp>
#include <libtorrent/address.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 { 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; class node_impl;
// this class may not be instantiated as a stack object // this class may not be instantiated as a stack object
struct traversal_algorithm : boost::noncopyable struct traversal_algorithm : boost::noncopyable
{ {
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(observer_ptr o);
void failed(node_id const& id, bool prevent_request = false);
enum flags_t { prevent_request = 1, short_timeout = 2 };
void failed(observer_ptr o, int flags = 0);
virtual ~traversal_algorithm(); virtual ~traversal_algorithm();
boost::pool<>& allocator() const;
void status(dht_lookup& l); void status(dht_lookup& l);
void* allocate_observer();
void free_observer(void* ptr);
virtual char const* name() const { return "traversal_algorithm"; } virtual char const* name() const { return "traversal_algorithm"; }
virtual void start();
node_id const& target() const { return m_target; } node_id const& target() const { return m_target; }
protected: void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags);
template<class InIt> traversal_algorithm(node_impl& node, node_id target);
traversal_algorithm(node_impl& node, node_id target, InIt start, InI
t end); protected:
void add_requests(); void add_requests();
void add_entry(node_id const& id, udp::endpoint addr, unsigned char flags);
void add_router_entries(); void add_router_entries();
void init(); void init();
virtual void done() = 0; virtual void done();
virtual void invoke(node_id const& id, udp::endpoint addr) = 0; // should construct an algorithm dependent
// observer in ptr.
struct result virtual observer_ptr new_observer(void* ptr
{ , udp::endpoint const& ep, node_id const& id);
result(node_id const& id, udp::endpoint addr, unsigned char
f = 0)
: id(id), addr(addr), flags(f) {}
node_id id;
udp::endpoint addr;
enum { queried = 1, initial = 2, no_id = 4 };
unsigned char flags;
};
std::vector<result>::iterator last_iterator(); virtual bool invoke(observer_ptr o) { return false; }
friend void intrusive_ptr_add_ref(traversal_algorithm* p) friend void intrusive_ptr_add_ref(traversal_algorithm* p)
{ {
p->m_ref_count++; p->m_ref_count++;
} }
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_impl& m_node;
node_id m_target; node_id m_target;
std::vector<result> m_results; std::vector<observer_ptr> m_results;
std::set<udp::endpoint> m_failed;
int m_invoke_count; int m_invoke_count;
int m_branch_factor; int m_branch_factor;
int m_responses; int m_responses;
int m_timeouts; int m_timeouts;
int m_num_target_nodes;
}; };
template<class InIt>
traversal_algorithm::traversal_algorithm(
node_impl& node
, node_id target
, InIt start // <- nodes to initiate traversal with
, InIt end)
: m_ref_count(0)
, m_node(node)
, m_target(target)
, m_invoke_count(0)
, m_branch_factor(3)
, m_responses(0)
, m_timeouts(0)
{
for (InIt i = start; i != end; ++i)
{
add_entry(i->id, udp::endpoint(i->addr, i->port), result::in
itial);
}
// in case the routing table is empty, use the
// router nodes in the table
if (start == end) add_router_entries();
init();
}
} } // namespace libtorrent::dht } } // namespace libtorrent::dht
#endif // TRAVERSAL_ALGORITHM_050324_HPP #endif // TRAVERSAL_ALGORITHM_050324_HPP
 End of changes. 13 change blocks. 
51 lines changed or deleted 22 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/io_service.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/session_settings.hpp" #include "libtorrent/session_settings.hpp"
#include "libtorrent/buffer.hpp" #include "libtorrent/buffer.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"
#include <deque> #include <deque>
#include <boost/function.hpp> #include <boost/function/function4.hpp>
#include <boost/thread/mutex.hpp>
namespace libtorrent namespace libtorrent
{ {
class connection_queue; class connection_queue;
class udp_socket : public intrusive_ptr_base<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;
typedef boost::function<void(error_code const& ec
, char const*, char const* buf, int size)> callback2
_t;
udp_socket(io_service& ios, callback_t const& c, connection_ udp_socket(io_service& ios, callback_t const& c, callback2_t
queue& cc); const& c2, connection_queue& cc);
virtual ~udp_socket(); ~udp_socket();
enum flags_t { dont_drop = 1, peer_connection = 2 };
bool is_open() const bool is_open() const
{ {
return m_ipv4_sock.is_open() return m_ipv4_sock.is_open()
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
|| m_ipv6_sock.is_open() || m_ipv6_sock.is_open()
#endif #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 // this is only valid when using a socks5 proxy
rror_code& ec); void send_hostname(char const* hostname, int port, char cons
t* p, int len, error_code& ec);
void send(udp::endpoint const& ep, char const* p, int len, e
rror_code& ec, int flags = 0);
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; } bool is_closed() const { return m_abort; }
tcp::endpoint local_endpoint(error_code& ec) const
{
udp::endpoint ep = m_ipv4_sock.local_endpoint(ec);
return tcp::endpoint(ep.address(), ep.port());
}
void set_buf_size(int s);
template <class SocketOption>
void set_option(SocketOption const& opt, error_code& ec)
{
m_ipv4_sock.set_option(opt, ec);
#if TORRENT_USE_IPV6
m_ipv6_sock.set_option(opt, ec);
#endif
}
template <class SocketOption>
void get_option(SocketOption& opt, error_code& ec)
{
m_ipv4_sock.get_option(opt, ec);
}
udp::endpoint proxy_addr() const { return m_proxy_addr; }
protected: protected:
struct queued_packet struct queued_packet
{ {
udp::endpoint ep; udp::endpoint ep;
char* hostname;
buffer buf; buffer buf;
int flags;
}; };
// number of outstanding UDP socket operations
// using the UDP socket buffer
int num_outstanding() const
{
return m_v4_outstanding
#if TORRENT_USE_IPV6
+ m_v6_outstanding
#endif
;
}
private: private:
#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
// necessary for logging member offsets // necessary for logging member offsets
public: public:
#endif #endif
// callback for regular incoming packets
callback_t m_callback; callback_t m_callback;
typedef boost::mutex mutex_t; // callback for proxied incoming packets with a domain
// name as source
callback2_t m_callback2;
void on_read(udp::socket* sock, error_code const& e, std::si ze_t bytes_transferred); void on_read(udp::socket* sock, error_code const& e, std::si ze_t bytes_transferred);
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);
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();
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 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 wrap(char const* hostname, int port, char const* p, int len, error_code& ec);
void unwrap(error_code const& e, char const* buf, int size); void unwrap(error_code const& e, char const* buf, int size);
bool maybe_clear_callback(mutex_t::scoped_lock& l); void maybe_realloc_buffers(int which = 3);
bool maybe_clear_callback();
mutable mutex_t m_mutex; #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
#if defined BOOST_HAS_PTHREADS
mutable pthread_t m_thread;
#endif
bool is_single_thread() const
{
#if defined BOOST_HAS_PTHREADS
if (m_thread == 0)
m_thread = pthread_self();
return m_thread == pthread_self();
#endif
return true;
}
#endif
udp::socket m_ipv4_sock; udp::socket m_ipv4_sock;
udp::endpoint m_v4_ep; udp::endpoint m_v4_ep;
char m_v4_buf[2000]; int m_v4_buf_size;
char* m_v4_buf;
// this is set to true to indicate that the
// m_v4_buf should be reallocated to the size
// of the buffer size members the next time their
// read handler gets triggered
bool m_reallocate_buffer4;
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
udp::socket m_ipv6_sock; udp::socket m_ipv6_sock;
udp::endpoint m_v6_ep; udp::endpoint m_v6_ep;
char m_v6_buf[2000]; int m_v6_buf_size;
char* m_v6_buf;
// this is set to true to indicate that the
// m_v6_buf should be reallocated to the size
// of the buffer size members the next time their
// read handler gets triggered
bool m_reallocate_buffer6;
#endif #endif
boost::uint16_t m_bind_port; boost::uint16_t m_bind_port;
boost::uint8_t m_v4_outstanding; boost::uint8_t m_v4_outstanding;
#if TORRENT_USE_IPV6 #if TORRENT_USE_IPV6
boost::uint8_t m_v6_outstanding; boost::uint8_t m_v6_outstanding;
#endif #endif
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[270];
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::deque<queued_packet> m_queue; std::deque<queued_packet> m_queue;
// counts the number of outstanding async // counts the number of outstanding async
// operations hanging on this socket // operations hanging on this socket
int m_outstanding_ops; int m_outstanding_ops;
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
bool m_started; bool m_started;
int m_magic; int m_magic;
int m_outstanding_when_aborted; int m_outstanding_when_aborted;
#endif #endif
}; };
struct rate_limited_udp_socket : public udp_socket struct rate_limited_udp_socket : public udp_socket
{ {
rate_limited_udp_socket(io_service& ios, callback_t const& c , connection_queue& cc); rate_limited_udp_socket(io_service& ios, callback_t const& c , callback2_t const& c2, connection_queue& cc);
void set_rate_limit(int limit) { m_rate_limit = limit; } 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 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); bool send(udp::endpoint const& ep, char const* p, int len, e rror_code& ec, int flags = 0);
void close(); void close();
private: private:
void on_tick(error_code const& e); void on_tick(error_code const& e);
deadline_timer m_timer; deadline_timer m_timer;
int m_queue_size_limit; int m_queue_size_limit;
 End of changes. 22 change blocks. 
18 lines changed or deleted 96 lines changed or added


 udp_tracker_connection.hpp   udp_tracker_connection.hpp 
skipping to change at line 64 skipping to change at line 64
#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
{ {
namespace aux { struct session_impl; } namespace aux { struct session_impl; }
class TORRENT_EXPORT udp_tracker_connection: public tracker_connecti on class TORRENT_EXTRA_EXPORT udp_tracker_connection: public tracker_co nnection
{ {
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
, boost::weak_ptr<request_callback> c , boost::weak_ptr<request_callback> c
, aux::session_impl const& ses , aux::session_impl& ses
, proxy_settings const& ps); , proxy_settings const& ps);
void start(); void start();
void close(); void close();
#if !defined TORRENT_VERBOSE_LOGGING && !defined TORRENT_LOGGING && !define #if !defined TORRENT_VERBOSE_LOGGING \
d TORRENT_ERROR_LOGGING && !defined TORRENT_LOGGING \
&& !defined TORRENT_ERROR_LOGGING
// necessary for logging member offsets // necessary for logging member offsets
private: private:
#endif #endif
enum action_t enum action_t
{ {
action_connect, action_connect,
action_announce, action_announce,
action_scrape, action_scrape,
action_error action_error
}; };
boost::intrusive_ptr<udp_tracker_connection> self() boost::intrusive_ptr<udp_tracker_connection> self()
{ return boost::intrusive_ptr<udp_tracker_connection>(this); } { return boost::intrusive_ptr<udp_tracker_connection>(this); }
void name_lookup(error_code const& error, udp::resolver::ite rator i); void name_lookup(error_code const& error, tcp::resolver::ite rator i);
void timeout(error_code const& error); void timeout(error_code const& error);
void start_announce();
void on_receive(error_code const& e, udp::endpoint const& ep bool on_receive(error_code const& e, udp::endpoint const& ep
, char const* buf, int size); , char const* buf, int size);
void on_connect_response(char const* buf, int size); bool on_receive_hostname(error_code const& e, char const* ho
void on_announce_response(char const* buf, int size); stname
void on_scrape_response(char const* buf, int size); , char const* buf, int size);
bool on_connect_response(char const* buf, int size);
bool on_announce_response(char const* buf, int size);
bool on_scrape_response(char const* buf, int size);
void send_udp_connect(); void send_udp_connect();
void send_udp_announce(); void send_udp_announce();
void send_udp_scrape(); void send_udp_scrape();
virtual void on_timeout(error_code const& ec); virtual void on_timeout(error_code const& ec);
tracker_manager& m_man; // tracker_manager& m_man;
udp::resolver m_name_lookup; bool m_abort;
boost::intrusive_ptr<udp_socket> m_socket; std::string m_hostname;
udp::endpoint m_target; udp::endpoint m_target;
std::list<udp::endpoint> m_endpoints; std::list<tcp::endpoint> m_endpoints;
int m_transaction_id; int m_transaction_id;
aux::session_impl const& m_ses; aux::session_impl& m_ses;
int m_attempts; int m_attempts;
struct connection_cache_entry struct connection_cache_entry
{ {
boost::int64_t connection_id; boost::int64_t connection_id;
ptime expires; ptime expires;
}; };
static std::map<address, connection_cache_entry> m_connectio n_cache; static std::map<address, connection_cache_entry> m_connectio n_cache;
static boost::mutex m_cache_mutex; static mutex m_cache_mutex;
action_t m_state; action_t m_state;
proxy_settings m_proxy;
}; };
} }
#endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED #endif // TORRENT_UDP_TRACKER_CONNECTION_HPP_INCLUDED
 End of changes. 13 change blocks. 
15 lines changed or deleted 22 lines changed or added


 upnp.hpp   upnp.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_UPNP_HPP #ifndef TORRENT_UPNP_HPP
#define TORRENT_UPNP_HPP #define TORRENT_UPNP_HPP
#include "libtorrent/socket.hpp" #include "libtorrent/socket.hpp"
#include "libtorrent/error_code.hpp"
#include "libtorrent/broadcast_socket.hpp" #include "libtorrent/broadcast_socket.hpp"
#include "libtorrent/http_connection.hpp" #include "libtorrent/http_connection.hpp"
#include "libtorrent/connection_queue.hpp" #include "libtorrent/connection_queue.hpp"
#include "libtorrent/intrusive_ptr_base.hpp" #include "libtorrent/intrusive_ptr_base.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/deadline_timer.hpp"
#include <boost/function.hpp> #include <boost/function/function1.hpp>
#include <boost/function/function3.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/condition.hpp>
#include <set> #include <set>
#if defined(TORRENT_UPNP_LOGGING) #if defined(TORRENT_UPNP_LOGGING)
#include <fstream> #include <fstream>
#endif #endif
namespace libtorrent namespace libtorrent
{ {
namespace upnp_errors namespace upnp_errors
skipping to change at line 90 skipping to change at line 92
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 TORRENT_EXPORT upnp_error_category upnp_category; extern TORRENT_EXPORT upnp_error_category upnp_category;
#endif #endif
// int: port-mapping index // int: port-mapping index
// address: external address as queried from router
// 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
// a port-mapping index of -1 means it's // a port-mapping index of -1 means it's
// an informational log message // an informational log message
typedef boost::function<void(int, int, error_code const&)> portmap_callback _t; typedef boost::function<void(int, address, int, error_code const&)> portmap _callback_t;
typedef boost::function<void(char const*)> log_callback_t; typedef boost::function<void(char const*)> log_callback_t;
class TORRENT_EXPORT 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, log_callback_t const& lcb , portmap_callback_t const& cb, log_callback_t const& lcb
, bool ignore_nonrouters, void* state = 0); , bool ignore_nonrouters, void* state = 0);
~upnp(); ~upnp();
skipping to change at line 119 skipping to change at line 122
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; 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::scoped_lock l(m_mutex);
return m_model; return m_model;
} }
private: private:
typedef boost::mutex mutex_t; void discover_device_impl(mutex::scoped_lock& l);
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, mutex_t::scoped_lock& l); void next(rootdevice& d, int i, mutex::scoped_lock& l);
void update_map(rootdevice& d, int i, mutex_t::scoped_lock& l); void update_map(rootdevice& d, int i, mutex::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_get_ip_address_response(error_code const& e
, libtorrent::http_parser const& p, rootdevice& d
, 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(error_code const& ec, mutex_t::scoped_lock& l); void disable(error_code const& ec, mutex::scoped_lock& l);
void return_error(int mapping, int code, mutex_t::scoped_lock& l); void return_error(int mapping, int code, mutex::scoped_lock& l);
void log(char const* msg, mutex_t::scoped_lock& l); void log(char const* msg, mutex::scoped_lock& l);
void get_ip_address(rootdevice& d);
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, char const* soap void post(upnp::rootdevice const& d, char const* soap
, char const* soap_action, mutex_t::scoped_lock& l); , char const* soap_action, mutex::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 219 skipping to change at line 224
}; };
struct rootdevice struct rootdevice
{ {
rootdevice(): service_namespace(0) rootdevice(): service_namespace(0)
, port(0) , port(0)
, lease_duration(default_lease_time) , lease_duration(default_lease_time)
, supports_specific_external(true) , supports_specific_external(true)
, disabled(false) , disabled(false)
{ {
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
magic = 1337; magic = 1337;
#endif #endif
} }
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
~rootdevice() ~rootdevice()
{ {
TORRENT_ASSERT(magic == 1337); TORRENT_ASSERT(magic == 1337);
magic = 0; magic = 0;
} }
#endif #endif
// the interface url, through which the list of // the interface url, through which the list of
// supported interfaces are fetched // supported interfaces are fetched
std::string url; std::string url;
skipping to change at line 249 skipping to change at line 254
char const* service_namespace; char const* service_namespace;
std::vector<mapping_t> mapping; std::vector<mapping_t> mapping;
// this is the hostname, port and path // this is the hostname, port and path
// component of the url or the control_url // component of the url or the control_url
// if it has been found // if it has been found
std::string hostname; std::string hostname;
int port; int port;
std::string path; std::string path;
address external_ip;
int lease_duration; int lease_duration;
// true if the device supports specifying a // true if the device supports specifying a
// specific external port, false if it doesn't // specific external port, false if it doesn't
bool supports_specific_external; bool supports_specific_external;
bool disabled; bool disabled;
mutable boost::shared_ptr<http_connection> upnp_connection; mutable boost::shared_ptr<http_connection> upnp_connection;
#ifdef TORRENT_DEBUG #if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
int magic; int magic;
#endif #endif
void close() const void close() const
{ {
TORRENT_ASSERT(magic == 1337); TORRENT_ASSERT(magic == 1337);
if (!upnp_connection) return; if (!upnp_connection) return;
upnp_connection->close(); upnp_connection->close();
upnp_connection.reset(); upnp_connection.reset();
} }
skipping to change at line 312 skipping to change at line 318
// 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;
mutex_t m_mutex; mutex m_mutex;
std::string m_model; std::string m_model;
}; };
} }
#endif #endif
 End of changes. 18 change blocks. 
18 lines changed or deleted 24 lines changed or added


 utf8.hpp   utf8.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_UTF8_HPP_INCLUDED #ifndef TORRENT_UTF8_HPP_INCLUDED
#define TORRENT_UTF8_HPP_INCLUDED #define TORRENT_UTF8_HPP_INCLUDED
#include "libtorrent/config.hpp" #include "libtorrent/config.hpp"
#if !defined BOOST_FILESYSTEM_NARROW_ONLY || defined TORRENT_WINDOWS // on windows we need these functions for
// convert_to_native and convert_from_native
#if TORRENT_USE_WSTRING || defined TORRENT_WINDOWS
#include <string> #include <string>
#include <cwchar> #include <cwchar>
#include "libtorrent/ConvertUTF.h"
namespace libtorrent namespace libtorrent
{ {
TORRENT_EXPORT int utf8_wchar(const std::string &utf8, std::wstring
inline int utf8_wchar(const std::string &utf8, std::wstring &wide) &wide);
{ TORRENT_EXPORT int wchar_utf8(const std::wstring &wide, std::string
// allocate space for worst-case &utf8);
wide.resize(utf8.size());
wchar_t const* dst_start = wide.c_str();
char const* src_start = utf8.c_str();
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.c_str());
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.c_str());
return ret;
}
else
{
return sourceIllegal;
}
}
inline int wchar_utf8(const std::wstring &wide, std::string &utf8)
{
// allocate space for worst-case
utf8.resize(wide.size() * 6);
if (wide.empty()) return 0;
char* dst_start = &utf8[0];
wchar_t const* src_start = wide.c_str();
ConversionResult ret;
if (sizeof(wchar_t) == sizeof(UTF32))
{
ret = ConvertUTF32toUTF8((const UTF32**)&src_start,
(const UTF32*)src_start
+ wide.size(), (UTF8**)&dst_start, (UTF8*)ds
t_start + utf8.size()
, lenientConversion);
utf8.resize(dst_start - &utf8[0]);
return ret;
}
else if (sizeof(wchar_t) == sizeof(UTF16))
{
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 #endif // !BOOST_NO_STD_WSTRING
#endif #endif
 End of changes. 4 change blocks. 
70 lines changed or deleted 8 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 15 #define LIBTORRENT_VERSION_MINOR 16
#define LIBTORRENT_VERSION_TINY 10 #define LIBTORRENT_VERSION_TINY 1
#define LIBTORRENT_VERSION "0.15.10.0" // the format of this version is: MMmmtt
#define LIBTORRENT_REVISION "$Rev: 6415 $" // M = Major version, m = minor version, t = tiny version
#define LIBTORRENT_VERSION_NUM ((LIBTORRENT_VERSION_MAJOR * 10000) + (LIBTO
RRENT_VERSION_MINOR * 100) + LIBTORRENT_VERSION_TINY)
#define LIBTORRENT_VERSION "0.16.1.0"
#define LIBTORRENT_REVISION "$Rev: 6976 $"
#endif #endif
 End of changes. 2 change blocks. 
4 lines changed or deleted 9 lines changed or added


 web_peer_connection.hpp   web_peer_connection.hpp 
skipping to change at line 42 skipping to change at line 42
#ifndef TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED #ifndef TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
#define TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED #define TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <vector> #include <vector>
#include <deque> #include <deque>
#include <string> #include <string>
#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>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(pop) #pragma warning(pop)
#endif #endif
#include "libtorrent/buffer.hpp" #include "libtorrent/config.hpp"
#include "libtorrent/peer_connection.hpp" #include "libtorrent/web_connection_base.hpp"
#include "libtorrent/socket.hpp" #include "libtorrent/disk_buffer_holder.hpp"
#include "libtorrent/peer_id.hpp"
#include "libtorrent/storage.hpp"
#include "libtorrent/stat.hpp"
#include "libtorrent/alert.hpp"
#include "libtorrent/torrent_handle.hpp"
#include "libtorrent/torrent.hpp" #include "libtorrent/torrent.hpp"
#include "libtorrent/peer_request.hpp"
#include "libtorrent/piece_block_progress.hpp" #include "libtorrent/piece_block_progress.hpp"
#include "libtorrent/config.hpp"
// parse_url
#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_parser.hpp" #include "libtorrent/http_parser.hpp"
namespace libtorrent namespace libtorrent
{ {
class torrent; class torrent;
namespace detail namespace detail
{ {
struct session_impl; struct session_impl;
} }
class TORRENT_EXPORT web_peer_connection class TORRENT_EXTRA_EXPORT web_peer_connection
: public peer_connection : public web_connection_base
{ {
friend class invariant_access; friend class invariant_access;
public: public:
// this is the constructor where the we are the active part. // this is the constructor where the we are the active part.
// The peer_conenction should handshake and verify that the // The peer_conenction should handshake and verify that the
// other end has the correct id // other end has the correct id
web_peer_connection( web_peer_connection(
aux::session_impl& ses aux::session_impl& ses
, boost::weak_ptr<torrent> t , boost::weak_ptr<torrent> t
, boost::shared_ptr<socket_type> s , boost::shared_ptr<socket_type> s
, tcp::endpoint const& remote , tcp::endpoint const& remote
, std::string const& url , std::string const& url
, policy::peer* peerinfo); , policy::peer* peerinfo
void start(); , std::string const& ext_auth
, web_seed_entry::headers_t const& ext_headers);
~web_peer_connection(); virtual int type() const { return peer_connection::url_seed_ connection; }
// called from the main loop when this connection has any // called from the main loop when this connection has any
// work to do. // work to do.
void on_sent(error_code const& error
, std::size_t bytes_transferred);
void on_receive(error_code const& error void on_receive(error_code const& error
, std::size_t bytes_transferred); , std::size_t bytes_transferred);
std::string const& url() const { return m_original_url; } std::string const& url() const { return m_url; }
virtual void get_specific_peer_info(peer_info& p) const; virtual void get_specific_peer_info(peer_info& p) const;
virtual bool in_handshake() const; virtual void disconnect(error_code const& ec, int error = 0) ;
// the following functions appends messages
// to the send buffer
void write_choke() {}
void write_unchoke() {}
void write_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)
{ incoming_reject_request(r); }
void write_have(int index) {}
void write_piece(peer_request const& r, disk_buffer_holder&
buffer) { TORRENT_ASSERT(false); }
void write_keepalive() {}
void on_connected();
void write_reject_request(peer_request const&) {}
void write_allow_fast(int) {}
#ifdef TORRENT_DEBUG
void check_invariant() const;
#endif
private: private:
bool maybe_harvest_block();
// returns the block currently being // returns the block currently being
// downloaded. And the progress of that // downloaded. And the progress of that
// block. If the peer isn't downloading // block. If the peer isn't downloading
// a piece for the moment, the boost::optional // a piece for the moment, the boost::optional
// will be invalid. // will be invalid.
boost::optional<piece_block_progress> downloading_piece_prog ress() const; boost::optional<piece_block_progress> downloading_piece_prog ress() const;
// this has one entry per bittorrent request
std::deque<peer_request> m_requests;
// this has one entry per http-request // this has one entry per http-request
// (might be more than the bt requests) // (might be more than the bt requests)
std::deque<int> m_file_requests; std::deque<int> m_file_requests;
std::string m_server_string;
http_parser m_parser;
std::string m_auth;
std::string m_host;
int m_port;
std::string m_path;
std::string m_url; std::string m_url;
const std::string m_original_url;
// the first request will contain a little bit more data
// than subsequent ones, things that aren't critical are lef
t
// out to save bandwidth.
bool m_first_request;
// this is used for intermediate storage of pieces // this is used for intermediate storage of pieces
// that are received in more than one HTTP response // that are received in more than one HTTP response
// TODO: if we make this be a disk_buffer_holder instead
// we would save a copy sometimes
std::vector<char> m_piece; std::vector<char> m_piece;
// the number of bytes into the receive buffer where
// current read cursor is.
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; size_type m_received_body;
// position in the current range response // position in the current range response
int m_range_pos; size_type m_range_pos;
// the position in the current block // the position in the current block
int m_block_pos; int m_block_pos;
// this is the offset inside the current receive
// buffer where the next chunk header will be.
// this is updated for each chunk header that's
// parsed. It does not necessarily point to a valid
// offset in the receive buffer, if we haven't received
// it yet. This offset never includes the HTTP header
size_type m_chunk_pos;
// this is the number of bytes we've already received
// from the next chunk header we're waiting for
int m_partial_chunk_header;
}; };
} }
#endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED #endif // TORRENT_WEB_PEER_CONNECTION_HPP_INCLUDED
 End of changes. 21 change blocks. 
62 lines changed or deleted 29 lines changed or added


 xml_parse.hpp   xml_parse.hpp 
skipping to change at line 39 skipping to change at line 39
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef TORRENT_XML_PARSE_HPP #ifndef TORRENT_XML_PARSE_HPP
#define TORRENT_XML_PARSE_HPP #define TORRENT_XML_PARSE_HPP
#include <cctype> #include <cctype>
#include <cstring> #include <cstring>
#include "libtorrent/escape_string.hpp"
namespace libtorrent namespace libtorrent
{ {
enum enum
{ {
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,
// used for tags that don't follow the convention of
// key-value pairs inside the tag brackets. Like !DOCTYPE
xml_tag_content
}; };
// 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)
skipping to change at line 84 skipping to change at line 89
} }
token = xml_string; token = xml_string;
callback(token, start, val_start); callback(token, start, val_start);
if (p != end) *p = '<'; if (p != end) *p = '<';
} }
if (p == end) break; if (p == end) break;
// skip '<' // skip '<'
++p; ++p;
if (p != end && p+8 < end && string_begins_no_case("
![CDATA[", p))
{
// CDATA. match '![CDATA['
p += 8;
start = p;
while (p != end && !string_begins_no_case("]
]>", p-2)) ++p;
// parse error
if (p == end)
{
token = xml_parse_error;
start = "unexpected end of file";
callback(token, start, val_start);
break;
}
token = xml_string;
char tmp = p[-2];
p[-2] = 0;
callback(token, start, val_start);
p[-2] = tmp;
continue;
}
// parse the name of the tag. // parse the name of the tag.
for (start = p; p != end && *p != '>' && !is_space(* p); ++p); for (start = p; p != end && *p != '>' && !is_space(* p); ++p);
char* tag_name_end = p; char* tag_name_end = p;
// skip the attributes for now // skip the attributes for now
for (; p != end && *p != '>'; ++p); for (; p != end && *p != '>'; ++p);
// parse error // parse error
skipping to change at line 163 skipping to change at line 191
for (; i != tag_end && is_space(*i); ++i); for (; i != tag_end && is_space(*i); ++i);
if (i == tag_end) break; if (i == tag_end) break;
start = i; start = i;
// find end of attribute name // find end of attribute name
for (; i != tag_end && *i != '=' && !is_spac e(*i); ++i); for (; i != tag_end && *i != '=' && !is_spac e(*i); ++i);
char* name_end = i; char* name_end = i;
// look for equality sign // look for equality sign
for (; i != tag_end && *i != '='; ++i); for (; i != tag_end && *i != '='; ++i);
// no equality sign found. Report this as xm
l_tag_content
// instead of a series of key value pairs
if (i == tag_end) if (i == tag_end)
{ {
token = xml_parse_error; char tmp = *i;
*i = 0; // null terminate the conten
t string
token = xml_tag_content;
val_start = 0; val_start = 0;
start = "garbage inside element brac kets";
callback(token, start, val_start); callback(token, start, val_start);
*i = tmp;
break; break;
} }
++i; ++i;
for (; i != tag_end && is_space(*i); ++i); for (; i != tag_end && is_space(*i); ++i);
// check for parse error (values must be quo ted) // check for parse error (values must be quo ted)
if (i == tag_end || (*i != '\'' && *i != '\" ')) if (i == tag_end || (*i != '\'' && *i != '\" '))
{ {
token = xml_parse_error; token = xml_parse_error;
val_start = 0; val_start = 0;
 End of changes. 7 change blocks. 
3 lines changed or deleted 39 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/