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