use bind_to_device for listen sockets
This commit is contained in:
parent
6d77000ab0
commit
72a24b63ba
|
@ -17,6 +17,7 @@ nobase_include_HEADERS = \
|
||||||
bandwidth_queue_entry.hpp \
|
bandwidth_queue_entry.hpp \
|
||||||
bencode.hpp \
|
bencode.hpp \
|
||||||
bdecode.hpp \
|
bdecode.hpp \
|
||||||
|
bind_to_device.hpp \
|
||||||
bitfield.hpp \
|
bitfield.hpp \
|
||||||
block_cache.hpp \
|
block_cache.hpp \
|
||||||
bloom_filter.hpp \
|
bloom_filter.hpp \
|
||||||
|
|
|
@ -1286,7 +1286,7 @@ namespace libtorrent
|
||||||
|
|
||||||
enum op_t
|
enum op_t
|
||||||
{
|
{
|
||||||
parse_addr, open, bind, listen, get_socket_name, accept, enum_if
|
parse_addr, open, bind, listen, get_socket_name, accept, enum_if, bind_to_device
|
||||||
};
|
};
|
||||||
|
|
||||||
// the specific low level operation that failed. See op_t.
|
// the specific low level operation that failed. See op_t.
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Copyright (c) 2016, 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_BIND_TO_DEVICE_HPP_INCLUDED
|
||||||
|
#define TORRENT_BIND_TO_DEVICE_HPP_INCLUDED
|
||||||
|
|
||||||
|
#include "libtorrent/config.hpp"
|
||||||
|
#include "libtorrent/socket.hpp"
|
||||||
|
|
||||||
|
#if TORRENT_USE_IFCONF || TORRENT_USE_NETLINK || TORRENT_USE_SYSCTL
|
||||||
|
#include <sys/socket.h> // for SO_BINDTODEVICE
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace libtorrent { namespace aux {
|
||||||
|
|
||||||
|
#if defined SO_BINDTODEVICE
|
||||||
|
|
||||||
|
struct bind_to_device
|
||||||
|
{
|
||||||
|
bind_to_device(char const* device): m_value(device) {}
|
||||||
|
template<class Protocol>
|
||||||
|
int level(Protocol const&) const { return SOL_SOCKET; }
|
||||||
|
template<class Protocol>
|
||||||
|
int name(Protocol const&) const { return SO_BINDTODEVICE; }
|
||||||
|
template<class Protocol>
|
||||||
|
char const* data(Protocol const&) const { return m_value; }
|
||||||
|
template<class Protocol>
|
||||||
|
size_t size(Protocol const&) const { return strlen(m_value) + 1; }
|
||||||
|
private:
|
||||||
|
char const* m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TORRENT_HAS_BINDTODEVICE 1
|
||||||
|
|
||||||
|
#elif defined IP_BOUND_IF
|
||||||
|
|
||||||
|
struct bind_to_device
|
||||||
|
{
|
||||||
|
bind_to_device(char const* device): m_value(if_nametoindex(device)) {}
|
||||||
|
template<class Protocol>
|
||||||
|
int level(Protocol const&) const { return IPPROTO_IP; }
|
||||||
|
template<class Protocol>
|
||||||
|
int name(Protocol const&) const { return IP_BOUND_IF; }
|
||||||
|
template<class Protocol>
|
||||||
|
char const* data(Protocol const&) const { return reinterpret_cast<char const*>(&m_value); }
|
||||||
|
template<class Protocol>
|
||||||
|
size_t size(Protocol const&) const { return sizeof(m_value); }
|
||||||
|
private:
|
||||||
|
unsigned int m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TORRENT_HAS_BINDTODEVICE 1
|
||||||
|
|
||||||
|
#elif defined IP_FORCE_OUT_IFP
|
||||||
|
|
||||||
|
struct bind_to_device
|
||||||
|
{
|
||||||
|
bind_to_device(char const* device): m_value(device) {}
|
||||||
|
template<class Protocol>
|
||||||
|
int level(Protocol const&) const { return SOL_SOCKET; }
|
||||||
|
template<class Protocol>
|
||||||
|
int name(Protocol const&) const { return IP_FORCE_OUT_IFP; }
|
||||||
|
template<class Protocol>
|
||||||
|
char const* data(Protocol const&) const { return m_value; }
|
||||||
|
template<class Protocol>
|
||||||
|
size_t size(Protocol const&) const { return strlen(m_value) + 1; }
|
||||||
|
private:
|
||||||
|
char const* m_value;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TORRENT_HAS_BINDTODEVICE 1
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define TORRENT_HAS_BINDTODEVICE 0
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -49,6 +49,7 @@ POSSIBILITY OF SUCH DAMAGE.
|
||||||
#include "libtorrent/address.hpp"
|
#include "libtorrent/address.hpp"
|
||||||
#include "libtorrent/error_code.hpp"
|
#include "libtorrent/error_code.hpp"
|
||||||
#include "libtorrent/socket.hpp"
|
#include "libtorrent/socket.hpp"
|
||||||
|
#include "libtorrent/aux_/bind_to_device.hpp"
|
||||||
|
|
||||||
namespace libtorrent
|
namespace libtorrent
|
||||||
{
|
{
|
||||||
|
@ -93,22 +94,6 @@ namespace libtorrent
|
||||||
|
|
||||||
TORRENT_EXTRA_EXPORT address get_default_gateway(io_service& ios, error_code& ec);
|
TORRENT_EXTRA_EXPORT address get_default_gateway(io_service& ios, error_code& ec);
|
||||||
|
|
||||||
#ifdef SO_BINDTODEVICE
|
|
||||||
struct bind_to_device_opt
|
|
||||||
{
|
|
||||||
bind_to_device_opt(char const* device): m_value(device) {}
|
|
||||||
template<class Protocol>
|
|
||||||
int level(Protocol const&) const { return SOL_SOCKET; }
|
|
||||||
template<class Protocol>
|
|
||||||
int name(Protocol const&) const { return SO_BINDTODEVICE; }
|
|
||||||
template<class Protocol>
|
|
||||||
const char* data(Protocol const&) const { return m_value; }
|
|
||||||
template<class Protocol>
|
|
||||||
size_t size(Protocol const&) const { return IFNAMSIZ; }
|
|
||||||
char const* m_value;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// attempt to bind socket to the device with the specified name. For systems
|
// attempt to bind socket to the device with the specified name. For systems
|
||||||
// that don't support SO_BINDTODEVICE the socket will be bound to one of the
|
// that don't support SO_BINDTODEVICE the socket will be bound to one of the
|
||||||
// IP addresses of the specified device. In this case it is necessary to
|
// IP addresses of the specified device. In this case it is necessary to
|
||||||
|
@ -116,7 +101,7 @@ namespace libtorrent
|
||||||
// the returned address is the ip the socket was bound to (or address_v4::any()
|
// the returned address is the ip the socket was bound to (or address_v4::any()
|
||||||
// in case SO_BINDTODEVICE succeeded and we don't need to verify it).
|
// in case SO_BINDTODEVICE succeeded and we don't need to verify it).
|
||||||
template <class Socket>
|
template <class Socket>
|
||||||
address bind_to_device(io_service& ios, Socket& sock
|
address bind_socket_to_device(io_service& ios, Socket& sock
|
||||||
, boost::asio::ip::tcp const& protocol
|
, boost::asio::ip::tcp const& protocol
|
||||||
, char const* device_name, int port, error_code& ec)
|
, char const* device_name, int port, error_code& ec)
|
||||||
{
|
{
|
||||||
|
@ -140,10 +125,10 @@ namespace libtorrent
|
||||||
|
|
||||||
ec.clear();
|
ec.clear();
|
||||||
|
|
||||||
#ifdef SO_BINDTODEVICE
|
#if TORRENT_HAS_BINDTODEVICE
|
||||||
// try to use SO_BINDTODEVICE here, if that exists. If it fails,
|
// try to use SO_BINDTODEVICE here, if that exists. If it fails,
|
||||||
// fall back to the mechanism we have below
|
// fall back to the mechanism we have below
|
||||||
sock.set_option(bind_to_device_opt(device_name), ec);
|
sock.set_option(aux::bind_to_device(device_name), ec);
|
||||||
if (ec)
|
if (ec)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
|
|
@ -818,7 +818,8 @@ namespace libtorrent {
|
||||||
"listen",
|
"listen",
|
||||||
"get_socket_name",
|
"get_socket_name",
|
||||||
"accept",
|
"accept",
|
||||||
"enum_if"
|
"enum_if",
|
||||||
|
"bind_to_device"
|
||||||
};
|
};
|
||||||
char ret[300];
|
char ret[300];
|
||||||
snprintf(ret, sizeof(ret), "listening on %s (device: %s) failed: [%s] [%s] %s"
|
snprintf(ret, sizeof(ret), "listening on %s (device: %s) failed: [%s] [%s] %s"
|
||||||
|
|
|
@ -117,6 +117,7 @@ const rlim_t rlim_infinity = RLIM_INFINITY;
|
||||||
#include "libtorrent/choker.hpp"
|
#include "libtorrent/choker.hpp"
|
||||||
#include "libtorrent/error.hpp"
|
#include "libtorrent/error.hpp"
|
||||||
#include "libtorrent/platform_util.hpp"
|
#include "libtorrent/platform_util.hpp"
|
||||||
|
#include "libtorrent/aux_/bind_to_device.hpp"
|
||||||
|
|
||||||
#ifndef TORRENT_DISABLE_LOGGING
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
|
||||||
|
@ -1737,6 +1738,30 @@ namespace aux {
|
||||||
}
|
}
|
||||||
#endif // TORRENT_USE_IPV6
|
#endif // TORRENT_USE_IPV6
|
||||||
|
|
||||||
|
if (!device.empty())
|
||||||
|
{
|
||||||
|
// we have an actual device we're interested in listening on, if we
|
||||||
|
// have SO_BINDTODEVICE functionality, use it now.
|
||||||
|
#if TORRENT_HAS_BINDTODEVICE
|
||||||
|
ret.sock->set_option(bind_to_device(device.c_str()), ec);
|
||||||
|
if (ec)
|
||||||
|
{
|
||||||
|
#ifndef TORRENT_DISABLE_LOGGING
|
||||||
|
session_log("bind to device failed (device: %s): %s"
|
||||||
|
, device.c_str(), ec.message().c_str());
|
||||||
|
#endif // TORRENT_DISABLE_LOGGING
|
||||||
|
|
||||||
|
last_op = listen_failed_alert::bind_to_device;
|
||||||
|
if (m_alerts.should_post<listen_failed_alert>())
|
||||||
|
{
|
||||||
|
m_alerts.emplace_alert<listen_failed_alert>(device, bind_ep
|
||||||
|
, last_op, ec, sock_type);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
ret.sock->bind(bind_ep, ec);
|
ret.sock->bind(bind_ep, ec);
|
||||||
last_op = listen_failed_alert::bind;
|
last_op = listen_failed_alert::bind;
|
||||||
|
|
||||||
|
@ -1876,7 +1901,7 @@ namespace aux {
|
||||||
address adr = address::from_string(device.c_str(), err);
|
address adr = address::from_string(device.c_str(), err);
|
||||||
if (!err)
|
if (!err)
|
||||||
{
|
{
|
||||||
listen_socket_t s = setup_listener(device, tcp::endpoint(adr, port)
|
listen_socket_t s = setup_listener("", tcp::endpoint(adr, port)
|
||||||
, flags | (ssl ? open_ssl_socket : 0), ec);
|
, flags | (ssl ? open_ssl_socket : 0), ec);
|
||||||
|
|
||||||
if (!ec && s.sock)
|
if (!ec && s.sock)
|
||||||
|
@ -4910,7 +4935,7 @@ namespace aux {
|
||||||
|
|
||||||
if (ec) return bind_ep;
|
if (ec) return bind_ep;
|
||||||
|
|
||||||
bind_ep.address(bind_to_device(m_io_service, s
|
bind_ep.address(bind_socket_to_device(m_io_service, s
|
||||||
, remote_address.is_v4()
|
, remote_address.is_v4()
|
||||||
? boost::asio::ip::tcp::v4()
|
? boost::asio::ip::tcp::v4()
|
||||||
: boost::asio::ip::tcp::v6()
|
: boost::asio::ip::tcp::v6()
|
||||||
|
|
|
@ -177,6 +177,7 @@ namespace libtorrent
|
||||||
{
|
{
|
||||||
if (i != in.begin()) ret += ",";
|
if (i != in.begin()) ret += ",";
|
||||||
|
|
||||||
|
#if TORRENT_USE_IPV6
|
||||||
error_code ec;
|
error_code ec;
|
||||||
address_v6::from_string(i->device, ec);
|
address_v6::from_string(i->device, ec);
|
||||||
if (!ec)
|
if (!ec)
|
||||||
|
@ -187,6 +188,7 @@ namespace libtorrent
|
||||||
ret += "]";
|
ret += "]";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
ret += i->device;
|
ret += i->device;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue