diff --git a/libtorrent/include/libtorrent/assert.hpp b/libtorrent/include/libtorrent/assert.hpp index 246e3b51b..dd3c6b737 100644 --- a/libtorrent/include/libtorrent/assert.hpp +++ b/libtorrent/include/libtorrent/assert.hpp @@ -41,6 +41,7 @@ TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, ch #define TORRENT_ASSERT(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__) #else +#include #define TORRENT_ASSERT(x) assert(x) #endif diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index cf627c70b..c9b6cb218 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -379,6 +379,7 @@ namespace libtorrent // this pool is used to allocate and recycle send // buffers from. boost::pool<> m_send_buffers; + boost::mutex m_send_buffer_mutex; // the file pool that all storages in this session's // torrents uses. It sets a limit on the number of diff --git a/libtorrent/include/libtorrent/bandwidth_limit.hpp b/libtorrent/include/libtorrent/bandwidth_limit.hpp new file mode 100644 index 000000000..e0675aa31 --- /dev/null +++ b/libtorrent/include/libtorrent/bandwidth_limit.hpp @@ -0,0 +1,120 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED +#define TORRENT_BANDWIDTH_LIMIT_HPP_INCLUDED + +#include + +#include "libtorrent/assert.hpp" + +namespace libtorrent { + +// member of peer_connection +struct bandwidth_limit +{ + static const int inf = boost::integer_traits::const_max; + + bandwidth_limit() + : m_quota_left(0) + , m_local_limit(inf) + , m_current_rate(0) + {} + + void throttle(int limit) + { + TORRENT_ASSERT(limit > 0); + m_local_limit = limit; + } + + int throttle() const + { + return m_local_limit; + } + + void assign(int amount) + { + TORRENT_ASSERT(amount >= 0); + m_current_rate += amount; + m_quota_left += amount; + } + + void use_quota(int amount) + { + TORRENT_ASSERT(amount <= m_quota_left); + m_quota_left -= amount; + } + + int quota_left() const + { + return (std::max)(m_quota_left, 0); + } + + void expire(int amount) + { + TORRENT_ASSERT(amount >= 0); + m_current_rate -= amount; + } + + int max_assignable() const + { + if (m_local_limit == inf) return inf; + if (m_local_limit <= m_current_rate) return 0; + return m_local_limit - m_current_rate; + } + +private: + + // this is the amount of bandwidth we have + // been assigned without using yet. i.e. + // the bandwidth that we use up every time + // we receive or send a message. Once this + // hits zero, we need to request more + // bandwidth from the torrent which + // in turn will request bandwidth from + // the bandwidth manager + int m_quota_left; + + // the local limit is the number of bytes + // per window size we are allowed to use. + int m_local_limit; + + // the current rate is the number of + // bytes we have been assigned within + // the window size. + int m_current_rate; +}; + +} + +#endif + diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index da251cf4b..68cb7c73a 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -44,6 +44,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket.hpp" #include "libtorrent/invariant_check.hpp" #include "libtorrent/assert.hpp" +#include "libtorrent/bandwidth_limit.hpp" +#include "libtorrent/bandwidth_queue_entry.hpp" using boost::weak_ptr; using boost::shared_ptr; @@ -77,91 +79,6 @@ struct history_entry weak_ptr tor; }; -template -struct bw_queue_entry -{ - bw_queue_entry(boost::intrusive_ptr const& pe - , int blk, bool no_prio) - : peer(pe), max_block_size(blk), non_prioritized(no_prio) {} - boost::intrusive_ptr peer; - int max_block_size; - bool non_prioritized; -}; - -// member of peer_connection -struct bandwidth_limit -{ - static const int inf = boost::integer_traits::const_max; - - bandwidth_limit() throw() - : m_quota_left(0) - , m_local_limit(inf) - , m_current_rate(0) - {} - - void throttle(int limit) throw() - { - m_local_limit = limit; - } - - int throttle() const throw() - { - return m_local_limit; - } - - void assign(int amount) throw() - { - TORRENT_ASSERT(amount >= 0); - m_current_rate += amount; - m_quota_left += amount; - } - - void use_quota(int amount) throw() - { - TORRENT_ASSERT(amount <= m_quota_left); - m_quota_left -= amount; - } - - int quota_left() const throw() - { - return (std::max)(m_quota_left, 0); - } - - void expire(int amount) throw() - { - TORRENT_ASSERT(amount >= 0); - m_current_rate -= amount; - } - - int max_assignable() const throw() - { - if (m_local_limit == inf) return inf; - if (m_local_limit <= m_current_rate) return 0; - return m_local_limit - m_current_rate; - } - -private: - - // this is the amount of bandwidth we have - // been assigned without using yet. i.e. - // the bandwidth that we use up every time - // we receive or send a message. Once this - // hits zero, we need to request more - // bandwidth from the torrent which - // in turn will request bandwidth from - // the bandwidth manager - int m_quota_left; - - // the local limit is the number of bytes - // per window size we are allowed to use. - int m_local_limit; - - // the current rate is the number of - // bytes we have been assigned within - // the window size. - int m_current_rate; -}; - template T clamp(T val, T ceiling, T floor) throw() { @@ -203,6 +120,19 @@ struct bandwidth_manager m_history_timer.cancel(); } +#ifndef NDEBUG + bool is_in_history(PeerConnection const* peer) const + { + mutex_t::scoped_lock l(m_mutex); + for (typename history_t::const_iterator i + = m_history.begin(), end(m_history.end()); i != end; ++i) + { + if (i->peer.get() == peer) return true; + } + return false; + } +#endif + // non prioritized means that, if there's a line for bandwidth, // others will cut in front of the non-prioritized peers. // this is used by web seeds @@ -213,6 +143,7 @@ struct bandwidth_manager INVARIANT_CHECK; TORRENT_ASSERT(blk > 0); + mutex_t::scoped_lock l(m_mutex); TORRENT_ASSERT(!peer->ignore_bandwidth_limits()); // make sure this peer isn't already in line @@ -224,6 +155,7 @@ struct bandwidth_manager TORRENT_ASSERT(i->peer < peer || peer < i->peer); } #endif + TORRENT_ASSERT(peer->max_assignable_bandwidth(m_channel) > 0); boost::shared_ptr t = peer->associated_torrent().lock(); @@ -257,7 +189,7 @@ struct bandwidth_manager #ifdef TORRENT_VERBOSE_BANDWIDTH_LIMIT std::cerr << " req_bandwidht. m_queue.size() = " << m_queue.size() << std::endl; #endif - if (!m_queue.empty()) hand_out_bandwidth(); + if (!m_queue.empty()) hand_out_bandwidth(l); } #ifndef NDEBUG @@ -309,6 +241,7 @@ private: TORRENT_ASSERT(!m_history.empty()); + mutex_t::scoped_lock l(m_mutex); ptime now(time_now()); while (!m_history.empty() && m_history.back().expires_at <= now) { @@ -318,8 +251,10 @@ private: TORRENT_ASSERT(m_current_quota >= 0); intrusive_ptr c = e.peer; shared_ptr t = e.tor.lock(); + l.unlock(); if (!c->is_disconnecting()) c->expire_bandwidth(m_channel, e.amount); if (t) t->expire_bandwidth(m_channel, e.amount); + l.lock(); } // now, wait for the next chunk to expire @@ -332,7 +267,7 @@ private: // since some bandwidth just expired, it // means we can hand out more (in case there // are still consumers in line) - if (!m_queue.empty()) hand_out_bandwidth(); + if (!m_queue.empty()) hand_out_bandwidth(l); #ifndef NDEBUG } catch (std::exception&) @@ -342,7 +277,7 @@ private: #endif } - void hand_out_bandwidth() throw() + void hand_out_bandwidth(boost::mutex::scoped_lock& l) throw() { // if we're already handing out bandwidth, just return back // to the loop further down on the callstack @@ -355,9 +290,7 @@ private: ptime now(time_now()); - mutex_t::scoped_lock l(m_mutex); int limit = m_limit; - l.unlock(); // available bandwidth to hand out int amount = limit - m_current_quota; @@ -369,34 +302,41 @@ private: << " m_current_quota = " << m_current_quota << std::endl; #endif - while (!m_queue.empty() && amount > 0) + if (amount <= 0) + { + m_in_hand_out_bandwidth = false; + return; + } + + queue_t q; + queue_t tmp; + m_queue.swap(q); + while (!q.empty() && amount > 0) { TORRENT_ASSERT(amount == limit - m_current_quota); - bw_queue_entry qe = m_queue.front(); + bw_queue_entry qe = q.front(); TORRENT_ASSERT(qe.max_block_size > 0); - m_queue.pop_front(); + q.pop_front(); shared_ptr t = qe.peer->associated_torrent().lock(); if (!t) continue; if (qe.peer->is_disconnecting()) { + l.unlock(); t->expire_bandwidth(m_channel, qe.max_block_size); - TORRENT_ASSERT(amount == limit - m_current_quota); + l.lock(); + amount = limit - m_current_quota; continue; } // at this point, max_assignable may actually be zero. Since - // the bandwidth quota is subtracted once the data has been - // sent. If the peer was added to the queue while the data was - // still being sent, max_assignable may have been > 0 at that time. - int max_assignable = (std::min)( - qe.peer->max_assignable_bandwidth(m_channel) - , t->max_assignable_bandwidth(m_channel)); + // the rate limit of the peer might have changed while it + // was in the queue. + int max_assignable = qe.peer->max_assignable_bandwidth(m_channel); if (max_assignable == 0) { - t->expire_bandwidth(m_channel, qe.max_block_size); - qe.peer->assign_bandwidth(m_channel, 0); - TORRENT_ASSERT(amount == limit - m_current_quota); + TORRENT_ASSERT(is_in_history(qe.peer.get())); + tmp.push_back(qe); continue; } @@ -441,7 +381,7 @@ private: #endif if (amount < block_size / 2) { - m_queue.push_front(qe); + tmp.push_back(qe); break; } @@ -454,12 +394,16 @@ private: TORRENT_ASSERT(amount == limit - m_current_quota); amount -= hand_out_amount; TORRENT_ASSERT(hand_out_amount <= qe.max_block_size); + l.unlock(); t->assign_bandwidth(m_channel, hand_out_amount, qe.max_block_size); qe.peer->assign_bandwidth(m_channel, hand_out_amount); + l.lock(); add_history_entry(history_entry( qe.peer, t, hand_out_amount, now + bw_window_size)); - TORRENT_ASSERT(amount == limit - m_current_quota); + amount = limit - m_current_quota; } + if (!q.empty()) m_queue.insert(m_queue.begin(), q.begin(), q.end()); + if (!tmp.empty()) m_queue.insert(m_queue.begin(), tmp.begin(), tmp.end()); #ifndef NDEBUG } catch (std::exception& e) diff --git a/libtorrent/include/libtorrent/bandwidth_queue_entry.hpp b/libtorrent/include/libtorrent/bandwidth_queue_entry.hpp new file mode 100644 index 000000000..76c119d96 --- /dev/null +++ b/libtorrent/include/libtorrent/bandwidth_queue_entry.hpp @@ -0,0 +1,54 @@ +/* + +Copyright (c) 2007, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED +#define TORRENT_BANDWIDTH_QUEUE_ENTRY_HPP_INCLUDED + +#include + +namespace libtorrent { + +template +struct bw_queue_entry +{ + bw_queue_entry(boost::intrusive_ptr const& pe + , int blk, bool no_prio) + : peer(pe), max_block_size(blk), non_prioritized(no_prio) {} + boost::intrusive_ptr peer; + int max_block_size; + bool non_prioritized; +}; + +} + +#endif + diff --git a/libtorrent/include/libtorrent/disk_io_thread.hpp b/libtorrent/include/libtorrent/disk_io_thread.hpp index a77522356..1d9d88534 100644 --- a/libtorrent/include/libtorrent/disk_io_thread.hpp +++ b/libtorrent/include/libtorrent/disk_io_thread.hpp @@ -30,6 +30,9 @@ POSSIBILITY OF SUCH DAMAGE. */ +#ifndef TORRENT_DISK_IO_THREAD +#define TORRENT_DISK_IO_THREAD + #ifdef TORRENT_DISK_STATS #include #endif @@ -99,7 +102,9 @@ namespace libtorrent int disk_allocations() const { return m_allocations; } #endif - + + void join(); + // aborts read operations void stop(boost::intrusive_ptr s); void add_job(disk_io_job const& j @@ -152,3 +157,5 @@ namespace libtorrent } +#endif + diff --git a/libtorrent/include/libtorrent/ip_filter.hpp b/libtorrent/include/libtorrent/ip_filter.hpp index eee76cdc4..1adb14551 100644 --- a/libtorrent/include/libtorrent/ip_filter.hpp +++ b/libtorrent/include/libtorrent/ip_filter.hpp @@ -76,9 +76,9 @@ namespace detail template Addr zero() { - typename Addr::bytes_type zero; + Addr zero; std::fill(zero.begin(), zero.end(), 0); - return Addr(zero); + return zero; } template<> @@ -87,8 +87,8 @@ namespace detail template Addr plus_one(Addr const& a) { - typename Addr::bytes_type tmp(a.to_bytes()); - typedef typename Addr::bytes_type::reverse_iterator iter; + Addr tmp(a); + typedef typename Addr::reverse_iterator iter; for (iter i = tmp.rbegin() , end(tmp.rend()); i != end; ++i) { @@ -99,7 +99,7 @@ namespace detail } *i = 0; } - return Addr(tmp); + return tmp; } inline boost::uint16_t plus_one(boost::uint16_t val) { return val + 1; } @@ -107,8 +107,8 @@ namespace detail template Addr minus_one(Addr const& a) { - typename Addr::bytes_type tmp(a.to_bytes()); - typedef typename Addr::bytes_type::reverse_iterator iter; + Addr tmp(a); + typedef typename Addr::reverse_iterator iter; for (iter i = tmp.rbegin() , end(tmp.rend()); i != end; ++i) { @@ -119,7 +119,7 @@ namespace detail } *i = (std::numeric_limits::max)(); } - return Addr(tmp); + return tmp; } inline boost::uint16_t minus_one(boost::uint16_t val) { return val - 1; } @@ -127,9 +127,9 @@ namespace detail template Addr max_addr() { - typename Addr::bytes_type tmp; + Addr tmp; std::fill(tmp.begin(), tmp.end() - , (std::numeric_limits::max)()); + , (std::numeric_limits::max)()); return Addr(tmp); } @@ -220,23 +220,24 @@ namespace detail return i->access; } - std::vector > export_filter() const + template + std::vector > export_filter() const { - std::vector > ret; + std::vector > ret; ret.reserve(m_access_list.size()); for (typename range_t::const_iterator i = m_access_list.begin() , end(m_access_list.end()); i != end;) { - ip_range r; - r.first = i->start; + ip_range r; + r.first = ExternalAddressType(i->start); r.flags = i->access; ++i; if (i == end) - r.last = max_addr(); + r.last = ExternalAddressType(max_addr()); else - r.last = minus_one(i->start); + r.last = ExternalAddressType(minus_one(i->start)); ret.push_back(r); } @@ -288,8 +289,8 @@ public: private: - detail::filter_impl m_filter4; - detail::filter_impl m_filter6; + detail::filter_impl m_filter4; + detail::filter_impl m_filter6; }; class TORRENT_EXPORT port_filter diff --git a/libtorrent/include/libtorrent/pe_crypto.hpp b/libtorrent/include/libtorrent/pe_crypto.hpp index e2276dee6..5db77f6c7 100644 --- a/libtorrent/include/libtorrent/pe_crypto.hpp +++ b/libtorrent/include/libtorrent/pe_crypto.hpp @@ -62,7 +62,7 @@ namespace libtorrent private: int get_local_key_size () const { - assert (m_DH); + TORRENT_ASSERT(m_DH); return BN_num_bytes (m_DH->pub_key); } @@ -97,8 +97,8 @@ namespace libtorrent void encrypt (char* pos, int len) { - assert (len >= 0); - assert (pos); + TORRENT_ASSERT(len >= 0); + TORRENT_ASSERT(pos); RC4 (&m_local_key, len, reinterpret_cast(pos), reinterpret_cast(pos)); @@ -106,8 +106,8 @@ namespace libtorrent void decrypt (char* pos, int len) { - assert (len >= 0); - assert (pos); + TORRENT_ASSERT(len >= 0); + TORRENT_ASSERT(pos); RC4 (&m_remote_key, len, reinterpret_cast(pos), reinterpret_cast(pos)); diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp index 805b38d9d..60cb4bc17 100755 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ b/libtorrent/include/libtorrent/peer_connection.hpp @@ -69,7 +69,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/piece_block_progress.hpp" #include "libtorrent/config.hpp" #include "libtorrent/session.hpp" -#include "libtorrent/bandwidth_manager.hpp" +#include "libtorrent/bandwidth_limit.hpp" #include "libtorrent/policy.hpp" #include "libtorrent/socket_type.hpp" #include "libtorrent/intrusive_ptr_base.hpp" diff --git a/libtorrent/include/libtorrent/session_settings.hpp b/libtorrent/include/libtorrent/session_settings.hpp index 7cc7d26da..2817d27d2 100644 --- a/libtorrent/include/libtorrent/session_settings.hpp +++ b/libtorrent/include/libtorrent/session_settings.hpp @@ -117,6 +117,7 @@ namespace libtorrent , use_dht_as_fallback(true) #endif , free_torrent_hashes(true) + , upnp_ignore_nonrouters(true) {} // this is the user agent that will be sent to the tracker @@ -292,6 +293,11 @@ namespace libtorrent // make the get_torrent_info() function to return an incomplete // torrent object that cannot be passed back to add_torrent() bool free_torrent_hashes; + + // when this is true, the upnp port mapper will ignore + // any upnp devices that don't have an address that matches + // our currently configured router. + bool upnp_ignore_nonrouters; }; #ifndef TORRENT_DISABLE_DHT diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index 4731da6b2..f66620999 100755 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -65,7 +65,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/piece_picker.hpp" #include "libtorrent/config.hpp" #include "libtorrent/escape_string.hpp" -#include "libtorrent/bandwidth_manager.hpp" +#include "libtorrent/bandwidth_limit.hpp" +#include "libtorrent/bandwidth_queue_entry.hpp" #include "libtorrent/storage.hpp" #include "libtorrent/hasher.hpp" #include "libtorrent/assert.hpp" diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp index 0b799d1e9..be8ec15cb 100644 --- a/libtorrent/include/libtorrent/upnp.hpp +++ b/libtorrent/include/libtorrent/upnp.hpp @@ -68,13 +68,14 @@ class upnp : public intrusive_ptr_base public: upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb); + , portmap_callback_t const& cb, bool ignore_nonrouters); ~upnp(); // maps the ports, if a port is set to 0 // it will not be mapped void set_mappings(int tcp, int udp); + void discover_device(); void close(); private: @@ -89,7 +90,6 @@ private: void resend_request(asio::error_code const& e); void on_reply(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred); - void discover_device(); struct rootdevice; @@ -233,6 +233,8 @@ private: connection_queue& m_cc; + std::vector
m_filter; + #ifdef TORRENT_UPNP_LOGGING std::ofstream m_log; #endif diff --git a/libtorrent/include/libtorrent/web_peer_connection.hpp b/libtorrent/include/libtorrent/web_peer_connection.hpp index 8871ad8ec..742d823f0 100755 --- a/libtorrent/include/libtorrent/web_peer_connection.hpp +++ b/libtorrent/include/libtorrent/web_peer_connection.hpp @@ -120,7 +120,8 @@ namespace libtorrent void write_interested() {} void write_not_interested() {} void write_request(peer_request const& r); - void write_cancel(peer_request const& r) {} + void write_cancel(peer_request const& r) + { incoming_reject_request(r); } void write_have(int index) {} void write_piece(peer_request const& r, char* buffer) { TORRENT_ASSERT(false); } void write_keepalive() {} diff --git a/libtorrent/src/broadcast_socket.cpp b/libtorrent/src/broadcast_socket.cpp index e03ad2274..3437648d9 100644 --- a/libtorrent/src/broadcast_socket.cpp +++ b/libtorrent/src/broadcast_socket.cpp @@ -170,12 +170,17 @@ namespace libtorrent for (std::list::iterator i = m_sockets.begin() , end(m_sockets.end()); i != end; ++i) { + if (!i->socket) continue; asio::error_code e; i->socket->send_to(asio::buffer(buffer, size), m_multicast_endpoint, 0, e); #ifndef NDEBUG // std::cerr << " sending on " << i->socket->local_endpoint().address().to_string() << std::endl; #endif - if (e) ec = e; + if (e) + { + i->socket->close(e); + i->socket.reset(); + } } } @@ -184,6 +189,7 @@ namespace libtorrent { if (ec || bytes_transferred == 0 || !m_on_receive) return; m_on_receive(s->remote, s->buffer, bytes_transferred); + if (!s->socket) return; s->socket->async_receive_from(asio::buffer(s->buffer, sizeof(s->buffer)) , s->remote, bind(&broadcast_socket::on_receive, this, s, _1, _2)); } @@ -195,6 +201,7 @@ namespace libtorrent for (std::list::iterator i = m_sockets.begin() , end(m_sockets.end()); i != end; ++i) { + if (!i->socket) continue; i->socket->close(); } } diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index 384bc2375..ca98888bd 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/src/bt_peer_connection.cpp @@ -295,6 +295,8 @@ namespace libtorrent { INVARIANT_CHECK; + if (!m_supports_fast) return; + TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); @@ -312,6 +314,7 @@ namespace libtorrent TORRENT_ASSERT(m_sent_handshake && m_sent_bitfield); TORRENT_ASSERT(associated_torrent().lock()->valid_metadata()); + TORRENT_ASSERT(m_supports_fast); char msg[] = {0,0,0,5, msg_allowed_fast, 0, 0, 0, 0}; char* ptr = msg + 5; @@ -1297,6 +1300,9 @@ namespace libtorrent detail::write_int32(r.start, ptr); // begin detail::write_int32(r.length, ptr); // length send_buffer(msg, sizeof(msg)); + + if (!m_supports_fast) + incoming_reject_request(r); } void bt_peer_connection::write_request(peer_request const& r) diff --git a/libtorrent/src/disk_io_thread.cpp b/libtorrent/src/disk_io_thread.cpp index e0fa982bc..886d5d891 100644 --- a/libtorrent/src/disk_io_thread.cpp +++ b/libtorrent/src/disk_io_thread.cpp @@ -62,12 +62,7 @@ namespace libtorrent disk_io_thread::~disk_io_thread() { - mutex_t::scoped_lock l(m_mutex); - m_abort = true; - m_signal.notify_all(); - l.unlock(); - - m_disk_io_thread.join(); + TORRENT_ASSERT(m_abort == true); } #ifndef NDEBUG @@ -95,6 +90,16 @@ namespace libtorrent #endif + void disk_io_thread::join() + { + mutex_t::scoped_lock l(m_mutex); + m_abort = true; + m_signal.notify_all(); + l.unlock(); + + m_disk_io_thread.join(); + } + // aborts read operations void disk_io_thread::stop(boost::intrusive_ptr s) { diff --git a/libtorrent/src/ip_filter.cpp b/libtorrent/src/ip_filter.cpp index 05334e578..eb91de0d0 100644 --- a/libtorrent/src/ip_filter.cpp +++ b/libtorrent/src/ip_filter.cpp @@ -44,12 +44,12 @@ namespace libtorrent if (first.is_v4()) { TORRENT_ASSERT(last.is_v4()); - m_filter4.add_rule(first.to_v4(), last.to_v4(), flags); + m_filter4.add_rule(first.to_v4().to_bytes(), last.to_v4().to_bytes(), flags); } else if (first.is_v6()) { TORRENT_ASSERT(last.is_v6()); - m_filter6.add_rule(first.to_v6(), last.to_v6(), flags); + m_filter6.add_rule(first.to_v6().to_bytes(), last.to_v6().to_bytes(), flags); } else TORRENT_ASSERT(false); @@ -58,15 +58,15 @@ namespace libtorrent int ip_filter::access(address const& addr) const { if (addr.is_v4()) - return m_filter4.access(addr.to_v4()); + return m_filter4.access(addr.to_v4().to_bytes()); TORRENT_ASSERT(addr.is_v6()); - return m_filter6.access(addr.to_v6()); + return m_filter6.access(addr.to_v6().to_bytes()); } ip_filter::filter_tuple_t ip_filter::export_filter() const { - return boost::make_tuple(m_filter4.export_filter() - , m_filter6.export_filter()); + return boost::make_tuple(m_filter4.export_filter() + , m_filter6.export_filter()); } void port_filter::add_rule(boost::uint16_t first, boost::uint16_t last, int flags) diff --git a/libtorrent/src/metadata_transfer.cpp b/libtorrent/src/metadata_transfer.cpp index 50dc57ec7..228566ed8 100644 --- a/libtorrent/src/metadata_transfer.cpp +++ b/libtorrent/src/metadata_transfer.cpp @@ -95,7 +95,6 @@ namespace libtorrent { namespace return ret; } - struct metadata_plugin : torrent_plugin { metadata_plugin(torrent& t) @@ -217,7 +216,7 @@ namespace libtorrent { namespace m_metadata_size = total_size; } - void piece_pass(int) + void on_piece_pass(int) { // if we became a seed, copy the metadata from // the torrent before it is deallocated diff --git a/libtorrent/src/pe_crypto.cpp b/libtorrent/src/pe_crypto.cpp index 955a7fea0..093bb1265 100644 --- a/libtorrent/src/pe_crypto.cpp +++ b/libtorrent/src/pe_crypto.cpp @@ -52,11 +52,11 @@ namespace libtorrent { m_DH->g = BN_bin2bn (m_dh_generator, sizeof(m_dh_generator), NULL); m_DH->length = 160l; - assert (sizeof(m_dh_prime) == DH_size(m_DH)); + TORRENT_ASSERT(sizeof(m_dh_prime) == DH_size(m_DH)); DH_generate_key (m_DH); // TODO Check != 0 - assert (m_DH->pub_key); + TORRENT_ASSERT(m_DH->pub_key); // DH can generate key sizes that are smaller than the size of // P with exponentially decreasing probability, in which case @@ -78,7 +78,7 @@ namespace libtorrent { DH_key_exchange::~DH_key_exchange () { - assert (m_DH); + TORRENT_ASSERT(m_DH); DH_free (m_DH); } @@ -91,7 +91,7 @@ namespace libtorrent { // compute shared secret given remote public key void DH_key_exchange::compute_secret (char const* remote_pubkey) { - assert (remote_pubkey); + TORRENT_ASSERT(remote_pubkey); BIGNUM* bn_remote_pubkey = BN_bin2bn ((unsigned char*)remote_pubkey, 96, NULL); char dh_secret[96]; diff --git a/libtorrent/src/peer_connection.cpp b/libtorrent/src/peer_connection.cpp index 9bd089234..ac61f042f 100755 --- a/libtorrent/src/peer_connection.cpp +++ b/libtorrent/src/peer_connection.cpp @@ -759,7 +759,7 @@ namespace libtorrent } // ----------------------------- - // -------- REJECT PIECE ------- + // ------- SUGGEST PIECE ------- // ----------------------------- void peer_connection::incoming_suggest(int index) @@ -1127,6 +1127,18 @@ namespace libtorrent "i: " << m_peer_interested << " | " "t: " << (int)t->torrent_file().piece_size(r.piece) << " | " "n: " << t->torrent_file().num_pieces() << " ]\n"; + + (*m_logger) << time_now_string() + << " ==> REJECT_PIECE [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " ]\n"; + + (*m_logger) << time_now_string() + << " ==> REJECT_PIECE [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " ]\n"; #endif write_reject_request(r); return; @@ -1155,8 +1167,13 @@ namespace libtorrent { write_reject_request(r); #ifdef TORRENT_VERBOSE_LOGGING - (*m_logger) << time_now_string() - << " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n"; + (*m_logger) << time_now_string() + << " *** REJECTING REQUEST [ peer choked and piece not in allowed fast set ]\n"; + (*m_logger) << time_now_string() + << " ==> REJECT_PIECE [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " ]\n"; #endif } else @@ -1179,6 +1196,12 @@ namespace libtorrent "n: " << t->torrent_file().num_pieces() << " | " "h: " << t->have_piece(r.piece) << " | " "block_limit: " << t->block_size() << " ]\n"; + + (*m_logger) << time_now_string() + << " ==> REJECT_PIECE [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " ]\n"; #endif write_reject_request(r); @@ -1365,6 +1388,9 @@ namespace libtorrent m_outstanding_writing_bytes += p.length; TORRENT_ASSERT(!m_reading); picker.mark_as_writing(block_finished, peer_info_struct()); +#ifndef NDEBUG + t->check_invariant(); +#endif } void peer_connection::on_disk_write_complete(int ret, disk_io_job const& j @@ -1479,6 +1505,14 @@ namespace libtorrent if (i != m_requests.end()) { m_requests.erase(i); +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() + << " ==> REJECT_PIECE [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " ]\n"; +#endif + write_reject_request(r); } else { @@ -1612,12 +1646,6 @@ namespace libtorrent } #endif - // if we already have the piece, we can - // ignore this message - if (t->valid_metadata() - && t->have_piece(index)) - return; - if (index < 0 || index >= int(m_have_piece.size())) { #ifdef TORRENT_VERBOSE_LOGGING @@ -1627,6 +1655,12 @@ namespace libtorrent return; } + // if we already have the piece, we can + // ignore this message + if (t->valid_metadata() + && t->have_piece(index)) + return; + m_allowed_fast.push_back(index); // if the peer has the piece and we want @@ -1735,11 +1769,6 @@ namespace libtorrent // sent yet, so we don't have to send a cancel. return; } - else - { - m_download_queue.erase(it); - t->picker().abort_download(block); - } int block_offset = block.block_index * t->block_size(); int block_size @@ -1753,13 +1782,12 @@ namespace libtorrent r.start = block_offset; r.length = block_size; - write_cancel(r); - #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << time_now_string() << " ==> CANCEL [ piece: " << block.piece_index << " | s: " << block_offset << " | l: " << block_size << " | " << block.block_index << " ]\n"; #endif + write_cancel(r); } void peer_connection::send_choke() @@ -1783,6 +1811,19 @@ namespace libtorrent // reject the requests we have in the queue std::for_each(m_requests.begin(), m_requests.end() , bind(&peer_connection::write_reject_request, this, _1)); + +#ifdef TORRENT_VERBOSE_LOGGING + for (std::deque::iterator i = m_requests.begin() + , end(m_requests.end()); i != end; ++i) + { + peer_request const& r = *i; + (*m_logger) << time_now_string() + << " ==> REJECT_PIECE [ " + "piece: " << r.piece << " | " + "s: " << r.start << " | " + "l: " << r.length << " ]\n"; + } +#endif m_requests.clear(); } @@ -2206,18 +2247,24 @@ namespace libtorrent else { piece_picker& picker = t->picker(); - while (!m_download_queue.empty()) + + std::deque dl(m_download_queue); + for (std::deque::iterator i = dl.begin() + , end(dl.end()); i != end; ++i) { piece_block const& r = m_download_queue.back(); - picker.abort_download(r); +#ifdef TORRENT_VERBOSE_LOGGING + (*m_logger) << time_now_string() + << " ==> CANCEL [ piece: " << r.piece_index + << " | block: " << r.block_index + << " ]\n"; +#endif write_cancel(t->to_req(r)); - m_download_queue.pop_back(); } while (!m_request_queue.empty()) { piece_block const& r = m_request_queue.back(); picker.abort_download(r); - write_cancel(t->to_req(r)); m_request_queue.pop_back(); } @@ -2562,6 +2609,7 @@ namespace libtorrent // return value is destructed buffer::interval peer_connection::allocate_send_buffer(int size) { + TORRENT_ASSERT(size > 0); char* insert = m_send_buffer.allocate_appendix(size); if (insert == 0) { @@ -2618,6 +2666,7 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "**ERROR**: " << error.message() << "[in peer_connection::on_receive_data]\n"; #endif + set_failed(); on_receive(error, bytes_transferred); throw std::runtime_error(error.message()); } @@ -2778,6 +2827,7 @@ namespace libtorrent (*m_ses.m_logger) << "CONNECTION FAILED: " << m_remote.address().to_string() << ": " << e.message() << "\n"; #endif + set_failed(); m_ses.connection_failed(self(), m_remote, e.message().c_str()); return; } @@ -2838,6 +2888,7 @@ namespace libtorrent #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "**ERROR**: " << error.message() << " [in peer_connection::on_send_data]\n"; #endif + set_failed(); throw std::runtime_error(error.message()); } if (m_disconnecting) return; @@ -2869,6 +2920,17 @@ namespace libtorrent #ifndef NDEBUG void peer_connection::check_invariant() const { + for (int i = 0; i < 2; ++i) + { + // this peer is in the bandwidth history iff max_assignable < limit + TORRENT_ASSERT((m_bandwidth_limit[i].max_assignable() < m_bandwidth_limit[i].throttle()) + == m_ses.m_bandwidth_manager[i]->is_in_history(this) + || m_bandwidth_limit[i].throttle() == bandwidth_limit::inf); + } + std::set unique; + std::copy(m_download_queue.begin(), m_download_queue.end(), std::inserter(unique, unique.begin())); + std::copy(m_request_queue.begin(), m_request_queue.end(), std::inserter(unique, unique.begin())); + TORRENT_ASSERT(unique.size() == m_download_queue.size() + m_request_queue.size()); if (m_peer_info) { TORRENT_ASSERT(m_peer_info->connection == this diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index f203eaa56..2fdc5358a 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -533,6 +533,12 @@ namespace libtorrent if (i->second.type == peer::not_connectable) continue; if (i->second.seed && finished) continue; if (i->second.failcount >= max_failcount) continue; + + // prefer peers with lower failcount + if (candidate != m_peers.end() + && candidate->second.failcount < i->second.failcount) + continue; + if (now - i->second.connected < seconds(i->second.failcount * min_reconnect_time)) continue; if (ses.m_port_filter.access(i->second.ip.port()) & port_filter::blocked) diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index c1969d523..055bf38db 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -2198,6 +2198,11 @@ namespace detail #endif m_checker_thread->join(); +#if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) + (*m_logger) << time_now_string() << " waiting for disk io thread\n"; +#endif + m_disk_thread.join(); + TORRENT_ASSERT(m_torrents.empty()); TORRENT_ASSERT(m_connections.empty()); #if defined(TORRENT_VERBOSE_LOGGING) || defined(TORRENT_LOGGING) @@ -2345,8 +2350,10 @@ namespace detail , m_listen_interface.address() , m_settings.user_agent , bind(&session_impl::on_port_mapping - , this, _1, _2, _3)); + , this, _1, _2, _3) + , m_settings.upnp_ignore_nonrouters); + m_upnp->discover_device(); m_upnp->set_mappings(m_listen_interface.port(), #ifndef TORRENT_DISABLE_DHT m_dht ? m_dht_settings.service_port : @@ -2385,7 +2392,11 @@ namespace detail std::pair session_impl::allocate_buffer(int size) { + TORRENT_ASSERT(size > 0); int num_buffers = (size + send_buffer_size - 1) / send_buffer_size; + TORRENT_ASSERT(num_buffers > 0); + + boost::mutex::scoped_lock l(m_send_buffer_mutex); #ifdef TORRENT_STATS m_buffer_allocations += num_buffers; m_buffer_usage_logger << log_time() << " protocol_buffer: " @@ -2397,8 +2408,12 @@ namespace detail void session_impl::free_buffer(char* buf, int size) { + TORRENT_ASSERT(size > 0); TORRENT_ASSERT(size % send_buffer_size == 0); int num_buffers = size / send_buffer_size; + TORRENT_ASSERT(num_buffers > 0); + + boost::mutex::scoped_lock l(m_send_buffer_mutex); #ifdef TORRENT_STATS m_buffer_allocations -= num_buffers; TORRENT_ASSERT(m_buffer_allocations >= 0); diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index e8c1f2247..12db1e59b 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -1589,6 +1589,18 @@ namespace libtorrent p->set_peer_info(0); TORRENT_ASSERT(i != m_connections.end()); m_connections.erase(i); + + // remove from bandwidth request-queue + for (int c = 0; c < 2; ++c) + { + for (queue_t::iterator i = m_bandwidth_queue[c].begin() + , end(m_bandwidth_queue[c].end()); i != end; ++i) + { + if (i->peer != p) continue; + m_bandwidth_queue[c].erase(i); + break; + } + } } catch (std::exception& e) { @@ -2147,6 +2159,11 @@ namespace libtorrent throw protocol_error("session is closing"); } + if (int(m_connections.size()) >= m_max_connections) + { + throw protocol_error("reached connection limit"); + } + TORRENT_ASSERT(m_connections.find(p) == m_connections.end()); peer_iterator ci = m_connections.insert(p).first; try @@ -2220,6 +2237,7 @@ namespace libtorrent , bool non_prioritized) { TORRENT_ASSERT(m_bandwidth_limit[channel].throttle() > 0); + TORRENT_ASSERT(p->max_assignable_bandwidth(channel) > 0); int block_size = m_bandwidth_limit[channel].throttle() / 10; if (block_size <= 0) block_size = 1; @@ -2244,16 +2262,23 @@ namespace libtorrent TORRENT_ASSERT(amount > 0); m_bandwidth_limit[channel].expire(amount); - + queue_t tmp; while (!m_bandwidth_queue[channel].empty()) { bw_queue_entry qe = m_bandwidth_queue[channel].front(); if (m_bandwidth_limit[channel].max_assignable() == 0) break; m_bandwidth_queue[channel].pop_front(); + if (qe.peer->max_assignable_bandwidth(channel) <= 0) + { + TORRENT_ASSERT(m_ses.m_bandwidth_manager[channel]->is_in_history(qe.peer.get())); + if (!qe.peer->is_disconnecting()) tmp.push_back(qe); + continue; + } perform_bandwidth_request(channel, qe.peer , qe.max_block_size, qe.non_prioritized); } + m_bandwidth_queue[channel].insert(m_bandwidth_queue[channel].begin(), tmp.begin(), tmp.end()); } void torrent::perform_bandwidth_request(int channel @@ -2592,6 +2617,9 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + TORRENT_ASSERT(m_bandwidth_queue[0].size() <= m_connections.size()); + TORRENT_ASSERT(m_bandwidth_queue[1].size() <= m_connections.size()); + int num_uploads = 0; std::map num_requests; for (const_peer_iterator i = begin(); i != end(); ++i) @@ -2615,7 +2643,8 @@ namespace libtorrent for (std::map::iterator i = num_requests.begin() , end(num_requests.end()); i != end; ++i) { - TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second); + if (!m_picker->is_downloaded(i->first)) + TORRENT_ASSERT(m_picker->num_peers(i->first) == i->second); } } diff --git a/libtorrent/src/torrent_info.cpp b/libtorrent/src/torrent_info.cpp index b89510f9f..0aac5a7ba 100755 --- a/libtorrent/src/torrent_info.cpp +++ b/libtorrent/src/torrent_info.cpp @@ -350,10 +350,23 @@ namespace libtorrent { m_name = info["name"].string(); } fs::path tmp = m_name; - if (tmp.is_complete()) throw std::runtime_error("torrent contains " - "a file with an absolute path: '" + m_name + "'"); - if (tmp.has_branch_path()) throw std::runtime_error( - "torrent contains name with directories: '" + m_name + "'"); + if (tmp.is_complete()) + { + m_name = tmp.leaf(); + } + else if (tmp.has_branch_path()) + { + fs::path p; + for (fs::path::iterator i = tmp.begin() + , end(tmp.end()); i != end; ++i) + { + if (*i == "." || *i == "..") continue; + p /= *i; + } + m_name = p.string(); + } + if (m_name == ".." || m_name == ".") + throw std::runtime_error("invalid 'name' of torrent (possible exploit attempt)"); // extract file list entry const* i = info.find_key("files"); diff --git a/libtorrent/src/udp_tracker_connection.cpp b/libtorrent/src/udp_tracker_connection.cpp index eb138e67a..0ad38ef86 100755 --- a/libtorrent/src/udp_tracker_connection.cpp +++ b/libtorrent/src/udp_tracker_connection.cpp @@ -106,7 +106,6 @@ namespace libtorrent , udp::resolver::iterator i) try { if (error == asio::error::operation_aborted) return; - if (!m_socket.is_open()) return; // the operation was aborted if (error || i == udp::resolver::iterator()) { fail(-1, error.message().c_str()); diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index 116eb1dfe..4f6ac7fbf 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/http_tracker_connection.hpp" #include "libtorrent/xml_parse.hpp" #include "libtorrent/connection_queue.hpp" +#include "libtorrent/enum_net.hpp" #include #include @@ -61,7 +62,7 @@ namespace libtorrent upnp::upnp(io_service& ios, connection_queue& cc , address const& listen_interface, std::string const& user_agent - , portmap_callback_t const& cb) + , portmap_callback_t const& cb, bool ignore_nonrouters) : m_udp_local_port(0) , m_tcp_local_port(0) , m_user_agent(user_agent) @@ -81,7 +82,21 @@ upnp::upnp(io_service& ios, connection_queue& cc m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc); #endif m_retry_count = 0; - discover_device(); + + if (ignore_nonrouters) + { + asio::error_code ec; + std::vector
const& net = enum_net_interfaces(m_io_service, ec); + m_filter.reserve(net.size()); + for (std::vector
::const_iterator i = net.begin() + , end(net.end()); i != end; ++i) + { + asio::error_code e; + address a = router_for_interface(*i, e); + if (e || is_loopback(a)) continue; + m_filter.push_back(a); + } + } } upnp::~upnp() @@ -266,6 +281,18 @@ try Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 */ + if (!m_filter.empty() && std::find(m_filter.begin(), m_filter.end() + , from.address()) == m_filter.end()) + { + // this upnp device is filtered because it's not in the + // list of configured routers +#ifdef TORRENT_UPNP_LOGGING + m_log << time_now_string() << " <== (" << from << ") Rootdevice " + "ignored because it's not out router" << std::endl; +#endif + return; + } + http_parser p; try { @@ -663,7 +690,7 @@ void upnp::on_upnp_xml(asio::error_code const& e parse_state s; s.reset("urn:schemas-upnp-org:service:WANIPConnection:1"); xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , m_strand.wrap(bind(&find_control_url, _1, _2, boost::ref(s)))); + , bind(&find_control_url, _1, _2, boost::ref(s))); if (s.found_service) { d.service_namespace = s.service_type; @@ -674,7 +701,7 @@ void upnp::on_upnp_xml(asio::error_code const& e // a PPP connection s.reset("urn:schemas-upnp-org:service:WANPPPConnection:1"); xml_parse((char*)p.get_body().begin, (char*)p.get_body().end - , m_strand.wrap(bind(&find_control_url, _1, _2, boost::ref(s)))); + , bind(&find_control_url, _1, _2, boost::ref(s))); if (s.found_service) { d.service_namespace = s.service_type; @@ -821,7 +848,7 @@ void upnp::on_upnp_map_response(asio::error_code const& e 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)))); + , bind(&find_error_code, _1, _2, boost::ref(s))); #ifdef TORRENT_UPNP_LOGGING if (s.error_code != -1)