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 \
|
||||
bencode.hpp \
|
||||
bdecode.hpp \
|
||||
bind_to_device.hpp \
|
||||
bitfield.hpp \
|
||||
block_cache.hpp \
|
||||
bloom_filter.hpp \
|
||||
|
|
|
@ -1286,7 +1286,7 @@ namespace libtorrent
|
|||
|
||||
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.
|
||||
|
|
|
@ -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/error_code.hpp"
|
||||
#include "libtorrent/socket.hpp"
|
||||
#include "libtorrent/aux_/bind_to_device.hpp"
|
||||
|
||||
namespace libtorrent
|
||||
{
|
||||
|
@ -93,22 +94,6 @@ namespace libtorrent
|
|||
|
||||
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
|
||||
// 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
|
||||
|
@ -116,7 +101,7 @@ namespace libtorrent
|
|||
// 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).
|
||||
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
|
||||
, char const* device_name, int port, error_code& ec)
|
||||
{
|
||||
|
@ -140,10 +125,10 @@ namespace libtorrent
|
|||
|
||||
ec.clear();
|
||||
|
||||
#ifdef SO_BINDTODEVICE
|
||||
#if TORRENT_HAS_BINDTODEVICE
|
||||
// try to use SO_BINDTODEVICE here, if that exists. If it fails,
|
||||
// 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)
|
||||
#endif
|
||||
{
|
||||
|
|
|
@ -818,7 +818,8 @@ namespace libtorrent {
|
|||
"listen",
|
||||
"get_socket_name",
|
||||
"accept",
|
||||
"enum_if"
|
||||
"enum_if",
|
||||
"bind_to_device"
|
||||
};
|
||||
char ret[300];
|
||||
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/error.hpp"
|
||||
#include "libtorrent/platform_util.hpp"
|
||||
#include "libtorrent/aux_/bind_to_device.hpp"
|
||||
|
||||
#ifndef TORRENT_DISABLE_LOGGING
|
||||
|
||||
|
@ -1737,6 +1738,30 @@ namespace aux {
|
|||
}
|
||||
#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);
|
||||
last_op = listen_failed_alert::bind;
|
||||
|
||||
|
@ -1876,7 +1901,7 @@ namespace aux {
|
|||
address adr = address::from_string(device.c_str(), 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);
|
||||
|
||||
if (!ec && s.sock)
|
||||
|
@ -4910,7 +4935,7 @@ namespace aux {
|
|||
|
||||
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()
|
||||
? boost::asio::ip::tcp::v4()
|
||||
: boost::asio::ip::tcp::v6()
|
||||
|
|
|
@ -177,6 +177,7 @@ namespace libtorrent
|
|||
{
|
||||
if (i != in.begin()) ret += ",";
|
||||
|
||||
#if TORRENT_USE_IPV6
|
||||
error_code ec;
|
||||
address_v6::from_string(i->device, ec);
|
||||
if (!ec)
|
||||
|
@ -187,6 +188,7 @@ namespace libtorrent
|
|||
ret += "]";
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret += i->device;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue