88#include < iostream>
99#include < thread>
1010
11+ #include < libtorrent/version.hpp>
1112#include < libtorrent/add_torrent_params.hpp>
1213#include < libtorrent/alert_types.hpp>
1314#include < libtorrent/bencode.hpp>
1415#include < libtorrent/create_torrent.hpp>
1516#include < libtorrent/fingerprint.hpp>
1617#include < libtorrent/session.hpp>
18+ #if LIBTORRENT_VERSION_NUM < 10200
1719#include < libtorrent/session_settings.hpp>
20+ #else
21+ #include < libtorrent/settings_pack.hpp>
22+ #include < libtorrent/torrent_flags.hpp> // lt::torrent_flags::paused
23+ #include < libtorrent/magnet_uri.hpp> // lt::parse_magnet_uri()
24+ // struct lt::aux::session_impl::session_plugin_wrapper:
25+ #include < libtorrent/aux_/session_impl.hpp>
26+ // lt::create_ut_metadata_plugin():
27+ #include < libtorrent/extensions/ut_metadata.hpp>
28+ // lt::create_ut_pex_plugin():
29+ #include < libtorrent/extensions/ut_pex.hpp>
30+ // lt::create_smart_ban_plugin():
31+ #include < libtorrent/extensions/smart_ban.hpp>
32+ #endif
1833#include < libtorrent/storage_defs.hpp> // lt::disabled_storage_constructor
1934#include < libtorrent/torrent_handle.hpp>
2035#include < libtorrent/torrent_info.hpp>
@@ -23,7 +38,8 @@ static int usage(const char *argv0) {
2338 std::cerr << " usage: [options] " << argv0 << " <magnet-url>" <<
2439 std::endl;
2540 std::cerr << " where options are:" << std::endl;
26- std::cerr << " -a, --anonymous anonymous mode" << std::endl;
41+ std::cerr << " -a, --anonymous anonymous mode"
42+ << " via socks5://localhost:9050" << std::endl;
2743 std::cerr << " -t, --tcp TCP mode" << std::endl;
2844 std::cerr << " -u, --udp UDP mode (specifying both"
2945 << " -t and -u enables both protocols" << std::endl;
@@ -36,11 +52,16 @@ namespace lt = libtorrent;
3652int main (int argc, char *argv[]) {
3753 std::set_terminate (__gnu_cxx::__verbose_terminate_handler);
3854
55+ #if LIBTORRENT_VERSION_NUM < 10200
3956 lt::session_settings sset;
40- lt::add_torrent_params atp;
57+ #else
58+ lt::settings_pack spack;
59+ #endif
4160 int sess_tcp_udp = 0 ;
61+ int sess_anon = 0 ;
4262 char *magnet_url = NULL ;
4363
64+ // Parse cmdline options and args:
4465 for (;;) {
4566 static struct option lopts[] = {
4667 {" anonymous" , no_argument, NULL , ' a' },
@@ -51,66 +72,114 @@ int main(int argc, char *argv[]) {
5172 int c = getopt_long (argc, argv, " atu" , lopts, &loptind);
5273 if (c == -1 ) break ;
5374 switch (c) {
54- case ' a' : sset. anonymous_mode = true ; break ;
55- case ' t' : sess_tcp_udp |= 1 ; break ;
56- case ' u' : sess_tcp_udp |= 2 ; break ;
57- default : return usage (argv[0 ]);;
75+ case ' a' : sess_anon = 1 ; break ;
76+ case ' t' : sess_tcp_udp |= 1 ; break ;
77+ case ' u' : sess_tcp_udp |= 2 ; break ;
78+ default : return usage (argv[0 ]);
5879 }
5980 }
6081 if (argc - optind != 1 ) return usage (argv[0 ]);
61- atp.url = argv[optind];
62- switch (sess_tcp_udp) {
63- case 0 :
64- sset.prefer_udp_trackers = false ;
65- sset.enable_outgoing_tcp = true ;
66- sset.enable_incoming_tcp = true ;
67- sset.enable_outgoing_utp = true ;
68- sset.enable_incoming_utp = true ;
69- break ;
70- case 1 :
71- sset.prefer_udp_trackers = false ;
72- sset.enable_outgoing_tcp = true ;
73- sset.enable_incoming_tcp = true ;
74- sset.enable_outgoing_utp = false ;
75- sset.enable_incoming_utp = false ;
76- break ;
77- case 2 :
78- sset.prefer_udp_trackers = true ;
79- sset.enable_outgoing_tcp = false ;
80- sset.enable_incoming_tcp = false ;
81- sset.enable_outgoing_utp = true ;
82- sset.enable_incoming_utp = true ;
83- break ;
84- case 3 :
85- sset.prefer_udp_trackers = true ;
86- sset.enable_outgoing_tcp = true ;
87- sset.enable_incoming_tcp = true ;
88- sset.enable_outgoing_utp = true ;
89- sset.enable_incoming_utp = true ;
90- break ;
91- }
82+ magnet_url = argv[optind];
83+
84+ // Init session settings:
85+ #if LIBTORRENT_VERSION_NUM < 10200
86+ sset.prefer_udp_trackers = sess_tcp_udp & 2 ? true : false ;
87+ sset.enable_outgoing_tcp = sess_tcp_udp == 2 ? false : true ;
88+ sset.enable_incoming_tcp = sess_tcp_udp == 2 ? false : true ;
89+ sset.enable_outgoing_utp = sess_tcp_udp == 1 ? false : true
90+ sset.enable_incoming_utp = sess_tcp_udp == 1 ? false : true ;
91+ sset.anonymous_mode = sess_anon ? true : false ;
92+ #else
93+ spack.set_bool (lt::settings_pack::prefer_udp_trackers,
94+ sess_tcp_udp & 2 ? true : false );
95+ spack.set_bool (lt::settings_pack::enable_outgoing_tcp,
96+ sess_tcp_udp == 2 ? false : true );
97+ spack.set_bool (lt::settings_pack::enable_incoming_tcp,
98+ sess_tcp_udp == 2 ? false : true );
99+ spack.set_bool (lt::settings_pack::enable_outgoing_utp,
100+ sess_tcp_udp == 1 ? false : true );
101+ spack.set_bool (lt::settings_pack::enable_incoming_utp,
102+ sess_tcp_udp == 1 ? false : true );
103+ spack.set_str (lt::settings_pack::peer_fingerprint,
104+ lt::generate_fingerprint (" LT" , 0 , 0 , 0 , 0 ));
105+ spack.set_str (lt::settings_pack::user_agent,
106+ " libtorrent/" LIBTORRENT_VERSION);
107+ if (sess_anon == 1 ) {
108+ spack.set_str (lt::settings_pack::proxy_hostname,
109+ " 127.0.0.1" );
110+ spack.set_int (lt::settings_pack::proxy_port, 9050 );
111+ spack.set_int (lt::settings_pack::proxy_type,
112+ lt::settings_pack::proxy_type_t ::socks5);
113+ // External listen interfaces are not needed when going via
114+ // 127.0.0.1:9050 (in fact, internal aren't too, but there's
115+ // no way to stop libtorrent from trying to bind to
116+ // something):
117+ spack.set_str (lt::settings_pack::listen_interfaces,
118+ " 127.0.0.1:6881" );
119+ // Connect only via proxy:
120+ spack.set_bool (lt::settings_pack::anonymous_mode, true );
121+ spack.set_bool (lt::settings_pack::proxy_peer_connections,
122+ true );
123+ spack.set_bool (lt::settings_pack::proxy_tracker_connections,
124+ true );
125+ // Resolve DNS via proxy:
126+ spack.set_bool (lt::settings_pack::proxy_hostnames, true );
127+ };
128+ // lt::session::start_default_features flag causes these to be set
129+ // to true, but neither is necessary for converting magnet: link
130+ // into .torrent file:
131+ spack.set_bool (lt::settings_pack::enable_upnp, false );
132+ spack.set_bool (lt::settings_pack::enable_natpmp, false );
133+ spack.set_bool (lt::settings_pack::enable_lsd, false );
134+ spack.set_bool (lt::settings_pack::enable_dht, false );
135+ #endif
92136
137+ #if LIBTORRENT_VERSION_NUM < 10200
93138 lt::session sess (lt::fingerprint (" LT" , 0 , 0 , 0 , 0 ),
94139 lt::session::add_default_plugins);
95140 sess.set_settings (sset);
141+ lt::add_torrent_params atp;
96142 atp.upload_mode = true ;
97143 atp.auto_managed = false ;
98144 atp.paused = false ;
99- // Start with "storage == disabled" to avoid pre-allocating any files
100- // mentioned in the torrent file on disk:
101- atp.storage = lt::disabled_storage_constructor;
102- atp.save_path = " ." ; // save in current dir
103145 /*
104146 // .flags duplicate .upload_mode/auto_managed/paused
105147 // functionality:
106148 atp.flags = lt::add_torrent_params::flag_update_subscribe
107149 | lt::add_torrent_params::flag_upload_mode
108150 | lt::add_torrent_params::flag_apply_ip_filter;
109151 */
152+ #else
153+ // Create session_params and session. The ut_metadata extension
154+ // (plugin) is requited to get .torrent metadata via magnet: link,
155+ // but the other two default plugins (ut_pex and smart_ban) aren't.
156+ using plgnwrp = lt::aux::session_impl::session_plugin_wrapper;
157+ std::vector<std::shared_ptr<lt::plugin>> exts;
158+ exts.push_back (
159+ std::make_shared<plgnwrp>(<::create_ut_metadata_plugin));
160+ lt::session_params sparams (spack, exts);
161+ // sparams.disk_io_constructor = lt::disabled_disk_io_constructor();
162+ lt::session sess (sparams);
163+ // sess.add_extension(<::create_ut_pex_plugin);
164+ // sess.add_extension(<::create_smart_ban_plugin);
165+ lt::add_torrent_params atp = lt::parse_magnet_uri (magnet_url);
166+ atp.flags = lt::torrent_flags::upload_mode
167+ | lt::torrent_flags::auto_managed
168+ | lt::torrent_flags::paused;
169+ #endif
170+ // Start loading torrent metadata with "storage == disabled" to avoid
171+ // pre-allocating any files mentioned in the torrent file on disk:
172+ atp.storage = lt::disabled_storage_constructor;
173+ atp.save_path = " ." ; // save in current dir
174+
110175 lt::torrent_handle torh = sess.add_torrent (atp);
111- std::cout << atp. url << " :" ;
176+ std::cout << magnet_url << " :" ;
112177 for (;;) {
178+ #if LIBTORRENT_VERSION_NUM < 10200
113179 std::deque<lt::alert*> alerts;
180+ #else
181+ std::vector<lt::alert*> alerts;
182+ #endif
114183 sess.pop_alerts (&alerts);
115184 for (lt::alert const * a : alerts) {
116185 std::cout << std::endl << a->message () << std::endl;
@@ -122,18 +191,30 @@ int main(int argc, char *argv[]) {
122191 }
123192 if (torh.status ().has_metadata ) {
124193 sess.pause ();
194+ #if LIBTORRENT_VERSION_NUM < 10200
125195 lt::torrent_info tinf =
126196 torh.get_torrent_info ();
127- std::cout << tinf.name () << std::endl;
197+ const std::string &tname = tinf.name ();
198+ #else
199+ std::shared_ptr<const lt::torrent_info> tinf =
200+ torh.torrent_file ();
201+ const std::string &tname = tinf->name ();
202+ #endif
203+ std::cout << tname << std::endl;
128204 std::cout.flush ();
129205 std::ofstream ofs;
130206 ofs.exceptions (std::ofstream::failbit
131207 | std::ofstream::badbit);
132- ofs.open (tinf. name () + " .torrent" ,
208+ ofs.open (tname + " .torrent" ,
133209 std::ofstream::binary);
134210 std::ostream_iterator<char > ofsi (ofs);
211+ #if LIBTORRENT_VERSION_NUM < 10200
135212 lt::bencode (ofsi, lt::create_torrent (tinf)
136213 .generate ());
214+ #else
215+ lt::bencode (ofsi, lt::create_torrent (*tinf)
216+ .generate ());
217+ #endif
137218 ofs.close ();
138219 sess.remove_torrent (torh);
139220 goto done0;
0 commit comments