Sync libtorrent to trunk.

Start of columns menu.
This commit is contained in:
Andrew Resch 2007-08-13 09:28:29 +00:00
parent ac29983651
commit b7e3c6b3df
33 changed files with 613 additions and 280 deletions

View File

@ -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>

View File

@ -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

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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;
};

View File

@ -59,7 +59,7 @@ POSSIBILITY OF SUCH DAMAGE.
*/
#include <iostream>
#include <iosfwd>
#include <map>
#include <list>
#include <string>

View File

@ -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:

View File

@ -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;
};
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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

View File

@ -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; }

View File

@ -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 ============

View File

@ -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; }

View File

@ -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 = '>';
}
}

View File

@ -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@

View File

@ -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)
{

View File

@ -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);

View File

@ -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);
}

View File

@ -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>

View File

@ -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();
}

View File

@ -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;

View File

@ -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.

View File

@ -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()

View File

@ -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

View File

@ -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();
}

View File

@ -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)
{

View File

@ -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)

View File

@ -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;
}

View File

@ -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);