diff --git a/ChangeLog b/ChangeLog index d5e3aa6ed..716298b5e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -82,6 +82,8 @@ * resume data no longer has timestamps of files * require C++11 to build libtorrent +1.1.6 release + * deprecate save_encryption_settings (they are part of the normal settings) * add getters for peer_class_filter and peer_class_type_filter * make torrent_handler::set_priority() to use peer_classes diff --git a/build_dist.sh b/build_dist.sh index 8269755c4..a03cbe4e2 100755 --- a/build_dist.sh +++ b/build_dist.sh @@ -1,25 +1,15 @@ #!/bin/sh -make clean +set -e +set -x + +python tools/clean.py cd docs -make clean -make RST2HTML=rst2html.py +make RST2HTML=rst2html-2.7.py cd .. -#clear out any extended attributes that Finder may add -sudo xattr -r -d com.apple.FinderInfo * - -rm -f config.log config.report configure rm -f m4/libtool.m4 m4/lt~obsolete.m4 m4/ltsugar.m4 m4/ltversion.m4 m4/ltoptions.m4 -rm -fr autom4te.cache build-aux -rm -f Makefile Makefile.in -rm -f src/Makefile src/Makefile.in -rm -f include/libtorrent/Makefile include/libtorrent/Makefile.in -rm -f examples/Makefile examples/Makefile.in examples/.dep examples/.libs -rm -rf test/Makefile test/Makefile.in test/.dep test/.lib -rm -rf bindings/Makefile bindings/Makefile.in bindings/.dep bindings/.libs -rm -f bindings/python/Makefile bindings/python/Makefile.in chmod a-x docs/*.rst docs/*.htm* src/*.cpp include/libtorrent/*.hpp ./autotool.sh diff --git a/docs/features.rst b/docs/features.rst index f81c0e1ca..ce8154790 100644 --- a/docs/features.rst +++ b/docs/features.rst @@ -292,11 +292,8 @@ code to implement a simple bittorrent client:: // usage a.out [torrent-file] int main(int argc, char* argv[]) try { - using namespace libtorrent; - - session s; - s.listen_on(std::make_pair(6881, 6889)); - add_torrent_params p; + lt::session s; + lt::add_torrent_params p; p.save_path = "./"; p.ti = new torrent_info(argv[1]); s.add_torrent(p); @@ -324,10 +321,10 @@ portability libtorrent runs on most major operating systems, including Windows, MacOS X, Linux, BSD and Solaris. -It uses Boost.Thread, Boost.Filesystem, Boost.Date_time and various other -boost libraries. At least version 1.46.1 of boost is required. +It uses Boost.Thread, Boost.Asio, Boost.Chrono, Boost.Random, Boost.Date_time +and various other boost libraries. At least version 1.49 of boost is required. -libtorrent uses asio, hence it will take full advantage of high performance +Since libtorrent uses Boost.Asio it will take full advantage of high performance network APIs on the most popular platforms. I/O completion ports on windows, epoll on linux and kqueue on MacOS X and BSD. diff --git a/examples/dump_torrent.cpp b/examples/dump_torrent.cpp index 37f6eb329..86fb288dd 100644 --- a/examples/dump_torrent.cpp +++ b/examples/dump_torrent.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003, Arvid Norberg +Copyright (c) 2003-2017, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -40,74 +40,26 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/bdecode.hpp" #include "libtorrent/magnet_uri.hpp" -int load_file(std::string const& filename, std::vector& v - , lt::error_code& ec, int limit = 8000000) +#include +#include + +std::vector load_file(std::string const& filename) { - ec.clear(); - FILE* f = std::fopen(filename.c_str(), "rb"); - if (f == nullptr) - { - ec.assign(errno, boost::system::system_category()); - return -1; - } - - int r = fseek(f, 0, SEEK_END); - if (r != 0) - { - ec.assign(errno, boost::system::system_category()); - std::fclose(f); - return -1; - } - long s = ftell(f); - if (s < 0) - { - ec.assign(errno, boost::system::system_category()); - std::fclose(f); - return -1; - } - - if (s > limit) - { - std::fclose(f); - return -2; - } - - r = fseek(f, 0, SEEK_SET); - if (r != 0) - { - ec.assign(errno, boost::system::system_category()); - std::fclose(f); - return -1; - } - - v.resize(s); - if (s == 0) - { - std::fclose(f); - return 0; - } - - r = int(fread(&v[0], 1, v.size(), f)); - if (r < 0) - { - ec.assign(errno, boost::system::system_category()); - std::fclose(f); - return -1; - } - - std::fclose(f); - - if (r != s) return -3; - - return 0; + std::vector ret; + std::fstream in; + in.exceptions(std::ifstream::failbit); + in.open(filename.c_str(), std::ios_base::in | std::ios_base::binary); + in.seekg(0, std::ios_base::end); + auto const size = in.tellg(); + in.seekg(0, std::ios_base::beg); + ret.resize(static_cast(size)); + in.read(ret.data(), ret.size()); + return ret; } -int main(int argc, char* argv[]) +int main(int argc, char* argv[]) try { - using namespace lt; - - if (argc < 2 || argc > 4) - { + if (argc < 2 || argc > 4) { fputs("usage: dump_torrent torrent-file [total-items-limit] [recursion-limit]\n", stderr); return 1; } @@ -118,41 +70,23 @@ int main(int argc, char* argv[]) if (argc > 2) item_limit = atoi(argv[2]); if (argc > 3) depth_limit = atoi(argv[3]); - std::vector buf; - error_code ec; - int ret = load_file(argv[1], buf, ec, 40 * 1000000); - if (ret == -1) - { - std::fprintf(stderr, "file too big, aborting\n"); - return 1; - } - - if (ret != 0) - { - std::fprintf(stderr, "failed to load file: %s\n", ec.message().c_str()); - return 1; - } - bdecode_node e; + std::vector buf = load_file(argv[1]); + lt::bdecode_node e; int pos = -1; - std::printf("decoding. recursion limit: %d total item count limit: %d\n" - , depth_limit, item_limit); - ret = bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos + lt::error_code ec; + std::cout << "decoding. recursion limit: " << depth_limit + << " total item count limit: " << item_limit << "\n"; + int const ret = lt::bdecode(&buf[0], &buf[0] + buf.size(), e, ec, &pos , depth_limit, item_limit); std::printf("\n\n----- raw info -----\n\n%s\n", print_entry(e).c_str()); - if (ret != 0) - { - std::fprintf(stderr, "failed to decode: '%s' at character: %d\n", ec.message().c_str(), pos); + if (ret != 0) { + std::cerr << "failed to decode: '" << ec.message() << "' at character: " << pos<< "\n"; return 1; } - torrent_info t(e, ec); - if (ec) - { - std::fprintf(stderr, "%s\n", ec.message().c_str()); - return 1; - } + lt::torrent_info const t(e); e.clear(); std::vector().swap(buf); @@ -185,11 +119,11 @@ int main(int argc, char* argv[]) , make_magnet_uri(t).c_str() , t.name().c_str() , t.num_files()); - file_storage const& st = t.files(); - for (file_index_t i(0); i < file_index_t(st.num_files()); ++i) + lt::file_storage const& st = t.files(); + for (lt::file_index_t i(0); i < lt::file_index_t(st.num_files()); ++i) { - piece_index_t const first = st.map_file(i, 0, 0).piece; - piece_index_t const last = st.map_file(i, (std::max)(std::int64_t(st.file_size(i))-1, std::int64_t(0)), 0).piece; + lt::piece_index_t const first = st.map_file(i, 0, 0).piece; + lt::piece_index_t const last = st.map_file(i, (std::max)(std::int64_t(st.file_size(i))-1, std::int64_t(0)), 0).piece; auto const flags = st.file_flags(i); std::stringstream file_hash; if (!st.hash(i).is_all_zeros()) @@ -197,25 +131,29 @@ int main(int argc, char* argv[]) std::printf(" %8" PRIx64 " %11" PRId64 " %c%c%c%c [ %5d, %5d ] %7u %s %s %s%s\n" , st.file_offset(i) , st.file_size(i) - , ((flags & file_storage::flag_pad_file)?'p':'-') - , ((flags & file_storage::flag_executable)?'x':'-') - , ((flags & file_storage::flag_hidden)?'h':'-') - , ((flags & file_storage::flag_symlink)?'l':'-') + , ((flags & lt::file_storage::flag_pad_file)?'p':'-') + , ((flags & lt::file_storage::flag_executable)?'x':'-') + , ((flags & lt::file_storage::flag_hidden)?'h':'-') + , ((flags & lt::file_storage::flag_symlink)?'l':'-') , static_cast(first) , static_cast(last) , std::uint32_t(st.mtime(i)) , file_hash.str().c_str() , st.file_path(i).c_str() - , (flags & file_storage::flag_symlink) ? "-> " : "" - , (flags & file_storage::flag_symlink) ? st.symlink(i).c_str() : ""); + , (flags & lt::file_storage::flag_symlink) ? "-> " : "" + , (flags & lt::file_storage::flag_symlink) ? st.symlink(i).c_str() : ""); } std::printf("web seeds:\n"); for (auto const& ws : t.web_seeds()) { std::printf("%s %s\n" - , ws.type == web_seed_entry::url_seed ? "BEP19" : "BEP17" + , ws.type == lt::web_seed_entry::url_seed ? "BEP19" : "BEP17" , ws.url.c_str()); } return 0; } +catch (std::exception const& e) +{ + std::cerr << "ERROR: " << e.what() << "\n"; +} diff --git a/examples/make_torrent.cpp b/examples/make_torrent.cpp index 205b6607e..1d582575f 100644 --- a/examples/make_torrent.cpp +++ b/examples/make_torrent.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2006, Arvid Norberg +Copyright (c) 2006-2017, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -42,12 +42,12 @@ POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #ifdef TORRENT_WINDOWS #include // for _getcwd #endif -using namespace lt; using namespace std::placeholders; std::vector load_file(std::string const& filename) @@ -112,7 +112,7 @@ bool file_filter(std::string const& f) return true; } -void print_progress(piece_index_t i, int num) +void print_progress(lt::piece_index_t i, int num) { std::fprintf(stderr, "\r%d/%d", static_cast(i)+1, num); } @@ -159,227 +159,193 @@ void print_usage() , stderr); } -int main(int argc, char* argv[]) +int main(int argc, char* argv[]) try { - using namespace lt; - std::string creator_str = "libtorrent"; std::string comment_str; - if (argc < 2) - { + if (argc < 2) { print_usage(); return 1; } -#ifndef BOOST_NO_EXCEPTIONS - try - { -#endif - std::vector web_seeds; - std::vector trackers; - std::vector collections; - std::vector similar; - int pad_file_limit = -1; - int piece_size = 0; - create_flags_t flags = {}; - std::string root_cert; + std::vector web_seeds; + std::vector trackers; + std::vector collections; + std::vector similar; + int pad_file_limit = -1; + int piece_size = 0; + lt::create_flags_t flags = {}; + std::string root_cert; - std::string outfile; - std::string merklefile; + std::string outfile; + std::string merklefile; #ifdef TORRENT_WINDOWS - // don't ever write binary data to the console on windows - // it will just be interpreted as text and corrupted - outfile = "a.torrent"; + // don't ever write binary data to the console on windows + // it will just be interpreted as text and corrupted + outfile = "a.torrent"; #endif - for (int i = 2; i < argc; ++i) - { - if (argv[i][0] != '-') - { - print_usage(); - return 1; - } + std::string full_path = argv[1]; + argv += 2; + argc -= 2; - switch (argv[i][1]) - { - case 'w': - ++i; - web_seeds.push_back(argv[i]); - break; - case 't': - ++i; - trackers.push_back(argv[i]); - break; - case 'M': - flags |= create_torrent::mutable_torrent_support; - pad_file_limit = 0x4000; - break; - case 'p': - ++i; - pad_file_limit = atoi(argv[i]); - flags |= create_torrent::optimize_alignment; - break; - case 's': - ++i; - piece_size = atoi(argv[i]); - break; - case 'm': - ++i; - merklefile = argv[i]; - flags |= create_torrent::merkle; - break; - case 'o': - ++i; - outfile = argv[i]; - break; - case 'l': - flags |= create_torrent::symlinks; - break; - case 'C': - ++i; - creator_str = argv[i]; - break; - case 'c': - ++i; - comment_str = argv[i]; - break; - case 'r': - ++i; - root_cert = argv[i]; - break; - case 'S': - { - ++i; - if (strlen(argv[i]) != 40) - { - std::fprintf(stderr, "invalid info-hash for -S. " - "Expected 40 hex characters\n"); - print_usage(); - return 1; - } - std::stringstream hash(argv[i]); - sha1_hash ih; - hash >> ih; - if (hash.fail()) - { - std::fprintf(stderr, "invalid info-hash for -S\n"); - print_usage(); - return 1; - } - similar.push_back(ih); - } - break; - case 'L': - ++i; - collections.push_back(argv[i]); - break; - default: + for (; argc > 0; --argc, ++argv) { + if (argv[0][0] != '-') { + print_usage(); + return 1; + } + + char const flag = argv[0][1]; + + switch (flag) + { + case 'M': + flags |= lt::create_torrent::mutable_torrent_support; + pad_file_limit = 0x4000; + continue; + case 'l': + flags |= lt::create_torrent::symlinks; + continue; + } + + if (argc < 2) { + print_usage(); + return 1; + } + + switch (flag) + { + case 'w': web_seeds.push_back(argv[1]); break; + case 't': trackers.push_back(argv[1]); break; + case 's': piece_size = atoi(argv[1]); break; + case 'o': outfile = argv[1]; break; + case 'C': creator_str = argv[1]; break; + case 'c': comment_str = argv[1]; break; + case 'r': root_cert = argv[1]; break; + case 'L': collections.push_back(argv[1]); break; + case 'p': + pad_file_limit = atoi(argv[1]); + flags |= lt::create_torrent::optimize_alignment; + break; + case 'm': + merklefile = argv[1]; + flags |= lt::create_torrent::merkle; + break; + case 'S': { + if (strlen(argv[1]) != 40) { + std::fprintf(stderr, "invalid info-hash for -S. " + "Expected 40 hex characters\n"); print_usage(); return 1; + } + std::stringstream hash(argv[1]); + lt::sha1_hash ih; + hash >> ih; + if (hash.fail()) { + std::fprintf(stderr, "invalid info-hash for -S\n"); + print_usage(); + return 1; + } + similar.push_back(ih); + break; } - } - - file_storage fs; - std::string full_path = argv[1]; -#ifdef TORRENT_WINDOWS - if (full_path[1] != ':') -#else - if (full_path[0] != '/') -#endif - { - char cwd[TORRENT_MAX_PATH]; -#ifdef TORRENT_WINDOWS - _getcwd(cwd, sizeof(cwd)); - full_path = cwd + ("\\" + full_path); -#else - char const* ret = getcwd(cwd, sizeof(cwd)); - if (ret == NULL) - { - std::fprintf(stderr, "failed to get current working directory: %s\n" - , strerror(errno)); + default: + print_usage(); return 1; - } - full_path = cwd + ("/" + full_path); -#endif } - - add_files(fs, full_path, file_filter, flags); - if (fs.num_files() == 0) - { - fputs("no files specified.\n", stderr); - return 1; - } - - create_torrent t(fs, piece_size, pad_file_limit, flags); - int tier = 0; - for (std::vector::iterator i = trackers.begin() - , end(trackers.end()); i != end; ++i, ++tier) - t.add_tracker(*i, tier); - - for (std::vector::iterator i = web_seeds.begin() - , end(web_seeds.end()); i != end; ++i) - t.add_url_seed(*i); - - for (std::vector::iterator i = collections.begin() - , end(collections.end()); i != end; ++i) - t.add_collection(*i); - - for (std::vector::iterator i = similar.begin() - , end(similar.end()); i != end; ++i) - t.add_similar_torrent(*i); - - error_code ec; - set_piece_hashes(t, branch_path(full_path) - , std::bind(&print_progress, _1, t.num_pieces()), ec); - if (ec) - { - std::fprintf(stderr, "%s\n", ec.message().c_str()); - return 1; - } - - std::fprintf(stderr, "\n"); - t.set_creator(creator_str.c_str()); - if (!comment_str.empty()) - t.set_comment(comment_str.c_str()); - - if (!root_cert.empty()) - { - std::vector pem = load_file(root_cert); - t.set_root_cert(std::string(&pem[0], pem.size())); - } - - // create the torrent and print it to stdout - std::vector torrent; - bencode(back_inserter(torrent), t.generate()); - if (!outfile.empty()) - { - std::fstream out; - out.exceptions(std::ifstream::failbit); - out.open(outfile.c_str(), std::ios_base::out | std::ios_base::binary); - out.write(&torrent[0], torrent.size()); - } - else - { - fwrite(&torrent[0], 1, torrent.size(), stdout); - } - - if (!merklefile.empty()) - { - std::fstream merkle; - merkle.exceptions(std::ifstream::failbit); - merkle.open(merklefile.c_str(), std::ios_base::out | std::ios_base::binary); - merkle.write(reinterpret_cast(&t.merkle_tree()[0]), t.merkle_tree().size() * 20); - } - -#ifndef BOOST_NO_EXCEPTIONS + ++argv; + --argc; } - catch (std::exception const& e) + + lt::file_storage fs; +#ifdef TORRENT_WINDOWS + if (full_path[1] != ':') +#else + if (full_path[0] != '/') +#endif { - std::fprintf(stderr, "%s\n", e.what()); - } + char cwd[TORRENT_MAX_PATH]; +#ifdef TORRENT_WINDOWS + _getcwd(cwd, sizeof(cwd)); + full_path = cwd + ("\\" + full_path); +#else + char const* ret = getcwd(cwd, sizeof(cwd)); + if (ret == NULL) + { + std::fprintf(stderr, "failed to get current working directory: %s\n" + , strerror(errno)); + return 1; + } + full_path = cwd + ("/" + full_path); #endif + } + lt::add_files(fs, full_path, file_filter, flags); + if (fs.num_files() == 0) { + std::cerr << "no files specified.\n"; + return 1; + } + + lt::create_torrent t(fs, piece_size, pad_file_limit, flags); + int tier = 0; + for (std::vector::iterator i = trackers.begin() + , end(trackers.end()); i != end; ++i, ++tier) + t.add_tracker(*i, tier); + + for (std::vector::iterator i = web_seeds.begin() + , end(web_seeds.end()); i != end; ++i) + t.add_url_seed(*i); + + for (std::vector::iterator i = collections.begin() + , end(collections.end()); i != end; ++i) + t.add_collection(*i); + + for (std::vector::iterator i = similar.begin() + , end(similar.end()); i != end; ++i) + t.add_similar_torrent(*i); + + lt::error_code ec; + set_piece_hashes(t, branch_path(full_path) + , std::bind(&print_progress, _1, t.num_pieces()), ec); + if (ec) { + std::cerr << ec.message() << "\n"; + return 1; + } + + std::cerr << "\n"; + t.set_creator(creator_str.c_str()); + if (!comment_str.empty()) { + t.set_comment(comment_str.c_str()); + } + + if (!root_cert.empty()) { + std::vector const pem = load_file(root_cert); + t.set_root_cert(std::string(&pem[0], pem.size())); + } + + // create the torrent and print it to stdout + std::vector torrent; + lt::bencode(back_inserter(torrent), t.generate()); + if (!outfile.empty()) { + std::fstream out; + out.exceptions(std::ifstream::failbit); + out.open(outfile.c_str(), std::ios_base::out | std::ios_base::binary); + out.write(&torrent[0], torrent.size()); + } + else { + std::cout.write(&torrent[0], torrent.size()); + } + + if (!merklefile.empty()) { + std::fstream merkle; + merkle.exceptions(std::ifstream::failbit); + merkle.open(merklefile.c_str(), std::ios_base::out | std::ios_base::binary); + merkle.write(reinterpret_cast(&t.merkle_tree()[0]), t.merkle_tree().size() * 20); + } return 0; } - +catch (std::exception& e) { + std::cerr << "ERROR: " << e.what() << "\n"; + return 1; +} diff --git a/examples/simple_client.cpp b/examples/simple_client.cpp index dbe12fc48..285e4db3a 100644 --- a/examples/simple_client.cpp +++ b/examples/simple_client.cpp @@ -1,6 +1,6 @@ /* -Copyright (c) 2003, Arvid Norberg +Copyright (c) 2003-2017, Arvid Norberg All rights reserved. Redistribution and use in source and binary forms, with or without @@ -36,35 +36,22 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/session.hpp" #include "libtorrent/torrent_info.hpp" -int main(int argc, char* argv[]) -{ - using namespace lt; +#include +int main(int argc, char* argv[]) try +{ if (argc != 2) { - fputs("usage: ./simple_client torrent-file\n" - "to stop the client, press return.\n", stderr); + std::cerr << "usage: ./simple_client torrent-file\n" + "to stop the client, press return.\n"; return 1; } - settings_pack sett; - sett.set_str(settings_pack::listen_interfaces, "0.0.0.0:6881"); - lt::session s(sett); - error_code ec; - add_torrent_params p; + lt::session s; + lt::add_torrent_params p; p.save_path = "./"; - p.ti = std::make_shared(std::string(argv[1]), std::ref(ec)); - if (ec) - { - std::fprintf(stderr, "%s\n", ec.message().c_str()); - return 1; - } - s.add_torrent(p, ec); - if (ec) - { - std::fprintf(stderr, "%s\n", ec.message().c_str()); - return 1; - } + p.ti = std::make_shared(std::string(argv[1])); + s.add_torrent(p); // wait for the user to end char a; @@ -72,4 +59,8 @@ int main(int argc, char* argv[]) (void)ret; // ignore return 0; } +catch (std::exception const& e) +{ + std::cerr << "ERROR: " << e.what() << "\n"; +} diff --git a/include/libtorrent/session_handle.hpp b/include/libtorrent/session_handle.hpp index 7eb223cdd..b3d24ea7a 100644 --- a/include/libtorrent/session_handle.hpp +++ b/include/libtorrent/session_handle.hpp @@ -670,7 +670,7 @@ namespace libtorrent { // class and returns a unique identifier. // // Identifiers are assigned from low numbers to higher. So if you plan on - // using certain peer classes in a call to `set_peer_class_filter()`_, + // using certain peer classes in a call to set_peer_class_filter(), // make sure to create those early on, to get low identifiers. // // For more information on peer classes, see peer-classes_. diff --git a/include/libtorrent/torrent.hpp b/include/libtorrent/torrent.hpp index 5dda8a6ec..e547c371b 100644 --- a/include/libtorrent/torrent.hpp +++ b/include/libtorrent/torrent.hpp @@ -1595,7 +1595,7 @@ namespace libtorrent { // the number of bytes of padding files std::uint32_t m_padding:24; - // TODO: 8 bits available here + // TODO: gap of 8 bits available here // ---- diff --git a/tools/clean.py b/tools/clean.py index 2e46e6550..bd1f624b4 100755 --- a/tools/clean.py +++ b/tools/clean.py @@ -13,6 +13,8 @@ def clean(): 'upnp.log', 'natpmp.log', 'bin', + 'build-aux', + '.deps', 'test_tmp_*', 'bjam_build.*.xml' '*.exe', @@ -34,6 +36,11 @@ def clean(): 'Jamfile.orig', '*.o', '*.lo', + 'autom4te.cache', + 'configure', + 'config.report', + 'config.log', + '.lib', ] directories = [