1 | |
---|
2 | // Copyright Eóin O'Callaghan 2006 - 2008. |
---|
3 | // Distributed under the Boost Software License, Version 1.0. |
---|
4 | // (See accompanying file LICENSE_1_0.txt or copy at |
---|
5 | // http://www.boost.org/LICENSE_1_0.txt) |
---|
6 | |
---|
7 | #pragma once |
---|
8 | |
---|
9 | #include <boost/tuple/tuple.hpp> |
---|
10 | #include <boost/enable_shared_from_this.hpp> |
---|
11 | #include <boost/multi_index_container.hpp> |
---|
12 | #include <boost/multi_index/ordered_index.hpp> |
---|
13 | #include <boost/multi_index/indexed_by.hpp> |
---|
14 | #include <boost/multi_index/identity.hpp> |
---|
15 | #include <boost/multi_index/member.hpp> |
---|
16 | #include <boost/multi_index/tag.hpp> |
---|
17 | |
---|
18 | #pragma warning (push, 1) |
---|
19 | # include <libtorrent/file.hpp> |
---|
20 | # include <libtorrent/hasher.hpp> |
---|
21 | # include <libtorrent/storage.hpp> |
---|
22 | # include <libtorrent/file_pool.hpp> |
---|
23 | # include <libtorrent/alert_types.hpp> |
---|
24 | # include <libtorrent/entry.hpp> |
---|
25 | # include <libtorrent/bencode.hpp> |
---|
26 | # include <libtorrent/session.hpp> |
---|
27 | # include <libtorrent/ip_filter.hpp> |
---|
28 | # include <libtorrent/torrent_handle.hpp> |
---|
29 | # include <libtorrent/peer_connection.hpp> |
---|
30 | # include <libtorrent/extensions/metadata_transfer.hpp> |
---|
31 | # include <libtorrent/extensions/ut_pex.hpp> |
---|
32 | #pragma warning (pop) |
---|
33 | |
---|
34 | #include "halIni.hpp" |
---|
35 | #include "halTypes.hpp" |
---|
36 | #include "halEvent.hpp" |
---|
37 | #include "halTorrentInternal.hpp" |
---|
38 | #include "halSignaler.hpp" |
---|
39 | |
---|
40 | namespace boost { |
---|
41 | namespace serialization { |
---|
42 | |
---|
43 | template<class Archive, class address_type> |
---|
44 | void save(Archive& ar, const address_type& ip, const unsigned int version) |
---|
45 | { |
---|
46 | unsigned long addr = ip.to_ulong(); |
---|
47 | ar & BOOST_SERIALIZATION_NVP(addr); |
---|
48 | } |
---|
49 | |
---|
50 | template<class Archive, class address_type> |
---|
51 | void load(Archive& ar, address_type& ip, const unsigned int version) |
---|
52 | { |
---|
53 | unsigned long addr; |
---|
54 | ar & BOOST_SERIALIZATION_NVP(addr); |
---|
55 | ip = address_type(addr); |
---|
56 | } |
---|
57 | |
---|
58 | template<class Archive, class String, class Traits> |
---|
59 | void save(Archive& ar, const boost::filesystem::basic_path<String, Traits>& p, const unsigned int version) |
---|
60 | { |
---|
61 | String str = p.string(); |
---|
62 | ar & BOOST_SERIALIZATION_NVP(str); |
---|
63 | } |
---|
64 | |
---|
65 | template<class Archive, class String, class Traits> |
---|
66 | void load(Archive& ar, boost::filesystem::basic_path<String, Traits>& p, const unsigned int version) |
---|
67 | { |
---|
68 | String str; |
---|
69 | ar & BOOST_SERIALIZATION_NVP(str); |
---|
70 | |
---|
71 | p = str; |
---|
72 | } |
---|
73 | |
---|
74 | template<class Archive, class String, class Traits> |
---|
75 | inline void serialize( |
---|
76 | Archive & ar, |
---|
77 | boost::filesystem::basic_path<String, Traits>& p, |
---|
78 | const unsigned int file_version) |
---|
79 | { |
---|
80 | split_free(ar, p, file_version); |
---|
81 | } |
---|
82 | |
---|
83 | template<class Archive, class address_type> |
---|
84 | void serialize(Archive& ar, libtorrent::ip_range<address_type>& addr, const unsigned int version) |
---|
85 | { |
---|
86 | ar & BOOST_SERIALIZATION_NVP(addr.first); |
---|
87 | ar & BOOST_SERIALIZATION_NVP(addr.last); |
---|
88 | addr.flags = libtorrent::ip_filter::blocked; |
---|
89 | } |
---|
90 | |
---|
91 | template<class Archive> |
---|
92 | void serialize(Archive& ar, hal::tracker_detail& tracker, const unsigned int version) |
---|
93 | { |
---|
94 | ar & BOOST_SERIALIZATION_NVP(tracker.url); |
---|
95 | ar & BOOST_SERIALIZATION_NVP(tracker.tier); |
---|
96 | } |
---|
97 | |
---|
98 | } // namespace serialization |
---|
99 | } // namespace boost |
---|
100 | |
---|
101 | BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v4) |
---|
102 | BOOST_SERIALIZATION_SPLIT_FREE(asio::ip::address_v6) |
---|
103 | |
---|
104 | namespace libtorrent |
---|
105 | { |
---|
106 | |
---|
107 | template<class Addr> |
---|
108 | bool operator==(const libtorrent::ip_range<Addr>& lhs, const int flags) |
---|
109 | { |
---|
110 | return (lhs.flags == flags); |
---|
111 | } |
---|
112 | |
---|
113 | inline |
---|
114 | std::ostream& operator<<(std::ostream& os, libtorrent::ip_range<asio::ip::address_v4>& ip) |
---|
115 | { |
---|
116 | os << ip.first.to_ulong(); |
---|
117 | os << ip.last.to_ulong(); |
---|
118 | |
---|
119 | return os; |
---|
120 | } |
---|
121 | |
---|
122 | } // namespace libtorrent |
---|
123 | |
---|
124 | namespace hal |
---|
125 | { |
---|
126 | |
---|
127 | namespace libt = libtorrent; |
---|
128 | |
---|
129 | inline |
---|
130 | bool operator!=(const libt::dht_settings& lhs, const libt::dht_settings& rhs) |
---|
131 | { |
---|
132 | return lhs.max_peers_reply != rhs.max_peers_reply || |
---|
133 | lhs.search_branching != rhs.search_branching || |
---|
134 | lhs.service_port != rhs.service_port || |
---|
135 | lhs.max_fail_count != rhs.max_fail_count; |
---|
136 | } |
---|
137 | |
---|
138 | template<typename Addr> |
---|
139 | void write_range(fs::ofstream& ofs, const libt::ip_range<Addr>& range) |
---|
140 | { |
---|
141 | const typename Addr::bytes_type first = range.first.to_bytes(); |
---|
142 | const typename Addr::bytes_type last = range.last.to_bytes(); |
---|
143 | ofs.write((char*)first.elems, first.size()); |
---|
144 | ofs.write((char*)last.elems, last.size()); |
---|
145 | } |
---|
146 | |
---|
147 | template<typename Addr> |
---|
148 | void write_vec_range(fs::ofstream& ofs, const std::vector<libt::ip_range<Addr> >& vec) |
---|
149 | { |
---|
150 | ofs << vec.size(); |
---|
151 | |
---|
152 | for (typename std::vector<libt::ip_range<Addr> >::const_iterator i=vec.begin(); |
---|
153 | i != vec.end(); ++i) |
---|
154 | { |
---|
155 | write_range(ofs, *i); |
---|
156 | } |
---|
157 | } |
---|
158 | |
---|
159 | template<typename Addr> |
---|
160 | void read_range_to_filter(fs::ifstream& ifs, libt::ip_filter& ip_filter) |
---|
161 | { |
---|
162 | typename Addr::bytes_type first; |
---|
163 | typename Addr::bytes_type last; |
---|
164 | ifs.read((char*)first.elems, first.size()); |
---|
165 | ifs.read((char*)last.elems, last.size()); |
---|
166 | |
---|
167 | ip_filter.add_rule(Addr(first), Addr(last), |
---|
168 | libt::ip_filter::blocked); |
---|
169 | } |
---|
170 | |
---|
171 | static event_logger::eventLevel lbtAlertToHalEvent(libt::alert::severity_t severity) |
---|
172 | { |
---|
173 | switch (severity) |
---|
174 | { |
---|
175 | case libt::alert::debug: |
---|
176 | return event_logger::debug; |
---|
177 | |
---|
178 | case libt::alert::info: |
---|
179 | return event_logger::info; |
---|
180 | |
---|
181 | case libt::alert::warning: |
---|
182 | return event_logger::warning; |
---|
183 | |
---|
184 | case libt::alert::critical: |
---|
185 | case libt::alert::fatal: |
---|
186 | return event_logger::critical; |
---|
187 | |
---|
188 | default: |
---|
189 | return event_logger::none; |
---|
190 | } |
---|
191 | } |
---|
192 | |
---|
193 | static event_logger::eventLevel lbt_category_to_event(int category) |
---|
194 | { |
---|
195 | switch (category) |
---|
196 | { |
---|
197 | case libt::alert::debug_notification: |
---|
198 | return event_logger::debug; |
---|
199 | |
---|
200 | case libt::alert::peer_notification: |
---|
201 | case libt::alert::port_mapping_notification: |
---|
202 | case libt::alert::storage_notification: |
---|
203 | case libt::alert::tracker_notification: |
---|
204 | case libt::alert::status_notification: |
---|
205 | case libt::alert::progress_notification: |
---|
206 | case libt::alert::ip_block_notification: |
---|
207 | return event_logger::info; |
---|
208 | |
---|
209 | case libt::alert::performance_warning: |
---|
210 | return event_logger::warning; |
---|
211 | |
---|
212 | case libt::alert::error_notification: |
---|
213 | return event_logger::critical; |
---|
214 | |
---|
215 | default: |
---|
216 | return event_logger::none; |
---|
217 | } |
---|
218 | } |
---|
219 | |
---|
220 | #define HAL_GENERIC_TORRENT_PROP_EXCEPTION_CATCH(FUNCTION) \ |
---|
221 | catch (const libt::invalid_handle&) \ |
---|
222 | {\ |
---|
223 | event_log.post(shared_ptr<EventDetail>( \ |
---|
224 | new EventInvalidTorrent(event_logger::critical, event_logger::invalidTorrent, name, std::string(FUNCTION)))); \ |
---|
225 | }\ |
---|
226 | catch (const invalidTorrent& t) \ |
---|
227 | { \ |
---|
228 | event_log.post(shared_ptr<EventDetail>( \ |
---|
229 | new EventInvalidTorrent(event_logger::info, event_logger::invalidTorrent, t.who(), std::string(FUNCTION)))); \ |
---|
230 | } \ |
---|
231 | catch (const access_violation& e) \ |
---|
232 | { \ |
---|
233 | hal::event_log.post(shared_ptr<hal::EventDetail>( \ |
---|
234 | new hal::EventMsg(hal::wform(L"Torrent property %1% access_violation (code %2$x) at %3$x. Bad address %4$x") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % (unsigned)e.badAddress(), \ |
---|
235 | hal::event_logger::critical))); \ |
---|
236 | } \ |
---|
237 | catch (const win32_exception& e) \ |
---|
238 | { \ |
---|
239 | hal::event_log.post(shared_ptr<hal::EventDetail>( \ |
---|
240 | new hal::EventMsg(hal::wform(L"Torrent property %1% win32_exception (code %2$x) at %3$x") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where(), \ |
---|
241 | hal::event_logger::critical))); \ |
---|
242 | } \ |
---|
243 | catch (const std::exception& e) \ |
---|
244 | { \ |
---|
245 | event_log.post(shared_ptr<EventDetail>( \ |
---|
246 | new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), name, std::string(FUNCTION)))); \ |
---|
247 | } \ |
---|
248 | catch(...) \ |
---|
249 | { \ |
---|
250 | hal::event_log.post(shared_ptr<hal::EventDetail>( \ |
---|
251 | new hal::EventMsg(hal::wform(L"%1% catch all") % hal::from_utf8(FUNCTION), \ |
---|
252 | hal::event_logger::critical))); \ |
---|
253 | } |
---|
254 | |
---|
255 | #define HAL_GENERIC_TORRENT_EXCEPTION_CATCH(TORRENT, FUNCTION) \ |
---|
256 | catch (const libt::invalid_handle&) \ |
---|
257 | {\ |
---|
258 | event_log.post(shared_ptr<EventDetail>( \ |
---|
259 | new EventInvalidTorrent(event_logger::critical, event_logger::invalidTorrent, TORRENT, std::string(FUNCTION)))); \ |
---|
260 | }\ |
---|
261 | catch (const invalidTorrent& t) \ |
---|
262 | {\ |
---|
263 | event_log.post(shared_ptr<EventDetail>( \ |
---|
264 | new EventInvalidTorrent(event_logger::info, event_logger::invalidTorrent, t.who(), std::string(FUNCTION)))); \ |
---|
265 | }\ |
---|
266 | catch (const access_violation& e) \ |
---|
267 | { \ |
---|
268 | hal::event_log.post(shared_ptr<hal::EventDetail>( \ |
---|
269 | new hal::EventMsg(hal::wform(L"Generic Torrent %1% access_violation (code %2$x) at %3$x. Bad address %4$x (%5%)") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % (unsigned)e.badAddress() % TORRENT, \ |
---|
270 | hal::event_logger::critical))); \ |
---|
271 | } \ |
---|
272 | catch (const win32_exception& e) \ |
---|
273 | { \ |
---|
274 | hal::event_log.post(shared_ptr<hal::EventDetail>( \ |
---|
275 | new hal::EventMsg(hal::wform(L"Generic Torrent %1% win32_exception (code %2$x) at %3$x (%4%)") % hal::from_utf8(FUNCTION) % e.code() % (unsigned)e.where() % TORRENT, \ |
---|
276 | hal::event_logger::critical))); \ |
---|
277 | } \ |
---|
278 | catch (const std::exception& e) \ |
---|
279 | { \ |
---|
280 | event_log.post(shared_ptr<EventDetail>( \ |
---|
281 | new EventTorrentException(event_logger::critical, event_logger::torrentException, std::string(e.what()), TORRENT, std::string(FUNCTION)))); \ |
---|
282 | } \ |
---|
283 | catch (...) \ |
---|
284 | { \ |
---|
285 | hal::event_log.post(shared_ptr<hal::EventDetail>( \ |
---|
286 | new hal::EventMsg(hal::wform(L"Generic Torrent %1% catch all") % hal::from_utf8(FUNCTION), \ |
---|
287 | hal::event_logger::critical))); \ |
---|
288 | } |
---|
289 | |
---|
290 | class bit_impl |
---|
291 | { |
---|
292 | friend class bit; |
---|
293 | |
---|
294 | private: |
---|
295 | bit_impl(); |
---|
296 | public: |
---|
297 | ~bit_impl(); |
---|
298 | |
---|
299 | bool listen_on(std::pair<int, int> const& range) |
---|
300 | { |
---|
301 | try |
---|
302 | { |
---|
303 | |
---|
304 | if (!session_.is_listening()) |
---|
305 | { |
---|
306 | return session_.listen_on(range); |
---|
307 | } |
---|
308 | else |
---|
309 | { |
---|
310 | int port = session_.listen_port(); |
---|
311 | |
---|
312 | if (port < range.first || port > range.second) |
---|
313 | return session_.listen_on(range); |
---|
314 | else |
---|
315 | { |
---|
316 | signals.successful_listen(); |
---|
317 | |
---|
318 | return true; |
---|
319 | } |
---|
320 | } |
---|
321 | |
---|
322 | } |
---|
323 | catch (const std::exception& e) |
---|
324 | { |
---|
325 | event_log.post(shared_ptr<EventDetail>( |
---|
326 | new EventStdException(event_logger::fatal, e, L"From bit::listenOn."))); |
---|
327 | |
---|
328 | return false; |
---|
329 | } |
---|
330 | catch(...) |
---|
331 | { |
---|
332 | return false; |
---|
333 | } |
---|
334 | } |
---|
335 | |
---|
336 | int is_listening_on() |
---|
337 | { |
---|
338 | if (!session_.is_listening()) |
---|
339 | return -1; |
---|
340 | else |
---|
341 | return session_.listen_port(); |
---|
342 | } |
---|
343 | |
---|
344 | void stop_listening() |
---|
345 | { |
---|
346 | ensure_dht_off(); |
---|
347 | session_.listen_on(std::make_pair(0, 0)); |
---|
348 | } |
---|
349 | |
---|
350 | bool ensure_dht_on(const dht_settings& dht) |
---|
351 | { |
---|
352 | libt::dht_settings settings; |
---|
353 | settings.max_peers_reply = dht.max_peers_reply; |
---|
354 | settings.search_branching = dht.search_branching; |
---|
355 | settings.service_port = dht.service_port; |
---|
356 | settings.max_fail_count = dht.max_fail_count; |
---|
357 | |
---|
358 | if (dht_settings_ != settings) |
---|
359 | { |
---|
360 | dht_settings_ = settings; |
---|
361 | session_.set_dht_settings(dht_settings_); |
---|
362 | } |
---|
363 | |
---|
364 | if (!dht_on_) |
---|
365 | { |
---|
366 | try |
---|
367 | { |
---|
368 | session_.start_dht(dht_state_); |
---|
369 | dht_on_ = true; |
---|
370 | } |
---|
371 | catch(...) |
---|
372 | {} |
---|
373 | } |
---|
374 | return dht_on_; |
---|
375 | } |
---|
376 | |
---|
377 | void ensure_dht_off() |
---|
378 | { |
---|
379 | if (dht_on_) |
---|
380 | { |
---|
381 | session_.stop_dht(); |
---|
382 | dht_on_ = false; |
---|
383 | } |
---|
384 | } |
---|
385 | |
---|
386 | void set_mapping(bool upnp, bool nat_pmp) |
---|
387 | { |
---|
388 | if (upnp) |
---|
389 | { |
---|
390 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting UPnP mapping."))); |
---|
391 | session_.start_upnp(); |
---|
392 | } |
---|
393 | else |
---|
394 | { |
---|
395 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Stopping UPnP mapping."))); |
---|
396 | session_.stop_upnp(); |
---|
397 | } |
---|
398 | |
---|
399 | if (nat_pmp) |
---|
400 | { |
---|
401 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Starting NAT-PMP mapping."))); |
---|
402 | session_.start_natpmp(); |
---|
403 | } |
---|
404 | else |
---|
405 | { |
---|
406 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Stopping NAT-PMP mapping."))); |
---|
407 | session_.stop_natpmp(); |
---|
408 | } |
---|
409 | } |
---|
410 | |
---|
411 | void set_timeouts(int peers, int tracker) |
---|
412 | { |
---|
413 | libt::session_settings settings = session_.settings(); |
---|
414 | settings.peer_connect_timeout = peers; |
---|
415 | settings.tracker_completion_timeout = tracker; |
---|
416 | |
---|
417 | session_.set_settings(settings); |
---|
418 | |
---|
419 | event_log.post(shared_ptr<EventDetail>(new EventMsg( |
---|
420 | hal::wform(L"Set Timeouts, peer %1%, tracker %2%.") % peers % tracker))); |
---|
421 | } |
---|
422 | |
---|
423 | queue_settings get_queue_settings() |
---|
424 | { |
---|
425 | libt::session_settings settings = session_.settings(); |
---|
426 | queue_settings queue; |
---|
427 | |
---|
428 | queue.auto_manage_interval = settings.auto_manage_interval; |
---|
429 | queue.active_downloads = settings.active_downloads; |
---|
430 | queue.active_seeds = settings.active_seeds; |
---|
431 | queue.seeds_hard_limit = settings.active_limit; |
---|
432 | queue.seed_ratio_limit = settings.share_ratio_limit; |
---|
433 | queue.seed_ratio_time_limit = settings.seed_time_ratio_limit; |
---|
434 | queue.seed_time_limit = settings.seed_time_limit; |
---|
435 | queue.dont_count_slow_torrents = settings.dont_count_slow_torrents; |
---|
436 | queue.auto_scrape_min_interval = settings.auto_scrape_min_interval; |
---|
437 | queue.auto_scrape_interval = settings.auto_scrape_interval; |
---|
438 | queue.close_redundant_connections = settings.close_redundant_connections; |
---|
439 | |
---|
440 | return queue; |
---|
441 | } |
---|
442 | |
---|
443 | void set_queue_settings(const queue_settings& queue) |
---|
444 | { |
---|
445 | libt::session_settings settings = session_.settings(); |
---|
446 | |
---|
447 | settings.auto_manage_interval = queue.auto_manage_interval; |
---|
448 | settings.active_downloads = queue.active_downloads; |
---|
449 | settings.active_seeds = queue.active_seeds; |
---|
450 | settings.active_limit = queue.seeds_hard_limit; |
---|
451 | settings.share_ratio_limit = queue.seed_ratio_limit; |
---|
452 | settings.seed_time_ratio_limit = queue.seed_ratio_time_limit; |
---|
453 | settings.seed_time_limit = queue.seed_time_limit; |
---|
454 | settings.dont_count_slow_torrents = queue.dont_count_slow_torrents; |
---|
455 | settings.auto_scrape_min_interval = queue.auto_scrape_min_interval; |
---|
456 | settings.auto_scrape_interval = queue.auto_scrape_interval; |
---|
457 | settings.close_redundant_connections = queue.close_redundant_connections; |
---|
458 | |
---|
459 | session_.set_settings(settings); |
---|
460 | |
---|
461 | event_log.post(shared_ptr<EventDetail>(new EventMsg( |
---|
462 | hal::wform(L"Set queue parameters, %1% downloads and %2% active seeds.") |
---|
463 | % settings.active_downloads % settings.active_seeds))); |
---|
464 | } |
---|
465 | |
---|
466 | timeouts get_timeouts() |
---|
467 | { |
---|
468 | libt::session_settings settings = session_.settings(); |
---|
469 | timeouts times; |
---|
470 | |
---|
471 | times.tracker_completion_timeout = settings.tracker_completion_timeout; |
---|
472 | times.tracker_receive_timeout = settings.tracker_receive_timeout; |
---|
473 | times.stop_tracker_timeout = settings.stop_tracker_timeout; |
---|
474 | |
---|
475 | times.request_queue_time = settings.request_queue_time; |
---|
476 | times.piece_timeout = settings.piece_timeout; |
---|
477 | times.min_reconnect_time = settings.min_reconnect_time; |
---|
478 | |
---|
479 | times.peer_timeout = settings.peer_timeout; |
---|
480 | times.urlseed_timeout = settings.urlseed_timeout; |
---|
481 | times.peer_connect_timeout = settings.peer_connect_timeout; |
---|
482 | times.inactivity_timeout = settings.inactivity_timeout; |
---|
483 | times.handshake_timeout = settings.handshake_timeout; |
---|
484 | |
---|
485 | return times; |
---|
486 | } |
---|
487 | |
---|
488 | void set_timeouts(const timeouts& times) |
---|
489 | { |
---|
490 | libt::session_settings settings = session_.settings(); |
---|
491 | |
---|
492 | settings.tracker_completion_timeout = times.tracker_completion_timeout; |
---|
493 | settings.tracker_receive_timeout = times.tracker_receive_timeout; |
---|
494 | settings.stop_tracker_timeout = times.stop_tracker_timeout; |
---|
495 | |
---|
496 | settings.request_queue_time = times.request_queue_time; |
---|
497 | settings.piece_timeout = times.piece_timeout; |
---|
498 | settings.min_reconnect_time = times.min_reconnect_time; |
---|
499 | |
---|
500 | settings.peer_timeout = times.peer_timeout; |
---|
501 | settings.urlseed_timeout = times.urlseed_timeout; |
---|
502 | settings.peer_connect_timeout = times.peer_connect_timeout; |
---|
503 | settings.inactivity_timeout = times.inactivity_timeout; |
---|
504 | settings.handshake_timeout = times.handshake_timeout; |
---|
505 | |
---|
506 | session_.set_settings(settings); |
---|
507 | |
---|
508 | event_log.post(shared_ptr<EventDetail>(new EventMsg( |
---|
509 | hal::wform(L"Set timeouts, peers- %1% secs, tracker- %2% secs.") |
---|
510 | % settings.peer_timeout % settings.tracker_receive_timeout))); |
---|
511 | } |
---|
512 | |
---|
513 | void set_session_limits(int maxConn, int maxUpload) |
---|
514 | { |
---|
515 | session_.set_max_uploads(maxUpload); |
---|
516 | session_.set_max_connections(maxConn); |
---|
517 | |
---|
518 | event_log.post(shared_ptr<EventDetail>(new EventMsg( |
---|
519 | hal::wform(L"Set connections totals %1% and uploads %2%.") |
---|
520 | % maxConn % maxUpload))); |
---|
521 | } |
---|
522 | |
---|
523 | void set_session_speed(float download, float upload) |
---|
524 | { |
---|
525 | int down = (download > 0) ? static_cast<int>(download*1024) : -1; |
---|
526 | session_.set_download_rate_limit(down); |
---|
527 | int up = (upload > 0) ? static_cast<int>(upload*1024) : -1; |
---|
528 | session_.set_upload_rate_limit(up); |
---|
529 | |
---|
530 | event_log.post(shared_ptr<EventDetail>(new EventMsg( |
---|
531 | hal::wform(L"Set session rates at download %1% and upload %2%.") |
---|
532 | % session_.download_rate_limit() % session_.upload_rate_limit()))); |
---|
533 | } |
---|
534 | |
---|
535 | bool ensure_ip_filter_on(progress_callback fn) |
---|
536 | { |
---|
537 | try |
---|
538 | { |
---|
539 | |
---|
540 | if (!ip_filter_loaded_) |
---|
541 | { |
---|
542 | ip_filter_load(fn); |
---|
543 | ip_filter_loaded_ = true; |
---|
544 | } |
---|
545 | |
---|
546 | if (!ip_filter_on_) |
---|
547 | { |
---|
548 | session_.set_ip_filter(ip_filter_); |
---|
549 | ip_filter_on_ = true; |
---|
550 | ip_filter_count(); |
---|
551 | } |
---|
552 | |
---|
553 | } |
---|
554 | catch(const std::exception& e) |
---|
555 | { |
---|
556 | hal::event_log.post(boost::shared_ptr<hal::EventDetail>( |
---|
557 | new hal::EventStdException(event_logger::critical, e, L"ensureIpFilterOn"))); |
---|
558 | |
---|
559 | ensure_ip_filter_off(); |
---|
560 | } |
---|
561 | |
---|
562 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters on."))); |
---|
563 | |
---|
564 | return false; |
---|
565 | } |
---|
566 | |
---|
567 | void ensure_ip_filter_off() |
---|
568 | { |
---|
569 | session_.set_ip_filter(libt::ip_filter()); |
---|
570 | ip_filter_on_ = false; |
---|
571 | |
---|
572 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"IP filters off."))); |
---|
573 | } |
---|
574 | |
---|
575 | #ifndef TORRENT_DISABLE_ENCRYPTION |
---|
576 | void ensure_pe_on(const pe_settings& pe_s) |
---|
577 | { |
---|
578 | libt::pe_settings pe; |
---|
579 | |
---|
580 | switch (pe_s.encrypt_level) |
---|
581 | { |
---|
582 | case 0: |
---|
583 | pe.allowed_enc_level = libt::pe_settings::plaintext; |
---|
584 | break; |
---|
585 | case 1: |
---|
586 | pe.allowed_enc_level = libt::pe_settings::rc4; |
---|
587 | break; |
---|
588 | case 2: |
---|
589 | pe.allowed_enc_level = libt::pe_settings::both; |
---|
590 | break; |
---|
591 | default: |
---|
592 | pe.allowed_enc_level = libt::pe_settings::both; |
---|
593 | |
---|
594 | hal::event_log.post(shared_ptr<hal::EventDetail>( |
---|
595 | new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, |
---|
596 | (hal::wform(hal::app().res_wstr(HAL_INCORRECT_ENCODING_LEVEL)) % pe_s.encrypt_level).str()))); |
---|
597 | } |
---|
598 | |
---|
599 | switch (pe_s.conn_in_policy) |
---|
600 | { |
---|
601 | case 0: |
---|
602 | pe.in_enc_policy = libt::pe_settings::forced; |
---|
603 | break; |
---|
604 | case 1: |
---|
605 | pe.in_enc_policy = libt::pe_settings::enabled; |
---|
606 | break; |
---|
607 | case 2: |
---|
608 | pe.in_enc_policy = libt::pe_settings::disabled; |
---|
609 | break; |
---|
610 | default: |
---|
611 | pe.in_enc_policy = libt::pe_settings::enabled; |
---|
612 | |
---|
613 | hal::event_log.post(shared_ptr<hal::EventDetail>( |
---|
614 | new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, |
---|
615 | (hal::wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % pe_s.conn_in_policy).str()))); |
---|
616 | } |
---|
617 | |
---|
618 | switch (pe_s.conn_out_policy) |
---|
619 | { |
---|
620 | case 0: |
---|
621 | pe.out_enc_policy = libt::pe_settings::forced; |
---|
622 | break; |
---|
623 | case 1: |
---|
624 | pe.out_enc_policy = libt::pe_settings::enabled; |
---|
625 | break; |
---|
626 | case 2: |
---|
627 | pe.out_enc_policy = libt::pe_settings::disabled; |
---|
628 | break; |
---|
629 | default: |
---|
630 | pe.out_enc_policy = libt::pe_settings::enabled; |
---|
631 | |
---|
632 | hal::event_log.post(shared_ptr<hal::EventDetail>( |
---|
633 | new hal::EventGeneral(hal::event_logger::warning, hal::event_logger::unclassified, |
---|
634 | (hal::wform(hal::app().res_wstr(HAL_INCORRECT_CONNECT_POLICY)) % pe_s.conn_out_policy).str()))); |
---|
635 | } |
---|
636 | |
---|
637 | pe.prefer_rc4 = pe_s.prefer_rc4; |
---|
638 | |
---|
639 | try |
---|
640 | { |
---|
641 | |
---|
642 | session_.set_pe_settings(pe); |
---|
643 | |
---|
644 | } |
---|
645 | catch(const std::exception& e) |
---|
646 | { |
---|
647 | hal::event_log.post(boost::shared_ptr<hal::EventDetail>( |
---|
648 | new hal::EventStdException(event_logger::critical, e, L"ensurePeOn"))); |
---|
649 | |
---|
650 | ensure_pe_off(); |
---|
651 | } |
---|
652 | |
---|
653 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption on."))); |
---|
654 | } |
---|
655 | |
---|
656 | void ensure_pe_off() |
---|
657 | { |
---|
658 | libt::pe_settings pe; |
---|
659 | pe.out_enc_policy = libt::pe_settings::disabled; |
---|
660 | pe.in_enc_policy = libt::pe_settings::disabled; |
---|
661 | |
---|
662 | pe.allowed_enc_level = libt::pe_settings::both; |
---|
663 | pe.prefer_rc4 = true; |
---|
664 | |
---|
665 | session_.set_pe_settings(pe); |
---|
666 | |
---|
667 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Protocol encryption off."))); |
---|
668 | } |
---|
669 | #endif |
---|
670 | |
---|
671 | void ip_v4_filter_block(boost::asio::ip::address_v4 first, boost::asio::ip::address_v4 last) |
---|
672 | { |
---|
673 | ip_filter_.add_rule(first, last, libt::ip_filter::blocked); |
---|
674 | ip_filter_count(); |
---|
675 | ip_filter_changed_ = true; |
---|
676 | } |
---|
677 | |
---|
678 | void ip_v6_filter_block(boost::asio::ip::address_v6 first, boost::asio::ip::address_v6 last) |
---|
679 | { |
---|
680 | ip_filter_.add_rule(first, last, libt::ip_filter::blocked); |
---|
681 | ip_filter_count(); |
---|
682 | ip_filter_changed_ = true; |
---|
683 | } |
---|
684 | |
---|
685 | size_t ip_filter_size() |
---|
686 | { |
---|
687 | return ip_filter_count_; |
---|
688 | } |
---|
689 | |
---|
690 | void clear_ip_filter() |
---|
691 | { |
---|
692 | ip_filter_ = libt::ip_filter(); |
---|
693 | session_.set_ip_filter(libt::ip_filter()); |
---|
694 | ip_filter_changed_ = true; |
---|
695 | ip_filter_count(); |
---|
696 | } |
---|
697 | |
---|
698 | bool ip_filter_import_dat(boost::filesystem::path file, progress_callback fn, bool octalFix); |
---|
699 | |
---|
700 | struct |
---|
701 | { |
---|
702 | signaler<> successful_listen; |
---|
703 | signaler<> torrent_finished; |
---|
704 | |
---|
705 | boost::signal<bool()> torrent_paused; |
---|
706 | } |
---|
707 | signals; |
---|
708 | |
---|
709 | void start_alert_handler(); |
---|
710 | void stop_alert_handler(); |
---|
711 | void alert_handler(); |
---|
712 | |
---|
713 | void add_torrent(wpath file, wpath saveDirectory, bool startStopped, bit::allocations alloc, |
---|
714 | boost::filesystem::wpath moveToDirectory, bool useMoveTo) |
---|
715 | { |
---|
716 | try |
---|
717 | { |
---|
718 | torrent_internal_ptr TIp; |
---|
719 | |
---|
720 | std::pair<std::string, std::string> names = extract_names(file); |
---|
721 | wstring xml_name = from_utf8(names.first) + L".xml"; |
---|
722 | |
---|
723 | if (false && fs::exists(file.parent_path()/xml_name)) |
---|
724 | { |
---|
725 | torrent_standalone tsa; |
---|
726 | |
---|
727 | if (tsa.load_standalone(file.parent_path()/xml_name)) |
---|
728 | { |
---|
729 | TIp = tsa.torrent; |
---|
730 | |
---|
731 | TIp->set_save_directory(saveDirectory, true); |
---|
732 | if (useMoveTo) |
---|
733 | TIp->set_move_to_directory(moveToDirectory); |
---|
734 | |
---|
735 | TIp->prepare(file); |
---|
736 | } |
---|
737 | } |
---|
738 | |
---|
739 | if (!TIp) |
---|
740 | { |
---|
741 | if (useMoveTo) |
---|
742 | TIp.reset(new torrent_internal(file, saveDirectory, alloc, moveToDirectory)); |
---|
743 | else |
---|
744 | TIp.reset(new torrent_internal(file, saveDirectory, alloc)); |
---|
745 | |
---|
746 | TIp->setTransferSpeed(bittorrent().defTorrentDownload(), bittorrent().defTorrentUpload()); |
---|
747 | TIp->setConnectionLimit(bittorrent().defTorrentMaxConn(), bittorrent().defTorrentMaxUpload()); |
---|
748 | } |
---|
749 | |
---|
750 | std::pair<TorrentManager::torrentByName::iterator, bool> p = |
---|
751 | the_torrents_.insert(TIp); |
---|
752 | |
---|
753 | if (p.second) |
---|
754 | { |
---|
755 | torrent_internal_ptr me = the_torrents_.get(TIp->name()); |
---|
756 | |
---|
757 | if (!startStopped) |
---|
758 | me->add_to_session(); |
---|
759 | else |
---|
760 | me->set_state_stopped(); |
---|
761 | } |
---|
762 | |
---|
763 | } |
---|
764 | catch (const std::exception& e) |
---|
765 | { |
---|
766 | event_log.post(shared_ptr<EventDetail>( |
---|
767 | new EventTorrentException(event_logger::critical, event_logger::torrentException, |
---|
768 | std::string(e.what()), to_utf8(file.string()), std::string("addTorrent")))); |
---|
769 | } |
---|
770 | } |
---|
771 | #if 0 |
---|
772 | std::pair<boost::intrusive_ptr<libt::torrent_info>, libt::entry> prep_torrent(wpath filename, wpath saveDirectory) |
---|
773 | { |
---|
774 | libt::torrent_info info(path_to_utf8(filename)); |
---|
775 | |
---|
776 | wstring torrentName = hal::from_utf8_safe(info.name()); |
---|
777 | if (!boost::find_last(torrentName, L".torrent")) |
---|
778 | torrentName += L".torrent"; |
---|
779 | |
---|
780 | wpath torrentFilename = torrentName; |
---|
781 | const wpath resumeFile = hal::app().get_working_directory()/L"resume"/torrentFilename.filename(); |
---|
782 | |
---|
783 | // vvv Handle old naming style! |
---|
784 | const wpath oldResumeFile = hal::app().get_working_directory()/L"resume"/filename.filename(); |
---|
785 | |
---|
786 | if (filename.filename() != torrentFilename.filename() && exists(oldResumeFile)) |
---|
787 | fs::rename(oldResumeFile, resumeFile); |
---|
788 | // ^^^ Handle old naming style! |
---|
789 | |
---|
790 | libt::entry resumeData; |
---|
791 | |
---|
792 | if (fs::exists(resumeFile)) |
---|
793 | { |
---|
794 | try |
---|
795 | { |
---|
796 | resumeData = haldecode(resumeFile); |
---|
797 | } |
---|
798 | catch(std::exception &e) |
---|
799 | { |
---|
800 | hal::event_log.post(boost::shared_ptr<hal::EventDetail>( |
---|
801 | new hal::EventStdException(event_logger::critical, e, L"prepTorrent, Resume"))); |
---|
802 | |
---|
803 | fs::remove(resumeFile); |
---|
804 | } |
---|
805 | } |
---|
806 | |
---|
807 | if (!fs::exists(hal::app().get_working_directory()/L"torrents")) |
---|
808 | fs::create_directory(hal::app().get_working_directory()/L"torrents"); |
---|
809 | |
---|
810 | if (!fs::exists(hal::app().get_working_directory()/L"torrents"/torrentFilename.filename())) |
---|
811 | fs::copy_file(filename.string(), hal::app().get_working_directory()/L"torrents"/torrentFilename.filename()); |
---|
812 | |
---|
813 | if (!fs::exists(saveDirectory)) |
---|
814 | fs::create_directory(saveDirectory); |
---|
815 | |
---|
816 | return std::make_pair(info, resumeData); |
---|
817 | } |
---|
818 | #endif |
---|
819 | void removal_thread(torrent_internal_ptr pIT, bool wipeFiles) |
---|
820 | { |
---|
821 | try { |
---|
822 | |
---|
823 | if (!wipeFiles) |
---|
824 | { |
---|
825 | session_.remove_torrent(pIT->handle()); |
---|
826 | } |
---|
827 | else |
---|
828 | { |
---|
829 | if (pIT->in_session()) |
---|
830 | { |
---|
831 | session_.remove_torrent(pIT->handle(), libt::session::delete_files); |
---|
832 | } |
---|
833 | else |
---|
834 | { |
---|
835 | //libt::torrent_info m_info = pIT->infoMemory(); |
---|
836 | |
---|
837 | /* // delete the files from disk |
---|
838 | std::string error; |
---|
839 | std::set<std::string> directories; |
---|
840 | |
---|
841 | for (libt::torrent_info::file_iterator i = m_info.begin_files(true) |
---|
842 | , end(m_info.end_files(true)); i != end; ++i) |
---|
843 | { |
---|
844 | std::string p = (hal::path_to_utf8(pIT->saveDirectory()) / i->path).string(); |
---|
845 | fs::path bp = i->path.parent_path(); |
---|
846 | |
---|
847 | std::pair<std::set<std::string>::iterator, bool> ret; |
---|
848 | ret.second = true; |
---|
849 | while (ret.second && !bp.empty()) |
---|
850 | { |
---|
851 | std::pair<std::set<std::string>::iterator, bool> ret = |
---|
852 | directories.insert((hal::path_to_utf8(pIT->saveDirectory()) / bp).string()); |
---|
853 | bp = bp.parent_path(); |
---|
854 | } |
---|
855 | if (!fs::remove(hal::from_utf8(p).c_str()) && errno != ENOENT) |
---|
856 | error = std::strerror(errno); |
---|
857 | } |
---|
858 | |
---|
859 | // remove the directories. Reverse order to delete subdirectories first |
---|
860 | |
---|
861 | for (std::set<std::string>::reverse_iterator i = directories.rbegin() |
---|
862 | , end(directories.rend()); i != end; ++i) |
---|
863 | { |
---|
864 | if (!fs::remove(hal::from_utf8(*i).c_str()) && errno != ENOENT) |
---|
865 | error = std::strerror(errno); |
---|
866 | } |
---|
867 | */ |
---|
868 | } |
---|
869 | } |
---|
870 | |
---|
871 | } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "removalThread") |
---|
872 | } |
---|
873 | |
---|
874 | void remove_torrent(const wstring& filename) |
---|
875 | { |
---|
876 | try { |
---|
877 | |
---|
878 | torrent_internal_ptr pTI = the_torrents_.get(filename); |
---|
879 | libt::torrent_handle handle = pTI->handle(); |
---|
880 | the_torrents_.erase(filename); |
---|
881 | |
---|
882 | thread_t t(bind(&bit_impl::removal_thread, this, pTI, false)); |
---|
883 | |
---|
884 | } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "remove_torrent") |
---|
885 | } |
---|
886 | |
---|
887 | void remove_torrent_wipe_files(const std::wstring& filename) |
---|
888 | { |
---|
889 | try { |
---|
890 | |
---|
891 | torrent_internal_ptr pTI = the_torrents_.get(filename); |
---|
892 | libt::torrent_handle handle = pTI->handle(); |
---|
893 | the_torrents_.erase(filename); |
---|
894 | |
---|
895 | thread_t t(bind(&bit_impl::removal_thread, this, pTI, true)); |
---|
896 | |
---|
897 | } HAL_GENERIC_TORRENT_EXCEPTION_CATCH(filename, "remove_torrent_wipe_files") |
---|
898 | } |
---|
899 | |
---|
900 | void resume_all() |
---|
901 | { |
---|
902 | try { |
---|
903 | |
---|
904 | event_log.post(shared_ptr<EventDetail>(new EventMsg(L"Resuming torrent."))); |
---|
905 | |
---|
906 | for (TorrentManager::torrentByName::iterator i=the_torrents_.begin(), e=the_torrents_.end(); i != e;) |
---|
907 | { |
---|
908 | wpath file = wpath(hal::app().get_working_directory())/L"torrents"/(*i).torrent->filename(); |
---|
909 | |
---|
910 | if (exists(file)) |
---|
911 | { |
---|
912 | try |
---|
913 | { |
---|
914 | |
---|
915 | (*i).torrent->prepare(file); |
---|
916 | |
---|
917 | switch ((*i).torrent->state()) |
---|
918 | { |
---|
919 | case torrent_details::torrent_stopped: |
---|
920 | break; |
---|
921 | case torrent_details::torrent_paused: |
---|
922 | (*i).torrent->add_to_session(true); |
---|
923 | break; |
---|
924 | case torrent_details::torrent_active: |
---|
925 | (*i).torrent->add_to_session(false); |
---|
926 | break; |
---|
927 | default: |
---|
928 | assert(false); |
---|
929 | }; |
---|
930 | |
---|
931 | ++i; |
---|
932 | |
---|
933 | } |
---|
934 | catch(const libt::duplicate_torrent&) |
---|
935 | { |
---|
936 | hal::event_log.post(shared_ptr<hal::EventDetail>( |
---|
937 | new hal::EventDebug(hal::event_logger::debug, L"Encountered duplicate torrent"))); |
---|
938 | |
---|
939 | ++i; // Harmless, don't worry about it. |
---|
940 | } |
---|
941 | catch(const std::exception& e) |
---|
942 | { |
---|
943 | hal::event_log.post(shared_ptr<hal::EventDetail>( |
---|
944 | new hal::EventStdException(hal::event_logger::warning, e, L"resumeAll"))); |
---|
945 | |
---|
946 | the_torrents_.erase(i++); |
---|
947 | } |
---|
948 | } |
---|
949 | else |
---|
950 | { |
---|
951 | the_torrents_.erase(i++); |
---|
952 | } |
---|
953 | } |
---|
954 | |
---|
955 | } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll") |
---|
956 | } |
---|
957 | |
---|
958 | void close_all(boost::optional<report_num_active> fn) |
---|
959 | { |
---|
960 | try |
---|
961 | { |
---|
962 | event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Saving torrent data..."))); |
---|
963 | |
---|
964 | save_torrent_data(); |
---|
965 | |
---|
966 | event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Stopping all torrents..."))); |
---|
967 | |
---|
968 | for (TorrentManager::torrentByName::iterator i=the_torrents_.begin(), e=the_torrents_.end(); |
---|
969 | i != e; ++i) |
---|
970 | { |
---|
971 | (*i).torrent->stop(); |
---|
972 | } |
---|
973 | |
---|
974 | // Ok this polling loop here is a bit curde, but a blocking wait is actually appropiate. |
---|
975 | for (int num_active = -1; num_active != 0; ) |
---|
976 | { |
---|
977 | num_active = 0; |
---|
978 | |
---|
979 | for (TorrentManager::torrentByName::iterator i=the_torrents_.begin(), e=the_torrents_.end(); |
---|
980 | i != e; ++i) |
---|
981 | { |
---|
982 | if ((*i).torrent->state() != torrent_details::torrent_stopped) |
---|
983 | ++num_active; |
---|
984 | } |
---|
985 | |
---|
986 | event_log.post(shared_ptr<EventDetail>(new EventInfo(hal::wform(L"%1% still active") % num_active))); |
---|
987 | |
---|
988 | if (fn) (*fn)(num_active); |
---|
989 | Sleep(200); |
---|
990 | } |
---|
991 | |
---|
992 | event_log.post(shared_ptr<EventDetail>(new EventInfo(L"All torrents stopped."))); |
---|
993 | event_log.post(shared_ptr<EventDetail>(new EventInfo(L"Fast-resume data written."))); |
---|
994 | |
---|
995 | } HAL_GENERIC_TORRENT_EXCEPTION_CATCH("Torrent Unknown!", "closeAll") |
---|
996 | } |
---|
997 | |
---|
998 | void save_torrent_data() |
---|
999 | { |
---|
1000 | mutex_t::scoped_lock l(mutex_); |
---|
1001 | try |
---|
1002 | { |
---|
1003 | |
---|
1004 | the_torrents_.save_to_ini(); |
---|
1005 | bittorrentIni.save_data(); |
---|
1006 | |
---|
1007 | if (dht_on_) |
---|
1008 | { |
---|
1009 | halencode(hal::app().get_working_directory()/L"DHTState.bin", session_.dht_state()); |
---|
1010 | } |
---|
1011 | |
---|
1012 | } |
---|
1013 | catch(std::exception& e) |
---|
1014 | { |
---|
1015 | event_log.post(shared_ptr<EventDetail>(\ |
---|
1016 | new EventStdException(event_logger::critical, e, L"saveTorrentData"))); |
---|
1017 | } |
---|
1018 | } |
---|
1019 | |
---|
1020 | int defTorrentMaxConn() { return defTorrentMaxConn_; } |
---|
1021 | int defTorrentMaxUpload() { return defTorrentMaxUpload_; } |
---|
1022 | float defTorrentDownload() { return defTorrentDownload_; } |
---|
1023 | float defTorrentUpload() { return defTorrentUpload_; } |
---|
1024 | |
---|
1025 | private: |
---|
1026 | bool create_torrent(const create_torrent_params& params, fs::wpath out_file, progress_callback fn); |
---|
1027 | |
---|
1028 | libt::session session_; |
---|
1029 | mutable mutex_t mutex_; |
---|
1030 | |
---|
1031 | boost::optional<thread_t> alert_checker_; |
---|
1032 | bool keepChecking_; |
---|
1033 | |
---|
1034 | ini_file bittorrentIni; |
---|
1035 | TorrentManager the_torrents_; |
---|
1036 | |
---|
1037 | int defTorrentMaxConn_; |
---|
1038 | int defTorrentMaxUpload_; |
---|
1039 | float defTorrentDownload_; |
---|
1040 | float defTorrentUpload_; |
---|
1041 | |
---|
1042 | bool ip_filter_on_; |
---|
1043 | bool ip_filter_loaded_; |
---|
1044 | bool ip_filter_changed_; |
---|
1045 | libt::ip_filter ip_filter_; |
---|
1046 | size_t ip_filter_count_; |
---|
1047 | |
---|
1048 | void ip_filter_count(); |
---|
1049 | void ip_filter_load(progress_callback fn); |
---|
1050 | void ip_filter_import(std::vector<libt::ip_range<boost::asio::ip::address_v4> >& v4, |
---|
1051 | std::vector<libt::ip_range<boost::asio::ip::address_v6> >& v6); |
---|
1052 | |
---|
1053 | bool dht_on_; |
---|
1054 | libt::dht_settings dht_settings_; |
---|
1055 | libt::entry dht_state_; |
---|
1056 | }; |
---|
1057 | |
---|
1058 | } |
---|