1 /* 2 3 Copyright (c) 2007-2018, Arvid Norberg 4 All rights reserved. 5 6 Redistribution and use in source and binary forms, with or without 7 modification, are permitted provided that the following conditions 8 are met: 9 10 * Redistributions of source code must retain the above copyright 11 notice, this list of conditions and the following disclaimer. 12 * Redistributions in binary form must reproduce the above copyright 13 notice, this list of conditions and the following disclaimer in 14 the documentation and/or other materials provided with the distribution. 15 * Neither the name of the author nor the names of its 16 contributors may be used to endorse or promote products derived 17 from this software without specific prior written permission. 18 19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 23 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 POSSIBILITY OF SUCH DAMAGE. 30 31 */ 32 33 #ifndef TORRENT_UDP_SOCKET_HPP_INCLUDED 34 #define TORRENT_UDP_SOCKET_HPP_INCLUDED 35 36 #include "libtorrent/socket.hpp" 37 #include "libtorrent/io_service.hpp" 38 #include "libtorrent/error_code.hpp" 39 #include "libtorrent/aux_/proxy_settings.hpp" 40 #include "libtorrent/debug.hpp" 41 #include "libtorrent/span.hpp" 42 #include "libtorrent/flags.hpp" 43 #include "libtorrent/aux_/listen_socket_handle.hpp" 44 45 #include <array> 46 #include <memory> 47 48 namespace libtorrent { 49 50 class alert_manager; 51 struct socks5; 52 53 using udp_send_flags_t = flags::bitfield_flag<std::uint8_t, struct udp_send_flags_tag>; 54 55 class TORRENT_EXTRA_EXPORT udp_socket : single_threaded 56 { 57 public: 58 explicit udp_socket(io_service& ios, aux::listen_socket_handle ls); 59 60 static constexpr udp_send_flags_t peer_connection = 0_bit; 61 static constexpr udp_send_flags_t tracker_connection = 1_bit; 62 static constexpr udp_send_flags_t dont_queue = 2_bit; 63 static constexpr udp_send_flags_t dont_fragment = 3_bit; 64 is_open() const65 bool is_open() const { return m_abort == false; } get_io_service()66 io_service& get_io_service() { return lt::get_io_service(m_socket); } 67 68 template <typename Handler> async_read(Handler && h)69 void async_read(Handler&& h) 70 { 71 m_socket.async_receive(null_buffers(), std::forward<Handler>(h)); 72 } 73 74 template <typename Handler> async_write(Handler && h)75 void async_write(Handler&& h) 76 { 77 m_socket.async_send(null_buffers(), std::forward<Handler>(h)); 78 } 79 80 struct packet 81 { 82 span<char> data; 83 udp::endpoint from; 84 error_code error; 85 }; 86 87 int read(span<packet> pkts, error_code& ec); 88 89 // this is only valid when using a socks5 proxy 90 void send_hostname(char const* hostname, int port, span<char const> p 91 , error_code& ec, udp_send_flags_t flags = {}); 92 93 void send(udp::endpoint const& ep, span<char const> p 94 , error_code& ec, udp_send_flags_t flags = {}); 95 void open(udp const& protocol, error_code& ec); 96 void bind(udp::endpoint const& ep, error_code& ec); 97 void close(); local_port() const98 int local_port() const { return m_bind_port; } 99 100 void set_proxy_settings(aux::proxy_settings const& ps, alert_manager& alerts); get_proxy_settings()101 aux::proxy_settings const& get_proxy_settings() { return m_proxy_settings; } 102 is_closed() const103 bool is_closed() const { return m_abort; } local_endpoint(error_code & ec) const104 udp::endpoint local_endpoint(error_code& ec) const 105 { return m_socket.local_endpoint(ec); } 106 // best effort, if you want to know the error, use 107 // ``local_endpoint(error_code& ec)`` local_endpoint() const108 udp::endpoint local_endpoint() const 109 { 110 error_code ec; 111 return local_endpoint(ec); 112 } 113 114 using receive_buffer_size = udp::socket::receive_buffer_size; 115 using send_buffer_size = udp::socket::send_buffer_size; 116 117 template <class SocketOption> get_option(SocketOption const & opt,error_code & ec)118 void get_option(SocketOption const& opt, error_code& ec) 119 { 120 m_socket.get_option(opt, ec); 121 } 122 123 template <class SocketOption> set_option(SocketOption const & opt,error_code & ec)124 void set_option(SocketOption const& opt, error_code& ec) 125 { 126 m_socket.set_option(opt, ec); 127 } 128 129 #ifdef TCP_NOTSENT_LOWAT set_option(tcp_notsent_lowat const &,error_code &)130 void set_option(tcp_notsent_lowat const&, error_code&) {} 131 #endif 132 133 template <class SocketOption> get_option(SocketOption & opt,error_code & ec)134 void get_option(SocketOption& opt, error_code& ec) 135 { 136 m_socket.get_option(opt, ec); 137 } 138 139 bool active_socks5() const; 140 141 private: 142 143 // non-copyable 144 udp_socket(udp_socket const&); 145 udp_socket& operator=(udp_socket const&); 146 147 void wrap(udp::endpoint const& ep, span<char const> p, error_code& ec, udp_send_flags_t flags); 148 void wrap(char const* hostname, int port, span<char const> p, error_code& ec, udp_send_flags_t flags); 149 bool unwrap(udp::endpoint& from, span<char>& buf); 150 151 udp::socket m_socket; 152 153 using receive_buffer = std::array<char, 1500>; 154 std::unique_ptr<receive_buffer> m_buf; 155 aux::listen_socket_handle m_listen_socket; 156 157 std::uint16_t m_bind_port; 158 159 aux::proxy_settings m_proxy_settings; 160 161 std::shared_ptr<socks5> m_socks5_connection; 162 163 bool m_abort:1; 164 165 #if TORRENT_USE_ASSERTS 166 bool m_started; 167 int m_magic; 168 #endif 169 }; 170 } 171 172 #endif 173