1 /*
2 
3 Copyright (c) 2006-2018, Arvid Norberg, Magnus Jonsson
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 #include "libtorrent/config.hpp"
34 
35 #include <ctime>
36 #include <algorithm>
37 #include <cctype>
38 #include <cstdio> // for snprintf
39 #include <cinttypes> // for PRId64 et.al.
40 #include <functional>
41 #include <type_traits>
42 #include <numeric> // for accumulate
43 
44 #if TORRENT_USE_INVARIANT_CHECKS
45 #include <unordered_set>
46 #endif
47 
48 #include "libtorrent/aux_/disable_warnings_push.hpp"
49 #include <boost/asio/ip/v6_only.hpp>
50 #include "libtorrent/aux_/disable_warnings_pop.hpp"
51 
52 #include "libtorrent/aux_/openssl.hpp"
53 #include "libtorrent/peer_id.hpp"
54 #include "libtorrent/torrent_info.hpp"
55 #include "libtorrent/tracker_manager.hpp"
56 #include "libtorrent/bencode.hpp"
57 #include "libtorrent/hasher.hpp"
58 #include "libtorrent/entry.hpp"
59 #include "libtorrent/session.hpp"
60 #include "libtorrent/fingerprint.hpp"
61 #include "libtorrent/alert_types.hpp"
62 #include "libtorrent/invariant_check.hpp"
63 #include "libtorrent/bt_peer_connection.hpp"
64 #include "libtorrent/peer_connection_handle.hpp"
65 #include "libtorrent/ip_filter.hpp"
66 #include "libtorrent/socket.hpp"
67 #include "libtorrent/aux_/session_impl.hpp"
68 #ifndef TORRENT_DISABLE_DHT
69 #include "libtorrent/kademlia/dht_tracker.hpp"
70 #include "libtorrent/kademlia/types.hpp"
71 #include "libtorrent/kademlia/node_entry.hpp"
72 #endif
73 #include "libtorrent/enum_net.hpp"
74 #include "libtorrent/utf8.hpp"
75 #include "libtorrent/upnp.hpp"
76 #include "libtorrent/natpmp.hpp"
77 #include "libtorrent/lsd.hpp"
78 #include "libtorrent/aux_/instantiate_connection.hpp"
79 #include "libtorrent/peer_info.hpp"
80 #include "libtorrent/random.hpp"
81 #include "libtorrent/magnet_uri.hpp"
82 #include "libtorrent/aux_/session_settings.hpp"
83 #include "libtorrent/torrent_peer.hpp"
84 #include "libtorrent/torrent_handle.hpp"
85 #include "libtorrent/choker.hpp"
86 #include "libtorrent/error.hpp"
87 #include "libtorrent/platform_util.hpp"
88 #include "libtorrent/aux_/bind_to_device.hpp"
89 #include "libtorrent/hex.hpp" // to_hex, from_hex
90 #include "libtorrent/aux_/scope_end.hpp"
91 #include "libtorrent/aux_/set_socket_buffer.hpp"
92 #include "libtorrent/aux_/generate_peer_id.hpp"
93 #include "libtorrent/aux_/ffs.hpp"
94 
95 #ifndef TORRENT_DISABLE_LOGGING
96 
97 #include "libtorrent/socket_io.hpp"
98 
99 // for logging stat layout
100 #include "libtorrent/stat.hpp"
101 
102 #include <cstdarg> // for va_list
103 
104 // for logging the size of DHT structures
105 #ifndef TORRENT_DISABLE_DHT
106 #include <libtorrent/kademlia/find_data.hpp>
107 #include <libtorrent/kademlia/refresh.hpp>
108 #include <libtorrent/kademlia/node.hpp>
109 #include <libtorrent/kademlia/observer.hpp>
110 #include <libtorrent/kademlia/item.hpp>
111 #endif // TORRENT_DISABLE_DHT
112 
113 #include "libtorrent/http_tracker_connection.hpp"
114 #include "libtorrent/udp_tracker_connection.hpp"
115 
116 #endif // TORRENT_DISABLE_LOGGING
117 
118 #ifdef TORRENT_USE_LIBGCRYPT
119 
120 #if GCRYPT_VERSION_NUMBER < 0x010600
121 extern "C" {
122 GCRY_THREAD_OPTION_PTHREAD_IMPL;
123 }
124 #endif
125 
126 namespace {
127 
128 	// libgcrypt requires this to initialize the library
129 	struct gcrypt_setup
130 	{
gcrypt_setup__anon13c9013d0111::gcrypt_setup131 		gcrypt_setup()
132 		{
133 			gcry_check_version(nullptr);
134 #if GCRYPT_VERSION_NUMBER < 0x010600
135 			gcry_error_t e = gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
136 			if (e != 0) std::fprintf(stderr, "libcrypt ERROR: %s\n", gcry_strerror(e));
137 			e = gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
138 			if (e != 0) std::fprintf(stderr, "initialization finished error: %s\n", gcry_strerror(e));
139 #endif
140 		}
141 	} gcrypt_global_constructor;
142 }
143 
144 #endif // TORRENT_USE_LIBGCRYPT
145 
146 #ifdef TORRENT_USE_OPENSSL
147 
148 #include <openssl/crypto.h>
149 #include <openssl/rand.h>
150 
151 // by openssl changelog at https://www.openssl.org/news/changelog.html
152 // Changes between 1.0.2h and 1.1.0  [25 Aug 2016]
153 // - Most global cleanup functions are no longer required because they are handled
154 //   via auto-deinit. Affected function CRYPTO_cleanup_all_ex_data()
155 #if !defined(OPENSSL_API_COMPAT) || OPENSSL_API_COMPAT < 0x10100000L
156 namespace {
157 
158 	// openssl requires this to clean up internal
159 	// structures it allocates
160 	struct openssl_cleanup
161 	{
162 #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO
163 #pragma clang diagnostic push
164 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
165 #endif
~openssl_cleanup__anon13c9013d0211::openssl_cleanup166 		~openssl_cleanup() { CRYPTO_cleanup_all_ex_data(); }
167 #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO
168 #pragma clang diagnostic pop
169 #endif
170 	} openssl_global_destructor;
171 }
172 #endif
173 
174 #ifdef TORRENT_WINDOWS
175 #include <wincrypt.h>
176 #endif
177 
178 #endif // TORRENT_USE_OPENSSL
179 
180 #ifdef TORRENT_WINDOWS
181 // for ERROR_SEM_TIMEOUT
182 #include <winerror.h>
183 #endif
184 
185 using namespace std::placeholders;
186 
187 #ifdef BOOST_NO_EXCEPTIONS
188 namespace boost {
189 
throw_exception(std::exception const & e)190 	void throw_exception(std::exception const& e) { std::abort(); }
191 }
192 #endif
193 
194 namespace libtorrent {
195 
196 #if defined TORRENT_ASIO_DEBUGGING
197 	std::map<std::string, async_t> _async_ops;
198 	std::deque<wakeup_t> _wakeups;
199 	int _async_ops_nthreads = 0;
200 	std::mutex _async_ops_mutex;
201 #endif
202 
203 namespace aux {
204 
205 	constexpr listen_socket_flags_t listen_socket_t::accept_incoming;
206 	constexpr listen_socket_flags_t listen_socket_t::local_network;
207 	constexpr listen_socket_flags_t listen_socket_t::was_expanded;
208 	constexpr listen_socket_flags_t listen_socket_t::proxy;
209 
210 	constexpr ip_source_t session_interface::source_dht;
211 	constexpr ip_source_t session_interface::source_peer;
212 	constexpr ip_source_t session_interface::source_tracker;
213 	constexpr ip_source_t session_interface::source_router;
214 
partition_listen_sockets(std::vector<listen_endpoint_t> & eps,std::vector<std::shared_ptr<listen_socket_t>> & sockets)215 	std::vector<std::shared_ptr<listen_socket_t>>::iterator partition_listen_sockets(
216 		std::vector<listen_endpoint_t>& eps
217 		, std::vector<std::shared_ptr<listen_socket_t>>& sockets)
218 	{
219 		return std::partition(sockets.begin(), sockets.end()
220 			, [&eps](std::shared_ptr<listen_socket_t> const& sock)
221 		{
222 			auto match = std::find_if(eps.begin(), eps.end()
223 				, [&sock](listen_endpoint_t const& ep)
224 			{
225 				return ep.ssl == sock->ssl
226 					&& ep.port == sock->original_port
227 					&& ep.device == sock->device
228 					&& ep.flags == sock->flags
229 					&& ep.addr == sock->local_endpoint.address();
230 			});
231 
232 			if (match != eps.end())
233 			{
234 				// remove the matched endpoint so that another socket can't match it
235 				// this also signals to the caller that it doesn't need to create a
236 				// socket for the endpoint
237 				eps.erase(match);
238 				return true;
239 			}
240 			else
241 			{
242 				return false;
243 			}
244 		});
245 	}
246 
247 	// To comply with BEP 45 multi homed clients must run separate DHT nodes
248 	// on each interface they use to talk to the DHT. This is enforced
249 	// by prohibiting creating a listen socket on [::] and 0.0.0.0. Instead the list of
250 	// interfaces is enumerated and sockets are created for each of them.
expand_unspecified_address(span<ip_interface const> const ifs,span<ip_route const> const routes,std::vector<listen_endpoint_t> & eps)251 	void expand_unspecified_address(span<ip_interface const> const ifs
252 		, span<ip_route const> const routes
253 		, std::vector<listen_endpoint_t>& eps)
254 	{
255 		auto unspecified_begin = std::partition(eps.begin(), eps.end()
256 			, [](listen_endpoint_t const& ep) { return !ep.addr.is_unspecified(); });
257 		std::vector<listen_endpoint_t> unspecified_eps(unspecified_begin, eps.end());
258 		eps.erase(unspecified_begin, eps.end());
259 		for (auto const& uep : unspecified_eps)
260 		{
261 			bool const v4 = uep.addr.is_v4();
262 			for (auto const& ipface : ifs)
263 			{
264 				if (!ipface.preferred)
265 					continue;
266 				if (ipface.interface_address.is_v4() != v4)
267 					continue;
268 				if (!uep.device.empty() && uep.device != ipface.name)
269 					continue;
270 				if (std::any_of(eps.begin(), eps.end(), [&](listen_endpoint_t const& e)
271 				{
272 					// ignore device name because we don't want to create
273 					// duplicates if the user explicitly configured an address
274 					// without a device name
275 					return e.addr == ipface.interface_address
276 						&& e.port == uep.port
277 						&& e.ssl == uep.ssl;
278 				}))
279 				{
280 					continue;
281 				}
282 
283 				// ignore interfaces that are down
284 				if (ipface.state != if_state::up && ipface.state != if_state::unknown)
285 					continue;
286 				if (!(ipface.flags & if_flags::up))
287 					continue;
288 
289 				// we assume this listen_socket_t is local-network under some
290 				// conditions, meaning we won't announce it to internet trackers
291 				bool const local
292 					= ipface.interface_address.is_loopback()
293 					|| is_link_local(ipface.interface_address)
294 					|| (ipface.flags & if_flags::loopback)
295 					|| (!is_global(ipface.interface_address)
296 						&& !(ipface.flags & if_flags::pointopoint)
297 						&& !has_internet_route(ipface.name, family(ipface.interface_address), routes));
298 
299 				eps.emplace_back(ipface.interface_address, uep.port, uep.device
300 					, uep.ssl, uep.flags | listen_socket_t::was_expanded
301 					| (local ? listen_socket_t::local_network : listen_socket_flags_t{}));
302 			}
303 		}
304 	}
305 
expand_devices(span<ip_interface const> const ifs,std::vector<listen_endpoint_t> & eps)306 	void expand_devices(span<ip_interface const> const ifs
307 		, std::vector<listen_endpoint_t>& eps)
308 	{
309 		for (auto& ep : eps)
310 		{
311 			auto const iface = ep.device.empty()
312 				? std::find_if(ifs.begin(), ifs.end(), [&](ip_interface const& ipface)
313 					{
314 						return match_addr_mask(ipface.interface_address, ep.addr, ipface.netmask);
315 					})
316 				: std::find_if(ifs.begin(), ifs.end(), [&](ip_interface const& ipface)
317 					{
318 						return ipface.name == ep.device
319 							&& match_addr_mask(ipface.interface_address, ep.addr, ipface.netmask);
320 					});
321 
322 			if (iface == ifs.end())
323 			{
324 				// we can't find which device this is for, just assume we can't
325 				// reach anything on it
326 				ep.netmask = build_netmask(0, ep.addr.is_v4() ? AF_INET : AF_INET6);
327 				continue;
328 			}
329 
330 			ep.netmask = iface->netmask;
331 			ep.device = iface->name;
332 		}
333 	}
334 
can_route(address const & addr) const335 	bool listen_socket_t::can_route(address const& addr) const
336 	{
337 		// if this is a proxy, we assume it can reach everything
338 		if (flags & proxy) return true;
339 
340 		if (is_v4(local_endpoint) != addr.is_v4()) return false;
341 
342 		if (local_endpoint.address().is_v6()
343 			&& local_endpoint.address().to_v6().scope_id() != addr.to_v6().scope_id())
344 			return false;
345 
346 		if (local_endpoint.address() == addr) return true;
347 		if (local_endpoint.address().is_unspecified()) return true;
348 		if (match_addr_mask(addr, local_endpoint.address(), netmask)) return true;
349 		return !(flags & local_network);
350 	}
351 
init_peer_class_filter(bool unlimited_local)352 	void session_impl::init_peer_class_filter(bool unlimited_local)
353 	{
354 		// set the default peer_class_filter to use the local peer class
355 		// for peers on local networks
356 		std::uint32_t lfilter = 1 << static_cast<std::uint32_t>(m_local_peer_class);
357 		std::uint32_t gfilter = 1 << static_cast<std::uint32_t>(m_global_class);
358 
359 		struct class_mapping
360 		{
361 			char const* first;
362 			char const* last;
363 			std::uint32_t filter;
364 		};
365 
366 		static const class_mapping v4_classes[] =
367 		{
368 			// everything
369 			{"0.0.0.0", "255.255.255.255", gfilter},
370 			// local networks
371 			{"10.0.0.0", "10.255.255.255", lfilter},
372 			{"172.16.0.0", "172.31.255.255", lfilter},
373 			{"192.168.0.0", "192.168.255.255", lfilter},
374 			// link-local
375 			{"169.254.0.0", "169.254.255.255", lfilter},
376 			// loop-back
377 			{"127.0.0.0", "127.255.255.255", lfilter},
378 		};
379 
380 		static const class_mapping v6_classes[] =
381 		{
382 			// everything
383 			{"::0", "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", gfilter},
384 			// local networks
385 			{"fc00::", "fdff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", lfilter},
386 			// link-local
387 			{"fe80::", "febf::ffff:ffff:ffff:ffff:ffff:ffff:ffff", lfilter},
388 			// loop-back
389 			{"::1", "::1", lfilter},
390 		};
391 
392 		class_mapping const* p = v4_classes;
393 		int len = sizeof(v4_classes) / sizeof(v4_classes[0]);
394 		if (!unlimited_local) len = 1;
395 		for (int i = 0; i < len; ++i)
396 		{
397 			error_code ec;
398 			address_v4 begin = make_address_v4(p[i].first, ec);
399 			address_v4 end = make_address_v4(p[i].last, ec);
400 			if (ec) continue;
401 			m_peer_class_filter.add_rule(begin, end, p[i].filter);
402 		}
403 		p = v6_classes;
404 		len = sizeof(v6_classes) / sizeof(v6_classes[0]);
405 		if (!unlimited_local) len = 1;
406 		for (int i = 0; i < len; ++i)
407 		{
408 			error_code ec;
409 			address_v6 begin = make_address_v6(p[i].first, ec);
410 			address_v6 end = make_address_v6(p[i].last, ec);
411 			if (ec) continue;
412 			m_peer_class_filter.add_rule(begin, end, p[i].filter);
413 		}
414 	}
415 
416 #if defined TORRENT_USE_OPENSSL && OPENSSL_VERSION_NUMBER >= 0x90812f
417 #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO
418 #pragma clang diagnostic push
419 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
420 #endif
421 	namespace {
422 	// when running bittorrent over SSL, the SNI (server name indication)
423 	// extension is used to know which torrent the incoming connection is
424 	// trying to connect to. The 40 first bytes in the name is expected to
425 	// be the hex encoded info-hash
servername_callback(SSL * s,int *,void * arg)426 	int servername_callback(SSL* s, int*, void* arg)
427 	{
428 		auto* ses = reinterpret_cast<session_impl*>(arg);
429 		const char* servername = SSL_get_servername(s, TLSEXT_NAMETYPE_host_name);
430 
431 		if (!servername || std::strlen(servername) < 40)
432 			return SSL_TLSEXT_ERR_ALERT_FATAL;
433 
434 		sha1_hash info_hash;
435 		bool valid = aux::from_hex({servername, 40}, info_hash.data());
436 
437 		// the server name is not a valid hex-encoded info-hash
438 		if (!valid)
439 			return SSL_TLSEXT_ERR_ALERT_FATAL;
440 
441 		// see if there is a torrent with this info-hash
442 		std::shared_ptr<torrent> t = ses->find_torrent(info_hash).lock();
443 
444 		// if there isn't, fail
445 		if (!t) return SSL_TLSEXT_ERR_ALERT_FATAL;
446 
447 		// if the torrent we found isn't an SSL torrent, also fail.
448 		if (!t->is_ssl_torrent()) return SSL_TLSEXT_ERR_ALERT_FATAL;
449 
450 		// if the torrent doesn't have an SSL context and should not allow
451 		// incoming SSL connections
452 		if (!t->ssl_ctx()) return SSL_TLSEXT_ERR_ALERT_FATAL;
453 
454 		// use this torrent's certificate
455 		SSL_CTX *torrent_context = t->ssl_ctx()->native_handle();
456 
457 		SSL_set_SSL_CTX(s, torrent_context);
458 		SSL_set_verify(s, SSL_CTX_get_verify_mode(torrent_context)
459 			, SSL_CTX_get_verify_callback(torrent_context));
460 
461 		return SSL_TLSEXT_ERR_OK;
462 	}
463 	} // anonymous namespace
464 #ifdef TORRENT_MACOS_DEPRECATED_LIBCRYPTO
465 #pragma clang diagnostic pop
466 #endif
467 #endif
468 
session_impl(io_service & ios,settings_pack const & pack,session_flags_t const flags)469 	session_impl::session_impl(io_service& ios, settings_pack const& pack
470 		, session_flags_t const flags)
471 		: m_settings(pack)
472 		, m_io_service(ios)
473 #ifdef TORRENT_USE_OPENSSL
474 #if BOOST_VERSION >= 106400
475 		, m_ssl_ctx(ssl::context::tls_client)
476 		, m_peer_ssl_ctx(ssl::context::tls)
477 #else
478 		, m_ssl_ctx(ssl::context::tlsv12_client)
479 		, m_peer_ssl_ctx(ssl::context::tlsv12)
480 #endif
481 #endif
482 		, m_alerts(m_settings.get_int(settings_pack::alert_queue_size)
483 			, alert_category_t{static_cast<unsigned int>(m_settings.get_int(settings_pack::alert_mask))})
484 		, m_disk_thread(m_io_service, m_settings, m_stats_counters)
485 		, m_download_rate(peer_connection::download_channel)
486 		, m_upload_rate(peer_connection::upload_channel)
487 		, m_host_resolver(m_io_service)
488 		, m_tracker_manager(
489 			std::bind(&session_impl::send_udp_packet_listen, this, _1, _2, _3, _4, _5)
490 			, std::bind(&session_impl::send_udp_packet_hostname_listen, this, _1, _2, _3, _4, _5, _6)
491 			, m_stats_counters
492 			, m_host_resolver
493 			, m_settings
494 #if !defined TORRENT_DISABLE_LOGGING || TORRENT_USE_ASSERTS
495 			, *this
496 #endif
497 			)
498 		, m_work(new io_service::work(m_io_service))
499 #if TORRENT_USE_I2P
500 		, m_i2p_conn(m_io_service)
501 #endif
502 		, m_created(clock_type::now())
503 		, m_last_tick(m_created)
504 		, m_last_second_tick(m_created - milliseconds(900))
505 		, m_last_choke(m_created)
506 		, m_last_auto_manage(m_created)
507 #ifndef TORRENT_DISABLE_DHT
508 		, m_dht_announce_timer(m_io_service)
509 #endif
510 		, m_utp_socket_manager(
511 			std::bind(&session_impl::send_udp_packet, this, _1, _2, _3, _4, _5)
512 			, std::bind(&session_impl::incoming_connection, this, _1)
513 			, m_io_service
514 			, m_settings, m_stats_counters, nullptr)
515 #ifdef TORRENT_USE_OPENSSL
516 		, m_ssl_utp_socket_manager(
517 			std::bind(&session_impl::send_udp_packet, this, _1, _2, _3, _4, _5)
518 			, std::bind(&session_impl::on_incoming_utp_ssl, this, _1)
519 			, m_io_service
520 			, m_settings, m_stats_counters
521 			, &m_peer_ssl_ctx)
522 #endif
523 		, m_timer(m_io_service)
524 		, m_lsd_announce_timer(m_io_service)
525 		, m_close_file_timer(m_io_service)
526 		, m_paused(flags & session::paused)
527 	{
528 	}
529 
530 	template <typename Fun, typename... Args>
wrap(Fun f,Args &&...a)531 	void session_impl::wrap(Fun f, Args&&... a)
532 #ifndef BOOST_NO_EXCEPTIONS
533 	try
534 #endif
535 	{
536 		(this->*f)(std::forward<Args>(a)...);
537 	}
538 #ifndef BOOST_NO_EXCEPTIONS
539 	catch (system_error const& e) {
540 		alerts().emplace_alert<session_error_alert>(e.code(), e.what());
541 		pause();
542 	} catch (std::exception const& e) {
543 		alerts().emplace_alert<session_error_alert>(error_code(), e.what());
544 		pause();
545 	} catch (...) {
546 		alerts().emplace_alert<session_error_alert>(error_code(), "unknown error");
547 		pause();
548 	}
549 #endif
550 
551 	// This function is called by the creating thread, not in the message loop's
552 	// io_service thread.
553 	// TODO: 2 is there a reason not to move all of this into init()? and just
554 	// post it to the io_service?
start_session()555 	void session_impl::start_session()
556 	{
557 #ifndef TORRENT_DISABLE_LOGGING
558 		session_log("start session");
559 #endif
560 
561 #ifdef TORRENT_USE_OPENSSL
562 		error_code ec;
563 		m_ssl_ctx.set_verify_mode(boost::asio::ssl::context::verify_none, ec);
564 		m_ssl_ctx.set_default_verify_paths(ec);
565 #ifndef TORRENT_DISABLE_LOGGING
566 		if (ec) session_log("SSL set_default verify_paths failed: %s", ec.message().c_str());
567 		ec.clear();
568 #endif
569 		m_peer_ssl_ctx.set_verify_mode(boost::asio::ssl::context::verify_none, ec);
570 #ifdef TORRENT_WINDOWS
571 		// load certificates from the windows system certificate store
572 		X509_STORE* store = X509_STORE_new();
573 		if (store)
574 		{
575 			HCERTSTORE system_store = CertOpenSystemStoreA(0, "ROOT");
576 			// this is best effort
577 			if (system_store)
578 			{
579 				CERT_CONTEXT const* ctx = nullptr;
580 				while ((ctx = CertEnumCertificatesInStore(system_store, ctx)) != nullptr)
581 				{
582 					unsigned char const* cert_ptr = reinterpret_cast<unsigned char const*>(ctx->pbCertEncoded);
583 					X509* x509 = d2i_X509(nullptr, &cert_ptr, ctx->cbCertEncoded);
584 					// this is best effort
585 					if (!x509) continue;
586 					X509_STORE_add_cert(store, x509);
587 					X509_free(x509);
588 				}
589 				CertFreeCertificateContext(ctx);
590 				CertCloseStore(system_store, 0);
591 			}
592 		}
593 
594 		SSL_CTX* ssl_ctx = m_ssl_ctx.native_handle();
595 		SSL_CTX_set_cert_store(ssl_ctx, store);
596 #endif
597 #ifdef __APPLE__
598 		m_ssl_ctx.load_verify_file("/etc/ssl/cert.pem", ec);
599 #ifndef TORRENT_DISABLE_LOGGING
600 		if (ec) session_log("SSL load_verify_file failed: %s", ec.message().c_str());
601 		ec.clear();
602 #endif
603 		m_ssl_ctx.add_verify_path("/etc/ssl/certs", ec);
604 #ifndef TORRENT_DISABLE_LOGGING
605 		if (ec) session_log("SSL add_verify_path failed: %s", ec.message().c_str());
606 		ec.clear();
607 #endif
608 #endif
609 #if OPENSSL_VERSION_NUMBER >= 0x90812f
610 		aux::openssl_set_tlsext_servername_callback(m_peer_ssl_ctx.native_handle()
611 			, servername_callback);
612 		aux::openssl_set_tlsext_servername_arg(m_peer_ssl_ctx.native_handle(), this);
613 #endif // OPENSSL_VERSION_NUMBER
614 #endif
615 
616 #ifndef TORRENT_DISABLE_DHT
617 		m_next_dht_torrent = m_torrents.begin();
618 #endif
619 		m_next_lsd_torrent = m_torrents.begin();
620 
621 		m_global_class = m_classes.new_peer_class("global");
622 		m_tcp_peer_class = m_classes.new_peer_class("tcp");
623 		m_local_peer_class = m_classes.new_peer_class("local");
624 		// local peers are always unchoked
625 		m_classes.at(m_local_peer_class)->ignore_unchoke_slots = true;
626 		// local peers are allowed to exceed the normal connection
627 		// limit by 50%
628 		m_classes.at(m_local_peer_class)->connection_limit_factor = 150;
629 
630 		TORRENT_ASSERT(m_global_class == session::global_peer_class_id);
631 		TORRENT_ASSERT(m_tcp_peer_class == session::tcp_peer_class_id);
632 		TORRENT_ASSERT(m_local_peer_class == session::local_peer_class_id);
633 
634 		init_peer_class_filter(true);
635 
636 		// TCP, SSL/TCP and I2P connections should be assigned the TCP peer class
637 		m_peer_class_type_filter.add(peer_class_type_filter::tcp_socket, m_tcp_peer_class);
638 		m_peer_class_type_filter.add(peer_class_type_filter::ssl_tcp_socket, m_tcp_peer_class);
639 		m_peer_class_type_filter.add(peer_class_type_filter::i2p_socket, m_tcp_peer_class);
640 
641 #ifndef TORRENT_DISABLE_LOGGING
642 
643 		session_log("version: %s revision: %s"
644 			, LIBTORRENT_VERSION, LIBTORRENT_REVISION);
645 
646 #endif // TORRENT_DISABLE_LOGGING
647 
648 		// ---- auto-cap max connections ----
649 		int const max_files = max_open_files();
650 		// deduct some margin for epoll/kqueue, log files,
651 		// futexes, shared objects etc.
652 		// 80% of the available file descriptors should go to connections
653 		m_settings.set_int(settings_pack::connections_limit, std::min(
654 			m_settings.get_int(settings_pack::connections_limit)
655 			, std::max(5, (max_files - 20) * 8 / 10)));
656 		// 20% goes towards regular files (see disk_io_thread)
657 #ifndef TORRENT_DISABLE_LOGGING
658 		if (should_log())
659 		{
660 			session_log("max-connections: %d max-files: %d"
661 				, m_settings.get_int(settings_pack::connections_limit)
662 				, max_files);
663 		}
664 #endif
665 
666 		m_io_service.post([this] { this->wrap(&session_impl::init); });
667 	}
668 
init()669 	void session_impl::init()
670 	{
671 		// this is a debug facility
672 		// see single_threaded in debug.hpp
673 		thread_started();
674 
675 		TORRENT_ASSERT(is_single_thread());
676 
677 #ifndef TORRENT_DISABLE_LOGGING
678 		session_log(" *** session thread init");
679 #endif
680 
681 		// this is where we should set up all async operations. This
682 		// is called from within the network thread as opposed to the
683 		// constructor which is called from the main thread
684 
685 #if defined TORRENT_ASIO_DEBUGGING
686 		async_inc_threads();
687 		add_outstanding_async("session_impl::on_tick");
688 #endif
689 		m_io_service.post([this]{ this->wrap(&session_impl::on_tick, error_code()); });
690 
691 		int const lsd_announce_interval
692 			= m_settings.get_int(settings_pack::local_service_announce_interval);
693 		int const delay = std::max(lsd_announce_interval
694 			/ std::max(static_cast<int>(m_torrents.size()), 1), 1);
695 		error_code ec;
696 		m_lsd_announce_timer.expires_from_now(seconds(delay), ec);
697 		ADD_OUTSTANDING_ASYNC("session_impl::on_lsd_announce");
698 		m_lsd_announce_timer.async_wait([this](error_code const& e) {
699 			this->wrap(&session_impl::on_lsd_announce, e); } );
700 		TORRENT_ASSERT(!ec);
701 
702 #ifndef TORRENT_DISABLE_LOGGING
703 		session_log(" done starting session");
704 #endif
705 
706 		// this applies unchoke settings from m_settings
707 		recalculate_unchoke_slots();
708 
709 		// apply all m_settings to this session
710 		run_all_updates(*this);
711 		reopen_listen_sockets(false);
712 
713 #if TORRENT_USE_INVARIANT_CHECKS
714 		check_invariant();
715 #endif
716 	}
717 
718 	// TODO: 2 the ip filter should probably be saved here too
save_state(entry * eptr,save_state_flags_t const flags) const719 	void session_impl::save_state(entry* eptr, save_state_flags_t const flags) const
720 	{
721 		TORRENT_ASSERT(is_single_thread());
722 
723 		entry& e = *eptr;
724 		// make it a dict
725 		e.dict();
726 
727 		if (flags & session::save_settings)
728 		{
729 			entry::dictionary_type& sett = e["settings"].dict();
730 			save_settings_to_dict(m_settings, sett);
731 		}
732 
733 #ifndef TORRENT_DISABLE_DHT
734 		if (flags & session::save_dht_settings)
735 		{
736 			e["dht"] = dht::save_dht_settings(m_dht_settings);
737 		}
738 
739 		if (m_dht && (flags & session::save_dht_state))
740 		{
741 			e["dht state"] = dht::save_dht_state(m_dht->state());
742 		}
743 #endif
744 
745 #ifndef TORRENT_DISABLE_EXTENSIONS
746 		for (auto const& ext : m_ses_extensions[plugins_all_idx])
747 		{
748 			ext->save_state(*eptr);
749 		}
750 #endif
751 	}
752 
proxy() const753 	proxy_settings session_impl::proxy() const
754 	{
755 		return proxy_settings(m_settings);
756 	}
757 
load_state(bdecode_node const * e,save_state_flags_t const flags)758 	void session_impl::load_state(bdecode_node const* e
759 		, save_state_flags_t const flags)
760 	{
761 		TORRENT_ASSERT(is_single_thread());
762 
763 		bdecode_node settings;
764 		if (e->type() != bdecode_node::dict_t) return;
765 
766 #ifndef TORRENT_DISABLE_DHT
767 		bool need_update_dht = false;
768 		if (flags & session_handle::save_dht_settings)
769 		{
770 			settings = e->dict_find_dict("dht");
771 			if (settings)
772 			{
773 				static_cast<dht::dht_settings&>(m_dht_settings) = dht::read_dht_settings(settings);
774 			}
775 		}
776 
777 		if (flags & session_handle::save_dht_state)
778 		{
779 			settings = e->dict_find_dict("dht state");
780 			if (settings)
781 			{
782 				m_dht_state = dht::read_dht_state(settings);
783 				need_update_dht = true;
784 			}
785 		}
786 #endif
787 
788 #if TORRENT_ABI_VERSION == 1
789 		bool need_update_proxy = false;
790 		if (flags & session_handle::save_proxy)
791 		{
792 			settings = e->dict_find_dict("proxy");
793 			if (settings)
794 			{
795 				m_settings.bulk_set([&settings](session_settings_single_thread& s)
796 				{
797 					bdecode_node val;
798 					val = settings.dict_find_int("port");
799 					if (val) s.set_int(settings_pack::proxy_port, int(val.int_value()));
800 					val = settings.dict_find_int("type");
801 					if (val) s.set_int(settings_pack::proxy_type, int(val.int_value()));
802 					val = settings.dict_find_int("proxy_hostnames");
803 					if (val) s.set_bool(settings_pack::proxy_hostnames, val.int_value() != 0);
804 					val = settings.dict_find_int("proxy_peer_connections");
805 					if (val) s.set_bool(settings_pack::proxy_peer_connections, val.int_value() != 0);
806 					val = settings.dict_find_string("hostname");
807 					if (val) s.set_str(settings_pack::proxy_hostname, val.string_value().to_string());
808 					val = settings.dict_find_string("password");
809 					if (val) s.set_str(settings_pack::proxy_password, val.string_value().to_string());
810 					val = settings.dict_find_string("username");
811 					if (val) s.set_str(settings_pack::proxy_username, val.string_value().to_string());
812 				});
813 				need_update_proxy = true;
814 			}
815 		}
816 
817 		settings = e->dict_find_dict("encryption");
818 		if (settings)
819 		{
820 			m_settings.bulk_set([&settings](session_settings_single_thread& s)
821 			{
822 				bdecode_node val;
823 				val = settings.dict_find_int("prefer_rc4");
824 				if (val) s.set_bool(settings_pack::prefer_rc4, val.int_value() != 0);
825 				val = settings.dict_find_int("out_enc_policy");
826 				if (val) s.set_int(settings_pack::out_enc_policy, int(val.int_value()));
827 				val = settings.dict_find_int("in_enc_policy");
828 				if (val) s.set_int(settings_pack::in_enc_policy, int(val.int_value()));
829 				val = settings.dict_find_int("allowed_enc_level");
830 				if (val) s.set_int(settings_pack::allowed_enc_level, int(val.int_value()));
831 			});
832 		}
833 #endif
834 
835 		if (flags & session_handle::save_settings)
836 		{
837 			settings = e->dict_find_dict("settings");
838 			if (settings)
839 			{
840 				// apply_settings_pack will update dht and proxy
841 				settings_pack pack = load_pack_from_dict(settings);
842 
843 				// these settings are not loaded from state
844 				// they are set by the client software, not configured by users
845 				pack.clear(settings_pack::user_agent);
846 				pack.clear(settings_pack::peer_fingerprint);
847 
848 				apply_settings_pack_impl(pack);
849 #ifndef TORRENT_DISABLE_DHT
850 				need_update_dht = false;
851 #endif
852 #if TORRENT_ABI_VERSION == 1
853 				need_update_proxy = false;
854 #endif
855 			}
856 		}
857 
858 #ifndef TORRENT_DISABLE_DHT
859 		if (need_update_dht) start_dht();
860 #endif
861 #if TORRENT_ABI_VERSION == 1
862 		if (need_update_proxy) update_proxy();
863 #endif
864 
865 #ifndef TORRENT_DISABLE_EXTENSIONS
866 		for (auto& ext : m_ses_extensions[plugins_all_idx])
867 		{
868 			ext->load_state(*e);
869 		}
870 #endif
871 	}
872 
873 #ifndef TORRENT_DISABLE_EXTENSIONS
874 
add_extension(ext_function_t ext)875 	void session_impl::add_extension(ext_function_t ext)
876 	{
877 		TORRENT_ASSERT(is_single_thread());
878 		TORRENT_ASSERT(ext);
879 
880 		add_ses_extension(std::make_shared<session_plugin_wrapper>(ext));
881 	}
882 
add_ses_extension(std::shared_ptr<plugin> ext)883 	void session_impl::add_ses_extension(std::shared_ptr<plugin> ext)
884 	{
885 		// this is called during startup of the session, from the thread creating
886 		// it, not its own thread
887 //		TORRENT_ASSERT(is_single_thread());
888 		TORRENT_ASSERT_VAL(ext, ext);
889 
890 		feature_flags_t const features = ext->implemented_features();
891 
892 		m_ses_extensions[plugins_all_idx].push_back(ext);
893 
894 		if (features & plugin::optimistic_unchoke_feature)
895 			m_ses_extensions[plugins_optimistic_unchoke_idx].push_back(ext);
896 		if (features & plugin::tick_feature)
897 			m_ses_extensions[plugins_tick_idx].push_back(ext);
898 		if (features & plugin::dht_request_feature)
899 			m_ses_extensions[plugins_dht_request_idx].push_back(ext);
900 		if (features & plugin::alert_feature)
901 			m_alerts.add_extension(ext);
902 		session_handle h(shared_from_this());
903 		ext->added(h);
904 	}
905 
906 #endif // TORRENT_DISABLE_EXTENSIONS
907 
pause()908 	void session_impl::pause()
909 	{
910 		TORRENT_ASSERT(is_single_thread());
911 
912 		if (m_paused) return;
913 #ifndef TORRENT_DISABLE_LOGGING
914 		session_log(" *** session paused ***");
915 #endif
916 		// this will abort all tracker announces other than event=stopped
917 		m_tracker_manager.abort_all_requests();
918 
919 		m_paused = true;
920 		for (auto& te : m_torrents)
921 		{
922 			te.second->set_session_paused(true);
923 		}
924 	}
925 
resume()926 	void session_impl::resume()
927 	{
928 		TORRENT_ASSERT(is_single_thread());
929 
930 		if (!m_paused) return;
931 		m_paused = false;
932 
933 		for (auto& te : m_torrents)
934 		{
935 			te.second->set_session_paused(false);
936 		}
937 	}
938 
abort()939 	void session_impl::abort() noexcept
940 	{
941 		TORRENT_ASSERT(is_single_thread());
942 
943 		if (m_abort) return;
944 #ifndef TORRENT_DISABLE_LOGGING
945 		session_log(" *** ABORT CALLED ***");
946 #endif
947 
948 		// at this point we cannot call the notify function anymore, since the
949 		// session will become invalid.
950 		m_alerts.set_notify_function({});
951 
952 		// this will cancel requests that are not critical for shutting down
953 		// cleanly. i.e. essentially tracker hostname lookups that we're not
954 		// about to send event=stopped to
955 		m_host_resolver.abort();
956 
957 		m_close_file_timer.cancel();
958 
959 		// abort the main thread
960 		m_abort = true;
961 		error_code ec;
962 
963 #if TORRENT_USE_I2P
964 		m_i2p_conn.close(ec);
965 #endif
966 		stop_ip_notifier();
967 		stop_lsd();
968 		stop_upnp();
969 		stop_natpmp();
970 #ifndef TORRENT_DISABLE_DHT
971 		stop_dht();
972 		m_dht_announce_timer.cancel(ec);
973 #endif
974 		m_lsd_announce_timer.cancel(ec);
975 
976 		for (auto const& s : m_incoming_sockets)
977 		{
978 			s->close(ec);
979 			TORRENT_ASSERT(!ec);
980 		}
981 		m_incoming_sockets.clear();
982 
983 #if TORRENT_USE_I2P
984 		if (m_i2p_listen_socket && m_i2p_listen_socket->is_open())
985 		{
986 			m_i2p_listen_socket->close(ec);
987 			TORRENT_ASSERT(!ec);
988 		}
989 		m_i2p_listen_socket.reset();
990 #endif
991 
992 #ifndef TORRENT_DISABLE_LOGGING
993 		session_log(" aborting all torrents (%d)", int(m_torrents.size()));
994 #endif
995 		// abort all torrents
996 		for (auto const& te : m_torrents)
997 		{
998 			te.second->abort();
999 		}
1000 		m_torrents.clear();
1001 		m_stats_counters.set_value(counters::num_peers_up_unchoked_all, 0);
1002 		m_stats_counters.set_value(counters::num_peers_up_unchoked, 0);
1003 		m_stats_counters.set_value(counters::num_peers_up_unchoked_optimistic, 0);
1004 
1005 #ifndef TORRENT_DISABLE_LOGGING
1006 		session_log(" aborting all tracker requests");
1007 #endif
1008 		m_tracker_manager.stop();
1009 
1010 #ifndef TORRENT_DISABLE_LOGGING
1011 		session_log(" aborting all connections (%d)", int(m_connections.size()));
1012 #endif
1013 		// abort all connections
1014 		for (auto i = m_connections.begin(); i != m_connections.end();)
1015 		{
1016 			peer_connection* p = (*i).get();
1017 			++i;
1018 			p->disconnect(errors::stopping_torrent, operation_t::bittorrent);
1019 		}
1020 
1021 		// close the listen sockets
1022 		for (auto const& l : m_listen_sockets)
1023 		{
1024 			if (l->sock)
1025 			{
1026 				l->sock->close(ec);
1027 				TORRENT_ASSERT(!ec);
1028 			}
1029 
1030 			// TODO: 3 closing the udp sockets here means that
1031 			// the uTP connections cannot be closed gracefully
1032 			if (l->udp_sock)
1033 			{
1034 				l->udp_sock->sock.close();
1035 			}
1036 		}
1037 
1038 		// we need to give all the sockets an opportunity to actually have their handlers
1039 		// called and cancelled before we continue the shutdown. This is a bit
1040 		// complicated, if there are no "undead" peers, it's safe to resume the
1041 		// shutdown, but if there are, we have to wait for them to be cleared out
1042 		// first. In session_impl::on_tick() we check them periodically. If we're
1043 		// shutting down and we remove the last one, we'll initiate
1044 		// shutdown_stage2 from there.
1045 		if (m_undead_peers.empty())
1046 		{
1047 			m_io_service.post(make_handler([this] { abort_stage2(); }
1048 				, m_abort_handler_storage, *this));
1049 		}
1050 	}
1051 
abort_stage2()1052 	void session_impl::abort_stage2() noexcept
1053 	{
1054 		m_download_rate.close();
1055 		m_upload_rate.close();
1056 
1057 		// it's OK to detach the threads here. The disk_io_thread
1058 		// has an internal counter and won't release the network
1059 		// thread until they're all dead (via m_work).
1060 		m_disk_thread.abort(false);
1061 
1062 		// now it's OK for the network thread to exit
1063 		m_work.reset();
1064 	}
1065 
has_connection(peer_connection * p) const1066 	bool session_impl::has_connection(peer_connection* p) const
1067 	{
1068 		return m_connections.find(p->self()) != m_connections.end();
1069 	}
1070 
insert_peer(std::shared_ptr<peer_connection> const & c)1071 	void session_impl::insert_peer(std::shared_ptr<peer_connection> const& c)
1072 	{
1073 		TORRENT_ASSERT(!c->m_in_constructor);
1074 
1075 		// removing a peer may not throw an exception, so prepare for this
1076 		// connection to be added to the undead peers now.
1077 		m_undead_peers.reserve(m_undead_peers.size() + m_connections.size() + 1);
1078 		m_connections.insert(c);
1079 
1080 		TORRENT_ASSERT_VAL(m_undead_peers.capacity() >= m_connections.size()
1081 			, m_undead_peers.capacity());
1082 	}
1083 
set_port_filter(port_filter const & f)1084 	void session_impl::set_port_filter(port_filter const& f)
1085 	{
1086 		m_port_filter = f;
1087 		if (m_settings.get_bool(settings_pack::no_connect_privileged_ports))
1088 			m_port_filter.add_rule(0, 1024, port_filter::blocked);
1089 		// Close connections whose endpoint is filtered
1090 		// by the new ip-filter
1091 		for (auto const& t : m_torrents)
1092 			t.second->port_filter_updated();
1093 	}
1094 
set_ip_filter(std::shared_ptr<ip_filter> const & f)1095 	void session_impl::set_ip_filter(std::shared_ptr<ip_filter> const& f)
1096 	{
1097 		INVARIANT_CHECK;
1098 
1099 		m_ip_filter = f;
1100 
1101 		// Close connections whose endpoint is filtered
1102 		// by the new ip-filter
1103 		for (auto& i : m_torrents)
1104 			i.second->set_ip_filter(m_ip_filter);
1105 	}
1106 
ban_ip(address addr)1107 	void session_impl::ban_ip(address addr)
1108 	{
1109 		TORRENT_ASSERT(is_single_thread());
1110 		if (!m_ip_filter) m_ip_filter = std::make_shared<ip_filter>();
1111 		m_ip_filter->add_rule(addr, addr, ip_filter::blocked);
1112 		for (auto& i : m_torrents)
1113 			i.second->set_ip_filter(m_ip_filter);
1114 	}
1115 
get_ip_filter()1116 	ip_filter const& session_impl::get_ip_filter()
1117 	{
1118 		TORRENT_ASSERT(is_single_thread());
1119 		if (!m_ip_filter) m_ip_filter = std::make_shared<ip_filter>();
1120 		return *m_ip_filter;
1121 	}
1122 
get_port_filter() const1123 	port_filter const& session_impl::get_port_filter() const
1124 	{
1125 		TORRENT_ASSERT(is_single_thread());
1126 		return m_port_filter;
1127 	}
1128 
create_peer_class(char const * name)1129 	peer_class_t session_impl::create_peer_class(char const* name)
1130 	{
1131 		TORRENT_ASSERT(is_single_thread());
1132 		return m_classes.new_peer_class(name);
1133 	}
1134 
delete_peer_class(peer_class_t const cid)1135 	void session_impl::delete_peer_class(peer_class_t const cid)
1136 	{
1137 		TORRENT_ASSERT(is_single_thread());
1138 		// if you hit this assert, you're deleting a non-existent peer class
1139 		TORRENT_ASSERT_PRECOND(m_classes.at(cid));
1140 		if (m_classes.at(cid) == nullptr) return;
1141 		m_classes.decref(cid);
1142 	}
1143 
get_peer_class(peer_class_t const cid) const1144 	peer_class_info session_impl::get_peer_class(peer_class_t const cid) const
1145 	{
1146 		peer_class_info ret{};
1147 		peer_class const* pc = m_classes.at(cid);
1148 		// if you hit this assert, you're passing in an invalid cid
1149 		TORRENT_ASSERT_PRECOND(pc);
1150 		if (pc == nullptr)
1151 		{
1152 #if TORRENT_USE_INVARIANT_CHECKS
1153 			// make it obvious that the return value is undefined
1154 			ret.upload_limit = 0xf0f0f0f;
1155 			ret.download_limit = 0xf0f0f0f;
1156 			ret.label.resize(20);
1157 			url_random(span<char>(ret.label));
1158 			ret.ignore_unchoke_slots = false;
1159 			ret.connection_limit_factor = 0xf0f0f0f;
1160 			ret.upload_priority = 0xf0f0f0f;
1161 			ret.download_priority = 0xf0f0f0f;
1162 #endif
1163 			return ret;
1164 		}
1165 
1166 		pc->get_info(&ret);
1167 		return ret;
1168 	}
1169 
1170 namespace {
1171 
make_announce_port(std::uint16_t const p)1172 	std::uint16_t make_announce_port(std::uint16_t const p)
1173 	{ return p == 0 ? 1 : p; }
1174 }
1175 
queue_tracker_request(tracker_request && req,std::weak_ptr<request_callback> c)1176 	void session_impl::queue_tracker_request(tracker_request&& req
1177 		, std::weak_ptr<request_callback> c)
1178 	{
1179 		req.listen_port = 0;
1180 #if TORRENT_USE_I2P
1181 		if (!m_settings.get_str(settings_pack::i2p_hostname).empty())
1182 		{
1183 			req.i2pconn = &m_i2p_conn;
1184 		}
1185 #endif
1186 
1187 #ifdef TORRENT_USE_OPENSSL
1188 		bool const use_ssl = req.ssl_ctx != nullptr && req.ssl_ctx != &m_ssl_ctx;
1189 		if (!use_ssl) req.ssl_ctx = &m_ssl_ctx;
1190 #endif
1191 
1192 		if (req.outgoing_socket)
1193 		{
1194 			auto ls = req.outgoing_socket.get();
1195 
1196 			req.listen_port =
1197 #if TORRENT_USE_I2P
1198 				(req.kind == tracker_request::i2p) ? 1 :
1199 #endif
1200 #ifdef TORRENT_USE_OPENSSL
1201 			// SSL torrents use the SSL listen port
1202 				use_ssl ? make_announce_port(ssl_listen_port(ls)) :
1203 #endif
1204 				make_announce_port(listen_port(ls));
1205 			m_tracker_manager.queue_request(get_io_service(), std::move(req)
1206 				, m_settings, c);
1207 		}
1208 		else
1209 		{
1210 			for (auto& ls : m_listen_sockets)
1211 			{
1212 				if (!(ls->flags & listen_socket_t::accept_incoming)) continue;
1213 #ifdef TORRENT_USE_OPENSSL
1214 				if ((ls->ssl == transport::ssl) != use_ssl) continue;
1215 #endif
1216 				tracker_request socket_req(req);
1217 				socket_req.listen_port =
1218 #if TORRENT_USE_I2P
1219 					(req.kind == tracker_request::i2p) ? 1 :
1220 #endif
1221 #ifdef TORRENT_USE_OPENSSL
1222 				// SSL torrents use the SSL listen port
1223 					use_ssl ? make_announce_port(ssl_listen_port(ls.get())) :
1224 #endif
1225 					make_announce_port(listen_port(ls.get()));
1226 
1227 				socket_req.outgoing_socket = ls;
1228 				m_tracker_manager.queue_request(get_io_service()
1229 					, std::move(socket_req), m_settings, c);
1230 			}
1231 		}
1232 	}
1233 
set_peer_class(peer_class_t const cid,peer_class_info const & pci)1234 	void session_impl::set_peer_class(peer_class_t const cid, peer_class_info const& pci)
1235 	{
1236 		peer_class* pc = m_classes.at(cid);
1237 		// if you hit this assert, you're passing in an invalid cid
1238 		TORRENT_ASSERT_PRECOND(pc);
1239 		if (pc == nullptr) return;
1240 
1241 		pc->set_info(&pci);
1242 	}
1243 
set_peer_class_filter(ip_filter const & f)1244 	void session_impl::set_peer_class_filter(ip_filter const& f)
1245 	{
1246 		INVARIANT_CHECK;
1247 		m_peer_class_filter = f;
1248 	}
1249 
get_peer_class_filter() const1250 	ip_filter const& session_impl::get_peer_class_filter() const
1251 	{
1252 		return m_peer_class_filter;
1253 	}
1254 
set_peer_class_type_filter(peer_class_type_filter f)1255 	void session_impl::set_peer_class_type_filter(peer_class_type_filter f)
1256 	{
1257 		m_peer_class_type_filter = f;
1258 	}
1259 
get_peer_class_type_filter()1260 	peer_class_type_filter session_impl::get_peer_class_type_filter()
1261 	{
1262 		return m_peer_class_type_filter;
1263 	}
1264 
set_peer_classes(peer_class_set * s,address const & a,int const st)1265 	void session_impl::set_peer_classes(peer_class_set* s, address const& a, int const st)
1266 	{
1267 		std::uint32_t peer_class_mask = m_peer_class_filter.access(a);
1268 
1269 		using sock_t = peer_class_type_filter::socket_type_t;
1270 		// assign peer class based on socket type
1271 		static const sock_t mapping[] = {
1272 			sock_t::tcp_socket, sock_t::tcp_socket
1273 			, sock_t::tcp_socket, sock_t::tcp_socket
1274 			, sock_t::utp_socket, sock_t::i2p_socket
1275 			, sock_t::ssl_tcp_socket, sock_t::ssl_tcp_socket
1276 			, sock_t::ssl_tcp_socket, sock_t::ssl_utp_socket
1277 		};
1278 		sock_t const socket_type = mapping[st];
1279 		// filter peer classes based on type
1280 		peer_class_mask = m_peer_class_type_filter.apply(socket_type, peer_class_mask);
1281 
1282 		for (peer_class_t i{0}; peer_class_mask; peer_class_mask >>= 1, ++i)
1283 		{
1284 			if ((peer_class_mask & 1) == 0) continue;
1285 
1286 			// if you hit this assert, your peer class filter contains
1287 			// a bitmask referencing a non-existent peer class
1288 			TORRENT_ASSERT_PRECOND(m_classes.at(i));
1289 
1290 			if (m_classes.at(i) == nullptr) continue;
1291 			s->add_class(m_classes, i);
1292 		}
1293 	}
1294 
ignore_unchoke_slots_set(peer_class_set const & set) const1295 	bool session_impl::ignore_unchoke_slots_set(peer_class_set const& set) const
1296 	{
1297 		int num = set.num_classes();
1298 		for (int i = 0; i < num; ++i)
1299 		{
1300 			peer_class const* pc = m_classes.at(set.class_at(i));
1301 			if (pc == nullptr) continue;
1302 			if (pc->ignore_unchoke_slots) return true;
1303 		}
1304 		return false;
1305 	}
1306 
get_bandwidth_manager(int channel)1307 	bandwidth_manager* session_impl::get_bandwidth_manager(int channel)
1308 	{
1309 		return (channel == peer_connection::download_channel)
1310 			? &m_download_rate : &m_upload_rate;
1311 	}
1312 
deferred_submit_jobs()1313 	void session_impl::deferred_submit_jobs()
1314 	{
1315 		if (m_deferred_submit_disk_jobs) return;
1316 		m_deferred_submit_disk_jobs = true;
1317 		m_io_service.post([this] { this->wrap(&session_impl::submit_disk_jobs); } );
1318 	}
1319 
submit_disk_jobs()1320 	void session_impl::submit_disk_jobs()
1321 	{
1322 		TORRENT_ASSERT(m_deferred_submit_disk_jobs);
1323 		m_deferred_submit_disk_jobs = false;
1324 		m_disk_thread.submit_jobs();
1325 	}
1326 
1327 	// copies pointers to bandwidth channels from the peer classes
1328 	// into the array. Only bandwidth channels with a bandwidth limit
1329 	// is considered pertinent and copied
1330 	// returns the number of pointers copied
1331 	// channel is upload_channel or download_channel
copy_pertinent_channels(peer_class_set const & set,int channel,bandwidth_channel ** dst,int const max)1332 	int session_impl::copy_pertinent_channels(peer_class_set const& set
1333 		, int channel, bandwidth_channel** dst, int const max)
1334 	{
1335 		int num_channels = set.num_classes();
1336 		int num_copied = 0;
1337 		for (int i = 0; i < num_channels; ++i)
1338 		{
1339 			peer_class* pc = m_classes.at(set.class_at(i));
1340 			TORRENT_ASSERT(pc);
1341 			if (pc == nullptr) continue;
1342 			bandwidth_channel* chan = &pc->channel[channel];
1343 			// no need to include channels that don't have any bandwidth limits
1344 			if (chan->throttle() == 0) continue;
1345 			dst[num_copied] = chan;
1346 			++num_copied;
1347 			if (num_copied == max) break;
1348 		}
1349 		return num_copied;
1350 	}
1351 
use_quota_overhead(bandwidth_channel * ch,int amount)1352 	bool session_impl::use_quota_overhead(bandwidth_channel* ch, int amount)
1353 	{
1354 		ch->use_quota(amount);
1355 		return (ch->throttle() > 0 && ch->throttle() < amount);
1356 	}
1357 
use_quota_overhead(peer_class_set & set,int const amount_down,int const amount_up)1358 	int session_impl::use_quota_overhead(peer_class_set& set, int const amount_down, int const amount_up)
1359 	{
1360 		int ret = 0;
1361 		int const num = set.num_classes();
1362 		for (int i = 0; i < num; ++i)
1363 		{
1364 			peer_class* p = m_classes.at(set.class_at(i));
1365 			if (p == nullptr) continue;
1366 
1367 			bandwidth_channel* ch = &p->channel[peer_connection::download_channel];
1368 			if (use_quota_overhead(ch, amount_down))
1369 				ret |= 1 << peer_connection::download_channel;
1370 			ch = &p->channel[peer_connection::upload_channel];
1371 			if (use_quota_overhead(ch, amount_up))
1372 				ret |= 1 << peer_connection::upload_channel;
1373 		}
1374 		return ret;
1375 	}
1376 
1377 	// session_impl is responsible for deleting 'pack'
apply_settings_pack(std::shared_ptr<settings_pack> pack)1378 	void session_impl::apply_settings_pack(std::shared_ptr<settings_pack> pack)
1379 	{
1380 		INVARIANT_CHECK;
1381 		apply_settings_pack_impl(*pack);
1382 	}
1383 
get_settings() const1384 	settings_pack session_impl::get_settings() const
1385 	{
1386 		settings_pack ret;
1387 		// TODO: it would be nice to reserve() these vectors up front
1388 		for (int i = settings_pack::string_type_base;
1389 			i < settings_pack::max_string_setting_internal; ++i)
1390 		{
1391 			ret.set_str(i, m_settings.get_str(i));
1392 		}
1393 		for (int i = settings_pack::int_type_base;
1394 			i < settings_pack::max_int_setting_internal; ++i)
1395 		{
1396 			ret.set_int(i, m_settings.get_int(i));
1397 		}
1398 		for (int i = settings_pack::bool_type_base;
1399 			i < settings_pack::max_bool_setting_internal; ++i)
1400 		{
1401 			ret.set_bool(i, m_settings.get_bool(i));
1402 		}
1403 		return ret;
1404 	}
1405 
apply_settings_pack_impl(settings_pack const & pack)1406 	void session_impl::apply_settings_pack_impl(settings_pack const& pack)
1407 	{
1408 		bool const reopen_listen_port =
1409 #if TORRENT_ABI_VERSION == 1
1410 			(pack.has_val(settings_pack::ssl_listen)
1411 				&& pack.get_int(settings_pack::ssl_listen)
1412 					!= m_settings.get_int(settings_pack::ssl_listen))
1413 			||
1414 #endif
1415 			(pack.has_val(settings_pack::listen_interfaces)
1416 				&& pack.get_str(settings_pack::listen_interfaces)
1417 					!= m_settings.get_str(settings_pack::listen_interfaces))
1418 			|| (pack.has_val(settings_pack::proxy_type)
1419 				&& pack.get_int(settings_pack::proxy_type)
1420 					!= m_settings.get_int(settings_pack::proxy_type))
1421 			|| (pack.has_val(settings_pack::proxy_peer_connections)
1422 				&& pack.get_bool(settings_pack::proxy_peer_connections)
1423 					!= m_settings.get_bool(settings_pack::proxy_peer_connections))
1424 			;
1425 
1426 #ifndef TORRENT_DISABLE_LOGGING
1427 		session_log("applying settings pack, reopen_listen_port=%s"
1428 			, reopen_listen_port ? "true" : "false");
1429 #endif
1430 
1431 		apply_pack(&pack, m_settings, this);
1432 		m_disk_thread.settings_updated();
1433 
1434 		if (!reopen_listen_port)
1435 		{
1436 			// no need to call this if reopen_listen_port is true
1437 			// since the apply_pack will do it
1438 			update_listen_interfaces();
1439 		}
1440 
1441 		if (reopen_listen_port)
1442 		{
1443 			reopen_listen_sockets();
1444 		}
1445 	}
1446 
setup_listener(listen_endpoint_t const & lep,error_code & ec)1447 	std::shared_ptr<listen_socket_t> session_impl::setup_listener(
1448 		listen_endpoint_t const& lep, error_code& ec)
1449 	{
1450 		int retries = m_settings.get_int(settings_pack::max_retry_port_bind);
1451 		tcp::endpoint bind_ep(lep.addr, std::uint16_t(lep.port));
1452 
1453 #ifndef TORRENT_DISABLE_LOGGING
1454 		if (should_log())
1455 		{
1456 			session_log("attempting to open listen socket to: %s on device: %s %s%s%s%s%s"
1457 				, print_endpoint(bind_ep).c_str(), lep.device.c_str()
1458 				, (lep.ssl == transport::ssl) ? "ssl " : ""
1459 				, (lep.flags & listen_socket_t::local_network) ? "local-network " : ""
1460 				, (lep.flags & listen_socket_t::accept_incoming) ? "accept-incoming " : "no-incoming "
1461 				, (lep.flags & listen_socket_t::was_expanded) ? "expanded-ip " : ""
1462 				, (lep.flags & listen_socket_t::proxy) ? "proxy " : "");
1463 		}
1464 #endif
1465 
1466 		auto ret = std::make_shared<listen_socket_t>();
1467 		ret->ssl = lep.ssl;
1468 		ret->original_port = bind_ep.port();
1469 		ret->flags = lep.flags;
1470 		ret->netmask = lep.netmask;
1471 		operation_t last_op = operation_t::unknown;
1472 		socket_type_t const sock_type
1473 			= (lep.ssl == transport::ssl)
1474 			? socket_type_t::tcp_ssl
1475 			: socket_type_t::tcp;
1476 
1477 		// if we're in force-proxy mode, don't open TCP listen sockets. We cannot
1478 		// accept connections on our local machine in this case.
1479 		// TODO: 3 the logic in this if-block should be factored out into a
1480 		// separate function. At least most of it
1481 		if (ret->flags & listen_socket_t::accept_incoming)
1482 		{
1483 			ret->sock = std::make_shared<tcp::acceptor>(m_io_service);
1484 			ret->sock->open(bind_ep.protocol(), ec);
1485 			last_op = operation_t::sock_open;
1486 			if (ec)
1487 			{
1488 #ifndef TORRENT_DISABLE_LOGGING
1489 				if (should_log())
1490 				{
1491 					session_log("failed to open socket: %s"
1492 						, ec.message().c_str());
1493 				}
1494 #endif
1495 
1496 				if (m_alerts.should_post<listen_failed_alert>())
1497 					m_alerts.emplace_alert<listen_failed_alert>(lep.device, bind_ep, last_op
1498 						, ec, sock_type);
1499 				return ret;
1500 			}
1501 
1502 #ifdef TORRENT_WINDOWS
1503 			{
1504 				// this is best-effort. ignore errors
1505 				error_code err;
1506 				ret->sock->set_option(exclusive_address_use(true), err);
1507 #ifndef TORRENT_DISABLE_LOGGING
1508 				if (err && should_log())
1509 				{
1510 					session_log("failed enable exclusive address use on listen socket: %s"
1511 						, err.message().c_str());
1512 				}
1513 #endif // TORRENT_DISABLE_LOGGING
1514 			}
1515 #else
1516 
1517 			{
1518 				// this is best-effort. ignore errors
1519 				error_code err;
1520 				ret->sock->set_option(tcp::acceptor::reuse_address(true), err);
1521 #ifndef TORRENT_DISABLE_LOGGING
1522 				if (err && should_log())
1523 				{
1524 					session_log("failed enable reuse-address on listen socket: %s"
1525 						, err.message().c_str());
1526 				}
1527 #endif // TORRENT_DISABLE_LOGGING
1528 			}
1529 #endif // TORRENT_WINDOWS
1530 
1531 			if (is_v6(bind_ep))
1532 			{
1533 				error_code err; // ignore errors here
1534 				ret->sock->set_option(boost::asio::ip::v6_only(true), err);
1535 #ifndef TORRENT_DISABLE_LOGGING
1536 				if (err && should_log())
1537 				{
1538 					session_log("failed enable v6 only on listen socket: %s"
1539 						, err.message().c_str());
1540 				}
1541 #endif // LOGGING
1542 
1543 #ifdef TORRENT_WINDOWS
1544 				// enable Teredo on windows
1545 				ret->sock->set_option(v6_protection_level(PROTECTION_LEVEL_UNRESTRICTED), err);
1546 #ifndef TORRENT_DISABLE_LOGGING
1547 				if (err && should_log())
1548 				{
1549 					session_log("failed enable IPv6 unrestricted protection level on "
1550 						"listen socket: %s", err.message().c_str());
1551 				}
1552 #endif // TORRENT_DISABLE_LOGGING
1553 #endif // TORRENT_WINDOWS
1554 			}
1555 
1556 			if (!lep.device.empty())
1557 			{
1558 				// we have an actual device we're interested in listening on, if we
1559 				// have SO_BINDTODEVICE functionality, use it now.
1560 #if TORRENT_HAS_BINDTODEVICE
1561 				bind_device(*ret->sock, lep.device.c_str(), ec);
1562 #ifndef TORRENT_DISABLE_LOGGING
1563 				if (ec && should_log())
1564 				{
1565 					session_log("bind to device failed (device: %s): %s"
1566 						, lep.device.c_str(), ec.message().c_str());
1567 				}
1568 #endif // TORRENT_DISABLE_LOGGING
1569 				ec.clear();
1570 #endif // TORRENT_HAS_BINDTODEVICE
1571 			}
1572 
1573 			ret->sock->bind(bind_ep, ec);
1574 			last_op = operation_t::sock_bind;
1575 
1576 			while (ec == error_code(error::address_in_use) && retries > 0)
1577 			{
1578 				TORRENT_ASSERT_VAL(ec, ec);
1579 #ifndef TORRENT_DISABLE_LOGGING
1580 				if (should_log())
1581 				{
1582 					session_log("failed to bind listen socket to: %s on device: %s :"
1583 						" [%s] (%d) %s (retries: %d)"
1584 						, print_endpoint(bind_ep).c_str()
1585 						, lep.device.c_str()
1586 						, ec.category().name(), ec.value(), ec.message().c_str()
1587 						, retries);
1588 				}
1589 #endif
1590 				ec.clear();
1591 				--retries;
1592 				bind_ep.port(bind_ep.port() + 1);
1593 				ret->sock->bind(bind_ep, ec);
1594 			}
1595 
1596 			if (ec == error_code(error::address_in_use)
1597 				&& m_settings.get_bool(settings_pack::listen_system_port_fallback)
1598 				&& bind_ep.port() != 0)
1599 			{
1600 				// instead of giving up, try let the OS pick a port
1601 				bind_ep.port(0);
1602 				ec.clear();
1603 				ret->sock->bind(bind_ep, ec);
1604 				last_op = operation_t::sock_bind;
1605 			}
1606 
1607 			if (ec)
1608 			{
1609 				// not even that worked, give up
1610 
1611 #ifndef TORRENT_DISABLE_LOGGING
1612 				if (should_log())
1613 				{
1614 					session_log("failed to bind listen socket to: %s on device: %s :"
1615 						" [%s] (%d) %s (giving up)"
1616 						, print_endpoint(bind_ep).c_str()
1617 						, lep.device.c_str()
1618 						, ec.category().name(), ec.value(), ec.message().c_str());
1619 				}
1620 #endif
1621 				if (m_alerts.should_post<listen_failed_alert>())
1622 				{
1623 					m_alerts.emplace_alert<listen_failed_alert>(lep.device, bind_ep
1624 						, last_op, ec, sock_type);
1625 				}
1626 				ret->sock.reset();
1627 				return ret;
1628 			}
1629 			ret->local_endpoint = ret->sock->local_endpoint(ec);
1630 			last_op = operation_t::getname;
1631 			if (ec)
1632 			{
1633 #ifndef TORRENT_DISABLE_LOGGING
1634 				if (should_log())
1635 				{
1636 					session_log("get_sockname failed on listen socket: %s"
1637 						, ec.message().c_str());
1638 				}
1639 #endif
1640 				if (m_alerts.should_post<listen_failed_alert>())
1641 				{
1642 					m_alerts.emplace_alert<listen_failed_alert>(lep.device, bind_ep
1643 						, last_op, ec, sock_type);
1644 				}
1645 				return ret;
1646 			}
1647 
1648 			TORRENT_ASSERT(ret->local_endpoint.port() == bind_ep.port()
1649 				|| bind_ep.port() == 0);
1650 
1651 			if (bind_ep.port() == 0) bind_ep = ret->local_endpoint;
1652 
1653 			ret->sock->listen(m_settings.get_int(settings_pack::listen_queue_size), ec);
1654 			last_op = operation_t::sock_listen;
1655 
1656 			if (ec)
1657 			{
1658 #ifndef TORRENT_DISABLE_LOGGING
1659 				if (should_log())
1660 				{
1661 					session_log("cannot listen on interface \"%s\": %s"
1662 						, lep.device.c_str(), ec.message().c_str());
1663 				}
1664 #endif
1665 				if (m_alerts.should_post<listen_failed_alert>())
1666 				{
1667 					m_alerts.emplace_alert<listen_failed_alert>(lep.device, bind_ep
1668 						, last_op, ec, sock_type);
1669 				}
1670 				return ret;
1671 			}
1672 		} // accept incoming
1673 
1674 		socket_type_t const udp_sock_type
1675 			= (lep.ssl == transport::ssl)
1676 			? socket_type_t::utp_ssl
1677 			: socket_type_t::udp;
1678 		udp::endpoint udp_bind_ep(bind_ep.address(), bind_ep.port());
1679 
1680 		ret->udp_sock = std::make_shared<session_udp_socket>(m_io_service, ret);
1681 		ret->udp_sock->sock.open(udp_bind_ep.protocol(), ec);
1682 		if (ec)
1683 		{
1684 #ifndef TORRENT_DISABLE_LOGGING
1685 			if (should_log())
1686 			{
1687 				session_log("failed to open UDP socket: %s: %s"
1688 					, lep.device.c_str(), ec.message().c_str());
1689 			}
1690 #endif
1691 
1692 			last_op = operation_t::sock_open;
1693 			if (m_alerts.should_post<listen_failed_alert>())
1694 				m_alerts.emplace_alert<listen_failed_alert>(lep.device
1695 					, bind_ep, last_op, ec, udp_sock_type);
1696 
1697 			return ret;
1698 		}
1699 
1700 #if TORRENT_HAS_BINDTODEVICE
1701 		if (!lep.device.empty())
1702 		{
1703 			bind_device(ret->udp_sock->sock, lep.device.c_str(), ec);
1704 #ifndef TORRENT_DISABLE_LOGGING
1705 			if (ec && should_log())
1706 			{
1707 				session_log("bind to device failed (device: %s): %s"
1708 					, lep.device.c_str(), ec.message().c_str());
1709 			}
1710 #endif // TORRENT_DISABLE_LOGGING
1711 			ec.clear();
1712 		}
1713 #endif
1714 		ret->udp_sock->sock.bind(udp_bind_ep, ec);
1715 
1716 		while (ec == error_code(error::address_in_use) && retries > 0)
1717 		{
1718 			TORRENT_ASSERT_VAL(ec, ec);
1719 #ifndef TORRENT_DISABLE_LOGGING
1720 			if (should_log())
1721 			{
1722 				session_log("failed to bind udp socket to: %s on device: %s :"
1723 					" [%s] (%d) %s (retries: %d)"
1724 					, print_endpoint(bind_ep).c_str()
1725 					, lep.device.c_str()
1726 					, ec.category().name(), ec.value(), ec.message().c_str()
1727 					, retries);
1728 			}
1729 #endif
1730 			ec.clear();
1731 			--retries;
1732 			udp_bind_ep.port(udp_bind_ep.port() + 1);
1733 			ret->udp_sock->sock.bind(udp_bind_ep, ec);
1734 		}
1735 
1736 		if (ec == error_code(error::address_in_use)
1737 			&& m_settings.get_bool(settings_pack::listen_system_port_fallback)
1738 			&& udp_bind_ep.port() != 0)
1739 		{
1740 			// instead of giving up, try let the OS pick a port
1741 			udp_bind_ep.port(0);
1742 			ec.clear();
1743 			ret->udp_sock->sock.bind(udp_bind_ep, ec);
1744 		}
1745 
1746 		last_op = operation_t::sock_bind;
1747 		if (ec)
1748 		{
1749 #ifndef TORRENT_DISABLE_LOGGING
1750 			if (should_log())
1751 			{
1752 				session_log("failed to bind UDP socket: %s: %s"
1753 					, lep.device.c_str(), ec.message().c_str());
1754 			}
1755 #endif
1756 
1757 			if (m_alerts.should_post<listen_failed_alert>())
1758 				m_alerts.emplace_alert<listen_failed_alert>(lep.device
1759 					, bind_ep, last_op, ec, udp_sock_type);
1760 
1761 			return ret;
1762 		}
1763 
1764 		// if we did not open a TCP listen socket, ret->local_endpoint was never
1765 		// initialized, so do that now, based on the UDP socket
1766 		if (!(ret->flags & listen_socket_t::accept_incoming))
1767 		{
1768 			auto const udp_ep = ret->udp_sock->local_endpoint();
1769 			ret->local_endpoint = tcp::endpoint(udp_ep.address(), udp_ep.port());
1770 		}
1771 
1772 		ret->device = lep.device;
1773 
1774 		error_code err;
1775 		set_socket_buffer_size(ret->udp_sock->sock, m_settings, err);
1776 		if (err)
1777 		{
1778 			if (m_alerts.should_post<udp_error_alert>())
1779 				m_alerts.emplace_alert<udp_error_alert>(ret->udp_sock->sock.local_endpoint(ec)
1780 					, operation_t::alloc_recvbuf, err);
1781 		}
1782 
1783 		// this call is necessary here because, unless the settings actually
1784 		// change after the session is up and listening, at no other point
1785 		// set_proxy_settings is called with the correct proxy configuration,
1786 		// internally, this method handle the SOCKS5's connection logic
1787 		ret->udp_sock->sock.set_proxy_settings(proxy(), m_alerts);
1788 
1789 		ADD_OUTSTANDING_ASYNC("session_impl::on_udp_packet");
1790 		ret->udp_sock->sock.async_read(aux::make_handler(std::bind(&session_impl::on_udp_packet
1791 			, this, ret->udp_sock, ret, ret->ssl, _1)
1792 			, ret->udp_handler_storage, *this));
1793 
1794 #ifndef TORRENT_DISABLE_LOGGING
1795 		if (should_log())
1796 		{
1797 			session_log(" listening on: %s TCP port: %d UDP port: %d"
1798 				, bind_ep.address().to_string().c_str()
1799 				, ret->tcp_external_port(), ret->udp_external_port());
1800 		}
1801 #endif
1802 		return ret;
1803 	}
1804 
on_exception(std::exception const & e)1805 	void session_impl::on_exception(std::exception const& e)
1806 	{
1807 		TORRENT_UNUSED(e);
1808 #ifndef TORRENT_DISABLE_LOGGING
1809 		session_log("FATAL SESSION ERROR [%s]", e.what());
1810 #endif
1811 		this->abort();
1812 	}
1813 
on_error(error_code const & ec)1814 	void session_impl::on_error(error_code const& ec)
1815 	{
1816 		TORRENT_UNUSED(ec);
1817 #ifndef TORRENT_DISABLE_LOGGING
1818 		session_log("FATAL SESSION ERROR (%s : %d) [%s]"
1819 			, ec.category().name(), ec.value(), ec.message().c_str());
1820 #endif
1821 		this->abort();
1822 	}
1823 
on_ip_change(error_code const & ec)1824 	void session_impl::on_ip_change(error_code const& ec)
1825 	{
1826 #ifndef TORRENT_DISABLE_LOGGING
1827 		if (!ec)
1828 			session_log("received ip change from internal ip_notifier");
1829 		else
1830 			session_log("received error on_ip_change: %d, %s", ec.value(), ec.message().c_str());
1831 #endif
1832 		if (ec || m_abort || !m_ip_notifier) return;
1833 		m_ip_notifier->async_wait([this] (error_code const& e)
1834 			{ this->wrap(&session_impl::on_ip_change, e); });
1835 		reopen_network_sockets({});
1836 	}
1837 
1838 	// TODO: could this function be merged with expand_unspecified_addresses?
1839 	// right now both listen_endpoint_t and listen_interface_t are almost
1840 	// identical, maybe the latter could be removed too
interface_to_endpoints(listen_interface_t const & iface,listen_socket_flags_t flags,span<ip_interface const> const ifs,std::vector<listen_endpoint_t> & eps)1841 	void interface_to_endpoints(listen_interface_t const& iface
1842 		, listen_socket_flags_t flags
1843 		, span<ip_interface const> const ifs
1844 		, std::vector<listen_endpoint_t>& eps)
1845 	{
1846 		flags |= iface.local ? listen_socket_t::local_network : listen_socket_flags_t{};
1847 		transport const ssl = iface.ssl ? transport::ssl : transport::plaintext;
1848 
1849 		// First, check to see if it's an IP address
1850 		error_code err;
1851 		address const adr = make_address(iface.device.c_str(), err);
1852 		if (!err)
1853 		{
1854 			eps.emplace_back(adr, iface.port, std::string{}, ssl, flags);
1855 		}
1856 		else
1857 		{
1858 			flags |= listen_socket_t::was_expanded;
1859 
1860 			// this is the case where device names a network device. We need to
1861 			// enumerate all IPs associated with this device
1862 			for (auto const& ipface : ifs)
1863 			{
1864 				// we're looking for a specific interface, and its address
1865 				// (which must be of the same family as the address we're
1866 				// connecting to)
1867 				if (iface.device != ipface.name) continue;
1868 
1869 				bool const local = iface.local
1870 					|| ipface.interface_address.is_loopback()
1871 					|| is_link_local(ipface.interface_address);
1872 
1873 				eps.emplace_back(ipface.interface_address, iface.port, iface.device
1874 					, ssl, flags | (local ? listen_socket_t::local_network : listen_socket_flags_t{}));
1875 			}
1876 		}
1877 	}
1878 
reopen_listen_sockets(bool const map_ports)1879 	void session_impl::reopen_listen_sockets(bool const map_ports)
1880 	{
1881 #ifndef TORRENT_DISABLE_LOGGING
1882 		session_log("reopen listen sockets");
1883 #endif
1884 
1885 		TORRENT_ASSERT(is_single_thread());
1886 
1887 		TORRENT_ASSERT(!m_abort);
1888 
1889 		error_code ec;
1890 
1891 		if (m_abort) return;
1892 
1893 		// first build a list of endpoints we should be listening on
1894 		// we need to remove any unneeded sockets first to avoid the possibility
1895 		// of a new socket failing to bind due to a conflict with a stale socket
1896 		std::vector<listen_endpoint_t> eps;
1897 
1898 		// if we don't proxy peer connections, don't apply the special logic for
1899 		// proxies
1900 		if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
1901 			&& m_settings.get_bool(settings_pack::proxy_peer_connections))
1902 		{
1903 			// we will be able to accept incoming connections over UDP. so use
1904 			// one of the ports the user specified to use a consistent port
1905 			// across sessions. If the user did not specify any ports, pick one
1906 			// at random
1907 			int const port = m_listen_interfaces.empty()
1908 				? int(random(63000) + 2000)
1909 				: m_listen_interfaces.front().port;
1910 			listen_endpoint_t ep(address_v4::any(), port, {}
1911 				, transport::plaintext, listen_socket_t::proxy);
1912 			eps.emplace_back(ep);
1913 		}
1914 		else
1915 		{
1916 			std::vector<ip_interface> const ifs = enum_net_interfaces(m_io_service, ec);
1917 			if (ec && m_alerts.should_post<listen_failed_alert>())
1918 			{
1919 				m_alerts.emplace_alert<listen_failed_alert>(""
1920 					, operation_t::enum_if, ec, socket_type_t::tcp);
1921 			}
1922 			auto const routes = enum_routes(m_io_service, ec);
1923 			if (ec && m_alerts.should_post<listen_failed_alert>())
1924 			{
1925 				m_alerts.emplace_alert<listen_failed_alert>(""
1926 					, operation_t::enum_route, ec, socket_type_t::tcp);
1927 			}
1928 
1929 			// expand device names and populate eps
1930 			for (auto const& iface : m_listen_interfaces)
1931 			{
1932 #ifndef TORRENT_USE_OPENSSL
1933 				if (iface.ssl)
1934 				{
1935 #ifndef TORRENT_DISABLE_LOGGING
1936 					session_log("attempted to listen ssl with no library support on device: \"%s\""
1937 						, iface.device.c_str());
1938 #endif
1939 					if (m_alerts.should_post<listen_failed_alert>())
1940 					{
1941 						m_alerts.emplace_alert<listen_failed_alert>(iface.device
1942 							, operation_t::sock_open
1943 							, boost::asio::error::operation_not_supported
1944 							, socket_type_t::tcp_ssl);
1945 					}
1946 					continue;
1947 				}
1948 #endif
1949 
1950 				// now we have a device to bind to. This device may actually just be an
1951 				// IP address or a device name. In case it's a device name, we want to
1952 				// (potentially) end up binding a socket for each IP address associated
1953 				// with that device.
1954 				interface_to_endpoints(iface, listen_socket_t::accept_incoming, ifs, eps);
1955 			}
1956 
1957 			if (eps.empty())
1958 			{
1959 #ifndef TORRENT_DISABLE_LOGGING
1960 				session_log("no listen sockets");
1961 #endif
1962 			}
1963 
1964 			expand_unspecified_address(ifs, routes, eps);
1965 			expand_devices(ifs, eps);
1966 		}
1967 
1968 		auto remove_iter = partition_listen_sockets(eps, m_listen_sockets);
1969 
1970 		while (remove_iter != m_listen_sockets.end())
1971 		{
1972 #ifndef TORRENT_DISABLE_DHT
1973 			if (m_dht)
1974 				m_dht->delete_socket(*remove_iter);
1975 #endif
1976 
1977 #ifndef TORRENT_DISABLE_LOGGING
1978 			if (should_log())
1979 			{
1980 				session_log("closing listen socket for %s on device \"%s\""
1981 					, print_endpoint((*remove_iter)->local_endpoint).c_str()
1982 					, (*remove_iter)->device.c_str());
1983 			}
1984 #endif
1985 			if ((*remove_iter)->sock) (*remove_iter)->sock->close(ec);
1986 			if ((*remove_iter)->udp_sock) (*remove_iter)->udp_sock->sock.close();
1987 			if ((*remove_iter)->natpmp_mapper) (*remove_iter)->natpmp_mapper->close();
1988 			if ((*remove_iter)->upnp_mapper) (*remove_iter)->upnp_mapper->close();
1989 			if ((*remove_iter)->lsd) (*remove_iter)->lsd->close();
1990 			remove_iter = m_listen_sockets.erase(remove_iter);
1991 		}
1992 
1993 		// all sockets in there stayed the same. Only sockets after this point are
1994 		// new and should post alerts
1995 		int const existing_sockets = int(m_listen_sockets.size());
1996 
1997 		m_stats_counters.set_value(counters::has_incoming_connections
1998 			, std::any_of(m_listen_sockets.begin(), m_listen_sockets.end()
1999 				, [](std::shared_ptr<listen_socket_t> const& l)
2000 				{ return l->incoming_connection; }));
2001 
2002 		// open new sockets on any endpoints that didn't match with
2003 		// an existing socket
2004 		for (auto const& ep : eps)
2005 		{
2006 #ifndef BOOST_NO_EXCEPTIONS
2007 			try
2008 #endif
2009 		{
2010 			std::shared_ptr<listen_socket_t> s = setup_listener(ep, ec);
2011 
2012 			if (!ec && (s->sock || s->udp_sock))
2013 			{
2014 				m_listen_sockets.emplace_back(s);
2015 
2016 #ifndef TORRENT_DISABLE_DHT
2017 				if (m_dht
2018 					&& s->ssl != transport::ssl
2019 					&& !(s->flags & listen_socket_t::local_network))
2020 				{
2021 					m_dht->new_socket(m_listen_sockets.back());
2022 				}
2023 #endif
2024 
2025 				TORRENT_ASSERT(bool(s->flags & listen_socket_t::accept_incoming) == bool(s->sock));
2026 				if (s->sock) async_accept(s->sock, s->ssl);
2027 			}
2028 		}
2029 #ifndef BOOST_NO_EXCEPTIONS
2030 		catch (std::exception const& e)
2031 		{
2032 			TORRENT_UNUSED(e);
2033 #ifndef TORRENT_DISABLE_LOGGING
2034 			if (should_log())
2035 			{
2036 				session_log("setup_listener(%s) device: %s failed: %s"
2037 					, print_endpoint(ep.addr, ep.port).c_str()
2038 					, ep.device.c_str()
2039 					, e.what());
2040 			}
2041 #endif // TORRENT_DISABLE_LOGGING
2042 		}
2043 #endif // BOOST_NO_EXCEPTIONS
2044 		}
2045 
2046 		if (m_listen_sockets.empty())
2047 		{
2048 #ifndef TORRENT_DISABLE_LOGGING
2049 			session_log("giving up on binding listen sockets");
2050 #endif
2051 			return;
2052 		}
2053 
2054 		auto const new_sockets = span<std::shared_ptr<listen_socket_t>>(
2055 			m_listen_sockets).subspan(existing_sockets);
2056 
2057 		// now, send out listen_succeeded_alert for the listen sockets we are
2058 		// listening on
2059 		if (m_alerts.should_post<listen_succeeded_alert>())
2060 		{
2061 			for (auto const& l : new_sockets)
2062 			{
2063 				error_code err;
2064 				if (l->sock)
2065 				{
2066 					tcp::endpoint const tcp_ep = l->sock->local_endpoint(err);
2067 					if (!err)
2068 					{
2069 						socket_type_t const socket_type
2070 							= l->ssl == transport::ssl
2071 							? socket_type_t::tcp_ssl
2072 							: socket_type_t::tcp;
2073 
2074 						m_alerts.emplace_alert<listen_succeeded_alert>(
2075 							tcp_ep, socket_type);
2076 					}
2077 				}
2078 
2079 				if (l->udp_sock)
2080 				{
2081 					udp::endpoint const udp_ep = l->udp_sock->sock.local_endpoint(err);
2082 					if (!err && l->udp_sock->sock.is_open())
2083 					{
2084 						socket_type_t const socket_type
2085 							= l->ssl == transport::ssl
2086 							? socket_type_t::utp_ssl
2087 							: socket_type_t::udp;
2088 
2089 						m_alerts.emplace_alert<listen_succeeded_alert>(
2090 							udp_ep, socket_type);
2091 					}
2092 				}
2093 			}
2094 		}
2095 
2096 		if (m_settings.get_int(settings_pack::peer_tos) != 0)
2097 		{
2098 			update_peer_tos();
2099 		}
2100 
2101 		ec.clear();
2102 
2103 		if (m_settings.get_bool(settings_pack::enable_natpmp))
2104 		{
2105 			for (auto const& s : new_sockets)
2106 				start_natpmp(*s);
2107 		}
2108 
2109 		if (m_settings.get_bool(settings_pack::enable_upnp))
2110 		{
2111 			for (auto const& s : new_sockets)
2112 				start_upnp(*s);
2113 		}
2114 
2115 		if (map_ports)
2116 		{
2117 			for (auto const& s : m_listen_sockets)
2118 				remap_ports(remap_natpmp_and_upnp, *s);
2119 		}
2120 		else
2121 		{
2122 			// new sockets need to map ports even if the caller did not request
2123 			// re-mapping
2124 			for (auto const& s : new_sockets)
2125 				remap_ports(remap_natpmp_and_upnp, *s);
2126 		}
2127 
2128 		update_lsd();
2129 
2130 #if TORRENT_USE_I2P
2131 		open_new_incoming_i2p_connection();
2132 #endif
2133 
2134 		// trackers that were not reachable, may have become reachable now.
2135 		// so clear the "disabled" flags to let them be tried one more time
2136 		// TODO: it would probably be better to do this by having a
2137 		// listen-socket "version" number that gets bumped. And instead of
2138 		// setting a bool to disable a tracker, we set the version number that
2139 		// it was disabled at. This change would affect the ABI in 1.2, so
2140 		// should be done in 2.0 or later
2141 		for (auto& t : m_torrents)
2142 			t.second->enable_all_trackers();
2143 	}
2144 
reopen_network_sockets(reopen_network_flags_t const options)2145 	void session_impl::reopen_network_sockets(reopen_network_flags_t const options)
2146 	{
2147 		reopen_listen_sockets(bool(options & session_handle::reopen_map_ports));
2148 	}
2149 
2150 	namespace {
2151 		template <typename MapProtocol, typename ProtoType, typename EndpointType>
map_port(MapProtocol & m,ProtoType protocol,EndpointType const & ep,port_mapping_t & map_handle)2152 		void map_port(MapProtocol& m, ProtoType protocol, EndpointType const& ep
2153 			, port_mapping_t& map_handle)
2154 		{
2155 			if (map_handle != port_mapping_t{-1}) m.delete_mapping(map_handle);
2156 			map_handle = port_mapping_t{-1};
2157 
2158 			address const addr = ep.address();
2159 			// with IPv4 the interface might be behind NAT so we can't skip them
2160 			// based on the scope of the local address
2161 			if (addr.is_v6() && is_local(addr))
2162 				return;
2163 
2164 			// only update this mapping if we actually have a socket listening
2165 			if (ep != EndpointType())
2166 				map_handle = m.add_mapping(protocol, ep.port(), ep);
2167 		}
2168 	}
2169 
remap_ports(remap_port_mask_t const mask,listen_socket_t & s)2170 	void session_impl::remap_ports(remap_port_mask_t const mask
2171 		, listen_socket_t& s)
2172 	{
2173 		tcp::endpoint const tcp_ep = s.sock ? s.sock->local_endpoint() : tcp::endpoint();
2174 		udp::endpoint const udp_ep = s.udp_sock ? s.udp_sock->sock.local_endpoint() : udp::endpoint();
2175 
2176 		if ((mask & remap_natpmp) && s.natpmp_mapper)
2177 		{
2178 			map_port(*s.natpmp_mapper, portmap_protocol::tcp, tcp_ep
2179 				, s.tcp_port_mapping[portmap_transport::natpmp].mapping);
2180 			map_port(*s.natpmp_mapper, portmap_protocol::udp, make_tcp(udp_ep)
2181 				, s.udp_port_mapping[portmap_transport::natpmp].mapping);
2182 		}
2183 		if ((mask & remap_upnp) && s.upnp_mapper)
2184 		{
2185 			map_port(*s.upnp_mapper, portmap_protocol::tcp, tcp_ep
2186 				, s.tcp_port_mapping[portmap_transport::upnp].mapping);
2187 			map_port(*s.upnp_mapper, portmap_protocol::udp, make_tcp(udp_ep)
2188 				, s.udp_port_mapping[portmap_transport::upnp].mapping);
2189 		}
2190 	}
2191 
update_i2p_bridge()2192 	void session_impl::update_i2p_bridge()
2193 	{
2194 		// we need this socket to be open before we
2195 		// can make name lookups for trackers for instance.
2196 		// pause the session now and resume it once we've
2197 		// established the i2p SAM connection
2198 #if TORRENT_USE_I2P
2199 		if (m_settings.get_str(settings_pack::i2p_hostname).empty())
2200 		{
2201 			error_code ec;
2202 			m_i2p_conn.close(ec);
2203 			return;
2204 		}
2205 		m_i2p_conn.open(m_settings.get_str(settings_pack::i2p_hostname)
2206 			, m_settings.get_int(settings_pack::i2p_port)
2207 			, std::bind(&session_impl::on_i2p_open, this, _1));
2208 #endif
2209 	}
2210 
2211 #ifndef TORRENT_DISABLE_DHT
external_udp_port(address const & local_address) const2212 	int session_impl::external_udp_port(address const& local_address) const
2213 	{
2214 		auto ls = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
2215 			, [&](std::shared_ptr<listen_socket_t> const& e)
2216 		{
2217 			return e->local_endpoint.address() == local_address;
2218 		});
2219 
2220 		if (ls != m_listen_sockets.end())
2221 			return (*ls)->udp_external_port();
2222 		else
2223 			return -1;
2224 	}
2225 #endif
2226 
2227 #if TORRENT_USE_I2P
2228 
i2p_proxy() const2229 	proxy_settings session_impl::i2p_proxy() const
2230 	{
2231 		proxy_settings ret;
2232 
2233 		ret.hostname = m_settings.get_str(settings_pack::i2p_hostname);
2234 		ret.type = settings_pack::i2p_proxy;
2235 		ret.port = std::uint16_t(m_settings.get_int(settings_pack::i2p_port));
2236 		return ret;
2237 	}
2238 
on_i2p_open(error_code const & ec)2239 	void session_impl::on_i2p_open(error_code const& ec)
2240 	{
2241 		if (ec)
2242 		{
2243 			if (m_alerts.should_post<i2p_alert>())
2244 				m_alerts.emplace_alert<i2p_alert>(ec);
2245 
2246 #ifndef TORRENT_DISABLE_LOGGING
2247 			if (should_log())
2248 				session_log("i2p open failed (%d) %s", ec.value(), ec.message().c_str());
2249 #endif
2250 		}
2251 		// now that we have our i2p connection established
2252 		// it's OK to start torrents and use this socket to
2253 		// do i2p name lookups
2254 
2255 		open_new_incoming_i2p_connection();
2256 	}
2257 
open_new_incoming_i2p_connection()2258 	void session_impl::open_new_incoming_i2p_connection()
2259 	{
2260 		if (!m_i2p_conn.is_open()) return;
2261 
2262 		if (m_i2p_listen_socket) return;
2263 
2264 		m_i2p_listen_socket = std::make_shared<socket_type>(m_io_service);
2265 		bool ret = instantiate_connection(m_io_service, m_i2p_conn.proxy()
2266 			, *m_i2p_listen_socket, nullptr, nullptr, true, false);
2267 		TORRENT_ASSERT_VAL(ret, ret);
2268 		TORRENT_UNUSED(ret);
2269 
2270 		ADD_OUTSTANDING_ASYNC("session_impl::on_i2p_accept");
2271 		i2p_stream& s = *m_i2p_listen_socket->get<i2p_stream>();
2272 		s.set_command(i2p_stream::cmd_accept);
2273 		s.set_session_id(m_i2p_conn.session_id());
2274 
2275 		s.async_connect(tcp::endpoint()
2276 			, std::bind(&session_impl::on_i2p_accept, this, m_i2p_listen_socket, _1));
2277 	}
2278 
on_i2p_accept(std::shared_ptr<socket_type> const & s,error_code const & e)2279 	void session_impl::on_i2p_accept(std::shared_ptr<socket_type> const& s
2280 		, error_code const& e)
2281 	{
2282 		COMPLETE_ASYNC("session_impl::on_i2p_accept");
2283 		m_i2p_listen_socket.reset();
2284 		if (e == boost::asio::error::operation_aborted) return;
2285 		if (e)
2286 		{
2287 			if (m_alerts.should_post<listen_failed_alert>())
2288 			{
2289 				m_alerts.emplace_alert<listen_failed_alert>("i2p"
2290 					, operation_t::sock_accept
2291 					, e, socket_type_t::i2p);
2292 			}
2293 #ifndef TORRENT_DISABLE_LOGGING
2294 			if (should_log())
2295 				session_log("i2p SAM connection failure: %s", e.message().c_str());
2296 #endif
2297 			return;
2298 		}
2299 		open_new_incoming_i2p_connection();
2300 		incoming_connection(s);
2301 	}
2302 #endif
2303 
send_udp_packet_hostname(std::weak_ptr<utp_socket_interface> sock,char const * hostname,int const port,span<char const> p,error_code & ec,udp_send_flags_t const flags)2304 	void session_impl::send_udp_packet_hostname(std::weak_ptr<utp_socket_interface> sock
2305 		, char const* hostname
2306 		, int const port
2307 		, span<char const> p
2308 		, error_code& ec
2309 		, udp_send_flags_t const flags)
2310 	{
2311 		auto si = sock.lock();
2312 		if (!si)
2313 		{
2314 			ec = boost::asio::error::bad_descriptor;
2315 			return;
2316 		}
2317 
2318 		auto s = std::static_pointer_cast<aux::listen_socket_t>(si)->udp_sock;
2319 
2320 		s->sock.send_hostname(hostname, port, p, ec, flags);
2321 
2322 		if ((ec == error::would_block || ec == error::try_again)
2323 			&& !s->write_blocked)
2324 		{
2325 			s->write_blocked = true;
2326 			ADD_OUTSTANDING_ASYNC("session_impl::on_udp_writeable");
2327 			s->sock.async_write(std::bind(&session_impl::on_udp_writeable
2328 				, this, s, _1));
2329 		}
2330 	}
2331 
send_udp_packet(std::weak_ptr<utp_socket_interface> sock,udp::endpoint const & ep,span<char const> p,error_code & ec,udp_send_flags_t const flags)2332 	void session_impl::send_udp_packet(std::weak_ptr<utp_socket_interface> sock
2333 		, udp::endpoint const& ep
2334 		, span<char const> p
2335 		, error_code& ec
2336 		, udp_send_flags_t const flags)
2337 	{
2338 		auto si = sock.lock();
2339 		if (!si)
2340 		{
2341 			ec = boost::asio::error::bad_descriptor;
2342 			return;
2343 		}
2344 
2345 		auto s = std::static_pointer_cast<aux::listen_socket_t>(si)->udp_sock;
2346 
2347 		TORRENT_ASSERT(s->sock.is_closed() || s->sock.local_endpoint().protocol() == ep.protocol());
2348 
2349 		s->sock.send(ep, p, ec, flags);
2350 
2351 		if ((ec == error::would_block || ec == error::try_again) && !s->write_blocked)
2352 		{
2353 			s->write_blocked = true;
2354 			ADD_OUTSTANDING_ASYNC("session_impl::on_udp_writeable");
2355 			s->sock.async_write(std::bind(&session_impl::on_udp_writeable
2356 				, this, s, _1));
2357 		}
2358 	}
2359 
on_udp_writeable(std::weak_ptr<session_udp_socket> sock,error_code const & ec)2360 	void session_impl::on_udp_writeable(std::weak_ptr<session_udp_socket> sock, error_code const& ec)
2361 	{
2362 		COMPLETE_ASYNC("session_impl::on_udp_writeable");
2363 		if (ec) return;
2364 
2365 		auto s = sock.lock();
2366 		if (!s) return;
2367 
2368 		s->write_blocked = false;
2369 
2370 #ifdef TORRENT_USE_OPENSSL
2371 		auto i = std::find_if(
2372 			m_listen_sockets.begin(), m_listen_sockets.end()
2373 			, [&s] (std::shared_ptr<listen_socket_t> const& ls) { return ls->udp_sock == s; });
2374 #endif
2375 
2376 		// notify the utp socket manager it can start sending on the socket again
2377 		struct utp_socket_manager& mgr =
2378 #ifdef TORRENT_USE_OPENSSL
2379 			(i != m_listen_sockets.end() && (*i)->ssl == transport::ssl) ? m_ssl_utp_socket_manager :
2380 #endif
2381 			m_utp_socket_manager;
2382 
2383 		mgr.writable();
2384 	}
2385 
2386 
on_udp_packet(std::weak_ptr<session_udp_socket> socket,std::weak_ptr<listen_socket_t> ls,transport const ssl,error_code const & ec)2387 	void session_impl::on_udp_packet(std::weak_ptr<session_udp_socket> socket
2388 		, std::weak_ptr<listen_socket_t> ls, transport const ssl, error_code const& ec)
2389 	{
2390 		COMPLETE_ASYNC("session_impl::on_udp_packet");
2391 		if (ec)
2392 		{
2393 			std::shared_ptr<session_udp_socket> s = socket.lock();
2394 			udp::endpoint ep;
2395 			if (s) ep = s->local_endpoint();
2396 
2397 			// don't bubble up operation aborted errors to the user
2398 			if (ec != boost::asio::error::operation_aborted
2399 				&& ec != boost::asio::error::bad_descriptor
2400 				&& m_alerts.should_post<udp_error_alert>())
2401 			{
2402 				m_alerts.emplace_alert<udp_error_alert>(ep
2403 					, operation_t::sock_read, ec);
2404 			}
2405 
2406 #ifndef TORRENT_DISABLE_LOGGING
2407 			if (should_log())
2408 			{
2409 				session_log("UDP error: %s (%d) %s"
2410 					, print_endpoint(ep).c_str(), ec.value(), ec.message().c_str());
2411 			}
2412 #endif
2413 			return;
2414 		}
2415 
2416 		m_stats_counters.inc_stats_counter(counters::on_udp_counter);
2417 
2418 		std::shared_ptr<session_udp_socket> s = socket.lock();
2419 		if (!s) return;
2420 
2421 		struct utp_socket_manager& mgr =
2422 #ifdef TORRENT_USE_OPENSSL
2423 			ssl == transport::ssl ? m_ssl_utp_socket_manager :
2424 #endif
2425 			m_utp_socket_manager;
2426 
2427 		for (;;)
2428 		{
2429 			aux::array<udp_socket::packet, 50> p;
2430 			error_code err;
2431 			int const num_packets = s->sock.read(p, err);
2432 
2433 			for (int i = 0; i < num_packets; ++i)
2434 			{
2435 				udp_socket::packet& packet = p[i];
2436 
2437 				if (packet.error)
2438 				{
2439 					// TODO: 3 it would be neat if the utp socket manager would
2440 					// handle ICMP errors too
2441 
2442 #ifndef TORRENT_DISABLE_DHT
2443 					if (m_dht)
2444 						m_dht->incoming_error(packet.error, packet.from);
2445 #endif
2446 
2447 					m_tracker_manager.incoming_error(packet.error, packet.from);
2448 					continue;
2449 				}
2450 
2451 				span<char const> const buf = packet.data;
2452 
2453 				// give the uTP socket manager first dibs on the packet. Presumably
2454 				// the majority of packets are uTP packets.
2455 				if (!mgr.incoming_packet(ls, packet.from, buf))
2456 				{
2457 					// if it wasn't a uTP packet, try the other users of the UDP
2458 					// socket
2459 					bool handled = false;
2460 #ifndef TORRENT_DISABLE_DHT
2461 					auto listen_socket = ls.lock();
2462 					if (m_dht && buf.size() > 20
2463 						&& buf.front() == 'd'
2464 						&& buf.back() == 'e'
2465 						&& listen_socket)
2466 					{
2467 						handled = m_dht->incoming_packet(listen_socket, packet.from, buf);
2468 					}
2469 #endif
2470 
2471 					if (!handled)
2472 					{
2473 						m_tracker_manager.incoming_packet(packet.from, buf);
2474 					}
2475 				}
2476 			}
2477 
2478 			if (err == error::would_block || err == error::try_again)
2479 			{
2480 				// there are no more packets on the socket
2481 				break;
2482 			}
2483 
2484 			if (err)
2485 			{
2486 				udp::endpoint const ep = s->local_endpoint();
2487 
2488 				if (err != boost::asio::error::operation_aborted
2489 					&& m_alerts.should_post<udp_error_alert>())
2490 					m_alerts.emplace_alert<udp_error_alert>(ep
2491 						, operation_t::sock_read, err);
2492 
2493 #ifndef TORRENT_DISABLE_LOGGING
2494 				if (should_log())
2495 				{
2496 					session_log("UDP error: %s (%d) %s"
2497 						, print_endpoint(ep).c_str(), ec.value(), ec.message().c_str());
2498 				}
2499 #endif
2500 
2501 				// any error other than these ones are considered fatal errors, and
2502 				// we won't read from the socket again
2503 				if (err != boost::asio::error::host_unreachable
2504 					&& err != boost::asio::error::fault
2505 					&& err != boost::asio::error::connection_reset
2506 					&& err != boost::asio::error::connection_refused
2507 					&& err != boost::asio::error::connection_aborted
2508 					&& err != boost::asio::error::operation_aborted
2509 					&& err != boost::asio::error::network_reset
2510 					&& err != boost::asio::error::network_unreachable
2511 #ifdef _WIN32
2512 					// ERROR_MORE_DATA means the same thing as EMSGSIZE
2513 					&& err != error_code(ERROR_MORE_DATA, system_category())
2514 					&& err != error_code(ERROR_HOST_UNREACHABLE, system_category())
2515 					&& err != error_code(ERROR_PORT_UNREACHABLE, system_category())
2516 					&& err != error_code(ERROR_RETRY, system_category())
2517 					&& err != error_code(ERROR_NETWORK_UNREACHABLE, system_category())
2518 					&& err != error_code(ERROR_CONNECTION_REFUSED, system_category())
2519 					&& err != error_code(ERROR_CONNECTION_ABORTED, system_category())
2520 #endif
2521 					&& err != boost::asio::error::message_size)
2522 				{
2523 					// fatal errors. Don't try to read from this socket again
2524 					mgr.socket_drained();
2525 					return;
2526 				}
2527 				// non-fatal UDP errors get here, we should re-issue the read.
2528 				continue;
2529 			}
2530 		}
2531 
2532 		mgr.socket_drained();
2533 
2534 		ADD_OUTSTANDING_ASYNC("session_impl::on_udp_packet");
2535 		s->sock.async_read(make_handler(std::bind(&session_impl::on_udp_packet
2536 			, this, std::move(socket), std::move(ls), ssl, _1), s->udp_handler_storage
2537 				, *this));
2538 	}
2539 
async_accept(std::shared_ptr<tcp::acceptor> const & listener,transport const ssl)2540 	void session_impl::async_accept(std::shared_ptr<tcp::acceptor> const& listener
2541 		, transport const ssl)
2542 	{
2543 		TORRENT_ASSERT(!m_abort);
2544 		std::shared_ptr<socket_type> c = std::make_shared<socket_type>(m_io_service);
2545 		tcp::socket* str = nullptr;
2546 
2547 #ifdef TORRENT_USE_OPENSSL
2548 		if (ssl == transport::ssl)
2549 		{
2550 			// accept connections initializing the SSL connection to use the peer
2551 			// ssl context. Since it has the servername callback set on it, we will
2552 			// switch away from this context into a specific torrent once we start
2553 			// handshaking
2554 			c->instantiate<ssl_stream<tcp::socket>>(m_io_service, &m_peer_ssl_ctx);
2555 			str = &c->get<ssl_stream<tcp::socket>>()->next_layer();
2556 		}
2557 		else
2558 #endif
2559 		{
2560 			c->instantiate<tcp::socket>(m_io_service);
2561 			str = c->get<tcp::socket>();
2562 		}
2563 
2564 		ADD_OUTSTANDING_ASYNC("session_impl::on_accept_connection");
2565 
2566 #ifdef TORRENT_USE_OPENSSL
2567 		TORRENT_ASSERT((ssl == transport::ssl) == is_ssl(*c));
2568 #endif
2569 
2570 		std::weak_ptr<tcp::acceptor> ls(listener);
2571 		m_stats_counters.inc_stats_counter(counters::num_outstanding_accept);
2572 		listener->async_accept(*str, [this, c, ls, ssl] (error_code const& ec)
2573 			{ return this->wrap(&session_impl::on_accept_connection, c, ls, ec, ssl); });
2574 	}
2575 
on_accept_connection(std::shared_ptr<socket_type> const & s,std::weak_ptr<tcp::acceptor> listen_socket,error_code const & e,transport const ssl)2576 	void session_impl::on_accept_connection(std::shared_ptr<socket_type> const& s
2577 		, std::weak_ptr<tcp::acceptor> listen_socket, error_code const& e
2578 		, transport const ssl)
2579 	{
2580 		COMPLETE_ASYNC("session_impl::on_accept_connection");
2581 		m_stats_counters.inc_stats_counter(counters::on_accept_counter);
2582 		m_stats_counters.inc_stats_counter(counters::num_outstanding_accept, -1);
2583 
2584 		TORRENT_ASSERT(is_single_thread());
2585 		std::shared_ptr<tcp::acceptor> listener = listen_socket.lock();
2586 		if (!listener) return;
2587 
2588 		if (e == boost::asio::error::operation_aborted) return;
2589 
2590 		if (m_abort) return;
2591 
2592 		error_code ec;
2593 		if (e)
2594 		{
2595 			tcp::endpoint const ep = listener->local_endpoint(ec);
2596 #ifndef TORRENT_DISABLE_LOGGING
2597 			if (should_log())
2598 			{
2599 				session_log("error accepting connection on '%s': %s"
2600 					, print_endpoint(ep).c_str(), e.message().c_str());
2601 			}
2602 #endif
2603 #ifdef TORRENT_WINDOWS
2604 			// Windows sometimes generates this error. It seems to be
2605 			// non-fatal and we have to do another async_accept.
2606 			if (e.value() == ERROR_SEM_TIMEOUT)
2607 			{
2608 				async_accept(listener, ssl);
2609 				return;
2610 			}
2611 #endif
2612 #ifdef TORRENT_BSD
2613 			// Leopard sometimes generates an "invalid argument" error. It seems to be
2614 			// non-fatal and we have to do another async_accept.
2615 			if (e.value() == EINVAL)
2616 			{
2617 				async_accept(listener, ssl);
2618 				return;
2619 			}
2620 #endif
2621 			if (e == boost::system::errc::too_many_files_open)
2622 			{
2623 				// if we failed to accept an incoming connection
2624 				// because we have too many files open, try again
2625 				// and lower the number of file descriptors used
2626 				// elsewhere.
2627 				if (m_settings.get_int(settings_pack::connections_limit) > 10)
2628 				{
2629 					// now, disconnect a random peer
2630 					auto const i = std::max_element(m_torrents.begin(), m_torrents.end()
2631 						, [](torrent_map::value_type const& lhs, torrent_map::value_type const& rhs)
2632 						{ return lhs.second->num_peers() < rhs.second->num_peers(); });
2633 
2634 					if (m_alerts.should_post<performance_alert>())
2635 						m_alerts.emplace_alert<performance_alert>(
2636 							torrent_handle(), performance_alert::too_few_file_descriptors);
2637 
2638 					if (i != m_torrents.end())
2639 					{
2640 						i->second->disconnect_peers(1, e);
2641 					}
2642 
2643 					m_settings.set_int(settings_pack::connections_limit
2644 						, std::max(10, int(m_connections.size())));
2645 				}
2646 				// try again, but still alert the user of the problem
2647 				async_accept(listener, ssl);
2648 			}
2649 			if (m_alerts.should_post<listen_failed_alert>())
2650 			{
2651 				error_code err;
2652 				m_alerts.emplace_alert<listen_failed_alert>(ep.address().to_string(err)
2653 					, ep, operation_t::sock_accept, e
2654 					, ssl == transport::ssl ? socket_type_t::tcp_ssl : socket_type_t::tcp);
2655 			}
2656 			return;
2657 		}
2658 		async_accept(listener, ssl);
2659 
2660 		// don't accept any connections from our local sockets if we're using a
2661 		// proxy
2662 		if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
2663 			&& m_settings.get_bool(settings_pack::proxy_peer_connections))
2664 			return;
2665 
2666 		auto listen = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
2667 			, [&listener](std::shared_ptr<listen_socket_t> const& l)
2668 		{ return l->sock == listener; });
2669 		if (listen != m_listen_sockets.end())
2670 			(*listen)->incoming_connection = true;
2671 
2672 #ifdef TORRENT_USE_OPENSSL
2673 		if (ssl == transport::ssl)
2674 		{
2675 			TORRENT_ASSERT(is_ssl(*s));
2676 
2677 			// for SSL connections, incoming_connection() is called
2678 			// after the handshake is done
2679 			ADD_OUTSTANDING_ASYNC("session_impl::ssl_handshake");
2680 			s->get<ssl_stream<tcp::socket>>()->async_accept_handshake(
2681 				std::bind(&session_impl::ssl_handshake, this, _1, s));
2682 			m_incoming_sockets.insert(s);
2683 		}
2684 		else
2685 #endif
2686 		{
2687 			incoming_connection(s);
2688 		}
2689 	}
2690 
2691 #ifdef TORRENT_USE_OPENSSL
2692 
on_incoming_utp_ssl(std::shared_ptr<socket_type> const & s)2693 	void session_impl::on_incoming_utp_ssl(std::shared_ptr<socket_type> const& s)
2694 	{
2695 		TORRENT_ASSERT(is_ssl(*s));
2696 
2697 		// for SSL connections, incoming_connection() is called
2698 		// after the handshake is done
2699 		ADD_OUTSTANDING_ASYNC("session_impl::ssl_handshake");
2700 		s->get<ssl_stream<utp_stream>>()->async_accept_handshake(
2701 			std::bind(&session_impl::ssl_handshake, this, _1, s));
2702 		m_incoming_sockets.insert(s);
2703 	}
2704 
2705 	// to test SSL connections, one can use this openssl command template:
2706 	//
2707 	// openssl s_client -cert <client-cert>.pem -key <client-private-key>.pem
2708 	//   -CAfile <torrent-cert>.pem  -debug -connect 127.0.0.1:4433 -tls1
2709 	//   -servername <hex-encoded-info-hash>
2710 
ssl_handshake(error_code const & ec,std::shared_ptr<socket_type> s)2711 	void session_impl::ssl_handshake(error_code const& ec, std::shared_ptr<socket_type> s)
2712 	{
2713 		COMPLETE_ASYNC("session_impl::ssl_handshake");
2714 		TORRENT_ASSERT(is_ssl(*s));
2715 
2716 		m_incoming_sockets.erase(s);
2717 
2718 		error_code e;
2719 		tcp::endpoint endp = s->remote_endpoint(e);
2720 		if (e) return;
2721 
2722 #ifndef TORRENT_DISABLE_LOGGING
2723 		if (should_log())
2724 		{
2725 			session_log(" *** peer SSL handshake done [ ip: %s ec: %s socket: %s ]"
2726 				, print_endpoint(endp).c_str(), ec.message().c_str(), s->type_name());
2727 		}
2728 #endif
2729 
2730 		if (ec)
2731 		{
2732 			if (m_alerts.should_post<peer_error_alert>())
2733 			{
2734 				m_alerts.emplace_alert<peer_error_alert>(torrent_handle(), endp
2735 					, peer_id(), operation_t::ssl_handshake, ec);
2736 			}
2737 			return;
2738 		}
2739 
2740 		incoming_connection(s);
2741 	}
2742 
2743 #endif // TORRENT_USE_OPENSSL
2744 
incoming_connection(std::shared_ptr<socket_type> const & s)2745 	void session_impl::incoming_connection(std::shared_ptr<socket_type> const& s)
2746 	{
2747 		TORRENT_ASSERT(is_single_thread());
2748 
2749 		// don't accept any connections from our local sockets if we're using a
2750 		// proxy
2751 		if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
2752 			&& m_settings.get_bool(settings_pack::proxy_peer_connections))
2753 			return;
2754 
2755 		if (m_paused)
2756 		{
2757 #ifndef TORRENT_DISABLE_LOGGING
2758 			session_log(" <== INCOMING CONNECTION [ ignored, paused ]");
2759 #endif
2760 			return;
2761 		}
2762 
2763 		error_code ec;
2764 		// we got a connection request!
2765 		tcp::endpoint endp = s->remote_endpoint(ec);
2766 
2767 		if (ec)
2768 		{
2769 #ifndef TORRENT_DISABLE_LOGGING
2770 			if (should_log())
2771 			{
2772 				session_log(" <== INCOMING CONNECTION [ rejected, could "
2773 					"not retrieve remote endpoint: %s ]"
2774 					, print_error(ec).c_str());
2775 			}
2776 #endif
2777 			return;
2778 		}
2779 
2780 		if (!m_settings.get_bool(settings_pack::enable_incoming_utp)
2781 			&& is_utp(*s))
2782 		{
2783 #ifndef TORRENT_DISABLE_LOGGING
2784 			session_log("<== INCOMING CONNECTION [ rejected uTP connection ]");
2785 #endif
2786 			if (m_alerts.should_post<peer_blocked_alert>())
2787 				m_alerts.emplace_alert<peer_blocked_alert>(torrent_handle()
2788 					, endp, peer_blocked_alert::utp_disabled);
2789 			return;
2790 		}
2791 
2792 		if (!m_settings.get_bool(settings_pack::enable_incoming_tcp)
2793 			&& s->get<tcp::socket>())
2794 		{
2795 #ifndef TORRENT_DISABLE_LOGGING
2796 			session_log("<== INCOMING CONNECTION [ rejected TCP connection ]");
2797 #endif
2798 			if (m_alerts.should_post<peer_blocked_alert>())
2799 				m_alerts.emplace_alert<peer_blocked_alert>(torrent_handle()
2800 					, endp, peer_blocked_alert::tcp_disabled);
2801 			return;
2802 		}
2803 
2804 		// if there are outgoing interfaces specified, verify this
2805 		// peer is correctly bound to one of them
2806 		if (!m_outgoing_interfaces.empty())
2807 		{
2808 			tcp::endpoint local = s->local_endpoint(ec);
2809 			if (ec)
2810 			{
2811 #ifndef TORRENT_DISABLE_LOGGING
2812 				if (should_log())
2813 				{
2814 					session_log("<== INCOMING CONNECTION [ rejected connection: %s ]"
2815 						, print_error(ec).c_str());
2816 				}
2817 #endif
2818 				return;
2819 			}
2820 
2821 			if (!verify_incoming_interface(local.address()))
2822 			{
2823 #ifndef TORRENT_DISABLE_LOGGING
2824 				if (should_log())
2825 				{
2826 					error_code err;
2827 					session_log("<== INCOMING CONNECTION [ rejected, local interface has incoming connections disabled: %s ]"
2828 						, local.address().to_string(err).c_str());
2829 				}
2830 #endif
2831 				if (m_alerts.should_post<peer_blocked_alert>())
2832 					m_alerts.emplace_alert<peer_blocked_alert>(torrent_handle()
2833 						, endp, peer_blocked_alert::invalid_local_interface);
2834 				return;
2835 			}
2836 			if (!verify_bound_address(local.address(), is_utp(*s), ec))
2837 			{
2838 				if (ec)
2839 				{
2840 #ifndef TORRENT_DISABLE_LOGGING
2841 					if (should_log())
2842 					{
2843 						session_log("<== INCOMING CONNECTION [ rejected, not allowed local interface: %s ]"
2844 							, print_error(ec).c_str());
2845 					}
2846 #endif
2847 					return;
2848 				}
2849 
2850 #ifndef TORRENT_DISABLE_LOGGING
2851 				if (should_log())
2852 				{
2853 					error_code err;
2854 					session_log("<== INCOMING CONNECTION [ rejected, not allowed local interface: %s ]"
2855 						, local.address().to_string(err).c_str());
2856 				}
2857 #endif
2858 				if (m_alerts.should_post<peer_blocked_alert>())
2859 					m_alerts.emplace_alert<peer_blocked_alert>(torrent_handle()
2860 						, endp, peer_blocked_alert::invalid_local_interface);
2861 				return;
2862 			}
2863 		}
2864 
2865 		// local addresses do not count, since it's likely
2866 		// coming from our own client through local service discovery
2867 		// and it does not reflect whether or not a router is open
2868 		// for incoming connections or not.
2869 		if (!is_local(endp.address()))
2870 			m_stats_counters.set_value(counters::has_incoming_connections, 1);
2871 
2872 		// this filter is ignored if a single torrent
2873 		// is set to ignore the filter, since this peer might be
2874 		// for that torrent
2875 		if (m_stats_counters[counters::non_filter_torrents] == 0
2876 			&& m_ip_filter
2877 			&& (m_ip_filter->access(endp.address()) & ip_filter::blocked))
2878 		{
2879 #ifndef TORRENT_DISABLE_LOGGING
2880 			session_log("<== INCOMING CONNECTION [ filtered blocked ip ]");
2881 #endif
2882 			if (m_alerts.should_post<peer_blocked_alert>())
2883 				m_alerts.emplace_alert<peer_blocked_alert>(torrent_handle()
2884 					, endp, peer_blocked_alert::ip_filter);
2885 			return;
2886 		}
2887 
2888 		// check if we have any active torrents
2889 		// if we don't reject the connection
2890 		if (m_torrents.empty())
2891 		{
2892 #ifndef TORRENT_DISABLE_LOGGING
2893 			session_log("<== INCOMING CONNECTION [ rejected, there are no torrents ]");
2894 #endif
2895 			return;
2896 		}
2897 
2898 		// figure out which peer classes this is connections has,
2899 		// to get connection_limit_factor
2900 		peer_class_set pcs;
2901 		set_peer_classes(&pcs, endp.address(), s->type());
2902 		int connection_limit_factor = 0;
2903 		for (int i = 0; i < pcs.num_classes(); ++i)
2904 		{
2905 			peer_class_t pc = pcs.class_at(i);
2906 			if (m_classes.at(pc) == nullptr) continue;
2907 			int f = m_classes.at(pc)->connection_limit_factor;
2908 			if (connection_limit_factor < f) connection_limit_factor = f;
2909 		}
2910 		if (connection_limit_factor == 0) connection_limit_factor = 100;
2911 
2912 		std::int64_t limit = m_settings.get_int(settings_pack::connections_limit);
2913 		limit = limit * 100 / connection_limit_factor;
2914 
2915 		// don't allow more connections than the max setting
2916 		// weighed by the peer class' setting
2917 		bool reject = num_connections() >= limit + m_settings.get_int(settings_pack::connections_slack);
2918 
2919 		if (reject)
2920 		{
2921 			if (m_alerts.should_post<peer_disconnected_alert>())
2922 			{
2923 				m_alerts.emplace_alert<peer_disconnected_alert>(torrent_handle(), endp, peer_id()
2924 						, operation_t::bittorrent, s->type()
2925 						, error_code(errors::too_many_connections)
2926 						, close_reason_t::none);
2927 			}
2928 #ifndef TORRENT_DISABLE_LOGGING
2929 			if (should_log())
2930 			{
2931 				session_log("<== INCOMING CONNECTION [ connections limit exceeded, conns: %d, limit: %d, slack: %d ]"
2932 					, num_connections(), m_settings.get_int(settings_pack::connections_limit)
2933 					, m_settings.get_int(settings_pack::connections_slack));
2934 			}
2935 #endif
2936 			return;
2937 		}
2938 
2939 		// if we don't have any active torrents, there's no
2940 		// point in accepting this connection. If, however,
2941 		// the setting to start up queued torrents when they
2942 		// get an incoming connection is enabled, we cannot
2943 		// perform this check.
2944 		if (!m_settings.get_bool(settings_pack::incoming_starts_queued_torrents))
2945 		{
2946 			bool has_active_torrent = std::any_of(m_torrents.begin(), m_torrents.end()
2947 				, [](std::pair<sha1_hash, std::shared_ptr<torrent>> const& i)
2948 				{ return !i.second->is_torrent_paused(); });
2949 			if (!has_active_torrent)
2950 			{
2951 #ifndef TORRENT_DISABLE_LOGGING
2952 				session_log("<== INCOMING CONNECTION [ rejected, no active torrents ]");
2953 #endif
2954 				return;
2955 			}
2956 		}
2957 
2958 		m_stats_counters.inc_stats_counter(counters::incoming_connections);
2959 
2960 		if (m_alerts.should_post<incoming_connection_alert>())
2961 			m_alerts.emplace_alert<incoming_connection_alert>(s->type(), endp);
2962 
2963 		peer_connection_args pack{
2964 			this
2965 			, &m_settings
2966 			, &m_stats_counters
2967 			, &m_disk_thread
2968 			, &m_io_service
2969 			, std::weak_ptr<torrent>()
2970 			, s
2971 			, endp
2972 			, nullptr
2973 			, aux::generate_peer_id(m_settings)
2974 		};
2975 
2976 		std::shared_ptr<peer_connection> c
2977 			= std::make_shared<bt_peer_connection>(std::move(pack));
2978 
2979 		if (!c->is_disconnecting())
2980 		{
2981 			// in case we've exceeded the limit, let this peer know that
2982 			// as soon as it's received the handshake, it needs to either
2983 			// disconnect or pick another peer to disconnect
2984 			if (num_connections() >= limit)
2985 				c->peer_exceeds_limit();
2986 
2987 			TORRENT_ASSERT(!c->m_in_constructor);
2988 			// removing a peer may not throw an exception, so prepare for this
2989 			// connection to be added to the undead peers now.
2990 			m_undead_peers.reserve(m_undead_peers.size() + m_connections.size() + 1);
2991 			m_connections.insert(c);
2992 			c->start();
2993 		}
2994 	}
2995 
close_connection(peer_connection * p)2996 	void session_impl::close_connection(peer_connection* p) noexcept
2997 	{
2998 		TORRENT_ASSERT(is_single_thread());
2999 		std::shared_ptr<peer_connection> sp(p->self());
3000 
3001 		TORRENT_ASSERT(p->is_disconnecting());
3002 
3003 		auto const i = m_connections.find(sp);
3004 		// make sure the next disk peer round-robin cursor stays valid
3005 		if (i != m_connections.end())
3006 		{
3007 			m_connections.erase(i);
3008 
3009 			TORRENT_ASSERT(std::find(m_undead_peers.begin()
3010 				, m_undead_peers.end(), sp) == m_undead_peers.end());
3011 
3012 			// someone else is holding a reference, it's important that
3013 			// it's destructed from the network thread. Make sure the
3014 			// last reference is held by the network thread.
3015 			TORRENT_ASSERT_VAL(m_undead_peers.capacity() > m_undead_peers.size()
3016 				, m_undead_peers.capacity());
3017 			if (sp.use_count() > 2)
3018 				m_undead_peers.push_back(sp);
3019 		}
3020 	}
3021 
3022 #if TORRENT_ABI_VERSION == 1
deprecated_get_peer_id() const3023 	peer_id session_impl::deprecated_get_peer_id() const
3024 	{
3025 		return aux::generate_peer_id(m_settings);
3026 	}
3027 #endif
3028 
next_port() const3029 	int session_impl::next_port() const
3030 	{
3031 		int start = m_settings.get_int(settings_pack::outgoing_port);
3032 		int num = m_settings.get_int(settings_pack::num_outgoing_ports);
3033 		std::pair<int, int> out_ports(start, start + num);
3034 		if (m_next_port < out_ports.first || m_next_port > out_ports.second)
3035 			m_next_port = out_ports.first;
3036 
3037 		int port = m_next_port;
3038 		++m_next_port;
3039 		if (m_next_port > out_ports.second) m_next_port = out_ports.first;
3040 #ifndef TORRENT_DISABLE_LOGGING
3041 		session_log(" *** BINDING OUTGOING CONNECTION [ port: %d ]", port);
3042 #endif
3043 		return port;
3044 	}
3045 
rate_limit(peer_class_t c,int channel) const3046 	int session_impl::rate_limit(peer_class_t c, int channel) const
3047 	{
3048 		TORRENT_ASSERT(channel >= 0 && channel <= 1);
3049 		if (channel < 0 || channel > 1) return 0;
3050 
3051 		peer_class const* pc = m_classes.at(c);
3052 		if (pc == nullptr) return 0;
3053 		return pc->channel[channel].throttle();
3054 	}
3055 
upload_rate_limit(peer_class_t c) const3056 	int session_impl::upload_rate_limit(peer_class_t c) const
3057 	{
3058 		return rate_limit(c, peer_connection::upload_channel);
3059 	}
3060 
download_rate_limit(peer_class_t c) const3061 	int session_impl::download_rate_limit(peer_class_t c) const
3062 	{
3063 		return rate_limit(c, peer_connection::download_channel);
3064 	}
3065 
set_rate_limit(peer_class_t c,int channel,int limit)3066 	void session_impl::set_rate_limit(peer_class_t c, int channel, int limit)
3067 	{
3068 		TORRENT_ASSERT(is_single_thread());
3069 		TORRENT_ASSERT(limit >= -1);
3070 		TORRENT_ASSERT(channel >= 0 && channel <= 1);
3071 
3072 		if (channel < 0 || channel > 1) return;
3073 
3074 		peer_class* pc = m_classes.at(c);
3075 		if (pc == nullptr) return;
3076 		if (limit <= 0) limit = 0;
3077 		else limit = std::min(limit, std::numeric_limits<int>::max() - 1);
3078 		pc->channel[channel].throttle(limit);
3079 	}
3080 
set_upload_rate_limit(peer_class_t c,int limit)3081 	void session_impl::set_upload_rate_limit(peer_class_t c, int limit)
3082 	{
3083 		set_rate_limit(c, peer_connection::upload_channel, limit);
3084 	}
3085 
set_download_rate_limit(peer_class_t c,int limit)3086 	void session_impl::set_download_rate_limit(peer_class_t c, int limit)
3087 	{
3088 		set_rate_limit(c, peer_connection::download_channel, limit);
3089 	}
3090 
3091 #if TORRENT_USE_ASSERTS
has_peer(peer_connection const * p) const3092 	bool session_impl::has_peer(peer_connection const* p) const
3093 	{
3094 		TORRENT_ASSERT(is_single_thread());
3095 		return std::any_of(m_connections.begin(), m_connections.end()
3096 			, [p] (std::shared_ptr<peer_connection> const& pr)
3097 			{ return pr.get() == p; });
3098 	}
3099 
any_torrent_has_peer(peer_connection const * p) const3100 	bool session_impl::any_torrent_has_peer(peer_connection const* p) const
3101 	{
3102 		for (auto& pe : m_torrents)
3103 			if (pe.second->has_peer(p)) return true;
3104 		return false;
3105 	}
3106 
verify_queue_position(torrent const * t,queue_position_t const pos)3107 	bool session_impl::verify_queue_position(torrent const* t, queue_position_t const pos)
3108 	{
3109 		return m_download_queue.end_index() > pos && m_download_queue[pos] == t;
3110 	}
3111 #endif
3112 
sent_bytes(int bytes_payload,int bytes_protocol)3113 	void session_impl::sent_bytes(int bytes_payload, int bytes_protocol)
3114 	{
3115 		TORRENT_ASSERT(bytes_payload >= 0);
3116 		TORRENT_ASSERT(bytes_protocol >= 0);
3117 		m_stats_counters.inc_stats_counter(counters::sent_bytes
3118 			, bytes_payload + bytes_protocol);
3119 		m_stats_counters.inc_stats_counter(counters::sent_payload_bytes
3120 			, bytes_payload);
3121 
3122 		m_stat.sent_bytes(bytes_payload, bytes_protocol);
3123 	}
3124 
received_bytes(int bytes_payload,int bytes_protocol)3125 	void session_impl::received_bytes(int bytes_payload, int bytes_protocol)
3126 	{
3127 		TORRENT_ASSERT(bytes_payload >= 0);
3128 		TORRENT_ASSERT(bytes_protocol >= 0);
3129 		m_stats_counters.inc_stats_counter(counters::recv_bytes
3130 			, bytes_payload + bytes_protocol);
3131 		m_stats_counters.inc_stats_counter(counters::recv_payload_bytes
3132 			, bytes_payload);
3133 
3134 		m_stat.received_bytes(bytes_payload, bytes_protocol);
3135 	}
3136 
trancieve_ip_packet(int bytes,bool ipv6)3137 	void session_impl::trancieve_ip_packet(int bytes, bool ipv6)
3138 	{
3139 		TORRENT_ASSERT(bytes >= 0);
3140 		// one TCP/IP packet header for the packet
3141 		// sent or received, and one for the ACK
3142 		// The IPv4 header is 20 bytes
3143 		// and IPv6 header is 40 bytes
3144 		int const header = (ipv6 ? 40 : 20) + 20;
3145 		int const mtu = 1500;
3146 		int const packet_size = mtu - header;
3147 		int const overhead = std::max(1, (bytes + packet_size - 1) / packet_size) * header;
3148 		m_stats_counters.inc_stats_counter(counters::sent_ip_overhead_bytes
3149 			, overhead);
3150 		m_stats_counters.inc_stats_counter(counters::recv_ip_overhead_bytes
3151 			, overhead);
3152 
3153 		m_stat.trancieve_ip_packet(bytes, ipv6);
3154 	}
3155 
sent_syn(bool ipv6)3156 	void session_impl::sent_syn(bool ipv6)
3157 	{
3158 		int const overhead = ipv6 ? 60 : 40;
3159 		m_stats_counters.inc_stats_counter(counters::sent_ip_overhead_bytes
3160 			, overhead);
3161 
3162 		m_stat.sent_syn(ipv6);
3163 	}
3164 
received_synack(bool ipv6)3165 	void session_impl::received_synack(bool ipv6)
3166 	{
3167 		int const overhead = ipv6 ? 60 : 40;
3168 		m_stats_counters.inc_stats_counter(counters::sent_ip_overhead_bytes
3169 			, overhead);
3170 		m_stats_counters.inc_stats_counter(counters::recv_ip_overhead_bytes
3171 			, overhead);
3172 
3173 		m_stat.received_synack(ipv6);
3174 	}
3175 
on_tick(error_code const & e)3176 	void session_impl::on_tick(error_code const& e)
3177 	{
3178 		COMPLETE_ASYNC("session_impl::on_tick");
3179 		m_stats_counters.inc_stats_counter(counters::on_tick_counter);
3180 
3181 		TORRENT_ASSERT(is_single_thread());
3182 
3183 		// submit all disk jobs when we leave this function
3184 		deferred_submit_jobs();
3185 
3186 		time_point const now = aux::time_now();
3187 
3188 		// remove undead peers that only have this list as their reference keeping them alive
3189 		if (!m_undead_peers.empty())
3190 		{
3191 			auto const remove_it = std::remove_if(m_undead_peers.begin(), m_undead_peers.end()
3192 				, [](std::shared_ptr<peer_connection>& ptr) { return ptr.use_count() == 1; });
3193 			m_undead_peers.erase(remove_it, m_undead_peers.end());
3194 			if (m_undead_peers.empty())
3195 			{
3196 				// we just removed our last "undead" peer (i.e. a peer connection
3197 				// that had some external reference to it). It's now safe to
3198 				// shut-down
3199 				if (m_abort)
3200 				{
3201 					m_io_service.post(std::bind(&session_impl::abort_stage2, this));
3202 				}
3203 			}
3204 		}
3205 
3206 // too expensive
3207 //		INVARIANT_CHECK;
3208 
3209 		// we have to keep ticking the utp socket manager
3210 		// until they're all closed
3211 		// we also have to keep updating the aux time while
3212 		// there are outstanding announces
3213 		if (m_abort)
3214 		{
3215 			if (m_utp_socket_manager.num_sockets() == 0
3216 #ifdef TORRENT_USE_OPENSSL
3217 				&& m_ssl_utp_socket_manager.num_sockets() == 0
3218 #endif
3219 				&& m_undead_peers.empty()
3220 				&& m_tracker_manager.empty())
3221 			{
3222 				return;
3223 			}
3224 #if defined TORRENT_ASIO_DEBUGGING
3225 			std::fprintf(stderr, "uTP sockets: %d ssl-uTP sockets: %d undead-peers left: %d\n"
3226 				, m_utp_socket_manager.num_sockets()
3227 #ifdef TORRENT_USE_OPENSSL
3228 				, m_ssl_utp_socket_manager.num_sockets()
3229 #else
3230 				, 0
3231 #endif
3232 				, int(m_undead_peers.size()));
3233 #endif
3234 		}
3235 
3236 		if (e == boost::asio::error::operation_aborted) return;
3237 
3238 		if (e)
3239 		{
3240 #ifndef TORRENT_DISABLE_LOGGING
3241 			if (should_log())
3242 				session_log("*** TICK TIMER FAILED %s", e.message().c_str());
3243 #endif
3244 			std::abort();
3245 		}
3246 
3247 		ADD_OUTSTANDING_ASYNC("session_impl::on_tick");
3248 		error_code ec;
3249 		m_timer.expires_at(now + milliseconds(m_settings.get_int(settings_pack::tick_interval)), ec);
3250 		m_timer.async_wait(aux::make_handler([this](error_code const& err)
3251 		{ this->wrap(&session_impl::on_tick, err); }, m_tick_handler_storage, *this));
3252 
3253 		m_download_rate.update_quotas(now - m_last_tick);
3254 		m_upload_rate.update_quotas(now - m_last_tick);
3255 
3256 		m_last_tick = now;
3257 
3258 		m_utp_socket_manager.tick(now);
3259 #ifdef TORRENT_USE_OPENSSL
3260 		m_ssl_utp_socket_manager.tick(now);
3261 #endif
3262 
3263 		// only tick the following once per second
3264 		if (now - m_last_second_tick < seconds(1)) return;
3265 
3266 #ifndef TORRENT_DISABLE_DHT
3267 		if (m_dht
3268 			&& m_dht_interval_update_torrents < 40
3269 			&& m_dht_interval_update_torrents != int(m_torrents.size()))
3270 			update_dht_announce_interval();
3271 #endif
3272 
3273 		m_utp_socket_manager.decay();
3274 #ifdef TORRENT_USE_OPENSSL
3275 		m_ssl_utp_socket_manager.decay();
3276 #endif
3277 
3278 		int const tick_interval_ms = aux::numeric_cast<int>(total_milliseconds(now - m_last_second_tick));
3279 		m_last_second_tick = now;
3280 
3281 		std::int32_t const stime = session_time();
3282 		if (stime > 65000)
3283 		{
3284 			// we're getting close to the point where our timestamps
3285 			// in torrent_peer are wrapping. We need to step all counters back
3286 			// four hours. This means that any timestamp that refers to a time
3287 			// more than 18.2 - 4 = 14.2 hours ago, will be incremented to refer to
3288 			// 14.2 hours ago.
3289 
3290 			m_created += hours(4);
3291 
3292 			constexpr int four_hours = 60 * 60 * 4;
3293 			for (auto& i : m_torrents)
3294 			{
3295 				i.second->step_session_time(four_hours);
3296 			}
3297 		}
3298 
3299 #ifndef TORRENT_DISABLE_EXTENSIONS
3300 		for (auto& ext : m_ses_extensions[plugins_tick_idx])
3301 		{
3302 			ext->on_tick();
3303 		}
3304 #endif
3305 
3306 		// don't do any of the following while we're shutting down
3307 		if (m_abort) return;
3308 
3309 		switch (m_settings.get_int(settings_pack::mixed_mode_algorithm))
3310 		{
3311 			case settings_pack::prefer_tcp:
3312 				set_upload_rate_limit(m_tcp_peer_class, 0);
3313 				set_download_rate_limit(m_tcp_peer_class, 0);
3314 				break;
3315 			case settings_pack::peer_proportional:
3316 				{
3317 					int num_peers[2][2] = {{0, 0}, {0, 0}};
3318 					for (auto const& i : m_connections)
3319 					{
3320 						peer_connection& p = *i;
3321 						if (p.in_handshake()) continue;
3322 						int protocol = 0;
3323 						if (is_utp(*p.get_socket())) protocol = 1;
3324 
3325 						if (p.download_queue().size() + p.request_queue().size() > 0)
3326 							++num_peers[protocol][peer_connection::download_channel];
3327 						if (!p.upload_queue().empty())
3328 							++num_peers[protocol][peer_connection::upload_channel];
3329 					}
3330 
3331 					peer_class* pc = m_classes.at(m_tcp_peer_class);
3332 					bandwidth_channel* tcp_channel = pc->channel;
3333 					int stat_rate[] = {m_stat.upload_rate(), m_stat.download_rate() };
3334 					// never throttle below this
3335 					int lower_limit[] = {5000, 30000};
3336 
3337 					for (int i = 0; i < 2; ++i)
3338 					{
3339 						// if there are no uploading uTP peers, don't throttle TCP up
3340 						if (num_peers[1][i] == 0)
3341 						{
3342 							tcp_channel[i].throttle(0);
3343 						}
3344 						else
3345 						{
3346 							if (num_peers[0][i] == 0) num_peers[0][i] = 1;
3347 							int total_peers = num_peers[0][i] + num_peers[1][i];
3348 							// this are 64 bits since it's multiplied by the number
3349 							// of peers, which otherwise might overflow an int
3350 							std::int64_t rate = stat_rate[i];
3351 							tcp_channel[i].throttle(std::max(int(rate * num_peers[0][i] / total_peers), lower_limit[i]));
3352 						}
3353 					}
3354 				}
3355 				break;
3356 		}
3357 
3358 		// --------------------------------------------------------------
3359 		// auto managed torrent
3360 		// --------------------------------------------------------------
3361 		if (!m_paused) m_auto_manage_time_scaler--;
3362 		if (m_auto_manage_time_scaler < 0)
3363 		{
3364 			m_auto_manage_time_scaler = settings().get_int(settings_pack::auto_manage_interval);
3365 			recalculate_auto_managed_torrents();
3366 		}
3367 
3368 		// --------------------------------------------------------------
3369 		// check for incoming connections that might have timed out
3370 		// --------------------------------------------------------------
3371 
3372 		for (auto i = m_connections.begin(); i != m_connections.end();)
3373 		{
3374 			peer_connection* p = (*i).get();
3375 			++i;
3376 			// ignore connections that already have a torrent, since they
3377 			// are ticked through the torrents' second_tick
3378 			if (!p->associated_torrent().expired()) continue;
3379 
3380 			// TODO: have a separate list for these connections, instead of having to loop through all of them
3381 			int timeout = m_settings.get_int(settings_pack::handshake_timeout);
3382 #if TORRENT_USE_I2P
3383 			timeout *= is_i2p(*p->get_socket()) ? 4 : 1;
3384 #endif
3385 			if (m_last_tick - p->connected_time () > seconds(timeout))
3386 				p->disconnect(errors::timed_out, operation_t::bittorrent);
3387 		}
3388 
3389 		// --------------------------------------------------------------
3390 		// second_tick every torrent (that wants it)
3391 		// --------------------------------------------------------------
3392 
3393 #if TORRENT_DEBUG_STREAMING > 0
3394 		std::printf("\033[2J\033[0;0H");
3395 #endif
3396 
3397 		aux::vector<torrent*>& want_tick = m_torrent_lists[torrent_want_tick];
3398 		for (int i = 0; i < int(want_tick.size()); ++i)
3399 		{
3400 			torrent& t = *want_tick[i];
3401 			TORRENT_ASSERT(t.want_tick());
3402 			TORRENT_ASSERT(!t.is_aborted());
3403 
3404 			t.second_tick(tick_interval_ms);
3405 
3406 			// if the call to second_tick caused the torrent
3407 			// to no longer want to be ticked (i.e. it was
3408 			// removed from the list) we need to back up the counter
3409 			// to not miss the torrent after it
3410 			if (!t.want_tick()) --i;
3411 		}
3412 
3413 		// TODO: this should apply to all bandwidth channels
3414 		if (m_settings.get_bool(settings_pack::rate_limit_ip_overhead))
3415 		{
3416 			int const up_limit = upload_rate_limit(m_global_class);
3417 			int const down_limit = download_rate_limit(m_global_class);
3418 
3419 			if (down_limit > 0
3420 				&& m_stat.download_ip_overhead() >= down_limit
3421 				&& m_alerts.should_post<performance_alert>())
3422 			{
3423 				m_alerts.emplace_alert<performance_alert>(torrent_handle()
3424 					, performance_alert::download_limit_too_low);
3425 			}
3426 
3427 			if (up_limit > 0
3428 				&& m_stat.upload_ip_overhead() >= up_limit
3429 				&& m_alerts.should_post<performance_alert>())
3430 			{
3431 				m_alerts.emplace_alert<performance_alert>(torrent_handle()
3432 					, performance_alert::upload_limit_too_low);
3433 			}
3434 		}
3435 
3436 #if TORRENT_ABI_VERSION == 1
3437 		m_peak_up_rate = std::max(m_stat.upload_rate(), m_peak_up_rate);
3438 #endif
3439 
3440 		m_stat.second_tick(tick_interval_ms);
3441 
3442 		// --------------------------------------------------------------
3443 		// scrape paused torrents that are auto managed
3444 		// (unless the session is paused)
3445 		// --------------------------------------------------------------
3446 		if (!m_paused)
3447 		{
3448 			INVARIANT_CHECK;
3449 			--m_auto_scrape_time_scaler;
3450 			if (m_auto_scrape_time_scaler <= 0)
3451 			{
3452 				aux::vector<torrent*>& want_scrape = m_torrent_lists[torrent_want_scrape];
3453 				m_auto_scrape_time_scaler = m_settings.get_int(settings_pack::auto_scrape_interval)
3454 					/ std::max(1, int(want_scrape.size()));
3455 				if (m_auto_scrape_time_scaler < m_settings.get_int(settings_pack::auto_scrape_min_interval))
3456 					m_auto_scrape_time_scaler = m_settings.get_int(settings_pack::auto_scrape_min_interval);
3457 
3458 				if (!want_scrape.empty() && !m_abort)
3459 				{
3460 					if (m_next_scrape_torrent >= int(want_scrape.size()))
3461 						m_next_scrape_torrent = 0;
3462 
3463 					torrent& t = *want_scrape[m_next_scrape_torrent];
3464 					TORRENT_ASSERT(t.is_paused() && t.is_auto_managed());
3465 
3466 					// false means it's not triggered by the user, but automatically
3467 					// by libtorrent
3468 					t.scrape_tracker(-1, false);
3469 
3470 					++m_next_scrape_torrent;
3471 					if (m_next_scrape_torrent >= int(want_scrape.size()))
3472 						m_next_scrape_torrent = 0;
3473 
3474 				}
3475 			}
3476 		}
3477 
3478 		// --------------------------------------------------------------
3479 		// connect new peers
3480 		// --------------------------------------------------------------
3481 
3482 		try_connect_more_peers();
3483 
3484 		// --------------------------------------------------------------
3485 		// unchoke set calculations
3486 		// --------------------------------------------------------------
3487 		m_unchoke_time_scaler--;
3488 		if (m_unchoke_time_scaler <= 0 && !m_connections.empty())
3489 		{
3490 			m_unchoke_time_scaler = settings().get_int(settings_pack::unchoke_interval);
3491 			recalculate_unchoke_slots();
3492 		}
3493 
3494 		// --------------------------------------------------------------
3495 		// optimistic unchoke calculation
3496 		// --------------------------------------------------------------
3497 		m_optimistic_unchoke_time_scaler--;
3498 		if (m_optimistic_unchoke_time_scaler <= 0)
3499 		{
3500 			m_optimistic_unchoke_time_scaler
3501 				= settings().get_int(settings_pack::optimistic_unchoke_interval);
3502 			recalculate_optimistic_unchoke_slots();
3503 		}
3504 
3505 		// --------------------------------------------------------------
3506 		// disconnect peers when we have too many
3507 		// --------------------------------------------------------------
3508 		--m_disconnect_time_scaler;
3509 		if (m_disconnect_time_scaler <= 0)
3510 		{
3511 			m_disconnect_time_scaler = m_settings.get_int(settings_pack::peer_turnover_interval);
3512 
3513 			// if the connections_limit is too low, the disconnect
3514 			// logic is disabled, since it is too disruptive
3515 			if (m_settings.get_int(settings_pack::connections_limit) > 5)
3516 			{
3517 				if (num_connections() >= m_settings.get_int(settings_pack::connections_limit)
3518 					* m_settings.get_int(settings_pack::peer_turnover_cutoff) / 100
3519 					&& !m_torrents.empty())
3520 				{
3521 					// every 90 seconds, disconnect the worst peers
3522 					// if we have reached the connection limit
3523 					auto const i = std::max_element(m_torrents.begin(), m_torrents.end()
3524 						, [] (torrent_map::value_type const& lhs, torrent_map::value_type const& rhs)
3525 						{ return lhs.second->num_peers() < rhs.second->num_peers(); });
3526 
3527 					TORRENT_ASSERT(i != m_torrents.end());
3528 					int const peers_to_disconnect = std::min(std::max(
3529 						i->second->num_peers() * m_settings.get_int(settings_pack::peer_turnover) / 100, 1)
3530 						, i->second->num_connect_candidates());
3531 					i->second->disconnect_peers(peers_to_disconnect
3532 						, error_code(errors::optimistic_disconnect));
3533 				}
3534 				else
3535 				{
3536 					// if we haven't reached the global max. see if any torrent
3537 					// has reached its local limit
3538 					for (auto const& pt : m_torrents)
3539 					{
3540 						std::shared_ptr<torrent> t = pt.second;
3541 
3542 						// ths disconnect logic is disabled for torrents with
3543 						// too low connection limit
3544 						if (t->num_peers() < t->max_connections()
3545 							* m_settings.get_int(settings_pack::peer_turnover_cutoff) / 100
3546 							|| t->max_connections() < 6)
3547 							continue;
3548 
3549 						int const peers_to_disconnect = std::min(std::max(t->num_peers()
3550 							* m_settings.get_int(settings_pack::peer_turnover) / 100, 1)
3551 							, t->num_connect_candidates());
3552 						t->disconnect_peers(peers_to_disconnect, errors::optimistic_disconnect);
3553 					}
3554 				}
3555 			}
3556 		}
3557 	}
3558 
received_buffer(int s)3559 	void session_impl::received_buffer(int s)
3560 	{
3561 		int index = std::min(aux::log2p1(std::uint32_t(s >> 3)), 17);
3562 		m_stats_counters.inc_stats_counter(counters::socket_recv_size3 + index);
3563 	}
3564 
sent_buffer(int s)3565 	void session_impl::sent_buffer(int s)
3566 	{
3567 		int index = std::min(aux::log2p1(std::uint32_t(s >> 3)), 17);
3568 		m_stats_counters.inc_stats_counter(counters::socket_send_size3 + index);
3569 	}
3570 
prioritize_connections(std::weak_ptr<torrent> t)3571 	void session_impl::prioritize_connections(std::weak_ptr<torrent> t)
3572 	{
3573 		m_prio_torrents.emplace_back(t, 10);
3574 	}
3575 
3576 #ifndef TORRENT_DISABLE_DHT
3577 
add_dht_node(udp::endpoint const & n)3578 	void session_impl::add_dht_node(udp::endpoint const& n)
3579 	{
3580 		TORRENT_ASSERT(is_single_thread());
3581 		if (m_dht) m_dht->add_node(n);
3582 		else m_dht_nodes.push_back(n);
3583 	}
3584 
has_dht() const3585 	bool session_impl::has_dht() const
3586 	{
3587 		return m_dht.get() != nullptr;
3588 	}
3589 
prioritize_dht(std::weak_ptr<torrent> t)3590 	void session_impl::prioritize_dht(std::weak_ptr<torrent> t)
3591 	{
3592 		TORRENT_ASSERT(!m_abort);
3593 		if (m_abort) return;
3594 
3595 		TORRENT_ASSERT(m_dht);
3596 		m_dht_torrents.push_back(t);
3597 #ifndef TORRENT_DISABLE_LOGGING
3598 		std::shared_ptr<torrent> tor = t.lock();
3599 		if (tor && should_log())
3600 			session_log("prioritizing DHT announce: \"%s\"", tor->name().c_str());
3601 #endif
3602 		// trigger a DHT announce right away if we just added a new torrent and
3603 		// there's no back-log. in the timer handler, as long as there are more
3604 		// high priority torrents to be announced to the DHT, it will keep the
3605 		// timer interval short until all torrents have been announced.
3606 		if (m_dht_torrents.size() == 1)
3607 		{
3608 			ADD_OUTSTANDING_ASYNC("session_impl::on_dht_announce");
3609 			error_code ec;
3610 			m_dht_announce_timer.expires_from_now(seconds(0), ec);
3611 			m_dht_announce_timer.async_wait([this](error_code const& err) {
3612 				this->wrap(&session_impl::on_dht_announce, err); });
3613 		}
3614 	}
3615 
on_dht_announce(error_code const & e)3616 	void session_impl::on_dht_announce(error_code const& e)
3617 	{
3618 		COMPLETE_ASYNC("session_impl::on_dht_announce");
3619 		TORRENT_ASSERT(is_single_thread());
3620 		if (e)
3621 		{
3622 #ifndef TORRENT_DISABLE_LOGGING
3623 			if (should_log())
3624 			{
3625 				session_log("aborting DHT announce timer (%d): %s"
3626 					, e.value(), e.message().c_str());
3627 			}
3628 #endif
3629 			return;
3630 		}
3631 
3632 		if (m_abort)
3633 		{
3634 #ifndef TORRENT_DISABLE_LOGGING
3635 			session_log("aborting DHT announce timer: m_abort set");
3636 #endif
3637 			return;
3638 		}
3639 
3640 		if (!m_dht)
3641 		{
3642 			m_dht_torrents.clear();
3643 			return;
3644 		}
3645 
3646 		TORRENT_ASSERT(m_dht);
3647 
3648 		// announce to DHT every 15 minutes
3649 		int delay = std::max(m_settings.get_int(settings_pack::dht_announce_interval)
3650 			/ std::max(int(m_torrents.size()), 1), 1);
3651 
3652 		if (!m_dht_torrents.empty())
3653 		{
3654 			// we have prioritized torrents that need
3655 			// an initial DHT announce. Don't wait too long
3656 			// until we announce those.
3657 			delay = std::min(4, delay);
3658 		}
3659 
3660 		ADD_OUTSTANDING_ASYNC("session_impl::on_dht_announce");
3661 		error_code ec;
3662 		m_dht_announce_timer.expires_from_now(seconds(delay), ec);
3663 		m_dht_announce_timer.async_wait([this](error_code const& err)
3664 			{ this->wrap(&session_impl::on_dht_announce, err); });
3665 
3666 		if (!m_dht_torrents.empty())
3667 		{
3668 			std::shared_ptr<torrent> t;
3669 			do
3670 			{
3671 				t = m_dht_torrents.front().lock();
3672 				m_dht_torrents.pop_front();
3673 			} while (!t && !m_dht_torrents.empty());
3674 
3675 			if (t)
3676 			{
3677 				t->dht_announce();
3678 				return;
3679 			}
3680 		}
3681 		if (m_torrents.empty()) return;
3682 
3683 		if (m_next_dht_torrent == m_torrents.end())
3684 			m_next_dht_torrent = m_torrents.begin();
3685 		m_next_dht_torrent->second->dht_announce();
3686 		// TODO: 2 make a list for torrents that want to be announced on the DHT so we
3687 		// don't have to loop over all torrents, just to find the ones that want to announce
3688 		++m_next_dht_torrent;
3689 		if (m_next_dht_torrent == m_torrents.end())
3690 			m_next_dht_torrent = m_torrents.begin();
3691 	}
3692 #endif
3693 
on_lsd_announce(error_code const & e)3694 	void session_impl::on_lsd_announce(error_code const& e)
3695 	{
3696 		COMPLETE_ASYNC("session_impl::on_lsd_announce");
3697 		m_stats_counters.inc_stats_counter(counters::on_lsd_counter);
3698 		TORRENT_ASSERT(is_single_thread());
3699 		if (e) return;
3700 
3701 		if (m_abort) return;
3702 
3703 		ADD_OUTSTANDING_ASYNC("session_impl::on_lsd_announce");
3704 		// announce on local network every 5 minutes
3705 		int const delay = std::max(m_settings.get_int(settings_pack::local_service_announce_interval)
3706 			/ std::max(int(m_torrents.size()), 1), 1);
3707 		error_code ec;
3708 		m_lsd_announce_timer.expires_from_now(seconds(delay), ec);
3709 		m_lsd_announce_timer.async_wait([this](error_code const& err) {
3710 			this->wrap(&session_impl::on_lsd_announce, err); });
3711 
3712 		if (m_torrents.empty()) return;
3713 
3714 		if (m_next_lsd_torrent == m_torrents.end())
3715 			m_next_lsd_torrent = m_torrents.begin();
3716 		m_next_lsd_torrent->second->lsd_announce();
3717 		++m_next_lsd_torrent;
3718 		if (m_next_lsd_torrent == m_torrents.end())
3719 			m_next_lsd_torrent = m_torrents.begin();
3720 	}
3721 
auto_manage_checking_torrents(std::vector<torrent * > & list,int & limit)3722 	void session_impl::auto_manage_checking_torrents(std::vector<torrent*>& list
3723 		, int& limit)
3724 	{
3725 		for (auto& t : list)
3726 		{
3727 			TORRENT_ASSERT(t->state() == torrent_status::checking_files);
3728 			TORRENT_ASSERT(t->is_auto_managed());
3729 			if (limit <= 0)
3730 			{
3731 				t->pause();
3732 			}
3733 			else
3734 			{
3735 				t->resume();
3736 				if (!t->should_check_files()) continue;
3737 				t->start_checking();
3738 				--limit;
3739 			}
3740 		}
3741 	}
3742 
auto_manage_torrents(std::vector<torrent * > & list,int & dht_limit,int & tracker_limit,int & lsd_limit,int & hard_limit,int type_limit)3743 	void session_impl::auto_manage_torrents(std::vector<torrent*>& list
3744 		, int& dht_limit, int& tracker_limit
3745 		, int& lsd_limit, int& hard_limit, int type_limit)
3746 	{
3747 		for (auto& t : list)
3748 		{
3749 			TORRENT_ASSERT(t->state() != torrent_status::checking_files);
3750 
3751 			// inactive torrents don't count (and if you configured them to do so,
3752 			// the torrent won't say it's inactive)
3753 			if (hard_limit > 0 && t->is_inactive())
3754 			{
3755 				t->set_announce_to_dht(--dht_limit >= 0);
3756 				t->set_announce_to_trackers(--tracker_limit >= 0);
3757 				t->set_announce_to_lsd(--lsd_limit >= 0);
3758 
3759 				--hard_limit;
3760 #ifndef TORRENT_DISABLE_LOGGING
3761 				if (t->is_torrent_paused())
3762 					t->log_to_all_peers("auto manager starting (inactive) torrent");
3763 #endif
3764 				t->set_paused(false);
3765 				continue;
3766 			}
3767 
3768 			if (type_limit > 0 && hard_limit > 0)
3769 			{
3770 				t->set_announce_to_dht(--dht_limit >= 0);
3771 				t->set_announce_to_trackers(--tracker_limit >= 0);
3772 				t->set_announce_to_lsd(--lsd_limit >= 0);
3773 
3774 				--hard_limit;
3775 				--type_limit;
3776 #ifndef TORRENT_DISABLE_LOGGING
3777 				if (t->is_torrent_paused())
3778 					t->log_to_all_peers("auto manager starting torrent");
3779 #endif
3780 				t->set_paused(false);
3781 				continue;
3782 			}
3783 
3784 #ifndef TORRENT_DISABLE_LOGGING
3785 			if (!t->is_torrent_paused())
3786 				t->log_to_all_peers("auto manager pausing torrent");
3787 #endif
3788 			// use graceful pause for auto-managed torrents
3789 			t->set_paused(true, torrent_handle::graceful_pause
3790 				| torrent_handle::clear_disk_cache);
3791 			t->set_announce_to_dht(false);
3792 			t->set_announce_to_trackers(false);
3793 			t->set_announce_to_lsd(false);
3794 		}
3795 	}
3796 
get_int_setting(int n) const3797 	int session_impl::get_int_setting(int n) const
3798 	{
3799 		int const v = settings().get_int(n);
3800 		if (v < 0) return std::numeric_limits<int>::max();
3801 		return v;
3802 	}
3803 
recalculate_auto_managed_torrents()3804 	void session_impl::recalculate_auto_managed_torrents()
3805 	{
3806 		INVARIANT_CHECK;
3807 
3808 		m_last_auto_manage = time_now();
3809 		m_need_auto_manage = false;
3810 
3811 		if (m_paused) return;
3812 
3813 		// make copies of the lists of torrents that we want to consider for auto
3814 		// management. We need copies because they will be sorted.
3815 		std::vector<torrent*> checking
3816 			= torrent_list(session_interface::torrent_checking_auto_managed);
3817 		std::vector<torrent*> downloaders
3818 			= torrent_list(session_interface::torrent_downloading_auto_managed);
3819 		std::vector<torrent*> seeds
3820 			= torrent_list(session_interface::torrent_seeding_auto_managed);
3821 
3822 		// these counters are set to the number of torrents
3823 		// of each kind we're allowed to have active
3824 		int downloading_limit = get_int_setting(settings_pack::active_downloads);
3825 		int seeding_limit = get_int_setting(settings_pack::active_seeds);
3826 		int checking_limit = get_int_setting(settings_pack::active_checking);
3827 		int dht_limit = get_int_setting(settings_pack::active_dht_limit);
3828 		int tracker_limit = get_int_setting(settings_pack::active_tracker_limit);
3829 		int lsd_limit = get_int_setting(settings_pack::active_lsd_limit);
3830 		int hard_limit = get_int_setting(settings_pack::active_limit);
3831 
3832 		// if hard_limit is <= 0, all torrents in these lists should be paused.
3833 		// The order is not relevant
3834 		if (hard_limit > 0)
3835 		{
3836 			// we only need to sort the first n torrents here, where n is the number
3837 			// of checking torrents we allow. The rest of the list is still used to
3838 			// make sure the remaining torrents are paused, but their order is not
3839 			// relevant
3840 			std::partial_sort(checking.begin(), checking.begin() +
3841 				std::min(checking_limit, int(checking.size())), checking.end()
3842 				, [](torrent const* lhs, torrent const* rhs)
3843 				{ return lhs->sequence_number() < rhs->sequence_number(); });
3844 
3845 			std::partial_sort(downloaders.begin(), downloaders.begin() +
3846 				std::min(hard_limit, int(downloaders.size())), downloaders.end()
3847 				, [](torrent const* lhs, torrent const* rhs)
3848 				{ return lhs->sequence_number() < rhs->sequence_number(); });
3849 
3850 			std::partial_sort(seeds.begin(), seeds.begin() +
3851 				std::min(hard_limit, int(seeds.size())), seeds.end()
3852 				, [this](torrent const* lhs, torrent const* rhs)
3853 				{ return lhs->seed_rank(m_settings) > rhs->seed_rank(m_settings); });
3854 		}
3855 
3856 		auto_manage_checking_torrents(checking, checking_limit);
3857 
3858 		if (settings().get_bool(settings_pack::auto_manage_prefer_seeds))
3859 		{
3860 			auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit
3861 				, hard_limit, seeding_limit);
3862 			auto_manage_torrents(downloaders, dht_limit, tracker_limit, lsd_limit
3863 				, hard_limit, downloading_limit);
3864 		}
3865 		else
3866 		{
3867 			auto_manage_torrents(downloaders, dht_limit, tracker_limit, lsd_limit
3868 				, hard_limit, downloading_limit);
3869 			auto_manage_torrents(seeds, dht_limit, tracker_limit, lsd_limit
3870 				, hard_limit, seeding_limit);
3871 		}
3872 	}
3873 
3874 	namespace {
3875 #ifndef TORRENT_DISABLE_EXTENSIONS
3876 		uint64_t const priority_undetermined = std::numeric_limits<uint64_t>::max() - 1;
3877 #endif
3878 
3879 		struct opt_unchoke_candidate
3880 		{
opt_unchoke_candidatelibtorrent::aux::__anon13c9013d2511::opt_unchoke_candidate3881 			explicit opt_unchoke_candidate(std::shared_ptr<peer_connection> const* tp)
3882 				: peer(tp)
3883 			{}
3884 
3885 			std::shared_ptr<peer_connection> const* peer;
3886 #ifndef TORRENT_DISABLE_EXTENSIONS
3887 			// this is mutable because comparison functors passed to std::partial_sort
3888 			// are not supposed to modify the elements they are sorting. Here the mutation
3889 			// being applied is idempotent so it should not pose a problem.
3890 			mutable uint64_t ext_priority = priority_undetermined;
3891 #endif
3892 		};
3893 
3894 		struct last_optimistic_unchoke_cmp
3895 		{
3896 #ifndef TORRENT_DISABLE_EXTENSIONS
last_optimistic_unchoke_cmplibtorrent::aux::__anon13c9013d2511::last_optimistic_unchoke_cmp3897 			explicit last_optimistic_unchoke_cmp(std::vector<std::shared_ptr<plugin>>& ps)
3898 				: plugins(ps)
3899 			{}
3900 
3901 			std::vector<std::shared_ptr<plugin>>& plugins;
3902 #endif
3903 
get_ext_prioritylibtorrent::aux::__anon13c9013d2511::last_optimistic_unchoke_cmp3904 			uint64_t get_ext_priority(opt_unchoke_candidate const& peer) const
3905 			{
3906 #ifndef TORRENT_DISABLE_EXTENSIONS
3907 				if (peer.ext_priority == priority_undetermined)
3908 				{
3909 					peer.ext_priority = std::numeric_limits<uint64_t>::max();
3910 					for (auto& e : plugins)
3911 					{
3912 						uint64_t const priority = e->get_unchoke_priority(peer_connection_handle(*peer.peer));
3913 						peer.ext_priority = std::min(priority, peer.ext_priority);
3914 					}
3915 				}
3916 				return peer.ext_priority;
3917 #else
3918 				TORRENT_UNUSED(peer);
3919 				return std::numeric_limits<uint64_t>::max();
3920 #endif
3921 			}
3922 
operator ()libtorrent::aux::__anon13c9013d2511::last_optimistic_unchoke_cmp3923 			bool operator()(opt_unchoke_candidate const& l
3924 				, opt_unchoke_candidate const& r) const
3925 			{
3926 				torrent_peer const* pil = (*l.peer)->peer_info_struct();
3927 				torrent_peer const* pir = (*r.peer)->peer_info_struct();
3928 				if (pil->last_optimistically_unchoked
3929 					!= pir->last_optimistically_unchoked)
3930 				{
3931 					return pil->last_optimistically_unchoked
3932 						< pir->last_optimistically_unchoked;
3933 				}
3934 				else
3935 				{
3936 					return get_ext_priority(l) < get_ext_priority(r);
3937 				}
3938 			}
3939 		};
3940 	}
3941 
recalculate_optimistic_unchoke_slots()3942 	void session_impl::recalculate_optimistic_unchoke_slots()
3943 	{
3944 		INVARIANT_CHECK;
3945 
3946 		TORRENT_ASSERT(is_single_thread());
3947 		if (m_stats_counters[counters::num_unchoke_slots] == 0) return;
3948 
3949 		// if we unchoke everyone, skip this logic
3950 		if (settings().get_int(settings_pack::choking_algorithm) == settings_pack::fixed_slots_choker
3951 			&& settings().get_int(settings_pack::unchoke_slots_limit) < 0)
3952 			return;
3953 
3954 		std::vector<opt_unchoke_candidate> opt_unchoke;
3955 
3956 		// collect the currently optimistically unchoked peers here, so we can
3957 		// choke them when we've found new optimistic unchoke candidates.
3958 		std::vector<torrent_peer*> prev_opt_unchoke;
3959 
3960 		// TODO: 3 it would probably make sense to have a separate list of peers
3961 		// that are eligible for optimistic unchoke, similar to the torrents
3962 		// perhaps this could even iterate over the pool allocators of
3963 		// torrent_peer objects. It could probably be done in a single pass and
3964 		// collect the n best candidates. maybe just a queue of peers would make
3965 		// even more sense, just pick the next peer in the queue for unchoking. It
3966 		// would be O(1).
3967 		for (auto& i : m_connections)
3968 		{
3969 			peer_connection* p = i.get();
3970 			TORRENT_ASSERT(p);
3971 			torrent_peer* pi = p->peer_info_struct();
3972 			if (!pi) continue;
3973 			if (pi->web_seed) continue;
3974 
3975 			if (pi->optimistically_unchoked)
3976 			{
3977 				prev_opt_unchoke.push_back(pi);
3978 			}
3979 
3980 			torrent const* t = p->associated_torrent().lock().get();
3981 			if (!t) continue;
3982 
3983 			// TODO: 3 peers should know whether their torrent is paused or not,
3984 			// instead of having to ask it over and over again
3985 			if (t->is_paused()) continue;
3986 
3987 			if (!p->is_connecting()
3988 				&& !p->is_disconnecting()
3989 				&& p->is_peer_interested()
3990 				&& t->free_upload_slots()
3991 				&& (p->is_choked() || pi->optimistically_unchoked)
3992 				&& !p->ignore_unchoke_slots()
3993 				&& t->valid_metadata())
3994 			{
3995 				opt_unchoke.emplace_back(&i);
3996 			}
3997 		}
3998 
3999 		// find the peers that has been waiting the longest to be optimistically
4000 		// unchoked
4001 
4002 		int num_opt_unchoke = m_settings.get_int(settings_pack::num_optimistic_unchoke_slots);
4003 		int const allowed_unchoke_slots = int(m_stats_counters[counters::num_unchoke_slots]);
4004 		if (num_opt_unchoke == 0) num_opt_unchoke = std::max(1, allowed_unchoke_slots / 5);
4005 		if (num_opt_unchoke > int(opt_unchoke.size())) num_opt_unchoke =
4006 			int(opt_unchoke.size());
4007 
4008 		// find the n best optimistic unchoke candidates
4009 		std::partial_sort(opt_unchoke.begin()
4010 			, opt_unchoke.begin() + num_opt_unchoke
4011 			, opt_unchoke.end()
4012 #ifndef TORRENT_DISABLE_EXTENSIONS
4013 			, last_optimistic_unchoke_cmp(m_ses_extensions[plugins_optimistic_unchoke_idx])
4014 #else
4015 			, last_optimistic_unchoke_cmp()
4016 #endif
4017 			);
4018 
4019 		// unchoke the first num_opt_unchoke peers in the candidate set
4020 		// and make sure that the others are choked
4021 		auto opt_unchoke_end = opt_unchoke.begin()
4022 			+ num_opt_unchoke;
4023 
4024 		for (auto i = opt_unchoke.begin(); i != opt_unchoke_end; ++i)
4025 		{
4026 			torrent_peer* pi = (*i->peer)->peer_info_struct();
4027 			peer_connection* p = static_cast<peer_connection*>(pi->connection);
4028 			if (pi->optimistically_unchoked)
4029 			{
4030 #ifndef TORRENT_DISABLE_LOGGING
4031 					p->peer_log(peer_log_alert::info, "OPTIMISTIC UNCHOKE"
4032 						, "already unchoked | session-time: %d"
4033 						, pi->last_optimistically_unchoked);
4034 #endif
4035 				TORRENT_ASSERT(!pi->connection->is_choked());
4036 				// remove this peer from prev_opt_unchoke, to prevent us from
4037 				// choking it later. This peer gets another round of optimistic
4038 				// unchoke
4039 				auto const existing =
4040 					std::find(prev_opt_unchoke.begin(), prev_opt_unchoke.end(), pi);
4041 				TORRENT_ASSERT(existing != prev_opt_unchoke.end());
4042 				prev_opt_unchoke.erase(existing);
4043 			}
4044 			else
4045 			{
4046 				TORRENT_ASSERT(p->is_choked());
4047 				std::shared_ptr<torrent> t = p->associated_torrent().lock();
4048 				bool ret = t->unchoke_peer(*p, true);
4049 				TORRENT_ASSERT(ret);
4050 				if (ret)
4051 				{
4052 					pi->optimistically_unchoked = true;
4053 					m_stats_counters.inc_stats_counter(counters::num_peers_up_unchoked_optimistic);
4054 					pi->last_optimistically_unchoked = std::uint16_t(session_time());
4055 #ifndef TORRENT_DISABLE_LOGGING
4056 					p->peer_log(peer_log_alert::info, "OPTIMISTIC UNCHOKE"
4057 						, "session-time: %d", pi->last_optimistically_unchoked);
4058 #endif
4059 				}
4060 			}
4061 		}
4062 
4063 		// now, choke all the previous optimistically unchoked peers
4064 		for (torrent_peer* pi : prev_opt_unchoke)
4065 		{
4066 			TORRENT_ASSERT(pi->optimistically_unchoked);
4067 			auto* p = static_cast<peer_connection*>(pi->connection);
4068 			std::shared_ptr<torrent> t = p->associated_torrent().lock();
4069 			pi->optimistically_unchoked = false;
4070 			m_stats_counters.inc_stats_counter(counters::num_peers_up_unchoked_optimistic, -1);
4071 			t->choke_peer(*p);
4072 		}
4073 
4074 		// if we have too many unchoked peers now, we need to trigger the regular
4075 		// choking logic to choke some
4076 		if (m_stats_counters[counters::num_unchoke_slots]
4077 			< m_stats_counters[counters::num_peers_up_unchoked_all])
4078 		{
4079 			m_unchoke_time_scaler = 0;
4080 		}
4081 	}
4082 
try_connect_more_peers()4083 	void session_impl::try_connect_more_peers()
4084 	{
4085 		if (m_abort) return;
4086 
4087 		if (num_connections() >= m_settings.get_int(settings_pack::connections_limit))
4088 			return;
4089 
4090 		// this is the maximum number of connections we will
4091 		// attempt this tick
4092 		int max_connections = m_settings.get_int(settings_pack::connection_speed);
4093 
4094 		// this loop will "hand out" connection_speed to the torrents, in a round
4095 		// robin fashion, so that every torrent is equally likely to connect to a
4096 		// peer
4097 
4098 		// boost connections are connections made by torrent connection
4099 		// boost, which are done immediately on a tracker response. These
4100 		// connections needs to be deducted from the regular connection attempt
4101 		// quota for this tick
4102 		if (m_boost_connections > 0)
4103 		{
4104 			if (m_boost_connections > max_connections)
4105 			{
4106 				m_boost_connections -= max_connections;
4107 				max_connections = 0;
4108 			}
4109 			else
4110 			{
4111 				max_connections -= m_boost_connections;
4112 				m_boost_connections = 0;
4113 			}
4114 		}
4115 
4116 		// zero connections speeds are allowed, we just won't make any connections
4117 		if (max_connections <= 0) return;
4118 
4119 		// TODO: use a lower limit than m_settings.connections_limit
4120 		// to allocate the to 10% or so of connection slots for incoming
4121 		// connections
4122 		// cap this at max - 1, since we may add one below
4123 		int const limit = std::min(m_settings.get_int(settings_pack::connections_limit)
4124 			- num_connections(), std::numeric_limits<int>::max() - 1);
4125 
4126 		// this logic is here to smooth out the number of new connection
4127 		// attempts over time, to prevent connecting a large number of
4128 		// sockets, wait 10 seconds, and then try again
4129 		if (m_settings.get_bool(settings_pack::smooth_connects) && max_connections > (limit+1) / 2)
4130 			max_connections = (limit + 1) / 2;
4131 
4132 		aux::vector<torrent*>& want_peers_download = m_torrent_lists[torrent_want_peers_download];
4133 		aux::vector<torrent*>& want_peers_finished = m_torrent_lists[torrent_want_peers_finished];
4134 
4135 		// if no torrent want any peers, just return
4136 		if (want_peers_download.empty() && want_peers_finished.empty()) return;
4137 
4138 		// if we don't have any connection attempt quota, return
4139 		if (max_connections <= 0) return;
4140 
4141 		int steps_since_last_connect = 0;
4142 		int const num_torrents = int(want_peers_finished.size() + want_peers_download.size());
4143 		for (;;)
4144 		{
4145 			if (m_next_downloading_connect_torrent >= int(want_peers_download.size()))
4146 				m_next_downloading_connect_torrent = 0;
4147 
4148 			if (m_next_finished_connect_torrent >= int(want_peers_finished.size()))
4149 				m_next_finished_connect_torrent = 0;
4150 
4151 			torrent* t = nullptr;
4152 			// there are prioritized torrents. Pick one of those
4153 			while (!m_prio_torrents.empty())
4154 			{
4155 				t = m_prio_torrents.front().first.lock().get();
4156 				--m_prio_torrents.front().second;
4157 				if (m_prio_torrents.front().second > 0
4158 					&& t != nullptr
4159 					&& t->want_peers()) break;
4160 				m_prio_torrents.pop_front();
4161 				t = nullptr;
4162 			}
4163 
4164 			if (t == nullptr)
4165 			{
4166 				if ((m_download_connect_attempts >= m_settings.get_int(
4167 						settings_pack::connect_seed_every_n_download)
4168 					&& !want_peers_finished.empty())
4169 						|| want_peers_download.empty())
4170 				{
4171 					// pick a finished torrent to give a peer to
4172 					t = want_peers_finished[m_next_finished_connect_torrent];
4173 					TORRENT_ASSERT(t->want_peers_finished());
4174 					m_download_connect_attempts = 0;
4175 					++m_next_finished_connect_torrent;
4176 				}
4177 				else
4178 				{
4179 					// pick a downloading torrent to give a peer to
4180 					t = want_peers_download[m_next_downloading_connect_torrent];
4181 					TORRENT_ASSERT(t->want_peers_download());
4182 					++m_download_connect_attempts;
4183 					++m_next_downloading_connect_torrent;
4184 				}
4185 			}
4186 
4187 			TORRENT_ASSERT(t->want_peers());
4188 			TORRENT_ASSERT(!t->is_torrent_paused());
4189 
4190 			if (t->try_connect_peer())
4191 			{
4192 				--max_connections;
4193 				steps_since_last_connect = 0;
4194 				m_stats_counters.inc_stats_counter(counters::connection_attempts);
4195 			}
4196 
4197 			++steps_since_last_connect;
4198 
4199 			// if there are no more free connection slots, abort
4200 			if (max_connections == 0) return;
4201 			// there are no more torrents that want peers
4202 			if (want_peers_download.empty() && want_peers_finished.empty()) break;
4203 			// if we have gone a whole loop without
4204 			// handing out a single connection, break
4205 			if (steps_since_last_connect > num_torrents + 1) break;
4206 			// maintain the global limit on number of connections
4207 			if (num_connections() >= m_settings.get_int(settings_pack::connections_limit)) break;
4208 		}
4209 	}
4210 
recalculate_unchoke_slots()4211 	void session_impl::recalculate_unchoke_slots()
4212 	{
4213 		TORRENT_ASSERT(is_single_thread());
4214 
4215 		time_point const now = aux::time_now();
4216 		time_duration const unchoke_interval = now - m_last_choke;
4217 		m_last_choke = now;
4218 
4219 		// if we unchoke everyone, skip this logic
4220 		if (settings().get_int(settings_pack::choking_algorithm) == settings_pack::fixed_slots_choker
4221 			&& settings().get_int(settings_pack::unchoke_slots_limit) < 0)
4222 		{
4223 			m_stats_counters.set_value(counters::num_unchoke_slots, std::numeric_limits<int>::max());
4224 			return;
4225 		}
4226 
4227 		// build list of all peers that are
4228 		// unchokable.
4229 		// TODO: 3 there should be a pre-calculated list of all peers eligible for
4230 		// unchoking
4231 		std::vector<peer_connection*> peers;
4232 		for (auto i = m_connections.begin(); i != m_connections.end();)
4233 		{
4234 			std::shared_ptr<peer_connection> p = *i;
4235 			TORRENT_ASSERT(p);
4236 			++i;
4237 			torrent* const t = p->associated_torrent().lock().get();
4238 			torrent_peer* const pi = p->peer_info_struct();
4239 
4240 			if (p->ignore_unchoke_slots() || t == nullptr || pi == nullptr
4241 				|| pi->web_seed || t->is_paused())
4242 			{
4243 				p->reset_choke_counters();
4244 				continue;
4245 			}
4246 
4247 			if (!p->is_peer_interested()
4248 				|| p->is_disconnecting()
4249 				|| p->is_connecting())
4250 			{
4251 				// this peer is not unchokable. So, if it's unchoked
4252 				// already, make sure to choke it.
4253 				if (p->is_choked())
4254 				{
4255 					p->reset_choke_counters();
4256 					continue;
4257 				}
4258 				if (pi && pi->optimistically_unchoked)
4259 				{
4260 					m_stats_counters.inc_stats_counter(counters::num_peers_up_unchoked_optimistic, -1);
4261 					pi->optimistically_unchoked = false;
4262 					// force a new optimistic unchoke
4263 					m_optimistic_unchoke_time_scaler = 0;
4264 					// TODO: post a message to have this happen
4265 					// immediately instead of waiting for the next tick
4266 				}
4267 				t->choke_peer(*p);
4268 				p->reset_choke_counters();
4269 				continue;
4270 			}
4271 
4272 			peers.push_back(p.get());
4273 		}
4274 
4275 #if TORRENT_ABI_VERSION == 1
4276 		// the unchoker wants an estimate of our upload rate capacity
4277 		// (used by bittyrant)
4278 		int max_upload_rate = upload_rate_limit(m_global_class);
4279 		if (m_settings.get_int(settings_pack::choking_algorithm)
4280 			== settings_pack::bittyrant_choker
4281 			&& max_upload_rate == 0)
4282 		{
4283 			// we don't know at what rate we can upload. If we have a
4284 			// measurement of the peak, use that + 10kB/s, otherwise
4285 			// assume 20 kB/s
4286 			max_upload_rate = std::max(20000, m_peak_up_rate + 10000);
4287 			if (m_alerts.should_post<performance_alert>())
4288 				m_alerts.emplace_alert<performance_alert>(torrent_handle()
4289 					, performance_alert::bittyrant_with_no_uplimit);
4290 		}
4291 #else
4292 		int const max_upload_rate = 0;
4293 #endif
4294 
4295 		int const allowed_upload_slots = unchoke_sort(peers, max_upload_rate
4296 			, unchoke_interval, m_settings);
4297 
4298 		if (m_settings.get_int(settings_pack::choking_algorithm) != settings_pack::fixed_slots_choker)
4299 		{
4300 			m_stats_counters.set_value(counters::num_unchoke_slots
4301 				, allowed_upload_slots);
4302 		}
4303 
4304 #ifndef TORRENT_DISABLE_LOGGING
4305 		if (should_log())
4306 		{
4307 			session_log("RECALCULATE UNCHOKE SLOTS: [ peers: %d "
4308 				"eligible-peers: %d"
4309 				" allowed-slots: %d ]"
4310 				, int(m_connections.size())
4311 				, int(peers.size())
4312 				, allowed_upload_slots);
4313 		}
4314 #endif
4315 
4316 		int const unchoked_counter_optimistic
4317 			= int(m_stats_counters[counters::num_peers_up_unchoked_optimistic]);
4318 		int const num_opt_unchoke = (unchoked_counter_optimistic == 0)
4319 			? std::max(1, allowed_upload_slots / 5) : unchoked_counter_optimistic;
4320 
4321 		int unchoke_set_size = allowed_upload_slots - num_opt_unchoke;
4322 
4323 		// go through all the peers and unchoke the first ones and choke
4324 		// all the other ones.
4325 		for (auto p : peers)
4326 		{
4327 			TORRENT_ASSERT(p != nullptr);
4328 			TORRENT_ASSERT(!p->ignore_unchoke_slots());
4329 
4330 			// this will update the m_uploaded_at_last_unchoke
4331 			p->reset_choke_counters();
4332 
4333 			torrent* t = p->associated_torrent().lock().get();
4334 			TORRENT_ASSERT(t);
4335 
4336 			if (unchoke_set_size > 0)
4337 			{
4338 				// yes, this peer should be unchoked
4339 				if (p->is_choked())
4340 				{
4341 					if (!t->unchoke_peer(*p))
4342 						continue;
4343 				}
4344 
4345 				--unchoke_set_size;
4346 
4347 				TORRENT_ASSERT(p->peer_info_struct());
4348 				if (p->peer_info_struct()->optimistically_unchoked)
4349 				{
4350 					// force a new optimistic unchoke
4351 					// since this one just got promoted into the
4352 					// proper unchoke set
4353 					m_optimistic_unchoke_time_scaler = 0;
4354 					p->peer_info_struct()->optimistically_unchoked = false;
4355 					m_stats_counters.inc_stats_counter(counters::num_peers_up_unchoked_optimistic, -1);
4356 				}
4357 			}
4358 			else
4359 			{
4360 				// no, this peer should be choked
4361 				TORRENT_ASSERT(p->peer_info_struct());
4362 				if (!p->is_choked() && !p->peer_info_struct()->optimistically_unchoked)
4363 					t->choke_peer(*p);
4364 			}
4365 		}
4366 	}
4367 
delay_load_torrent(sha1_hash const & info_hash,peer_connection * pc)4368 	std::shared_ptr<torrent> session_impl::delay_load_torrent(sha1_hash const& info_hash
4369 		, peer_connection* pc)
4370 	{
4371 #ifndef TORRENT_DISABLE_EXTENSIONS
4372 		for (auto& e : m_ses_extensions[plugins_all_idx])
4373 		{
4374 			add_torrent_params p;
4375 			if (e->on_unknown_torrent(info_hash, peer_connection_handle(pc->self()), p))
4376 			{
4377 				error_code ec;
4378 				torrent_handle handle = add_torrent(std::move(p), ec);
4379 
4380 				return handle.native_handle();
4381 			}
4382 		}
4383 #else
4384 		TORRENT_UNUSED(pc);
4385 		TORRENT_UNUSED(info_hash);
4386 #endif
4387 		return std::shared_ptr<torrent>();
4388 	}
4389 
4390 	// the return value from this function is valid only as long as the
4391 	// session is locked!
find_torrent(sha1_hash const & info_hash) const4392 	std::weak_ptr<torrent> session_impl::find_torrent(sha1_hash const& info_hash) const
4393 	{
4394 		TORRENT_ASSERT(is_single_thread());
4395 
4396 		auto const i = m_torrents.find(info_hash);
4397 #if TORRENT_USE_INVARIANT_CHECKS
4398 		for (auto const& te : m_torrents)
4399 		{
4400 			TORRENT_ASSERT(te.second);
4401 		}
4402 #endif
4403 		if (i != m_torrents.end()) return i->second;
4404 		return std::weak_ptr<torrent>();
4405 	}
4406 
insert_torrent(sha1_hash const & ih,std::shared_ptr<torrent> const & t,std::string const uuid)4407 	void session_impl::insert_torrent(sha1_hash const& ih, std::shared_ptr<torrent> const& t
4408 #if TORRENT_ABI_VERSION == 1
4409 		, std::string const uuid
4410 #endif
4411 		)
4412 	{
4413 		sha1_hash const next_lsd = m_next_lsd_torrent != m_torrents.end()
4414 			? m_next_lsd_torrent->first : sha1_hash();
4415 #ifndef TORRENT_DISABLE_DHT
4416 		sha1_hash const next_dht = m_next_dht_torrent != m_torrents.end()
4417 			? m_next_dht_torrent->first : sha1_hash();
4418 #endif
4419 
4420 		float const load_factor = m_torrents.load_factor();
4421 
4422 		m_torrents.emplace(ih, t);
4423 
4424 #if !defined TORRENT_DISABLE_ENCRYPTION
4425 		static char const req2[4] = {'r', 'e', 'q', '2'};
4426 		hasher h(req2);
4427 		h.update(ih);
4428 		// this is SHA1("req2" + info-hash), used for
4429 		// encrypted hand shakes
4430 		m_obfuscated_torrents.emplace(h.final(), t);
4431 #endif
4432 
4433 		// if this insert made the hash grow, the iterators became invalid
4434 		// we need to reset them
4435 		if (m_torrents.load_factor() < load_factor)
4436 		{
4437 			// this indicates the hash table re-hashed
4438 			if (!next_lsd.is_all_zeros())
4439 				m_next_lsd_torrent = m_torrents.find(next_lsd);
4440 #ifndef TORRENT_DISABLE_DHT
4441 			if (!next_dht.is_all_zeros())
4442 				m_next_dht_torrent = m_torrents.find(next_dht);
4443 #endif
4444 		}
4445 
4446 #if TORRENT_ABI_VERSION == 1
4447 		//deprecated in 1.2
4448 		if (!uuid.empty()) m_uuids.insert(std::make_pair(uuid, t));
4449 #endif
4450 
4451 		t->added();
4452 	}
4453 
set_queue_position(torrent * me,queue_position_t p)4454 	void session_impl::set_queue_position(torrent* me, queue_position_t p)
4455 	{
4456 		queue_position_t const current_pos = me->queue_position();
4457 		if (current_pos == p) return;
4458 
4459 		if (p >= queue_position_t{0} && current_pos == no_pos)
4460 		{
4461 			// we're inserting the torrent into the download queue
4462 			queue_position_t const last = m_download_queue.end_index();
4463 			if (p >= last)
4464 			{
4465 				m_download_queue.push_back(me);
4466 				me->set_queue_position_impl(last);
4467 			}
4468 			else
4469 			{
4470 				m_download_queue.insert(m_download_queue.begin() + static_cast<int>(p), me);
4471 				for (queue_position_t i = p; i < m_download_queue.end_index(); ++i)
4472 				{
4473 					m_download_queue[i]->set_queue_position_impl(i);
4474 				}
4475 			}
4476 		}
4477 		else if (p < queue_position_t{})
4478 		{
4479 			// we're removing the torrent from the download queue
4480 			TORRENT_ASSERT(current_pos >= queue_position_t{0});
4481 			TORRENT_ASSERT(p == no_pos);
4482 			TORRENT_ASSERT(m_download_queue[current_pos] == me);
4483 			m_download_queue.erase(m_download_queue.begin() + static_cast<int>(current_pos));
4484 			me->set_queue_position_impl(no_pos);
4485 			for (queue_position_t i = current_pos; i < m_download_queue.end_index(); ++i)
4486 			{
4487 				m_download_queue[i]->set_queue_position_impl(i);
4488 			}
4489 		}
4490 		else if (p < current_pos)
4491 		{
4492 			// we're moving the torrent up the queue
4493 			torrent* tmp = me;
4494 			for (queue_position_t i = p; i <= current_pos; ++i)
4495 			{
4496 				std::swap(m_download_queue[i], tmp);
4497 				m_download_queue[i]->set_queue_position_impl(i);
4498 			}
4499 			TORRENT_ASSERT(tmp == me);
4500 		}
4501 		else if (p > current_pos)
4502 		{
4503 			// we're moving the torrent down the queue
4504 			p = std::min(p, prev(m_download_queue.end_index()));
4505 			for (queue_position_t i = current_pos; i < p; ++i)
4506 			{
4507 				m_download_queue[i] = m_download_queue[next(i)];
4508 				m_download_queue[i]->set_queue_position_impl(i);
4509 			}
4510 			m_download_queue[p] = me;
4511 			me->set_queue_position_impl(p);
4512 		}
4513 
4514 		trigger_auto_manage();
4515 	}
4516 
4517 #if !defined TORRENT_DISABLE_ENCRYPTION
find_encrypted_torrent(sha1_hash const & info_hash,sha1_hash const & xor_mask)4518 	torrent const* session_impl::find_encrypted_torrent(sha1_hash const& info_hash
4519 		, sha1_hash const& xor_mask)
4520 	{
4521 		sha1_hash obfuscated = info_hash;
4522 		obfuscated ^= xor_mask;
4523 
4524 		auto const i = m_obfuscated_torrents.find(obfuscated);
4525 		if (i == m_obfuscated_torrents.end()) return nullptr;
4526 		return i->second.get();
4527 	}
4528 #endif
4529 
4530 #if TORRENT_ABI_VERSION == 1
4531 	//deprecated in 1.2
find_torrent(std::string const & uuid) const4532 	std::weak_ptr<torrent> session_impl::find_torrent(std::string const& uuid) const
4533 	{
4534 		TORRENT_ASSERT(is_single_thread());
4535 
4536 		auto const i = m_uuids.find(uuid);
4537 		if (i != m_uuids.end()) return i->second;
4538 		return std::weak_ptr<torrent>();
4539 	}
4540 #endif
4541 
4542 #ifndef TORRENT_DISABLE_MUTABLE_TORRENTS
find_collection(std::string const & collection) const4543 	std::vector<std::shared_ptr<torrent>> session_impl::find_collection(
4544 		std::string const& collection) const
4545 	{
4546 		std::vector<std::shared_ptr<torrent>> ret;
4547 		for (auto const& tp : m_torrents)
4548 		{
4549 			std::shared_ptr<torrent> t = tp.second;
4550 			if (!t) continue;
4551 			std::vector<std::string> const& c = t->torrent_file().collections();
4552 			if (std::find(c.begin(), c.end(), collection) == c.end()) continue;
4553 			ret.push_back(t);
4554 		}
4555 		return ret;
4556 	}
4557 #endif //TORRENT_DISABLE_MUTABLE_TORRENTS
4558 
4559 	namespace {
4560 
4561 	// returns true if lhs is a better disconnect candidate than rhs
compare_disconnect_torrent(session_impl::torrent_map::value_type const & lhs,session_impl::torrent_map::value_type const & rhs)4562 	bool compare_disconnect_torrent(session_impl::torrent_map::value_type const& lhs
4563 		, session_impl::torrent_map::value_type const& rhs)
4564 	{
4565 		// a torrent with 0 peers is never a good disconnect candidate
4566 		// since there's nothing to disconnect
4567 		if ((lhs.second->num_peers() == 0) != (rhs.second->num_peers() == 0))
4568 			return lhs.second->num_peers() != 0;
4569 
4570 		// other than that, always prefer to disconnect peers from seeding torrents
4571 		// in order to not harm downloading ones
4572 		if (lhs.second->is_seed() != rhs.second->is_seed())
4573 			return lhs.second->is_seed();
4574 
4575 		return lhs.second->num_peers() > rhs.second->num_peers();
4576 	}
4577 
4578 	} // anonymous namespace
4579 
find_disconnect_candidate_torrent() const4580 	std::weak_ptr<torrent> session_impl::find_disconnect_candidate_torrent() const
4581 	{
4582 		auto const i = std::min_element(m_torrents.begin(), m_torrents.end()
4583 			, &compare_disconnect_torrent);
4584 
4585 		TORRENT_ASSERT(i != m_torrents.end());
4586 		if (i == m_torrents.end()) return std::shared_ptr<torrent>();
4587 
4588 		return i->second;
4589 	}
4590 
4591 #ifndef TORRENT_DISABLE_LOGGING
should_log() const4592 	bool session_impl::should_log() const
4593 	{
4594 		return m_alerts.should_post<log_alert>();
4595 	}
4596 
4597 	TORRENT_FORMAT(2,3)
session_log(char const * fmt,...) const4598 	void session_impl::session_log(char const* fmt, ...) const noexcept try
4599 	{
4600 		if (!m_alerts.should_post<log_alert>()) return;
4601 
4602 		va_list v;
4603 		va_start(v, fmt);
4604 		m_alerts.emplace_alert<log_alert>(fmt, v);
4605 		va_end(v);
4606 	}
4607 	catch (std::exception const&) {}
4608 #endif
4609 
get_torrent_status(std::vector<torrent_status> * ret,std::function<bool (torrent_status const &)> const & pred,status_flags_t const flags) const4610 	void session_impl::get_torrent_status(std::vector<torrent_status>* ret
4611 		, std::function<bool(torrent_status const&)> const& pred
4612 		, status_flags_t const flags) const
4613 	{
4614 		for (auto const& t : m_torrents)
4615 		{
4616 			if (t.second->is_aborted()) continue;
4617 			torrent_status st;
4618 			t.second->status(&st, flags);
4619 			if (!pred(st)) continue;
4620 			ret->push_back(std::move(st));
4621 		}
4622 	}
4623 
refresh_torrent_status(std::vector<torrent_status> * ret,status_flags_t const flags) const4624 	void session_impl::refresh_torrent_status(std::vector<torrent_status>* ret
4625 		, status_flags_t const flags) const
4626 	{
4627 		for (auto& st : *ret)
4628 		{
4629 			auto t = st.handle.m_torrent.lock();
4630 			if (!t) continue;
4631 			t->status(&st, flags);
4632 		}
4633 	}
4634 
post_torrent_updates(status_flags_t const flags)4635 	void session_impl::post_torrent_updates(status_flags_t const flags)
4636 	{
4637 		INVARIANT_CHECK;
4638 
4639 		TORRENT_ASSERT(is_single_thread());
4640 
4641 		std::vector<torrent*>& state_updates
4642 			= m_torrent_lists[aux::session_impl::torrent_state_updates];
4643 
4644 #if TORRENT_USE_ASSERTS
4645 		m_posting_torrent_updates = true;
4646 #endif
4647 
4648 		std::vector<torrent_status> status;
4649 		status.reserve(state_updates.size());
4650 
4651 		// TODO: it might be a nice feature here to limit the number of torrents
4652 		// to send in a single update. By just posting the first n torrents, they
4653 		// would nicely be round-robined because the torrent lists are always
4654 		// pushed back. Perhaps the status_update_alert could even have a fixed
4655 		// array of n entries rather than a vector, to further improve memory
4656 		// locality.
4657 		for (auto& t : state_updates)
4658 		{
4659 			TORRENT_ASSERT(t->m_links[aux::session_impl::torrent_state_updates].in_list());
4660 			status.emplace_back();
4661 			// querying accurate download counters may require
4662 			// the torrent to be loaded. Loading a torrent, and evicting another
4663 			// one will lead to calling state_updated(), which screws with
4664 			// this list while we're working on it, and break things
4665 			t->status(&status.back(), flags);
4666 			t->clear_in_state_update();
4667 		}
4668 		state_updates.clear();
4669 
4670 #if TORRENT_USE_ASSERTS
4671 		m_posting_torrent_updates = false;
4672 #endif
4673 
4674 		m_alerts.emplace_alert<state_update_alert>(std::move(status));
4675 	}
4676 
post_session_stats()4677 	void session_impl::post_session_stats()
4678 	{
4679 		if (!m_posted_stats_header)
4680 		{
4681 			m_posted_stats_header = true;
4682 			m_alerts.emplace_alert<session_stats_header_alert>();
4683 		}
4684 		m_disk_thread.update_stats_counters(m_stats_counters);
4685 
4686 #ifndef TORRENT_DISABLE_DHT
4687 		if (m_dht)
4688 			m_dht->update_stats_counters(m_stats_counters);
4689 #endif
4690 
4691 		m_stats_counters.set_value(counters::limiter_up_queue
4692 			, m_upload_rate.queue_size());
4693 		m_stats_counters.set_value(counters::limiter_down_queue
4694 			, m_download_rate.queue_size());
4695 
4696 		m_stats_counters.set_value(counters::limiter_up_bytes
4697 			, m_upload_rate.queued_bytes());
4698 		m_stats_counters.set_value(counters::limiter_down_bytes
4699 			, m_download_rate.queued_bytes());
4700 
4701 		m_alerts.emplace_alert<session_stats_alert>(m_stats_counters);
4702 	}
4703 
post_dht_stats()4704 	void session_impl::post_dht_stats()
4705 	{
4706 		std::vector<dht_lookup> requests;
4707 		std::vector<dht_routing_bucket> table;
4708 
4709 #ifndef TORRENT_DISABLE_DHT
4710 		if (m_dht)
4711 			m_dht->dht_status(table, requests);
4712 #endif
4713 
4714 		m_alerts.emplace_alert<dht_stats_alert>(std::move(table), std::move(requests));
4715 	}
4716 
get_torrents() const4717 	std::vector<torrent_handle> session_impl::get_torrents() const
4718 	{
4719 		std::vector<torrent_handle> ret;
4720 
4721 		for (auto const& i : m_torrents)
4722 		{
4723 			if (i.second->is_aborted()) continue;
4724 			ret.push_back(torrent_handle(i.second));
4725 		}
4726 		return ret;
4727 	}
4728 
find_torrent_handle(sha1_hash const & info_hash)4729 	torrent_handle session_impl::find_torrent_handle(sha1_hash const& info_hash)
4730 	{
4731 		return torrent_handle(find_torrent(info_hash));
4732 	}
4733 
async_add_torrent(add_torrent_params * params)4734 	void session_impl::async_add_torrent(add_torrent_params* params)
4735 	{
4736 		std::unique_ptr<add_torrent_params> holder(params);
4737 
4738 #if TORRENT_ABI_VERSION == 1
4739 		if (!params->ti && string_begins_no_case("file://", params->url.c_str()))
4740 		{
4741 			if (!m_torrent_load_thread)
4742 				m_torrent_load_thread.reset(new work_thread_t());
4743 
4744 			m_torrent_load_thread->ios.post([params, this]
4745 			{
4746 				std::string const torrent_file_path = resolve_file_url(params->url);
4747 				params->url.clear();
4748 
4749 				std::unique_ptr<add_torrent_params> holder2(params);
4750 				error_code ec;
4751 				params->ti = std::make_shared<torrent_info>(torrent_file_path, ec);
4752 				this->m_io_service.post(std::bind(&session_impl::on_async_load_torrent
4753 					, this, params, ec));
4754 				holder2.release();
4755 			});
4756 			holder.release();
4757 			return;
4758 		}
4759 #endif
4760 
4761 		error_code ec;
4762 		add_torrent(std::move(*params), ec);
4763 	}
4764 
4765 #if TORRENT_ABI_VERSION == 1
on_async_load_torrent(add_torrent_params * params,error_code ec)4766 	void session_impl::on_async_load_torrent(add_torrent_params* params, error_code ec)
4767 	{
4768 		std::unique_ptr<add_torrent_params> holder(params);
4769 
4770 		if (ec)
4771 		{
4772 			m_alerts.emplace_alert<add_torrent_alert>(torrent_handle()
4773 				, *params, ec);
4774 			return;
4775 		}
4776 		TORRENT_ASSERT(params->ti->is_valid());
4777 		TORRENT_ASSERT(params->ti->num_files() > 0);
4778 		params->url.clear();
4779 		add_torrent(std::move(*params), ec);
4780 	}
4781 #endif
4782 
4783 #ifndef TORRENT_DISABLE_EXTENSIONS
add_extensions_to_torrent(std::shared_ptr<torrent> const & torrent_ptr,void * userdata)4784 	void session_impl::add_extensions_to_torrent(
4785 		std::shared_ptr<torrent> const& torrent_ptr, void* userdata)
4786 	{
4787 		for (auto& e : m_ses_extensions[plugins_all_idx])
4788 		{
4789 			std::shared_ptr<torrent_plugin> tp(e->new_torrent(
4790 				torrent_ptr->get_handle(), userdata));
4791 			if (tp) torrent_ptr->add_extension(std::move(tp));
4792 		}
4793 	}
4794 #endif
4795 
add_torrent(add_torrent_params && params,error_code & ec)4796 	torrent_handle session_impl::add_torrent(add_torrent_params&& params
4797 		, error_code& ec)
4798 	{
4799 		// params is updated by add_torrent_impl()
4800 		std::shared_ptr<torrent> torrent_ptr;
4801 
4802 		// in case there's an error, make sure to abort the torrent before leaving
4803 		// the scope
4804 		auto abort_torrent = aux::scope_end([&]{ if (torrent_ptr) torrent_ptr->abort(); });
4805 
4806 		bool added;
4807 		// TODO: 3 perhaps params could be moved into the torrent object, instead
4808 		// of it being copied by the torrent constructor
4809 		std::tie(torrent_ptr, added) = add_torrent_impl(params, ec);
4810 
4811 		torrent_handle const handle(torrent_ptr);
4812 		m_alerts.emplace_alert<add_torrent_alert>(handle, params, ec);
4813 
4814 		if (!torrent_ptr) return handle;
4815 
4816 		// params.info_hash should have been initialized by add_torrent_impl()
4817 		TORRENT_ASSERT(params.info_hash != sha1_hash(nullptr));
4818 
4819 #ifndef TORRENT_DISABLE_DHT
4820 		if (params.ti)
4821 		{
4822 			for (auto const& n : params.ti->nodes())
4823 				add_dht_node_name(n);
4824 		}
4825 #endif
4826 
4827 #if TORRENT_ABI_VERSION == 1
4828 		if (m_alerts.should_post<torrent_added_alert>())
4829 			m_alerts.emplace_alert<torrent_added_alert>(handle);
4830 #endif
4831 
4832 		// if this was an existing torrent, we can't start it again, or add
4833 		// another set of plugins etc. we're done
4834 		if (!added)
4835 		{
4836 			abort_torrent.disarm();
4837 			return handle;
4838 		}
4839 
4840 		torrent_ptr->set_ip_filter(m_ip_filter);
4841 		torrent_ptr->start();
4842 
4843 #ifndef TORRENT_DISABLE_EXTENSIONS
4844 		for (auto& ext : params.extensions)
4845 		{
4846 			std::shared_ptr<torrent_plugin> tp(ext(handle, params.userdata));
4847 			if (tp) torrent_ptr->add_extension(std::move(tp));
4848 		}
4849 
4850 		add_extensions_to_torrent(torrent_ptr, params.userdata);
4851 #endif
4852 
4853 		insert_torrent(params.info_hash, torrent_ptr
4854 #if TORRENT_ABI_VERSION == 1
4855 			//deprecated in 1.2
4856 			, params.uuid.empty()
4857 				? params.url.empty() ? std::string()
4858 				: params.url
4859 				: params.uuid
4860 #endif
4861 		);
4862 
4863 		// once we successfully add the torrent, we can disarm the abort action
4864 		abort_torrent.disarm();
4865 
4866 		// recalculate auto-managed torrents sooner (or put it off)
4867 		// if another torrent will be added within one second from now
4868 		// we want to put it off again anyway. So that while we're adding
4869 		// a boat load of torrents, we postpone the recalculation until
4870 		// we're done adding them all (since it's kind of an expensive operation)
4871 		if (params.flags & torrent_flags::auto_managed)
4872 		{
4873 			const int max_downloading = settings().get_int(settings_pack::active_downloads);
4874 			const int max_seeds = settings().get_int(settings_pack::active_seeds);
4875 			const int max_active = settings().get_int(settings_pack::active_limit);
4876 
4877 			const int num_downloading
4878 			= int(torrent_list(session_interface::torrent_downloading_auto_managed).size());
4879 			const int num_seeds
4880 			= int(torrent_list(session_interface::torrent_seeding_auto_managed).size());
4881 			const int num_active = num_downloading + num_seeds;
4882 
4883 			// there's no point in triggering the auto manage logic early if we
4884 			// don't have a reason to believe anything will change. It's kind of
4885 			// expensive.
4886 			if ((num_downloading < max_downloading
4887 				|| num_seeds < max_seeds)
4888 				&& num_active < max_active)
4889 			{
4890 				trigger_auto_manage();
4891 			}
4892 		}
4893 
4894 		return handle;
4895 	}
4896 
4897 	std::pair<std::shared_ptr<torrent>, bool>
add_torrent_impl(add_torrent_params & params,error_code & ec)4898 	session_impl::add_torrent_impl(add_torrent_params& params, error_code& ec)
4899 	{
4900 		TORRENT_ASSERT(!params.save_path.empty());
4901 
4902 		using ptr_t = std::shared_ptr<torrent>;
4903 
4904 #if TORRENT_ABI_VERSION == 1
4905 		if (string_begins_no_case("magnet:", params.url.c_str()))
4906 		{
4907 			parse_magnet_uri(params.url, params, ec);
4908 			if (ec) return std::make_pair(ptr_t(), false);
4909 			params.url.clear();
4910 		}
4911 
4912 		if (!params.ti && string_begins_no_case("file://", params.url.c_str()))
4913 		{
4914 			std::string const torrent_file_path = resolve_file_url(params.url);
4915 			params.url.clear();
4916 			auto t = std::make_shared<torrent_info>(torrent_file_path, std::ref(ec), 0);
4917 			if (ec) return std::make_pair(ptr_t(), false);
4918 			params.ti = t;
4919 		}
4920 #endif
4921 
4922 		if (params.ti && !params.ti->is_valid())
4923 		{
4924 			ec = errors::no_metadata;
4925 			return std::make_pair(ptr_t(), false);
4926 		}
4927 
4928 		if (params.ti && params.ti->is_valid() && params.ti->num_files() == 0)
4929 		{
4930 			ec = errors::no_files_in_torrent;
4931 			return std::make_pair(ptr_t(), false);
4932 		}
4933 
4934 		if (params.ti
4935 			&& !params.info_hash.is_all_zeros()
4936 			&& params.info_hash != params.ti->info_hash())
4937 		{
4938 			ec = errors::mismatching_info_hash;
4939 			return std::make_pair(ptr_t(), false);
4940 		}
4941 
4942 #ifndef TORRENT_DISABLE_DHT
4943 		// add params.dht_nodes to the DHT, if enabled
4944 		for (auto const& n : params.dht_nodes)
4945 			add_dht_node_name(n);
4946 #endif
4947 
4948 		INVARIANT_CHECK;
4949 
4950 		if (is_aborted())
4951 		{
4952 			ec = errors::session_is_closing;
4953 			return std::make_pair(ptr_t(), false);
4954 		}
4955 
4956 		// figure out the info hash of the torrent and make sure params.info_hash
4957 		// is set correctly
4958 		if (params.ti) params.info_hash = params.ti->info_hash();
4959 #if TORRENT_ABI_VERSION == 1
4960 		//deprecated in 1.2
4961 		else if (!params.url.empty())
4962 		{
4963 			// in order to avoid info-hash collisions, for
4964 			// torrents where we don't have an info-hash, but
4965 			// just a URL, set the temporary info-hash to the
4966 			// hash of the URL. This will be changed once we
4967 			// have the actual .torrent file
4968 			params.info_hash = hasher(&params.url[0], int(params.url.size())).final();
4969 		}
4970 #endif
4971 
4972 		if (params.info_hash.is_all_zeros())
4973 		{
4974 			ec = errors::missing_info_hash_in_uri;
4975 			return std::make_pair(ptr_t(), false);
4976 		}
4977 
4978 		// is the torrent already active?
4979 		std::shared_ptr<torrent> torrent_ptr = find_torrent(params.info_hash).lock();
4980 #if TORRENT_ABI_VERSION == 1
4981 		//deprecated in 1.2
4982 		if (!torrent_ptr && !params.uuid.empty()) torrent_ptr = find_torrent(params.uuid).lock();
4983 		// if we still can't find the torrent, look for it by url
4984 		if (!torrent_ptr && !params.url.empty())
4985 		{
4986 			auto const i = std::find_if(m_torrents.begin(), m_torrents.end()
4987 				, [&params](torrent_map::value_type const& te)
4988 				{ return te.second->url() == params.url; });
4989 			if (i != m_torrents.end())
4990 				torrent_ptr = i->second;
4991 		}
4992 #endif
4993 
4994 		if (torrent_ptr)
4995 		{
4996 			if (!(params.flags & torrent_flags::duplicate_is_error))
4997 			{
4998 #if TORRENT_ABI_VERSION == 1
4999 				//deprecated in 1.2
5000 				if (!params.uuid.empty() && torrent_ptr->uuid().empty())
5001 					torrent_ptr->set_uuid(params.uuid);
5002 				if (!params.url.empty() && torrent_ptr->url().empty())
5003 					torrent_ptr->set_url(params.url);
5004 #endif
5005 				return std::make_pair(torrent_ptr, false);
5006 			}
5007 
5008 			ec = errors::duplicate_torrent;
5009 			return std::make_pair(ptr_t(), false);
5010 		}
5011 
5012 		// make sure we have enough memory in the torrent lists up-front,
5013 		// since when torrents changes states, we cannot allocate memory that
5014 		// might fail.
5015 		size_t const num_torrents = m_torrents.size();
5016 		for (auto& l : m_torrent_lists)
5017 		{
5018 			l.reserve(num_torrents + 1);
5019 		}
5020 
5021 		torrent_ptr = std::make_shared<torrent>(*this, m_paused, params);
5022 		torrent_ptr->set_queue_position(m_download_queue.end_index());
5023 
5024 		return std::make_pair(torrent_ptr, true);
5025 	}
5026 
update_outgoing_interfaces()5027 	void session_impl::update_outgoing_interfaces()
5028 	{
5029 		std::string const net_interfaces = m_settings.get_str(settings_pack::outgoing_interfaces);
5030 
5031 		// declared in string_util.hpp
5032 		parse_comma_separated_string(net_interfaces, m_outgoing_interfaces);
5033 
5034 #ifndef TORRENT_DISABLE_LOGGING
5035 		if (!net_interfaces.empty() && m_outgoing_interfaces.empty())
5036 		{
5037 			session_log("ERROR: failed to parse outgoing interface list: %s"
5038 				, net_interfaces.c_str());
5039 		}
5040 #endif
5041 	}
5042 
bind_outgoing_socket(socket_type & s,address const & remote_address,error_code & ec) const5043 	tcp::endpoint session_impl::bind_outgoing_socket(socket_type& s
5044 		, address const& remote_address, error_code& ec) const
5045 	{
5046 		tcp::endpoint bind_ep(address_v4(), 0);
5047 		if (m_settings.get_int(settings_pack::outgoing_port) > 0)
5048 		{
5049 #ifdef TORRENT_WINDOWS
5050 			s.set_option(exclusive_address_use(true), ec);
5051 #else
5052 			s.set_option(tcp::acceptor::reuse_address(true), ec);
5053 #endif
5054 			// ignore errors because the underlying socket may not
5055 			// be opened yet. This happens when we're routing through
5056 			// a proxy. In that case, we don't yet know the address of
5057 			// the proxy server, and more importantly, we don't know
5058 			// the address family of its address. This means we can't
5059 			// open the socket yet. The socks abstraction layer defers
5060 			// opening it.
5061 			ec.clear();
5062 			bind_ep.port(std::uint16_t(next_port()));
5063 		}
5064 
5065 		if (is_utp(s))
5066 		{
5067 			// TODO: factor out this logic into a separate function for unit
5068 			// testing
5069 
5070 			utp_socket_impl* impl = nullptr;
5071 			transport ssl = transport::plaintext;
5072 #ifdef TORRENT_USE_OPENSSL
5073 			if (s.get<ssl_stream<utp_stream>>() != nullptr)
5074 			{
5075 				impl = s.get<ssl_stream<utp_stream>>()->next_layer().get_impl();
5076 				ssl = transport::ssl;
5077 			}
5078 			else
5079 #endif
5080 				impl = s.get<utp_stream>()->get_impl();
5081 
5082 			std::vector<std::shared_ptr<listen_socket_t>> with_gateways;
5083 			std::shared_ptr<listen_socket_t> match;
5084 			for (auto& ls : m_listen_sockets)
5085 			{
5086 				if (is_v4(ls->local_endpoint) != remote_address.is_v4()) continue;
5087 				if (ls->ssl != ssl) continue;
5088 				if (!(ls->flags & listen_socket_t::local_network))
5089 					with_gateways.push_back(ls);
5090 
5091 				if (match_addr_mask(ls->local_endpoint.address(), remote_address, ls->netmask))
5092 				{
5093 					// is this better than the previous match?
5094 					match = ls;
5095 				}
5096 			}
5097 			if (!match && !with_gateways.empty())
5098 				match = with_gateways[random(std::uint32_t(with_gateways.size() - 1))];
5099 
5100 			if (match)
5101 			{
5102 				utp_init_socket(impl, match);
5103 				return match->local_endpoint;
5104 			}
5105 			ec.assign(boost::system::errc::not_supported, generic_category());
5106 			return {};
5107 		}
5108 
5109 		if (!m_outgoing_interfaces.empty())
5110 		{
5111 			if (m_interface_index >= m_outgoing_interfaces.size()) m_interface_index = 0;
5112 			std::string const& ifname = m_outgoing_interfaces[m_interface_index++];
5113 
5114 			bind_ep.address(bind_socket_to_device(m_io_service, s
5115 				, remote_address.is_v4() ? tcp::v4() : tcp::v6()
5116 				, ifname.c_str(), bind_ep.port(), ec));
5117 			return bind_ep;
5118 		}
5119 
5120 		// if we're not binding to a specific interface, bind
5121 		// to the same protocol family as the target endpoint
5122 		if (is_any(bind_ep.address()))
5123 		{
5124 			if (remote_address.is_v6())
5125 				bind_ep.address(address_v6::any());
5126 			else
5127 				bind_ep.address(address_v4::any());
5128 		}
5129 
5130 		s.bind(bind_ep, ec);
5131 		return bind_ep;
5132 	}
5133 
5134 	// verify that ``addr``s interface allows incoming connections
verify_incoming_interface(address const & addr)5135 	bool session_impl::verify_incoming_interface(address const& addr)
5136 	{
5137 		auto const iter = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
5138 			, [&addr](std::shared_ptr<listen_socket_t> const& s)
5139 			{ return s->local_endpoint.address() == addr; });
5140 		return iter == m_listen_sockets.end()
5141 			? false
5142 			: bool((*iter)->flags & listen_socket_t::accept_incoming);
5143 	}
5144 
5145 	// verify that the given local address satisfies the requirements of
5146 	// the outgoing interfaces. i.e. that one of the allowed outgoing
5147 	// interfaces has this address. For uTP sockets, which are all backed
5148 	// by an unconnected udp socket, we won't be able to tell what local
5149 	// address is used for this peer's packets, in that case, just make
5150 	// sure one of the allowed interfaces exists and maybe that it's the
5151 	// default route. For systems that have SO_BINDTODEVICE, it should be
5152 	// enough to just know that one of the devices exist
verify_bound_address(address const & addr,bool utp,error_code & ec)5153 	bool session_impl::verify_bound_address(address const& addr, bool utp
5154 		, error_code& ec)
5155 	{
5156 		TORRENT_UNUSED(utp);
5157 
5158 		// we have specific outgoing interfaces specified. Make sure the
5159 		// local endpoint for this socket is bound to one of the allowed
5160 		// interfaces. the list can be a mixture of interfaces and IP
5161 		// addresses.
5162 		for (auto const& s : m_outgoing_interfaces)
5163 		{
5164 			error_code err;
5165 			address const ip = make_address(s.c_str(), err);
5166 			if (err) continue;
5167 			if (ip == addr) return true;
5168 		}
5169 
5170 		// we didn't find the address as an IP in the interface list. Now,
5171 		// resolve which device (if any) has this IP address.
5172 		std::string const device = device_for_address(addr, m_io_service, ec);
5173 		if (ec) return false;
5174 
5175 		// if no device was found to have this address, we fail
5176 		if (device.empty()) return false;
5177 
5178 		return std::any_of(m_outgoing_interfaces.begin(), m_outgoing_interfaces.end()
5179 			, [&device](std::string const& s) { return s == device; });
5180 	}
5181 
has_lsd() const5182 	bool session_impl::has_lsd() const
5183 	{
5184 		return std::any_of(m_listen_sockets.begin(), m_listen_sockets.end()
5185 			, [](std::shared_ptr<listen_socket_t> const& s) { return bool(s->lsd); });
5186 	}
5187 
remove_torrent(const torrent_handle & h,remove_flags_t const options)5188 	void session_impl::remove_torrent(const torrent_handle& h
5189 		, remove_flags_t const options)
5190 	{
5191 		INVARIANT_CHECK;
5192 
5193 		std::shared_ptr<torrent> tptr = h.m_torrent.lock();
5194 		if (!tptr) return;
5195 
5196 		m_alerts.emplace_alert<torrent_removed_alert>(tptr->get_handle()
5197 			, tptr->info_hash());
5198 
5199 		remove_torrent_impl(tptr, options);
5200 
5201 		tptr->abort();
5202 	}
5203 
remove_torrent_impl(std::shared_ptr<torrent> tptr,remove_flags_t const options)5204 	void session_impl::remove_torrent_impl(std::shared_ptr<torrent> tptr
5205 		, remove_flags_t const options)
5206 	{
5207 #if TORRENT_ABI_VERSION == 1
5208 		// deprecated in 1.2
5209 		// remove from uuid list
5210 		if (!tptr->uuid().empty())
5211 		{
5212 			auto const j = m_uuids.find(tptr->uuid());
5213 			if (j != m_uuids.end()) m_uuids.erase(j);
5214 		}
5215 #endif
5216 
5217 		auto i = m_torrents.find(tptr->torrent_file().info_hash());
5218 
5219 #if TORRENT_ABI_VERSION == 1
5220 		// deprecated in 1.2
5221 		// this torrent might be filed under the URL-hash
5222 		if (i == m_torrents.end() && !tptr->url().empty())
5223 		{
5224 			i = m_torrents.find(hasher(tptr->url()).final());
5225 		}
5226 #endif
5227 
5228 		if (i == m_torrents.end()) return;
5229 
5230 		torrent& t = *i->second;
5231 		if (options)
5232 		{
5233 			if (!t.delete_files(options))
5234 			{
5235 				if (m_alerts.should_post<torrent_delete_failed_alert>())
5236 					m_alerts.emplace_alert<torrent_delete_failed_alert>(t.get_handle()
5237 						, error_code(), t.torrent_file().info_hash());
5238 			}
5239 		}
5240 
5241 		tptr->update_gauge();
5242 
5243 #if TORRENT_USE_ASSERTS
5244 		sha1_hash i_hash = t.torrent_file().info_hash();
5245 #endif
5246 #ifndef TORRENT_DISABLE_DHT
5247 		if (i == m_next_dht_torrent)
5248 			++m_next_dht_torrent;
5249 #endif
5250 		if (i == m_next_lsd_torrent)
5251 			++m_next_lsd_torrent;
5252 
5253 		m_torrents.erase(i);
5254 		tptr->removed();
5255 
5256 #if !defined TORRENT_DISABLE_ENCRYPTION
5257 		static char const req2[4] = {'r', 'e', 'q', '2'};
5258 		hasher h(req2);
5259 		h.update(tptr->info_hash());
5260 		m_obfuscated_torrents.erase(h.final());
5261 #endif
5262 
5263 #ifndef TORRENT_DISABLE_DHT
5264 		if (m_next_dht_torrent == m_torrents.end())
5265 			m_next_dht_torrent = m_torrents.begin();
5266 #endif
5267 		if (m_next_lsd_torrent == m_torrents.end())
5268 			m_next_lsd_torrent = m_torrents.begin();
5269 
5270 		// this torrent may open up a slot for a queued torrent
5271 		trigger_auto_manage();
5272 
5273 		TORRENT_ASSERT(m_torrents.find(i_hash) == m_torrents.end());
5274 	}
5275 
5276 #if TORRENT_ABI_VERSION == 1
5277 
update_ssl_listen()5278 	void session_impl::update_ssl_listen()
5279 	{
5280 		INVARIANT_CHECK;
5281 
5282 		// this function maps the previous functionality of just setting the ssl
5283 		// listen port in order to enable the ssl listen sockets, to the new
5284 		// mechanism where SSL sockets are specified in listen_interfaces.
5285 		std::vector<std::string> ignore;
5286 		auto current_ifaces = parse_listen_interfaces(
5287 			m_settings.get_str(settings_pack::listen_interfaces), ignore);
5288 		// these are the current interfaces we have, first remove all the SSL
5289 		// interfaces
5290 		current_ifaces.erase(std::remove_if(current_ifaces.begin(), current_ifaces.end()
5291 			, std::bind(&listen_interface_t::ssl, _1)), current_ifaces.end());
5292 
5293 		int const ssl_listen_port = m_settings.get_int(settings_pack::ssl_listen);
5294 
5295 		// setting a port of 0 means to disable listening on SSL, so just update
5296 		// the interface list with the new list, and we're done
5297 		if (ssl_listen_port == 0)
5298 		{
5299 			m_settings.set_str(settings_pack::listen_interfaces
5300 				, print_listen_interfaces(current_ifaces));
5301 			return;
5302 		}
5303 
5304 		std::vector<listen_interface_t> new_ifaces;
5305 		std::transform(current_ifaces.begin(), current_ifaces.end()
5306 			, std::back_inserter(new_ifaces), [](listen_interface_t in)
5307 			{ in.ssl = true; return in; });
5308 
5309 		current_ifaces.insert(current_ifaces.end(), new_ifaces.begin(), new_ifaces.end());
5310 
5311 		m_settings.set_str(settings_pack::listen_interfaces
5312 			, print_listen_interfaces(current_ifaces));
5313 	}
5314 #endif // TORRENT_ABI_VERSION
5315 
update_listen_interfaces()5316 	void session_impl::update_listen_interfaces()
5317 	{
5318 		INVARIANT_CHECK;
5319 
5320 		std::string const net_interfaces = m_settings.get_str(settings_pack::listen_interfaces);
5321 		std::vector<std::string> err;
5322 		m_listen_interfaces = parse_listen_interfaces(net_interfaces, err);
5323 
5324 		for (auto const& e : err)
5325 		{
5326 			m_alerts.emplace_alert<listen_failed_alert>(e, lt::address{}, 0
5327 				, operation_t::parse_address, errors::invalid_port, lt::socket_type_t::tcp);
5328 		}
5329 
5330 #ifndef TORRENT_DISABLE_LOGGING
5331 		if (should_log())
5332 		{
5333 			session_log("update listen interfaces: %s", net_interfaces.c_str());
5334 			session_log("parsed listen interfaces count: %d, ifaces: %s"
5335 				, int(m_listen_interfaces.size())
5336 				, print_listen_interfaces(m_listen_interfaces).c_str());
5337 		}
5338 #endif
5339 	}
5340 
update_privileged_ports()5341 	void session_impl::update_privileged_ports()
5342 	{
5343 		if (m_settings.get_bool(settings_pack::no_connect_privileged_ports))
5344 		{
5345 			m_port_filter.add_rule(0, 1024, port_filter::blocked);
5346 
5347 			// Close connections whose endpoint is filtered
5348 			// by the new ip-filter
5349 			for (auto const& t : m_torrents)
5350 				t.second->port_filter_updated();
5351 		}
5352 		else
5353 		{
5354 			m_port_filter.add_rule(0, 1024, 0);
5355 		}
5356 	}
5357 
update_auto_sequential()5358 	void session_impl::update_auto_sequential()
5359 	{
5360 		for (auto& i : m_torrents)
5361 			i.second->update_auto_sequential();
5362 	}
5363 
update_max_failcount()5364 	void session_impl::update_max_failcount()
5365 	{
5366 		for (auto& i : m_torrents)
5367 			i.second->update_max_failcount();
5368 	}
5369 
update_resolver_cache_timeout()5370 	void session_impl::update_resolver_cache_timeout()
5371 	{
5372 		int const timeout = m_settings.get_int(settings_pack::resolver_cache_timeout);
5373 		m_host_resolver.set_cache_timeout(seconds(timeout));
5374 	}
5375 
update_proxy()5376 	void session_impl::update_proxy()
5377 	{
5378 		for (auto& i : m_listen_sockets)
5379 			i->udp_sock->sock.set_proxy_settings(proxy(), m_alerts);
5380 	}
5381 
update_ip_notifier()5382 	void session_impl::update_ip_notifier()
5383 	{
5384 		if (m_settings.get_bool(settings_pack::enable_ip_notifier))
5385 			start_ip_notifier();
5386 		else
5387 			stop_ip_notifier();
5388 	}
5389 
update_upnp()5390 	void session_impl::update_upnp()
5391 	{
5392 		if (m_settings.get_bool(settings_pack::enable_upnp))
5393 			start_upnp();
5394 		else
5395 			stop_upnp();
5396 	}
5397 
update_natpmp()5398 	void session_impl::update_natpmp()
5399 	{
5400 		if (m_settings.get_bool(settings_pack::enable_natpmp))
5401 			start_natpmp();
5402 		else
5403 			stop_natpmp();
5404 	}
5405 
update_lsd()5406 	void session_impl::update_lsd()
5407 	{
5408 		if (m_settings.get_bool(settings_pack::enable_lsd))
5409 			start_lsd();
5410 		else
5411 			stop_lsd();
5412 	}
5413 
update_dht()5414 	void session_impl::update_dht()
5415 	{
5416 #ifndef TORRENT_DISABLE_DHT
5417 		if (m_settings.get_bool(settings_pack::enable_dht))
5418 		{
5419 			if (!m_settings.get_str(settings_pack::dht_bootstrap_nodes).empty()
5420 				&& m_dht_router_nodes.empty())
5421 			{
5422 				// if we have bootstrap nodes configured, make sure we initiate host
5423 				// name lookups. once these complete, the DHT will be started.
5424 				// they are tracked by m_outstanding_router_lookups
5425 				update_dht_bootstrap_nodes();
5426 			}
5427 			else
5428 			{
5429 				start_dht();
5430 			}
5431 		}
5432 		else
5433 			stop_dht();
5434 #endif
5435 	}
5436 
update_dht_bootstrap_nodes()5437 	void session_impl::update_dht_bootstrap_nodes()
5438 	{
5439 #ifndef TORRENT_DISABLE_DHT
5440 		if (!m_settings.get_bool(settings_pack::enable_dht)) return;
5441 
5442 		std::string const& node_list = m_settings.get_str(settings_pack::dht_bootstrap_nodes);
5443 		std::vector<std::pair<std::string, int>> nodes;
5444 		parse_comma_separated_string_port(node_list, nodes);
5445 
5446 #ifndef TORRENT_DISABLE_LOGGING
5447 		if (!node_list.empty() && nodes.empty())
5448 		{
5449 			session_log("ERROR: failed to parse DHT bootstrap list: %s", node_list.c_str());
5450 		}
5451 #endif
5452 		for (auto const& n : nodes)
5453 			add_dht_router(n);
5454 #endif
5455 	}
5456 
update_dht_settings()5457 	void session_impl::update_dht_settings()
5458 	{
5459 #ifndef TORRENT_DISABLE_DHT
5460 		bool const prefer_verified_nodes = m_settings.get_bool(
5461 			settings_pack::dht_prefer_verified_node_ids);
5462 
5463 		m_dht_settings.prefer_verified_node_ids = prefer_verified_nodes;
5464 #endif
5465 	}
5466 
update_count_slow()5467 	void session_impl::update_count_slow()
5468 	{
5469 		error_code ec;
5470 		for (auto const& tp : m_torrents)
5471 		{
5472 			tp.second->on_inactivity_tick(ec);
5473 		}
5474 	}
5475 
5476 	// TODO: 2 this function should be removed and users need to deal with the
5477 	// more generic case of having multiple listen ports
listen_port() const5478 	std::uint16_t session_impl::listen_port() const
5479 	{
5480 		return listen_port(nullptr);
5481 	}
5482 
listen_port(listen_socket_t * sock) const5483 	std::uint16_t session_impl::listen_port(listen_socket_t* sock) const
5484 	{
5485 		if (m_listen_sockets.empty()) return 0;
5486 		if (sock)
5487 		{
5488 			// if we're using a proxy, we won't be able to accept any TCP
5489 			// connections. Not even uTP connections via the port we know about.
5490 			// The DHT may use the implied port to make it work, but the port we
5491 			// announce here has no relevance for that.
5492 			if (sock->flags & listen_socket_t::proxy)
5493 				return 0;
5494 
5495 			if (!(sock->flags & listen_socket_t::accept_incoming))
5496 				return 0;
5497 
5498 			return std::uint16_t(sock->tcp_external_port());
5499 		}
5500 
5501 #ifdef TORRENT_USE_OPENSSL
5502 		for (auto const& s : m_listen_sockets)
5503 		{
5504 			if (!(s->flags & listen_socket_t::accept_incoming)) continue;
5505 			if (s->ssl == transport::plaintext)
5506 				return std::uint16_t(s->tcp_external_port());
5507 		}
5508 		return 0;
5509 #else
5510 		sock = m_listen_sockets.front().get();
5511 		if (!(sock->flags & listen_socket_t::accept_incoming)) return 0;
5512 		return std::uint16_t(sock->tcp_external_port());
5513 #endif
5514 	}
5515 
5516 	// TODO: 2 this function should be removed and users need to deal with the
5517 	// more generic case of having multiple ssl ports
ssl_listen_port() const5518 	std::uint16_t session_impl::ssl_listen_port() const
5519 	{
5520 		return ssl_listen_port(nullptr);
5521 	}
5522 
ssl_listen_port(listen_socket_t * sock) const5523 	std::uint16_t session_impl::ssl_listen_port(listen_socket_t* sock) const
5524 	{
5525 #ifdef TORRENT_USE_OPENSSL
5526 		if (sock)
5527 		{
5528 			if (!(sock->flags & listen_socket_t::accept_incoming)) return 0;
5529 			return std::uint16_t(sock->tcp_external_port());
5530 		}
5531 
5532 		if (m_settings.get_int(settings_pack::proxy_type) != settings_pack::none
5533 			&& m_settings.get_bool(settings_pack::proxy_peer_connections))
5534 			return 0;
5535 
5536 		for (auto const& s : m_listen_sockets)
5537 		{
5538 			if (!(s->flags & listen_socket_t::accept_incoming)) continue;
5539 			if (s->ssl == transport::ssl)
5540 				return std::uint16_t(s->tcp_external_port());
5541 		}
5542 #else
5543 		TORRENT_UNUSED(sock);
5544 #endif
5545 		return 0;
5546 	}
5547 
get_listen_port(transport const ssl,aux::listen_socket_handle const & s)5548 	int session_impl::get_listen_port(transport const ssl, aux::listen_socket_handle const& s)
5549 	{
5550 		auto socket = s.get();
5551 		if (socket->ssl != ssl)
5552 		{
5553 			auto alt_socket = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
5554 				, [&](std::shared_ptr<listen_socket_t> const& e)
5555 			{
5556 				return e->ssl == ssl
5557 					&& e->external_address.external_address()
5558 						== socket->external_address.external_address();
5559 			});
5560 			if (alt_socket != m_listen_sockets.end())
5561 				socket = alt_socket->get();
5562 		}
5563 		return socket->udp_external_port();
5564 	}
5565 
listen_port(transport const ssl,address const & local_addr)5566 	int session_impl::listen_port(transport const ssl, address const& local_addr)
5567 	{
5568 		auto socket = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
5569 			, [&](std::shared_ptr<listen_socket_t> const& e)
5570 		{
5571 			if (!(e->flags & listen_socket_t::accept_incoming)) return false;
5572 			auto const& listen_addr = e->external_address.external_address();
5573 			return e->ssl == ssl
5574 				&& (listen_addr == local_addr
5575 					|| (listen_addr.is_v4() == local_addr.is_v4() && listen_addr.is_unspecified()));
5576 		});
5577 		if (socket != m_listen_sockets.end())
5578 			return (*socket)->tcp_external_port();
5579 		return 0;
5580 	}
5581 
announce_lsd(sha1_hash const & ih,int port)5582 	void session_impl::announce_lsd(sha1_hash const& ih, int port)
5583 	{
5584 		// use internal listen port for local peers
5585 		for (auto const& s : m_listen_sockets)
5586 		{
5587 			if (s->lsd) s->lsd->announce(ih, port);
5588 		}
5589 	}
5590 
on_lsd_peer(tcp::endpoint const & peer,sha1_hash const & ih)5591 	void session_impl::on_lsd_peer(tcp::endpoint const& peer, sha1_hash const& ih)
5592 	{
5593 		m_stats_counters.inc_stats_counter(counters::on_lsd_peer_counter);
5594 		TORRENT_ASSERT(is_single_thread());
5595 
5596 		INVARIANT_CHECK;
5597 
5598 		std::shared_ptr<torrent> t = find_torrent(ih).lock();
5599 		if (!t) return;
5600 		// don't add peers from lsd to private torrents
5601 		if (t->torrent_file().priv() || (t->torrent_file().is_i2p()
5602 			&& !m_settings.get_bool(settings_pack::allow_i2p_mixed))) return;
5603 
5604 		t->add_peer(peer, peer_info::lsd);
5605 #ifndef TORRENT_DISABLE_LOGGING
5606 		if (should_log())
5607 		{
5608 			error_code ec;
5609 			t->debug_log("lsd add_peer() [ %s ]"
5610 				, peer.address().to_string(ec).c_str());
5611 		}
5612 #endif
5613 
5614 		t->do_connect_boost();
5615 
5616 		if (m_alerts.should_post<lsd_peer_alert>())
5617 			m_alerts.emplace_alert<lsd_peer_alert>(t->get_handle(), peer);
5618 	}
5619 
start_natpmp(aux::listen_socket_t & s)5620 	void session_impl::start_natpmp(aux::listen_socket_t& s)
5621 	{
5622 		// don't create mappings for local IPv6 addresses
5623 		// they can't be reached from outside of the local network anyways
5624 		if (is_v6(s.local_endpoint) && is_local(s.local_endpoint.address()))
5625 			return;
5626 
5627 		if (!s.natpmp_mapper
5628 			&& !(s.flags & listen_socket_t::local_network)
5629 			&& !(s.flags & listen_socket_t::proxy))
5630 		{
5631 			// the natpmp constructor may fail and call the callbacks
5632 			// into the session_impl.
5633 			s.natpmp_mapper = std::make_shared<natpmp>(m_io_service, *this);
5634 			ip_interface ip;
5635 			ip.interface_address = s.local_endpoint.address();
5636 			ip.netmask = s.netmask;
5637 			std::strncpy(ip.name, s.device.c_str(), sizeof(ip.name) - 1);
5638 			ip.name[sizeof(ip.name) - 1] = '\0';
5639 			s.natpmp_mapper->start(ip);
5640 		}
5641 	}
5642 
5643 	namespace {
find_tcp_port_mapping(portmap_transport const transport,port_mapping_t mapping,std::shared_ptr<listen_socket_t> const & ls)5644 		bool find_tcp_port_mapping(portmap_transport const transport
5645 			, port_mapping_t mapping, std::shared_ptr<listen_socket_t> const& ls)
5646 		{
5647 			return ls->tcp_port_mapping[transport].mapping == mapping;
5648 		}
5649 
find_udp_port_mapping(portmap_transport const transport,port_mapping_t mapping,std::shared_ptr<listen_socket_t> const & ls)5650 		bool find_udp_port_mapping(portmap_transport const transport
5651 			, port_mapping_t mapping, std::shared_ptr<listen_socket_t> const& ls)
5652 		{
5653 			return ls->udp_port_mapping[transport].mapping == mapping;
5654 		}
5655 	}
5656 
on_port_mapping(port_mapping_t const mapping,address const & ip,int port,portmap_protocol const proto,error_code const & ec,portmap_transport const transport)5657 	void session_impl::on_port_mapping(port_mapping_t const mapping
5658 		, address const& ip, int port
5659 		, portmap_protocol const proto, error_code const& ec
5660 		, portmap_transport const transport)
5661 	{
5662 		TORRENT_ASSERT(is_single_thread());
5663 
5664 		// NOTE: don't assume that if ec != 0, the rest of the logic
5665 		// is not necessary, the ports still need to be set, in other
5666 		// words, don't early return without careful review of the
5667 		// remaining logic
5668 		if (ec && m_alerts.should_post<portmap_error_alert>())
5669 		{
5670 			m_alerts.emplace_alert<portmap_error_alert>(mapping
5671 				, transport, ec);
5672 		}
5673 
5674 		// look through our listen sockets to see if this mapping is for one of
5675 		// them (it could also be a user mapping)
5676 
5677 		auto ls
5678 			= std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
5679 			, std::bind(find_tcp_port_mapping, transport, mapping, _1));
5680 
5681 		bool tcp = true;
5682 		if (ls == m_listen_sockets.end())
5683 		{
5684 			ls = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
5685 				, std::bind(find_udp_port_mapping, transport, mapping, _1));
5686 			tcp = false;
5687 		}
5688 
5689 		if (ls != m_listen_sockets.end())
5690 		{
5691 			if (!ec && ip != address())
5692 			{
5693 				// TODO: 1 report the proper address of the router as the source IP of
5694 				// this vote of our external address, instead of the empty address
5695 				(*ls)->external_address.cast_vote(ip, source_router, address());
5696 			}
5697 
5698 			if (tcp) (*ls)->tcp_port_mapping[transport].port = port;
5699 			else (*ls)->udp_port_mapping[transport].port = port;
5700 		}
5701 
5702 		if (!ec && m_alerts.should_post<portmap_alert>())
5703 		{
5704 			m_alerts.emplace_alert<portmap_alert>(mapping, port
5705 				, transport, proto);
5706 		}
5707 	}
5708 
5709 #if TORRENT_ABI_VERSION == 1
status() const5710 	session_status session_impl::status() const
5711 	{
5712 //		INVARIANT_CHECK;
5713 		TORRENT_ASSERT(is_single_thread());
5714 
5715 		session_status s;
5716 
5717 		s.optimistic_unchoke_counter = m_optimistic_unchoke_time_scaler;
5718 		s.unchoke_counter = m_unchoke_time_scaler;
5719 		s.num_dead_peers = int(m_undead_peers.size());
5720 
5721 		s.num_peers = int(m_stats_counters[counters::num_peers_connected]);
5722 		s.num_unchoked = int(m_stats_counters[counters::num_peers_up_unchoked_all]);
5723 		s.allowed_upload_slots = int(m_stats_counters[counters::num_unchoke_slots]);
5724 
5725 		s.num_torrents
5726 			= int(m_stats_counters[counters::num_checking_torrents]
5727 			+ m_stats_counters[counters::num_stopped_torrents]
5728 			+ m_stats_counters[counters::num_queued_seeding_torrents]
5729 			+ m_stats_counters[counters::num_queued_download_torrents]
5730 			+ m_stats_counters[counters::num_upload_only_torrents]
5731 			+ m_stats_counters[counters::num_downloading_torrents]
5732 			+ m_stats_counters[counters::num_seeding_torrents]
5733 			+ m_stats_counters[counters::num_error_torrents]);
5734 
5735 		s.num_paused_torrents
5736 			= int(m_stats_counters[counters::num_stopped_torrents]
5737 			+ m_stats_counters[counters::num_error_torrents]
5738 			+ m_stats_counters[counters::num_queued_seeding_torrents]
5739 			+ m_stats_counters[counters::num_queued_download_torrents]);
5740 
5741 		s.total_redundant_bytes = m_stats_counters[counters::recv_redundant_bytes];
5742 		s.total_failed_bytes = m_stats_counters[counters::recv_failed_bytes];
5743 
5744 		s.up_bandwidth_queue = int(m_stats_counters[counters::limiter_up_queue]);
5745 		s.down_bandwidth_queue = int(m_stats_counters[counters::limiter_down_queue]);
5746 
5747 		s.up_bandwidth_bytes_queue = int(m_stats_counters[counters::limiter_up_bytes]);
5748 		s.down_bandwidth_bytes_queue = int(m_stats_counters[counters::limiter_down_bytes]);
5749 
5750 		s.disk_write_queue = int(m_stats_counters[counters::num_peers_down_disk]);
5751 		s.disk_read_queue = int(m_stats_counters[counters::num_peers_up_disk]);
5752 
5753 		s.has_incoming_connections = m_stats_counters[counters::has_incoming_connections] != 0;
5754 
5755 		// total
5756 		s.download_rate = m_stat.download_rate();
5757 		s.total_upload = m_stat.total_upload();
5758 		s.upload_rate = m_stat.upload_rate();
5759 		s.total_download = m_stat.total_download();
5760 
5761 		// payload
5762 		s.payload_download_rate = m_stat.transfer_rate(stat::download_payload);
5763 		s.total_payload_download = m_stat.total_transfer(stat::download_payload);
5764 		s.payload_upload_rate = m_stat.transfer_rate(stat::upload_payload);
5765 		s.total_payload_upload = m_stat.total_transfer(stat::upload_payload);
5766 
5767 		// IP-overhead
5768 		s.ip_overhead_download_rate = m_stat.transfer_rate(stat::download_ip_protocol);
5769 		s.total_ip_overhead_download = m_stats_counters[counters::recv_ip_overhead_bytes];
5770 		s.ip_overhead_upload_rate = m_stat.transfer_rate(stat::upload_ip_protocol);
5771 		s.total_ip_overhead_upload = m_stats_counters[counters::sent_ip_overhead_bytes];
5772 
5773 		// tracker
5774 		s.total_tracker_download = m_stats_counters[counters::recv_tracker_bytes];
5775 		s.total_tracker_upload = m_stats_counters[counters::sent_tracker_bytes];
5776 
5777 		// dht
5778 		s.total_dht_download = m_stats_counters[counters::dht_bytes_in];
5779 		s.total_dht_upload = m_stats_counters[counters::dht_bytes_out];
5780 
5781 		// deprecated
5782 		s.tracker_download_rate = 0;
5783 		s.tracker_upload_rate = 0;
5784 		s.dht_download_rate = 0;
5785 		s.dht_upload_rate = 0;
5786 
5787 #ifndef TORRENT_DISABLE_DHT
5788 		if (m_dht)
5789 		{
5790 			m_dht->dht_status(s);
5791 		}
5792 		else
5793 #endif
5794 		{
5795 			s.dht_nodes = 0;
5796 			s.dht_node_cache = 0;
5797 			s.dht_torrents = 0;
5798 			s.dht_global_nodes = 0;
5799 			s.dht_total_allocations = 0;
5800 		}
5801 
5802 		s.utp_stats.packet_loss = std::uint64_t(m_stats_counters[counters::utp_packet_loss]);
5803 		s.utp_stats.timeout = std::uint64_t(m_stats_counters[counters::utp_timeout]);
5804 		s.utp_stats.packets_in = std::uint64_t(m_stats_counters[counters::utp_packets_in]);
5805 		s.utp_stats.packets_out = std::uint64_t(m_stats_counters[counters::utp_packets_out]);
5806 		s.utp_stats.fast_retransmit = std::uint64_t(m_stats_counters[counters::utp_fast_retransmit]);
5807 		s.utp_stats.packet_resend = std::uint64_t(m_stats_counters[counters::utp_packet_resend]);
5808 		s.utp_stats.samples_above_target = std::uint64_t(m_stats_counters[counters::utp_samples_above_target]);
5809 		s.utp_stats.samples_below_target = std::uint64_t(m_stats_counters[counters::utp_samples_below_target]);
5810 		s.utp_stats.payload_pkts_in = std::uint64_t(m_stats_counters[counters::utp_payload_pkts_in]);
5811 		s.utp_stats.payload_pkts_out = std::uint64_t(m_stats_counters[counters::utp_payload_pkts_out]);
5812 		s.utp_stats.invalid_pkts_in = std::uint64_t(m_stats_counters[counters::utp_invalid_pkts_in]);
5813 		s.utp_stats.redundant_pkts_in = std::uint64_t(m_stats_counters[counters::utp_redundant_pkts_in]);
5814 
5815 		s.utp_stats.num_idle = int(m_stats_counters[counters::num_utp_idle]);
5816 		s.utp_stats.num_syn_sent = int(m_stats_counters[counters::num_utp_syn_sent]);
5817 		s.utp_stats.num_connected = int(m_stats_counters[counters::num_utp_connected]);
5818 		s.utp_stats.num_fin_sent = int(m_stats_counters[counters::num_utp_fin_sent]);
5819 		s.utp_stats.num_close_wait = int(m_stats_counters[counters::num_utp_close_wait]);
5820 
5821 		// this loop is potentially expensive. It could be optimized by
5822 		// simply keeping a global counter
5823 		s.peerlist_size = std::accumulate(m_torrents.begin(), m_torrents.end(), 0
5824 			, [](int const acc, std::pair<sha1_hash, std::shared_ptr<torrent>> const& t)
5825 			{ return acc + t.second->num_known_peers(); });
5826 
5827 		return s;
5828 	}
5829 #endif // TORRENT_ABI_VERSION
5830 
get_cache_info(torrent_handle h,cache_status * ret,int flags) const5831 	void session_impl::get_cache_info(torrent_handle h, cache_status* ret, int flags) const
5832 	{
5833 		storage_index_t st{0};
5834 		bool whole_session = true;
5835 		std::shared_ptr<torrent> t = h.m_torrent.lock();
5836 		if (t)
5837 		{
5838 			if (t->has_storage())
5839 			{
5840 				st = t->storage();
5841 				whole_session = false;
5842 			}
5843 			else
5844 				flags = session::disk_cache_no_pieces;
5845 		}
5846 		m_disk_thread.get_cache_info(ret, st
5847 			, flags & session::disk_cache_no_pieces, whole_session);
5848 	}
5849 
5850 #ifndef TORRENT_DISABLE_DHT
5851 
start_dht()5852 	void session_impl::start_dht()
5853 	{
5854 		INVARIANT_CHECK;
5855 
5856 		stop_dht();
5857 
5858 		if (!m_settings.get_bool(settings_pack::enable_dht)) return;
5859 
5860 		// postpone starting the DHT if we're still resolving the DHT router
5861 		if (m_outstanding_router_lookups > 0)
5862 		{
5863 #ifndef TORRENT_DISABLE_LOGGING
5864 			session_log("not starting DHT, outstanding router lookups: %d"
5865 				, m_outstanding_router_lookups);
5866 #endif
5867 			return;
5868 		}
5869 
5870 		if (m_abort)
5871 		{
5872 #ifndef TORRENT_DISABLE_LOGGING
5873 			session_log("not starting DHT, aborting");
5874 #endif
5875 			return;
5876 		}
5877 
5878 #ifndef TORRENT_DISABLE_LOGGING
5879 		session_log("starting DHT, running: %s, router lookups: %d"
5880 			, m_dht ? "true" : "false", m_outstanding_router_lookups);
5881 #endif
5882 
5883 		// TODO: refactor, move the storage to dht_tracker
5884 		m_dht_storage = m_dht_storage_constructor(m_dht_settings);
5885 		m_dht = std::make_shared<dht::dht_tracker>(
5886 			static_cast<dht::dht_observer*>(this)
5887 			, m_io_service
5888 			, [=](aux::listen_socket_handle const& sock
5889 				, udp::endpoint const& ep
5890 				, span<char const> p
5891 				, error_code& ec
5892 				, udp_send_flags_t const flags)
5893 				{ send_udp_packet_listen(sock, ep, p, ec, flags); }
5894 			, m_dht_settings
5895 			, m_stats_counters
5896 			, *m_dht_storage
5897 			, std::move(m_dht_state));
5898 
5899 		for (auto& s : m_listen_sockets)
5900 		{
5901 			if (s->ssl != transport::ssl
5902 				&& !(s->flags & listen_socket_t::local_network))
5903 			{
5904 				m_dht->new_socket(s);
5905 			}
5906 		}
5907 
5908 		for (auto const& n : m_dht_router_nodes)
5909 		{
5910 			m_dht->add_router_node(n);
5911 		}
5912 
5913 		for (auto const& n : m_dht_nodes)
5914 		{
5915 			m_dht->add_node(n);
5916 		}
5917 		m_dht_nodes.clear();
5918 		m_dht_nodes.shrink_to_fit();
5919 
5920 		auto cb = [this](
5921 			std::vector<std::pair<dht::node_entry, std::string>> const&)
5922 		{
5923 			if (m_alerts.should_post<dht_bootstrap_alert>())
5924 				m_alerts.emplace_alert<dht_bootstrap_alert>();
5925 		};
5926 
5927 		m_dht->start(cb);
5928 	}
5929 
stop_dht()5930 	void session_impl::stop_dht()
5931 	{
5932 #ifndef TORRENT_DISABLE_LOGGING
5933 		session_log("about to stop DHT, running: %s", m_dht ? "true" : "false");
5934 #endif
5935 
5936 		if (m_dht)
5937 		{
5938 			m_dht->stop();
5939 			m_dht.reset();
5940 		}
5941 
5942 		m_dht_storage.reset();
5943 	}
5944 
set_dht_settings(dht::dht_settings const & settings)5945 	void session_impl::set_dht_settings(dht::dht_settings const& settings)
5946 	{
5947 		static_cast<dht::dht_settings&>(m_dht_settings) = settings;
5948 		if (m_dht_settings.upload_rate_limit > std::numeric_limits<int>::max() / 3)
5949 			m_dht_settings.upload_rate_limit = std::numeric_limits<int>::max() / 3;
5950 		m_settings.set_int(settings_pack::dht_upload_rate_limit, m_dht_settings.upload_rate_limit);
5951 	}
5952 
set_dht_state(dht::dht_state && state)5953 	void session_impl::set_dht_state(dht::dht_state&& state)
5954 	{
5955 		m_dht_state = std::move(state);
5956 	}
5957 
set_dht_storage(dht::dht_storage_constructor_type sc)5958 	void session_impl::set_dht_storage(dht::dht_storage_constructor_type sc)
5959 	{
5960 		m_dht_storage_constructor = std::move(sc);
5961 	}
5962 
5963 #if TORRENT_ABI_VERSION == 1
dht_state() const5964 	entry session_impl::dht_state() const
5965 	{
5966 		return m_dht ? dht::save_dht_state(m_dht->state()) : entry();
5967 	}
5968 
start_dht_deprecated(entry const & startup_state)5969 	void session_impl::start_dht_deprecated(entry const& startup_state)
5970 	{
5971 		m_settings.set_bool(settings_pack::enable_dht, true);
5972 		std::vector<char> tmp;
5973 		bencode(std::back_inserter(tmp), startup_state);
5974 
5975 		bdecode_node e;
5976 		error_code ec;
5977 		if (tmp.empty() || bdecode(&tmp[0], &tmp[0] + tmp.size(), e, ec) != 0)
5978 			return;
5979 		m_dht_state = dht::read_dht_state(e);
5980 		start_dht();
5981 	}
5982 #endif
5983 
add_dht_node_name(std::pair<std::string,int> const & node)5984 	void session_impl::add_dht_node_name(std::pair<std::string, int> const& node)
5985 	{
5986 		ADD_OUTSTANDING_ASYNC("session_impl::on_dht_name_lookup");
5987 		m_host_resolver.async_resolve(node.first, resolver::abort_on_shutdown
5988 			, std::bind(&session_impl::on_dht_name_lookup
5989 				, this, _1, _2, node.second));
5990 	}
5991 
on_dht_name_lookup(error_code const & e,std::vector<address> const & addresses,int port)5992 	void session_impl::on_dht_name_lookup(error_code const& e
5993 		, std::vector<address> const& addresses, int port)
5994 	{
5995 		COMPLETE_ASYNC("session_impl::on_dht_name_lookup");
5996 
5997 		if (e)
5998 		{
5999 			if (m_alerts.should_post<dht_error_alert>())
6000 				m_alerts.emplace_alert<dht_error_alert>(
6001 					operation_t::hostname_lookup, e);
6002 			return;
6003 		}
6004 
6005 		for (auto const& addr : addresses)
6006 		{
6007 			udp::endpoint ep(addr, std::uint16_t(port));
6008 			add_dht_node(ep);
6009 		}
6010 	}
6011 
add_dht_router(std::pair<std::string,int> const & node)6012 	void session_impl::add_dht_router(std::pair<std::string, int> const& node)
6013 	{
6014 		ADD_OUTSTANDING_ASYNC("session_impl::on_dht_router_name_lookup");
6015 		++m_outstanding_router_lookups;
6016 		m_host_resolver.async_resolve(node.first, resolver::abort_on_shutdown
6017 			, std::bind(&session_impl::on_dht_router_name_lookup
6018 				, this, _1, _2, node.second));
6019 	}
6020 
on_dht_router_name_lookup(error_code const & e,std::vector<address> const & addresses,int port)6021 	void session_impl::on_dht_router_name_lookup(error_code const& e
6022 		, std::vector<address> const& addresses, int port)
6023 	{
6024 		COMPLETE_ASYNC("session_impl::on_dht_router_name_lookup");
6025 		--m_outstanding_router_lookups;
6026 
6027 		if (e)
6028 		{
6029 			if (m_alerts.should_post<dht_error_alert>())
6030 				m_alerts.emplace_alert<dht_error_alert>(
6031 					operation_t::hostname_lookup, e);
6032 
6033 			if (m_outstanding_router_lookups == 0) start_dht();
6034 			return;
6035 		}
6036 
6037 
6038 		for (auto const& addr : addresses)
6039 		{
6040 			// router nodes should be added before the DHT is started (and bootstrapped)
6041 			udp::endpoint ep(addr, std::uint16_t(port));
6042 			if (m_dht) m_dht->add_router_node(ep);
6043 			m_dht_router_nodes.push_back(ep);
6044 		}
6045 
6046 		if (m_outstanding_router_lookups == 0) start_dht();
6047 	}
6048 
6049 	// callback for dht_immutable_get
get_immutable_callback(sha1_hash target,dht::item const & i)6050 	void session_impl::get_immutable_callback(sha1_hash target
6051 		, dht::item const& i)
6052 	{
6053 		TORRENT_ASSERT(!i.is_mutable());
6054 		m_alerts.emplace_alert<dht_immutable_item_alert>(target, i.value());
6055 	}
6056 
dht_get_immutable_item(sha1_hash const & target)6057 	void session_impl::dht_get_immutable_item(sha1_hash const& target)
6058 	{
6059 		if (!m_dht) return;
6060 		m_dht->get_item(target, std::bind(&session_impl::get_immutable_callback
6061 			, this, target, _1));
6062 	}
6063 
6064 	// callback for dht_mutable_get
get_mutable_callback(dht::item const & i,bool const authoritative)6065 	void session_impl::get_mutable_callback(dht::item const& i
6066 		, bool const authoritative)
6067 	{
6068 		TORRENT_ASSERT(i.is_mutable());
6069 		m_alerts.emplace_alert<dht_mutable_item_alert>(i.pk().bytes
6070 			, i.sig().bytes, i.seq().value
6071 			, i.salt(), i.value(), authoritative);
6072 	}
6073 
6074 	// key is a 32-byte binary string, the public key to look up.
6075 	// the salt is optional
6076 	// TODO: 3 use public_key here instead of std::array
dht_get_mutable_item(std::array<char,32> key,std::string salt)6077 	void session_impl::dht_get_mutable_item(std::array<char, 32> key
6078 		, std::string salt)
6079 	{
6080 		if (!m_dht) return;
6081 		m_dht->get_item(dht::public_key(key.data()), std::bind(&session_impl::get_mutable_callback
6082 			, this, _1, _2), std::move(salt));
6083 	}
6084 
6085 	namespace {
6086 
on_dht_put_immutable_item(alert_manager & alerts,sha1_hash target,int num)6087 		void on_dht_put_immutable_item(alert_manager& alerts, sha1_hash target, int num)
6088 		{
6089 			if (alerts.should_post<dht_put_alert>())
6090 				alerts.emplace_alert<dht_put_alert>(target, num);
6091 		}
6092 
on_dht_put_mutable_item(alert_manager & alerts,dht::item const & i,int num)6093 		void on_dht_put_mutable_item(alert_manager& alerts, dht::item const& i, int num)
6094 		{
6095 			if (alerts.should_post<dht_put_alert>())
6096 			{
6097 				dht::signature const sig = i.sig();
6098 				dht::public_key const pk = i.pk();
6099 				dht::sequence_number const seq = i.seq();
6100 				std::string salt = i.salt();
6101 				alerts.emplace_alert<dht_put_alert>(pk.bytes, sig.bytes
6102 					, std::move(salt), seq.value, num);
6103 			}
6104 		}
6105 
put_mutable_callback(dht::item & i,std::function<void (entry &,std::array<char,64> &,std::int64_t &,std::string const &)> cb)6106 		void put_mutable_callback(dht::item& i
6107 			, std::function<void(entry&, std::array<char, 64>&
6108 				, std::int64_t&, std::string const&)> cb)
6109 		{
6110 			entry value = i.value();
6111 			dht::signature sig = i.sig();
6112 			dht::public_key pk = i.pk();
6113 			dht::sequence_number seq = i.seq();
6114 			std::string salt = i.salt();
6115 			cb(value, sig.bytes, seq.value, salt);
6116 			i.assign(std::move(value), salt, seq, pk, sig);
6117 		}
6118 
on_dht_get_peers(alert_manager & alerts,sha1_hash info_hash,std::vector<tcp::endpoint> const & peers)6119 		void on_dht_get_peers(alert_manager& alerts, sha1_hash info_hash, std::vector<tcp::endpoint> const& peers)
6120 		{
6121 			if (alerts.should_post<dht_get_peers_reply_alert>())
6122 				alerts.emplace_alert<dht_get_peers_reply_alert>(info_hash, peers);
6123 		}
6124 
on_direct_response(alert_manager & alerts,void * userdata,dht::msg const & msg)6125 		void on_direct_response(alert_manager& alerts, void* userdata, dht::msg const& msg)
6126 		{
6127 			if (msg.message.type() == bdecode_node::none_t)
6128 				alerts.emplace_alert<dht_direct_response_alert>(userdata, msg.addr);
6129 			else
6130 				alerts.emplace_alert<dht_direct_response_alert>(userdata, msg.addr, msg.message);
6131 		}
6132 
6133 	} // anonymous namespace
6134 
dht_put_immutable_item(entry const & data,sha1_hash target)6135 	void session_impl::dht_put_immutable_item(entry const& data, sha1_hash target)
6136 	{
6137 		if (!m_dht) return;
6138 		m_dht->put_item(data, std::bind(&on_dht_put_immutable_item, std::ref(m_alerts)
6139 			, target, _1));
6140 	}
6141 
dht_put_mutable_item(std::array<char,32> key,std::function<void (entry &,std::array<char,64> &,std::int64_t &,std::string const &)> cb,std::string salt)6142 	void session_impl::dht_put_mutable_item(std::array<char, 32> key
6143 		, std::function<void(entry&, std::array<char,64>&
6144 		, std::int64_t&, std::string const&)> cb
6145 		, std::string salt)
6146 	{
6147 		if (!m_dht) return;
6148 		m_dht->put_item(dht::public_key(key.data())
6149 			, std::bind(&on_dht_put_mutable_item, std::ref(m_alerts), _1, _2)
6150 			, std::bind(&put_mutable_callback, _1, std::move(cb)), salt);
6151 	}
6152 
dht_get_peers(sha1_hash const & info_hash)6153 	void session_impl::dht_get_peers(sha1_hash const& info_hash)
6154 	{
6155 		if (!m_dht) return;
6156 		m_dht->get_peers(info_hash, std::bind(&on_dht_get_peers, std::ref(m_alerts), info_hash, _1));
6157 	}
6158 
dht_announce(sha1_hash const & info_hash,int port,dht::announce_flags_t const flags)6159 	void session_impl::dht_announce(sha1_hash const& info_hash, int port, dht::announce_flags_t const flags)
6160 	{
6161 		if (!m_dht) return;
6162 		m_dht->announce(info_hash, port, flags, std::bind(&on_dht_get_peers, std::ref(m_alerts), info_hash, _1));
6163 	}
6164 
dht_live_nodes(sha1_hash const & nid)6165 	void session_impl::dht_live_nodes(sha1_hash const& nid)
6166 	{
6167 		if (!m_dht) return;
6168 		auto nodes = m_dht->live_nodes(nid);
6169 		m_alerts.emplace_alert<dht_live_nodes_alert>(nid, nodes);
6170 	}
6171 
dht_sample_infohashes(udp::endpoint const & ep,sha1_hash const & target)6172 	void session_impl::dht_sample_infohashes(udp::endpoint const& ep, sha1_hash const& target)
6173 	{
6174 		if (!m_dht) return;
6175 		m_dht->sample_infohashes(ep, target, [this, ep](time_duration const interval
6176 			, int const num, std::vector<sha1_hash> samples
6177 			, std::vector<std::pair<sha1_hash, udp::endpoint>> nodes)
6178 		{
6179 			m_alerts.emplace_alert<dht_sample_infohashes_alert>(ep
6180 				, interval, num, std::move(samples), std::move(nodes));
6181 		});
6182 	}
6183 
dht_direct_request(udp::endpoint const & ep,entry & e,void * userdata)6184 	void session_impl::dht_direct_request(udp::endpoint const& ep, entry& e, void* userdata)
6185 	{
6186 		if (!m_dht) return;
6187 		m_dht->direct_request(ep, e, std::bind(&on_direct_response, std::ref(m_alerts), userdata, _1));
6188 	}
6189 
6190 #endif
6191 
6192 #if !defined TORRENT_DISABLE_ENCRYPTION
add_obfuscated_hash(sha1_hash const & obfuscated,std::weak_ptr<torrent> const & t)6193 	void session_impl::add_obfuscated_hash(sha1_hash const& obfuscated
6194 		, std::weak_ptr<torrent> const& t)
6195 	{
6196 		m_obfuscated_torrents.insert(std::make_pair(obfuscated, t.lock()));
6197 	}
6198 #endif // TORRENT_DISABLE_ENCRYPTION
6199 
is_listening() const6200 	bool session_impl::is_listening() const
6201 	{
6202 		return !m_listen_sockets.empty();
6203 	}
6204 
~session_impl()6205 	session_impl::~session_impl()
6206 	{
6207 		// since we're destructing the session, no more alerts will make it out to
6208 		// the user. So stop posting them now
6209 		m_alerts.set_alert_mask({});
6210 
6211 		// this is not allowed to be the network thread!
6212 //		TORRENT_ASSERT(is_not_thread());
6213 // TODO: asserts that no outstanding async operations are still in flight
6214 
6215 		// this can happen if we end the io_service run loop with an exception
6216 		m_connections.clear();
6217 		for (auto& t : m_torrents)
6218 		{
6219 			t.second->panic();
6220 			t.second->abort();
6221 		}
6222 		m_torrents.clear();
6223 #if !defined TORRENT_DISABLE_ENCRYPTION
6224 		m_obfuscated_torrents.clear();
6225 #endif
6226 #if TORRENT_ABI_VERSION == 1
6227 		m_uuids.clear();
6228 #endif
6229 
6230 #if defined TORRENT_ASIO_DEBUGGING
6231 		FILE* f = fopen("wakeups.log", "w+");
6232 		if (f != nullptr)
6233 		{
6234 			time_point m = min_time();
6235 			if (!_wakeups.empty()) m = _wakeups[0].timestamp;
6236 			time_point prev = m;
6237 			std::uint64_t prev_csw = 0;
6238 			if (!_wakeups.empty()) prev_csw = _wakeups[0].context_switches;
6239 			std::fprintf(f, "abs. time\trel. time\tctx switch\tidle-wakeup\toperation\n");
6240 			for (wakeup_t const& w : _wakeups)
6241 			{
6242 				bool const idle_wakeup = w.context_switches > prev_csw;
6243 				std::fprintf(f, "%" PRId64 "\t%" PRId64 "\t%" PRId64 "\t%c\t%s\n"
6244 					, total_microseconds(w.timestamp - m)
6245 					, total_microseconds(w.timestamp - prev)
6246 					, w.context_switches
6247 					, idle_wakeup ? '*' : '.'
6248 					, w.operation);
6249 				prev = w.timestamp;
6250 				prev_csw = w.context_switches;
6251 			}
6252 			fclose(f);
6253 		}
6254 #endif
6255 	}
6256 
6257 #if TORRENT_ABI_VERSION == 1
max_connections() const6258 	int session_impl::max_connections() const
6259 	{
6260 		return m_settings.get_int(settings_pack::connections_limit);
6261 	}
6262 
max_uploads() const6263 	int session_impl::max_uploads() const
6264 	{
6265 		return m_settings.get_int(settings_pack::unchoke_slots_limit);
6266 	}
6267 
set_local_download_rate_limit(int bytes_per_second)6268 	void session_impl::set_local_download_rate_limit(int bytes_per_second)
6269 	{
6270 		INVARIANT_CHECK;
6271 		settings_pack p;
6272 		p.set_int(settings_pack::local_download_rate_limit, bytes_per_second);
6273 		apply_settings_pack_impl(p);
6274 	}
6275 
set_local_upload_rate_limit(int bytes_per_second)6276 	void session_impl::set_local_upload_rate_limit(int bytes_per_second)
6277 	{
6278 		INVARIANT_CHECK;
6279 		settings_pack p;
6280 		p.set_int(settings_pack::local_upload_rate_limit, bytes_per_second);
6281 		apply_settings_pack_impl(p);
6282 	}
6283 
set_download_rate_limit_depr(int bytes_per_second)6284 	void session_impl::set_download_rate_limit_depr(int bytes_per_second)
6285 	{
6286 		INVARIANT_CHECK;
6287 		settings_pack p;
6288 		p.set_int(settings_pack::download_rate_limit, bytes_per_second);
6289 		apply_settings_pack_impl(p);
6290 	}
6291 
set_upload_rate_limit_depr(int bytes_per_second)6292 	void session_impl::set_upload_rate_limit_depr(int bytes_per_second)
6293 	{
6294 		INVARIANT_CHECK;
6295 		settings_pack p;
6296 		p.set_int(settings_pack::upload_rate_limit, bytes_per_second);
6297 		apply_settings_pack_impl(p);
6298 	}
6299 
set_max_connections(int limit)6300 	void session_impl::set_max_connections(int limit)
6301 	{
6302 		INVARIANT_CHECK;
6303 		settings_pack p;
6304 		p.set_int(settings_pack::connections_limit, limit);
6305 		apply_settings_pack_impl(p);
6306 	}
6307 
set_max_uploads(int limit)6308 	void session_impl::set_max_uploads(int limit)
6309 	{
6310 		INVARIANT_CHECK;
6311 		settings_pack p;
6312 		p.set_int(settings_pack::unchoke_slots_limit, limit);
6313 		apply_settings_pack_impl(p);
6314 	}
6315 
local_upload_rate_limit() const6316 	int session_impl::local_upload_rate_limit() const
6317 	{
6318 		return upload_rate_limit(m_local_peer_class);
6319 	}
6320 
local_download_rate_limit() const6321 	int session_impl::local_download_rate_limit() const
6322 	{
6323 		return download_rate_limit(m_local_peer_class);
6324 	}
6325 
upload_rate_limit_depr() const6326 	int session_impl::upload_rate_limit_depr() const
6327 	{
6328 		return upload_rate_limit(m_global_class);
6329 	}
6330 
download_rate_limit_depr() const6331 	int session_impl::download_rate_limit_depr() const
6332 	{
6333 		return download_rate_limit(m_global_class);
6334 	}
6335 #endif // DEPRECATE
6336 
6337 
6338 	namespace {
6339 		template <typename Socket>
set_tos(Socket & s,int v,error_code & ec)6340 		void set_tos(Socket& s, int v, error_code& ec)
6341 		{
6342 #if defined IPV6_TCLASS
6343 			if (is_v6(s.local_endpoint(ec)))
6344 				s.set_option(traffic_class(char(v)), ec);
6345 			else if (!ec)
6346 #endif
6347 				s.set_option(type_of_service(char(v)), ec);
6348 		}
6349 	}
6350 
6351 	// TODO: 2 this should be factored into the udp socket, so we only have the
6352 	// code once
update_peer_tos()6353 	void session_impl::update_peer_tos()
6354 	{
6355 		int const tos = m_settings.get_int(settings_pack::peer_tos);
6356 		for (auto const& l : m_listen_sockets)
6357 		{
6358 			if (l->sock)
6359 			{
6360 				error_code ec;
6361 				set_tos(*l->sock, tos, ec);
6362 
6363 #ifndef TORRENT_DISABLE_LOGGING
6364 				if (should_log())
6365 				{
6366 					session_log(">>> SET_TOS [ tcp (%s %d) tos: %x e: %s ]"
6367 						, l->sock->local_endpoint().address().to_string().c_str()
6368 						, l->sock->local_endpoint().port(), tos, ec.message().c_str());
6369 				}
6370 #endif
6371 			}
6372 
6373 			if (l->udp_sock)
6374 			{
6375 				error_code ec;
6376 				set_tos(l->udp_sock->sock, tos, ec);
6377 
6378 #ifndef TORRENT_DISABLE_LOGGING
6379 				if (should_log())
6380 				{
6381 					session_log(">>> SET_TOS [ udp (%s %d) tos: %x e: %s ]"
6382 						, l->udp_sock->sock.local_endpoint().address().to_string().c_str()
6383 						, l->udp_sock->sock.local_port()
6384 						, tos, ec.message().c_str());
6385 				}
6386 #endif
6387 			}
6388 		}
6389 	}
6390 
update_user_agent()6391 	void session_impl::update_user_agent()
6392 	{
6393 		// replace all occurrences of '\n' with ' '.
6394 		std::string agent = m_settings.get_str(settings_pack::user_agent);
6395 		std::string::iterator i = agent.begin();
6396 		while ((i = std::find(i, agent.end(), '\n'))
6397 			!= agent.end())
6398 			*i = ' ';
6399 		m_settings.set_str(settings_pack::user_agent, agent);
6400 	}
6401 
update_unchoke_limit()6402 	void session_impl::update_unchoke_limit()
6403 	{
6404 		int const allowed_upload_slots = get_int_setting(settings_pack::unchoke_slots_limit);
6405 
6406 		m_stats_counters.set_value(counters::num_unchoke_slots
6407 			, allowed_upload_slots);
6408 
6409 		if (m_settings.get_int(settings_pack::num_optimistic_unchoke_slots)
6410 			>= allowed_upload_slots / 2)
6411 		{
6412 			if (m_alerts.should_post<performance_alert>())
6413 				m_alerts.emplace_alert<performance_alert>(torrent_handle()
6414 					, performance_alert::too_many_optimistic_unchoke_slots);
6415 		}
6416 
6417 		if (settings().get_int(settings_pack::choking_algorithm) != settings_pack::fixed_slots_choker)
6418 			return;
6419 
6420 		if (allowed_upload_slots == std::numeric_limits<int>::max())
6421 		{
6422 			// this means we're not aplpying upload slot limits, unchoke
6423 			// everyone
6424 			for (auto const& p : m_connections)
6425 			{
6426 				if (p->is_disconnecting()
6427 					|| p->is_connecting()
6428 					|| !p->is_choked()
6429 					|| p->in_handshake()
6430 					|| p->ignore_unchoke_slots()
6431 					)
6432 					continue;
6433 
6434 				auto const t = p->associated_torrent().lock();
6435 				t->unchoke_peer(*p);
6436 			}
6437 		}
6438 		else
6439 		{
6440 			// trigger recalculating unchoke slots
6441 			m_unchoke_time_scaler = 0;
6442 		}
6443 	}
6444 
update_connection_speed()6445 	void session_impl::update_connection_speed()
6446 	{
6447 		if (m_settings.get_int(settings_pack::connection_speed) < 0)
6448 			m_settings.set_int(settings_pack::connection_speed, 200);
6449 	}
6450 
update_queued_disk_bytes()6451 	void session_impl::update_queued_disk_bytes()
6452 	{
6453 		int const cache_size = m_settings.get_int(settings_pack::cache_size);
6454 		if (m_settings.get_int(settings_pack::max_queued_disk_bytes) / 16 / 1024
6455 			> cache_size / 2
6456 			&& cache_size > 5
6457 			&& m_alerts.should_post<performance_alert>())
6458 		{
6459 			m_alerts.emplace_alert<performance_alert>(torrent_handle()
6460 				, performance_alert::too_high_disk_queue_limit);
6461 		}
6462 	}
6463 
update_alert_queue_size()6464 	void session_impl::update_alert_queue_size()
6465 	{
6466 		m_alerts.set_alert_queue_size_limit(m_settings.get_int(settings_pack::alert_queue_size));
6467 	}
6468 
preemptive_unchoke() const6469 	bool session_impl::preemptive_unchoke() const
6470 	{
6471 		if (settings().get_int(settings_pack::choking_algorithm) != settings_pack::fixed_slots_choker) return false;
6472 		return m_stats_counters[counters::num_peers_up_unchoked]
6473 			< m_stats_counters[counters::num_unchoke_slots]
6474 			|| m_settings.get_int(settings_pack::unchoke_slots_limit) < 0;
6475 	}
6476 
update_dht_upload_rate_limit()6477 	void session_impl::update_dht_upload_rate_limit()
6478 	{
6479 #ifndef TORRENT_DISABLE_DHT
6480 		m_dht_settings.upload_rate_limit = m_settings.get_int(settings_pack::dht_upload_rate_limit);
6481 		if (m_dht_settings.upload_rate_limit > std::numeric_limits<int>::max() / 3)
6482 		{
6483 			m_settings.set_int(settings_pack::dht_upload_rate_limit, std::numeric_limits<int>::max() / 3);
6484 			m_dht_settings.upload_rate_limit = std::numeric_limits<int>::max() / 3;
6485 		}
6486 #endif
6487 	}
6488 
update_disk_threads()6489 	void session_impl::update_disk_threads()
6490 	{
6491 		if (m_settings.get_int(settings_pack::aio_threads) < 0)
6492 			m_settings.set_int(settings_pack::aio_threads, 0);
6493 
6494 #if !TORRENT_USE_PREAD && !TORRENT_USE_PREADV
6495 		// if we don't have pread() nor preadv() there's no way
6496 		// to perform concurrent file operations on the same file
6497 		// handle, so we must limit the disk thread to a single one
6498 
6499 		if (m_settings.get_int(settings_pack::aio_threads) > 1)
6500 			m_settings.set_int(settings_pack::aio_threads, 1);
6501 #endif
6502 	}
6503 
update_report_web_seed_downloads()6504 	void session_impl::update_report_web_seed_downloads()
6505 	{
6506 		// if this flag changed, update all web seed connections
6507 		bool report = m_settings.get_bool(settings_pack::report_web_seed_downloads);
6508 		for (auto const& c : m_connections)
6509 		{
6510 			connection_type const type = c->type();
6511 			if (type == connection_type::url_seed
6512 				|| type == connection_type::http_seed)
6513 				c->ignore_stats(!report);
6514 		}
6515 	}
6516 
trigger_auto_manage()6517 	void session_impl::trigger_auto_manage()
6518 	{
6519 		if (m_pending_auto_manage || m_abort) return;
6520 
6521 		// we recalculated auto-managed torrents less than a second ago,
6522 		// put it off one second.
6523 		if (time_now() - m_last_auto_manage < seconds(1))
6524 		{
6525 			m_auto_manage_time_scaler = 0;
6526 			return;
6527 		}
6528 		m_pending_auto_manage = true;
6529 		m_need_auto_manage = true;
6530 
6531 		m_io_service.post([this]{ this->wrap(&session_impl::on_trigger_auto_manage); });
6532 	}
6533 
on_trigger_auto_manage()6534 	void session_impl::on_trigger_auto_manage()
6535 	{
6536 		TORRENT_ASSERT(m_pending_auto_manage);
6537 		if (!m_need_auto_manage || m_abort)
6538 		{
6539 			m_pending_auto_manage = false;
6540 			return;
6541 		}
6542 		// don't clear m_pending_auto_manage until after we've
6543 		// recalculated the auto managed torrents. The auto-managed
6544 		// logic may trigger another auto-managed event otherwise
6545 		recalculate_auto_managed_torrents();
6546 		m_pending_auto_manage = false;
6547 	}
6548 
update_socket_buffer_size()6549 	void session_impl::update_socket_buffer_size()
6550 	{
6551 		for (auto const& l : m_listen_sockets)
6552 		{
6553 			error_code ec;
6554 			set_socket_buffer_size(l->udp_sock->sock, m_settings, ec);
6555 #ifndef TORRENT_DISABLE_LOGGING
6556 			if (ec && should_log())
6557 			{
6558 				error_code err;
6559 				session_log("listen socket buffer size [ udp %s:%d ] %s"
6560 					, l->udp_sock->sock.local_endpoint().address().to_string(err).c_str()
6561 					, l->udp_sock->sock.local_port(), print_error(ec).c_str());
6562 			}
6563 #endif
6564 			ec.clear();
6565 			set_socket_buffer_size(*l->sock, m_settings, ec);
6566 #ifndef TORRENT_DISABLE_LOGGING
6567 			if (ec && should_log())
6568 			{
6569 				error_code err;
6570 				session_log("listen socket buffer size [ tcp %s:%d] %s"
6571 					, l->sock->local_endpoint().address().to_string(err).c_str()
6572 					, l->sock->local_endpoint().port(), print_error(ec).c_str());
6573 			}
6574 #endif
6575 		}
6576 	}
6577 
update_dht_announce_interval()6578 	void session_impl::update_dht_announce_interval()
6579 	{
6580 #ifndef TORRENT_DISABLE_DHT
6581 		if (!m_dht)
6582 		{
6583 #ifndef TORRENT_DISABLE_LOGGING
6584 			session_log("not starting DHT announce timer: m_dht == nullptr");
6585 #endif
6586 			return;
6587 		}
6588 
6589 		m_dht_interval_update_torrents = int(m_torrents.size());
6590 
6591 		if (m_abort)
6592 		{
6593 #ifndef TORRENT_DISABLE_LOGGING
6594 			session_log("not starting DHT announce timer: m_abort set");
6595 #endif
6596 			return;
6597 		}
6598 
6599 		ADD_OUTSTANDING_ASYNC("session_impl::on_dht_announce");
6600 		error_code ec;
6601 		int delay = std::max(m_settings.get_int(settings_pack::dht_announce_interval)
6602 			/ std::max(int(m_torrents.size()), 1), 1);
6603 		m_dht_announce_timer.expires_from_now(seconds(delay), ec);
6604 		m_dht_announce_timer.async_wait([this](error_code const& e) {
6605 			this->wrap(&session_impl::on_dht_announce, e); });
6606 #endif
6607 	}
6608 
6609 #if TORRENT_ABI_VERSION == 1
update_local_download_rate()6610 	void session_impl::update_local_download_rate()
6611 	{
6612 		if (m_settings.get_int(settings_pack::local_download_rate_limit) < 0)
6613 			m_settings.set_int(settings_pack::local_download_rate_limit, 0);
6614 		set_download_rate_limit(m_local_peer_class
6615 			, m_settings.get_int(settings_pack::local_download_rate_limit));
6616 	}
6617 
update_local_upload_rate()6618 	void session_impl::update_local_upload_rate()
6619 	{
6620 		if (m_settings.get_int(settings_pack::local_upload_rate_limit) < 0)
6621 			m_settings.set_int(settings_pack::local_upload_rate_limit, 0);
6622 		set_upload_rate_limit(m_local_peer_class
6623 			, m_settings.get_int(settings_pack::local_upload_rate_limit));
6624 	}
6625 #endif
6626 
update_download_rate()6627 	void session_impl::update_download_rate()
6628 	{
6629 		if (m_settings.get_int(settings_pack::download_rate_limit) < 0)
6630 			m_settings.set_int(settings_pack::download_rate_limit, 0);
6631 		set_download_rate_limit(m_global_class
6632 			, m_settings.get_int(settings_pack::download_rate_limit));
6633 	}
6634 
update_upload_rate()6635 	void session_impl::update_upload_rate()
6636 	{
6637 		if (m_settings.get_int(settings_pack::upload_rate_limit) < 0)
6638 			m_settings.set_int(settings_pack::upload_rate_limit, 0);
6639 		set_upload_rate_limit(m_global_class
6640 			, m_settings.get_int(settings_pack::upload_rate_limit));
6641 	}
6642 
update_connections_limit()6643 	void session_impl::update_connections_limit()
6644 	{
6645 		int limit = m_settings.get_int(settings_pack::connections_limit);
6646 
6647 		if (limit <= 0) limit = max_open_files();
6648 
6649 		m_settings.set_int(settings_pack::connections_limit, limit);
6650 
6651 		if (num_connections() > m_settings.get_int(settings_pack::connections_limit)
6652 			&& !m_torrents.empty())
6653 		{
6654 			// if we have more connections that we're allowed, disconnect
6655 			// peers from the torrents so that they are all as even as possible
6656 
6657 			int to_disconnect = num_connections() - m_settings.get_int(settings_pack::connections_limit);
6658 
6659 			int last_average = 0;
6660 			int average = m_settings.get_int(settings_pack::connections_limit) / int(m_torrents.size());
6661 
6662 			// the number of slots that are unused by torrents
6663 			int extra = m_settings.get_int(settings_pack::connections_limit) % int(m_torrents.size());
6664 
6665 			// run 3 iterations of this, then we're probably close enough
6666 			for (int iter = 0; iter < 4; ++iter)
6667 			{
6668 				// the number of torrents that are above average
6669 				int num_above = 0;
6670 				for (auto const& t : m_torrents)
6671 				{
6672 					int const num = t.second->num_peers();
6673 					if (num <= last_average) continue;
6674 					if (num > average) ++num_above;
6675 					if (num < average) extra += average - num;
6676 				}
6677 
6678 				// distribute extra among the torrents that are above average
6679 				if (num_above == 0) num_above = 1;
6680 				last_average = average;
6681 				average += extra / num_above;
6682 				if (extra == 0) break;
6683 				// save the remainder for the next iteration
6684 				extra = extra % num_above;
6685 			}
6686 
6687 			for (auto const& t : m_torrents)
6688 			{
6689 				int const num = t.second->num_peers();
6690 				if (num <= average) continue;
6691 
6692 				// distribute the remainder
6693 				int my_average = average;
6694 				if (extra > 0)
6695 				{
6696 					++my_average;
6697 					--extra;
6698 				}
6699 
6700 				int const disconnect = std::min(to_disconnect, num - my_average);
6701 				to_disconnect -= disconnect;
6702 				t.second->disconnect_peers(disconnect, errors::too_many_connections);
6703 			}
6704 		}
6705 	}
6706 
update_alert_mask()6707 	void session_impl::update_alert_mask()
6708 	{
6709 		m_alerts.set_alert_mask(alert_category_t(
6710 			static_cast<std::uint32_t>(m_settings.get_int(settings_pack::alert_mask))));
6711 	}
6712 
update_validate_https()6713 	void session_impl::update_validate_https()
6714 	{
6715 #ifdef TORRENT_USE_OPENSSL
6716 		using boost::asio::ssl::context;
6717 		auto const flags = m_settings.get_bool(settings_pack::validate_https_trackers)
6718 			? context::verify_peer
6719 				| context::verify_fail_if_no_peer_cert
6720 				| context::verify_client_once
6721 			: context::verify_none;
6722 		error_code ec;
6723 		m_ssl_ctx.set_verify_mode(flags, ec);
6724 
6725 #ifndef TORRENT_DISABLE_LOGGING
6726 		if (ec) session_log("SSL set_verify_mode failed: %s", ec.message().c_str());
6727 #endif
6728 #endif
6729 	}
6730 
pop_alerts(std::vector<alert * > * alerts)6731 	void session_impl::pop_alerts(std::vector<alert*>* alerts)
6732 	{
6733 		m_alerts.get_all(*alerts);
6734 	}
6735 
6736 #if TORRENT_ABI_VERSION == 1
update_rate_limit_utp()6737 	void session_impl::update_rate_limit_utp()
6738 	{
6739 		if (m_settings.get_bool(settings_pack::rate_limit_utp))
6740 		{
6741 			// allow the global or local peer class to limit uTP peers
6742 			m_peer_class_type_filter.allow(peer_class_type_filter::utp_socket
6743 				, m_global_class);
6744 			m_peer_class_type_filter.allow(peer_class_type_filter::ssl_utp_socket
6745 				, m_global_class);
6746 		}
6747 		else
6748 		{
6749 			// don't add the global or local peer class to limit uTP peers
6750 			m_peer_class_type_filter.disallow(peer_class_type_filter::utp_socket
6751 				, m_global_class);
6752 			m_peer_class_type_filter.disallow(peer_class_type_filter::ssl_utp_socket
6753 				, m_global_class);
6754 		}
6755 	}
6756 
update_ignore_rate_limits_on_local_network()6757 	void session_impl::update_ignore_rate_limits_on_local_network()
6758 	{
6759 		init_peer_class_filter(
6760 			m_settings.get_bool(settings_pack::ignore_limits_on_local_network));
6761 	}
6762 
6763 	// this function is called on the user's thread
6764 	// not the network thread
pop_alerts()6765 	void session_impl::pop_alerts()
6766 	{
6767 		// if we don't have any alerts in our local cache, we have to ask
6768 		// the alert_manager for more. It will swap our vector with its and
6769 		// destruct eny left-over alerts in there.
6770 		if (m_alert_pointer_pos >= int(m_alert_pointers.size()))
6771 		{
6772 			pop_alerts(&m_alert_pointers);
6773 			m_alert_pointer_pos = 0;
6774 		}
6775 	}
6776 
pop_alert()6777 	alert const* session_impl::pop_alert()
6778 	{
6779 		if (m_alert_pointer_pos >= int(m_alert_pointers.size()))
6780 		{
6781 			pop_alerts();
6782 			if (m_alert_pointers.empty())
6783 				return nullptr;
6784 		}
6785 
6786 		if (m_alert_pointers.empty()) return nullptr;
6787 
6788 		// clone here to be backwards compatible, to make the client delete the
6789 		// alert object
6790 		return m_alert_pointers[m_alert_pointer_pos++];
6791 	}
6792 
6793 #endif
6794 
wait_for_alert(time_duration max_wait)6795 	alert* session_impl::wait_for_alert(time_duration max_wait)
6796 	{
6797 		return m_alerts.wait_for_alert(max_wait);
6798 	}
6799 
6800 #if TORRENT_ABI_VERSION == 1
set_alert_queue_size_limit(std::size_t queue_size_limit_)6801 	std::size_t session_impl::set_alert_queue_size_limit(std::size_t queue_size_limit_)
6802 	{
6803 		m_settings.set_int(settings_pack::alert_queue_size, int(queue_size_limit_));
6804 		return std::size_t(m_alerts.set_alert_queue_size_limit(int(queue_size_limit_)));
6805 	}
6806 #endif
6807 
start_ip_notifier()6808 	void session_impl::start_ip_notifier()
6809 	{
6810 		INVARIANT_CHECK;
6811 
6812 		if (m_ip_notifier) return;
6813 
6814 		m_ip_notifier = create_ip_notifier(m_io_service);
6815 		m_ip_notifier->async_wait([this](error_code const& e)
6816 			{ this->wrap(&session_impl::on_ip_change, e); });
6817 	}
6818 
start_lsd()6819 	void session_impl::start_lsd()
6820 	{
6821 		INVARIANT_CHECK;
6822 
6823 		for (auto& s : m_listen_sockets)
6824 		{
6825 			// we're not looking for local peers when we're using a proxy. We
6826 			// want all traffic to go through the proxy
6827 			if (s->flags & listen_socket_t::proxy) continue;
6828 			if (s->lsd) continue;
6829 			s->lsd = std::make_shared<lsd>(m_io_service, *this, s->local_endpoint.address()
6830 				, s->netmask);
6831 			error_code ec;
6832 			s->lsd->start(ec);
6833 			if (ec)
6834 			{
6835 				if (m_alerts.should_post<lsd_error_alert>())
6836 					m_alerts.emplace_alert<lsd_error_alert>(ec);
6837 				s->lsd.reset();
6838 			}
6839 		}
6840 	}
6841 
start_natpmp()6842 	void session_impl::start_natpmp()
6843 	{
6844 		INVARIANT_CHECK;
6845 		for (auto& s : m_listen_sockets)
6846 		{
6847 			start_natpmp(*s);
6848 			remap_ports(remap_natpmp, *s);
6849 		}
6850 	}
6851 
start_upnp()6852 	void session_impl::start_upnp()
6853 	{
6854 		INVARIANT_CHECK;
6855 		for (auto& s : m_listen_sockets)
6856 		{
6857 			start_upnp(*s);
6858 			remap_ports(remap_upnp, *s);
6859 		}
6860 	}
6861 
start_upnp(aux::listen_socket_t & s)6862 	void session_impl::start_upnp(aux::listen_socket_t& s)
6863 	{
6864 		// until we support SSDP over an IPv6 network (
6865 		// https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol )
6866 		// there's no point in starting upnp on one.
6867 		if (is_v6(s.local_endpoint))
6868 			return;
6869 
6870 		// there's no point in starting the UPnP mapper for a network that isn't
6871 		// connected to the internet. The whole point is to forward ports through
6872 		// the gateway
6873 		if ((s.flags & listen_socket_t::local_network)
6874 			|| (s.flags & listen_socket_t::proxy))
6875 			return;
6876 
6877 		if (!s.upnp_mapper)
6878 		{
6879 			// the upnp constructor may fail and call the callbacks
6880 			// into the session_impl.
6881 			s.upnp_mapper = std::make_shared<upnp>(m_io_service, m_settings
6882 				, *this, s.local_endpoint.address().to_v4(), s.netmask.to_v4(), s.device);
6883 			s.upnp_mapper->start();
6884 		}
6885 	}
6886 
add_port_mapping(portmap_protocol const t,int const external_port,int const local_port)6887 	std::vector<port_mapping_t> session_impl::add_port_mapping(portmap_protocol const t
6888 		, int const external_port
6889 		, int const local_port)
6890 	{
6891 		std::vector<port_mapping_t> ret;
6892 		for (auto& s : m_listen_sockets)
6893 		{
6894 			if (s->upnp_mapper) ret.push_back(s->upnp_mapper->add_mapping(t, external_port
6895 				, tcp::endpoint(s->local_endpoint.address(), static_cast<std::uint16_t>(local_port))));
6896 			if (s->natpmp_mapper) ret.push_back(s->natpmp_mapper->add_mapping(t, external_port
6897 				, tcp::endpoint(s->local_endpoint.address(), static_cast<std::uint16_t>(local_port))));
6898 		}
6899 		return ret;
6900 	}
6901 
delete_port_mapping(port_mapping_t handle)6902 	void session_impl::delete_port_mapping(port_mapping_t handle)
6903 	{
6904 		for (auto& s : m_listen_sockets)
6905 		{
6906 			if (s->upnp_mapper) s->upnp_mapper->delete_mapping(handle);
6907 			if (s->natpmp_mapper) s->natpmp_mapper->delete_mapping(handle);
6908 		}
6909 	}
6910 
stop_ip_notifier()6911 	void session_impl::stop_ip_notifier()
6912 	{
6913 		if (!m_ip_notifier) return;
6914 
6915 		m_ip_notifier->cancel();
6916 		m_ip_notifier.reset();
6917 	}
6918 
stop_lsd()6919 	void session_impl::stop_lsd()
6920 	{
6921 		for (auto& s : m_listen_sockets)
6922 		{
6923 			if (!s->lsd) continue;
6924 			s->lsd->close();
6925 			s->lsd.reset();
6926 		}
6927 	}
6928 
stop_natpmp()6929 	void session_impl::stop_natpmp()
6930 	{
6931 		for (auto& s : m_listen_sockets)
6932 		{
6933 			s->tcp_port_mapping[portmap_transport::natpmp] = listen_port_mapping();
6934 			s->udp_port_mapping[portmap_transport::natpmp] = listen_port_mapping();
6935 			if (!s->natpmp_mapper) continue;
6936 			s->natpmp_mapper->close();
6937 			s->natpmp_mapper.reset();
6938 		}
6939 	}
6940 
stop_upnp()6941 	void session_impl::stop_upnp()
6942 	{
6943 		for (auto& s : m_listen_sockets)
6944 		{
6945 			if (!s->upnp_mapper) continue;
6946 			s->tcp_port_mapping[portmap_transport::upnp] = listen_port_mapping();
6947 			s->udp_port_mapping[portmap_transport::upnp] = listen_port_mapping();
6948 			s->upnp_mapper->close();
6949 			s->upnp_mapper.reset();
6950 		}
6951 	}
6952 
external_address() const6953 	external_ip session_impl::external_address() const
6954 	{
6955 		address ips[2][2];
6956 
6957 		// take the first IP we find which matches each category
6958 		for (auto const& i : m_listen_sockets)
6959 		{
6960 			address external_addr = i->external_address.external_address();
6961 			if (ips[0][external_addr.is_v6()] == address())
6962 				ips[0][external_addr.is_v6()] = external_addr;
6963 			address local_addr = i->local_endpoint.address();
6964 			if (ips[is_local(local_addr)][local_addr.is_v6()] == address())
6965 				ips[is_local(local_addr)][local_addr.is_v6()] = local_addr;
6966 		}
6967 
6968 		return {ips[1][0], ips[0][0], ips[1][1], ips[0][1]};
6969 	}
6970 
6971 	// this is the DHT observer version. DHT is the implied source
set_external_address(aux::listen_socket_handle const & iface,address const & ip,address const & source)6972 	void session_impl::set_external_address(aux::listen_socket_handle const& iface
6973 		, address const& ip, address const& source)
6974 	{
6975 		auto i = iface.m_sock.lock();
6976 		TORRENT_ASSERT(i);
6977 		if (!i) return;
6978 		set_external_address(i, ip, source_dht, source);
6979 	}
6980 
get_peers(sha1_hash const & ih)6981 	void session_impl::get_peers(sha1_hash const& ih)
6982 	{
6983 		if (!m_alerts.should_post<dht_get_peers_alert>()) return;
6984 		m_alerts.emplace_alert<dht_get_peers_alert>(ih);
6985 	}
6986 
announce(sha1_hash const & ih,address const & addr,int port)6987 	void session_impl::announce(sha1_hash const& ih, address const& addr
6988 		, int port)
6989 	{
6990 		if (!m_alerts.should_post<dht_announce_alert>()) return;
6991 		m_alerts.emplace_alert<dht_announce_alert>(addr, port, ih);
6992 	}
6993 
outgoing_get_peers(sha1_hash const & target,sha1_hash const & sent_target,udp::endpoint const & ep)6994 	void session_impl::outgoing_get_peers(sha1_hash const& target
6995 		, sha1_hash const& sent_target, udp::endpoint const& ep)
6996 	{
6997 		if (!m_alerts.should_post<dht_outgoing_get_peers_alert>()) return;
6998 		m_alerts.emplace_alert<dht_outgoing_get_peers_alert>(target, sent_target, ep);
6999 	}
7000 
7001 #ifndef TORRENT_DISABLE_LOGGING
should_log(module_t) const7002 	bool session_impl::should_log(module_t) const
7003 	{
7004 		return m_alerts.should_post<dht_log_alert>();
7005 	}
7006 
7007 	TORRENT_FORMAT(3,4)
log(module_t m,char const * fmt,...)7008 	void session_impl::log(module_t m, char const* fmt, ...)
7009 	{
7010 		if (!m_alerts.should_post<dht_log_alert>()) return;
7011 
7012 		va_list v;
7013 		va_start(v, fmt);
7014 		m_alerts.emplace_alert<dht_log_alert>(
7015 			static_cast<dht_log_alert::dht_module_t>(m), fmt, v);
7016 		va_end(v);
7017 	}
7018 
log_packet(message_direction_t dir,span<char const> pkt,udp::endpoint const & node)7019 	void session_impl::log_packet(message_direction_t dir, span<char const> pkt
7020 		, udp::endpoint const& node)
7021 	{
7022 		if (!m_alerts.should_post<dht_pkt_alert>()) return;
7023 
7024 		dht_pkt_alert::direction_t d = dir == dht::dht_logger::incoming_message
7025 			? dht_pkt_alert::incoming : dht_pkt_alert::outgoing;
7026 
7027 		m_alerts.emplace_alert<dht_pkt_alert>(pkt, d, node);
7028 	}
7029 
should_log_portmap(portmap_transport) const7030 	bool session_impl::should_log_portmap(portmap_transport) const
7031 	{
7032 		return m_alerts.should_post<portmap_log_alert>();
7033 	}
7034 
log_portmap(portmap_transport transport,char const * msg) const7035 	void session_impl::log_portmap(portmap_transport transport, char const* msg) const
7036 	{
7037 		if (m_alerts.should_post<portmap_log_alert>())
7038 			m_alerts.emplace_alert<portmap_log_alert>(transport, msg);
7039 	}
7040 
should_log_lsd() const7041 	bool session_impl::should_log_lsd() const
7042 	{
7043 		return m_alerts.should_post<log_alert>();
7044 	}
7045 
log_lsd(char const * msg) const7046 	void session_impl::log_lsd(char const* msg) const
7047 	{
7048 		if (m_alerts.should_post<log_alert>())
7049 			m_alerts.emplace_alert<log_alert>(msg);
7050 	}
7051 #endif
7052 
on_dht_request(string_view query,dht::msg const & request,entry & response)7053 	bool session_impl::on_dht_request(string_view query
7054 		, dht::msg const& request, entry& response)
7055 	{
7056 #ifndef TORRENT_DISABLE_EXTENSIONS
7057 		for (auto const& ext : m_ses_extensions[plugins_dht_request_idx])
7058 		{
7059 			if (ext->on_dht_request(query
7060 				, request.addr, request.message, response))
7061 				return true;
7062 		}
7063 #else
7064 		TORRENT_UNUSED(query);
7065 		TORRENT_UNUSED(request);
7066 		TORRENT_UNUSED(response);
7067 #endif
7068 		return false;
7069 	}
7070 
set_external_address(tcp::endpoint const & local_endpoint,address const & ip,ip_source_t const source_type,address const & source)7071 	void session_impl::set_external_address(
7072 		tcp::endpoint const& local_endpoint, address const& ip
7073 		, ip_source_t const source_type, address const& source)
7074 	{
7075 		auto sock = std::find_if(m_listen_sockets.begin(), m_listen_sockets.end()
7076 			, [&](std::shared_ptr<listen_socket_t> const& v)
7077 			{ return v->local_endpoint.address() == local_endpoint.address(); });
7078 
7079 		if (sock != m_listen_sockets.end())
7080 			set_external_address(*sock, ip, source_type, source);
7081 	}
7082 
set_external_address(std::shared_ptr<listen_socket_t> const & sock,address const & ip,ip_source_t const source_type,address const & source)7083 	void session_impl::set_external_address(std::shared_ptr<listen_socket_t> const& sock
7084 		, address const& ip, ip_source_t const source_type, address const& source)
7085 	{
7086 		if (!sock->external_address.cast_vote(ip, source_type, source)) return;
7087 
7088 #ifndef TORRENT_DISABLE_LOGGING
7089 		if (should_log())
7090 		{
7091 			session_log("external address updated for %s [ new-ip: %s type: %d last-voter: %s ]"
7092 				, sock->device.empty() ? print_endpoint(sock->local_endpoint).c_str() : sock->device.c_str()
7093 				, print_address(ip).c_str()
7094 				, static_cast<std::uint8_t>(source_type)
7095 				, print_address(source).c_str());
7096 		}
7097 #endif
7098 
7099 		if (m_alerts.should_post<external_ip_alert>())
7100 			m_alerts.emplace_alert<external_ip_alert>(ip);
7101 
7102 		for (auto const& t : m_torrents)
7103 		{
7104 			t.second->new_external_ip();
7105 		}
7106 
7107 		// since we have a new external IP now, we need to
7108 		// restart the DHT with a new node ID
7109 
7110 #ifndef TORRENT_DISABLE_DHT
7111 		if (m_dht) m_dht->update_node_id(sock);
7112 #endif
7113 	}
7114 
7115 #if TORRENT_USE_INVARIANT_CHECKS
check_invariant() const7116 	void session_impl::check_invariant() const
7117 	{
7118 		TORRENT_ASSERT(is_single_thread());
7119 
7120 		if (m_settings.get_int(settings_pack::unchoke_slots_limit) < 0
7121 			&& m_settings.get_int(settings_pack::choking_algorithm) == settings_pack::fixed_slots_choker)
7122 			TORRENT_ASSERT(m_stats_counters[counters::num_unchoke_slots] == std::numeric_limits<int>::max());
7123 
7124 		for (torrent_list_index_t l{}; l != m_torrent_lists.end_index(); ++l)
7125 		{
7126 			std::vector<torrent*> const& list = m_torrent_lists[l];
7127 			for (auto const& i : list)
7128 			{
7129 				TORRENT_ASSERT(i->m_links[l].in_list());
7130 			}
7131 
7132 			queue_position_t idx{};
7133 			for (auto t : m_download_queue)
7134 			{
7135 				TORRENT_ASSERT(t->queue_position() == idx);
7136 				++idx;
7137 			}
7138 		}
7139 
7140 		int const num_gauges = counters::num_error_torrents - counters::num_checking_torrents + 1;
7141 		aux::array<int, num_gauges> torrent_state_gauges;
7142 		torrent_state_gauges.fill(0);
7143 
7144 #if defined TORRENT_EXPENSIVE_INVARIANT_CHECKS
7145 		std::unordered_set<queue_position_t> unique;
7146 #endif
7147 
7148 		int num_active_downloading = 0;
7149 		int num_active_finished = 0;
7150 		int total_downloaders = 0;
7151 		for (auto const& tor : m_torrents)
7152 		{
7153 			std::shared_ptr<torrent> const& t = tor.second;
7154 			if (t->want_peers_download()) ++num_active_downloading;
7155 			if (t->want_peers_finished()) ++num_active_finished;
7156 			TORRENT_ASSERT(!(t->want_peers_download() && t->want_peers_finished()));
7157 
7158 			int const state = t->current_stats_state() - counters::num_checking_torrents;
7159 			if (state != torrent::no_gauge_state)
7160 			{
7161 				++torrent_state_gauges[state];
7162 			}
7163 
7164 			queue_position_t const pos = t->queue_position();
7165 			if (pos < queue_position_t{})
7166 			{
7167 				TORRENT_ASSERT(pos == no_pos);
7168 				continue;
7169 			}
7170 			++total_downloaders;
7171 
7172 #if defined TORRENT_EXPENSIVE_INVARIANT_CHECKS
7173 			unique.insert(t->queue_position());
7174 #endif
7175 		}
7176 
7177 		for (int i = 0, j = counters::num_checking_torrents;
7178 			j < counters::num_error_torrents + 1; ++i, ++j)
7179 		{
7180 			TORRENT_ASSERT(torrent_state_gauges[i] == m_stats_counters[j]);
7181 		}
7182 
7183 #if defined TORRENT_EXPENSIVE_INVARIANT_CHECKS
7184 		TORRENT_ASSERT(int(unique.size()) == total_downloaders);
7185 #endif
7186 		TORRENT_ASSERT(num_active_downloading == int(m_torrent_lists[torrent_want_peers_download].size()));
7187 		TORRENT_ASSERT(num_active_finished == int(m_torrent_lists[torrent_want_peers_finished].size()));
7188 
7189 		std::unordered_set<peer_connection*> unique_peers;
7190 
7191 		int unchokes = 0;
7192 		int unchokes_all = 0;
7193 		int num_optimistic = 0;
7194 		int disk_queue[2] = {0, 0};
7195 		for (auto const& p : m_connections)
7196 		{
7197 			TORRENT_ASSERT(p);
7198 			if (p->is_disconnecting()) continue;
7199 
7200 			std::shared_ptr<torrent> t = p->associated_torrent().lock();
7201 			TORRENT_ASSERT(unique_peers.find(p.get()) == unique_peers.end());
7202 			unique_peers.insert(p.get());
7203 
7204 			if (p->m_channel_state[0] & peer_info::bw_disk) ++disk_queue[0];
7205 			if (p->m_channel_state[1] & peer_info::bw_disk) ++disk_queue[1];
7206 
7207 			if (p->ignore_unchoke_slots())
7208 			{
7209 				if (!p->is_choked()) ++unchokes_all;
7210 				continue;
7211 			}
7212 			if (!p->is_choked())
7213 			{
7214 				++unchokes;
7215 				++unchokes_all;
7216 			}
7217 
7218 			if (p->peer_info_struct()
7219 				&& p->peer_info_struct()->optimistically_unchoked)
7220 			{
7221 				++num_optimistic;
7222 				TORRENT_ASSERT(!p->is_choked());
7223 			}
7224 		}
7225 
7226 		for (auto const& p : m_undead_peers)
7227 		{
7228 			if (p->ignore_unchoke_slots())
7229 			{
7230 				if (!p->is_choked()) ++unchokes_all;
7231 				continue;
7232 			}
7233 			if (!p->is_choked())
7234 			{
7235 				++unchokes_all;
7236 				++unchokes;
7237 			}
7238 
7239 			if (p->peer_info_struct()
7240 				&& p->peer_info_struct()->optimistically_unchoked)
7241 			{
7242 				++num_optimistic;
7243 				TORRENT_ASSERT(!p->is_choked());
7244 			}
7245 		}
7246 
7247 		TORRENT_ASSERT(disk_queue[peer_connection::download_channel]
7248 			== m_stats_counters[counters::num_peers_down_disk]);
7249 		TORRENT_ASSERT(disk_queue[peer_connection::upload_channel]
7250 			== m_stats_counters[counters::num_peers_up_disk]);
7251 
7252 		if (m_settings.get_int(settings_pack::num_optimistic_unchoke_slots))
7253 		{
7254 			TORRENT_ASSERT(num_optimistic <= m_settings.get_int(
7255 				settings_pack::num_optimistic_unchoke_slots));
7256 		}
7257 
7258 		int const unchoked_counter_all = int(m_stats_counters[counters::num_peers_up_unchoked_all]);
7259 		int const unchoked_counter = int(m_stats_counters[counters::num_peers_up_unchoked]);
7260 		int const unchoked_counter_optimistic
7261 			= int(m_stats_counters[counters::num_peers_up_unchoked_optimistic]);
7262 
7263 		TORRENT_ASSERT_VAL(unchoked_counter_all == unchokes_all, unchokes_all);
7264 		TORRENT_ASSERT_VAL(unchoked_counter == unchokes, unchokes);
7265 		TORRENT_ASSERT_VAL(unchoked_counter_optimistic == num_optimistic, num_optimistic);
7266 
7267 		for (auto const& te : m_torrents)
7268 		{
7269 			TORRENT_ASSERT(te.second);
7270 		}
7271 	}
7272 #endif // TORRENT_USE_INVARIANT_CHECKS
7273 
7274 #ifndef TORRENT_DISABLE_LOGGING
tracker_logger(session_interface & ses)7275 		tracker_logger::tracker_logger(session_interface& ses): m_ses(ses) {}
tracker_warning(tracker_request const &,std::string const & str)7276 		void tracker_logger::tracker_warning(tracker_request const&
7277 			, std::string const& str)
7278 		{
7279 			debug_log("*** tracker warning: %s", str.c_str());
7280 		}
7281 
tracker_response(tracker_request const &,libtorrent::address const & tracker_ip,std::list<address> const & tracker_ips,struct tracker_response const & resp)7282 		void tracker_logger::tracker_response(tracker_request const&
7283 			, libtorrent::address const& tracker_ip
7284 			, std::list<address> const& tracker_ips
7285 			, struct tracker_response const& resp)
7286 		{
7287 			TORRENT_UNUSED(tracker_ips);
7288 			debug_log("TRACKER RESPONSE\n"
7289 				"interval: %d\n"
7290 				"external ip: %s\n"
7291 				"we connected to: %s\n"
7292 				"peers:"
7293 				, resp.interval.count()
7294 				, print_address(resp.external_ip).c_str()
7295 				, print_address(tracker_ip).c_str());
7296 
7297 			for (auto const& p : resp.peers)
7298 			{
7299 				debug_log("  %16s %5d %s", p.hostname.c_str(), p.port
7300 					, p.pid.is_all_zeros() ? "" : to_hex(p.pid).c_str());
7301 			}
7302 			for (auto const& p : resp.peers4)
7303 			{
7304 				debug_log("  %s:%d", print_address(address_v4(p.ip)).c_str(), p.port);
7305 			}
7306 			for (auto const& p : resp.peers6)
7307 			{
7308 				debug_log("  [%s]:%d", print_address(address_v6(p.ip)).c_str(), p.port);
7309 			}
7310 		}
7311 
tracker_request_error(tracker_request const &,error_code const & ec,std::string const & str,seconds32 const retry_interval)7312 		void tracker_logger::tracker_request_error(tracker_request const&
7313 			, error_code const& ec, std::string const& str
7314 			, seconds32 const retry_interval)
7315 		{
7316 			TORRENT_UNUSED(retry_interval);
7317 			debug_log("*** tracker error: %s %s"
7318 				, ec.message().c_str(), str.c_str());
7319 		}
7320 
should_log() const7321 		bool tracker_logger::should_log() const
7322 		{
7323 			return m_ses.alerts().should_post<log_alert>();
7324 		}
7325 
debug_log(const char * fmt,...) const7326 		void tracker_logger::debug_log(const char* fmt, ...) const noexcept try
7327 		{
7328 			if (!m_ses.alerts().should_post<log_alert>()) return;
7329 
7330 			va_list v;
7331 			va_start(v, fmt);
7332 			m_ses.alerts().emplace_alert<log_alert>(fmt, v);
7333 			va_end(v);
7334 		}
7335 		catch (std::exception const&) {}
7336 #endif // TORRENT_DISABLE_LOGGING
7337 }}
7338