libtorrent various fixes including upnp
This commit is contained in:
parent
47e47ac9cc
commit
02720ddcd9
|
@ -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
|
||||
{
|
||||
|
|
|
@ -30,9 +30,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
*/
|
||||
|
||||
#ifndef TORRENT_ASSERT_HPP_INCLUDED
|
||||
#define TORRENT_ASSERT_HPP_INCLUDED
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <boost/shared_ptr.hpp>
|
||||
#include <boost/intrusive_ptr.hpp>
|
||||
#include <boost/function.hpp>
|
||||
|
@ -44,6 +41,10 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <boost/thread/mutex.hpp>
|
||||
#include <deque>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -34,8 +34,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
//#define TORRENT_BUFFER_DEBUG
|
||||
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
#include <memory>
|
||||
#include "libtorrent/invariant_check.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent {
|
||||
|
||||
|
|
|
@ -37,6 +37,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <sstream>
|
||||
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -91,3 +92,4 @@ namespace libtorrent
|
|||
}
|
||||
|
||||
#endif // TORRENT_FINGERPRINT_HPP_INCLUDED
|
||||
|
||||
|
|
|
@ -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<void(asio::error_code const&
|
||||
, http_parser const&, char const* data, int size)> http_handler;
|
||||
|
||||
typedef boost::function<void(http_connection&)> http_connect_handler;
|
||||
|
||||
// TODO: add bind interface
|
||||
|
||||
// when bottled, the last two arguments to the handler
|
||||
|
@ -58,11 +63,13 @@ typedef boost::function<void(asio::error_code const&
|
|||
struct http_connection : boost::enable_shared_from_this<http_connection>, 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<http_connection>, 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;
|
||||
|
|
|
@ -33,6 +33,9 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#ifndef TORRENT_IP_FILTER_HPP
|
||||
#define TORRENT_IP_FILTER_HPP
|
||||
|
||||
#include <set>
|
||||
#include <iostream>
|
||||
|
||||
#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 <set>
|
||||
#include <iostream>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
|
|
@ -50,6 +50,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <libtorrent/kademlia/node_entry.hpp>
|
||||
#include <libtorrent/session_settings.hpp>
|
||||
#include <libtorrent/size_type.hpp>
|
||||
#include <libtorrent/assert.hpp>
|
||||
|
||||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/peer_id.hpp"
|
||||
#include "libtorrent/broadcast_socket.hpp"
|
||||
|
||||
#include <boost/function.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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<piece_block> const& picked
|
||||
, std::vector<bool> 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<bool> const& bitmask) const;
|
||||
std::pair<int, int> expand_piece(int piece, int whole_pieces
|
||||
, std::vector<bool> const& have) const;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -55,6 +55,7 @@ namespace libtorrent
|
|||
|| _POSIX_MONOTONIC_CLOCK < 0)) || defined (TORRENT_USE_BOOST_DATE_TIME)
|
||||
|
||||
#include <boost/date_time/posix_time/posix_time_types.hpp>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -85,6 +86,7 @@ namespace libtorrent
|
|||
|
||||
#include <asio/time_traits.hpp>
|
||||
#include <boost/cstdint.hpp>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -170,6 +172,7 @@ namespace asio
|
|||
|
||||
#include <mach/mach_time.h>
|
||||
#include <boost/cstdint.hpp>
|
||||
#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 <Windows.h>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -335,6 +339,7 @@ namespace libtorrent
|
|||
#elif defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
|
||||
|
||||
#include <time.h>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -385,4 +390,4 @@ namespace libtorrent
|
|||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<entry> timed_out;
|
||||
for (std::list<entry>::iterator i = m_queue.begin();
|
||||
!m_queue.empty() && i != m_queue.end();)
|
||||
{
|
||||
if (i->connecting && i->expires < now)
|
||||
{
|
||||
boost::function<void()> on_timeout = i->on_timeout;
|
||||
m_queue.erase(i++);
|
||||
std::list<entry>::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<entry>::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);
|
||||
|
|
|
@ -31,7 +31,6 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
*/
|
||||
|
||||
#include "libtorrent/pch.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
@ -40,6 +39,8 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <cctype>
|
||||
#include <algorithm>
|
||||
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
std::string unescape_string(std::string const& s)
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include <libtorrent/kademlia/closest_nodes.hpp>
|
||||
#include <libtorrent/kademlia/routing_table.hpp>
|
||||
#include <libtorrent/kademlia/rpc_manager.hpp>
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent { namespace dht
|
||||
{
|
||||
|
|
|
@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/lsd.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/http_tracker_connection.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/ref.hpp>
|
||||
#include <asio/ip/host_name.hpp>
|
||||
|
@ -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();
|
||||
|
|
|
@ -32,11 +32,13 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
|
||||
#include "libtorrent/pch.hpp"
|
||||
|
||||
#include <libtorrent/natpmp.hpp>
|
||||
#include <libtorrent/io.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <asio/ip/host_name.hpp>
|
||||
|
||||
#include "libtorrent/natpmp.hpp"
|
||||
#include "libtorrent/io.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
using boost::bind;
|
||||
using namespace libtorrent;
|
||||
|
||||
|
|
|
@ -263,8 +263,23 @@ namespace libtorrent
|
|||
}
|
||||
m_downloads.erase(i);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
void piece_picker::verify_pick(std::vector<piece_block> const& picked
|
||||
, std::vector<bool> const& bitfield) const
|
||||
{
|
||||
assert(bitfield.size() == m_piece_map.size());
|
||||
for (std::vector<piece_block>::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<int>::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<bool> 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<block_info>::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<downloading_piece>::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<downloading_piece>::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);
|
||||
}
|
||||
|
|
|
@ -1535,4 +1535,3 @@ namespace libtorrent
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ namespace libtorrent
|
|||
, bool paused
|
||||
, storage_constructor_type sc)
|
||||
{
|
||||
assert(!ti.m_half_metadata);
|
||||
boost::intrusive_ptr<torrent_info> 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);
|
||||
|
|
|
@ -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<peer_connection> 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())
|
||||
|
|
|
@ -33,6 +33,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
|||
#include "libtorrent/pch.hpp"
|
||||
|
||||
#include "libtorrent/socks5_stream.hpp"
|
||||
#include "libtorrent/assert.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
|
|
@ -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<int>::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<int>::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<bool, float> 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<piece_block, int> num_requests;
|
||||
for (const_peer_iterator i = begin(); i != end(); ++i)
|
||||
|
|
|
@ -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<rootdevice&>(*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<rootdevice&>(*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<std::string>(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 << "<?xml version=\"1.0\"?>\n"
|
||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body><u:" << soap_action << " xmlns:u=\"" << d.service_namespace << "\">";
|
||||
|
||||
soap << "<NewRemoteHost></NewRemoteHost>"
|
||||
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
|
||||
"<NewProtocol>" << (d.mapping[i].protocol ? "UDP" : "TCP") << "</NewProtocol>"
|
||||
"<NewInternalPort>" << d.mapping[i].local_port << "</NewInternalPort>"
|
||||
"<NewInternalClient>" << c.socket().local_endpoint().address().to_string() << "</NewInternalClient>"
|
||||
"<NewEnabled>1</NewEnabled>"
|
||||
"<NewPortMappingDescription>" << m_user_agent << "</NewPortMappingDescription>"
|
||||
"<NewLeaseDuration>" << d.lease_duration << "</NewLeaseDuration>";
|
||||
soap << "</u:" << soap_action << "></s:Body></s:Envelope>";
|
||||
|
||||
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<std::string>(d.port)
|
||||
, seconds(10));
|
||||
}
|
||||
|
||||
void upnp::delete_port_mapping(rootdevice& d, int i)
|
||||
{
|
||||
std::stringstream soap;
|
||||
|
||||
std::string soap_action = "DeletePortMapping";
|
||||
|
||||
soap << "<?xml version=\"1.0\"?>\n"
|
||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
|
@ -543,20 +480,10 @@ void upnp::map_port(rootdevice& d, int i)
|
|||
|
||||
soap << "<NewRemoteHost></NewRemoteHost>"
|
||||
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
|
||||
"<NewProtocol>" << (d.mapping[i].protocol ? "UDP" : "TCP") << "</NewProtocol>"
|
||||
"<NewInternalPort>" << d.mapping[i].local_port << "</NewInternalPort>"
|
||||
"<NewInternalClient>" << m_local_ip.to_string() << "</NewInternalClient>"
|
||||
"<NewEnabled>1</NewEnabled>"
|
||||
"<NewPortMappingDescription>" << m_user_agent << "</NewPortMappingDescription>"
|
||||
"<NewLeaseDuration>" << d.lease_duration << "</NewLeaseDuration>";
|
||||
"<NewProtocol>" << (d.mapping[i].protocol ? "UDP" : "TCP") << "</NewProtocol>";
|
||||
soap << "</u:" << soap_action << "></s:Body></s:Envelope>";
|
||||
|
||||
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 << "<?xml version=\"1.0\"?>\n"
|
||||
"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" "
|
||||
"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">"
|
||||
"<s:Body><u:" << soap_action << " xmlns:u=\"" << d.service_namespace << "\">";
|
||||
|
||||
soap << "<NewRemoteHost></NewRemoteHost>"
|
||||
"<NewExternalPort>" << d.mapping[i].external_port << "</NewExternalPort>"
|
||||
"<NewProtocol>" << (d.mapping[i].protocol ? "UDP" : "TCP") << "</NewProtocol>";
|
||||
soap << "</u:" << soap_action << "></s:Body></s:Envelope>";
|
||||
|
||||
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<std::string>(d.port)
|
||||
, seconds(10));
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
Loading…
Reference in New Issue