diff --git a/libtorrent/include/libtorrent/alert_types.hpp b/libtorrent/include/libtorrent/alert_types.hpp index c810dd3f6..36c13c5ab 100755 --- a/libtorrent/include/libtorrent/alert_types.hpp +++ b/libtorrent/include/libtorrent/alert_types.hpp @@ -38,6 +38,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket.hpp" #include "libtorrent/peer_connection.hpp" #include "libtorrent/config.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { diff --git a/libtorrent/include/libtorrent/assert.hpp b/libtorrent/include/libtorrent/assert.hpp index 8ab605080..62425809e 100644 --- a/libtorrent/include/libtorrent/assert.hpp +++ b/libtorrent/include/libtorrent/assert.hpp @@ -30,9 +30,6 @@ POSSIBILITY OF SUCH DAMAGE. */ -#ifndef TORRENT_ASSERT_HPP_INCLUDED -#define TORRENT_ASSERT_HPP_INCLUDED - #include #ifndef NDEBUG @@ -43,7 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. void assert_fail(const char* expr, int line, char const* file, char const* function); -#define assert(x) if (!(x)) assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__) +#define assert(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__) #endif @@ -53,5 +50,3 @@ void assert_fail(const char* expr, int line, char const* file, char const* funct #endif #endif -#endif - diff --git a/libtorrent/include/libtorrent/aux_/session_impl.hpp b/libtorrent/include/libtorrent/aux_/session_impl.hpp index 74ca7c8f7..0389bf3dc 100644 --- a/libtorrent/include/libtorrent/aux_/session_impl.hpp +++ b/libtorrent/include/libtorrent/aux_/session_impl.hpp @@ -83,6 +83,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket_type.hpp" #include "libtorrent/connection_queue.hpp" #include "libtorrent/disk_io_thread.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -275,6 +276,7 @@ namespace libtorrent int max_connections() const { return m_max_connections; } int max_uploads() const { return m_max_uploads; } + int max_half_open_connections() const { return m_half_open.limit(); } int num_uploads() const { return m_num_unchoked; } int num_connections() const diff --git a/libtorrent/include/libtorrent/bandwidth_manager.hpp b/libtorrent/include/libtorrent/bandwidth_manager.hpp index c46772bd8..03d4f65ae 100644 --- a/libtorrent/include/libtorrent/bandwidth_manager.hpp +++ b/libtorrent/include/libtorrent/bandwidth_manager.hpp @@ -33,9 +33,6 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED #define TORRENT_BANDWIDTH_MANAGER_HPP_INCLUDED -#include "libtorrent/socket.hpp" -#include "libtorrent/invariant_check.hpp" - #include #include #include @@ -44,6 +41,10 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#include "libtorrent/socket.hpp" +#include "libtorrent/invariant_check.hpp" +#include "libtorrent/assert.hpp" + using boost::weak_ptr; using boost::shared_ptr; using boost::intrusive_ptr; diff --git a/libtorrent/include/libtorrent/bencode.hpp b/libtorrent/include/libtorrent/bencode.hpp index a142b5864..9e670c10b 100755 --- a/libtorrent/include/libtorrent/bencode.hpp +++ b/libtorrent/include/libtorrent/bencode.hpp @@ -79,6 +79,8 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/entry.hpp" #include "libtorrent/config.hpp" +#include "libtorrent/assert.hpp" + #if defined(_MSC_VER) namespace std { diff --git a/libtorrent/include/libtorrent/buffer.hpp b/libtorrent/include/libtorrent/buffer.hpp index 0cb44225a..0f37edcbd 100644 --- a/libtorrent/include/libtorrent/buffer.hpp +++ b/libtorrent/include/libtorrent/buffer.hpp @@ -34,8 +34,9 @@ POSSIBILITY OF SUCH DAMAGE. //#define TORRENT_BUFFER_DEBUG -#include "libtorrent/invariant_check.hpp" #include +#include "libtorrent/invariant_check.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { diff --git a/libtorrent/include/libtorrent/fingerprint.hpp b/libtorrent/include/libtorrent/fingerprint.hpp index d7e5a5fc6..712be6979 100755 --- a/libtorrent/include/libtorrent/fingerprint.hpp +++ b/libtorrent/include/libtorrent/fingerprint.hpp @@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/peer_id.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -91,3 +92,4 @@ namespace libtorrent } #endif // TORRENT_FINGERPRINT_HPP_INCLUDED + diff --git a/libtorrent/include/libtorrent/http_connection.hpp b/libtorrent/include/libtorrent/http_connection.hpp index 409213857..ccc145413 100644 --- a/libtorrent/include/libtorrent/http_connection.hpp +++ b/libtorrent/include/libtorrent/http_connection.hpp @@ -44,13 +44,18 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket.hpp" #include "libtorrent/http_tracker_connection.hpp" #include "libtorrent/time.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { +struct http_connection; + typedef boost::function http_handler; +typedef boost::function http_connect_handler; + // TODO: add bind interface // when bottled, the last two arguments to the handler @@ -58,11 +63,13 @@ typedef boost::function, boost::noncopyable { http_connection(asio::io_service& ios, connection_queue& cc - , http_handler handler, bool bottled = true) + , http_handler const& handler, bool bottled = true + , http_connect_handler const& ch = http_connect_handler()) : m_sock(ios) , m_read_pos(0) , m_resolver(ios) , m_handler(handler) + , m_connect_handler(ch) , m_timer(ios) , m_last_receive(time_now()) , m_bottled(bottled) @@ -92,6 +99,8 @@ struct http_connection : boost::enable_shared_from_this, boost: , time_duration timeout, bool handle_redirect = true); void close(); + tcp::socket const& socket() const { return m_sock; } + private: void on_resolve(asio::error_code const& e @@ -112,6 +121,7 @@ private: tcp::resolver m_resolver; http_parser m_parser; http_handler m_handler; + http_connect_handler m_connect_handler; deadline_timer m_timer; time_duration m_timeout; ptime m_last_receive; diff --git a/libtorrent/include/libtorrent/ip_filter.hpp b/libtorrent/include/libtorrent/ip_filter.hpp index 8b1793c3a..7b8cc0e17 100644 --- a/libtorrent/include/libtorrent/ip_filter.hpp +++ b/libtorrent/include/libtorrent/ip_filter.hpp @@ -33,6 +33,9 @@ POSSIBILITY OF SUCH DAMAGE. #ifndef TORRENT_IP_FILTER_HPP #define TORRENT_IP_FILTER_HPP +#include +#include + #ifdef _MSC_VER #pragma warning(push, 1) #endif @@ -48,8 +51,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/socket.hpp" -#include -#include +#include "libtorrent/assert.hpp" namespace libtorrent { diff --git a/libtorrent/include/libtorrent/kademlia/routing_table.hpp b/libtorrent/include/libtorrent/kademlia/routing_table.hpp index 45a7dd762..9e10a3483 100644 --- a/libtorrent/include/libtorrent/kademlia/routing_table.hpp +++ b/libtorrent/include/libtorrent/kademlia/routing_table.hpp @@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include namespace libtorrent { namespace dht { diff --git a/libtorrent/include/libtorrent/lsd.hpp b/libtorrent/include/libtorrent/lsd.hpp index 9ffbcdfc3..e8eaf0df1 100644 --- a/libtorrent/include/libtorrent/lsd.hpp +++ b/libtorrent/include/libtorrent/lsd.hpp @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/socket.hpp" #include "libtorrent/peer_id.hpp" +#include "libtorrent/broadcast_socket.hpp" #include #include @@ -58,35 +59,26 @@ public: , peer_callback_t const& cb); ~lsd(); - void rebind(address const& listen_interface); +// void rebind(address const& listen_interface); void announce(sha1_hash const& ih, int listen_port); void close(); private: - static address_v4 lsd_multicast_address; - static udp::endpoint lsd_multicast_endpoint; - void resend_announce(asio::error_code const& e, std::string msg); - void on_announce(asio::error_code const& e + void on_announce(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred); - void setup_receive(); +// void setup_receive(); peer_callback_t m_callback; // current retry count int m_retry_count; - // used to receive responses in - char m_receive_buffer[1024]; - - // the endpoint we received the message from - udp::endpoint m_remote; - // the udp socket used to send and receive // multicast messages on - datagram_socket m_socket; + broadcast_socket m_socket; // used to resend udp packets in case // they time out diff --git a/libtorrent/include/libtorrent/peer_connection.hpp b/libtorrent/include/libtorrent/peer_connection.hpp index 219abc5d7..5e65f767a 100755 --- a/libtorrent/include/libtorrent/peer_connection.hpp +++ b/libtorrent/include/libtorrent/peer_connection.hpp @@ -72,6 +72,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/policy.hpp" #include "libtorrent/socket_type.hpp" #include "libtorrent/intrusive_ptr_base.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -750,4 +751,3 @@ namespace libtorrent #endif // TORRENT_PEER_CONNECTION_HPP_INCLUDED - diff --git a/libtorrent/include/libtorrent/piece_picker.hpp b/libtorrent/include/libtorrent/piece_picker.hpp index 08cfebd96..94f274a27 100755 --- a/libtorrent/include/libtorrent/piece_picker.hpp +++ b/libtorrent/include/libtorrent/piece_picker.hpp @@ -275,6 +275,8 @@ namespace libtorrent #ifndef NDEBUG // used in debug mode void check_invariant(const torrent* t = 0) const; + void verify_pick(std::vector const& picked + , std::vector const& bitfield) const; #endif // functor that compares indices on downloading_pieces @@ -293,6 +295,7 @@ namespace libtorrent private: + bool can_pick(int piece, std::vector const& bitmask) const; std::pair expand_piece(int piece, int whole_pieces , std::vector const& have) const; diff --git a/libtorrent/include/libtorrent/session.hpp b/libtorrent/include/libtorrent/session.hpp index a7ccc8d57..2ce19349e 100755 --- a/libtorrent/include/libtorrent/session.hpp +++ b/libtorrent/include/libtorrent/session.hpp @@ -237,6 +237,7 @@ namespace libtorrent int upload_rate_limit() const; int download_rate_limit() const; + int max_half_open_connections() const; void set_upload_rate_limit(int bytes_per_second); void set_download_rate_limit(int bytes_per_second); diff --git a/libtorrent/include/libtorrent/stat.hpp b/libtorrent/include/libtorrent/stat.hpp index 2424d5d6c..24e477a37 100755 --- a/libtorrent/include/libtorrent/stat.hpp +++ b/libtorrent/include/libtorrent/stat.hpp @@ -40,6 +40,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/size_type.hpp" #include "libtorrent/invariant_check.hpp" #include "libtorrent/config.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { diff --git a/libtorrent/include/libtorrent/time.hpp b/libtorrent/include/libtorrent/time.hpp index 2227fc932..27d61af9d 100644 --- a/libtorrent/include/libtorrent/time.hpp +++ b/libtorrent/include/libtorrent/time.hpp @@ -55,6 +55,7 @@ namespace libtorrent || _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME) #include +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -85,6 +86,7 @@ namespace libtorrent #include #include +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -170,6 +172,7 @@ namespace asio #include #include +#include "libtorrent/assert.hpp" // high precision timer for darwin intel and ppc @@ -249,6 +252,7 @@ namespace libtorrent #define WIN32_LEAN_AND_MEAN #endif #include +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -335,6 +339,7 @@ namespace libtorrent #elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0 #include +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -385,4 +390,4 @@ namespace libtorrent #endif #endif - + diff --git a/libtorrent/include/libtorrent/torrent.hpp b/libtorrent/include/libtorrent/torrent.hpp index b8f8d7ae4..bcc54899f 100755 --- a/libtorrent/include/libtorrent/torrent.hpp +++ b/libtorrent/include/libtorrent/torrent.hpp @@ -68,6 +68,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bandwidth_manager.hpp" #include "libtorrent/storage.hpp" #include "libtorrent/hasher.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { diff --git a/libtorrent/include/libtorrent/torrent_info.hpp b/libtorrent/include/libtorrent/torrent_info.hpp index 093d33781..492fda48d 100755 --- a/libtorrent/include/libtorrent/torrent_info.hpp +++ b/libtorrent/include/libtorrent/torrent_info.hpp @@ -58,6 +58,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/time.hpp" #include "libtorrent/intrusive_ptr_base.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { @@ -321,8 +322,10 @@ namespace libtorrent entry m_extra_info; #ifndef NDEBUG + public: // this is set to true when seed_free() is called bool m_half_metadata; + private: #endif }; diff --git a/libtorrent/include/libtorrent/upnp.hpp b/libtorrent/include/libtorrent/upnp.hpp index d4b701aad..fc0650631 100644 --- a/libtorrent/include/libtorrent/upnp.hpp +++ b/libtorrent/include/libtorrent/upnp.hpp @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #define TORRENT_UPNP_HPP #include "libtorrent/socket.hpp" +#include "libtorrent/broadcast_socket.hpp" #include "libtorrent/http_connection.hpp" #include "libtorrent/connection_queue.hpp" @@ -56,9 +57,6 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { -bool is_local(address const& a); -address_v4 guess_local_address(asio::io_service&); - // int: external tcp port // int: external udp port // std::string: error message @@ -72,8 +70,6 @@ public: , portmap_callback_t const& cb); ~upnp(); - void rebind(address const& listen_interface); - // maps the ports, if a port is set to 0 // it will not be mapped void set_mappings(int tcp, int udp); @@ -90,7 +86,7 @@ private: void update_mapping(int i, int port); void resend_request(asio::error_code const& e); - void on_reply(asio::error_code const& e + void on_reply(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred); void discover_device(); @@ -106,12 +102,15 @@ private: , int mapping); void on_expire(asio::error_code const& e); - void post(rootdevice& d, std::stringstream const& s - , std::string const& soap_action); void map_port(rootdevice& d, int i); void unmap_port(rootdevice& d, int i); void disable(); + void delete_port_mapping(rootdevice& d, int i); + void create_port_mapping(http_connection& c, rootdevice& d, int i); + void post(upnp::rootdevice const& d, std::string const& soap + , std::string const& soap_action); + struct mapping_t { mapping_t() @@ -198,18 +197,13 @@ private: // current retry count int m_retry_count; - // used to receive responses in - char m_receive_buffer[1024]; + asio::io_service& m_io_service; - // the endpoint we received the message from - udp::endpoint m_remote; + asio::strand m_strand; - // the local address we're listening on - address_v4 m_local_ip; - // the udp socket used to send and receive // multicast messages on the network - datagram_socket m_socket; + broadcast_socket m_socket; // used to resend udp packets in case // they time out @@ -217,8 +211,6 @@ private: // timer used to refresh mappings deadline_timer m_refresh_timer; - - asio::strand m_strand; bool m_disabled; bool m_closing; diff --git a/libtorrent/src/bt_peer_connection.cpp b/libtorrent/src/bt_peer_connection.cpp index 1b1de3a81..11a39675f 100755 --- a/libtorrent/src/bt_peer_connection.cpp +++ b/libtorrent/src/bt_peer_connection.cpp @@ -710,16 +710,16 @@ namespace libtorrent #ifndef TORRENT_DISABLE_DHT // indicate that we support the DHT messages - *(i.begin + 7) = 0x01; + *(i.begin + 7) |= 0x01; #endif #ifndef TORRENT_DISABLE_EXTENSIONS // we support extensions - *(i.begin + 5) = 0x10; + *(i.begin + 5) |= 0x10; #endif // we support FAST extension - *(i.begin + 7) = 0x04; + *(i.begin + 7) |= 0x04; i.begin += 8; diff --git a/libtorrent/src/connection_queue.cpp b/libtorrent/src/connection_queue.cpp index 544ebec6b..0b3f5ff54 100644 --- a/libtorrent/src/connection_queue.cpp +++ b/libtorrent/src/connection_queue.cpp @@ -109,8 +109,6 @@ namespace libtorrent void connection_queue::try_connect() { - mutex_t::scoped_lock l(m_mutex); - INVARIANT_CHECK; if (!free_slots() || m_queue.empty()) @@ -166,21 +164,35 @@ namespace libtorrent ptime next_expire = max_time(); ptime now = time_now(); + std::list timed_out; for (std::list::iterator i = m_queue.begin(); !m_queue.empty() && i != m_queue.end();) { if (i->connecting && i->expires < now) { - boost::function on_timeout = i->on_timeout; - m_queue.erase(i++); + std::list::iterator j = i; + ++i; + timed_out.splice(timed_out.end(), m_queue, j, i); --m_num_connecting; - try { on_timeout(); } catch (std::exception&) {} continue; } if (i->expires < next_expire) next_expire = i->expires; ++i; } + + // we don't want to call the timeout callback while we're locked + // since that is a recepie for dead-locks + l.unlock(); + + for (std::list::iterator i = timed_out.begin() + , end(timed_out.end()); i != end; ++i) + { + try { i->on_timeout(); } catch (std::exception&) {} + } + + l.lock(); + if (next_expire < max_time()) { m_timer.expires_at(next_expire); diff --git a/libtorrent/src/escape_string.cpp b/libtorrent/src/escape_string.cpp index 673d56288..faff3de95 100755 --- a/libtorrent/src/escape_string.cpp +++ b/libtorrent/src/escape_string.cpp @@ -31,7 +31,6 @@ POSSIBILITY OF SUCH DAMAGE. */ #include "libtorrent/pch.hpp" -#include "libtorrent/assert.hpp" #include #include @@ -40,6 +39,8 @@ POSSIBILITY OF SUCH DAMAGE. #include #include +#include "libtorrent/assert.hpp" + namespace libtorrent { std::string unescape_string(std::string const& s) diff --git a/libtorrent/src/http_connection.cpp b/libtorrent/src/http_connection.cpp index 53798cae1..788fc3aff 100644 --- a/libtorrent/src/http_connection.cpp +++ b/libtorrent/src/http_connection.cpp @@ -165,6 +165,7 @@ void http_connection::on_connect(asio::error_code const& e if (!e) { m_last_receive = time_now(); + if (m_connect_handler) m_connect_handler(*this); asio::async_write(m_sock, asio::buffer(sendbuffer) , bind(&http_connection::on_write, shared_from_this(), _1)); } diff --git a/libtorrent/src/kademlia/closest_nodes.cpp b/libtorrent/src/kademlia/closest_nodes.cpp index 0c7d9d276..a3849ed69 100644 --- a/libtorrent/src/kademlia/closest_nodes.cpp +++ b/libtorrent/src/kademlia/closest_nodes.cpp @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include "libtorrent/assert.hpp" namespace libtorrent { namespace dht { diff --git a/libtorrent/src/lsd.cpp b/libtorrent/src/lsd.cpp index 76f25548d..d7590ec47 100644 --- a/libtorrent/src/lsd.cpp +++ b/libtorrent/src/lsd.cpp @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/lsd.hpp" #include "libtorrent/io.hpp" #include "libtorrent/http_tracker_connection.hpp" + #include #include #include @@ -52,76 +53,22 @@ namespace libtorrent address_v4 guess_local_address(asio::io_service&); } -address_v4 lsd::lsd_multicast_address; -udp::endpoint lsd::lsd_multicast_endpoint; - lsd::lsd(io_service& ios, address const& listen_interface , peer_callback_t const& cb) : m_callback(cb) , m_retry_count(0) - , m_socket(ios) + , m_socket(ios, udp::endpoint(address_v4::from_string("239.192.152.143"), 6771) + , bind(&lsd::on_announce, this, _1, _2, _3)) , m_broadcast_timer(ios) , m_disabled(false) { - // Bittorrent Local discovery multicast address and port - lsd_multicast_address = address_v4::from_string("239.192.152.143"); - lsd_multicast_endpoint = udp::endpoint(lsd_multicast_address, 6771); - #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log.open("lsd.log", std::ios::in | std::ios::out | std::ios::trunc); #endif - assert(lsd_multicast_address.is_multicast()); - rebind(listen_interface); } lsd::~lsd() {} -void lsd::rebind(address const& listen_interface) -{ - address_v4 local_ip = address_v4::any(); - if (listen_interface.is_v4() && listen_interface != address_v4::any()) - { - local_ip = listen_interface.to_v4(); - } - - try - { - // the local interface hasn't changed - if (m_socket.is_open() - && m_socket.local_endpoint().address() == local_ip) - return; - - m_socket.close(); - - using namespace asio::ip::multicast; - - m_socket.open(udp::v4()); - m_socket.set_option(datagram_socket::reuse_address(true)); - m_socket.bind(udp::endpoint(local_ip, 6771)); - -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "local ip: " << local_ip << std::endl; -#endif - - m_socket.set_option(join_group(lsd_multicast_address)); - m_socket.set_option(outbound_interface(local_ip)); - m_socket.set_option(enable_loopback(true)); - m_socket.set_option(hops(255)); - } - catch (std::exception& e) - { -#if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) - m_log << "socket multicast error " << e.what() - << ". disabling local service discovery" << std::endl; -#endif - m_disabled = true; - return; - } - m_disabled = false; - - setup_receive(); -} - void lsd::announce(sha1_hash const& ih, int listen_port) { if (m_disabled) return; @@ -136,8 +83,7 @@ void lsd::announce(sha1_hash const& ih, int listen_port) m_retry_count = 0; asio::error_code ec; - m_socket.send_to(asio::buffer(msg.c_str(), msg.size() - 1) - , lsd_multicast_endpoint, 0, ec); + m_socket.send(msg.c_str(), int(msg.size()), ec); if (ec) { m_disabled = true; @@ -157,8 +103,8 @@ void lsd::resend_announce(asio::error_code const& e, std::string msg) try { if (e) return; - m_socket.send_to(asio::buffer(msg, msg.size() - 1) - , lsd_multicast_endpoint); + asio::error_code ec; + m_socket.send(msg.c_str(), int(msg.size()), ec); ++m_retry_count; if (m_retry_count >= 5) @@ -170,14 +116,13 @@ void lsd::resend_announce(asio::error_code const& e, std::string msg) try catch (std::exception&) {} -void lsd::on_announce(asio::error_code const& e +void lsd::on_announce(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) { using namespace libtorrent::detail; - if (e) return; - char* p = m_receive_buffer; - char* end = m_receive_buffer + bytes_transferred; + char* p = buffer; + char* end = buffer + bytes_transferred; char* line = std::find(p, end, '\n'); for (char* i = p; i < line; ++i) *i = std::tolower(*i); #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) @@ -190,7 +135,6 @@ void lsd::on_announce(asio::error_code const& e m_log << time_now_string() << " *** assumed 'bt-search', ignoring" << std::endl; #endif - setup_receive(); return; } p = line + 1; @@ -223,25 +167,15 @@ void lsd::on_announce(asio::error_code const& e { #if defined(TORRENT_LOGGING) || defined(TORRENT_VERBOSE_LOGGING) m_log << time_now_string() - << " *** incoming local announce " << m_remote.address() + << " *** incoming local announce " << from.address() << ":" << port << " ih: " << ih << std::endl; #endif // we got an announce, pass it on through the callback - try { m_callback(tcp::endpoint(m_remote.address(), port), ih); } + try { m_callback(tcp::endpoint(from.address(), port), ih); } catch (std::exception&) {} } - setup_receive(); } -void lsd::setup_receive() try -{ - assert(m_socket.is_open()); - m_socket.async_receive_from(asio::buffer(m_receive_buffer - , sizeof(m_receive_buffer)), m_remote, bind(&lsd::on_announce, this, _1, _2)); -} -catch (std::exception&) -{} - void lsd::close() { m_socket.close(); diff --git a/libtorrent/src/natpmp.cpp b/libtorrent/src/natpmp.cpp index 0a5932a56..bdcabce9a 100644 --- a/libtorrent/src/natpmp.cpp +++ b/libtorrent/src/natpmp.cpp @@ -32,11 +32,13 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/pch.hpp" -#include -#include #include #include +#include "libtorrent/natpmp.hpp" +#include "libtorrent/io.hpp" +#include "libtorrent/assert.hpp" + using boost::bind; using namespace libtorrent; diff --git a/libtorrent/src/piece_picker.cpp b/libtorrent/src/piece_picker.cpp index 6d2fc2218..8c8911e7c 100755 --- a/libtorrent/src/piece_picker.cpp +++ b/libtorrent/src/piece_picker.cpp @@ -263,8 +263,23 @@ namespace libtorrent } m_downloads.erase(i); } + #ifndef NDEBUG + void piece_picker::verify_pick(std::vector const& picked + , std::vector const& bitfield) const + { + assert(bitfield.size() == m_piece_map.size()); + for (std::vector::const_iterator i = picked.begin() + , end(picked.end()); i != end; ++i) + { + assert(i->piece_index >= 0); + assert(i->piece_index < int(bitfield.size())); + assert(bitfield[i->piece_index]); + assert(!m_piece_map[i->piece_index].have()); + } + } + void piece_picker::check_invariant(const torrent* t) const { assert(sizeof(piece_pos) == 4); @@ -1138,11 +1153,7 @@ namespace libtorrent { assert(*i >= 0); assert(*i < int(m_piece_map.size())); - if (!pieces[*i] - || m_piece_map[*i].have() - || m_piece_map[*i].downloading - || m_piece_map[*i].filtered()) - continue; + if (!can_pick(*i, pieces)) continue; if (m_piece_map[*i].priority(m_sequenced_download_threshold) == bucket_index) suggested_bucket.push_back(*i); } @@ -1171,21 +1182,14 @@ namespace libtorrent for (std::vector::const_iterator i = suggested_pieces.begin() , end(suggested_pieces.end()); i != end; ++i) { - if (!pieces[*i] - || m_piece_map[*i].have() - || m_piece_map[*i].downloading - || m_piece_map[*i].filtered()) - continue; + if (!can_pick(*i, pieces)) continue; start_piece = *i; break; } int piece = start_piece; while (num_blocks > 0) { - while (!pieces[piece] - || m_piece_map[piece].have() - || m_piece_map[piece].downloading - || m_piece_map[piece].filtered()) + while (!can_pick(piece, pieces)) { ++piece; if (piece == int(m_piece_map.size())) piece = 0; @@ -1223,6 +1227,14 @@ namespace libtorrent , backup_blocks.begin(), backup_blocks.end()); } + bool piece_picker::can_pick(int piece, std::vector const& bitmask) const + { + return bitmask[piece] + && !m_piece_map[piece].have() + && !m_piece_map[piece].downloading + && !m_piece_map[piece].filtered(); + } + void piece_picker::clear_peer(void* peer) { for (std::vector::iterator i = m_block_info.begin() @@ -1311,8 +1323,17 @@ namespace libtorrent } } } - if (num_blocks <= 0) return 0; + if (num_blocks <= 0) + { +#ifndef NDEBUG + verify_pick(interesting_blocks, pieces); +#endif + return 0; + } } +#ifndef NDEBUG + verify_pick(interesting_blocks, pieces); +#endif return num_blocks; } @@ -1325,6 +1346,8 @@ namespace libtorrent for (std::vector::const_iterator i = m_downloads.begin() , end(m_downloads.end()); i != end; ++i) { + if (!pieces[i->index]) continue; + int num_blocks_in_piece = blocks_in_piece(i->index); // is true if all the other pieces that are currently @@ -1374,21 +1397,33 @@ namespace libtorrent // piece even though we have num_blocks if (prefer_whole_pieces > 0) continue; assert(num_blocks >= 0); - if (num_blocks == 0) return num_blocks; + if (num_blocks <= 0) break; } + if (num_blocks <= 0) break; } assert(num_blocks >= 0 || prefer_whole_pieces > 0); + +#ifndef NDEBUG + verify_pick(interesting_blocks, pieces); + verify_pick(backup_blocks, pieces); +#endif + if (num_blocks <= 0) return 0; if (on_parole) return num_blocks; interesting_blocks.insert(interesting_blocks.end() , backup_blocks.begin(), backup_blocks.end()); + num_blocks -= int(backup_blocks.size()); backup_blocks.clear(); + if (num_blocks <= 0) return 0; + for (std::vector::const_iterator i = m_downloads.begin() , end(m_downloads.end()); i != end; ++i) { + if (!pieces[i->index]) continue; + int num_blocks_in_piece = blocks_in_piece(i->index); // fill in with blocks requested from other peers @@ -1402,6 +1437,9 @@ namespace libtorrent backup_blocks.push_back(piece_block(i->index, j)); } } +#ifndef NDEBUG + verify_pick(backup_blocks, pieces); +#endif return num_blocks; } @@ -1414,10 +1452,7 @@ namespace libtorrent int lower_limit = piece - whole_pieces; if (lower_limit < -1) lower_limit = -1; while (start > lower_limit - && have[start] - && !m_piece_map[start].downloading - && !m_piece_map[start].filtered() - && !m_piece_map[start].have()) + && can_pick(start, have)) --start; ++start; assert(start >= 0); @@ -1425,10 +1460,7 @@ namespace libtorrent int upper_limit = start + whole_pieces; if (upper_limit > int(m_piece_map.size())) upper_limit = int(m_piece_map.size()); while (end < upper_limit - && have[end] - && !m_piece_map[end].downloading - && !m_piece_map[end].filtered() - && !m_piece_map[end].have()) + && can_pick(end, have)) ++end; return std::make_pair(start, end); } diff --git a/libtorrent/src/policy.cpp b/libtorrent/src/policy.cpp index f8e19db7b..3193ae455 100755 --- a/libtorrent/src/policy.cpp +++ b/libtorrent/src/policy.cpp @@ -1535,4 +1535,3 @@ namespace libtorrent } } - diff --git a/libtorrent/src/session.cpp b/libtorrent/src/session.cpp index 818af3ada..1d7a070c2 100755 --- a/libtorrent/src/session.cpp +++ b/libtorrent/src/session.cpp @@ -182,6 +182,7 @@ namespace libtorrent , bool paused , storage_constructor_type sc) { + assert(!ti.m_half_metadata); boost::intrusive_ptr tip(new torrent_info(ti)); return m_impl->add_torrent(tip, save_path, resume_data , compact_mode, sc, paused); @@ -195,6 +196,7 @@ namespace libtorrent , bool paused , storage_constructor_type sc) { + assert(!ti->m_half_metadata); return m_impl->add_torrent(ti, save_path, resume_data , compact_mode, sc, paused); } @@ -349,6 +351,11 @@ namespace libtorrent m_impl->set_max_connections(limit); } + int session::max_half_open_connections() const + { + return m_impl->max_half_open_connections(); + } + void session::set_max_half_open_connections(int limit) { m_impl->set_max_half_open_connections(limit); diff --git a/libtorrent/src/session_impl.cpp b/libtorrent/src/session_impl.cpp index 3d687eaf8..c0c129e79 100755 --- a/libtorrent/src/session_impl.cpp +++ b/libtorrent/src/session_impl.cpp @@ -532,6 +532,11 @@ namespace detail , m_next_connect_torrent(0) , m_checker_impl(*this) { +#ifdef WIN32 + // windows XP has a limit of 10 simultaneous connections + m_half_open.limit(8); +#endif + m_bandwidth_manager[peer_connection::download_channel] = &m_download_channel; m_bandwidth_manager[peer_connection::upload_channel] = &m_upload_channel; @@ -1254,29 +1259,7 @@ namespace detail assert(false); #endif }; // msvc 7.1 seems to require this -/* - void session_impl::connection_completed( - boost::intrusive_ptr const& p) try - { - mutex_t::scoped_lock l(m_mutex); - connection_map::iterator i = m_half_open.find(p->get_socket()); - m_connections.insert(std::make_pair(p->get_socket(), p)); - assert(i != m_half_open.end()); - if (i != m_half_open.end()) m_half_open.erase(i); - - if (m_abort) return; - - process_connection_queue(); - } - catch (std::exception& e) - { -#ifndef NDEBUG - std::cerr << e.what() << std::endl; - assert(false); -#endif - }; -*/ void session_impl::operator()() { eh_initializer(); @@ -1709,16 +1692,6 @@ namespace detail bool new_listen_address = m_listen_interface.address() != new_interface.address(); - if (new_listen_address) - { - if (m_natpmp.get()) - m_natpmp->rebind(new_interface.address()); - if (m_upnp.get()) - m_upnp->rebind(new_interface.address()); - if (m_lsd.get()) - m_lsd->rebind(new_interface.address()); - } - if (m_natpmp.get()) m_natpmp->set_mappings(m_listen_interface.port(), 0); if (m_upnp.get()) diff --git a/libtorrent/src/socks5_stream.cpp b/libtorrent/src/socks5_stream.cpp index b1679c4ac..a6b5544e4 100644 --- a/libtorrent/src/socks5_stream.cpp +++ b/libtorrent/src/socks5_stream.cpp @@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/pch.hpp" #include "libtorrent/socks5_stream.hpp" +#include "libtorrent/assert.hpp" namespace libtorrent { diff --git a/libtorrent/src/torrent.cpp b/libtorrent/src/torrent.cpp index 1a3083b7d..ddf8a9164 100755 --- a/libtorrent/src/torrent.cpp +++ b/libtorrent/src/torrent.cpp @@ -72,6 +72,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/extensions.hpp" #include "libtorrent/aux_/session_impl.hpp" #include "libtorrent/instantiate_connection.hpp" +#include "libtorrent/assert.hpp" using namespace libtorrent; using boost::tuples::tuple; @@ -203,9 +204,6 @@ namespace libtorrent , m_num_uploads(0) , m_max_connections((std::numeric_limits::max)()) { -#ifndef NDEBUG - m_initial_done = 0; -#endif m_policy.reset(new policy(this)); } @@ -266,10 +264,6 @@ namespace libtorrent , m_num_uploads(0) , m_max_connections((std::numeric_limits::max)()) { -#ifndef NDEBUG - m_initial_done = 0; -#endif - INVARIANT_CHECK; if (name) m_name.reset(new std::string(name)); @@ -2215,14 +2209,12 @@ namespace libtorrent } pause(); } -#ifndef NDEBUG - m_initial_done = boost::get<0>(bytes_done()); -#endif return done; } std::pair torrent::check_files() { + assert(m_torrent_file->is_valid()); INVARIANT_CHECK; assert(m_owning_storage.get()); @@ -2250,9 +2242,6 @@ namespace libtorrent pause(); } -#ifndef NDEBUG - m_initial_done = boost::get<0>(bytes_done()); -#endif return progress; } @@ -2261,6 +2250,7 @@ namespace libtorrent { session_impl::mutex_t::scoped_lock l(m_ses.m_mutex); + assert(m_torrent_file->is_valid()); INVARIANT_CHECK; if (!is_seed()) @@ -2320,9 +2310,6 @@ namespace libtorrent } } } -#ifndef NDEBUG - m_initial_done = boost::get<0>(bytes_done()); -#endif } alert_manager& torrent::alerts() const @@ -2385,9 +2372,6 @@ namespace libtorrent #ifndef NDEBUG void torrent::check_invariant() const { -// size_type download = m_stat.total_payload_download(); -// size_type done = boost::get<0>(bytes_done()); -// assert(download >= done - m_initial_done); int num_uploads = 0; std::map num_requests; for (const_peer_iterator i = begin(); i != end(); ++i) diff --git a/libtorrent/src/upnp.cpp b/libtorrent/src/upnp.cpp index e16c136bb..995897ad5 100644 --- a/libtorrent/src/upnp.cpp +++ b/libtorrent/src/upnp.cpp @@ -53,38 +53,10 @@ POSSIBILITY OF SUCH DAMAGE. using boost::bind; using namespace libtorrent; -address_v4 upnp::upnp_multicast_address; -udp::endpoint upnp::upnp_multicast_endpoint; - namespace libtorrent { - bool is_local(address const& a) - { - if (a.is_v6()) return false; - address_v4 a4 = a.to_v4(); - 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) - { - // make a best guess of the interface we're using and its IP - udp::resolver r(ios); - udp::resolver::iterator i = r.resolve(udp::resolver::query(asio::ip::host_name(), "0")); - for (;i != udp::resolver_iterator(); ++i) - { - // ignore the loopback - if (i->endpoint().address() == address_v4((127 << 24) + 1)) continue; - // ignore addresses that are not on a local network - if (!is_local(i->endpoint().address())) continue; - // ignore non-IPv4 addresses - if (i->endpoint().address().is_v4()) break; - } - if (i == udp::resolver_iterator()) return address_v4::any(); - return i->endpoint().address().to_v4(); - } + bool is_local(address const& a); + address_v4 guess_local_address(asio::io_service&); } upnp::upnp(io_service& ios, connection_queue& cc @@ -95,89 +67,27 @@ upnp::upnp(io_service& ios, connection_queue& cc , m_user_agent(user_agent) , m_callback(cb) , m_retry_count(0) - , m_socket(ios) + , m_io_service(ios) + , m_strand(ios) + , m_socket(ios, udp::endpoint(address_v4::from_string("239.255.255.250"), 1900) + , m_strand.wrap(bind(&upnp::on_reply, this, _1, _2, _3))) , m_broadcast_timer(ios) , m_refresh_timer(ios) - , m_strand(ios) , m_disabled(false) , m_closing(false) , m_cc(cc) { - // UPnP multicast address and port - upnp_multicast_address = address_v4::from_string("239.255.255.250"); - upnp_multicast_endpoint = udp::endpoint(upnp_multicast_address, 1900); - #ifdef TORRENT_UPNP_LOGGING m_log.open("upnp.log", std::ios::in | std::ios::out | std::ios::trunc); #endif - rebind(listen_interface); + m_retry_count = 0; + discover_device(); } upnp::~upnp() { } -void upnp::rebind(address const& listen_interface) try -{ - address_v4 bind_to = address_v4::any(); - if (listen_interface.is_v4() && listen_interface != address_v4::any()) - { - m_local_ip = listen_interface.to_v4(); - bind_to = listen_interface.to_v4(); - if (!is_local(m_local_ip)) - { - // the local address seems to be an external - // internet address. Assume it is not behind a NAT - throw std::runtime_error("local IP is not on a local network"); - } - } - else - { - m_local_ip = guess_local_address(m_socket.io_service()); - bind_to = address_v4::any(); - } - - if (!is_local(m_local_ip)) - { - throw std::runtime_error("local host is probably not on a NATed " - "network. disabling UPnP"); - } - -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " local ip: " << m_local_ip.to_string() - << " bind to: " << bind_to.to_string() << std::endl; -#endif - - // the local interface hasn't changed - if (m_socket.is_open() - && m_socket.local_endpoint().address() == m_local_ip) - return; - - m_socket.close(); - - using namespace asio::ip::multicast; - - m_socket.open(udp::v4()); - m_socket.set_option(datagram_socket::reuse_address(true)); - m_socket.bind(udp::endpoint(bind_to, 0)); - - m_socket.set_option(join_group(upnp_multicast_address)); - m_socket.set_option(outbound_interface(bind_to)); - m_socket.set_option(hops(255)); - m_disabled = false; - - m_retry_count = 0; - discover_device(); -} -catch (std::exception& e) -{ - disable(); - std::stringstream msg; - msg << "UPnP portmapping disabled: " << e.what(); - m_callback(0, 0, msg.str()); -}; - void upnp::discover_device() try { const char msearch[] = @@ -188,20 +98,20 @@ void upnp::discover_device() try "MX:3\r\n" "\r\n\r\n"; - m_socket.async_receive_from(asio::buffer(m_receive_buffer - , sizeof(m_receive_buffer)), m_remote, m_strand.wrap(bind( - &upnp::on_reply, this, _1, _2))); - asio::error_code ec; #ifdef TORRENT_DEBUG_UPNP // simulate packet loss if (m_retry_count & 1) #endif - m_socket.send_to(asio::buffer(msearch, sizeof(msearch) - 1) - , upnp_multicast_endpoint, 0, ec); + m_socket.send(msearch, sizeof(msearch) - 1, ec); if (ec) { +#ifdef TORRENT_UPNP_LOGGING + m_log << time_now_string() + << " ==> Broadcast FAILED: " << ec.message() << std::endl + << "aborting" << std::endl; +#endif disable(); return; } @@ -292,7 +202,7 @@ try rootdevice& d = const_cast(*i); try { - d.upnp_connection.reset(new http_connection(m_socket.io_service() + d.upnp_connection.reset(new http_connection(m_io_service , m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, this, _1, _2 , boost::ref(d))))); d.upnp_connection->get(d.url); @@ -316,20 +226,13 @@ catch (std::exception&) } #endif -void upnp::on_reply(asio::error_code const& e +void upnp::on_reply(udp::endpoint const& from, char* buffer , std::size_t bytes_transferred) #ifndef NDEBUG try #endif { using namespace libtorrent::detail; - if (e) - { -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() << " *** on_reply aborted: " << e.message() << std::endl; -#endif - return; - } // parse out the url for the device @@ -348,15 +251,14 @@ try http_parser p; try { - p.incoming(buffer::const_interval(m_receive_buffer - , m_receive_buffer + bytes_transferred)); + p.incoming(buffer::const_interval(buffer + , buffer + bytes_transferred)); } catch (std::exception& e) { #ifdef TORRENT_UPNP_LOGGING m_log << time_now_string() - << " <== Rootdevice responded with incorrect HTTP packet: " - << e.what() << ". Ignoring device" << std::endl; + << " <== Rootdevice responded with incorrect HTTP packet. Ignoring device" << std::endl; #endif return; } @@ -469,7 +371,7 @@ try rootdevice& d = const_cast(*i); try { - d.upnp_connection.reset(new http_connection(m_socket.io_service() + d.upnp_connection.reset(new http_connection(m_io_service , m_cc, m_strand.wrap(bind(&upnp::on_upnp_xml, this, _1, _2 , boost::ref(d))))); d.upnp_connection->get(d.url); @@ -494,7 +396,7 @@ catch (std::exception&) }; #endif -void upnp::post(rootdevice& d, std::stringstream const& soap +void upnp::post(upnp::rootdevice const& d, std::string const& soap , std::string const& soap_action) { std::stringstream header; @@ -502,12 +404,40 @@ void upnp::post(rootdevice& d, std::stringstream const& soap header << "POST " << d.control_url << " HTTP/1.1\r\n" "Host: " << d.hostname << ":" << d.port << "\r\n" "Content-Type: text/xml; charset=\"utf-8\"\r\n" - "Content-Length: " << soap.str().size() << "\r\n" - "Soapaction: \"" << d.service_namespace << "#" << soap_action << "\"\r\n\r\n" << soap.str(); + "Content-Length: " << soap.size() << "\r\n" + "Soapaction: \"" << d.service_namespace << "#" << soap_action << "\"\r\n\r\n" << soap; d.upnp_connection->sendbuffer = header.str(); - d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) - , seconds(10)); + +#ifdef TORRENT_UPNP_LOGGING + m_log << time_now_string() + << " ==> sending: " << soap << std::endl; +#endif + +} + +void upnp::create_port_mapping(http_connection& c, rootdevice& d, int i) +{ + std::string soap_action = "AddPortMapping"; + + std::stringstream soap; + + soap << "\n" + "" + ""; + + soap << "" + "" << d.mapping[i].external_port << "" + "" << (d.mapping[i].protocol ? "UDP" : "TCP") << "" + "" << d.mapping[i].local_port << "" + "" << c.socket().local_endpoint().address().to_string() << "" + "1" + "" << m_user_agent << "" + "" << d.lease_duration << ""; + soap << ""; + + post(d, soap.str(), soap_action); } void upnp::map_port(rootdevice& d, int i) @@ -528,14 +458,21 @@ void upnp::map_port(rootdevice& d, int i) assert(!d.upnp_connection); assert(d.service_namespace); - d.upnp_connection.reset(new http_connection(m_socket.io_service() + d.upnp_connection.reset(new http_connection(m_io_service , m_cc, m_strand.wrap(bind(&upnp::on_upnp_map_response, this, _1, _2 - , boost::ref(d), i)))); + , boost::ref(d), i)), true + , bind(&upnp::create_port_mapping, this, _1, boost::ref(d), i))); - std::string soap_action = "AddPortMapping"; + d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) + , seconds(10)); +} +void upnp::delete_port_mapping(rootdevice& d, int i) +{ std::stringstream soap; + std::string soap_action = "DeletePortMapping"; + soap << "\n" "" @@ -543,20 +480,10 @@ void upnp::map_port(rootdevice& d, int i) soap << "" "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol ? "UDP" : "TCP") << "" - "" << d.mapping[i].local_port << "" - "" << m_local_ip.to_string() << "" - "1" - "" << m_user_agent << "" - "" << d.lease_duration << ""; + "" << (d.mapping[i].protocol ? "UDP" : "TCP") << ""; soap << ""; - - post(d, soap, soap_action); -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> AddPortMapping: " << soap.str() << std::endl; -#endif + post(d, soap.str(), soap_action); } // requires the mutex to be locked @@ -574,29 +501,13 @@ void upnp::unmap_port(rootdevice& d, int i) } return; } - d.upnp_connection.reset(new http_connection(m_socket.io_service() + d.upnp_connection.reset(new http_connection(m_io_service , m_cc, m_strand.wrap(bind(&upnp::on_upnp_unmap_response, this, _1, _2 - , boost::ref(d), i)))); + , boost::ref(d), i)), true + , bind(&upnp::delete_port_mapping, this, boost::ref(d), i))); - std::string soap_action = "DeletePortMapping"; - - std::stringstream soap; - - soap << "\n" - "" - ""; - - soap << "" - "" << d.mapping[i].external_port << "" - "" << (d.mapping[i].protocol ? "UDP" : "TCP") << ""; - soap << ""; - - post(d, soap, soap_action); -#ifdef TORRENT_UPNP_LOGGING - m_log << time_now_string() - << " ==> DeletePortMapping: " << soap.str() << std::endl; -#endif + d.upnp_connection->start(d.hostname, boost::lexical_cast(d.port) + , seconds(10)); } namespace