finish sync
This commit is contained in:
parent
b2fe562dd4
commit
a9961adda7
|
@ -33,12 +33,14 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <cassert>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#if defined __linux__ && defined __GNUC__
|
||||
#if (defined __linux__ || defined __MACH__) && defined __GNUC__
|
||||
#ifdef assert
|
||||
#undef assert
|
||||
#endif
|
||||
|
||||
void assert_fail(const char* expr, int line, char const* file, char const* function);
|
||||
#include "libtorrent/config.hpp"
|
||||
|
||||
TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
|
||||
|
||||
#define assert(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)
|
||||
|
||||
|
|
|
@ -185,7 +185,7 @@ namespace libtorrent
|
|||
~session_impl();
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
|
||||
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext);
|
||||
#endif
|
||||
void operator()();
|
||||
|
||||
|
@ -246,7 +246,8 @@ namespace libtorrent
|
|||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, storage_constructor_type sc
|
||||
, bool paused);
|
||||
, bool paused
|
||||
, void* userdata);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
char const* tracker_url
|
||||
|
@ -256,7 +257,8 @@ namespace libtorrent
|
|||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, storage_constructor_type sc
|
||||
, bool paused);
|
||||
, bool paused
|
||||
, void* userdata);
|
||||
|
||||
void remove_torrent(torrent_handle const& h);
|
||||
|
||||
|
@ -519,7 +521,7 @@ namespace libtorrent
|
|||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
typedef std::list<boost::function<boost::shared_ptr<
|
||||
torrent_plugin>(torrent*)> > extension_list_t;
|
||||
torrent_plugin>(torrent*, void*)> > extension_list_t;
|
||||
|
||||
extension_list_t m_extensions;
|
||||
#endif
|
||||
|
|
|
@ -180,6 +180,7 @@ struct bandwidth_manager
|
|||
, m_limit(bandwidth_limit::inf)
|
||||
, m_current_quota(0)
|
||||
, m_channel(channel)
|
||||
, m_in_hand_out_bandwidth(false)
|
||||
{}
|
||||
|
||||
void throttle(int limit) throw()
|
||||
|
@ -328,6 +329,10 @@ private:
|
|||
|
||||
void hand_out_bandwidth() throw()
|
||||
{
|
||||
// if we're already handing out bandwidth, just return back
|
||||
// to the loop further down on the callstack
|
||||
if (m_in_hand_out_bandwidth) return;
|
||||
m_in_hand_out_bandwidth = true;
|
||||
#ifndef NDEBUG
|
||||
try {
|
||||
#endif
|
||||
|
@ -361,6 +366,7 @@ private:
|
|||
if (qe.peer->is_disconnecting())
|
||||
{
|
||||
t->expire_bandwidth(m_channel, qe.max_block_size);
|
||||
assert(amount == limit - m_current_quota);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -374,6 +380,7 @@ private:
|
|||
if (max_assignable == 0)
|
||||
{
|
||||
t->expire_bandwidth(m_channel, qe.max_block_size);
|
||||
assert(amount == limit - m_current_quota);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -388,15 +395,15 @@ private:
|
|||
// the history window is one second, and the block will be forgotten
|
||||
// after one second.
|
||||
int block_size = (std::min)(qe.peer->bandwidth_throttle(m_channel)
|
||||
, m_limit / 10);
|
||||
, limit / 10);
|
||||
|
||||
if (block_size < min_bandwidth_block_size)
|
||||
{
|
||||
block_size = (std::min)(int(min_bandwidth_block_size), m_limit);
|
||||
block_size = (std::min)(int(min_bandwidth_block_size), limit);
|
||||
}
|
||||
else if (block_size > max_bandwidth_block_size)
|
||||
{
|
||||
if (m_limit == bandwidth_limit::inf)
|
||||
if (limit == bandwidth_limit::inf)
|
||||
{
|
||||
block_size = max_bandwidth_block_size;
|
||||
}
|
||||
|
@ -407,8 +414,8 @@ private:
|
|||
// as possible
|
||||
// TODO: move this calculcation to where the limit
|
||||
// is changed
|
||||
block_size = m_limit
|
||||
/ (m_limit / max_bandwidth_block_size);
|
||||
block_size = limit
|
||||
/ (limit / max_bandwidth_block_size);
|
||||
}
|
||||
}
|
||||
if (block_size > qe.max_block_size) block_size = qe.max_block_size;
|
||||
|
@ -428,18 +435,21 @@ private:
|
|||
int hand_out_amount = (std::min)((std::min)(block_size, max_assignable)
|
||||
, amount);
|
||||
assert(hand_out_amount > 0);
|
||||
assert(amount == limit - m_current_quota);
|
||||
amount -= hand_out_amount;
|
||||
assert(hand_out_amount <= qe.max_block_size);
|
||||
t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size);
|
||||
qe.peer->assign_bandwidth(m_channel, hand_out_amount);
|
||||
add_history_entry(history_entry<PeerConnection, Torrent>(
|
||||
qe.peer, t, hand_out_amount, now + bw_window_size));
|
||||
assert(amount == limit - m_current_quota);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{ assert(false); };
|
||||
#endif
|
||||
m_in_hand_out_bandwidth = false;
|
||||
}
|
||||
|
||||
|
||||
|
@ -472,6 +482,11 @@ private:
|
|||
// this is the channel within the consumers
|
||||
// that bandwidth is assigned to (upload or download)
|
||||
int m_channel;
|
||||
|
||||
// this is true while we're in the hand_out_bandwidth loop
|
||||
// to prevent recursive invocations to interfere
|
||||
bool m_in_hand_out_bandwidth;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@ namespace libtorrent
|
|||
{
|
||||
|
||||
bool is_local(address const& a);
|
||||
bool is_loopback(address const& addr);
|
||||
bool is_multicast(address const& addr);
|
||||
|
||||
address_v4 guess_local_address(asio::io_service&);
|
||||
|
||||
typedef boost::function<void(udp::endpoint const& from
|
||||
|
@ -51,7 +54,8 @@ namespace libtorrent
|
|||
{
|
||||
public:
|
||||
broadcast_socket(asio::io_service& ios, udp::endpoint const& multicast_endpoint
|
||||
, receive_handler_t const& handler);
|
||||
, receive_handler_t const& handler, bool loopback = true);
|
||||
~broadcast_socket() { close(); }
|
||||
|
||||
void send(char const* buffer, int size, asio::error_code& ec);
|
||||
void close();
|
||||
|
|
|
@ -34,7 +34,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#define TORRENT_CONFIG_HPP_INCLUDED
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
|
||||
|
|
|
@ -30,6 +30,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
#include <fstream>
|
||||
#endif
|
||||
|
||||
#include "libtorrent/storage.hpp"
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
@ -50,6 +54,7 @@ namespace libtorrent
|
|||
, buffer_size(0)
|
||||
, piece(0)
|
||||
, offset(0)
|
||||
, priority(0)
|
||||
{}
|
||||
|
||||
enum action_t
|
||||
|
@ -72,6 +77,12 @@ namespace libtorrent
|
|||
// to the error message
|
||||
std::string str;
|
||||
|
||||
// priority decides whether or not this
|
||||
// job will skip entries in the queue or
|
||||
// not. It always skips in front of entries
|
||||
// with lower priority
|
||||
int priority;
|
||||
|
||||
// this is called when operation completes
|
||||
boost::function<void(int, disk_io_job const&)> callback;
|
||||
};
|
||||
|
@ -115,6 +126,10 @@ namespace libtorrent
|
|||
int m_block_size;
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
std::ofstream m_log;
|
||||
#endif
|
||||
|
||||
// thread for performing blocking disk io operations
|
||||
boost::thread m_disk_io_thread;
|
||||
};
|
||||
|
|
|
@ -149,6 +149,12 @@ namespace libtorrent
|
|||
virtual bool on_cancel(peer_request const& req)
|
||||
{ return false; }
|
||||
|
||||
virtual bool on_reject(peer_request const& req)
|
||||
{ return false; }
|
||||
|
||||
virtual bool on_suggest(int index)
|
||||
{ return false; }
|
||||
|
||||
// called when an extended message is received. If returning true,
|
||||
// the message is not processed by any other plugin and if false
|
||||
// is returned the next plugin in the chain will receive it to
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace libtorrent
|
|||
{
|
||||
struct torrent_plugin;
|
||||
class torrent;
|
||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent*);
|
||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent*, void*);
|
||||
}
|
||||
|
||||
#endif // TORRENT_METADATA_TRANSFER_HPP_INCLUDED
|
||||
|
|
|
@ -48,7 +48,7 @@ namespace libtorrent
|
|||
{
|
||||
struct torrent_plugin;
|
||||
class torrent;
|
||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*);
|
||||
TORRENT_EXPORT boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent*, void*);
|
||||
}
|
||||
|
||||
#endif // TORRENT_UT_PEX_EXTENSION_HPP_INCLUDED
|
||||
|
|
|
@ -180,4 +180,3 @@ namespace libtorrent
|
|||
|
||||
#endif // TORRENT_HTTP_TRACKER_CONNECTION_HPP_INCLUDED
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ namespace libtorrent
|
|||
template<class T>
|
||||
struct intrusive_ptr_base
|
||||
{
|
||||
intrusive_ptr_base(const intrusive_ptr_base<T>& b)
|
||||
intrusive_ptr_base(intrusive_ptr_base<T> const&)
|
||||
: m_refs(0) {}
|
||||
|
||||
friend void intrusive_ptr_add_ref(intrusive_ptr_base<T> const* s)
|
||||
|
|
|
@ -72,7 +72,8 @@ namespace libtorrent
|
|||
dht = 0x2,
|
||||
pex = 0x4,
|
||||
lsd = 0x8,
|
||||
resume_data = 0x10
|
||||
resume_data = 0x10,
|
||||
incoming = 0x20
|
||||
};
|
||||
|
||||
int source;
|
||||
|
|
|
@ -233,7 +233,7 @@ namespace libtorrent
|
|||
bool is_finished(piece_block block) const;
|
||||
|
||||
// marks this piece-block as queued for downloading
|
||||
void mark_as_downloading(piece_block block, void* peer
|
||||
bool mark_as_downloading(piece_block block, void* peer
|
||||
, piece_state_t s);
|
||||
void mark_as_writing(piece_block block, void* peer);
|
||||
void mark_as_finished(piece_block block, void* peer);
|
||||
|
|
|
@ -150,7 +150,8 @@ namespace libtorrent
|
|||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, bool paused = false
|
||||
, storage_constructor_type sc = default_storage_constructor);
|
||||
, storage_constructor_type sc = default_storage_constructor
|
||||
, void* userdata = 0);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
char const* tracker_url
|
||||
|
@ -160,7 +161,8 @@ namespace libtorrent
|
|||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, bool paused = false
|
||||
, storage_constructor_type sc = default_storage_constructor);
|
||||
, storage_constructor_type sc = default_storage_constructor
|
||||
, void* userdata = 0);
|
||||
|
||||
session_proxy abort() { return session_proxy(m_impl); }
|
||||
|
||||
|
@ -181,7 +183,7 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
|
||||
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext);
|
||||
#endif
|
||||
|
||||
void set_ip_filter(ip_filter const& f);
|
||||
|
|
|
@ -0,0 +1,594 @@
|
|||
/*
|
||||
|
||||
Copyright (c) 2006, Arvid Norberg
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the author nor the names of its
|
||||
contributors may be used to endorse or promote products derived
|
||||
from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_SESSION_IMPL_HPP_INCLUDED
|
||||
#define TORRENT_SESSION_IMPL_HPP_INCLUDED
|
||||
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
#endif
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/thread/recursive_mutex.hpp>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#include "libtorrent/torrent_handle.hpp"
|
||||
#include "libtorrent/entry.hpp"
|
||||
#include "libtorrent/torrent_info.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/peer_connection.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/policy.hpp"
|
||||
#include "libtorrent/tracker_manager.hpp"
|
||||
#include "libtorrent/peer_info.hpp"
|
||||
#include "libtorrent/alert.hpp"
|
||||
#include "libtorrent/fingerprint.hpp"
|
||||
#include "libtorrent/debug.hpp"
|
||||
#include "libtorrent/peer_request.hpp"
|
||||
#include "libtorrent/piece_block_progress.hpp"
|
||||
#include "libtorrent/ip_filter.hpp"
|
||||
#include "libtorrent/config.hpp"
|
||||
#include "libtorrent/session_settings.hpp"
|
||||
#include "libtorrent/kademlia/dht_tracker.hpp"
|
||||
#include "libtorrent/session_status.hpp"
|
||||
#include "libtorrent/session.hpp"
|
||||
#include "libtorrent/stat.hpp"
|
||||
#include "libtorrent/file_pool.hpp"
|
||||
#include "libtorrent/bandwidth_manager.hpp"
|
||||
#include "libtorrent/natpmp.hpp"
|
||||
#include "libtorrent/upnp.hpp"
|
||||
#include "libtorrent/lsd.hpp"
|
||||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/connection_queue.hpp"
|
||||
#include "libtorrent/disk_io_thread.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
namespace fs = boost::filesystem;
|
||||
|
||||
namespace aux
|
||||
{
|
||||
struct session_impl;
|
||||
|
||||
// this data is shared between the main thread and the
|
||||
// thread that initialize pieces
|
||||
struct piece_checker_data
|
||||
{
|
||||
piece_checker_data()
|
||||
: processing(false), progress(0.f), abort(false) {}
|
||||
|
||||
boost::shared_ptr<torrent> torrent_ptr;
|
||||
fs::path save_path;
|
||||
|
||||
sha1_hash info_hash;
|
||||
|
||||
void parse_resume_data(
|
||||
const entry& rd
|
||||
, const torrent_info& info
|
||||
, std::string& error);
|
||||
|
||||
std::vector<int> piece_map;
|
||||
std::vector<piece_picker::downloading_piece> unfinished_pieces;
|
||||
std::vector<piece_picker::block_info> block_info;
|
||||
std::vector<tcp::endpoint> peers;
|
||||
entry resume_data;
|
||||
|
||||
// this is true if this torrent is being processed (checked)
|
||||
// if it is not being processed, then it can be removed from
|
||||
// the queue without problems, otherwise the abort flag has
|
||||
// to be set.
|
||||
bool processing;
|
||||
|
||||
// is filled in by storage::initialize_pieces()
|
||||
// and represents the progress. It should be a
|
||||
// value in the range [0, 1]
|
||||
float progress;
|
||||
|
||||
// abort defaults to false and is typically
|
||||
// filled in by torrent_handle when the user
|
||||
// aborts the torrent
|
||||
bool abort;
|
||||
};
|
||||
|
||||
struct checker_impl: boost::noncopyable
|
||||
{
|
||||
checker_impl(session_impl& s): m_ses(s), m_abort(false) {}
|
||||
void operator()();
|
||||
piece_checker_data* find_torrent(const sha1_hash& info_hash);
|
||||
void remove_torrent(sha1_hash const& info_hash);
|
||||
|
||||
#ifndef NDEBUG
|
||||
void check_invariant() const;
|
||||
#endif
|
||||
|
||||
// when the files has been checked
|
||||
// the torrent is added to the session
|
||||
session_impl& m_ses;
|
||||
|
||||
mutable boost::mutex m_mutex;
|
||||
boost::condition m_cond;
|
||||
|
||||
// a list of all torrents that are currently in queue
|
||||
// or checking their files
|
||||
std::deque<boost::shared_ptr<piece_checker_data> > m_torrents;
|
||||
std::deque<boost::shared_ptr<piece_checker_data> > m_processing;
|
||||
|
||||
bool m_abort;
|
||||
};
|
||||
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
struct tracker_logger;
|
||||
#endif
|
||||
|
||||
// this is the link between the main thread and the
|
||||
// thread started to run the main downloader loop
|
||||
struct session_impl: boost::noncopyable
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
friend class ::libtorrent::peer_connection;
|
||||
#endif
|
||||
friend struct checker_impl;
|
||||
friend class invariant_access;
|
||||
typedef std::map<boost::shared_ptr<socket_type>
|
||||
, boost::intrusive_ptr<peer_connection> >
|
||||
connection_map;
|
||||
typedef std::map<sha1_hash, boost::shared_ptr<torrent> > torrent_map;
|
||||
|
||||
session_impl(
|
||||
std::pair<int, int> listen_port_range
|
||||
, fingerprint const& cl_fprint
|
||||
, char const* listen_interface = "0.0.0.0");
|
||||
~session_impl();
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
void add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext);
|
||||
#endif
|
||||
void operator()();
|
||||
|
||||
void open_listen_port();
|
||||
|
||||
void async_accept();
|
||||
void on_incoming_connection(boost::shared_ptr<socket_type> const& s
|
||||
, boost::weak_ptr<socket_acceptor> const& as, asio::error_code const& e);
|
||||
|
||||
// must be locked to access the data
|
||||
// in this struct
|
||||
typedef boost::recursive_mutex mutex_t;
|
||||
mutable mutex_t m_mutex;
|
||||
|
||||
boost::weak_ptr<torrent> find_torrent(const sha1_hash& info_hash);
|
||||
peer_id const& get_peer_id() const { return m_peer_id; }
|
||||
|
||||
void close_connection(boost::intrusive_ptr<peer_connection> const& p);
|
||||
void connection_failed(boost::shared_ptr<socket_type> const& s
|
||||
, tcp::endpoint const& a, char const* message);
|
||||
|
||||
void set_settings(session_settings const& s);
|
||||
session_settings const& settings() const { return m_settings; }
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
void add_dht_node(std::pair<std::string, int> const& node);
|
||||
void add_dht_node(udp::endpoint n);
|
||||
void add_dht_router(std::pair<std::string, int> const& node);
|
||||
void set_dht_settings(dht_settings const& s);
|
||||
dht_settings const& get_dht_settings() const { return m_dht_settings; }
|
||||
void start_dht(entry const& startup_state);
|
||||
void stop_dht();
|
||||
entry dht_state() const;
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
void set_pe_settings(pe_settings const& settings);
|
||||
pe_settings const& get_pe_settings() const { return m_pe_settings; }
|
||||
#endif
|
||||
|
||||
// called when a port mapping is successful, or a router returns
|
||||
// a failure to map a port
|
||||
void on_port_mapping(int tcp_port, int udp_port, std::string const& errmsg);
|
||||
|
||||
bool is_aborted() const { return m_abort; }
|
||||
|
||||
void set_ip_filter(ip_filter const& f);
|
||||
void set_port_filter(port_filter const& f);
|
||||
|
||||
bool listen_on(
|
||||
std::pair<int, int> const& port_range
|
||||
, const char* net_interface = 0);
|
||||
bool is_listening() const;
|
||||
|
||||
torrent_handle add_torrent(
|
||||
torrent_info const& ti
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size
|
||||
, storage_constructor_type sc);
|
||||
|
||||
torrent_handle add_torrent(
|
||||
char const* tracker_url
|
||||
, sha1_hash const& info_hash
|
||||
, char const* name
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, int block_size
|
||||
, storage_constructor_type sc);
|
||||
|
||||
void remove_torrent(torrent_handle const& h);
|
||||
|
||||
std::vector<torrent_handle> get_torrents();
|
||||
|
||||
void set_severity_level(alert::severity_t s);
|
||||
std::auto_ptr<alert> pop_alert();
|
||||
|
||||
int upload_rate_limit() const;
|
||||
int download_rate_limit() const;
|
||||
|
||||
void set_download_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_connections(int limit);
|
||||
void set_max_uploads(int limit);
|
||||
|
||||
int max_connections() const { return m_max_connections; }
|
||||
int max_uploads() const { return m_max_uploads; }
|
||||
|
||||
int num_uploads() const { return m_num_unchoked; }
|
||||
int num_connections() const
|
||||
{ return m_connections.size(); }
|
||||
|
||||
void unchoke_peer(peer_connection& c)
|
||||
{
|
||||
c.send_unchoke();
|
||||
++m_num_unchoked;
|
||||
}
|
||||
|
||||
session_status status() const;
|
||||
void set_peer_id(peer_id const& id);
|
||||
void set_key(int key);
|
||||
unsigned short listen_port() const;
|
||||
|
||||
void abort();
|
||||
|
||||
torrent_handle find_torrent_handle(sha1_hash const& info_hash);
|
||||
|
||||
void announce_lsd(sha1_hash const& ih);
|
||||
|
||||
void set_peer_proxy(proxy_settings const& s)
|
||||
{ m_peer_proxy = s; }
|
||||
void set_web_seed_proxy(proxy_settings const& s)
|
||||
{ m_web_seed_proxy = s; }
|
||||
void set_tracker_proxy(proxy_settings const& s)
|
||||
{ m_tracker_proxy = s; }
|
||||
|
||||
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
|
||||
void set_dht_proxy(proxy_settings const& s)
|
||||
{ m_dht_proxy = s; }
|
||||
proxy_settings const& dht_proxy() const
|
||||
{ return m_dht_proxy; }
|
||||
#endif
|
||||
|
||||
void start_lsd();
|
||||
void start_natpmp();
|
||||
void start_upnp();
|
||||
|
||||
void stop_lsd();
|
||||
void stop_natpmp();
|
||||
void stop_upnp();
|
||||
|
||||
// handles delayed alerts
|
||||
alert_manager m_alerts;
|
||||
|
||||
// private:
|
||||
|
||||
void on_lsd_peer(tcp::endpoint peer, sha1_hash const& ih);
|
||||
|
||||
// this is where all active sockets are stored.
|
||||
// the selector can sleep while there's no activity on
|
||||
// them
|
||||
io_service m_io_service;
|
||||
asio::strand m_strand;
|
||||
|
||||
// the file pool that all storages in this session's
|
||||
// torrents uses. It sets a limit on the number of
|
||||
// open files by this session.
|
||||
// file pool must be destructed after the torrents
|
||||
// since they will still have references to it
|
||||
// when they are destructed.
|
||||
file_pool m_files;
|
||||
|
||||
// handles disk io requests asynchronously
|
||||
disk_io_thread m_disk_thread;
|
||||
|
||||
// this is a list of half-open tcp connections
|
||||
// (only outgoing connections)
|
||||
// this has to be one of the last
|
||||
// members to be destructed
|
||||
connection_queue m_half_open;
|
||||
|
||||
// the bandwidth manager is responsible for
|
||||
// handing out bandwidth to connections that
|
||||
// asks for it, it can also throttle the
|
||||
// rate.
|
||||
bandwidth_manager<peer_connection, torrent> m_download_channel;
|
||||
bandwidth_manager<peer_connection, torrent> m_upload_channel;
|
||||
|
||||
bandwidth_manager<peer_connection, torrent>* m_bandwidth_manager[2];
|
||||
|
||||
tracker_manager m_tracker_manager;
|
||||
torrent_map m_torrents;
|
||||
|
||||
// this maps sockets to their peer_connection
|
||||
// object. It is the complete list of all connected
|
||||
// peers.
|
||||
connection_map m_connections;
|
||||
|
||||
// filters incoming connections
|
||||
ip_filter m_ip_filter;
|
||||
|
||||
// filters outgoing connections
|
||||
port_filter m_port_filter;
|
||||
|
||||
// the peer id that is generated at the start of the session
|
||||
peer_id m_peer_id;
|
||||
|
||||
// the key is an id that is used to identify the
|
||||
// client with the tracker only. It is randomized
|
||||
// at startup
|
||||
int m_key;
|
||||
|
||||
// the range of ports we try to listen on
|
||||
std::pair<int, int> m_listen_port_range;
|
||||
|
||||
// the ip-address of the interface
|
||||
// we are supposed to listen on.
|
||||
// if the ip is set to zero, it means
|
||||
// that we should let the os decide which
|
||||
// interface to listen on
|
||||
tcp::endpoint m_listen_interface;
|
||||
|
||||
// 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 m_external_listen_port;
|
||||
|
||||
boost::shared_ptr<socket_acceptor> m_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
|
||||
|
||||
// set to true when the session object
|
||||
// is being destructed and the thread
|
||||
// should exit
|
||||
volatile bool m_abort;
|
||||
|
||||
int m_max_uploads;
|
||||
int m_max_connections;
|
||||
|
||||
// the number of unchoked peers
|
||||
int m_num_unchoked;
|
||||
|
||||
// this is initialized to the unchoke_interval
|
||||
// session_setting and decreased every second.
|
||||
// when it reaches zero, it is reset to the
|
||||
// unchoke_interval and the unchoke set is
|
||||
// recomputed.
|
||||
int m_unchoke_time_scaler;
|
||||
|
||||
// works like unchoke_time_scaler but it
|
||||
// is only decresed when the unchoke set
|
||||
// is recomputed, and when it reaches zero,
|
||||
// the optimistic unchoke is moved to another peer.
|
||||
int m_optimistic_unchoke_time_scaler;
|
||||
|
||||
// works like unchoke_time_scaler. Each time
|
||||
// it reaches 0, and all the connections are
|
||||
// used, the worst connection will be disconnected
|
||||
// from the torrent with the most peers
|
||||
int m_disconnect_time_scaler;
|
||||
|
||||
// statistics gathered from all torrents.
|
||||
stat m_stat;
|
||||
|
||||
// is false by default and set to true when
|
||||
// the first incoming connection is established
|
||||
// this is used to know if the client is behind
|
||||
// NAT or not.
|
||||
bool m_incoming_connection;
|
||||
|
||||
void second_tick(asio::error_code const& e);
|
||||
ptime m_last_tick;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
boost::intrusive_ptr<dht::dht_tracker> m_dht;
|
||||
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;
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
pe_settings m_pe_settings;
|
||||
#endif
|
||||
|
||||
boost::shared_ptr<natpmp> m_natpmp;
|
||||
boost::shared_ptr<upnp> m_upnp;
|
||||
boost::shared_ptr<lsd> m_lsd;
|
||||
|
||||
// the timer used to fire the second_tick
|
||||
deadline_timer m_timer;
|
||||
|
||||
// the index of the torrent that will be offered to
|
||||
// connect to a peer next time second_tick is called.
|
||||
// This implements a round robin.
|
||||
int m_next_connect_torrent;
|
||||
#ifndef NDEBUG
|
||||
void check_invariant(const char *place = 0);
|
||||
#endif
|
||||
|
||||
#ifdef TORRENT_STATS
|
||||
// logger used to write bandwidth usage statistics
|
||||
std::ofstream m_stats_logger;
|
||||
int m_second_counter;
|
||||
#endif
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
boost::shared_ptr<logger> create_log(std::string const& name
|
||||
, int instance, bool append = true);
|
||||
|
||||
// this list of tracker loggers serves as tracker_callbacks when
|
||||
// shutting down. This list is just here to keep them alive during
|
||||
// whe shutting down process
|
||||
std::list<boost::shared_ptr<tracker_logger> > m_tracker_loggers;
|
||||
|
||||
public:
|
||||
boost::shared_ptr<logger> m_logger;
|
||||
private:
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
typedef std::list<boost::function<boost::shared_ptr<
|
||||
torrent_plugin>(torrent*)> > extension_list_t;
|
||||
|
||||
extension_list_t m_extensions;
|
||||
#endif
|
||||
|
||||
// data shared between the main thread
|
||||
// and the checker thread
|
||||
checker_impl m_checker_impl;
|
||||
|
||||
// the main working thread
|
||||
boost::scoped_ptr<boost::thread> m_thread;
|
||||
|
||||
// the thread that calls initialize_pieces()
|
||||
// on all torrents before they start downloading
|
||||
boost::scoped_ptr<boost::thread> m_checker_thread;
|
||||
};
|
||||
|
||||
#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING)
|
||||
struct tracker_logger : request_callback
|
||||
{
|
||||
tracker_logger(session_impl& ses): m_ses(ses) {}
|
||||
void tracker_warning(std::string const& str)
|
||||
{
|
||||
debug_log("*** tracker warning: " + str);
|
||||
}
|
||||
|
||||
void tracker_response(tracker_request const&
|
||||
, std::vector<peer_entry>& peers
|
||||
, int interval
|
||||
, int complete
|
||||
, int incomplete)
|
||||
{
|
||||
std::stringstream s;
|
||||
s << "TRACKER RESPONSE:\n"
|
||||
"interval: " << interval << "\n"
|
||||
"peers:\n";
|
||||
for (std::vector<peer_entry>::const_iterator i = peers.begin();
|
||||
i != peers.end(); ++i)
|
||||
{
|
||||
s << " " << std::setfill(' ') << std::setw(16) << i->ip
|
||||
<< " " << std::setw(5) << std::dec << i->port << " ";
|
||||
if (!i->pid.is_all_zeros()) s << " " << i->pid;
|
||||
s << "\n";
|
||||
}
|
||||
debug_log(s.str());
|
||||
}
|
||||
|
||||
void tracker_request_timed_out(
|
||||
tracker_request const&)
|
||||
{
|
||||
debug_log("*** tracker timed out");
|
||||
}
|
||||
|
||||
void tracker_request_error(
|
||||
tracker_request const&
|
||||
, int response_code
|
||||
, const std::string& str)
|
||||
{
|
||||
debug_log(std::string("*** tracker error: ")
|
||||
+ boost::lexical_cast<std::string>(response_code) + ": "
|
||||
+ str);
|
||||
}
|
||||
|
||||
void debug_log(const std::string& line)
|
||||
{
|
||||
(*m_ses.m_logger) << line << "\n";
|
||||
}
|
||||
session_impl& m_ses;
|
||||
};
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -202,7 +202,8 @@ namespace libtorrent
|
|||
void async_read(
|
||||
peer_request const& r
|
||||
, boost::function<void(int, disk_io_job const&)> const& handler
|
||||
, char* buffer = 0);
|
||||
, char* buffer = 0
|
||||
, int priority = 0);
|
||||
|
||||
void async_write(
|
||||
peer_request const& r
|
||||
|
@ -343,7 +344,8 @@ namespace libtorrent
|
|||
std::multimap<sha1_hash, int> m_hash_to_piece;
|
||||
|
||||
// this map contains partial hashes for downloading
|
||||
// pieces.
|
||||
// pieces. This is only accessed from within the
|
||||
// disk-io thread.
|
||||
std::map<int, partial_hash> m_piece_hasher;
|
||||
|
||||
disk_io_thread& m_io_thread;
|
||||
|
|
|
@ -399,6 +399,7 @@ namespace libtorrent
|
|||
, m_info_hash(h)
|
||||
{
|
||||
assert(m_ses != 0);
|
||||
assert(m_chk != 0);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
|
|
@ -194,11 +194,10 @@ namespace libtorrent
|
|||
, address bind_interface
|
||||
, boost::weak_ptr<request_callback> r);
|
||||
|
||||
request_callback& requester();
|
||||
boost::shared_ptr<request_callback> requester();
|
||||
virtual ~tracker_connection() {}
|
||||
|
||||
tracker_request const& tracker_req() const { return m_req; }
|
||||
bool has_requester() const { return !m_requester.expired(); }
|
||||
|
||||
void fail(int code, char const* msg);
|
||||
void fail_timeout();
|
||||
|
|
|
@ -13,7 +13,7 @@ kademlia/traversal_algorithm.cpp
|
|||
endif
|
||||
|
||||
libtorrent_la_SOURCES = entry.cpp escape_string.cpp \
|
||||
enum_net.cpp broadcast_socket.cpp \
|
||||
assert.cpp enum_net.cpp broadcast_socket.cpp \
|
||||
peer_connection.cpp bt_peer_connection.cpp web_peer_connection.cpp \
|
||||
natpmp.cpp piece_picker.cpp policy.cpp session.cpp session_impl.cpp sha1.cpp \
|
||||
stat.cpp storage.cpp torrent.cpp torrent_handle.cpp pe_crypto.cpp \
|
||||
|
@ -28,6 +28,7 @@ $(kademlia_sources)
|
|||
noinst_HEADERS = \
|
||||
$(top_srcdir)/include/libtorrent/alert.hpp \
|
||||
$(top_srcdir)/include/libtorrent/alert_types.hpp \
|
||||
$(top_srcdir)/include/libtorrent/assert.hpp \
|
||||
$(top_srcdir)/include/libtorrent/aux_/session_impl.hpp \
|
||||
$(top_srcdir)/include/libtorrent/bandwidth_manager.hpp \
|
||||
$(top_srcdir)/include/libtorrent/bencode.hpp \
|
||||
|
|
|
@ -34,7 +34,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#if defined __linux__ && defined __GNUC__
|
||||
#include <execinfo.h>
|
||||
#endif
|
||||
|
||||
void assert_fail(char const* expr, int line, char const* file, char const* function)
|
||||
{
|
||||
|
@ -48,6 +51,7 @@ void assert_fail(char const* expr, int line, char const* file, char const* funct
|
|||
"expression: %s\n"
|
||||
"stack:\n", file, line, function, expr);
|
||||
|
||||
#if defined __linux__ && defined __GNUC__
|
||||
void* stack[50];
|
||||
int size = backtrace(stack, 50);
|
||||
char** symbols = backtrace_symbols(stack, size);
|
||||
|
@ -58,7 +62,11 @@ void assert_fail(char const* expr, int line, char const* file, char const* funct
|
|||
}
|
||||
|
||||
free(symbols);
|
||||
exit(1);
|
||||
#endif
|
||||
// send SIGINT to the current process
|
||||
// to break into the debugger
|
||||
raise(SIGINT);
|
||||
abort();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,7 +43,7 @@ namespace libtorrent
|
|||
{
|
||||
bool is_local(address const& a)
|
||||
{
|
||||
if (a.is_v6()) return false;
|
||||
if (a.is_v6()) return a.to_v6().is_link_local();
|
||||
address_v4 a4 = a.to_v4();
|
||||
unsigned long ip = a4.to_ulong();
|
||||
return ((ip & 0xff000000) == 0x0a000000
|
||||
|
@ -58,25 +58,40 @@ namespace libtorrent
|
|||
udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0"));
|
||||
for (;i != udp::resolver_iterator(); ++i)
|
||||
{
|
||||
// ignore the loopback
|
||||
if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue;
|
||||
// ignore addresses that are not on a local network
|
||||
if (!is_local(i->endpoint().address())) continue;
|
||||
address const& a = i->endpoint().address();
|
||||
// ignore non-IPv4 addresses
|
||||
if (i->endpoint().address().is_v4()) break;
|
||||
if (!a.is_v4()) break;
|
||||
// ignore the loopback
|
||||
if (a.to_v4() == address_v4::loopback()) continue;
|
||||
}
|
||||
if (i == udp::resolver_iterator()) return address_v4::any();
|
||||
return i->endpoint().address().to_v4();
|
||||
}
|
||||
|
||||
bool is_loopback(address const& addr)
|
||||
{
|
||||
if (addr.is_v4())
|
||||
return addr.to_v4() == address_v4::loopback();
|
||||
else
|
||||
return addr.to_v6() == address_v6::loopback();
|
||||
}
|
||||
|
||||
bool is_multicast(address const& addr)
|
||||
{
|
||||
if (addr.is_v4())
|
||||
return addr.to_v4().is_multicast();
|
||||
else
|
||||
return addr.to_v6().is_multicast();
|
||||
}
|
||||
|
||||
broadcast_socket::broadcast_socket(asio::io_service& ios
|
||||
, udp::endpoint const& multicast_endpoint
|
||||
, receive_handler_t const& handler)
|
||||
, receive_handler_t const& handler
|
||||
, bool loopback)
|
||||
: m_multicast_endpoint(multicast_endpoint)
|
||||
, m_on_receive(handler)
|
||||
{
|
||||
assert(m_multicast_endpoint.address().is_v4());
|
||||
assert(m_multicast_endpoint.address().to_v4().is_multicast());
|
||||
assert(is_multicast(m_multicast_endpoint.address()));
|
||||
|
||||
using namespace asio::ip::multicast;
|
||||
|
||||
|
@ -87,26 +102,51 @@ namespace libtorrent
|
|||
, end(interfaces.end()); i != end; ++i)
|
||||
{
|
||||
// only broadcast to IPv4 addresses that are not local
|
||||
if (!i->is_v4() || !is_local(*i)) continue;
|
||||
// ignore the loopback interface
|
||||
if (i->to_v4() == address_v4((127 << 24) + 1)) continue;
|
||||
if (!is_local(*i)) continue;
|
||||
// only multicast on compatible networks
|
||||
if (i->is_v4() != multicast_endpoint.address().is_v4()) continue;
|
||||
// ignore any loopback interface
|
||||
if (is_loopback(*i)) continue;
|
||||
|
||||
boost::shared_ptr<datagram_socket> s(new datagram_socket(ios));
|
||||
s->open(udp::v4(), ec);
|
||||
if (i->is_v4())
|
||||
{
|
||||
s->open(udp::v4(), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(datagram_socket::reuse_address(true), ec);
|
||||
if (ec) continue;
|
||||
s->bind(udp::endpoint(address_v4::any(), multicast_endpoint.port()), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(join_group(multicast_endpoint.address()), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(outbound_interface(i->to_v4()), ec);
|
||||
if (ec) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->open(udp::v6(), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(datagram_socket::reuse_address(true), ec);
|
||||
if (ec) continue;
|
||||
s->bind(udp::endpoint(address_v6::any(), multicast_endpoint.port()), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(join_group(multicast_endpoint.address()), ec);
|
||||
if (ec) continue;
|
||||
// s->set_option(outbound_interface(i->to_v6()), ec);
|
||||
// if (ec) continue;
|
||||
}
|
||||
s->set_option(hops(255), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(datagram_socket::reuse_address(true), ec);
|
||||
s->set_option(enable_loopback(loopback), ec);
|
||||
if (ec) continue;
|
||||
s->bind(udp::endpoint(*i, 0), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(join_group(multicast_endpoint.address()), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(outbound_interface(i->to_v4()), ec);
|
||||
if (ec) continue;
|
||||
s->set_option(hops(255));
|
||||
m_sockets.push_back(socket_entry(s));
|
||||
socket_entry& se = m_sockets.back();
|
||||
s->async_receive_from(asio::buffer(se.buffer, sizeof(se.buffer))
|
||||
, se.remote, bind(&broadcast_socket::on_receive, this, &se, _1, _2));
|
||||
#ifndef NDEBUG
|
||||
// std::cerr << "broadcast socket [ if: " << i->to_v4().to_string()
|
||||
// << " group: " << multicast_endpoint.address() << " ]" << std::endl;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -117,7 +157,9 @@ namespace libtorrent
|
|||
{
|
||||
asio::error_code e;
|
||||
i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e);
|
||||
#ifndef NDEBUG
|
||||
// std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << std::endl;
|
||||
#endif
|
||||
if (e) ec = e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/version.hpp"
|
||||
#include "libtorrent/extensions.hpp"
|
||||
#include "libtorrent/aux_/session_impl.hpp"
|
||||
#include "libtorrent/enum_net.hpp"
|
||||
|
||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
#include "libtorrent/pe_crypto.hpp"
|
||||
|
@ -1221,7 +1222,7 @@ namespace libtorrent
|
|||
{
|
||||
tcp::endpoint adr(remote().address()
|
||||
, (unsigned short)listen_port->integer());
|
||||
t->get_policy().peer_from_tracker(adr, pid(), 0, 0);
|
||||
t->get_policy().peer_from_tracker(adr, pid(), peer_info::incoming, 0);
|
||||
}
|
||||
}
|
||||
// there should be a version too
|
||||
|
@ -1474,6 +1475,19 @@ namespace libtorrent
|
|||
detail::write_address(remote().address(), out);
|
||||
handshake["yourip"] = remote_address;
|
||||
handshake["reqq"] = m_ses.settings().max_allowed_in_request_queue;
|
||||
asio::error_code ec;
|
||||
std::vector<address> const& interfaces = enum_net_interfaces(get_socket()->io_service(), ec);
|
||||
for (std::vector<address>::const_iterator i = interfaces.begin()
|
||||
, end(interfaces.end()); i != end; ++i)
|
||||
{
|
||||
// TODO: only use global IPv6 addresses
|
||||
if (!i->is_v6() || i->to_v6().is_link_local()) continue;
|
||||
std::string ipv6_address;
|
||||
std::back_insert_iterator<std::string> out(ipv6_address);
|
||||
detail::write_address(*i, out);
|
||||
handshake["ipv6"] = ipv6_address;
|
||||
break;
|
||||
}
|
||||
|
||||
// loop backwards, to make the first extension be the last
|
||||
// to fill in the handshake (i.e. give the first extensions priority)
|
||||
|
|
|
@ -34,6 +34,24 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <deque>
|
||||
#include "libtorrent/disk_io_thread.hpp"
|
||||
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
|
||||
#include "libtorrent/time.hpp"
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
std::string log_time()
|
||||
{
|
||||
using namespace libtorrent;
|
||||
static ptime start = time_now();
|
||||
return boost::lexical_cast<std::string>(
|
||||
total_milliseconds(time_now() - start));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
||||
|
@ -45,7 +63,12 @@ namespace libtorrent
|
|||
, m_block_size(block_size)
|
||||
#endif
|
||||
, m_disk_io_thread(boost::ref(*this))
|
||||
{}
|
||||
{
|
||||
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log.open("disk_io_thread.log", std::ios::trunc);
|
||||
#endif
|
||||
}
|
||||
|
||||
disk_io_thread::~disk_io_thread()
|
||||
{
|
||||
|
@ -89,8 +112,15 @@ namespace libtorrent
|
|||
|
||||
namespace
|
||||
{
|
||||
// The semantic of this operator is:
|
||||
// shouls lhs come before rhs in the job queue
|
||||
bool operator<(disk_io_job const& lhs, disk_io_job const& rhs)
|
||||
{
|
||||
// NOTE: comparison inverted to make higher priority
|
||||
// skip _in_front_of_ lower priority
|
||||
if (lhs.priority > rhs.priority) return true;
|
||||
if (lhs.priority < rhs.priority) return false;
|
||||
|
||||
if (lhs.storage.get() < rhs.storage.get()) return true;
|
||||
if (lhs.storage.get() > rhs.storage.get()) return false;
|
||||
if (lhs.piece < rhs.piece) return true;
|
||||
|
@ -165,6 +195,9 @@ namespace libtorrent
|
|||
{
|
||||
for (;;)
|
||||
{
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " idle" << std::endl;
|
||||
#endif
|
||||
boost::mutex::scoped_lock l(m_mutex);
|
||||
while (m_jobs.empty() && !m_abort)
|
||||
m_signal.wait(l);
|
||||
|
@ -182,10 +215,16 @@ namespace libtorrent
|
|||
bool free_buffer = true;
|
||||
try
|
||||
{
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
ptime start = time_now();
|
||||
#endif
|
||||
// std::cerr << "DISK THREAD: executing job: " << j.action << std::endl;
|
||||
switch (j.action)
|
||||
{
|
||||
case disk_io_job::read:
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " read " << j.buffer_size << std::endl;
|
||||
#endif
|
||||
if (j.buffer == 0)
|
||||
{
|
||||
l.lock();
|
||||
|
@ -210,6 +249,9 @@ namespace libtorrent
|
|||
// usleep(300);
|
||||
break;
|
||||
case disk_io_job::write:
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " write " << j.buffer_size << std::endl;
|
||||
#endif
|
||||
assert(j.buffer);
|
||||
assert(j.buffer_size <= m_block_size);
|
||||
j.storage->write_impl(j.buffer, j.piece, j.offset
|
||||
|
@ -220,16 +262,25 @@ namespace libtorrent
|
|||
break;
|
||||
case disk_io_job::hash:
|
||||
{
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " hash" << std::endl;
|
||||
#endif
|
||||
sha1_hash h = j.storage->hash_for_piece_impl(j.piece);
|
||||
j.str.resize(20);
|
||||
std::memcpy(&j.str[0], &h[0], 20);
|
||||
}
|
||||
break;
|
||||
case disk_io_job::move_storage:
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " move" << std::endl;
|
||||
#endif
|
||||
ret = j.storage->move_storage_impl(j.str) ? 1 : 0;
|
||||
j.str = j.storage->save_path().string();
|
||||
break;
|
||||
case disk_io_job::release_files:
|
||||
#ifdef TORRENT_DISK_STATS
|
||||
m_log << log_time() << " release" << std::endl;
|
||||
#endif
|
||||
j.storage->release_files_impl();
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -72,8 +72,17 @@ namespace libtorrent
|
|||
ifreq const& item = *reinterpret_cast<ifreq*>(ifr);
|
||||
if (item.ifr_addr.sa_family == AF_INET)
|
||||
{
|
||||
ret.push_back(address::from_string(
|
||||
inet_ntoa(((sockaddr_in const*)&item.ifr_addr)->sin_addr)));
|
||||
typedef asio::ip::address_v4::bytes_type bytes_t;
|
||||
bytes_t b;
|
||||
memcpy(&b[0], &((sockaddr_in const*)&item.ifr_addr)->sin_addr, b.size());
|
||||
ret.push_back(address_v4(b));
|
||||
}
|
||||
else if (item.ifr_addr.sa_family == AF_INET6)
|
||||
{
|
||||
typedef asio::ip::address_v6::bytes_type bytes_t;
|
||||
bytes_t b;
|
||||
memcpy(&b[0], &((sockaddr_in6 const*)&item.ifr_addr)->sin6_addr, b.size());
|
||||
ret.push_back(address_v6(b));
|
||||
}
|
||||
|
||||
#if defined __MACH__ || defined(__FreeBSD__)
|
||||
|
|
|
@ -247,19 +247,16 @@ namespace libtorrent
|
|||
|
||||
void set_size(size_type s)
|
||||
{
|
||||
size_type pos = tell();
|
||||
// Only set size if current file size not equals s.
|
||||
// 2 as "m" argument is to be sure seek() sets SEEK_END on
|
||||
// all compilers.
|
||||
if(s != seek(0, 2))
|
||||
#ifdef _WIN32
|
||||
#error file.cpp is for posix systems only. use file_win.cpp on windows
|
||||
#else
|
||||
if (ftruncate(m_fd, s) < 0)
|
||||
{
|
||||
seek(s - 1);
|
||||
char dummy = 0;
|
||||
read(&dummy, 1);
|
||||
seek(s - 1);
|
||||
write(&dummy, 1);
|
||||
std::stringstream msg;
|
||||
msg << "ftruncate failed: '" << strerror(errno);
|
||||
throw file_error(msg.str());
|
||||
}
|
||||
seek(pos);
|
||||
#endif
|
||||
}
|
||||
|
||||
size_type seek(size_type offset, int m = 1)
|
||||
|
|
|
@ -952,4 +952,3 @@ namespace libtorrent
|
|||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -556,7 +556,7 @@ namespace libtorrent { namespace
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent* t)
|
||||
boost::shared_ptr<torrent_plugin> create_metadata_plugin(torrent* t, void*)
|
||||
{
|
||||
return boost::shared_ptr<torrent_plugin>(new metadata_plugin(*t));
|
||||
}
|
||||
|
|
|
@ -687,6 +687,14 @@ namespace libtorrent
|
|||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
assert(t);
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_reject(r)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
std::deque<piece_block>::iterator i = std::find_if(
|
||||
m_download_queue.begin(), m_download_queue.end()
|
||||
, bind(match_request, boost::cref(r), _1, t->block_size()));
|
||||
|
@ -743,7 +751,7 @@ namespace libtorrent
|
|||
void peer_connection::incoming_suggest(int index)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
<< " <== SUGGEST_PIECE [ piece: " << index << " ]\n";
|
||||
|
@ -751,6 +759,14 @@ namespace libtorrent
|
|||
boost::shared_ptr<torrent> t = m_torrent.lock();
|
||||
if (!t) return;
|
||||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
if ((*i)->on_suggest(index)) return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (t->have_piece(index)) return;
|
||||
|
||||
if (m_suggested_pieces.size() > 9)
|
||||
|
@ -1647,7 +1663,9 @@ namespace libtorrent
|
|||
state = piece_picker::slow;
|
||||
}
|
||||
|
||||
t->picker().mark_as_downloading(block, peer_info_struct(), state);
|
||||
if (!t->picker().mark_as_downloading(block, peer_info_struct(), state))
|
||||
return;
|
||||
|
||||
if (t->alerts().should_post(alert::info))
|
||||
{
|
||||
t->alerts().post_alert(block_downloading_alert(t->get_handle(),
|
||||
|
@ -1934,7 +1952,6 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
t->remove_peer(this);
|
||||
|
||||
m_torrent.reset();
|
||||
}
|
||||
|
||||
|
@ -2838,6 +2855,8 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
assert(t->connection_for(remote()) != 0 || m_in_constructor);
|
||||
|
||||
if (!m_in_constructor && t->connection_for(remote()) != this
|
||||
&& !m_ses.settings().allow_multiple_connections_per_ip)
|
||||
{
|
||||
|
@ -2897,11 +2916,6 @@ namespace libtorrent
|
|||
// TODO: the timeout should be called by an event
|
||||
INVARIANT_CHECK;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// allow step debugging without timing out
|
||||
return false;
|
||||
#endif
|
||||
|
||||
ptime now(time_now());
|
||||
|
||||
// if the socket is still connecting, don't
|
||||
|
@ -2915,6 +2929,10 @@ namespace libtorrent
|
|||
d = now - m_last_receive;
|
||||
if (d > seconds(m_timeout)) return true;
|
||||
|
||||
// if it takes more than 5 seconds to receive
|
||||
// handshake, disconnect
|
||||
if (in_handshake() && d > seconds(5)) return true;
|
||||
|
||||
// disconnect peers that we unchoked, but
|
||||
// they didn't send a request within 20 seconds.
|
||||
// but only if we're a seed
|
||||
|
|
|
@ -1229,6 +1229,7 @@ namespace libtorrent
|
|||
|
||||
bool piece_picker::can_pick(int piece, std::vector<bool> const& bitmask) const
|
||||
{
|
||||
assert(piece >= 0 && piece < int(m_piece_map.size()));
|
||||
return bitmask[piece]
|
||||
&& !m_piece_map[piece].have()
|
||||
&& !m_piece_map[piece].downloading
|
||||
|
@ -1375,10 +1376,8 @@ namespace libtorrent
|
|||
{
|
||||
// ignore completed blocks and already requested blocks
|
||||
block_info const& info = i->info[j];
|
||||
if (info.state == block_info::state_finished
|
||||
|| info.state == block_info::state_writing
|
||||
|| info.state == block_info::state_requested)
|
||||
continue;
|
||||
if (info.state != block_info::state_none)
|
||||
continue;
|
||||
|
||||
assert(i->info[j].state == block_info::state_none);
|
||||
|
||||
|
@ -1432,6 +1431,80 @@ namespace libtorrent
|
|||
|
||||
if (num_blocks <= 0) return 0;
|
||||
|
||||
if (prefer_whole_pieces > 0)
|
||||
{
|
||||
for (std::vector<downloading_piece>::const_iterator i = m_downloads.begin()
|
||||
, end(m_downloads.end()); i != end; ++i)
|
||||
{
|
||||
if (!pieces[i->index]) continue;
|
||||
int num_blocks_in_piece = blocks_in_piece(i->index);
|
||||
bool exclusive;
|
||||
bool exclusive_active;
|
||||
boost::tie(exclusive, exclusive_active)
|
||||
= requested_from(*i, num_blocks_in_piece, peer);
|
||||
|
||||
if (exclusive_active) continue;
|
||||
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
block_info const& info = i->info[j];
|
||||
if (info.state != block_info::state_none) continue;
|
||||
backup_blocks.push_back(piece_block(i->index, j));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (int(backup_blocks.size()) >= num_blocks) return num_blocks;
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
// make sure that we at this point has added requests to all unrequested blocks
|
||||
// in all downloading pieces
|
||||
|
||||
for (std::vector<downloading_piece>::const_iterator i = m_downloads.begin()
|
||||
, end(m_downloads.end()); i != end; ++i)
|
||||
{
|
||||
if (!pieces[i->index]) continue;
|
||||
|
||||
int num_blocks_in_piece = blocks_in_piece(i->index);
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
block_info const& info = i->info[j];
|
||||
if (info.state != block_info::state_none) continue;
|
||||
std::vector<piece_block>::iterator k = std::find(
|
||||
interesting_blocks.begin(), interesting_blocks.end()
|
||||
, piece_block(i->index, j));
|
||||
if (k != interesting_blocks.end()) continue;
|
||||
|
||||
k = std::find(backup_blocks.begin()
|
||||
, backup_blocks.end(), piece_block(i->index, j));
|
||||
if (k != backup_blocks.end()) continue;
|
||||
|
||||
std::cerr << "interesting blocks:" << std::endl;
|
||||
for (k = interesting_blocks.begin(); k != interesting_blocks.end(); ++k)
|
||||
std::cerr << "(" << k->piece_index << ", " << k->block_index << ") ";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "backup blocks:" << std::endl;
|
||||
for (k = backup_blocks.begin(); k != backup_blocks.end(); ++k)
|
||||
std::cerr << "(" << k->piece_index << ", " << k->block_index << ") ";
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "num_blocks: " << num_blocks << std::endl;
|
||||
|
||||
for (std::vector<downloading_piece>::const_iterator l = m_downloads.begin()
|
||||
, end(m_downloads.end()); l != end; ++l)
|
||||
{
|
||||
std::cerr << l->index << " : ";
|
||||
int num_blocks_in_piece = blocks_in_piece(l->index);
|
||||
for (int m = 0; m < num_blocks_in_piece; ++m)
|
||||
std::cerr << l->info[m].state;
|
||||
std::cerr << std::endl;
|
||||
}
|
||||
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (std::vector<downloading_piece>::const_iterator i = m_downloads.begin()
|
||||
, end(m_downloads.end()); i != end; ++i)
|
||||
{
|
||||
|
@ -1554,7 +1627,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
|
||||
void piece_picker::mark_as_downloading(piece_block block
|
||||
bool piece_picker::mark_as_downloading(piece_block block
|
||||
, void* peer, piece_state_t state)
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
@ -1589,6 +1662,9 @@ namespace libtorrent
|
|||
= std::find_if(m_downloads.begin(), m_downloads.end(), has_index(block.piece_index));
|
||||
assert(i != m_downloads.end());
|
||||
block_info& info = i->info[block.block_index];
|
||||
if (info.state == block_info::state_writing
|
||||
|| info.state == block_info::state_finished)
|
||||
return false;
|
||||
assert(info.state == block_info::state_none
|
||||
|| (info.state == block_info::state_requested
|
||||
&& (info.num_peers > 0)));
|
||||
|
@ -1601,6 +1677,7 @@ namespace libtorrent
|
|||
++info.num_peers;
|
||||
if (i->state == none) i->state = state;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int piece_picker::num_peers(piece_block block) const
|
||||
|
|
|
@ -138,28 +138,28 @@ namespace
|
|||
return free_upload;
|
||||
}
|
||||
|
||||
struct match_peer_ip
|
||||
struct match_peer_address
|
||||
{
|
||||
match_peer_ip(address const& ip)
|
||||
: m_ip(ip)
|
||||
match_peer_address(address const& addr)
|
||||
: m_addr(addr)
|
||||
{}
|
||||
|
||||
bool operator()(policy::peer const& p) const
|
||||
{ return p.ip.address() == m_ip; }
|
||||
{ return p.ip.address() == m_addr; }
|
||||
|
||||
address const& m_ip;
|
||||
address const& m_addr;
|
||||
};
|
||||
|
||||
struct match_peer_id
|
||||
struct match_peer_endpoint
|
||||
{
|
||||
match_peer_id(peer_id const& id_)
|
||||
: m_id(id_)
|
||||
match_peer_endpoint(tcp::endpoint const& ep)
|
||||
: m_ep(ep)
|
||||
{}
|
||||
|
||||
bool operator()(policy::peer const& p) const
|
||||
{ return p.connection && p.connection->pid() == m_id; }
|
||||
{ return p.ip == m_ep; }
|
||||
|
||||
peer_id const& m_id;
|
||||
tcp::endpoint const& m_ep;
|
||||
};
|
||||
|
||||
struct match_peer_connection
|
||||
|
@ -939,7 +939,7 @@ namespace libtorrent
|
|||
i = std::find_if(
|
||||
m_peers.begin()
|
||||
, m_peers.end()
|
||||
, match_peer_ip(c.remote().address()));
|
||||
, match_peer_address(c.remote().address()));
|
||||
}
|
||||
|
||||
if (i != m_peers.end())
|
||||
|
@ -1029,14 +1029,14 @@ namespace libtorrent
|
|||
i = std::find_if(
|
||||
m_peers.begin()
|
||||
, m_peers.end()
|
||||
, match_peer_id(pid));
|
||||
, match_peer_endpoint(remote));
|
||||
}
|
||||
else
|
||||
{
|
||||
i = std::find_if(
|
||||
m_peers.begin()
|
||||
, m_peers.end()
|
||||
, match_peer_ip(remote.address()));
|
||||
, match_peer_address(remote.address()));
|
||||
}
|
||||
|
||||
if (i == m_peers.end())
|
||||
|
@ -1291,9 +1291,15 @@ namespace libtorrent
|
|||
|
||||
try
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
p->connected = time_now();
|
||||
p->connection = m_torrent->connect_to_peer(&*p);
|
||||
if (p->connection == 0) return false;
|
||||
assert(p->connection == m_torrent->connection_for(p->ip));
|
||||
if (p->connection == 0)
|
||||
{
|
||||
++p->failcount;
|
||||
return false;
|
||||
}
|
||||
p->connection->add_stat(p->prev_amount_download, p->prev_amount_upload);
|
||||
p->prev_amount_download = 0;
|
||||
p->prev_amount_upload = 0;
|
||||
|
@ -1305,6 +1311,7 @@ namespace libtorrent
|
|||
(*m_torrent->session().m_logger) << "*** CONNECTION FAILED '"
|
||||
<< e.what() << "'\n";
|
||||
#endif
|
||||
std::cerr << e.what() << std::endl;
|
||||
++p->failcount;
|
||||
return false;
|
||||
}
|
||||
|
@ -1402,15 +1409,22 @@ namespace libtorrent
|
|||
int nonempty_connections = 0;
|
||||
|
||||
std::set<address> unique_test;
|
||||
std::set<tcp::endpoint> unique_test2;
|
||||
for (const_iterator i = m_peers.begin();
|
||||
i != m_peers.end(); ++i)
|
||||
{
|
||||
peer const& p = *i;
|
||||
if (!m_torrent->settings().allow_multiple_connections_per_ip)
|
||||
assert(unique_test.find(p.ip.address()) == unique_test.end());
|
||||
assert(unique_test2.find(p.ip) == unique_test2.end());
|
||||
unique_test.insert(p.ip.address());
|
||||
unique_test2.insert(p.ip);
|
||||
++total_connections;
|
||||
if (!p.connection) continue;
|
||||
if (!p.connection)
|
||||
{
|
||||
// assert(m_torrent->connection_for(p.ip) == 0);
|
||||
continue;
|
||||
}
|
||||
if (!m_torrent->settings().allow_multiple_connections_per_ip)
|
||||
{
|
||||
std::vector<peer_connection*> conns;
|
||||
|
|
|
@ -132,7 +132,7 @@ namespace libtorrent
|
|||
m_impl->abort();
|
||||
}
|
||||
|
||||
void session::add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext)
|
||||
void session::add_extension(boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
|
||||
{
|
||||
m_impl->add_extension(ext);
|
||||
}
|
||||
|
@ -185,7 +185,7 @@ namespace libtorrent
|
|||
assert(!ti.m_half_metadata);
|
||||
boost::intrusive_ptr<torrent_info> tip(new torrent_info(ti));
|
||||
return m_impl->add_torrent(tip, save_path, resume_data
|
||||
, compact_mode, sc, paused);
|
||||
, compact_mode, sc, paused, 0);
|
||||
}
|
||||
|
||||
torrent_handle session::add_torrent(
|
||||
|
@ -194,11 +194,12 @@ namespace libtorrent
|
|||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, bool paused
|
||||
, storage_constructor_type sc)
|
||||
, storage_constructor_type sc
|
||||
, void* userdata)
|
||||
{
|
||||
assert(!ti->m_half_metadata);
|
||||
return m_impl->add_torrent(ti, save_path, resume_data
|
||||
, compact_mode, sc, paused);
|
||||
, compact_mode, sc, paused, userdata);
|
||||
}
|
||||
|
||||
torrent_handle session::add_torrent(
|
||||
|
@ -209,10 +210,11 @@ namespace libtorrent
|
|||
, entry const& e
|
||||
, bool compact_mode
|
||||
, bool paused
|
||||
, storage_constructor_type sc)
|
||||
, storage_constructor_type sc
|
||||
, void* userdata)
|
||||
{
|
||||
return m_impl->add_torrent(tracker_url, info_hash, name, save_path, e
|
||||
, compact_mode, sc, paused);
|
||||
, compact_mode, sc, paused, userdata);
|
||||
}
|
||||
|
||||
void session::remove_torrent(const torrent_handle& h)
|
||||
|
|
|
@ -593,7 +593,7 @@ namespace detail
|
|||
|
||||
#ifndef TORRENT_DISABLE_EXTENSIONS
|
||||
void session_impl::add_extension(
|
||||
boost::function<boost::shared_ptr<torrent_plugin>(torrent*)> ext)
|
||||
boost::function<boost::shared_ptr<torrent_plugin>(torrent*, void*)> ext)
|
||||
{
|
||||
m_extensions.push_back(ext);
|
||||
}
|
||||
|
@ -1474,7 +1474,8 @@ namespace detail
|
|||
, entry const& resume_data
|
||||
, bool compact_mode
|
||||
, storage_constructor_type sc
|
||||
, bool paused)
|
||||
, bool paused
|
||||
, void* userdata)
|
||||
{
|
||||
// if you get this assert, you haven't managed to
|
||||
// open a listen port. call listen_on() first.
|
||||
|
@ -1514,7 +1515,7 @@ namespace detail
|
|||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get()));
|
||||
boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get(), userdata));
|
||||
if (tp) torrent_ptr->add_extension(tp);
|
||||
}
|
||||
#endif
|
||||
|
@ -1554,7 +1555,8 @@ namespace detail
|
|||
, entry const&
|
||||
, bool compact_mode
|
||||
, storage_constructor_type sc
|
||||
, bool paused)
|
||||
, bool paused
|
||||
, void* userdata)
|
||||
{
|
||||
|
||||
// TODO: support resume data in this case
|
||||
|
@ -1593,7 +1595,7 @@ namespace detail
|
|||
for (extension_list_t::iterator i = m_extensions.begin()
|
||||
, end(m_extensions.end()); i != end; ++i)
|
||||
{
|
||||
boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get()));
|
||||
boost::shared_ptr<torrent_plugin> tp((*i)(torrent_ptr.get(), userdata));
|
||||
if (tp) torrent_ptr->add_extension(tp);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -403,13 +403,19 @@ namespace libtorrent
|
|||
assert(ph.offset == 0 || partial_copy.final() == partial.final());
|
||||
#endif
|
||||
int slot_size = piece_size - ph.offset;
|
||||
if (slot_size == 0) return ph.h.final();
|
||||
m_scratch_buffer.resize(slot_size);
|
||||
read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, true);
|
||||
ph.h.update(&m_scratch_buffer[0], slot_size);
|
||||
if (slot_size > 0)
|
||||
{
|
||||
m_scratch_buffer.resize(slot_size);
|
||||
read_impl(&m_scratch_buffer[0], slot, ph.offset, slot_size, true);
|
||||
ph.h.update(&m_scratch_buffer[0], slot_size);
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
sha1_hash ret = ph.h.final();
|
||||
assert(whole.final() == ret);
|
||||
assert(ret == whole.final());
|
||||
return ret;
|
||||
#else
|
||||
return ph.h.final();
|
||||
#endif
|
||||
}
|
||||
|
||||
void storage::initialize(bool allocate_files)
|
||||
|
@ -996,9 +1002,6 @@ namespace libtorrent
|
|||
int err = statfs(query_path.native_directory_string().c_str(), &buf);
|
||||
if (err == 0)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "buf.f_type " << std::hex << buf.f_type << std::endl;
|
||||
#endif
|
||||
switch (buf.f_type)
|
||||
{
|
||||
case 0x5346544e: // NTFS
|
||||
|
@ -1084,7 +1087,8 @@ namespace libtorrent
|
|||
void piece_manager::async_read(
|
||||
peer_request const& r
|
||||
, boost::function<void(int, disk_io_job const&)> const& handler
|
||||
, char* buffer)
|
||||
, char* buffer
|
||||
, int priority)
|
||||
{
|
||||
disk_io_job j;
|
||||
j.storage = this;
|
||||
|
@ -1093,6 +1097,7 @@ namespace libtorrent
|
|||
j.offset = r.start;
|
||||
j.buffer_size = r.length;
|
||||
j.buffer = buffer;
|
||||
j.priority = priority;
|
||||
// if a buffer is not specified, only one block can be read
|
||||
// since that is the size of the pool allocator's buffers
|
||||
assert(r.length <= 16 * 1024 || buffer != 0);
|
||||
|
@ -1295,6 +1300,7 @@ namespace libtorrent
|
|||
if (i != m_piece_hasher.end())
|
||||
{
|
||||
assert(i->second.offset > 0);
|
||||
assert(offset >= i->second.offset);
|
||||
if (offset == i->second.offset)
|
||||
{
|
||||
i->second.offset += size;
|
||||
|
|
|
@ -1653,6 +1653,7 @@ namespace libtorrent
|
|||
assert(m_connections.find(a) == m_connections.end());
|
||||
|
||||
// add the newly connected peer to this torrent's peer list
|
||||
assert(m_connections.find(a) == m_connections.end());
|
||||
m_connections.insert(
|
||||
std::make_pair(a, boost::get_pointer(c)));
|
||||
m_ses.m_connections.insert(std::make_pair(s, c));
|
||||
|
@ -1669,8 +1670,8 @@ namespace libtorrent
|
|||
#endif
|
||||
|
||||
// TODO: post an error alert!
|
||||
std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
|
||||
if (i != m_connections.end()) m_connections.erase(i);
|
||||
// std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
|
||||
// if (i != m_connections.end()) m_connections.erase(i);
|
||||
m_ses.connection_failed(s, a, e.what());
|
||||
c->disconnect();
|
||||
}
|
||||
|
@ -1857,6 +1858,8 @@ namespace libtorrent
|
|||
|
||||
try
|
||||
{
|
||||
assert(m_connections.find(a) == m_connections.end());
|
||||
|
||||
// add the newly connected peer to this torrent's peer list
|
||||
m_connections.insert(
|
||||
std::make_pair(a, boost::get_pointer(c)));
|
||||
|
@ -1869,6 +1872,7 @@ namespace libtorrent
|
|||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
assert(false);
|
||||
// TODO: post an error alert!
|
||||
std::map<tcp::endpoint, peer_connection*>::iterator i = m_connections.find(a);
|
||||
if (i != m_connections.end()) m_connections.erase(i);
|
||||
|
@ -1925,6 +1929,7 @@ namespace libtorrent
|
|||
= m_connections.find(p->remote());
|
||||
if (c != m_connections.end())
|
||||
{
|
||||
assert(p != c->second);
|
||||
// we already have a peer_connection to this ip.
|
||||
// It may currently be waiting for completing a
|
||||
// connection attempt that might fail. So,
|
||||
|
@ -1948,6 +1953,7 @@ namespace libtorrent
|
|||
throw protocol_error("session is closing");
|
||||
}
|
||||
|
||||
assert(m_connections.find(p->remote()) == m_connections.end());
|
||||
peer_iterator ci = m_connections.insert(
|
||||
std::make_pair(p->remote(), p)).first;
|
||||
try
|
||||
|
@ -2408,6 +2414,12 @@ namespace libtorrent
|
|||
assert(m_abort || m_have_pieces.empty());
|
||||
}
|
||||
|
||||
/* for (policy::const_iterator i = m_policy->begin_peer()
|
||||
, end(m_policy->end_peer()); i != end; ++i)
|
||||
{
|
||||
assert(i->connection == const_cast<torrent*>(this)->connection_for(i->ip));
|
||||
}
|
||||
*/
|
||||
size_type total_done = quantized_bytes_done();
|
||||
if (m_torrent_file->is_valid())
|
||||
{
|
||||
|
|
|
@ -94,18 +94,11 @@ namespace libtorrent
|
|||
, aux::checker_impl* chk
|
||||
, sha1_hash const& hash)
|
||||
{
|
||||
if (ses == 0) throw_invalid_handle();
|
||||
aux::piece_checker_data* d = chk->find_torrent(hash);
|
||||
if (d != 0) return d->torrent_ptr;
|
||||
|
||||
if (chk)
|
||||
{
|
||||
aux::piece_checker_data* d = chk->find_torrent(hash);
|
||||
if (d != 0) return d->torrent_ptr;
|
||||
}
|
||||
|
||||
{
|
||||
boost::shared_ptr<torrent> t = ses->find_torrent(hash).lock();
|
||||
if (t) return t;
|
||||
}
|
||||
boost::shared_ptr<torrent> t = ses->find_torrent(hash).lock();
|
||||
if (t) return t;
|
||||
|
||||
// throwing directly instead of calling
|
||||
// the throw_invalid_handle() function
|
||||
|
@ -118,7 +111,7 @@ namespace libtorrent
|
|||
|
||||
void torrent_handle::check_invariant() const
|
||||
{
|
||||
assert((m_ses == 0 && m_chk == 0) || (m_ses != 0));
|
||||
assert((m_ses == 0 && m_chk == 0) || (m_ses != 0 && m_chk != 0));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -127,6 +120,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
assert(max_uploads >= 2 || max_uploads == -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
|
@ -138,6 +134,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->use_interface(net_interface);
|
||||
|
@ -147,6 +146,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
assert(max_connections >= 2 || max_connections == -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
|
@ -159,6 +161,9 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
assert(limit >= -1);
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_peer_upload_limit(ip, limit);
|
||||
|
@ -169,6 +174,9 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
assert(limit >= -1);
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_peer_download_limit(ip, limit);
|
||||
|
@ -178,6 +186,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
assert(limit >= -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
|
@ -188,6 +199,10 @@ namespace libtorrent
|
|||
int torrent_handle::upload_limit() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->upload_limit();
|
||||
|
@ -197,6 +212,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
assert(limit >= -1);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
|
@ -208,6 +226,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->download_limit();
|
||||
|
@ -218,6 +239,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->move_storage(save_path);
|
||||
|
@ -227,6 +251,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->valid_metadata();
|
||||
|
@ -236,6 +263,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->is_seed();
|
||||
|
@ -245,6 +275,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->is_paused();
|
||||
|
@ -254,6 +287,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->pause();
|
||||
|
@ -263,6 +299,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->resume();
|
||||
|
@ -273,6 +312,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_tracker_login(name, password);
|
||||
|
@ -283,31 +325,27 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
||||
if (m_chk)
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0)
|
||||
{
|
||||
mutex::scoped_lock l(m_chk->m_mutex);
|
||||
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0)
|
||||
if (!d->processing)
|
||||
{
|
||||
if (!d->processing)
|
||||
{
|
||||
torrent_info const& info = d->torrent_ptr->torrent_file();
|
||||
progress.clear();
|
||||
progress.resize(info.num_files(), 0.f);
|
||||
return;
|
||||
}
|
||||
d->torrent_ptr->file_progress(progress);
|
||||
torrent_info const& info = d->torrent_ptr->torrent_file();
|
||||
progress.clear();
|
||||
progress.resize(info.num_files(), 0.f);
|
||||
return;
|
||||
}
|
||||
d->torrent_ptr->file_progress(progress);
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (t) return t->file_progress(progress);
|
||||
}
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (t) return t->file_progress(progress);
|
||||
|
||||
throw_invalid_handle();
|
||||
}
|
||||
|
@ -317,36 +355,32 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
||||
if (m_chk)
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0)
|
||||
{
|
||||
mutex::scoped_lock l(m_chk->m_mutex);
|
||||
torrent_status st;
|
||||
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0)
|
||||
if (d->processing)
|
||||
{
|
||||
torrent_status st;
|
||||
|
||||
if (d->processing)
|
||||
{
|
||||
if (d->torrent_ptr->is_allocating())
|
||||
st.state = torrent_status::allocating;
|
||||
else
|
||||
st.state = torrent_status::checking_files;
|
||||
}
|
||||
if (d->torrent_ptr->is_allocating())
|
||||
st.state = torrent_status::allocating;
|
||||
else
|
||||
st.state = torrent_status::queued_for_checking;
|
||||
st.progress = d->progress;
|
||||
st.paused = d->torrent_ptr->is_paused();
|
||||
return st;
|
||||
st.state = torrent_status::checking_files;
|
||||
}
|
||||
else
|
||||
st.state = torrent_status::queued_for_checking;
|
||||
st.progress = d->progress;
|
||||
st.paused = d->torrent_ptr->is_paused();
|
||||
return st;
|
||||
}
|
||||
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (t) return t->status();
|
||||
}
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
if (t) return t->status();
|
||||
|
||||
throw_invalid_handle();
|
||||
return torrent_status();
|
||||
|
@ -355,6 +389,10 @@ namespace libtorrent
|
|||
void torrent_handle::set_sequenced_download_threshold(int threshold) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_sequenced_download_threshold(threshold);
|
||||
|
@ -364,6 +402,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->name();
|
||||
|
@ -374,6 +415,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->piece_availability(avail);
|
||||
|
@ -383,6 +427,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->set_piece_priority(index, priority);
|
||||
|
@ -392,6 +439,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->piece_priority(index);
|
||||
|
@ -401,6 +451,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->prioritize_pieces(pieces);
|
||||
|
@ -409,6 +462,10 @@ namespace libtorrent
|
|||
std::vector<int> torrent_handle::piece_priorities() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
std::vector<int> ret;
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
@ -420,6 +477,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->prioritize_files(files);
|
||||
|
@ -430,6 +490,10 @@ namespace libtorrent
|
|||
void torrent_handle::filter_piece(int index, bool filter) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filter_piece(index, filter);
|
||||
|
@ -438,6 +502,10 @@ namespace libtorrent
|
|||
void torrent_handle::filter_pieces(std::vector<bool> const& pieces) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filter_pieces(pieces);
|
||||
|
@ -446,6 +514,10 @@ namespace libtorrent
|
|||
bool torrent_handle::is_piece_filtered(int index) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->is_piece_filtered(index);
|
||||
|
@ -454,6 +526,10 @@ namespace libtorrent
|
|||
std::vector<bool> torrent_handle::filtered_pieces() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
std::vector<bool> ret;
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
|
@ -464,6 +540,10 @@ namespace libtorrent
|
|||
void torrent_handle::filter_files(std::vector<bool> const& files) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->filter_files(files);
|
||||
|
@ -476,6 +556,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->trackers();
|
||||
|
@ -485,6 +568,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->add_url_seed(url);
|
||||
|
@ -494,6 +580,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->remove_url_seed(url);
|
||||
|
@ -503,6 +592,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->url_seeds();
|
||||
|
@ -513,6 +605,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->replace_trackers(urls);
|
||||
|
@ -521,6 +616,10 @@ namespace libtorrent
|
|||
torrent_info const& torrent_handle::get_torrent_info() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
boost::shared_ptr<torrent> t = find_torrent(m_ses, m_chk, m_info_hash);
|
||||
|
@ -533,16 +632,14 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) return false;
|
||||
assert(m_chk);
|
||||
|
||||
if (m_chk)
|
||||
{
|
||||
mutex::scoped_lock l(m_chk->m_mutex);
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0) return true;
|
||||
}
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
aux::piece_checker_data* d = m_chk->find_torrent(m_info_hash);
|
||||
if (d != 0) return true;
|
||||
|
||||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::weak_ptr<torrent> t = m_ses->find_torrent(m_info_hash);
|
||||
if (!t.expired()) return true;
|
||||
}
|
||||
|
@ -556,6 +653,7 @@ namespace libtorrent
|
|||
|
||||
std::vector<int> piece_index;
|
||||
if (m_ses == 0) return entry();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
|
@ -674,6 +772,9 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->save_path();
|
||||
|
@ -684,6 +785,7 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
|
@ -712,6 +814,7 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
|
@ -726,6 +829,7 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
|
@ -738,8 +842,10 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
assert(ratio >= 0.f);
|
||||
|
||||
if (ratio < 1.f && ratio > 0.f)
|
||||
ratio = 1.f;
|
||||
|
||||
|
@ -752,6 +858,10 @@ namespace libtorrent
|
|||
void torrent_handle::resolve_countries(bool r)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
find_torrent(m_ses, m_chk, m_info_hash)->resolve_countries(r);
|
||||
|
@ -760,6 +870,10 @@ namespace libtorrent
|
|||
bool torrent_handle::resolve_countries() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l1(m_ses->m_mutex);
|
||||
mutex::scoped_lock l2(m_chk->m_mutex);
|
||||
return find_torrent(m_ses, m_chk, m_info_hash)->resolving_countries();
|
||||
|
@ -770,8 +884,10 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
v.clear();
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
v.clear();
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
|
||||
|
@ -803,6 +919,7 @@ namespace libtorrent
|
|||
INVARIANT_CHECK;
|
||||
|
||||
if (m_ses == 0) throw_invalid_handle();
|
||||
assert(m_chk);
|
||||
|
||||
session_impl::mutex_t::scoped_lock l(m_ses->m_mutex);
|
||||
boost::shared_ptr<torrent> t = m_ses->find_torrent(m_info_hash).lock();
|
||||
|
|
|
@ -365,23 +365,22 @@ namespace libtorrent
|
|||
, m_req(req)
|
||||
{}
|
||||
|
||||
request_callback& tracker_connection::requester()
|
||||
boost::shared_ptr<request_callback> tracker_connection::requester()
|
||||
{
|
||||
boost::shared_ptr<request_callback> r = m_requester.lock();
|
||||
assert(r);
|
||||
return *r;
|
||||
return m_requester.lock();
|
||||
}
|
||||
|
||||
void tracker_connection::fail(int code, char const* msg)
|
||||
{
|
||||
if (has_requester()) requester().tracker_request_error(
|
||||
m_req, code, msg);
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb) cb->tracker_request_error(m_req, code, msg);
|
||||
close();
|
||||
}
|
||||
|
||||
void tracker_connection::fail_timeout()
|
||||
{
|
||||
if (has_requester()) requester().tracker_request_timed_out(m_req);
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb) cb->tracker_request_timed_out(m_req);
|
||||
close();
|
||||
}
|
||||
|
||||
|
@ -548,7 +547,8 @@ namespace libtorrent
|
|||
|
||||
m_connections.push_back(con);
|
||||
|
||||
if (con->has_requester()) con->requester().m_manager = this;
|
||||
boost::shared_ptr<request_callback> cb = con->requester();
|
||||
if (cb) cb->m_manager = this;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
|
|
@ -110,8 +110,9 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (has_requester()) requester().debug_log("udp tracker name lookup successful");
|
||||
if (cb) cb->debug_log("udp tracker name lookup successful");
|
||||
#endif
|
||||
restart_read_timeout();
|
||||
|
||||
|
@ -126,11 +127,11 @@ namespace libtorrent
|
|||
if (target == end)
|
||||
{
|
||||
assert(target_address.address().is_v4() != bind_interface().is_v4());
|
||||
if (has_requester())
|
||||
if (cb)
|
||||
{
|
||||
std::string tracker_address_type = target_address.address().is_v4() ? "IPv4" : "IPv6";
|
||||
std::string bind_address_type = bind_interface().is_v4() ? "IPv4" : "IPv6";
|
||||
requester().tracker_warning("the tracker only resolves to an "
|
||||
cb->tracker_warning("the tracker only resolves to an "
|
||||
+ tracker_address_type + " address, and you're listening on an "
|
||||
+ bind_address_type + " socket. This may prevent you from receiving incoming connections.");
|
||||
}
|
||||
|
@ -140,7 +141,7 @@ namespace libtorrent
|
|||
target_address = *target;
|
||||
}
|
||||
|
||||
if (has_requester()) requester().m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
|
||||
if (cb) cb->m_tracker_address = tcp::endpoint(target_address.address(), target_address.port());
|
||||
m_target = target_address;
|
||||
m_socket.reset(new datagram_socket(m_name_lookup.io_service()));
|
||||
m_socket->open(target_address.protocol());
|
||||
|
@ -163,9 +164,10 @@ namespace libtorrent
|
|||
void udp_tracker_connection::send_udp_connect()
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (has_requester())
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb)
|
||||
{
|
||||
requester().debug_log("==> UDP_TRACKER_CONNECT ["
|
||||
cb->debug_log("==> UDP_TRACKER_CONNECT ["
|
||||
+ lexical_cast<std::string>(tracker_req().info_hash) + "]");
|
||||
}
|
||||
#endif
|
||||
|
@ -259,9 +261,10 @@ namespace libtorrent
|
|||
m_connection_id = detail::read_int64(ptr);
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (has_requester())
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb)
|
||||
{
|
||||
requester().debug_log("<== UDP_TRACKER_CONNECT_RESPONSE ["
|
||||
cb->debug_log("<== UDP_TRACKER_CONNECT_RESPONSE ["
|
||||
+ lexical_cast<std::string>(m_connection_id) + "]");
|
||||
}
|
||||
#endif
|
||||
|
@ -321,9 +324,10 @@ namespace libtorrent
|
|||
detail::write_uint16(0, out);
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (has_requester())
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (cb)
|
||||
{
|
||||
requester().debug_log("==> UDP_TRACKER_ANNOUNCE ["
|
||||
cb->debug_log("==> UDP_TRACKER_ANNOUNCE ["
|
||||
+ lexical_cast<std::string>(req.info_hash) + "]");
|
||||
}
|
||||
#endif
|
||||
|
@ -431,14 +435,15 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING)
|
||||
if (has_requester())
|
||||
if (cb)
|
||||
{
|
||||
requester().debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE");
|
||||
cb->debug_log("<== UDP_TRACKER_ANNOUNCE_RESPONSE");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!has_requester())
|
||||
if (!cb)
|
||||
{
|
||||
m_man.remove_request(this);
|
||||
return;
|
||||
|
@ -459,7 +464,7 @@ namespace libtorrent
|
|||
peer_list.push_back(e);
|
||||
}
|
||||
|
||||
requester().tracker_response(tracker_req(), peer_list, interval
|
||||
cb->tracker_response(tracker_req(), peer_list, interval
|
||||
, complete, incomplete);
|
||||
|
||||
m_man.remove_request(this);
|
||||
|
@ -534,14 +539,15 @@ namespace libtorrent
|
|||
/*int downloaded = */detail::read_int32(buf);
|
||||
int incomplete = detail::read_int32(buf);
|
||||
|
||||
if (!has_requester())
|
||||
boost::shared_ptr<request_callback> cb = requester();
|
||||
if (!cb)
|
||||
{
|
||||
m_man.remove_request(this);
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<peer_entry> peer_list;
|
||||
requester().tracker_response(tracker_req(), peer_list, 0
|
||||
cb->tracker_response(tracker_req(), peer_list, 0
|
||||
, complete, incomplete);
|
||||
|
||||
m_man.remove_request(this);
|
||||
|
|
|
@ -997,4 +997,3 @@ void upnp::close()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -67,8 +67,6 @@ namespace libtorrent { namespace
|
|||
if (!p.is_local()) return false;
|
||||
// don't send out peers that we haven't successfully connected to
|
||||
if (p.is_connecting()) return false;
|
||||
// ut pex does not support IPv6
|
||||
if (!p.remote().address().is_v4()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -98,9 +96,15 @@ namespace libtorrent { namespace
|
|||
std::string& pla = pex["added"].string();
|
||||
std::string& pld = pex["dropped"].string();
|
||||
std::string& plf = pex["added.f"].string();
|
||||
std::string& pla6 = pex["added6"].string();
|
||||
std::string& pld6 = pex["dropped6"].string();
|
||||
std::string& plf6 = pex["added6.f"].string();
|
||||
std::back_insert_iterator<std::string> pla_out(pla);
|
||||
std::back_insert_iterator<std::string> pld_out(pld);
|
||||
std::back_insert_iterator<std::string> plf_out(plf);
|
||||
std::back_insert_iterator<std::string> pla6_out(pla6);
|
||||
std::back_insert_iterator<std::string> pld6_out(pld6);
|
||||
std::back_insert_iterator<std::string> plf6_out(plf6);
|
||||
|
||||
std::set<tcp::endpoint> dropped;
|
||||
m_old_peers.swap(dropped);
|
||||
|
@ -123,8 +127,6 @@ namespace libtorrent { namespace
|
|||
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(i->second);
|
||||
if (!p) continue;
|
||||
|
||||
// i->first was added since the last time
|
||||
detail::write_endpoint(i->first, pla_out);
|
||||
// no supported flags to set yet
|
||||
// 0x01 - peer supports encryption
|
||||
// 0x02 - peer is a seed
|
||||
|
@ -132,7 +134,17 @@ namespace libtorrent { namespace
|
|||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
flags |= p->supports_encryption() ? 1 : 0;
|
||||
#endif
|
||||
detail::write_uint8(flags, plf_out);
|
||||
// i->first was added since the last time
|
||||
if (i->first.address().is_v4())
|
||||
{
|
||||
detail::write_endpoint(i->first, pla_out);
|
||||
detail::write_uint8(flags, plf_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::write_endpoint(i->first, pla6_out);
|
||||
detail::write_uint8(flags, plf6_out);
|
||||
}
|
||||
++num_added;
|
||||
}
|
||||
else
|
||||
|
@ -146,8 +158,10 @@ namespace libtorrent { namespace
|
|||
for (std::set<tcp::endpoint>::const_iterator i = dropped.begin()
|
||||
, end(dropped.end());i != end; ++i)
|
||||
{
|
||||
if (!i->address().is_v4()) continue;
|
||||
detail::write_endpoint(*i, pld_out);
|
||||
if (i->address().is_v4())
|
||||
detail::write_endpoint(*i, pld_out);
|
||||
else
|
||||
detail::write_endpoint(*i, pld6_out);
|
||||
}
|
||||
|
||||
m_ut_pex_msg.clear();
|
||||
|
@ -227,6 +241,28 @@ namespace libtorrent { namespace
|
|||
char flags = detail::read_uint8(fin);
|
||||
p.peer_from_tracker(adr, pid, peer_info::pex, flags);
|
||||
}
|
||||
|
||||
if (entry const* p6 = pex_msg.find_key("added6"))
|
||||
{
|
||||
std::string const& peers6 = p6->string();
|
||||
std::string const& peer6_flags = pex_msg["added6.f"].string();
|
||||
|
||||
int num_peers = peers6.length() / 18;
|
||||
char const* in = peers6.c_str();
|
||||
char const* fin = peer6_flags.c_str();
|
||||
|
||||
if (int(peer6_flags.size()) != num_peers)
|
||||
return true;
|
||||
|
||||
peer_id pid(0);
|
||||
policy& p = m_torrent.get_policy();
|
||||
for (int i = 0; i < num_peers; ++i)
|
||||
{
|
||||
tcp::endpoint adr = detail::read_v6_endpoint<tcp::endpoint>(in);
|
||||
char flags = detail::read_uint8(fin);
|
||||
p.peer_from_tracker(adr, pid, peer_info::pex, flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
|
@ -279,8 +315,13 @@ namespace libtorrent { namespace
|
|||
pex["dropped"].string();
|
||||
std::string& pla = pex["added"].string();
|
||||
std::string& plf = pex["added.f"].string();
|
||||
pex["dropped6"].string();
|
||||
std::string& pla6 = pex["added6"].string();
|
||||
std::string& plf6 = pex["added6.f"].string();
|
||||
std::back_insert_iterator<std::string> pla_out(pla);
|
||||
std::back_insert_iterator<std::string> plf_out(plf);
|
||||
std::back_insert_iterator<std::string> pla6_out(pla6);
|
||||
std::back_insert_iterator<std::string> plf6_out(plf6);
|
||||
|
||||
int num_added = 0;
|
||||
for (torrent::peer_iterator i = m_torrent.begin()
|
||||
|
@ -295,8 +336,6 @@ namespace libtorrent { namespace
|
|||
bt_peer_connection* p = dynamic_cast<bt_peer_connection*>(i->second);
|
||||
if (!p) continue;
|
||||
|
||||
// i->first was added since the last time
|
||||
detail::write_endpoint(i->first, pla_out);
|
||||
// no supported flags to set yet
|
||||
// 0x01 - peer supports encryption
|
||||
// 0x02 - peer is a seed
|
||||
|
@ -304,7 +343,17 @@ namespace libtorrent { namespace
|
|||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
flags |= p->supports_encryption() ? 1 : 0;
|
||||
#endif
|
||||
detail::write_uint8(flags, plf_out);
|
||||
// i->first was added since the last time
|
||||
if (i->first.address().is_v4())
|
||||
{
|
||||
detail::write_endpoint(i->first, pla_out);
|
||||
detail::write_uint8(flags, plf_out);
|
||||
}
|
||||
else
|
||||
{
|
||||
detail::write_endpoint(i->first, pla6_out);
|
||||
detail::write_uint8(flags, plf6_out);
|
||||
}
|
||||
++num_added;
|
||||
}
|
||||
std::vector<char> pex_msg;
|
||||
|
@ -347,7 +396,7 @@ namespace libtorrent { namespace
|
|||
namespace libtorrent
|
||||
{
|
||||
|
||||
boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent* t)
|
||||
boost::shared_ptr<torrent_plugin> create_ut_pex_plugin(torrent* t, void*)
|
||||
{
|
||||
if (t->torrent_file().priv())
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue