2007-12-09 05:15:24 +01:00
|
|
|
/*
|
|
|
|
|
2016-01-18 00:57:46 +01:00
|
|
|
Copyright (c) 2007-2016, Arvid Norberg
|
2007-12-09 05:15:24 +01:00
|
|
|
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_UDP_SOCKET_HPP_INCLUDED
|
|
|
|
#define TORRENT_UDP_SOCKET_HPP_INCLUDED
|
|
|
|
|
|
|
|
#include "libtorrent/socket.hpp"
|
2009-11-23 09:38:50 +01:00
|
|
|
#include "libtorrent/io_service.hpp"
|
2009-09-16 05:46:36 +02:00
|
|
|
#include "libtorrent/error_code.hpp"
|
2007-12-09 05:15:24 +01:00
|
|
|
#include "libtorrent/session_settings.hpp"
|
2008-11-08 18:40:06 +01:00
|
|
|
#include "libtorrent/buffer.hpp"
|
2009-10-20 04:49:56 +02:00
|
|
|
#include "libtorrent/thread.hpp"
|
2009-09-16 05:46:36 +02:00
|
|
|
#include "libtorrent/deadline_timer.hpp"
|
2014-07-06 21:18:00 +02:00
|
|
|
#include "libtorrent/debug.hpp"
|
2015-11-25 22:36:06 +01:00
|
|
|
#include "libtorrent/aux_/allocating_handler.hpp"
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2011-03-14 08:23:32 +01:00
|
|
|
#include <deque>
|
2007-12-09 05:15:24 +01:00
|
|
|
|
|
|
|
namespace libtorrent
|
|
|
|
{
|
2015-11-19 01:51:17 +01:00
|
|
|
struct TORRENT_EXTRA_EXPORT udp_socket_observer
|
2012-06-22 06:21:20 +02:00
|
|
|
{
|
|
|
|
// return true if the packet was handled (it won't be
|
|
|
|
// propagated to the next observer)
|
|
|
|
virtual bool incoming_packet(error_code const& ec
|
|
|
|
, udp::endpoint const&, char const* buf, int size) = 0;
|
2014-07-07 08:28:48 +02:00
|
|
|
virtual bool incoming_packet(error_code const& /* ec */
|
|
|
|
, char const* /* hostname */, char const* /* buf */, int /* size */) { return false; }
|
2012-06-22 06:21:20 +02:00
|
|
|
|
2012-07-01 20:44:46 +02:00
|
|
|
// called when the socket becomes writeable, after having
|
|
|
|
// failed with EWOULDBLOCK
|
|
|
|
virtual void writable() {}
|
|
|
|
|
2012-06-22 06:21:20 +02:00
|
|
|
// called every time the socket is drained of packets
|
|
|
|
virtual void socket_drained() {}
|
2015-04-19 08:28:21 +02:00
|
|
|
protected:
|
|
|
|
~udp_socket_observer() {}
|
2012-06-22 06:21:20 +02:00
|
|
|
};
|
|
|
|
|
2016-01-19 07:19:16 +01:00
|
|
|
class TORRENT_EXTRA_EXPORT udp_socket : single_threaded
|
2007-12-09 05:15:24 +01:00
|
|
|
{
|
|
|
|
public:
|
2014-10-03 22:56:57 +02:00
|
|
|
udp_socket(io_service& ios);
|
2008-12-28 02:50:55 +01:00
|
|
|
~udp_socket();
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2015-08-25 04:18:10 +02:00
|
|
|
enum flags_t {
|
|
|
|
dont_drop = 1
|
|
|
|
, peer_connection = 2
|
|
|
|
, tracker_connection = 4
|
|
|
|
, dont_queue = 8
|
|
|
|
};
|
2011-01-24 04:24:28 +01:00
|
|
|
|
2016-02-22 02:00:55 +01:00
|
|
|
bool is_open() const { return m_abort == false; }
|
2008-05-03 18:05:42 +02:00
|
|
|
io_service& get_io_service() { return m_ipv4_sock.get_io_service(); }
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2012-06-22 06:21:20 +02:00
|
|
|
void subscribe(udp_socket_observer* o);
|
|
|
|
void unsubscribe(udp_socket_observer* o);
|
|
|
|
|
2010-08-03 11:08:37 +02:00
|
|
|
// this is only valid when using a socks5 proxy
|
2013-11-20 02:19:42 +01:00
|
|
|
void send_hostname(char const* hostname, int port, char const* p
|
|
|
|
, int len, error_code& ec, int flags = 0);
|
2010-08-03 11:08:37 +02:00
|
|
|
|
2013-11-20 02:19:42 +01:00
|
|
|
void send(udp::endpoint const& ep, char const* p, int len
|
|
|
|
, error_code& ec, int flags = 0);
|
2008-05-03 18:05:42 +02:00
|
|
|
void bind(udp::endpoint const& ep, error_code& ec);
|
2007-12-09 05:15:24 +01:00
|
|
|
void close();
|
|
|
|
int local_port() const { return m_bind_port; }
|
|
|
|
|
2015-08-25 04:18:10 +02:00
|
|
|
void set_proxy_settings(aux::proxy_settings const& ps);
|
|
|
|
aux::proxy_settings const& get_proxy_settings() { return m_proxy_settings; }
|
2013-02-19 07:48:53 +01:00
|
|
|
void set_force_proxy(bool f) { m_force_proxy = f; }
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2008-12-28 02:50:55 +01:00
|
|
|
bool is_closed() const { return m_abort; }
|
2010-11-29 02:33:05 +01:00
|
|
|
tcp::endpoint local_endpoint(error_code& ec) const
|
2010-05-30 03:33:03 +02:00
|
|
|
{
|
2010-07-18 16:45:43 +02:00
|
|
|
udp::endpoint ep = m_ipv4_sock.local_endpoint(ec);
|
2010-05-30 03:33:03 +02:00
|
|
|
return tcp::endpoint(ep.address(), ep.port());
|
|
|
|
}
|
2008-09-23 01:43:21 +02:00
|
|
|
|
2010-11-29 02:33:05 +01:00
|
|
|
void set_buf_size(int s);
|
|
|
|
|
2015-07-12 05:01:27 +02:00
|
|
|
typedef udp::socket::receive_buffer_size receive_buffer_size;
|
|
|
|
typedef udp::socket::send_buffer_size send_buffer_size;
|
|
|
|
|
2013-09-03 10:39:30 +02:00
|
|
|
template <class SocketOption>
|
|
|
|
void get_option(SocketOption const& opt, error_code& ec)
|
|
|
|
{
|
|
|
|
#if TORRENT_USE_IPV6
|
2016-04-02 23:20:48 +02:00
|
|
|
if (opt.level(udp::v6()) == IPPROTO_IPV6)
|
|
|
|
m_ipv6_sock.get_option(opt, ec);
|
|
|
|
else
|
2013-09-03 10:39:30 +02:00
|
|
|
#endif
|
2016-04-02 23:20:48 +02:00
|
|
|
m_ipv4_sock.get_option(opt, ec);
|
2013-09-03 10:39:30 +02:00
|
|
|
}
|
|
|
|
|
2010-11-29 02:33:05 +01:00
|
|
|
template <class SocketOption>
|
|
|
|
void set_option(SocketOption const& opt, error_code& ec)
|
|
|
|
{
|
2016-04-02 23:20:48 +02:00
|
|
|
if (opt.level(udp::v4()) != IPPROTO_IPV6)
|
|
|
|
m_ipv4_sock.set_option(opt, ec);
|
2010-11-29 02:33:05 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
2016-04-02 23:20:48 +02:00
|
|
|
if (opt.level(udp::v6()) != IPPROTO_IP)
|
|
|
|
m_ipv6_sock.set_option(opt, ec);
|
2010-11-29 02:33:05 +01:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class SocketOption>
|
|
|
|
void get_option(SocketOption& opt, error_code& ec)
|
|
|
|
{
|
2016-04-02 23:20:48 +02:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
if (opt.level(udp::v6()) == IPPROTO_IPV6)
|
|
|
|
m_ipv6_sock.get_option(opt, ec);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
m_ipv4_sock.get_option(opt, ec);
|
2010-11-29 02:33:05 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
udp::endpoint proxy_addr() const { return m_proxy_addr; }
|
|
|
|
|
2016-02-22 02:00:55 +01:00
|
|
|
private:
|
2010-02-18 05:37:02 +01:00
|
|
|
|
|
|
|
struct queued_packet
|
|
|
|
{
|
2015-06-02 03:14:52 +02:00
|
|
|
queued_packet()
|
|
|
|
: hostname(NULL)
|
|
|
|
, flags(0)
|
|
|
|
{}
|
|
|
|
|
2010-02-18 05:37:02 +01:00
|
|
|
udp::endpoint ep;
|
2010-08-03 11:08:37 +02:00
|
|
|
char* hostname;
|
2010-02-18 05:37:02 +01:00
|
|
|
buffer buf;
|
2011-01-24 04:24:28 +01:00
|
|
|
int flags;
|
2010-02-18 05:37:02 +01:00
|
|
|
};
|
|
|
|
|
2011-04-09 19:59:00 +02:00
|
|
|
// number of outstanding UDP socket operations
|
|
|
|
// using the UDP socket buffer
|
2011-02-09 08:27:04 +01:00
|
|
|
int num_outstanding() const
|
|
|
|
{
|
|
|
|
return m_v4_outstanding
|
|
|
|
#if TORRENT_USE_IPV6
|
2015-05-18 03:30:32 +02:00
|
|
|
+ m_v6_outstanding
|
2011-02-09 08:27:04 +01:00
|
|
|
#endif
|
|
|
|
;
|
|
|
|
}
|
|
|
|
|
2015-04-01 00:27:32 +02:00
|
|
|
// non-copyable
|
|
|
|
udp_socket(udp_socket const&);
|
|
|
|
udp_socket& operator=(udp_socket const&);
|
|
|
|
|
2016-02-22 02:00:55 +01:00
|
|
|
void close_impl();
|
|
|
|
|
2012-06-30 17:30:38 +02:00
|
|
|
// observers on this udp socket
|
2012-06-22 06:21:20 +02:00
|
|
|
std::vector<udp_socket_observer*> m_observers;
|
2012-06-30 17:30:38 +02:00
|
|
|
std::vector<udp_socket_observer*> m_added_observers;
|
|
|
|
|
2015-11-25 22:36:06 +01:00
|
|
|
template <class Handler>
|
|
|
|
aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>
|
|
|
|
make_read_handler4(Handler const& handler)
|
|
|
|
{
|
|
|
|
return aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>(
|
|
|
|
handler, m_v4_read_handler_storage
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
template <class Handler>
|
|
|
|
aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>
|
|
|
|
make_read_handler6(Handler const& handler)
|
|
|
|
{
|
|
|
|
return aux::allocating_handler<Handler, TORRENT_READ_HANDLER_MAX_SIZE>(
|
|
|
|
handler, m_v6_read_handler_storage
|
|
|
|
);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-06-30 17:30:38 +02:00
|
|
|
// this is true while iterating over the observers
|
|
|
|
// vector, invoking observer hooks. We may not
|
|
|
|
// add new observers during this time, since it
|
|
|
|
// may invalidate the iterator. If this is true,
|
|
|
|
// instead add new observers to m_added_observers
|
|
|
|
// and they will be added later
|
|
|
|
bool m_observers_locked;
|
2010-08-03 11:08:37 +02:00
|
|
|
|
2013-11-20 02:19:42 +01:00
|
|
|
void call_handler(error_code const& ec, udp::endpoint const& ep
|
|
|
|
, char const* buf, int size);
|
|
|
|
void call_handler(error_code const& ec, const char* host
|
|
|
|
, char const* buf, int size);
|
2012-06-22 06:21:20 +02:00
|
|
|
void call_drained_handler();
|
2012-07-01 20:44:46 +02:00
|
|
|
void call_writable_handler();
|
|
|
|
|
|
|
|
void on_writable(error_code const& ec, udp::socket* s);
|
2012-06-21 17:05:57 +02:00
|
|
|
|
|
|
|
void setup_read(udp::socket* s);
|
2012-07-15 04:16:02 +02:00
|
|
|
void on_read(error_code const& ec, udp::socket* s);
|
2015-05-18 07:04:55 +02:00
|
|
|
void on_read_impl(udp::endpoint const& ep
|
2012-06-21 17:05:57 +02:00
|
|
|
, error_code const& e, std::size_t bytes_transferred);
|
2008-05-03 18:05:42 +02:00
|
|
|
void on_name_lookup(error_code const& e, tcp::resolver::iterator i);
|
2014-10-03 22:56:57 +02:00
|
|
|
void on_connect_timeout(error_code const& ec);
|
|
|
|
void on_connected(error_code const& ec);
|
2008-05-03 18:05:42 +02:00
|
|
|
void handshake1(error_code const& e);
|
|
|
|
void handshake2(error_code const& e);
|
|
|
|
void handshake3(error_code const& e);
|
|
|
|
void handshake4(error_code const& e);
|
2010-09-25 23:39:27 +02:00
|
|
|
void socks_forward_udp();
|
2008-05-03 18:05:42 +02:00
|
|
|
void connect1(error_code const& e);
|
|
|
|
void connect2(error_code const& e);
|
2010-07-25 03:31:15 +02:00
|
|
|
void hung_up(error_code const& e);
|
2017-05-20 12:07:24 +02:00
|
|
|
void retry_socks_connect(error_code const& ec);
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2013-06-12 09:57:13 +02:00
|
|
|
void drain_queue();
|
|
|
|
|
2008-05-03 18:05:42 +02:00
|
|
|
void wrap(udp::endpoint const& ep, char const* p, int len, error_code& ec);
|
2010-08-03 11:08:37 +02:00
|
|
|
void wrap(char const* hostname, int port, char const* p, int len, error_code& ec);
|
2008-05-03 18:05:42 +02:00
|
|
|
void unwrap(error_code const& e, char const* buf, int size);
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2015-06-06 19:49:18 +02:00
|
|
|
udp::socket m_ipv4_sock;
|
2015-11-25 22:36:06 +01:00
|
|
|
aux::handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> m_v4_read_handler_storage;
|
2014-10-03 22:56:57 +02:00
|
|
|
deadline_timer m_timer;
|
2012-06-21 17:05:57 +02:00
|
|
|
int m_buf_size;
|
2012-10-18 09:34:39 +02:00
|
|
|
|
|
|
|
// if the buffer size is attempted
|
|
|
|
// to be changed while the buffer is
|
|
|
|
// being used, this member is set to
|
|
|
|
// the desired size, and it's resized
|
|
|
|
// later
|
|
|
|
int m_new_buf_size;
|
2012-06-21 17:05:57 +02:00
|
|
|
char* m_buf;
|
2009-04-04 18:59:53 +02:00
|
|
|
|
|
|
|
#if TORRENT_USE_IPV6
|
2015-06-06 19:49:18 +02:00
|
|
|
udp::socket m_ipv6_sock;
|
2015-11-25 22:36:06 +01:00
|
|
|
aux::handler_storage<TORRENT_READ_HANDLER_MAX_SIZE> m_v6_read_handler_storage;
|
2009-04-04 18:59:53 +02:00
|
|
|
#endif
|
|
|
|
|
2011-02-05 22:19:33 +01:00
|
|
|
boost::uint16_t m_bind_port;
|
|
|
|
boost::uint8_t m_v4_outstanding;
|
2015-11-25 22:36:06 +01:00
|
|
|
boost::uint8_t m_restart_v4;
|
2011-02-05 22:19:33 +01:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
boost::uint8_t m_v6_outstanding;
|
2015-11-25 22:36:06 +01:00
|
|
|
boost::uint8_t m_restart_v6;
|
2011-02-05 22:19:33 +01:00
|
|
|
#endif
|
2007-12-09 05:15:24 +01:00
|
|
|
|
2015-06-06 19:49:18 +02:00
|
|
|
tcp::socket m_socks5_sock;
|
2017-05-20 12:07:24 +02:00
|
|
|
deadline_timer m_retry_timer;
|
2015-08-25 04:18:10 +02:00
|
|
|
aux::proxy_settings m_proxy_settings;
|
2007-12-09 05:15:24 +01:00
|
|
|
tcp::resolver m_resolver;
|
2010-08-03 11:08:37 +02:00
|
|
|
char m_tmp_buf[270];
|
2010-02-18 05:37:02 +01:00
|
|
|
bool m_queue_packets;
|
2007-12-09 05:15:24 +01:00
|
|
|
bool m_tunnel_packets;
|
2013-02-19 07:48:53 +01:00
|
|
|
bool m_force_proxy;
|
2008-12-28 02:50:55 +01:00
|
|
|
bool m_abort;
|
2013-05-24 08:28:46 +02:00
|
|
|
|
|
|
|
// this is the endpoint the proxy server lives at.
|
|
|
|
// when performing a UDP associate, we get another
|
|
|
|
// endpoint (presumably on the same IP) where we're
|
|
|
|
// supposed to send UDP packets.
|
2007-12-09 05:15:24 +01:00
|
|
|
udp::endpoint m_proxy_addr;
|
2013-05-24 08:28:46 +02:00
|
|
|
|
|
|
|
// this is where UDP packets that are to be forwarded
|
|
|
|
// are sent. The result from UDP ASSOCIATE is stored
|
|
|
|
// in here.
|
|
|
|
udp::endpoint m_udp_proxy_addr;
|
|
|
|
|
2010-02-18 05:37:02 +01:00
|
|
|
// while we're connecting to the proxy
|
|
|
|
// we have to queue the packets, we'll flush
|
|
|
|
// them once we're connected
|
2011-03-14 08:23:32 +01:00
|
|
|
std::deque<queued_packet> m_queue;
|
2011-04-09 19:59:00 +02:00
|
|
|
|
|
|
|
// counts the number of outstanding async
|
|
|
|
// operations hanging on this socket
|
|
|
|
int m_outstanding_ops;
|
|
|
|
|
2012-07-01 20:44:46 +02:00
|
|
|
#if TORRENT_USE_IPV6
|
|
|
|
bool m_v6_write_subscribed:1;
|
|
|
|
#endif
|
|
|
|
bool m_v4_write_subscribed:1;
|
|
|
|
|
2014-01-19 20:45:50 +01:00
|
|
|
#if TORRENT_USE_ASSERTS
|
2009-04-13 19:52:45 +02:00
|
|
|
bool m_started;
|
2008-09-23 01:43:21 +02:00
|
|
|
int m_magic;
|
2010-02-21 21:15:07 +01:00
|
|
|
int m_outstanding_when_aborted;
|
2012-10-21 05:56:22 +02:00
|
|
|
int m_outstanding_connect;
|
|
|
|
int m_outstanding_timeout;
|
|
|
|
int m_outstanding_resolve;
|
|
|
|
int m_outstanding_socks;
|
2008-09-23 01:43:21 +02:00
|
|
|
#endif
|
2007-12-09 05:15:24 +01:00
|
|
|
};
|
2008-11-08 18:40:06 +01:00
|
|
|
|
|
|
|
struct rate_limited_udp_socket : public udp_socket
|
|
|
|
{
|
2014-10-03 22:56:57 +02:00
|
|
|
rate_limited_udp_socket(io_service& ios);
|
2008-11-08 18:40:06 +01:00
|
|
|
void set_rate_limit(int limit) { m_rate_limit = limit; }
|
2013-11-20 02:19:42 +01:00
|
|
|
bool send(udp::endpoint const& ep, char const* p, int len
|
|
|
|
, error_code& ec, int flags = 0);
|
2014-07-06 21:18:00 +02:00
|
|
|
bool has_quota();
|
2008-11-08 18:40:06 +01:00
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
|
|
int m_rate_limit;
|
|
|
|
int m_quota;
|
2015-03-12 05:34:54 +01:00
|
|
|
time_point m_last_tick;
|
2008-11-08 18:40:06 +01:00
|
|
|
};
|
2007-12-09 05:15:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|