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(¶ms.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 , [¶ms](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