/src/libtorrent/src/session.cpp
Line | Count | Source |
1 | | /* |
2 | | |
3 | | Copyright (c) 2003, Magnus Jonsson |
4 | | Copyright (c) 2003, 2006, 2008-2020, 2022, Arvid Norberg |
5 | | Copyright (c) 2016, Alden Torres |
6 | | Copyright (c) 2017, 2020, Steven Siloti |
7 | | All rights reserved. |
8 | | |
9 | | Redistribution and use in source and binary forms, with or without |
10 | | modification, are permitted provided that the following conditions |
11 | | are met: |
12 | | |
13 | | * Redistributions of source code must retain the above copyright |
14 | | notice, this list of conditions and the following disclaimer. |
15 | | * Redistributions in binary form must reproduce the above copyright |
16 | | notice, this list of conditions and the following disclaimer in |
17 | | the documentation and/or other materials provided with the distribution. |
18 | | * Neither the name of the author nor the names of its |
19 | | contributors may be used to endorse or promote products derived |
20 | | from this software without specific prior written permission. |
21 | | |
22 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
23 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
24 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
25 | | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
26 | | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
27 | | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
28 | | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
29 | | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
30 | | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
31 | | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
32 | | POSSIBILITY OF SUCH DAMAGE. |
33 | | |
34 | | */ |
35 | | |
36 | | #include "libtorrent/config.hpp" |
37 | | #include "libtorrent/session.hpp" |
38 | | #include "libtorrent/extensions.hpp" |
39 | | #include "libtorrent/aux_/session_impl.hpp" |
40 | | #include "libtorrent/aux_/session_call.hpp" |
41 | | #include "libtorrent/extensions.hpp" // for add_peer_flags_t |
42 | | #include "libtorrent/disk_interface.hpp" |
43 | | #include "libtorrent/mmap_disk_io.hpp" |
44 | | #include "libtorrent/posix_disk_io.hpp" |
45 | | #include "libtorrent/platform_util.hpp" |
46 | | |
47 | | namespace libtorrent { |
48 | | |
49 | | #ifndef TORRENT_DISABLE_EXTENSIONS |
50 | | // declared in extensions.hpp |
51 | | // remove this once C++17 is required |
52 | | constexpr feature_flags_t plugin::optimistic_unchoke_feature; |
53 | | constexpr feature_flags_t plugin::tick_feature; |
54 | | constexpr feature_flags_t plugin::dht_request_feature; |
55 | | constexpr feature_flags_t plugin::alert_feature; |
56 | | constexpr feature_flags_t plugin::unknown_torrent_feature; |
57 | | #endif |
58 | | |
59 | | namespace aux { |
60 | | constexpr torrent_list_index_t session_interface::torrent_state_updates; |
61 | | constexpr torrent_list_index_t session_interface::torrent_want_tick; |
62 | | constexpr torrent_list_index_t session_interface::torrent_want_peers_download; |
63 | | constexpr torrent_list_index_t session_interface::torrent_want_peers_finished; |
64 | | constexpr torrent_list_index_t session_interface::torrent_want_scrape; |
65 | | constexpr torrent_list_index_t session_interface::torrent_downloading_auto_managed; |
66 | | constexpr torrent_list_index_t session_interface::torrent_seeding_auto_managed; |
67 | | constexpr torrent_list_index_t session_interface::torrent_checking_auto_managed; |
68 | | } |
69 | | |
70 | | #ifndef TORRENT_DISABLE_EXTENSIONS |
71 | | constexpr add_peer_flags_t torrent_plugin::first_time; |
72 | | constexpr add_peer_flags_t torrent_plugin::filtered; |
73 | | #endif |
74 | | |
75 | | namespace { |
76 | | |
77 | | #if defined TORRENT_ASIO_DEBUGGING |
78 | | void wait_for_asio_handlers() |
79 | | { |
80 | | int counter = 0; |
81 | | while (log_async()) |
82 | | { |
83 | | std::this_thread::sleep_for(milliseconds(300)); |
84 | | ++counter; |
85 | | std::printf("\x1b[2J\x1b[0;0H\x1b[33m==== Waiting to shut down: %d ==== \x1b[0m\n\n" |
86 | | , counter); |
87 | | } |
88 | | async_dec_threads(); |
89 | | |
90 | | std::fprintf(stderr, "\n\nEXPECTS NO MORE ASYNC OPS\n\n\n"); |
91 | | } |
92 | | #endif |
93 | | } // anonymous namespace |
94 | | |
95 | | settings_pack min_memory_usage() |
96 | 0 | { |
97 | 0 | settings_pack set; |
98 | 0 | #if TORRENT_ABI_VERSION == 1 |
99 | | // receive data directly into disk buffers |
100 | | // this yields more system calls to read() and |
101 | | // kqueue(), but saves RAM. |
102 | 0 | set.set_bool(settings_pack::contiguous_recv_buffer, false); |
103 | 0 | #endif |
104 | |
|
105 | 0 | set.set_int(settings_pack::max_peer_recv_buffer_size, 32 * 1024 + 200); |
106 | |
|
107 | 0 | set.set_int(settings_pack::disk_io_write_mode, settings_pack::disable_os_cache); |
108 | 0 | set.set_int(settings_pack::disk_io_read_mode, settings_pack::disable_os_cache); |
109 | | |
110 | | // keep 2 blocks outstanding when hashing |
111 | 0 | set.set_int(settings_pack::checking_mem_usage, 2); |
112 | | |
113 | | // don't use any extra threads to do SHA-1 hashing |
114 | 0 | set.set_int(settings_pack::aio_threads, 1); |
115 | |
|
116 | 0 | set.set_int(settings_pack::alert_queue_size, 100); |
117 | |
|
118 | 0 | set.set_int(settings_pack::max_out_request_queue, 300); |
119 | 0 | set.set_int(settings_pack::max_allowed_in_request_queue, 100); |
120 | | |
121 | | // setting this to a low limit, means more |
122 | | // peers are more likely to request from the |
123 | | // same piece. Which means fewer partial |
124 | | // pieces and fewer entries in the partial |
125 | | // piece list |
126 | 0 | set.set_int(settings_pack::whole_pieces_threshold, 2); |
127 | 0 | set.set_bool(settings_pack::use_parole_mode, false); |
128 | 0 | set.set_bool(settings_pack::prioritize_partial_pieces, true); |
129 | | |
130 | | // connect to 5 peers per second |
131 | 0 | set.set_int(settings_pack::connection_speed, 5); |
132 | | |
133 | | // only have 4 files open at a time |
134 | 0 | set.set_int(settings_pack::file_pool_size, 4); |
135 | | |
136 | | // we want to keep the peer list as small as possible |
137 | 0 | set.set_bool(settings_pack::allow_multiple_connections_per_ip, false); |
138 | 0 | set.set_int(settings_pack::max_failcount, 2); |
139 | 0 | set.set_int(settings_pack::inactivity_timeout, 120); |
140 | | |
141 | | // whenever a peer has downloaded one block, write |
142 | | // it to disk, and don't read anything from the |
143 | | // socket until the disk write is complete |
144 | 0 | set.set_int(settings_pack::max_queued_disk_bytes, 1); |
145 | | |
146 | | // never keep more than one 16kB block in |
147 | | // the send buffer |
148 | 0 | set.set_int(settings_pack::send_buffer_watermark, 9); |
149 | |
|
150 | 0 | set.set_bool(settings_pack::close_redundant_connections, true); |
151 | |
|
152 | 0 | set.set_int(settings_pack::max_peerlist_size, 500); |
153 | 0 | set.set_int(settings_pack::max_paused_peerlist_size, 50); |
154 | | |
155 | | // udp trackers are cheaper to talk to |
156 | 0 | set.set_bool(settings_pack::prefer_udp_trackers, true); |
157 | |
|
158 | 0 | set.set_int(settings_pack::max_rejects, 10); |
159 | |
|
160 | 0 | set.set_int(settings_pack::recv_socket_buffer_size, 16 * 1024); |
161 | 0 | set.set_int(settings_pack::send_socket_buffer_size, 16 * 1024); |
162 | 0 | return set; |
163 | 0 | } |
164 | | |
165 | | settings_pack high_performance_seed() |
166 | 0 | { |
167 | 0 | settings_pack set; |
168 | | // don't throttle TCP, assume there is |
169 | | // plenty of bandwidth |
170 | 0 | set.set_int(settings_pack::mixed_mode_algorithm, settings_pack::prefer_tcp); |
171 | |
|
172 | 0 | set.set_int(settings_pack::max_out_request_queue, 1500); |
173 | 0 | set.set_int(settings_pack::max_allowed_in_request_queue, 2000); |
174 | |
|
175 | 0 | set.set_int(settings_pack::max_peer_recv_buffer_size, 5 * 1024 * 1024); |
176 | | |
177 | | // we will probably see a high rate of alerts, make it less |
178 | | // likely to loose alerts |
179 | 0 | set.set_int(settings_pack::alert_queue_size, 10000); |
180 | | |
181 | | // allow 500 files open at a time |
182 | 0 | set.set_int(settings_pack::file_pool_size, 500); |
183 | | |
184 | | // don't update access time for each read/write |
185 | 0 | set.set_bool(settings_pack::no_atime_storage, true); |
186 | | |
187 | | // as a seed box, we must accept multiple peers behind |
188 | | // the same NAT |
189 | | // set.set_bool(settings_pack::allow_multiple_connections_per_ip, true); |
190 | | |
191 | | // connect to 50 peers per second |
192 | 0 | set.set_int(settings_pack::connection_speed, 500); |
193 | | |
194 | | // allow 8000 peer connections |
195 | 0 | set.set_int(settings_pack::connections_limit, 8000); |
196 | | |
197 | | // allow lots of peers to try to connect simultaneously |
198 | 0 | set.set_int(settings_pack::listen_queue_size, 3000); |
199 | | |
200 | | // unchoke all peers |
201 | 0 | set.set_int(settings_pack::unchoke_slots_limit, -1); |
202 | | |
203 | | // the max number of bytes pending write before we throttle |
204 | | // download rate |
205 | 0 | set.set_int(settings_pack::max_queued_disk_bytes, 7 * 1024 * 1024); |
206 | | |
207 | | // prevent fast pieces to interfere with suggested pieces |
208 | | // since we unchoke everyone, we don't need fast pieces anyway |
209 | 0 | set.set_int(settings_pack::allowed_fast_set_size, 0); |
210 | | |
211 | | // suggest pieces in the read cache for higher cache hit rate |
212 | 0 | set.set_int(settings_pack::suggest_mode, settings_pack::suggest_read_cache); |
213 | |
|
214 | 0 | set.set_bool(settings_pack::close_redundant_connections, true); |
215 | |
|
216 | 0 | set.set_int(settings_pack::max_rejects, 10); |
217 | |
|
218 | 0 | set.set_int(settings_pack::send_not_sent_low_watermark, 524288); |
219 | | |
220 | | // don't let connections linger for too long |
221 | 0 | set.set_int(settings_pack::request_timeout, 10); |
222 | 0 | set.set_int(settings_pack::peer_timeout, 20); |
223 | 0 | set.set_int(settings_pack::inactivity_timeout, 20); |
224 | |
|
225 | 0 | set.set_int(settings_pack::active_limit, 20000); |
226 | 0 | set.set_int(settings_pack::active_tracker_limit, 2000); |
227 | 0 | set.set_int(settings_pack::active_dht_limit, 600); |
228 | 0 | set.set_int(settings_pack::active_seeds, 2000); |
229 | |
|
230 | 0 | set.set_int(settings_pack::choking_algorithm, settings_pack::fixed_slots_choker); |
231 | | |
232 | | // of 500 ms, and a send rate of 4 MB/s, the upper |
233 | | // limit should be 2 MB |
234 | 0 | set.set_int(settings_pack::send_buffer_watermark, 3 * 1024 * 1024); |
235 | | |
236 | | // put 1.5 seconds worth of data in the send buffer |
237 | | // this gives the disk I/O more heads-up on disk |
238 | | // reads, and can maximize throughput |
239 | 0 | set.set_int(settings_pack::send_buffer_watermark_factor, 150); |
240 | | |
241 | | // always stuff at least 1 MiB down each peer |
242 | | // pipe, to quickly ramp up send rates |
243 | 0 | set.set_int(settings_pack::send_buffer_low_watermark, 1 * 1024 * 1024); |
244 | | |
245 | | // don't retry peers if they fail once. Let them |
246 | | // connect to us if they want to |
247 | 0 | set.set_int(settings_pack::max_failcount, 1); |
248 | | |
249 | | // number of disk threads for low level file operations |
250 | 0 | set.set_int(settings_pack::aio_threads, 8); |
251 | |
|
252 | 0 | set.set_int(settings_pack::checking_mem_usage, 2048); |
253 | |
|
254 | 0 | return set; |
255 | 0 | } |
256 | | |
257 | | void session::start(session_flags_t const flags, session_params&& params, io_context* ios) |
258 | 0 | { |
259 | 0 | bool const internal_executor = ios == nullptr; |
260 | |
|
261 | 0 | if (internal_executor) |
262 | 0 | { |
263 | | // the user did not provide an executor, we have to use our own |
264 | 0 | m_io_service = std::make_shared<io_context>(1); |
265 | 0 | ios = m_io_service.get(); |
266 | 0 | } |
267 | |
|
268 | 0 | #if TORRENT_ABI_VERSION <= 2 |
269 | 0 | #ifndef TORRENT_DISABLE_DHT |
270 | | // in case the session_params has its dht_settings in use, pick out the |
271 | | // non-default settings from there and move them into the main settings. |
272 | | // any conflicting options set in main settings take precedence |
273 | 0 | { |
274 | 0 | dht::dht_settings const def_sett{}; |
275 | 0 | #define SET_BOOL(name) if (!params.settings.has_val(settings_pack::dht_ ## name) && \ |
276 | 0 | def_sett.name != params.dht_settings.name) \ |
277 | 0 | params.settings.set_bool(settings_pack::dht_ ## name, params.dht_settings.name) |
278 | 0 | #define SET_INT(name) if (!params.settings.has_val(settings_pack::dht_ ## name) && \ |
279 | 0 | def_sett.name != params.dht_settings.name) \ |
280 | 0 | params.settings.set_int(settings_pack::dht_ ## name, params.dht_settings.name) |
281 | |
|
282 | 0 | SET_INT(max_peers_reply); |
283 | 0 | SET_INT(search_branching); |
284 | 0 | SET_INT(max_fail_count); |
285 | 0 | SET_INT(max_torrents); |
286 | 0 | SET_INT(max_dht_items); |
287 | 0 | SET_INT(max_peers); |
288 | 0 | SET_INT(max_torrent_search_reply); |
289 | 0 | SET_BOOL(restrict_routing_ips); |
290 | 0 | SET_BOOL(restrict_search_ips); |
291 | 0 | SET_BOOL(extended_routing_table); |
292 | 0 | SET_BOOL(aggressive_lookups); |
293 | 0 | SET_BOOL(privacy_lookups); |
294 | 0 | SET_BOOL(enforce_node_id); |
295 | 0 | SET_BOOL(ignore_dark_internet); |
296 | 0 | SET_INT(block_timeout); |
297 | 0 | SET_INT(block_ratelimit); |
298 | 0 | SET_BOOL(read_only); |
299 | 0 | SET_INT(item_lifetime); |
300 | 0 | SET_INT(upload_rate_limit); |
301 | 0 | SET_INT(sample_infohashes_interval); |
302 | 0 | SET_INT(max_infohashes_sample_count); |
303 | 0 | #undef SET_BOOL |
304 | 0 | #undef SET_INT |
305 | 0 | } |
306 | 0 | #endif |
307 | 0 | #endif |
308 | |
|
309 | 0 | m_impl = std::make_shared<aux::session_impl>(std::ref(*ios) |
310 | 0 | , std::move(params.settings) |
311 | 0 | , std::move(params.disk_io_constructor) |
312 | 0 | , flags); |
313 | 0 | *static_cast<session_handle*>(this) = session_handle(m_impl); |
314 | |
|
315 | 0 | #ifndef TORRENT_DISABLE_EXTENSIONS |
316 | 0 | for (auto& ext : params.extensions) |
317 | 0 | { |
318 | 0 | ext->load_state(params.ext_state); |
319 | 0 | m_impl->add_ses_extension(std::move(ext)); |
320 | 0 | } |
321 | 0 | #endif |
322 | |
|
323 | 0 | #ifndef TORRENT_DISABLE_DHT |
324 | 0 | m_impl->set_dht_state(std::move(params.dht_state)); |
325 | |
|
326 | 0 | TORRENT_ASSERT(params.dht_storage_constructor); |
327 | 0 | m_impl->set_dht_storage(std::move(params.dht_storage_constructor)); |
328 | 0 | #endif |
329 | |
|
330 | 0 | if (!params.ip_filter.empty()) |
331 | 0 | { |
332 | 0 | std::shared_ptr<ip_filter> copy = std::make_shared<ip_filter>(std::move(params.ip_filter)); |
333 | 0 | m_impl->set_ip_filter(std::move(copy)); |
334 | 0 | } |
335 | |
|
336 | 0 | m_impl->start_session(); |
337 | |
|
338 | 0 | if (internal_executor) |
339 | 0 | { |
340 | | // start a thread for the message pump |
341 | 0 | auto s = m_io_service; |
342 | 0 | m_thread = std::make_shared<std::thread>([=] |
343 | 0 | { |
344 | 0 | set_thread_name("libtorrent-network-thread"); |
345 | 0 | s->run(); |
346 | 0 | }); |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | #if TORRENT_ABI_VERSION <= 2 |
351 | | void session::start(session_flags_t const flags, settings_pack&& sp, io_context* ios) |
352 | 0 | { |
353 | 0 | if (flags & add_default_plugins) |
354 | 0 | { |
355 | 0 | session_params sp_(std::move(sp)); |
356 | 0 | start(flags, std::move(sp_), ios); |
357 | 0 | } |
358 | 0 | else |
359 | 0 | { |
360 | 0 | session_params sp_(std::move(sp), {}); |
361 | 0 | start(flags, std::move(sp_), ios); |
362 | 0 | } |
363 | 0 | } |
364 | | #endif |
365 | | |
366 | 0 | session::session(session&&) = default; |
367 | | |
368 | | session::session(session_params const& params) |
369 | 0 | { |
370 | 0 | start({}, session_params(params), nullptr); |
371 | 0 | } |
372 | | |
373 | | session::session(session_params&& params) |
374 | 0 | { |
375 | 0 | start({}, std::move(params), nullptr); |
376 | 0 | } |
377 | | |
378 | | session::session(session_params const& params, session_flags_t const flags) |
379 | 0 | { |
380 | 0 | start(flags, session_params(params), nullptr); |
381 | 0 | } |
382 | | |
383 | | session::session(session_params&& params, session_flags_t const flags) |
384 | 0 | { |
385 | 0 | start(flags, std::move(params), nullptr); |
386 | 0 | } |
387 | | |
388 | | session::session() |
389 | 0 | { |
390 | 0 | session_params params; |
391 | 0 | start({}, std::move(params), nullptr); |
392 | 0 | } |
393 | | |
394 | | session::session(session_params&& params, io_context& ios) |
395 | 0 | { |
396 | 0 | start({}, std::move(params), &ios); |
397 | 0 | } |
398 | | |
399 | | session::session(session_params const& params, io_context& ios) |
400 | 0 | { |
401 | 0 | start({}, session_params(params), &ios); |
402 | 0 | } |
403 | | |
404 | | session::session(session_params&& params, io_context& ios, session_flags_t const flags) |
405 | 0 | { |
406 | 0 | start(flags, std::move(params), &ios); |
407 | 0 | } |
408 | | |
409 | | session::session(session_params const& params, io_context& ios, session_flags_t const flags) |
410 | 0 | { |
411 | 0 | start(flags, session_params(params), &ios); |
412 | 0 | } |
413 | | |
414 | | |
415 | | #if TORRENT_ABI_VERSION <= 2 |
416 | | session::session(settings_pack&& pack, session_flags_t const flags) |
417 | 0 | { |
418 | 0 | start(flags, std::move(pack), nullptr); |
419 | 0 | } |
420 | | |
421 | | session::session(settings_pack const& pack, session_flags_t const flags) |
422 | 0 | { |
423 | 0 | start(flags, settings_pack(pack), nullptr); |
424 | 0 | } |
425 | | |
426 | | session::session(settings_pack&& pack, io_context& ios, session_flags_t const flags) |
427 | 0 | { |
428 | 0 | start(flags, std::move(pack), &ios); |
429 | 0 | } |
430 | | |
431 | | session::session(settings_pack const& pack, io_context& ios, session_flags_t const flags) |
432 | 0 | { |
433 | 0 | start(flags, settings_pack(pack), &ios); |
434 | 0 | } |
435 | | #endif |
436 | | |
437 | | #if TORRENT_ABI_VERSION == 1 |
438 | | #include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" |
439 | | session::session(fingerprint const& print, session_flags_t const flags |
440 | | , alert_category_t const alert_mask) |
441 | 0 | { |
442 | 0 | settings_pack pack; |
443 | 0 | pack.set_int(settings_pack::alert_mask, int(alert_mask)); |
444 | 0 | pack.set_str(settings_pack::peer_fingerprint, print.to_string()); |
445 | 0 | if (!(flags & start_default_features)) |
446 | 0 | { |
447 | 0 | pack.set_bool(settings_pack::enable_upnp, false); |
448 | 0 | pack.set_bool(settings_pack::enable_natpmp, false); |
449 | 0 | pack.set_bool(settings_pack::enable_lsd, false); |
450 | 0 | pack.set_bool(settings_pack::enable_dht, false); |
451 | 0 | } |
452 | |
|
453 | 0 | start(flags, std::move(pack), nullptr); |
454 | 0 | } |
455 | | |
456 | | session::session(fingerprint const& print, std::pair<int, int> listen_port_range |
457 | | , char const* listen_interface, session_flags_t const flags |
458 | | , alert_category_t const alert_mask) |
459 | 0 | { |
460 | 0 | TORRENT_ASSERT(listen_port_range.first > 0); |
461 | 0 | TORRENT_ASSERT(listen_port_range.first <= listen_port_range.second); |
462 | |
|
463 | 0 | settings_pack pack; |
464 | 0 | pack.set_int(settings_pack::alert_mask, int(alert_mask)); |
465 | 0 | pack.set_int(settings_pack::max_retry_port_bind, listen_port_range.second - listen_port_range.first); |
466 | 0 | pack.set_str(settings_pack::peer_fingerprint, print.to_string()); |
467 | 0 | char if_string[100]; |
468 | |
|
469 | 0 | if (listen_interface == nullptr) listen_interface = "0.0.0.0"; |
470 | 0 | std::snprintf(if_string, sizeof(if_string), "%s:%d", listen_interface, listen_port_range.first); |
471 | 0 | pack.set_str(settings_pack::listen_interfaces, if_string); |
472 | |
|
473 | 0 | if (!(flags & start_default_features)) |
474 | 0 | { |
475 | 0 | pack.set_bool(settings_pack::enable_upnp, false); |
476 | 0 | pack.set_bool(settings_pack::enable_natpmp, false); |
477 | 0 | pack.set_bool(settings_pack::enable_lsd, false); |
478 | 0 | pack.set_bool(settings_pack::enable_dht, false); |
479 | 0 | } |
480 | 0 | start(flags, std::move(pack), nullptr); |
481 | 0 | } |
482 | | #include "libtorrent/aux_/disable_warnings_pop.hpp" |
483 | | #endif // TORRENT_ABI_VERSION |
484 | 0 | session& session::operator=(session&&) & = default; |
485 | | |
486 | | session::~session() |
487 | 0 | { |
488 | 0 | if (!m_impl) return; |
489 | | |
490 | 0 | aux::dump_call_profile(); |
491 | | |
492 | | // capture the shared_ptr in the dispatched function |
493 | | // to keep the session_impl alive |
494 | 0 | m_impl->call_abort(); |
495 | |
|
496 | 0 | if (m_thread && m_thread.use_count() == 1) |
497 | 0 | { |
498 | | #if defined TORRENT_ASIO_DEBUGGING |
499 | | wait_for_asio_handlers(); |
500 | | #endif |
501 | 0 | m_thread->join(); |
502 | 0 | } |
503 | 0 | } |
504 | | |
505 | | session_proxy session::abort() |
506 | 0 | { |
507 | | // stop calling the alert notify function now, to avoid it thinking the |
508 | | // session is still alive |
509 | 0 | m_impl->alerts().set_notify_function({}); |
510 | 0 | return session_proxy(m_io_service, m_thread, m_impl); |
511 | 0 | } |
512 | | |
513 | 0 | session_proxy::session_proxy() = default; |
514 | | session_proxy::session_proxy(std::shared_ptr<io_context> ios |
515 | | , std::shared_ptr<std::thread> t |
516 | | , std::shared_ptr<aux::session_impl> impl) |
517 | 0 | : m_io_service(std::move(ios)) |
518 | 0 | , m_thread(std::move(t)) |
519 | 0 | , m_impl(std::move(impl)) |
520 | 0 | {} |
521 | 0 | session_proxy::session_proxy(session_proxy const&) = default; |
522 | 0 | session_proxy& session_proxy::operator=(session_proxy const&) & = default; |
523 | 0 | session_proxy::session_proxy(session_proxy&&) noexcept = default; |
524 | 0 | session_proxy& session_proxy::operator=(session_proxy&&) & noexcept = default; |
525 | | session_proxy::~session_proxy() |
526 | 0 | { |
527 | 0 | if (m_thread && m_thread.use_count() == 1) |
528 | 0 | { |
529 | | #if defined TORRENT_ASIO_DEBUGGING |
530 | | wait_for_asio_handlers(); |
531 | | #endif |
532 | 0 | m_thread->join(); |
533 | 0 | } |
534 | 0 | } |
535 | | |
536 | | TORRENT_EXPORT std::unique_ptr<disk_interface> default_disk_io_constructor( |
537 | | io_context& ios, settings_interface const& sett, counters& cnt) |
538 | 0 | { |
539 | 0 | #if TORRENT_HAVE_MMAP || TORRENT_HAVE_MAP_VIEW_OF_FILE |
540 | | // TODO: In C++17. use if constexpr instead |
541 | 0 | #include "libtorrent/aux_/disable_deprecation_warnings_push.hpp" |
542 | 0 | if (sizeof(void*) == 8) |
543 | 0 | return mmap_disk_io_constructor(ios, sett, cnt); |
544 | 0 | else |
545 | 0 | return posix_disk_io_constructor(ios, sett, cnt); |
546 | 0 | #include "libtorrent/aux_/disable_warnings_pop.hpp" |
547 | | #else |
548 | | return posix_disk_io_constructor(ios, sett, cnt); |
549 | | #endif |
550 | 0 | } |
551 | | |
552 | | } |