parent
ac29983651
commit
b7e3c6b3df
|
@ -35,6 +35,11 @@
|
|||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator2">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menuitem_updatetracker">
|
||||
<property name="visible">True</property>
|
||||
|
@ -69,7 +74,7 @@
|
|||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator">
|
||||
<widget class="GtkSeparatorMenuItem" id="separator1">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
|
@ -90,97 +95,5 @@
|
|||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkSeparatorMenuItem" id="separator">
|
||||
<property name="visible">True</property>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menuitem_queue">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">_Queue</property>
|
||||
<property name="use_underline">True</property>
|
||||
<child>
|
||||
<widget class="GtkMenu" id="menu1">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menuitem_queuetop">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">_Top</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_menuitem_queuetop_activate"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="menu-item-image10">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="stock">gtk-goto-top</property>
|
||||
<property name="icon_size">1</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menuitem_queueup">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Up</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_menuitem_queueup_activate"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="menu-item-image6">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="stock">gtk-go-up</property>
|
||||
<property name="icon_size">1</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menuitem_queuedown">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Down</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_menuitem_queuedown_activate"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="menu-item-image7">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="stock">gtk-go-down</property>
|
||||
<property name="icon_size">1</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child>
|
||||
<widget class="GtkImageMenuItem" id="menuitem_queuebottom">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">_Bottom</property>
|
||||
<property name="use_underline">True</property>
|
||||
<signal name="activate" handler="on_menuitem_queuebottom_activate"/>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="menu-item-image8">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="stock">gtk-goto-bottom</property>
|
||||
<property name="icon_size">1</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
<child internal-child="image">
|
||||
<widget class="GtkImage" id="menu-item-image11">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="stock">gtk-sort-ascending</property>
|
||||
<property name="icon_size">1</property>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</child>
|
||||
</widget>
|
||||
</glade-interface>
|
||||
|
|
|
@ -82,6 +82,7 @@ class ListView:
|
|||
def __init__(self, name, column_indices):
|
||||
self.name = name
|
||||
self.column_indices = column_indices
|
||||
self.column = None
|
||||
|
||||
def __init__(self, treeview_widget=None):
|
||||
log.debug("ListView initialized..")
|
||||
|
@ -113,6 +114,13 @@ class ListView:
|
|||
else:
|
||||
return self.columns[name].column_indices[0]
|
||||
|
||||
def create_checklist_menu(self):
|
||||
menu = gtk.Menu()
|
||||
for column in self.columns.values():
|
||||
menuitem = gtk.CheckMenuItem(column.name)
|
||||
menu.append(menuitem)
|
||||
return menu
|
||||
|
||||
def create_new_liststore(self):
|
||||
# Create a new liststore with added column and move the data from the
|
||||
# old one to the new one.
|
||||
|
@ -158,6 +166,7 @@ class ListView:
|
|||
column.set_reorderable(True)
|
||||
column.set_visible(visible)
|
||||
self.treeview.append_column(column)
|
||||
self.columns[header].column = column
|
||||
|
||||
return True
|
||||
|
||||
|
@ -194,7 +203,8 @@ class ListView:
|
|||
column.set_min_width(10)
|
||||
column.set_reorderable(True)
|
||||
self.treeview.append_column(column)
|
||||
|
||||
self.columns[header].column = column
|
||||
|
||||
return True
|
||||
|
||||
def add_progress_column(self, header):
|
||||
|
@ -221,7 +231,8 @@ class ListView:
|
|||
column.set_min_width(10)
|
||||
column.set_reorderable(True)
|
||||
self.treeview.append_column(column)
|
||||
|
||||
self.columns[header].column = column
|
||||
|
||||
return True
|
||||
|
||||
def add_texticon_column(self, header):
|
||||
|
@ -251,5 +262,6 @@ class ListView:
|
|||
column.add_attribute(render, 'text',
|
||||
self.columns[header].column_indices[1])
|
||||
self.treeview.append_column(column)
|
||||
|
||||
self.columns[header].column = column
|
||||
|
||||
return True
|
||||
|
|
|
@ -80,6 +80,9 @@ class TorrentView(listview.ListView):
|
|||
listview.cell_data_ratio,
|
||||
[float])
|
||||
|
||||
self.window.main_glade.get_widget("menu_columns").set_submenu(
|
||||
self.create_checklist_menu())
|
||||
|
||||
### Connect Signals ###
|
||||
# Connect to the 'button-press-event' to know when to bring up the
|
||||
# torrent menu popup.
|
||||
|
@ -100,7 +103,7 @@ class TorrentView(listview.ListView):
|
|||
"eta"]
|
||||
status = functions.get_torrent_status(self.core, torrent_id,
|
||||
status_keys)
|
||||
|
||||
|
||||
# Set values for each column in the row
|
||||
|
||||
self.liststore.set_value(row,
|
||||
|
|
|
@ -184,6 +184,63 @@ namespace libtorrent
|
|||
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT piece_finished_alert: torrent_alert
|
||||
{
|
||||
piece_finished_alert(
|
||||
const torrent_handle& h
|
||||
, int piece_num
|
||||
, const std::string& msg)
|
||||
: torrent_alert(h, alert::warning, msg)
|
||||
, piece_index(piece_num)
|
||||
{ assert(piece_index >= 0);}
|
||||
|
||||
int piece_index;
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new piece_finished_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT block_finished_alert: torrent_alert
|
||||
{
|
||||
block_finished_alert(
|
||||
const torrent_handle& h
|
||||
, int block_num
|
||||
, int piece_num
|
||||
, const std::string& msg)
|
||||
: torrent_alert(h, alert::warning, msg)
|
||||
, block_index(block_num)
|
||||
, piece_index(piece_num)
|
||||
{ assert(block_index >= 0 && piece_index >= 0);}
|
||||
|
||||
int block_index;
|
||||
int piece_index;
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new block_finished_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT block_downloading_alert: torrent_alert
|
||||
{
|
||||
block_downloading_alert(
|
||||
const torrent_handle& h
|
||||
, std::string& speedmsg
|
||||
, int block_num
|
||||
, int piece_num
|
||||
, const std::string& msg)
|
||||
: torrent_alert(h, alert::warning, msg)
|
||||
, peer_speedmsg(speedmsg)
|
||||
, block_index(block_num)
|
||||
, piece_index(piece_num)
|
||||
{ assert(block_index >= 0 && piece_index >= 0);}
|
||||
|
||||
std::string peer_speedmsg;
|
||||
int block_index;
|
||||
int piece_index;
|
||||
|
||||
virtual std::auto_ptr<alert> clone() const
|
||||
{ return std::auto_ptr<alert>(new block_downloading_alert(*this)); }
|
||||
};
|
||||
|
||||
struct TORRENT_EXPORT storage_moved_alert: torrent_alert
|
||||
{
|
||||
storage_moved_alert(torrent_handle const& h, std::string const& path)
|
||||
|
|
|
@ -90,47 +90,47 @@ struct bandwidth_limit
|
|||
{
|
||||
static const int inf = boost::integer_traits<int>::const_max;
|
||||
|
||||
bandwidth_limit()
|
||||
bandwidth_limit() throw()
|
||||
: m_quota_left(0)
|
||||
, m_local_limit(inf)
|
||||
, m_current_rate(0)
|
||||
{}
|
||||
|
||||
void throttle(int limit)
|
||||
void throttle(int limit) throw()
|
||||
{
|
||||
m_local_limit = limit;
|
||||
}
|
||||
|
||||
int throttle() const
|
||||
int throttle() const throw()
|
||||
{
|
||||
return m_local_limit;
|
||||
}
|
||||
|
||||
void assign(int amount)
|
||||
void assign(int amount) throw()
|
||||
{
|
||||
assert(amount > 0);
|
||||
m_current_rate += amount;
|
||||
m_quota_left += amount;
|
||||
}
|
||||
|
||||
void use_quota(int amount)
|
||||
void use_quota(int amount) throw()
|
||||
{
|
||||
assert(amount <= m_quota_left);
|
||||
m_quota_left -= amount;
|
||||
}
|
||||
|
||||
int quota_left() const
|
||||
int quota_left() const throw()
|
||||
{
|
||||
return (std::max)(m_quota_left, 0);
|
||||
}
|
||||
|
||||
void expire(int amount)
|
||||
void expire(int amount) throw()
|
||||
{
|
||||
assert(amount >= 0);
|
||||
m_current_rate -= amount;
|
||||
}
|
||||
|
||||
int max_assignable() const
|
||||
int max_assignable() const throw()
|
||||
{
|
||||
if (m_local_limit == inf) return inf;
|
||||
if (m_local_limit <= m_current_rate) return 0;
|
||||
|
@ -160,7 +160,7 @@ private:
|
|||
};
|
||||
|
||||
template<class T>
|
||||
T clamp(T val, T ceiling, T floor)
|
||||
T clamp(T val, T ceiling, T floor) throw()
|
||||
{
|
||||
assert(ceiling >= floor);
|
||||
if (val >= ceiling) return ceiling;
|
||||
|
@ -171,7 +171,7 @@ T clamp(T val, T ceiling, T floor)
|
|||
template<class PeerConnection, class Torrent>
|
||||
struct bandwidth_manager
|
||||
{
|
||||
bandwidth_manager(io_service& ios, int channel)
|
||||
bandwidth_manager(io_service& ios, int channel) throw()
|
||||
: m_ios(ios)
|
||||
, m_history_timer(m_ios)
|
||||
, m_limit(bandwidth_limit::inf)
|
||||
|
@ -179,14 +179,14 @@ struct bandwidth_manager
|
|||
, m_channel(channel)
|
||||
{}
|
||||
|
||||
void throttle(int limit)
|
||||
void throttle(int limit) throw()
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
assert(limit >= 0);
|
||||
m_limit = limit;
|
||||
}
|
||||
|
||||
int throttle() const
|
||||
int throttle() const throw()
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
return m_limit;
|
||||
|
@ -197,7 +197,7 @@ struct bandwidth_manager
|
|||
// this is used by web seeds
|
||||
void request_bandwidth(intrusive_ptr<PeerConnection> peer
|
||||
, int blk
|
||||
, bool non_prioritized)
|
||||
, bool non_prioritized) throw()
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
assert(blk > 0);
|
||||
|
@ -257,8 +257,11 @@ struct bandwidth_manager
|
|||
|
||||
private:
|
||||
|
||||
void add_history_entry(history_entry<PeerConnection, Torrent> const& e) try
|
||||
void add_history_entry(history_entry<PeerConnection, Torrent> const& e) throw()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
try {
|
||||
#endif
|
||||
INVARIANT_CHECK;
|
||||
m_history.push_front(e);
|
||||
m_current_quota += e.amount;
|
||||
|
@ -268,11 +271,17 @@ private:
|
|||
|
||||
m_history_timer.expires_at(e.expires_at);
|
||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception&) { assert(false); }
|
||||
#endif
|
||||
}
|
||||
catch (std::exception&) { assert(false); }
|
||||
|
||||
void on_history_expire(asio::error_code const& e) try
|
||||
void on_history_expire(asio::error_code const& e) throw()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
try {
|
||||
#endif
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (e) return;
|
||||
|
@ -303,14 +312,20 @@ private:
|
|||
// means we can hand out more (in case there
|
||||
// are still consumers in line)
|
||||
if (!m_queue.empty()) hand_out_bandwidth();
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
assert(false);
|
||||
};
|
||||
|
||||
void hand_out_bandwidth() try
|
||||
void hand_out_bandwidth() throw()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
try {
|
||||
#endif
|
||||
INVARIANT_CHECK;
|
||||
|
||||
ptime now(time_now());
|
||||
|
@ -404,9 +419,12 @@ private:
|
|||
add_history_entry(history_entry<PeerConnection, Torrent>(
|
||||
qe.peer, t, hand_out_amount, now + bw_window_size));
|
||||
}
|
||||
#ifndef NDEBUG
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{ assert(false); };
|
||||
#endif
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{ assert(false); };
|
||||
|
||||
|
||||
typedef boost::mutex mutex_t;
|
||||
|
|
|
@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||
|
||||
#define TORRENT_DEPRECATED __attribute__ ((deprecated))
|
||||
|
||||
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
|
||||
# define TORRENT_EXPORT __attribute__ ((visibility("default")))
|
||||
# else
|
||||
|
@ -61,6 +63,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
# define TORRENT_EXPORT
|
||||
#endif
|
||||
|
||||
#ifndef TORRENT_DEPRECATED
|
||||
#define TORRENT_DEPRECATED
|
||||
#endif
|
||||
|
||||
#endif // TORRENT_CONFIG_HPP_INCLUDED
|
||||
|
||||
|
|
|
@ -111,6 +111,10 @@ namespace libtorrent
|
|||
// memory pool for read and write operations
|
||||
boost::pool<> m_pool;
|
||||
|
||||
#ifndef NDEBUG
|
||||
int m_block_size;
|
||||
#endif
|
||||
|
||||
// thread for performing blocking disk io operations
|
||||
boost::thread m_disk_io_thread;
|
||||
};
|
||||
|
|
|
@ -59,7 +59,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <iosfwd>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
|
|
@ -74,10 +74,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/socket_type.hpp"
|
||||
#include "libtorrent/intrusive_ptr_base.hpp"
|
||||
|
||||
// TODO: each time a block is 'taken over'
|
||||
// from another peer. That peer must be given
|
||||
// a chance to become not-interested.
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
class torrent;
|
||||
|
@ -395,9 +391,7 @@ namespace libtorrent
|
|||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||
buffer::interval wr_recv_buffer()
|
||||
{
|
||||
#if defined _SECURE_SCL && _SECURE_SCL > 0
|
||||
if (m_recv_buffer.empty()) return buffer::interval(0,0);
|
||||
#endif
|
||||
return buffer::interval(&m_recv_buffer[0]
|
||||
, &m_recv_buffer[0] + m_recv_pos);
|
||||
}
|
||||
|
@ -405,9 +399,7 @@ namespace libtorrent
|
|||
|
||||
buffer::const_interval receive_buffer() const
|
||||
{
|
||||
#if defined _SECURE_SCL && _SECURE_SCL > 0
|
||||
if (m_recv_buffer.empty()) return buffer::const_interval(0,0);
|
||||
#endif
|
||||
return buffer::const_interval(&m_recv_buffer[0]
|
||||
, &m_recv_buffer[0] + m_recv_pos);
|
||||
}
|
||||
|
@ -646,7 +638,8 @@ namespace libtorrent
|
|||
bool m_queued;
|
||||
|
||||
// these are true when there's a asynchronous write
|
||||
// or read operation running.
|
||||
// or read operation in progress. Or an asyncronous bandwidth
|
||||
// request is in progress.
|
||||
bool m_writing;
|
||||
bool m_reading;
|
||||
|
||||
|
@ -701,6 +694,10 @@ namespace libtorrent
|
|||
// a timestamp when the remote download rate
|
||||
// was last updated
|
||||
ptime m_remote_dl_update;
|
||||
|
||||
// the number of bytes send to the disk-io
|
||||
// thread that hasn't yet been completely written.
|
||||
int m_outstanding_writing_bytes;
|
||||
|
||||
#ifndef NDEBUG
|
||||
public:
|
||||
|
|
|
@ -144,6 +144,10 @@ namespace libtorrent
|
|||
|
||||
// approximate peer download rate
|
||||
int remote_dl_rate;
|
||||
|
||||
// number of bytes this peer has in
|
||||
// the disk write queue
|
||||
int pending_disk_bytes;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -163,7 +163,9 @@ namespace libtorrent
|
|||
void we_have(int index);
|
||||
|
||||
// sets the priority of a piece.
|
||||
void set_piece_priority(int index, int prio);
|
||||
// returns true if the priority was changed from 0 to non-0
|
||||
// or vice versa
|
||||
bool set_piece_priority(int index, int prio);
|
||||
|
||||
// returns the priority for the piece at 'index'
|
||||
int piece_priority(int index) const;
|
||||
|
@ -215,6 +217,9 @@ namespace libtorrent
|
|||
void mark_as_finished(piece_block block, void* peer);
|
||||
int num_peers(piece_block block) const;
|
||||
|
||||
// returns information about the given piece
|
||||
void piece_info(int index, piece_picker::downloading_piece& st) const;
|
||||
|
||||
// if a piece had a hash-failure, it must be restored and
|
||||
// made available for redownloading
|
||||
void restore_piece(int index);
|
||||
|
|
|
@ -110,6 +110,8 @@ namespace libtorrent
|
|||
// the peer is not interested in our pieces
|
||||
void not_interested(peer_connection& c);
|
||||
|
||||
void ip_filter_updated();
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool has_connection(const peer_connection* p);
|
||||
|
||||
|
|
|
@ -144,14 +144,15 @@ namespace libtorrent
|
|||
, int block_size = 16 * 1024
|
||||
, storage_constructor_type sc = default_storage_constructor);
|
||||
|
||||
// TODO: deprecated, this is for backwards compatibility only
|
||||
// ==== deprecated, this is for backwards compatibility only
|
||||
// instead, use one of the other add_torrent overloads
|
||||
torrent_handle add_torrent(
|
||||
entry const& e
|
||||
, fs::path const& save_path
|
||||
, entry const& resume_data = entry()
|
||||
, bool compact_mode = true
|
||||
, int block_size = 16 * 1024
|
||||
, storage_constructor_type sc = default_storage_constructor)
|
||||
, storage_constructor_type sc = default_storage_constructor) TORRENT_DEPRECATED
|
||||
{
|
||||
return add_torrent(torrent_info(e), save_path, resume_data
|
||||
, compact_mode, block_size, sc);
|
||||
|
|
|
@ -108,6 +108,7 @@ namespace libtorrent
|
|||
, unchoke_interval(20)
|
||||
, num_want(200)
|
||||
, initial_picker_threshold(4)
|
||||
, max_outstanding_disk_bytes_per_connection(64 * 1024)
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
, use_dht_as_fallback(true)
|
||||
#endif
|
||||
|
@ -251,6 +252,14 @@ namespace libtorrent
|
|||
// random pieces instead of rarest first.
|
||||
int initial_picker_threshold;
|
||||
|
||||
// the maximum number of bytes a connection may have
|
||||
// pending in the disk write queue before its download
|
||||
// rate is being throttled. This prevents fast downloads
|
||||
// to slow medias to allocate more and more memory
|
||||
// indefinitely. This should be set to at least 32 kB
|
||||
// to not completely disrupt normal downloads.
|
||||
int max_outstanding_disk_bytes_per_connection;
|
||||
|
||||
#ifndef TORRENT_DISABLE_DHT
|
||||
// while this is true, the dht will note be used unless the
|
||||
// tracker is online
|
||||
|
|
|
@ -175,6 +175,8 @@ namespace libtorrent
|
|||
boost::tuples::tuple<size_type, size_type> bytes_done() const;
|
||||
size_type quantized_bytes_done() const;
|
||||
|
||||
void ip_filter_updated() { m_policy->ip_filter_updated(); }
|
||||
|
||||
void pause();
|
||||
void resume();
|
||||
bool is_paused() const { return m_paused; }
|
||||
|
|
|
@ -241,6 +241,12 @@ namespace libtorrent
|
|||
enum { max_blocks_per_piece = 256 };
|
||||
int piece_index;
|
||||
int blocks_in_piece;
|
||||
// the number of blocks in the finished state
|
||||
int finished;
|
||||
// the number of blocks in the writing state
|
||||
int writing;
|
||||
// the number of blocks in the requested state
|
||||
int requested;
|
||||
block_info blocks[max_blocks_per_piece];
|
||||
enum state_t { none, slow, medium, fast };
|
||||
state_t piece_state;
|
||||
|
@ -290,13 +296,13 @@ namespace libtorrent
|
|||
|
||||
// marks the piece with the given index as filtered
|
||||
// it will not be downloaded
|
||||
void filter_piece(int index, bool filter) const;
|
||||
void filter_pieces(std::vector<bool> const& pieces) const;
|
||||
bool is_piece_filtered(int index) const;
|
||||
std::vector<bool> filtered_pieces() const;
|
||||
void filter_piece(int index, bool filter) const TORRENT_DEPRECATED;
|
||||
void filter_pieces(std::vector<bool> const& pieces) const TORRENT_DEPRECATED;
|
||||
bool is_piece_filtered(int index) const TORRENT_DEPRECATED;
|
||||
std::vector<bool> filtered_pieces() const TORRENT_DEPRECATED;
|
||||
// marks the file with the given index as filtered
|
||||
// it will not be downloaded
|
||||
void filter_files(std::vector<bool> const& files) const;
|
||||
void filter_files(std::vector<bool> const& files) const TORRENT_DEPRECATED;
|
||||
|
||||
// ================ end deprecation ============
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iosfwd>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push, 1)
|
||||
|
@ -146,7 +147,8 @@ namespace libtorrent
|
|||
const std::string& name() const { assert(m_piece_length > 0); return m_name; }
|
||||
|
||||
// ------- start deprecation -------
|
||||
void print(std::ostream& os) const;
|
||||
// this functionaily will be removed in a future version
|
||||
void print(std::ostream& os) const TORRENT_DEPRECATED;
|
||||
// ------- end deprecation -------
|
||||
|
||||
bool is_valid() const { return m_piece_length > 0; }
|
||||
|
|
|
@ -33,11 +33,25 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_XML_PARSE_HPP
|
||||
#define TORRENT_XML_PARSE_HPP
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
const int xml_start_tag = 0;
|
||||
const int xml_end_tag = 1;
|
||||
const int xml_string = 2;
|
||||
enum
|
||||
{
|
||||
xml_start_tag,
|
||||
xml_end_tag,
|
||||
xml_empty_tag,
|
||||
xml_declaration_tag,
|
||||
xml_string,
|
||||
xml_attribute,
|
||||
xml_comment,
|
||||
xml_parse_error
|
||||
};
|
||||
|
||||
// callback(int type, char const* name, char const* val)
|
||||
// str2 is only used for attributes. name is element or attribute
|
||||
// name and val is attribute value
|
||||
|
||||
template <class CallbackType>
|
||||
void xml_parse(char* p, char* end, CallbackType callback)
|
||||
|
@ -45,6 +59,8 @@ namespace libtorrent
|
|||
for(;p != end; ++p)
|
||||
{
|
||||
char const* start = p;
|
||||
char const* val_start = 0;
|
||||
int token;
|
||||
// look for tag start
|
||||
for(; *p != '<' && p != end; ++p);
|
||||
|
||||
|
@ -55,39 +71,135 @@ namespace libtorrent
|
|||
assert(*p == '<');
|
||||
*p = 0;
|
||||
}
|
||||
callback(xml_string, start);
|
||||
token = xml_string;
|
||||
callback(token, start, val_start);
|
||||
if (p != end) *p = '<';
|
||||
}
|
||||
|
||||
|
||||
if (p == end) break;
|
||||
|
||||
// skip '<'
|
||||
++p;
|
||||
|
||||
// parse the name of the tag. Ignore attributes
|
||||
for (start = p; p != end && *p != '>'; ++p)
|
||||
{
|
||||
// terminate the string at the first space
|
||||
// to ignore tag attributes
|
||||
if (*p == ' ') *p = 0;
|
||||
}
|
||||
// parse the name of the tag.
|
||||
for (start = p; p != end && *p != '>' && !std::isspace(*p); ++p);
|
||||
|
||||
char* tag_name_end = p;
|
||||
|
||||
// skip the attributes for now
|
||||
for (; p != end && *p != '>'; ++p);
|
||||
|
||||
// parse error
|
||||
if (p == end) break;
|
||||
if (p == end)
|
||||
{
|
||||
token = xml_parse_error;
|
||||
start = "unexpected end of file";
|
||||
callback(token, start, val_start);
|
||||
break;
|
||||
}
|
||||
|
||||
assert(*p == '>');
|
||||
*p = 0;
|
||||
// save the character that terminated the tag name
|
||||
// it could be both '>' and ' '.
|
||||
char save = *tag_name_end;
|
||||
*tag_name_end = 0;
|
||||
|
||||
char* tag_end = p;
|
||||
if (*start == '/')
|
||||
{
|
||||
++start;
|
||||
callback(xml_end_tag, start);
|
||||
token = xml_end_tag;
|
||||
callback(token, start, val_start);
|
||||
}
|
||||
else if (*(p-1) == '/')
|
||||
{
|
||||
*(p-1) = 0;
|
||||
token = xml_empty_tag;
|
||||
callback(token, start, val_start);
|
||||
*(p-1) = '/';
|
||||
tag_end = p - 1;
|
||||
}
|
||||
else if (*start == '?' && *(p-1) == '?')
|
||||
{
|
||||
*(p-1) = 0;
|
||||
++start;
|
||||
token = xml_declaration_tag;
|
||||
callback(token, start, val_start);
|
||||
*(p-1) = '?';
|
||||
tag_end = p - 1;
|
||||
}
|
||||
else if (start + 5 < p && memcmp(start, "!--", 3) == 0 && memcmp(p-2, "--", 2) == 0)
|
||||
{
|
||||
start += 3;
|
||||
*(p-2) = 0;
|
||||
token = xml_comment;
|
||||
callback(token, start, val_start);
|
||||
*(p-2) = '-';
|
||||
tag_end = p - 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(xml_start_tag, start);
|
||||
token = xml_start_tag;
|
||||
callback(token, start, val_start);
|
||||
}
|
||||
|
||||
*tag_name_end = save;
|
||||
|
||||
// parse attributes
|
||||
for (char* i = tag_name_end; i < tag_end; ++i)
|
||||
{
|
||||
// find start of attribute name
|
||||
for (; i != tag_end && std::isspace(*i); ++i);
|
||||
if (i == tag_end) break;
|
||||
start = i;
|
||||
// find end of attribute name
|
||||
for (; i != tag_end && *i != '=' && !std::isspace(*i); ++i);
|
||||
char* name_end = i;
|
||||
|
||||
// look for equality sign
|
||||
for (; i != tag_end && *i != '='; ++i);
|
||||
|
||||
if (i == tag_end)
|
||||
{
|
||||
token = xml_parse_error;
|
||||
val_start = 0;
|
||||
start = "garbage inside element brackets";
|
||||
callback(token, start, val_start);
|
||||
break;
|
||||
}
|
||||
|
||||
++i;
|
||||
for (; i != tag_end && std::isspace(*i); ++i);
|
||||
// check for parse error (values must be quoted)
|
||||
if (i == tag_end || (*i != '\'' && *i != '\"'))
|
||||
{
|
||||
token = xml_parse_error;
|
||||
val_start = 0;
|
||||
start = "unquoted attribute value";
|
||||
callback(token, start, val_start);
|
||||
break;
|
||||
}
|
||||
char quote = *i;
|
||||
++i;
|
||||
val_start = i;
|
||||
for (; i != tag_end && *i != quote; ++i);
|
||||
// parse error (missing end quote)
|
||||
if (i == tag_end)
|
||||
{
|
||||
token = xml_parse_error;
|
||||
val_start = 0;
|
||||
start = "missing end quote on attribute";
|
||||
callback(token, start, val_start);
|
||||
break;
|
||||
}
|
||||
save = *i;
|
||||
*i = 0;
|
||||
*name_end = 0;
|
||||
token = xml_attribute;
|
||||
callback(token, start, val_start);
|
||||
*name_end = '=';
|
||||
*i = save;
|
||||
}
|
||||
*p = '>';
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -95,6 +95,6 @@ $(top_srcdir)/include/libtorrent/version.hpp
|
|||
libtorrent_la_LDFLAGS = $(LDFLAGS) -release @VERSION@
|
||||
libtorrent_la_LIBADD = @ZLIB@ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@
|
||||
|
||||
AM_CXXFLAGS= -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@
|
||||
AM_CXXFLAGS= -ftemplate-depth-50 -I$(top_srcdir)/include -I$(top_srcdir)/include/libtorrent @ZLIBINCL@ @DEBUGFLAGS@ @PTHREAD_CFLAGS@ -DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION
|
||||
AM_LDFLAGS= $(LDFLAGS) -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@
|
||||
|
||||
|
|
|
@ -159,7 +159,7 @@ namespace libtorrent
|
|||
ptime next_expire = max_time();
|
||||
ptime now = time_now();
|
||||
for (std::list<entry>::iterator i = m_queue.begin();
|
||||
i != m_queue.end();)
|
||||
!m_queue.empty() && i != m_queue.end();)
|
||||
{
|
||||
if (i->connecting && i->expires < now)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,9 @@ namespace libtorrent
|
|||
: m_abort(false)
|
||||
, m_queue_buffer_size(0)
|
||||
, m_pool(block_size)
|
||||
#ifndef NDEBUG
|
||||
, m_block_size(block_size)
|
||||
#endif
|
||||
, m_disk_io_thread(boost::ref(*this))
|
||||
{}
|
||||
|
||||
|
@ -192,6 +195,7 @@ namespace libtorrent
|
|||
}
|
||||
else
|
||||
{
|
||||
assert(j.buffer_size <= m_block_size);
|
||||
ret = j.storage->read_impl(j.buffer, j.piece, j.offset
|
||||
, j.buffer_size);
|
||||
|
||||
|
@ -201,6 +205,7 @@ namespace libtorrent
|
|||
break;
|
||||
case disk_io_job::write:
|
||||
assert(j.buffer);
|
||||
assert(j.buffer_size <= m_block_size);
|
||||
j.storage->write_impl(j.buffer, j.piece, j.offset
|
||||
, j.buffer_size);
|
||||
|
||||
|
|
|
@ -248,11 +248,17 @@ namespace libtorrent
|
|||
void set_size(size_type s)
|
||||
{
|
||||
size_type pos = tell();
|
||||
seek(s - 1);
|
||||
char dummy = 0;
|
||||
read(&dummy, 1);
|
||||
seek(s - 1);
|
||||
write(&dummy, 1);
|
||||
// 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))
|
||||
{
|
||||
seek(s - 1);
|
||||
char dummy = 0;
|
||||
read(&dummy, 1);
|
||||
seek(s - 1);
|
||||
write(&dummy, 1);
|
||||
}
|
||||
seek(pos);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/lsd.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/http_tracker_connection.hpp"
|
||||
#include "libtorrent/xml_parse.hpp"
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <asio/ip/host_name.hpp>
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace libtorrent
|
|||
, m_remote_bytes_dled(0)
|
||||
, m_remote_dl_rate(0)
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_outstanding_writing_bytes(0)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
|
@ -189,6 +190,7 @@ namespace libtorrent
|
|||
, m_remote_bytes_dled(0)
|
||||
, m_remote_dl_rate(0)
|
||||
, m_remote_dl_update(time_now())
|
||||
, m_outstanding_writing_bytes(0)
|
||||
#ifndef NDEBUG
|
||||
, m_in_constructor(true)
|
||||
#endif
|
||||
|
@ -936,7 +938,8 @@ namespace libtorrent
|
|||
&& r.start < t->torrent_file().piece_size(r.piece)
|
||||
&& r.length > 0
|
||||
&& r.length + r.start <= t->torrent_file().piece_size(r.piece)
|
||||
&& m_peer_interested)
|
||||
&& m_peer_interested
|
||||
&& r.length <= t->block_size())
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << time_now_string()
|
||||
|
@ -961,7 +964,8 @@ namespace libtorrent
|
|||
"i: " << m_peer_interested << " | "
|
||||
"t: " << (int)t->torrent_file().piece_size(r.piece) << " | "
|
||||
"n: " << t->torrent_file().num_pieces() << " | "
|
||||
"h: " << t->have_piece(r.piece) << " ]\n";
|
||||
"h: " << t->have_piece(r.piece) << " | "
|
||||
"block_limit: " << t->block_size() << " ]\n";
|
||||
#endif
|
||||
|
||||
++m_num_invalid_requests;
|
||||
|
@ -1150,6 +1154,8 @@ namespace libtorrent
|
|||
|
||||
fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete
|
||||
, self(), _1, _2, p, t));
|
||||
m_outstanding_writing_bytes += p.length;
|
||||
assert(!m_reading);
|
||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
||||
}
|
||||
|
||||
|
@ -1158,6 +1164,16 @@ namespace libtorrent
|
|||
{
|
||||
session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
|
||||
|
||||
m_outstanding_writing_bytes -= p.length;
|
||||
assert(m_outstanding_writing_bytes >= 0);
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << " *** on_disk_write_complete() " << p.length << "\n";
|
||||
#endif
|
||||
// in case the outstanding bytes just dropped down
|
||||
// to allow to receive more data
|
||||
setup_receive();
|
||||
|
||||
if (ret == -1 || !t)
|
||||
{
|
||||
if (!t)
|
||||
|
@ -1183,6 +1199,11 @@ namespace libtorrent
|
|||
assert(p.start == j.offset);
|
||||
piece_block block_finished(p.piece, p.start / t->block_size());
|
||||
picker.mark_as_finished(block_finished, peer_info_struct());
|
||||
if (t->alerts().should_post(alert::info))
|
||||
{
|
||||
t->alerts().post_alert(block_finished_alert(t->get_handle(),
|
||||
block_finished.block_index, block_finished.piece_index, "block finished"));
|
||||
}
|
||||
|
||||
if (!has_peer_choked() && !t->is_seed() && !m_torrent.expired())
|
||||
{
|
||||
|
@ -1290,11 +1311,29 @@ namespace libtorrent
|
|||
|
||||
piece_picker::piece_state_t state;
|
||||
peer_speed_t speed = peer_speed();
|
||||
if (speed == fast) state = piece_picker::fast;
|
||||
else if (speed == medium) state = piece_picker::medium;
|
||||
else state = piece_picker::slow;
|
||||
std::string speedmsg;
|
||||
if (speed == fast)
|
||||
{
|
||||
speedmsg = "fast";
|
||||
state = piece_picker::fast;
|
||||
}
|
||||
else if (speed == medium)
|
||||
{
|
||||
speedmsg = "medium";
|
||||
state = piece_picker::medium;
|
||||
}
|
||||
else
|
||||
{
|
||||
speedmsg = "slow";
|
||||
state = piece_picker::slow;
|
||||
}
|
||||
|
||||
t->picker().mark_as_downloading(block, peer_info_struct(), state);
|
||||
if (t->alerts().should_post(alert::info))
|
||||
{
|
||||
t->alerts().post_alert(block_downloading_alert(t->get_handle(),
|
||||
speedmsg, block.block_index, block.piece_index, "block downloading"));
|
||||
}
|
||||
|
||||
m_request_queue.push_back(block);
|
||||
}
|
||||
|
@ -1642,6 +1681,7 @@ namespace libtorrent
|
|||
p.payload_up_speed = statistics().upload_payload_rate();
|
||||
p.pid = pid();
|
||||
p.ip = remote();
|
||||
p.pending_disk_bytes = m_outstanding_writing_bytes;
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
p.country[0] = m_country[0];
|
||||
|
@ -2015,11 +2055,13 @@ namespace libtorrent
|
|||
m_bandwidth_limit[channel].assign(amount);
|
||||
if (channel == upload_channel)
|
||||
{
|
||||
assert(m_writing);
|
||||
m_writing = false;
|
||||
setup_send();
|
||||
}
|
||||
else if (channel == download_channel)
|
||||
{
|
||||
assert(m_reading);
|
||||
m_reading = false;
|
||||
setup_receive();
|
||||
}
|
||||
|
@ -2067,10 +2109,11 @@ namespace libtorrent
|
|||
(*m_logger) << "req bandwidth [ " << upload_channel << " ]\n";
|
||||
#endif
|
||||
|
||||
assert(!m_writing);
|
||||
// peers that we are not interested in are non-prioritized
|
||||
m_writing = true;
|
||||
t->request_bandwidth(upload_channel, self()
|
||||
, !(is_interesting() && !has_peer_choked()));
|
||||
m_writing = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2116,6 +2159,9 @@ namespace libtorrent
|
|||
|
||||
INVARIANT_CHECK;
|
||||
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "setup_receive: reading = " << m_reading << "\n";
|
||||
#endif
|
||||
if (m_reading) return;
|
||||
|
||||
shared_ptr<torrent> t = m_torrent.lock();
|
||||
|
@ -2130,8 +2176,8 @@ namespace libtorrent
|
|||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
||||
#endif
|
||||
t->request_bandwidth(download_channel, self(), m_non_prioritized);
|
||||
m_reading = true;
|
||||
t->request_bandwidth(download_channel, self(), m_non_prioritized);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -2144,7 +2190,7 @@ namespace libtorrent
|
|||
if (!m_ignore_bandwidth_limits && max_receive > quota_left)
|
||||
max_receive = quota_left;
|
||||
|
||||
assert(max_receive > 0);
|
||||
if (max_receive == 0) return;
|
||||
|
||||
assert(m_recv_pos >= 0);
|
||||
assert(m_packet_size > 0);
|
||||
|
@ -2242,10 +2288,7 @@ namespace libtorrent
|
|||
m_recv_pos += bytes_transferred;
|
||||
assert(m_recv_pos <= int(m_recv_buffer.size()));
|
||||
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
on_receive(error, bytes_transferred);
|
||||
}
|
||||
on_receive(error, bytes_transferred);
|
||||
|
||||
assert(m_packet_size > 0);
|
||||
|
||||
|
@ -2322,9 +2365,17 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
return (m_bandwidth_limit[download_channel].quota_left() > 0
|
||||
bool ret = (m_bandwidth_limit[download_channel].quota_left() > 0
|
||||
|| m_ignore_bandwidth_limits)
|
||||
&& !m_connecting;
|
||||
&& !m_connecting
|
||||
&& m_outstanding_writing_bytes <
|
||||
m_ses.settings().max_outstanding_disk_bytes_per_connection;
|
||||
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
(*m_logger) << "*** can_read() " << ret << " reading: " << m_reading << "\n";
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void peer_connection::connect(int ticket)
|
||||
|
@ -2649,6 +2700,7 @@ namespace libtorrent
|
|||
(*m_logger) << time_now_string() << " ==> KEEPALIVE\n";
|
||||
#endif
|
||||
|
||||
m_last_sent = time_now();
|
||||
write_keepalive();
|
||||
}
|
||||
|
||||
|
|
|
@ -129,6 +129,35 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
void piece_picker::piece_info(int index, piece_picker::downloading_piece& st) const
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
|
||||
assert(index >= 0);
|
||||
assert(index < int(m_piece_map.size()));
|
||||
|
||||
if (m_piece_map[index].downloading)
|
||||
{
|
||||
std::vector<downloading_piece>::const_iterator piece = std::find_if(
|
||||
m_downloads.begin(), m_downloads.end()
|
||||
, bind(&downloading_piece::index, _1) == index);
|
||||
assert(piece != m_downloads.end());
|
||||
st = *piece;
|
||||
st.info = 0;
|
||||
return;
|
||||
}
|
||||
st.info = 0;
|
||||
st.index = index;
|
||||
st.writing = 0;
|
||||
st.requested = 0;
|
||||
if (m_piece_map[index].have())
|
||||
{
|
||||
st.finished = blocks_in_piece(index);
|
||||
return;
|
||||
}
|
||||
st.finished = 0;
|
||||
}
|
||||
|
||||
void piece_picker::set_sequenced_download_threshold(
|
||||
int sequenced_download_threshold)
|
||||
{
|
||||
|
@ -196,7 +225,8 @@ namespace libtorrent
|
|||
int block_index = num_downloads * m_blocks_per_piece;
|
||||
if (int(m_block_info.size()) < block_index + m_blocks_per_piece)
|
||||
{
|
||||
block_info* base = &m_block_info[0];
|
||||
block_info* base = 0;
|
||||
if (!m_block_info.empty()) base = &m_block_info[0];
|
||||
m_block_info.resize(block_index + m_blocks_per_piece);
|
||||
if (!m_downloads.empty() && &m_block_info[0] != base)
|
||||
{
|
||||
|
@ -605,9 +635,10 @@ namespace libtorrent
|
|||
void piece_picker::sort_piece(std::vector<downloading_piece>::iterator dp)
|
||||
{
|
||||
assert(m_piece_map[dp->index].downloading);
|
||||
if (dp == m_downloads.begin()) return;
|
||||
int complete = dp->writing + dp->finished;
|
||||
for (std::vector<downloading_piece>::iterator i = dp, j(dp-1);
|
||||
i != m_downloads.begin(); --i, --j)
|
||||
i != m_downloads.begin() && j != m_downloads.begin(); --i, --j)
|
||||
{
|
||||
assert(j >= m_downloads.begin());
|
||||
if (j->finished + j->writing >= complete) return;
|
||||
|
@ -935,7 +966,7 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
|
||||
void piece_picker::set_piece_priority(int index, int new_piece_priority)
|
||||
bool piece_picker::set_piece_priority(int index, int new_piece_priority)
|
||||
{
|
||||
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||
assert(new_piece_priority >= 0);
|
||||
|
@ -946,16 +977,18 @@ namespace libtorrent
|
|||
piece_pos& p = m_piece_map[index];
|
||||
|
||||
// if the priority isn't changed, don't do anything
|
||||
if (new_piece_priority == int(p.piece_priority)) return;
|
||||
if (new_piece_priority == int(p.piece_priority)) return false;
|
||||
|
||||
int prev_priority = p.priority(m_sequenced_download_threshold);
|
||||
|
||||
bool ret = false;
|
||||
if (new_piece_priority == piece_pos::filter_priority
|
||||
&& p.piece_priority != piece_pos::filter_priority)
|
||||
{
|
||||
// the piece just got filtered
|
||||
if (p.have()) ++m_num_have_filtered;
|
||||
else ++m_num_filtered;
|
||||
ret = true;
|
||||
}
|
||||
else if (new_piece_priority != piece_pos::filter_priority
|
||||
&& p.piece_priority == piece_pos::filter_priority)
|
||||
|
@ -963,6 +996,7 @@ namespace libtorrent
|
|||
// the piece just got unfiltered
|
||||
if (p.have()) --m_num_have_filtered;
|
||||
else --m_num_filtered;
|
||||
ret = true;
|
||||
}
|
||||
assert(m_num_filtered >= 0);
|
||||
assert(m_num_have_filtered >= 0);
|
||||
|
@ -970,7 +1004,7 @@ namespace libtorrent
|
|||
p.piece_priority = new_piece_priority;
|
||||
int new_priority = p.priority(m_sequenced_download_threshold);
|
||||
|
||||
if (new_priority == prev_priority) return;
|
||||
if (new_priority == prev_priority) return false;
|
||||
|
||||
if (prev_priority == 0)
|
||||
{
|
||||
|
@ -980,6 +1014,7 @@ namespace libtorrent
|
|||
{
|
||||
move(prev_priority, p.index);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int piece_picker::piece_priority(int index) const
|
||||
|
@ -1051,8 +1086,12 @@ namespace libtorrent
|
|||
// downloaded to
|
||||
std::vector<piece_block> backup_blocks;
|
||||
|
||||
// When prefer_whole_pieces is set (usually set when downloading from
|
||||
// fast peers) the partial pieces will not be prioritized, but actually
|
||||
// ignored as long as possible. All blocks found in downloading
|
||||
// pieces are regarded as backup blocks
|
||||
bool ignore_downloading_pieces = false;
|
||||
if (!prefer_whole_pieces)
|
||||
if (prefer_whole_pieces)
|
||||
{
|
||||
std::vector<int> downloading_pieces;
|
||||
downloading_pieces.reserve(m_downloads.size());
|
||||
|
@ -1061,8 +1100,8 @@ namespace libtorrent
|
|||
{
|
||||
downloading_pieces.push_back(i->index);
|
||||
}
|
||||
num_blocks = add_interesting_blocks(downloading_pieces, pieces
|
||||
, interesting_blocks, backup_blocks, num_blocks
|
||||
add_interesting_blocks(downloading_pieces, pieces
|
||||
, backup_blocks, backup_blocks, num_blocks
|
||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||
ignore_downloading_pieces = true;
|
||||
}
|
||||
|
@ -1072,10 +1111,6 @@ namespace libtorrent
|
|||
// has filled the interesting_blocks with num_blocks
|
||||
// blocks.
|
||||
|
||||
// When prefer_whole_pieces is set (usually set when downloading from
|
||||
// fast peers) the partial pieces will not be prioritized, but actually
|
||||
// ignored as long as possible.
|
||||
|
||||
// +1 is to ignore pieces that no peer has. The bucket with index 0 contains
|
||||
// pieces that 0 other peers have. bucket will point to a bucket with
|
||||
// pieces with the same priority. It will be iterated in priority
|
||||
|
@ -1128,8 +1163,7 @@ namespace libtorrent
|
|||
|
||||
if (!backup_blocks.empty())
|
||||
interesting_blocks.insert(interesting_blocks.end()
|
||||
, backup_blocks.begin(), backup_blocks.begin()
|
||||
+ (std::min)(num_blocks, (int)backup_blocks.size()));
|
||||
, backup_blocks.begin(), backup_blocks.end());
|
||||
}
|
||||
|
||||
void piece_picker::clear_peer(void* peer)
|
||||
|
@ -1216,7 +1250,6 @@ namespace libtorrent
|
|||
// will be picked.
|
||||
if (prefer_whole_pieces && !exclusive)
|
||||
{
|
||||
if (int(backup_blocks.size()) >= num_blocks) continue;
|
||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||
{
|
||||
block_info const& info = p->info[j];
|
||||
|
@ -1251,7 +1284,6 @@ namespace libtorrent
|
|||
&& !exclusive_active
|
||||
&& !ignore_speed_categories)
|
||||
{
|
||||
if (int(backup_blocks.size()) >= num_blocks) continue;
|
||||
backup_blocks.push_back(piece_block(*i, j));
|
||||
continue;
|
||||
}
|
||||
|
@ -1264,9 +1296,9 @@ namespace libtorrent
|
|||
// to look for blocks until we have num_blocks
|
||||
// blocks that have not been requested from any
|
||||
// other peer.
|
||||
interesting_blocks.push_back(piece_block(*i, j));
|
||||
if (p->info[j].state == block_info::state_none)
|
||||
{
|
||||
interesting_blocks.push_back(piece_block(*i, j));
|
||||
// we have found a block that's free to download
|
||||
num_blocks--;
|
||||
// if we prefer whole pieces, continue picking from this
|
||||
|
@ -1275,6 +1307,10 @@ namespace libtorrent
|
|||
assert(num_blocks >= 0);
|
||||
if (num_blocks == 0) return num_blocks;
|
||||
}
|
||||
else
|
||||
{
|
||||
backup_blocks.push_back(piece_block(*i, j));
|
||||
}
|
||||
}
|
||||
assert(num_blocks >= 0 || prefer_whole_pieces);
|
||||
if (num_blocks < 0) num_blocks = 0;
|
||||
|
|
|
@ -249,7 +249,7 @@ namespace libtorrent
|
|||
// with the other's, to see if we should abort another
|
||||
// peer_connection in favour of this one
|
||||
std::vector<piece_block> busy_pieces;
|
||||
busy_pieces.reserve(10);
|
||||
busy_pieces.reserve(num_requests);
|
||||
|
||||
for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
|
||||
i != interesting_pieces.end(); ++i)
|
||||
|
@ -272,6 +272,8 @@ namespace libtorrent
|
|||
// by somebody else. request it from this peer
|
||||
// and return
|
||||
c.add_request(*i);
|
||||
assert(p.num_peers(*i) == 1);
|
||||
assert(p.is_requested(*i));
|
||||
num_requests--;
|
||||
}
|
||||
|
||||
|
@ -286,6 +288,8 @@ namespace libtorrent
|
|||
return;
|
||||
}
|
||||
|
||||
// if all blocks has the same number of peers on them
|
||||
// we want to pick a random block
|
||||
std::random_shuffle(busy_pieces.begin(), busy_pieces.end());
|
||||
|
||||
// find the block with the fewest requests to it
|
||||
|
@ -293,7 +297,11 @@ namespace libtorrent
|
|||
busy_pieces.begin(), busy_pieces.end()
|
||||
, bind(&piece_picker::num_peers, boost::cref(p), _1) <
|
||||
bind(&piece_picker::num_peers, boost::cref(p), _2));
|
||||
|
||||
#ifndef NDEBUG
|
||||
piece_picker::downloading_piece st;
|
||||
p.piece_info(i->piece_index, st);
|
||||
assert(st.requested + st.finished + st.writing == p.blocks_in_piece(i->piece_index));
|
||||
#endif
|
||||
c.add_request(*i);
|
||||
c.send_block_requests();
|
||||
}
|
||||
|
@ -304,6 +312,47 @@ namespace libtorrent
|
|||
, m_available_free_upload(0)
|
||||
, m_last_optimistic_disconnect(min_time())
|
||||
{ assert(t); }
|
||||
|
||||
// disconnects and removes all peers that are now filtered
|
||||
void policy::ip_filter_updated()
|
||||
{
|
||||
aux::session_impl& ses = m_torrent->session();
|
||||
piece_picker* p = 0;
|
||||
if (m_torrent->has_picker())
|
||||
p = &m_torrent->picker();
|
||||
for (std::list<peer>::iterator i = m_peers.begin()
|
||||
, end(m_peers.end()); i != end;)
|
||||
{
|
||||
if ((ses.m_ip_filter.access(i->ip.address()) & ip_filter::blocked) == 0)
|
||||
{
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (i->connection)
|
||||
{
|
||||
i->connection->disconnect();
|
||||
if (ses.m_alerts.should_post(alert::info))
|
||||
{
|
||||
ses.m_alerts.post_alert(peer_blocked_alert(i->ip.address()
|
||||
, "disconnected blocked peer"));
|
||||
}
|
||||
assert(i->connection == 0
|
||||
|| i->connection->peer_info_struct() == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ses.m_alerts.should_post(alert::info))
|
||||
{
|
||||
ses.m_alerts.post_alert(peer_blocked_alert(i->ip.address()
|
||||
, "blocked peer removed from peer list"));
|
||||
}
|
||||
}
|
||||
if (p) p->clear_peer(&(*i));
|
||||
m_peers.erase(i++);
|
||||
}
|
||||
}
|
||||
|
||||
// finds the peer that has the worst download rate
|
||||
// and returns it. May return 0 if all peers are
|
||||
// choked.
|
||||
|
|
|
@ -613,29 +613,9 @@ namespace detail
|
|||
|
||||
// Close connections whose endpoint is filtered
|
||||
// by the new ip-filter
|
||||
for (session_impl::connection_map::iterator i
|
||||
= m_connections.begin(); i != m_connections.end();)
|
||||
{
|
||||
tcp::endpoint sender;
|
||||
try { sender = i->first->remote_endpoint(); }
|
||||
catch (std::exception&) { sender = i->second->remote(); }
|
||||
if (m_ip_filter.access(sender.address()) & ip_filter::blocked)
|
||||
{
|
||||
#if defined(TORRENT_VERBOSE_LOGGING)
|
||||
(*i->second->m_logger) << "*** CONNECTION FILTERED\n";
|
||||
#endif
|
||||
if (m_alerts.should_post(alert::info))
|
||||
{
|
||||
m_alerts.post_alert(peer_blocked_alert(sender.address()
|
||||
, "peer connection closed by IP filter"));
|
||||
}
|
||||
|
||||
session_impl::connection_map::iterator j = i;
|
||||
++i;
|
||||
j->second->disconnect();
|
||||
}
|
||||
else ++i;
|
||||
}
|
||||
for (torrent_map::iterator i = m_torrents.begin()
|
||||
, end(m_torrents.end()); i != end; ++i)
|
||||
i->second->ip_filter_updated();
|
||||
}
|
||||
|
||||
void session_impl::set_settings(session_settings const& s)
|
||||
|
@ -1921,13 +1901,15 @@ namespace detail
|
|||
int session_impl::upload_rate_limit() const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
return m_bandwidth_manager[peer_connection::upload_channel]->throttle();
|
||||
int ret = m_bandwidth_manager[peer_connection::upload_channel]->throttle();
|
||||
return ret == std::numeric_limits<int>::max() ? -1 : ret;
|
||||
}
|
||||
|
||||
int session_impl::download_rate_limit() const
|
||||
{
|
||||
mutex_t::scoped_lock l(m_mutex);
|
||||
return m_bandwidth_manager[peer_connection::download_channel]->throttle();
|
||||
int ret = m_bandwidth_manager[peer_connection::download_channel]->throttle();
|
||||
return ret == std::numeric_limits<int>::max() ? -1 : ret;
|
||||
}
|
||||
|
||||
void session_impl::start_lsd()
|
||||
|
|
|
@ -981,7 +981,7 @@ namespace libtorrent
|
|||
return true;
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__) || defined(__linux__)
|
||||
#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||
// find the last existing directory of the save path
|
||||
fs::path query_path = p;
|
||||
while (!query_path.empty() && !exists(query_path))
|
||||
|
@ -1019,6 +1019,7 @@ namespace libtorrent
|
|||
return true;
|
||||
}
|
||||
|
||||
// workaround for bugs in Mac OS X where zero run is not reported
|
||||
if (!strcmp(fsinfo.f_fstypename, "hfs")
|
||||
|| !strcmp(fsinfo.f_fstypename, "ufs"))
|
||||
return true;
|
||||
|
@ -1026,7 +1027,7 @@ namespace libtorrent
|
|||
return false;
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
struct statfs buf;
|
||||
int err = statfs(query_path.native_directory_string().c_str(), &buf);
|
||||
if (err == 0)
|
||||
|
@ -1044,6 +1045,7 @@ namespace libtorrent
|
|||
case 0x52345362: // Reiser4
|
||||
case 0x58465342: // XFS
|
||||
case 0x65735546: // NTFS-3G
|
||||
case 0x19540119: // UFS2
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -1125,6 +1127,7 @@ namespace libtorrent
|
|||
j.piece = r.piece;
|
||||
j.offset = r.start;
|
||||
j.buffer_size = r.length;
|
||||
assert(r.length <= 16 * 1024);
|
||||
m_io_thread.add_job(j, handler);
|
||||
}
|
||||
|
||||
|
@ -1569,16 +1572,12 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
if (m_unallocated_slots.empty())
|
||||
{
|
||||
m_state = state_create_files;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_compact_mode)
|
||||
{
|
||||
else if (m_compact_mode)
|
||||
m_state = state_create_files;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
m_state = state_allocating;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_state = state_full_check;
|
||||
|
@ -1598,7 +1597,7 @@ namespace libtorrent
|
|||
| |
|
||||
| v
|
||||
| +------------+
|
||||
| | allocating |
|
||||
|->| allocating |
|
||||
| +------------+
|
||||
| |
|
||||
| v
|
||||
|
|
|
@ -831,6 +831,11 @@ namespace libtorrent
|
|||
|
||||
if (passed_hash_check)
|
||||
{
|
||||
if (m_ses.m_alerts.should_post(alert::info))
|
||||
{
|
||||
m_ses.m_alerts.post_alert(piece_finished_alert(get_handle()
|
||||
, index, "piece finished"));
|
||||
}
|
||||
// the following call may cause picker to become invalid
|
||||
// in case we just became a seed
|
||||
announce_piece(index);
|
||||
|
@ -1104,7 +1109,7 @@ namespace libtorrent
|
|||
|
||||
void torrent::set_piece_priority(int index, int priority)
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
assert(valid_metadata());
|
||||
if (is_seed()) return;
|
||||
|
@ -1114,13 +1119,13 @@ namespace libtorrent
|
|||
assert(index >= 0);
|
||||
assert(index < m_torrent_file.num_pieces());
|
||||
|
||||
m_picker->set_piece_priority(index, priority);
|
||||
update_peer_interest();
|
||||
bool filter_updated = m_picker->set_piece_priority(index, priority);
|
||||
if (filter_updated) update_peer_interest();
|
||||
}
|
||||
|
||||
int torrent::piece_priority(int index) const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
assert(valid_metadata());
|
||||
if (is_seed()) return 1;
|
||||
|
@ -1144,14 +1149,15 @@ namespace libtorrent
|
|||
assert(m_picker.get());
|
||||
|
||||
int index = 0;
|
||||
bool filter_updated = false;
|
||||
for (std::vector<int>::const_iterator i = pieces.begin()
|
||||
, end(pieces.end()); i != end; ++i, ++index)
|
||||
{
|
||||
assert(*i >= 0);
|
||||
assert(*i <= 7);
|
||||
m_picker->set_piece_priority(index, *i);
|
||||
filter_updated |= m_picker->set_piece_priority(index, *i);
|
||||
}
|
||||
update_peer_interest();
|
||||
if (filter_updated) update_peer_interest();
|
||||
}
|
||||
|
||||
void torrent::piece_priorities(std::vector<int>& pieces) const
|
||||
|
@ -1653,17 +1659,26 @@ namespace libtorrent
|
|||
};
|
||||
|
||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||
namespace
|
||||
{
|
||||
unsigned long swap_bytes(unsigned long a)
|
||||
{
|
||||
return (a >> 24) | ((a & 0xff0000) >> 8) | ((a & 0xff00) << 8) | (a << 24);
|
||||
}
|
||||
}
|
||||
|
||||
void torrent::resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const
|
||||
{
|
||||
if (m_resolving_country
|
||||
|| p->has_country()
|
||||
|| p->is_connecting()
|
||||
|| p->is_queued()
|
||||
|| p->in_handshake()) return;
|
||||
|| p->in_handshake()
|
||||
|| p->remote().address().is_v6()) return;
|
||||
|
||||
m_resolving_country = true;
|
||||
tcp::resolver::query q(boost::lexical_cast<std::string>(p->remote().address())
|
||||
+ ".zz.countries.nerd.dk", "0");
|
||||
asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong()));
|
||||
tcp::resolver::query q(reversed.to_string() + ".zz.countries.nerd.dk", "0");
|
||||
m_host_resolver.async_resolve(q, m_ses.m_strand.wrap(
|
||||
bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)));
|
||||
}
|
||||
|
@ -2325,15 +2340,11 @@ namespace libtorrent
|
|||
|
||||
torrent_handle torrent::get_handle() const
|
||||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash());
|
||||
}
|
||||
|
||||
session_settings const& torrent::settings() const
|
||||
{
|
||||
// INVARIANT_CHECK;
|
||||
|
||||
return m_ses.settings();
|
||||
}
|
||||
|
||||
|
|
|
@ -773,6 +773,9 @@ namespace libtorrent
|
|||
partial_piece_info pi;
|
||||
pi.piece_state = (partial_piece_info::state_t)i->state;
|
||||
pi.blocks_in_piece = p.blocks_in_piece(i->index);
|
||||
pi.finished = (int)i->finished;
|
||||
pi.writing = (int)i->writing;
|
||||
pi.requested = (int)i->requested;
|
||||
int piece_size = t->torrent_file().piece_size(i->index);
|
||||
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
||||
{
|
||||
|
|
|
@ -62,9 +62,10 @@ namespace libtorrent
|
|||
{
|
||||
if (a.is_v6()) return false;
|
||||
address_v4 a4 = a.to_v4();
|
||||
return ((a4.to_ulong() & 0xff000000) == 0x0a000000
|
||||
|| (a4.to_ulong() & 0xfff00000) == 0xac100000
|
||||
|| (a4.to_ulong() & 0xffff0000) == 0xc0a80000);
|
||||
unsigned long ip = a4.to_ulong();
|
||||
return ((ip & 0xff000000) == 0x0a000000
|
||||
|| (ip & 0xfff00000) == 0xac100000
|
||||
|| (ip & 0xffff0000) == 0xc0a80000);
|
||||
}
|
||||
|
||||
address_v4 guess_local_address(asio::io_service& ios)
|
||||
|
@ -658,7 +659,7 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||
d.upnp_connection.reset();
|
||||
}
|
||||
|
||||
if (e)
|
||||
if (e && e != asio::error::eof)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
|
@ -671,7 +672,16 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== incomplete http message" << std::endl;
|
||||
<< " <== error while fetching control url: incomplete http message" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (p.status_code() != 200)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== error while fetching control url: " << p.message() << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -790,7 +800,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||
d.upnp_connection.reset();
|
||||
}
|
||||
|
||||
if (e)
|
||||
if (e && e != asio::error::eof)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
|
@ -823,12 +833,22 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== incomplete http message" << std::endl;
|
||||
<< " <== error while adding portmap: incomplete http message" << std::endl;
|
||||
#endif
|
||||
m_devices.erase(d);
|
||||
return;
|
||||
}
|
||||
|
||||
if (p.status_code() != 200)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== error while adding portmap: " << p.message() << std::endl;
|
||||
#endif
|
||||
m_devices.erase(d);
|
||||
return;
|
||||
}
|
||||
|
||||
error_code_parse_state s;
|
||||
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
|
||||
, m_strand.wrap(bind(&find_error_code, _1, _2, boost::ref(s))));
|
||||
|
@ -932,7 +952,7 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
|||
d.upnp_connection.reset();
|
||||
}
|
||||
|
||||
if (e)
|
||||
if (e && e != asio::error::eof)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
|
@ -944,11 +964,21 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
|||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== incomplete http message" << std::endl;
|
||||
<< " <== error while deleting portmap: incomplete http message" << std::endl;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (p.status_code() != 200)
|
||||
{
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== error while deleting portmap: " << p.message() << std::endl;
|
||||
#endif
|
||||
m_devices.erase(d);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef TORRENT_UPNP_LOGGING
|
||||
m_log << time_now_string()
|
||||
<< " <== unmap response: " << std::string(p.get_body().begin, p.get_body().end)
|
||||
|
|
|
@ -197,39 +197,41 @@ namespace libtorrent { namespace
|
|||
}
|
||||
|
||||
virtual bool on_extended(int length, int msg, buffer::const_interval body)
|
||||
try
|
||||
{
|
||||
if (msg != extension_index) return false;
|
||||
if (m_message_index == 0) return false;
|
||||
|
||||
if (length > 500 * 1024)
|
||||
throw protocol_error("ut peer exchange message larger than 500 kB");
|
||||
throw protocol_error("uT peer exchange message larger than 500 kB");
|
||||
|
||||
if (body.left() < length) return true;
|
||||
|
||||
entry pex_msg = bdecode(body.begin, body.end);
|
||||
std::string const& peers = pex_msg["added"].string();
|
||||
std::string const& peer_flags = pex_msg["added.f"].string();
|
||||
|
||||
int num_peers = peers.length() / 6;
|
||||
char const* in = peers.c_str();
|
||||
char const* fin = peer_flags.c_str();
|
||||
|
||||
if (int(peer_flags.size()) != num_peers)
|
||||
return true;
|
||||
|
||||
peer_id pid(0);
|
||||
policy& p = m_torrent.get_policy();
|
||||
for (int i = 0; i < num_peers; ++i)
|
||||
try
|
||||
{
|
||||
tcp::endpoint adr = detail::read_v4_endpoint<tcp::endpoint>(in);
|
||||
char flags = detail::read_uint8(fin);
|
||||
p.peer_from_tracker(adr, pid, peer_info::pex, flags);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
entry pex_msg = bdecode(body.begin, body.end);
|
||||
std::string const& peers = pex_msg["added"].string();
|
||||
std::string const& peer_flags = pex_msg["added.f"].string();
|
||||
|
||||
int num_peers = peers.length() / 6;
|
||||
char const* in = peers.c_str();
|
||||
char const* fin = peer_flags.c_str();
|
||||
|
||||
if (int(peer_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_v4_endpoint<tcp::endpoint>(in);
|
||||
char flags = detail::read_uint8(fin);
|
||||
p.peer_from_tracker(adr, pid, peer_info::pex, flags);
|
||||
}
|
||||
}
|
||||
catch (std::exception&)
|
||||
{
|
||||
throw protocol_error("invalid uT peer exchange message");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -315,7 +315,14 @@ namespace libtorrent
|
|||
{
|
||||
INVARIANT_CHECK;
|
||||
|
||||
if (error) return;
|
||||
if (error)
|
||||
{
|
||||
#ifdef TORRENT_VERBOSE_LOGGING
|
||||
(*m_logger) << "*** web_peer_connection error: "
|
||||
<< error.message() << "\n";
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||
assert(t);
|
||||
|
|
Loading…
Reference in New Issue