mirror of
https://github.com/codex-storage/deluge.git
synced 2025-01-11 20:14:13 +00:00
Sync libtorrent to trunk.
Start of columns menu.
This commit is contained in:
parent
ac29983651
commit
b7e3c6b3df
@ -35,6 +35,11 @@
|
|||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<widget class="GtkSeparatorMenuItem" id="separator2">
|
||||||
|
<property name="visible">True</property>
|
||||||
|
</widget>
|
||||||
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkImageMenuItem" id="menuitem_updatetracker">
|
<widget class="GtkImageMenuItem" id="menuitem_updatetracker">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
@ -69,7 +74,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
<child>
|
||||||
<widget class="GtkSeparatorMenuItem" id="separator">
|
<widget class="GtkSeparatorMenuItem" id="separator1">
|
||||||
<property name="visible">True</property>
|
<property name="visible">True</property>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</child>
|
||||||
@ -90,97 +95,5 @@
|
|||||||
</child>
|
</child>
|
||||||
</widget>
|
</widget>
|
||||||
</child>
|
</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>
|
</widget>
|
||||||
</glade-interface>
|
</glade-interface>
|
||||||
|
@ -82,6 +82,7 @@ class ListView:
|
|||||||
def __init__(self, name, column_indices):
|
def __init__(self, name, column_indices):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.column_indices = column_indices
|
self.column_indices = column_indices
|
||||||
|
self.column = None
|
||||||
|
|
||||||
def __init__(self, treeview_widget=None):
|
def __init__(self, treeview_widget=None):
|
||||||
log.debug("ListView initialized..")
|
log.debug("ListView initialized..")
|
||||||
@ -113,6 +114,13 @@ class ListView:
|
|||||||
else:
|
else:
|
||||||
return self.columns[name].column_indices[0]
|
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):
|
def create_new_liststore(self):
|
||||||
# Create a new liststore with added column and move the data from the
|
# Create a new liststore with added column and move the data from the
|
||||||
# old one to the new one.
|
# old one to the new one.
|
||||||
@ -158,6 +166,7 @@ class ListView:
|
|||||||
column.set_reorderable(True)
|
column.set_reorderable(True)
|
||||||
column.set_visible(visible)
|
column.set_visible(visible)
|
||||||
self.treeview.append_column(column)
|
self.treeview.append_column(column)
|
||||||
|
self.columns[header].column = column
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -194,7 +203,8 @@ class ListView:
|
|||||||
column.set_min_width(10)
|
column.set_min_width(10)
|
||||||
column.set_reorderable(True)
|
column.set_reorderable(True)
|
||||||
self.treeview.append_column(column)
|
self.treeview.append_column(column)
|
||||||
|
self.columns[header].column = column
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_progress_column(self, header):
|
def add_progress_column(self, header):
|
||||||
@ -221,7 +231,8 @@ class ListView:
|
|||||||
column.set_min_width(10)
|
column.set_min_width(10)
|
||||||
column.set_reorderable(True)
|
column.set_reorderable(True)
|
||||||
self.treeview.append_column(column)
|
self.treeview.append_column(column)
|
||||||
|
self.columns[header].column = column
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def add_texticon_column(self, header):
|
def add_texticon_column(self, header):
|
||||||
@ -251,5 +262,6 @@ class ListView:
|
|||||||
column.add_attribute(render, 'text',
|
column.add_attribute(render, 'text',
|
||||||
self.columns[header].column_indices[1])
|
self.columns[header].column_indices[1])
|
||||||
self.treeview.append_column(column)
|
self.treeview.append_column(column)
|
||||||
|
self.columns[header].column = column
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -80,6 +80,9 @@ class TorrentView(listview.ListView):
|
|||||||
listview.cell_data_ratio,
|
listview.cell_data_ratio,
|
||||||
[float])
|
[float])
|
||||||
|
|
||||||
|
self.window.main_glade.get_widget("menu_columns").set_submenu(
|
||||||
|
self.create_checklist_menu())
|
||||||
|
|
||||||
### Connect Signals ###
|
### Connect Signals ###
|
||||||
# Connect to the 'button-press-event' to know when to bring up the
|
# Connect to the 'button-press-event' to know when to bring up the
|
||||||
# torrent menu popup.
|
# torrent menu popup.
|
||||||
@ -100,7 +103,7 @@ class TorrentView(listview.ListView):
|
|||||||
"eta"]
|
"eta"]
|
||||||
status = functions.get_torrent_status(self.core, torrent_id,
|
status = functions.get_torrent_status(self.core, torrent_id,
|
||||||
status_keys)
|
status_keys)
|
||||||
|
|
||||||
# Set values for each column in the row
|
# Set values for each column in the row
|
||||||
|
|
||||||
self.liststore.set_value(row,
|
self.liststore.set_value(row,
|
||||||
|
@ -184,6 +184,63 @@ namespace libtorrent
|
|||||||
{ return std::auto_ptr<alert>(new torrent_finished_alert(*this)); }
|
{ 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
|
struct TORRENT_EXPORT storage_moved_alert: torrent_alert
|
||||||
{
|
{
|
||||||
storage_moved_alert(torrent_handle const& h, std::string const& path)
|
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;
|
static const int inf = boost::integer_traits<int>::const_max;
|
||||||
|
|
||||||
bandwidth_limit()
|
bandwidth_limit() throw()
|
||||||
: m_quota_left(0)
|
: m_quota_left(0)
|
||||||
, m_local_limit(inf)
|
, m_local_limit(inf)
|
||||||
, m_current_rate(0)
|
, m_current_rate(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void throttle(int limit)
|
void throttle(int limit) throw()
|
||||||
{
|
{
|
||||||
m_local_limit = limit;
|
m_local_limit = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
int throttle() const
|
int throttle() const throw()
|
||||||
{
|
{
|
||||||
return m_local_limit;
|
return m_local_limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void assign(int amount)
|
void assign(int amount) throw()
|
||||||
{
|
{
|
||||||
assert(amount > 0);
|
assert(amount > 0);
|
||||||
m_current_rate += amount;
|
m_current_rate += amount;
|
||||||
m_quota_left += amount;
|
m_quota_left += amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void use_quota(int amount)
|
void use_quota(int amount) throw()
|
||||||
{
|
{
|
||||||
assert(amount <= m_quota_left);
|
assert(amount <= m_quota_left);
|
||||||
m_quota_left -= amount;
|
m_quota_left -= amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int quota_left() const
|
int quota_left() const throw()
|
||||||
{
|
{
|
||||||
return (std::max)(m_quota_left, 0);
|
return (std::max)(m_quota_left, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void expire(int amount)
|
void expire(int amount) throw()
|
||||||
{
|
{
|
||||||
assert(amount >= 0);
|
assert(amount >= 0);
|
||||||
m_current_rate -= amount;
|
m_current_rate -= amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int max_assignable() const
|
int max_assignable() const throw()
|
||||||
{
|
{
|
||||||
if (m_local_limit == inf) return inf;
|
if (m_local_limit == inf) return inf;
|
||||||
if (m_local_limit <= m_current_rate) return 0;
|
if (m_local_limit <= m_current_rate) return 0;
|
||||||
@ -160,7 +160,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T clamp(T val, T ceiling, T floor)
|
T clamp(T val, T ceiling, T floor) throw()
|
||||||
{
|
{
|
||||||
assert(ceiling >= floor);
|
assert(ceiling >= floor);
|
||||||
if (val >= ceiling) return ceiling;
|
if (val >= ceiling) return ceiling;
|
||||||
@ -171,7 +171,7 @@ T clamp(T val, T ceiling, T floor)
|
|||||||
template<class PeerConnection, class Torrent>
|
template<class PeerConnection, class Torrent>
|
||||||
struct bandwidth_manager
|
struct bandwidth_manager
|
||||||
{
|
{
|
||||||
bandwidth_manager(io_service& ios, int channel)
|
bandwidth_manager(io_service& ios, int channel) throw()
|
||||||
: m_ios(ios)
|
: m_ios(ios)
|
||||||
, m_history_timer(m_ios)
|
, m_history_timer(m_ios)
|
||||||
, m_limit(bandwidth_limit::inf)
|
, m_limit(bandwidth_limit::inf)
|
||||||
@ -179,14 +179,14 @@ struct bandwidth_manager
|
|||||||
, m_channel(channel)
|
, m_channel(channel)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void throttle(int limit)
|
void throttle(int limit) throw()
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
assert(limit >= 0);
|
assert(limit >= 0);
|
||||||
m_limit = limit;
|
m_limit = limit;
|
||||||
}
|
}
|
||||||
|
|
||||||
int throttle() const
|
int throttle() const throw()
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
mutex_t::scoped_lock l(m_mutex);
|
||||||
return m_limit;
|
return m_limit;
|
||||||
@ -197,7 +197,7 @@ struct bandwidth_manager
|
|||||||
// this is used by web seeds
|
// this is used by web seeds
|
||||||
void request_bandwidth(intrusive_ptr<PeerConnection> peer
|
void request_bandwidth(intrusive_ptr<PeerConnection> peer
|
||||||
, int blk
|
, int blk
|
||||||
, bool non_prioritized)
|
, bool non_prioritized) throw()
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
assert(blk > 0);
|
assert(blk > 0);
|
||||||
@ -257,8 +257,11 @@ struct bandwidth_manager
|
|||||||
|
|
||||||
private:
|
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;
|
INVARIANT_CHECK;
|
||||||
m_history.push_front(e);
|
m_history.push_front(e);
|
||||||
m_current_quota += e.amount;
|
m_current_quota += e.amount;
|
||||||
@ -268,11 +271,17 @@ private:
|
|||||||
|
|
||||||
m_history_timer.expires_at(e.expires_at);
|
m_history_timer.expires_at(e.expires_at);
|
||||||
m_history_timer.async_wait(bind(&bandwidth_manager::on_history_expire, this, _1));
|
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;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
if (e) return;
|
if (e) return;
|
||||||
@ -303,14 +312,20 @@ private:
|
|||||||
// means we can hand out more (in case there
|
// means we can hand out more (in case there
|
||||||
// are still consumers in line)
|
// are still consumers in line)
|
||||||
if (!m_queue.empty()) hand_out_bandwidth();
|
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;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
ptime now(time_now());
|
ptime now(time_now());
|
||||||
@ -404,9 +419,12 @@ private:
|
|||||||
add_history_entry(history_entry<PeerConnection, Torrent>(
|
add_history_entry(history_entry<PeerConnection, Torrent>(
|
||||||
qe.peer, t, hand_out_amount, now + bw_window_size));
|
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;
|
typedef boost::mutex mutex_t;
|
||||||
|
@ -37,6 +37,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#if defined(__GNUC__) && __GNUC__ >= 4
|
#if defined(__GNUC__) && __GNUC__ >= 4
|
||||||
|
|
||||||
|
#define TORRENT_DEPRECATED __attribute__ ((deprecated))
|
||||||
|
|
||||||
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
|
# if defined(TORRENT_BUILDING_SHARED) || defined(TORRENT_LINKING_SHARED)
|
||||||
# define TORRENT_EXPORT __attribute__ ((visibility("default")))
|
# define TORRENT_EXPORT __attribute__ ((visibility("default")))
|
||||||
# else
|
# else
|
||||||
@ -61,6 +63,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
# define TORRENT_EXPORT
|
# define TORRENT_EXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TORRENT_DEPRECATED
|
||||||
|
#define TORRENT_DEPRECATED
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // TORRENT_CONFIG_HPP_INCLUDED
|
#endif // TORRENT_CONFIG_HPP_INCLUDED
|
||||||
|
|
||||||
|
@ -111,6 +111,10 @@ namespace libtorrent
|
|||||||
// memory pool for read and write operations
|
// memory pool for read and write operations
|
||||||
boost::pool<> m_pool;
|
boost::pool<> m_pool;
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
int m_block_size;
|
||||||
|
#endif
|
||||||
|
|
||||||
// thread for performing blocking disk io operations
|
// thread for performing blocking disk io operations
|
||||||
boost::thread m_disk_io_thread;
|
boost::thread m_disk_io_thread;
|
||||||
};
|
};
|
||||||
|
@ -59,7 +59,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <iostream>
|
#include <iosfwd>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
@ -74,10 +74,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/socket_type.hpp"
|
#include "libtorrent/socket_type.hpp"
|
||||||
#include "libtorrent/intrusive_ptr_base.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
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
class torrent;
|
class torrent;
|
||||||
@ -395,9 +391,7 @@ namespace libtorrent
|
|||||||
#ifndef TORRENT_DISABLE_ENCRYPTION
|
#ifndef TORRENT_DISABLE_ENCRYPTION
|
||||||
buffer::interval wr_recv_buffer()
|
buffer::interval wr_recv_buffer()
|
||||||
{
|
{
|
||||||
#if defined _SECURE_SCL && _SECURE_SCL > 0
|
|
||||||
if (m_recv_buffer.empty()) return buffer::interval(0,0);
|
if (m_recv_buffer.empty()) return buffer::interval(0,0);
|
||||||
#endif
|
|
||||||
return buffer::interval(&m_recv_buffer[0]
|
return buffer::interval(&m_recv_buffer[0]
|
||||||
, &m_recv_buffer[0] + m_recv_pos);
|
, &m_recv_buffer[0] + m_recv_pos);
|
||||||
}
|
}
|
||||||
@ -405,9 +399,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
buffer::const_interval receive_buffer() const
|
buffer::const_interval receive_buffer() const
|
||||||
{
|
{
|
||||||
#if defined _SECURE_SCL && _SECURE_SCL > 0
|
|
||||||
if (m_recv_buffer.empty()) return buffer::const_interval(0,0);
|
if (m_recv_buffer.empty()) return buffer::const_interval(0,0);
|
||||||
#endif
|
|
||||||
return buffer::const_interval(&m_recv_buffer[0]
|
return buffer::const_interval(&m_recv_buffer[0]
|
||||||
, &m_recv_buffer[0] + m_recv_pos);
|
, &m_recv_buffer[0] + m_recv_pos);
|
||||||
}
|
}
|
||||||
@ -646,7 +638,8 @@ namespace libtorrent
|
|||||||
bool m_queued;
|
bool m_queued;
|
||||||
|
|
||||||
// these are true when there's a asynchronous write
|
// 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_writing;
|
||||||
bool m_reading;
|
bool m_reading;
|
||||||
|
|
||||||
@ -701,6 +694,10 @@ namespace libtorrent
|
|||||||
// a timestamp when the remote download rate
|
// a timestamp when the remote download rate
|
||||||
// was last updated
|
// was last updated
|
||||||
ptime m_remote_dl_update;
|
ptime m_remote_dl_update;
|
||||||
|
|
||||||
|
// the number of bytes send to the disk-io
|
||||||
|
// thread that hasn't yet been completely written.
|
||||||
|
int m_outstanding_writing_bytes;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
public:
|
public:
|
||||||
|
@ -144,6 +144,10 @@ namespace libtorrent
|
|||||||
|
|
||||||
// approximate peer download rate
|
// approximate peer download rate
|
||||||
int remote_dl_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);
|
void we_have(int index);
|
||||||
|
|
||||||
// sets the priority of a piece.
|
// 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'
|
// returns the priority for the piece at 'index'
|
||||||
int piece_priority(int index) const;
|
int piece_priority(int index) const;
|
||||||
@ -215,6 +217,9 @@ namespace libtorrent
|
|||||||
void mark_as_finished(piece_block block, void* peer);
|
void mark_as_finished(piece_block block, void* peer);
|
||||||
int num_peers(piece_block block) const;
|
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
|
// if a piece had a hash-failure, it must be restored and
|
||||||
// made available for redownloading
|
// made available for redownloading
|
||||||
void restore_piece(int index);
|
void restore_piece(int index);
|
||||||
|
@ -110,6 +110,8 @@ namespace libtorrent
|
|||||||
// the peer is not interested in our pieces
|
// the peer is not interested in our pieces
|
||||||
void not_interested(peer_connection& c);
|
void not_interested(peer_connection& c);
|
||||||
|
|
||||||
|
void ip_filter_updated();
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool has_connection(const peer_connection* p);
|
bool has_connection(const peer_connection* p);
|
||||||
|
|
||||||
|
@ -144,14 +144,15 @@ namespace libtorrent
|
|||||||
, int block_size = 16 * 1024
|
, int block_size = 16 * 1024
|
||||||
, storage_constructor_type sc = default_storage_constructor);
|
, 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(
|
torrent_handle add_torrent(
|
||||||
entry const& e
|
entry const& e
|
||||||
, fs::path const& save_path
|
, fs::path const& save_path
|
||||||
, entry const& resume_data = entry()
|
, entry const& resume_data = entry()
|
||||||
, bool compact_mode = true
|
, bool compact_mode = true
|
||||||
, int block_size = 16 * 1024
|
, 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
|
return add_torrent(torrent_info(e), save_path, resume_data
|
||||||
, compact_mode, block_size, sc);
|
, compact_mode, block_size, sc);
|
||||||
|
@ -108,6 +108,7 @@ namespace libtorrent
|
|||||||
, unchoke_interval(20)
|
, unchoke_interval(20)
|
||||||
, num_want(200)
|
, num_want(200)
|
||||||
, initial_picker_threshold(4)
|
, initial_picker_threshold(4)
|
||||||
|
, max_outstanding_disk_bytes_per_connection(64 * 1024)
|
||||||
#ifndef TORRENT_DISABLE_DHT
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
, use_dht_as_fallback(true)
|
, use_dht_as_fallback(true)
|
||||||
#endif
|
#endif
|
||||||
@ -251,6 +252,14 @@ namespace libtorrent
|
|||||||
// random pieces instead of rarest first.
|
// random pieces instead of rarest first.
|
||||||
int initial_picker_threshold;
|
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
|
#ifndef TORRENT_DISABLE_DHT
|
||||||
// while this is true, the dht will note be used unless the
|
// while this is true, the dht will note be used unless the
|
||||||
// tracker is online
|
// tracker is online
|
||||||
|
@ -175,6 +175,8 @@ namespace libtorrent
|
|||||||
boost::tuples::tuple<size_type, size_type> bytes_done() const;
|
boost::tuples::tuple<size_type, size_type> bytes_done() const;
|
||||||
size_type quantized_bytes_done() const;
|
size_type quantized_bytes_done() const;
|
||||||
|
|
||||||
|
void ip_filter_updated() { m_policy->ip_filter_updated(); }
|
||||||
|
|
||||||
void pause();
|
void pause();
|
||||||
void resume();
|
void resume();
|
||||||
bool is_paused() const { return m_paused; }
|
bool is_paused() const { return m_paused; }
|
||||||
|
@ -241,6 +241,12 @@ namespace libtorrent
|
|||||||
enum { max_blocks_per_piece = 256 };
|
enum { max_blocks_per_piece = 256 };
|
||||||
int piece_index;
|
int piece_index;
|
||||||
int blocks_in_piece;
|
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];
|
block_info blocks[max_blocks_per_piece];
|
||||||
enum state_t { none, slow, medium, fast };
|
enum state_t { none, slow, medium, fast };
|
||||||
state_t piece_state;
|
state_t piece_state;
|
||||||
@ -290,13 +296,13 @@ namespace libtorrent
|
|||||||
|
|
||||||
// marks the piece with the given index as filtered
|
// marks the piece with the given index as filtered
|
||||||
// it will not be downloaded
|
// it will not be downloaded
|
||||||
void filter_piece(int index, bool filter) const;
|
void filter_piece(int index, bool filter) const TORRENT_DEPRECATED;
|
||||||
void filter_pieces(std::vector<bool> const& pieces) const;
|
void filter_pieces(std::vector<bool> const& pieces) const TORRENT_DEPRECATED;
|
||||||
bool is_piece_filtered(int index) const;
|
bool is_piece_filtered(int index) const TORRENT_DEPRECATED;
|
||||||
std::vector<bool> filtered_pieces() const;
|
std::vector<bool> filtered_pieces() const TORRENT_DEPRECATED;
|
||||||
// marks the file with the given index as filtered
|
// marks the file with the given index as filtered
|
||||||
// it will not be downloaded
|
// it will not be downloaded
|
||||||
void filter_files(std::vector<bool> const& files) const;
|
void filter_files(std::vector<bool> const& files) const TORRENT_DEPRECATED;
|
||||||
|
|
||||||
// ================ end deprecation ============
|
// ================ end deprecation ============
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(push, 1)
|
#pragma warning(push, 1)
|
||||||
@ -146,7 +147,8 @@ namespace libtorrent
|
|||||||
const std::string& name() const { assert(m_piece_length > 0); return m_name; }
|
const std::string& name() const { assert(m_piece_length > 0); return m_name; }
|
||||||
|
|
||||||
// ------- start deprecation -------
|
// ------- 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 -------
|
// ------- end deprecation -------
|
||||||
|
|
||||||
bool is_valid() const { return m_piece_length > 0; }
|
bool is_valid() const { return m_piece_length > 0; }
|
||||||
|
@ -33,11 +33,25 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#ifndef TORRENT_XML_PARSE_HPP
|
#ifndef TORRENT_XML_PARSE_HPP
|
||||||
#define TORRENT_XML_PARSE_HPP
|
#define TORRENT_XML_PARSE_HPP
|
||||||
|
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
const int xml_start_tag = 0;
|
enum
|
||||||
const int xml_end_tag = 1;
|
{
|
||||||
const int xml_string = 2;
|
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>
|
template <class CallbackType>
|
||||||
void xml_parse(char* p, char* end, CallbackType callback)
|
void xml_parse(char* p, char* end, CallbackType callback)
|
||||||
@ -45,6 +59,8 @@ namespace libtorrent
|
|||||||
for(;p != end; ++p)
|
for(;p != end; ++p)
|
||||||
{
|
{
|
||||||
char const* start = p;
|
char const* start = p;
|
||||||
|
char const* val_start = 0;
|
||||||
|
int token;
|
||||||
// look for tag start
|
// look for tag start
|
||||||
for(; *p != '<' && p != end; ++p);
|
for(; *p != '<' && p != end; ++p);
|
||||||
|
|
||||||
@ -55,39 +71,135 @@ namespace libtorrent
|
|||||||
assert(*p == '<');
|
assert(*p == '<');
|
||||||
*p = 0;
|
*p = 0;
|
||||||
}
|
}
|
||||||
callback(xml_string, start);
|
token = xml_string;
|
||||||
|
callback(token, start, val_start);
|
||||||
if (p != end) *p = '<';
|
if (p != end) *p = '<';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p == end) break;
|
if (p == end) break;
|
||||||
|
|
||||||
// skip '<'
|
// skip '<'
|
||||||
++p;
|
++p;
|
||||||
|
|
||||||
// parse the name of the tag. Ignore attributes
|
// parse the name of the tag.
|
||||||
for (start = p; p != end && *p != '>'; ++p)
|
for (start = p; p != end && *p != '>' && !std::isspace(*p); ++p);
|
||||||
{
|
|
||||||
// terminate the string at the first space
|
char* tag_name_end = p;
|
||||||
// to ignore tag attributes
|
|
||||||
if (*p == ' ') *p = 0;
|
// skip the attributes for now
|
||||||
}
|
for (; p != end && *p != '>'; ++p);
|
||||||
|
|
||||||
// parse error
|
// 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 == '>');
|
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 == '/')
|
if (*start == '/')
|
||||||
{
|
{
|
||||||
++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
|
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_LDFLAGS = $(LDFLAGS) -release @VERSION@
|
||||||
libtorrent_la_LIBADD = @ZLIB@ -l@BOOST_DATE_TIME_LIB@ -l@BOOST_FILESYSTEM_LIB@ -l@BOOST_THREAD_LIB@ @PTHREAD_LIBS@
|
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@
|
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 next_expire = max_time();
|
||||||
ptime now = time_now();
|
ptime now = time_now();
|
||||||
for (std::list<entry>::iterator i = m_queue.begin();
|
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)
|
if (i->connecting && i->expires < now)
|
||||||
{
|
{
|
||||||
|
@ -41,6 +41,9 @@ namespace libtorrent
|
|||||||
: m_abort(false)
|
: m_abort(false)
|
||||||
, m_queue_buffer_size(0)
|
, m_queue_buffer_size(0)
|
||||||
, m_pool(block_size)
|
, m_pool(block_size)
|
||||||
|
#ifndef NDEBUG
|
||||||
|
, m_block_size(block_size)
|
||||||
|
#endif
|
||||||
, m_disk_io_thread(boost::ref(*this))
|
, m_disk_io_thread(boost::ref(*this))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -192,6 +195,7 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
assert(j.buffer_size <= m_block_size);
|
||||||
ret = j.storage->read_impl(j.buffer, j.piece, j.offset
|
ret = j.storage->read_impl(j.buffer, j.piece, j.offset
|
||||||
, j.buffer_size);
|
, j.buffer_size);
|
||||||
|
|
||||||
@ -201,6 +205,7 @@ namespace libtorrent
|
|||||||
break;
|
break;
|
||||||
case disk_io_job::write:
|
case disk_io_job::write:
|
||||||
assert(j.buffer);
|
assert(j.buffer);
|
||||||
|
assert(j.buffer_size <= m_block_size);
|
||||||
j.storage->write_impl(j.buffer, j.piece, j.offset
|
j.storage->write_impl(j.buffer, j.piece, j.offset
|
||||||
, j.buffer_size);
|
, j.buffer_size);
|
||||||
|
|
||||||
|
@ -248,11 +248,17 @@ namespace libtorrent
|
|||||||
void set_size(size_type s)
|
void set_size(size_type s)
|
||||||
{
|
{
|
||||||
size_type pos = tell();
|
size_type pos = tell();
|
||||||
seek(s - 1);
|
// Only set size if current file size not equals s.
|
||||||
char dummy = 0;
|
// 2 as "m" argument is to be sure seek() sets SEEK_END on
|
||||||
read(&dummy, 1);
|
// all compilers.
|
||||||
seek(s - 1);
|
if(s != seek(0, 2))
|
||||||
write(&dummy, 1);
|
{
|
||||||
|
seek(s - 1);
|
||||||
|
char dummy = 0;
|
||||||
|
read(&dummy, 1);
|
||||||
|
seek(s - 1);
|
||||||
|
write(&dummy, 1);
|
||||||
|
}
|
||||||
seek(pos);
|
seek(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,7 +35,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "libtorrent/lsd.hpp"
|
#include "libtorrent/lsd.hpp"
|
||||||
#include "libtorrent/io.hpp"
|
#include "libtorrent/io.hpp"
|
||||||
#include "libtorrent/http_tracker_connection.hpp"
|
#include "libtorrent/http_tracker_connection.hpp"
|
||||||
#include "libtorrent/xml_parse.hpp"
|
|
||||||
#include <boost/bind.hpp>
|
#include <boost/bind.hpp>
|
||||||
#include <boost/ref.hpp>
|
#include <boost/ref.hpp>
|
||||||
#include <asio/ip/host_name.hpp>
|
#include <asio/ip/host_name.hpp>
|
||||||
|
@ -116,6 +116,7 @@ namespace libtorrent
|
|||||||
, m_remote_bytes_dled(0)
|
, m_remote_bytes_dled(0)
|
||||||
, m_remote_dl_rate(0)
|
, m_remote_dl_rate(0)
|
||||||
, m_remote_dl_update(time_now())
|
, m_remote_dl_update(time_now())
|
||||||
|
, m_outstanding_writing_bytes(0)
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
, m_in_constructor(true)
|
, m_in_constructor(true)
|
||||||
#endif
|
#endif
|
||||||
@ -189,6 +190,7 @@ namespace libtorrent
|
|||||||
, m_remote_bytes_dled(0)
|
, m_remote_bytes_dled(0)
|
||||||
, m_remote_dl_rate(0)
|
, m_remote_dl_rate(0)
|
||||||
, m_remote_dl_update(time_now())
|
, m_remote_dl_update(time_now())
|
||||||
|
, m_outstanding_writing_bytes(0)
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
, m_in_constructor(true)
|
, m_in_constructor(true)
|
||||||
#endif
|
#endif
|
||||||
@ -936,7 +938,8 @@ namespace libtorrent
|
|||||||
&& r.start < t->torrent_file().piece_size(r.piece)
|
&& r.start < t->torrent_file().piece_size(r.piece)
|
||||||
&& r.length > 0
|
&& r.length > 0
|
||||||
&& r.length + r.start <= t->torrent_file().piece_size(r.piece)
|
&& 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
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << time_now_string()
|
(*m_logger) << time_now_string()
|
||||||
@ -961,7 +964,8 @@ namespace libtorrent
|
|||||||
"i: " << m_peer_interested << " | "
|
"i: " << m_peer_interested << " | "
|
||||||
"t: " << (int)t->torrent_file().piece_size(r.piece) << " | "
|
"t: " << (int)t->torrent_file().piece_size(r.piece) << " | "
|
||||||
"n: " << t->torrent_file().num_pieces() << " | "
|
"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
|
#endif
|
||||||
|
|
||||||
++m_num_invalid_requests;
|
++m_num_invalid_requests;
|
||||||
@ -1150,6 +1154,8 @@ namespace libtorrent
|
|||||||
|
|
||||||
fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete
|
fs.async_write(p, data, bind(&peer_connection::on_disk_write_complete
|
||||||
, self(), _1, _2, p, t));
|
, self(), _1, _2, p, t));
|
||||||
|
m_outstanding_writing_bytes += p.length;
|
||||||
|
assert(!m_reading);
|
||||||
picker.mark_as_writing(block_finished, peer_info_struct());
|
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);
|
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 (ret == -1 || !t)
|
||||||
{
|
{
|
||||||
if (!t)
|
if (!t)
|
||||||
@ -1183,6 +1199,11 @@ namespace libtorrent
|
|||||||
assert(p.start == j.offset);
|
assert(p.start == j.offset);
|
||||||
piece_block block_finished(p.piece, p.start / t->block_size());
|
piece_block block_finished(p.piece, p.start / t->block_size());
|
||||||
picker.mark_as_finished(block_finished, peer_info_struct());
|
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())
|
if (!has_peer_choked() && !t->is_seed() && !m_torrent.expired())
|
||||||
{
|
{
|
||||||
@ -1290,11 +1311,29 @@ namespace libtorrent
|
|||||||
|
|
||||||
piece_picker::piece_state_t state;
|
piece_picker::piece_state_t state;
|
||||||
peer_speed_t speed = peer_speed();
|
peer_speed_t speed = peer_speed();
|
||||||
if (speed == fast) state = piece_picker::fast;
|
std::string speedmsg;
|
||||||
else if (speed == medium) state = piece_picker::medium;
|
if (speed == fast)
|
||||||
else state = piece_picker::slow;
|
{
|
||||||
|
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);
|
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);
|
m_request_queue.push_back(block);
|
||||||
}
|
}
|
||||||
@ -1642,6 +1681,7 @@ namespace libtorrent
|
|||||||
p.payload_up_speed = statistics().upload_payload_rate();
|
p.payload_up_speed = statistics().upload_payload_rate();
|
||||||
p.pid = pid();
|
p.pid = pid();
|
||||||
p.ip = remote();
|
p.ip = remote();
|
||||||
|
p.pending_disk_bytes = m_outstanding_writing_bytes;
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
||||||
p.country[0] = m_country[0];
|
p.country[0] = m_country[0];
|
||||||
@ -2015,11 +2055,13 @@ namespace libtorrent
|
|||||||
m_bandwidth_limit[channel].assign(amount);
|
m_bandwidth_limit[channel].assign(amount);
|
||||||
if (channel == upload_channel)
|
if (channel == upload_channel)
|
||||||
{
|
{
|
||||||
|
assert(m_writing);
|
||||||
m_writing = false;
|
m_writing = false;
|
||||||
setup_send();
|
setup_send();
|
||||||
}
|
}
|
||||||
else if (channel == download_channel)
|
else if (channel == download_channel)
|
||||||
{
|
{
|
||||||
|
assert(m_reading);
|
||||||
m_reading = false;
|
m_reading = false;
|
||||||
setup_receive();
|
setup_receive();
|
||||||
}
|
}
|
||||||
@ -2067,10 +2109,11 @@ namespace libtorrent
|
|||||||
(*m_logger) << "req bandwidth [ " << upload_channel << " ]\n";
|
(*m_logger) << "req bandwidth [ " << upload_channel << " ]\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
assert(!m_writing);
|
||||||
// peers that we are not interested in are non-prioritized
|
// peers that we are not interested in are non-prioritized
|
||||||
|
m_writing = true;
|
||||||
t->request_bandwidth(upload_channel, self()
|
t->request_bandwidth(upload_channel, self()
|
||||||
, !(is_interesting() && !has_peer_choked()));
|
, !(is_interesting() && !has_peer_choked()));
|
||||||
m_writing = true;
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2116,6 +2159,9 @@ namespace libtorrent
|
|||||||
|
|
||||||
INVARIANT_CHECK;
|
INVARIANT_CHECK;
|
||||||
|
|
||||||
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
|
(*m_logger) << "setup_receive: reading = " << m_reading << "\n";
|
||||||
|
#endif
|
||||||
if (m_reading) return;
|
if (m_reading) return;
|
||||||
|
|
||||||
shared_ptr<torrent> t = m_torrent.lock();
|
shared_ptr<torrent> t = m_torrent.lock();
|
||||||
@ -2130,8 +2176,8 @@ namespace libtorrent
|
|||||||
#ifdef TORRENT_VERBOSE_LOGGING
|
#ifdef TORRENT_VERBOSE_LOGGING
|
||||||
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
(*m_logger) << "req bandwidth [ " << download_channel << " ]\n";
|
||||||
#endif
|
#endif
|
||||||
t->request_bandwidth(download_channel, self(), m_non_prioritized);
|
|
||||||
m_reading = true;
|
m_reading = true;
|
||||||
|
t->request_bandwidth(download_channel, self(), m_non_prioritized);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2144,7 +2190,7 @@ namespace libtorrent
|
|||||||
if (!m_ignore_bandwidth_limits && max_receive > quota_left)
|
if (!m_ignore_bandwidth_limits && max_receive > quota_left)
|
||||||
max_receive = quota_left;
|
max_receive = quota_left;
|
||||||
|
|
||||||
assert(max_receive > 0);
|
if (max_receive == 0) return;
|
||||||
|
|
||||||
assert(m_recv_pos >= 0);
|
assert(m_recv_pos >= 0);
|
||||||
assert(m_packet_size > 0);
|
assert(m_packet_size > 0);
|
||||||
@ -2242,10 +2288,7 @@ namespace libtorrent
|
|||||||
m_recv_pos += bytes_transferred;
|
m_recv_pos += bytes_transferred;
|
||||||
assert(m_recv_pos <= int(m_recv_buffer.size()));
|
assert(m_recv_pos <= int(m_recv_buffer.size()));
|
||||||
|
|
||||||
{
|
on_receive(error, bytes_transferred);
|
||||||
INVARIANT_CHECK;
|
|
||||||
on_receive(error, bytes_transferred);
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(m_packet_size > 0);
|
assert(m_packet_size > 0);
|
||||||
|
|
||||||
@ -2322,9 +2365,17 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
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_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)
|
void peer_connection::connect(int ticket)
|
||||||
@ -2649,6 +2700,7 @@ namespace libtorrent
|
|||||||
(*m_logger) << time_now_string() << " ==> KEEPALIVE\n";
|
(*m_logger) << time_now_string() << " ==> KEEPALIVE\n";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
m_last_sent = time_now();
|
||||||
write_keepalive();
|
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(
|
void piece_picker::set_sequenced_download_threshold(
|
||||||
int sequenced_download_threshold)
|
int sequenced_download_threshold)
|
||||||
{
|
{
|
||||||
@ -196,7 +225,8 @@ namespace libtorrent
|
|||||||
int block_index = num_downloads * m_blocks_per_piece;
|
int block_index = num_downloads * m_blocks_per_piece;
|
||||||
if (int(m_block_info.size()) < block_index + 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);
|
m_block_info.resize(block_index + m_blocks_per_piece);
|
||||||
if (!m_downloads.empty() && &m_block_info[0] != base)
|
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)
|
void piece_picker::sort_piece(std::vector<downloading_piece>::iterator dp)
|
||||||
{
|
{
|
||||||
assert(m_piece_map[dp->index].downloading);
|
assert(m_piece_map[dp->index].downloading);
|
||||||
|
if (dp == m_downloads.begin()) return;
|
||||||
int complete = dp->writing + dp->finished;
|
int complete = dp->writing + dp->finished;
|
||||||
for (std::vector<downloading_piece>::iterator i = dp, j(dp-1);
|
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());
|
assert(j >= m_downloads.begin());
|
||||||
if (j->finished + j->writing >= complete) return;
|
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;
|
TORRENT_PIECE_PICKER_INVARIANT_CHECK;
|
||||||
assert(new_piece_priority >= 0);
|
assert(new_piece_priority >= 0);
|
||||||
@ -946,16 +977,18 @@ namespace libtorrent
|
|||||||
piece_pos& p = m_piece_map[index];
|
piece_pos& p = m_piece_map[index];
|
||||||
|
|
||||||
// if the priority isn't changed, don't do anything
|
// 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);
|
int prev_priority = p.priority(m_sequenced_download_threshold);
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
if (new_piece_priority == piece_pos::filter_priority
|
if (new_piece_priority == piece_pos::filter_priority
|
||||||
&& p.piece_priority != piece_pos::filter_priority)
|
&& p.piece_priority != piece_pos::filter_priority)
|
||||||
{
|
{
|
||||||
// the piece just got filtered
|
// the piece just got filtered
|
||||||
if (p.have()) ++m_num_have_filtered;
|
if (p.have()) ++m_num_have_filtered;
|
||||||
else ++m_num_filtered;
|
else ++m_num_filtered;
|
||||||
|
ret = true;
|
||||||
}
|
}
|
||||||
else if (new_piece_priority != piece_pos::filter_priority
|
else if (new_piece_priority != piece_pos::filter_priority
|
||||||
&& p.piece_priority == piece_pos::filter_priority)
|
&& p.piece_priority == piece_pos::filter_priority)
|
||||||
@ -963,6 +996,7 @@ namespace libtorrent
|
|||||||
// the piece just got unfiltered
|
// the piece just got unfiltered
|
||||||
if (p.have()) --m_num_have_filtered;
|
if (p.have()) --m_num_have_filtered;
|
||||||
else --m_num_filtered;
|
else --m_num_filtered;
|
||||||
|
ret = true;
|
||||||
}
|
}
|
||||||
assert(m_num_filtered >= 0);
|
assert(m_num_filtered >= 0);
|
||||||
assert(m_num_have_filtered >= 0);
|
assert(m_num_have_filtered >= 0);
|
||||||
@ -970,7 +1004,7 @@ namespace libtorrent
|
|||||||
p.piece_priority = new_piece_priority;
|
p.piece_priority = new_piece_priority;
|
||||||
int new_priority = p.priority(m_sequenced_download_threshold);
|
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)
|
if (prev_priority == 0)
|
||||||
{
|
{
|
||||||
@ -980,6 +1014,7 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
move(prev_priority, p.index);
|
move(prev_priority, p.index);
|
||||||
}
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int piece_picker::piece_priority(int index) const
|
int piece_picker::piece_priority(int index) const
|
||||||
@ -1051,8 +1086,12 @@ namespace libtorrent
|
|||||||
// downloaded to
|
// downloaded to
|
||||||
std::vector<piece_block> backup_blocks;
|
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;
|
bool ignore_downloading_pieces = false;
|
||||||
if (!prefer_whole_pieces)
|
if (prefer_whole_pieces)
|
||||||
{
|
{
|
||||||
std::vector<int> downloading_pieces;
|
std::vector<int> downloading_pieces;
|
||||||
downloading_pieces.reserve(m_downloads.size());
|
downloading_pieces.reserve(m_downloads.size());
|
||||||
@ -1061,8 +1100,8 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
downloading_pieces.push_back(i->index);
|
downloading_pieces.push_back(i->index);
|
||||||
}
|
}
|
||||||
num_blocks = add_interesting_blocks(downloading_pieces, pieces
|
add_interesting_blocks(downloading_pieces, pieces
|
||||||
, interesting_blocks, backup_blocks, num_blocks
|
, backup_blocks, backup_blocks, num_blocks
|
||||||
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
, prefer_whole_pieces, peer, speed, ignore_downloading_pieces);
|
||||||
ignore_downloading_pieces = true;
|
ignore_downloading_pieces = true;
|
||||||
}
|
}
|
||||||
@ -1072,10 +1111,6 @@ namespace libtorrent
|
|||||||
// has filled the interesting_blocks with num_blocks
|
// has filled the interesting_blocks with num_blocks
|
||||||
// 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
|
// +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 that 0 other peers have. bucket will point to a bucket with
|
||||||
// pieces with the same priority. It will be iterated in priority
|
// pieces with the same priority. It will be iterated in priority
|
||||||
@ -1128,8 +1163,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (!backup_blocks.empty())
|
if (!backup_blocks.empty())
|
||||||
interesting_blocks.insert(interesting_blocks.end()
|
interesting_blocks.insert(interesting_blocks.end()
|
||||||
, backup_blocks.begin(), backup_blocks.begin()
|
, backup_blocks.begin(), backup_blocks.end());
|
||||||
+ (std::min)(num_blocks, (int)backup_blocks.size()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void piece_picker::clear_peer(void* peer)
|
void piece_picker::clear_peer(void* peer)
|
||||||
@ -1216,7 +1250,6 @@ namespace libtorrent
|
|||||||
// will be picked.
|
// will be picked.
|
||||||
if (prefer_whole_pieces && !exclusive)
|
if (prefer_whole_pieces && !exclusive)
|
||||||
{
|
{
|
||||||
if (int(backup_blocks.size()) >= num_blocks) continue;
|
|
||||||
for (int j = 0; j < num_blocks_in_piece; ++j)
|
for (int j = 0; j < num_blocks_in_piece; ++j)
|
||||||
{
|
{
|
||||||
block_info const& info = p->info[j];
|
block_info const& info = p->info[j];
|
||||||
@ -1251,7 +1284,6 @@ namespace libtorrent
|
|||||||
&& !exclusive_active
|
&& !exclusive_active
|
||||||
&& !ignore_speed_categories)
|
&& !ignore_speed_categories)
|
||||||
{
|
{
|
||||||
if (int(backup_blocks.size()) >= num_blocks) continue;
|
|
||||||
backup_blocks.push_back(piece_block(*i, j));
|
backup_blocks.push_back(piece_block(*i, j));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1264,9 +1296,9 @@ namespace libtorrent
|
|||||||
// to look for blocks until we have num_blocks
|
// to look for blocks until we have num_blocks
|
||||||
// blocks that have not been requested from any
|
// blocks that have not been requested from any
|
||||||
// other peer.
|
// other peer.
|
||||||
interesting_blocks.push_back(piece_block(*i, j));
|
|
||||||
if (p->info[j].state == block_info::state_none)
|
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
|
// we have found a block that's free to download
|
||||||
num_blocks--;
|
num_blocks--;
|
||||||
// if we prefer whole pieces, continue picking from this
|
// if we prefer whole pieces, continue picking from this
|
||||||
@ -1275,6 +1307,10 @@ namespace libtorrent
|
|||||||
assert(num_blocks >= 0);
|
assert(num_blocks >= 0);
|
||||||
if (num_blocks == 0) return num_blocks;
|
if (num_blocks == 0) return num_blocks;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backup_blocks.push_back(piece_block(*i, j));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
assert(num_blocks >= 0 || prefer_whole_pieces);
|
assert(num_blocks >= 0 || prefer_whole_pieces);
|
||||||
if (num_blocks < 0) num_blocks = 0;
|
if (num_blocks < 0) num_blocks = 0;
|
||||||
|
@ -249,7 +249,7 @@ namespace libtorrent
|
|||||||
// with the other's, to see if we should abort another
|
// with the other's, to see if we should abort another
|
||||||
// peer_connection in favour of this one
|
// peer_connection in favour of this one
|
||||||
std::vector<piece_block> busy_pieces;
|
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();
|
for (std::vector<piece_block>::iterator i = interesting_pieces.begin();
|
||||||
i != interesting_pieces.end(); ++i)
|
i != interesting_pieces.end(); ++i)
|
||||||
@ -272,6 +272,8 @@ namespace libtorrent
|
|||||||
// by somebody else. request it from this peer
|
// by somebody else. request it from this peer
|
||||||
// and return
|
// and return
|
||||||
c.add_request(*i);
|
c.add_request(*i);
|
||||||
|
assert(p.num_peers(*i) == 1);
|
||||||
|
assert(p.is_requested(*i));
|
||||||
num_requests--;
|
num_requests--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,6 +288,8 @@ namespace libtorrent
|
|||||||
return;
|
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());
|
std::random_shuffle(busy_pieces.begin(), busy_pieces.end());
|
||||||
|
|
||||||
// find the block with the fewest requests to it
|
// find the block with the fewest requests to it
|
||||||
@ -293,7 +297,11 @@ namespace libtorrent
|
|||||||
busy_pieces.begin(), busy_pieces.end()
|
busy_pieces.begin(), busy_pieces.end()
|
||||||
, bind(&piece_picker::num_peers, boost::cref(p), _1) <
|
, bind(&piece_picker::num_peers, boost::cref(p), _1) <
|
||||||
bind(&piece_picker::num_peers, boost::cref(p), _2));
|
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.add_request(*i);
|
||||||
c.send_block_requests();
|
c.send_block_requests();
|
||||||
}
|
}
|
||||||
@ -304,6 +312,47 @@ namespace libtorrent
|
|||||||
, m_available_free_upload(0)
|
, m_available_free_upload(0)
|
||||||
, m_last_optimistic_disconnect(min_time())
|
, m_last_optimistic_disconnect(min_time())
|
||||||
{ assert(t); }
|
{ 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
|
// finds the peer that has the worst download rate
|
||||||
// and returns it. May return 0 if all peers are
|
// and returns it. May return 0 if all peers are
|
||||||
// choked.
|
// choked.
|
||||||
|
@ -613,29 +613,9 @@ namespace detail
|
|||||||
|
|
||||||
// Close connections whose endpoint is filtered
|
// Close connections whose endpoint is filtered
|
||||||
// by the new ip-filter
|
// by the new ip-filter
|
||||||
for (session_impl::connection_map::iterator i
|
for (torrent_map::iterator i = m_torrents.begin()
|
||||||
= m_connections.begin(); i != m_connections.end();)
|
, end(m_torrents.end()); i != end; ++i)
|
||||||
{
|
i->second->ip_filter_updated();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void session_impl::set_settings(session_settings const& s)
|
void session_impl::set_settings(session_settings const& s)
|
||||||
@ -1921,13 +1901,15 @@ namespace detail
|
|||||||
int session_impl::upload_rate_limit() const
|
int session_impl::upload_rate_limit() const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
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
|
int session_impl::download_rate_limit() const
|
||||||
{
|
{
|
||||||
mutex_t::scoped_lock l(m_mutex);
|
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()
|
void session_impl::start_lsd()
|
||||||
|
@ -981,7 +981,7 @@ namespace libtorrent
|
|||||||
return true;
|
return true;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__APPLE__) || defined(__linux__)
|
#if defined(__APPLE__) || defined(__linux__) || defined(__FreeBSD__)
|
||||||
// find the last existing directory of the save path
|
// find the last existing directory of the save path
|
||||||
fs::path query_path = p;
|
fs::path query_path = p;
|
||||||
while (!query_path.empty() && !exists(query_path))
|
while (!query_path.empty() && !exists(query_path))
|
||||||
@ -1019,6 +1019,7 @@ namespace libtorrent
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// workaround for bugs in Mac OS X where zero run is not reported
|
||||||
if (!strcmp(fsinfo.f_fstypename, "hfs")
|
if (!strcmp(fsinfo.f_fstypename, "hfs")
|
||||||
|| !strcmp(fsinfo.f_fstypename, "ufs"))
|
|| !strcmp(fsinfo.f_fstypename, "ufs"))
|
||||||
return true;
|
return true;
|
||||||
@ -1026,7 +1027,7 @@ namespace libtorrent
|
|||||||
return false;
|
return false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#if defined(__linux__) || defined(__FreeBSD__)
|
||||||
struct statfs buf;
|
struct statfs buf;
|
||||||
int err = statfs(query_path.native_directory_string().c_str(), &buf);
|
int err = statfs(query_path.native_directory_string().c_str(), &buf);
|
||||||
if (err == 0)
|
if (err == 0)
|
||||||
@ -1044,6 +1045,7 @@ namespace libtorrent
|
|||||||
case 0x52345362: // Reiser4
|
case 0x52345362: // Reiser4
|
||||||
case 0x58465342: // XFS
|
case 0x58465342: // XFS
|
||||||
case 0x65735546: // NTFS-3G
|
case 0x65735546: // NTFS-3G
|
||||||
|
case 0x19540119: // UFS2
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1125,6 +1127,7 @@ namespace libtorrent
|
|||||||
j.piece = r.piece;
|
j.piece = r.piece;
|
||||||
j.offset = r.start;
|
j.offset = r.start;
|
||||||
j.buffer_size = r.length;
|
j.buffer_size = r.length;
|
||||||
|
assert(r.length <= 16 * 1024);
|
||||||
m_io_thread.add_job(j, handler);
|
m_io_thread.add_job(j, handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1569,16 +1572,12 @@ namespace libtorrent
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_unallocated_slots.empty())
|
if (m_unallocated_slots.empty())
|
||||||
{
|
|
||||||
m_state = state_create_files;
|
m_state = state_create_files;
|
||||||
return false;
|
else if (m_compact_mode)
|
||||||
}
|
|
||||||
|
|
||||||
if (m_compact_mode)
|
|
||||||
{
|
|
||||||
m_state = state_create_files;
|
m_state = state_create_files;
|
||||||
return false;
|
else
|
||||||
}
|
m_state = state_allocating;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_state = state_full_check;
|
m_state = state_full_check;
|
||||||
@ -1598,7 +1597,7 @@ namespace libtorrent
|
|||||||
| |
|
| |
|
||||||
| v
|
| v
|
||||||
| +------------+
|
| +------------+
|
||||||
| | allocating |
|
|->| allocating |
|
||||||
| +------------+
|
| +------------+
|
||||||
| |
|
| |
|
||||||
| v
|
| v
|
||||||
|
@ -831,6 +831,11 @@ namespace libtorrent
|
|||||||
|
|
||||||
if (passed_hash_check)
|
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
|
// the following call may cause picker to become invalid
|
||||||
// in case we just became a seed
|
// in case we just became a seed
|
||||||
announce_piece(index);
|
announce_piece(index);
|
||||||
@ -1104,7 +1109,7 @@ namespace libtorrent
|
|||||||
|
|
||||||
void torrent::set_piece_priority(int index, int priority)
|
void torrent::set_piece_priority(int index, int priority)
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(valid_metadata());
|
assert(valid_metadata());
|
||||||
if (is_seed()) return;
|
if (is_seed()) return;
|
||||||
@ -1114,13 +1119,13 @@ namespace libtorrent
|
|||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
assert(index < m_torrent_file.num_pieces());
|
assert(index < m_torrent_file.num_pieces());
|
||||||
|
|
||||||
m_picker->set_piece_priority(index, priority);
|
bool filter_updated = m_picker->set_piece_priority(index, priority);
|
||||||
update_peer_interest();
|
if (filter_updated) update_peer_interest();
|
||||||
}
|
}
|
||||||
|
|
||||||
int torrent::piece_priority(int index) const
|
int torrent::piece_priority(int index) const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
// INVARIANT_CHECK;
|
||||||
|
|
||||||
assert(valid_metadata());
|
assert(valid_metadata());
|
||||||
if (is_seed()) return 1;
|
if (is_seed()) return 1;
|
||||||
@ -1144,14 +1149,15 @@ namespace libtorrent
|
|||||||
assert(m_picker.get());
|
assert(m_picker.get());
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
bool filter_updated = false;
|
||||||
for (std::vector<int>::const_iterator i = pieces.begin()
|
for (std::vector<int>::const_iterator i = pieces.begin()
|
||||||
, end(pieces.end()); i != end; ++i, ++index)
|
, end(pieces.end()); i != end; ++i, ++index)
|
||||||
{
|
{
|
||||||
assert(*i >= 0);
|
assert(*i >= 0);
|
||||||
assert(*i <= 7);
|
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
|
void torrent::piece_priorities(std::vector<int>& pieces) const
|
||||||
@ -1653,17 +1659,26 @@ namespace libtorrent
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_RESOLVE_COUNTRIES
|
#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
|
void torrent::resolve_peer_country(boost::intrusive_ptr<peer_connection> const& p) const
|
||||||
{
|
{
|
||||||
if (m_resolving_country
|
if (m_resolving_country
|
||||||
|| p->has_country()
|
|| p->has_country()
|
||||||
|| p->is_connecting()
|
|| p->is_connecting()
|
||||||
|| p->is_queued()
|
|| p->is_queued()
|
||||||
|| p->in_handshake()) return;
|
|| p->in_handshake()
|
||||||
|
|| p->remote().address().is_v6()) return;
|
||||||
|
|
||||||
m_resolving_country = true;
|
m_resolving_country = true;
|
||||||
tcp::resolver::query q(boost::lexical_cast<std::string>(p->remote().address())
|
asio::ip::address_v4 reversed(swap_bytes(p->remote().address().to_v4().to_ulong()));
|
||||||
+ ".zz.countries.nerd.dk", "0");
|
tcp::resolver::query q(reversed.to_string() + ".zz.countries.nerd.dk", "0");
|
||||||
m_host_resolver.async_resolve(q, m_ses.m_strand.wrap(
|
m_host_resolver.async_resolve(q, m_ses.m_strand.wrap(
|
||||||
bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)));
|
bind(&torrent::on_country_lookup, shared_from_this(), _1, _2, p)));
|
||||||
}
|
}
|
||||||
@ -2325,15 +2340,11 @@ namespace libtorrent
|
|||||||
|
|
||||||
torrent_handle torrent::get_handle() const
|
torrent_handle torrent::get_handle() const
|
||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
|
||||||
|
|
||||||
return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash());
|
return torrent_handle(&m_ses, &m_checker, m_torrent_file.info_hash());
|
||||||
}
|
}
|
||||||
|
|
||||||
session_settings const& torrent::settings() const
|
session_settings const& torrent::settings() const
|
||||||
{
|
{
|
||||||
// INVARIANT_CHECK;
|
|
||||||
|
|
||||||
return m_ses.settings();
|
return m_ses.settings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,6 +773,9 @@ namespace libtorrent
|
|||||||
partial_piece_info pi;
|
partial_piece_info pi;
|
||||||
pi.piece_state = (partial_piece_info::state_t)i->state;
|
pi.piece_state = (partial_piece_info::state_t)i->state;
|
||||||
pi.blocks_in_piece = p.blocks_in_piece(i->index);
|
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);
|
int piece_size = t->torrent_file().piece_size(i->index);
|
||||||
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
for (int j = 0; j < pi.blocks_in_piece; ++j)
|
||||||
{
|
{
|
||||||
|
@ -62,9 +62,10 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
if (a.is_v6()) return false;
|
if (a.is_v6()) return false;
|
||||||
address_v4 a4 = a.to_v4();
|
address_v4 a4 = a.to_v4();
|
||||||
return ((a4.to_ulong() & 0xff000000) == 0x0a000000
|
unsigned long ip = a4.to_ulong();
|
||||||
|| (a4.to_ulong() & 0xfff00000) == 0xac100000
|
return ((ip & 0xff000000) == 0x0a000000
|
||||||
|| (a4.to_ulong() & 0xffff0000) == 0xc0a80000);
|
|| (ip & 0xfff00000) == 0xac100000
|
||||||
|
|| (ip & 0xffff0000) == 0xc0a80000);
|
||||||
}
|
}
|
||||||
|
|
||||||
address_v4 guess_local_address(asio::io_service& ios)
|
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();
|
d.upnp_connection.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e)
|
if (e && e != asio::error::eof)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
@ -671,7 +672,16 @@ void upnp::on_upnp_xml(asio::error_code const& e
|
|||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
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
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -790,7 +800,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||||||
d.upnp_connection.reset();
|
d.upnp_connection.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e)
|
if (e && e != asio::error::eof)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
@ -823,12 +833,22 @@ void upnp::on_upnp_map_response(asio::error_code const& e
|
|||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== incomplete http message" << std::endl;
|
<< " <== error while adding portmap: incomplete http message" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
m_devices.erase(d);
|
m_devices.erase(d);
|
||||||
return;
|
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;
|
error_code_parse_state s;
|
||||||
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
|
xml_parse((char*)p.get_body().begin, (char*)p.get_body().end
|
||||||
, m_strand.wrap(bind(&find_error_code, _1, _2, boost::ref(s))));
|
, 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();
|
d.upnp_connection.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e)
|
if (e && e != asio::error::eof)
|
||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
@ -944,11 +964,21 @@ void upnp::on_upnp_unmap_response(asio::error_code const& e
|
|||||||
{
|
{
|
||||||
#ifdef TORRENT_UPNP_LOGGING
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== incomplete http message" << std::endl;
|
<< " <== error while deleting portmap: incomplete http message" << std::endl;
|
||||||
#endif
|
#endif
|
||||||
return;
|
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
|
#ifdef TORRENT_UPNP_LOGGING
|
||||||
m_log << time_now_string()
|
m_log << time_now_string()
|
||||||
<< " <== unmap response: " << std::string(p.get_body().begin, p.get_body().end)
|
<< " <== 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)
|
virtual bool on_extended(int length, int msg, buffer::const_interval body)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (msg != extension_index) return false;
|
if (msg != extension_index) return false;
|
||||||
if (m_message_index == 0) return false;
|
if (m_message_index == 0) return false;
|
||||||
|
|
||||||
if (length > 500 * 1024)
|
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;
|
if (body.left() < length) return true;
|
||||||
|
|
||||||
entry pex_msg = bdecode(body.begin, body.end);
|
try
|
||||||
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);
|
entry pex_msg = bdecode(body.begin, body.end);
|
||||||
char flags = detail::read_uint8(fin);
|
std::string const& peers = pex_msg["added"].string();
|
||||||
p.peer_from_tracker(adr, pid, peer_info::pex, flags);
|
std::string const& peer_flags = pex_msg["added.f"].string();
|
||||||
}
|
|
||||||
return true;
|
int num_peers = peers.length() / 6;
|
||||||
}
|
char const* in = peers.c_str();
|
||||||
catch (std::exception&)
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,7 +315,14 @@ namespace libtorrent
|
|||||||
{
|
{
|
||||||
INVARIANT_CHECK;
|
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();
|
boost::shared_ptr<torrent> t = associated_torrent().lock();
|
||||||
assert(t);
|
assert(t);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user