From 61af222d92299b388f502b5c61305b709be410bf Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 25 Oct 2016 08:03:26 -0400 Subject: [PATCH] add utility function for generating peer ID fingerprint (#1249) add utility function for generating peer ID fingerprint --- CMakeLists.txt | 1 + ChangeLog | 1 + Jamfile | 1 + bindings/python/src/fingerprint.cpp | 2 + include/libtorrent/fingerprint.hpp | 107 +++++++++---------------- include/libtorrent/identify_client.hpp | 29 +++++-- include/libtorrent/session.hpp | 14 ++++ include/libtorrent/settings_pack.hpp | 5 +- src/Makefile.am | 1 + src/bt_peer_connection.cpp | 3 +- src/fingerprint.cpp | 100 +++++++++++++++++++++++ src/identify_client.cpp | 10 ++- test/test_primitives.cpp | 8 ++ 13 files changed, 202 insertions(+), 80 deletions(-) create mode 100644 src/fingerprint.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 37c2ad28e..e9df1478b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -32,6 +32,7 @@ set(sources escape_string string_util file + fingerprint gzip hasher hex diff --git a/ChangeLog b/ChangeLog index 75c2b5cfc..9851584c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,4 @@ + * add utility function for generating peer ID fingerprint * fix bug in last-seen-complete * remove file size limit in torrent_info filename constructor * fix tail-padding for last file in create_torrent diff --git a/Jamfile b/Jamfile index 31a2023cc..5580ccf91 100644 --- a/Jamfile +++ b/Jamfile @@ -582,6 +582,7 @@ SOURCES = escape_string string_util file + fingerprint gzip hasher hex diff --git a/bindings/python/src/fingerprint.cpp b/bindings/python/src/fingerprint.cpp index 27215fac4..b079ef3c5 100644 --- a/bindings/python/src/fingerprint.cpp +++ b/bindings/python/src/fingerprint.cpp @@ -10,6 +10,7 @@ void bind_fingerprint() using namespace boost::python; using namespace libtorrent; +#ifndef TORRENT_NO_DEPRECATE class_("fingerprint", no_init) .def( init( @@ -23,5 +24,6 @@ void bind_fingerprint() .def_readonly("revision_version", &fingerprint::revision_version) .def_readonly("tag_version", &fingerprint::tag_version) ; +#endif } diff --git a/include/libtorrent/fingerprint.hpp b/include/libtorrent/fingerprint.hpp index 78f302661..371c7fb3a 100644 --- a/include/libtorrent/fingerprint.hpp +++ b/include/libtorrent/fingerprint.hpp @@ -38,90 +38,61 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" #include "libtorrent/peer_id.hpp" -#include "libtorrent/assert.hpp" #include "libtorrent/export.hpp" namespace libtorrent { + // This is a utility function to produce a client ID fingerprint formatted to + // the most common convention. + // + // The name string should contain exactly two characters. These are the + // characters unique to your client, used to identify it. Make sure not to + // clash with anybody else. Here are some taken id's: + // + // +----------+-----------------------+ + // | id chars | client | + // +==========+=======================+ + // | 'AZ' | Azureus | + // +----------+-----------------------+ + // | 'LT' | libtorrent (default) | + // +----------+-----------------------+ + // | 'BX' | BittorrentX | + // +----------+-----------------------+ + // | 'MT' | Moonlight Torrent | + // +----------+-----------------------+ + // | 'TS' | Torrent Storm | + // +----------+-----------------------+ + // | 'SS' | Swarm Scope | + // +----------+-----------------------+ + // | 'XT' | Xan Torrent | + // +----------+-----------------------+ + // + // There's an informal directory of client id's here_. + // + // .. _here: http://wiki.theory.org/BitTorrentSpecification#peer_id + // + // The ``major``, ``minor``, ``revision`` and ``tag`` parameters are used to + // identify the version of your client. + TORRENT_EXPORT std::string generate_fingerprint(std::string name + , int major, int minor = 0, int revision = 0, int tag = 0); + // The fingerprint class represents information about a client and its version. It is used // to encode this information into the client's peer id. - struct TORRENT_DEPRECATED_EXPORT fingerprint + struct TORRENT_DEPRECATED TORRENT_DEPRECATED_EXPORT fingerprint { + fingerprint(const char* id_string, int major, int minor, int revision, int tag); - // The constructor takes a ``char const*`` that should point to a string constant containing - // exactly two characters. These are the characters that should be unique for your client. Make - // sure not to clash with anybody else. Here are some taken id's: - // - // +----------+-----------------------+ - // | id chars | client | - // +==========+=======================+ - // | 'AZ' | Azureus | - // +----------+-----------------------+ - // | 'LT' | libtorrent (default) | - // +----------+-----------------------+ - // | 'BX' | BittorrentX | - // +----------+-----------------------+ - // | 'MT' | Moonlight Torrent | - // +----------+-----------------------+ - // | 'TS' | Torrent Storm | - // +----------+-----------------------+ - // | 'SS' | Swarm Scope | - // +----------+-----------------------+ - // | 'XT' | Xan Torrent | - // +----------+-----------------------+ - // - // There's an informal directory of client id's here_. - // - // .. _here: http://wiki.theory.org/BitTorrentSpecification#peer_id - // - // The ``major``, ``minor``, ``revision`` and ``tag`` parameters are used to identify the - // version of your client. - fingerprint(const char* id_string, int major, int minor, int revision, int tag) - : major_version(major) - , minor_version(minor) - , revision_version(revision) - , tag_version(tag) - { - TORRENT_ASSERT(id_string); - TORRENT_ASSERT(major >= 0); - TORRENT_ASSERT(minor >= 0); - TORRENT_ASSERT(revision >= 0); - TORRENT_ASSERT(tag >= 0); - TORRENT_ASSERT(std::strlen(id_string) == 2); - name[0] = id_string[0]; - name[1] = id_string[1]; - } - +#ifndef TORRENT_NO_DEPRECATE // generates the actual string put in the peer-id, and return it. - std::string to_string() const - { - char s[100]; - snprintf(s, 100, "-%c%c%c%c%c%c-" - , name[0], name[1] - , version_to_char(major_version) - , version_to_char(minor_version) - , version_to_char(revision_version) - , version_to_char(tag_version)); - return s; - } + std::string to_string() const; +#endif char name[2]; int major_version; int minor_version; int revision_version; int tag_version; - - private: - - char version_to_char(int v) const - { - if (v >= 0 && v < 10) return char('0' + v); - else if (v >= 10) return char('A' + (v - 10)); - TORRENT_ASSERT(false); - return '0'; - } - }; } diff --git a/include/libtorrent/identify_client.hpp b/include/libtorrent/identify_client.hpp index e1816a7d5..d038f97ab 100644 --- a/include/libtorrent/identify_client.hpp +++ b/include/libtorrent/identify_client.hpp @@ -35,21 +35,19 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/config.hpp" +#ifndef TORRENT_NO_DEPRECATE #include "libtorrent/aux_/disable_warnings_push.hpp" - #include - #include "libtorrent/aux_/disable_warnings_pop.hpp" +#endif #include "libtorrent/peer_id.hpp" #include "libtorrent/fingerprint.hpp" +// TODO: hide this declaration when deprecated functions are disabled, and +// remove its internal use namespace libtorrent { - - // TODO: hide these declarations when deprecaated functions are disabled, and - // expose them internally in a header under aux_. - // these functions don't really need to be public. This mechanism of // advertising client software and version is also out-dated. @@ -59,6 +57,16 @@ namespace libtorrent TORRENT_DEPRECATED_EXPORT TORRENT_DEPRECATED std::string identify_client(const peer_id& p); +#ifndef TORRENT_NO_DEPRECATE + +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif // Returns an optional fingerprint if any can be identified from the peer // id. This can be used to automate the identification of clients. It will // not be able to identify peers with non- standard encodings. Only Azureus @@ -67,6 +75,15 @@ namespace libtorrent boost::optional client_fingerprint(peer_id const& p); +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#endif // TORRENT_NO_DEPRECATE + } #endif // TORRENT_IDENTIFY_CLIENT_HPP_INCLUDED diff --git a/include/libtorrent/session.hpp b/include/libtorrent/session.hpp index f16f41e15..6a0476d3a 100644 --- a/include/libtorrent/session.hpp +++ b/include/libtorrent/session.hpp @@ -201,6 +201,14 @@ namespace libtorrent } #ifndef TORRENT_NO_DEPRECATE +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +#endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif TORRENT_DEPRECATED session(fingerprint const& print , int flags = start_default_features | add_default_plugins @@ -253,6 +261,12 @@ namespace libtorrent } start(flags, pack, NULL); } +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #endif // TORRENT_NO_DEPRECATE // The destructor of session will notify all trackers that our torrents diff --git a/include/libtorrent/settings_pack.hpp b/include/libtorrent/settings_pack.hpp index 6776de8c3..1608083ac 100644 --- a/include/libtorrent/settings_pack.hpp +++ b/include/libtorrent/settings_pack.hpp @@ -201,7 +201,10 @@ namespace libtorrent // this is the fingerprint for the client. It will be used as the // prefix to the peer_id. If this is 20 bytes (or longer) it will be - // used as the peer-id + // truncated at 20 bytes and used as the entire peer-id + // + // There is a utility function, generate_fingerprint() that can be used + // to generate a standard client peer ID fingerprint prefix. peer_fingerprint, // This is a comma-separated list of IP port-pairs. They will be added diff --git a/src/Makefile.am b/src/Makefile.am index f273f90fe..70ffc0bd4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,7 @@ libtorrent_rasterbar_la_SOURCES = \ file.cpp \ file_pool.cpp \ file_storage.cpp \ + fingerprint.cpp \ gzip.cpp \ hasher.cpp \ hex.cpp \ diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index d99f9905c..e04e61801 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -3405,8 +3405,7 @@ namespace libtorrent } m_client_version = identify_client(pid); - boost::optional f = client_fingerprint(pid); - if (f && std::equal(f->name, f->name + 2, "BC")) + if (pid[0] == '-' && pid[1] == 'B' && pid[2] == 'C' && pid[7] == '-') { // if this is a bitcomet client, lower the request queue size limit if (max_out_request_queue() > 50) max_out_request_queue(50); diff --git a/src/fingerprint.cpp b/src/fingerprint.cpp new file mode 100644 index 000000000..763f61833 --- /dev/null +++ b/src/fingerprint.cpp @@ -0,0 +1,100 @@ +/* + +Copyright (c) 2016, Arvid Norberg +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution. + * Neither the name of the author nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "libtorrent/fingerprint.hpp" +#include "libtorrent/assert.hpp" + +namespace libtorrent { + namespace { + + char version_to_char(int const v) + { + if (v >= 0 && v < 10) return char('0' + v); + else if (v >= 10) return char('A' + (v - 10)); + TORRENT_ASSERT(false); + return '0'; + } + + } // anonymous namespace + + std::string generate_fingerprint(std::string name, int const major + , int const minor + , int const revision + , int const tag) + { + TORRENT_ASSERT_PRECOND(major >= 0); + TORRENT_ASSERT_PRECOND(minor >= 0); + TORRENT_ASSERT_PRECOND(revision >= 0); + TORRENT_ASSERT_PRECOND(tag >= 0); + TORRENT_ASSERT_PRECOND(name.size() == 2); + if (name.size() < 2) name = "--"; + + std::string ret; + ret.resize(8); + ret[0] = '-'; + ret[1] = name[0]; + ret[2] = name[1]; + ret[3] = version_to_char(major); + ret[4] = version_to_char(minor); + ret[5] = version_to_char(revision); + ret[6] = version_to_char(tag); + ret[7] = '-'; + return ret; + } + + fingerprint::fingerprint(const char* id_string, int major, int minor + , int revision, int tag) + : major_version(major) + , minor_version(minor) + , revision_version(revision) + , tag_version(tag) + { + TORRENT_ASSERT(id_string); + TORRENT_ASSERT(major >= 0); + TORRENT_ASSERT(minor >= 0); + TORRENT_ASSERT(revision >= 0); + TORRENT_ASSERT(tag >= 0); + TORRENT_ASSERT(std::strlen(id_string) == 2); + name[0] = id_string[0]; + name[1] = id_string[1]; + } + +#ifndef TORRENT_NO_DEPRECATE + std::string fingerprint::to_string() const + { + return generate_fingerprint(name, major_version, minor_version + , revision_version, tag_version); + } +#endif // TORRENT_NO_DEPRECATE + +} + diff --git a/src/identify_client.cpp b/src/identify_client.cpp index a04444be0..6748431ca 100644 --- a/src/identify_client.cpp +++ b/src/identify_client.cpp @@ -35,9 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include #include "libtorrent/aux_/disable_warnings_push.hpp" - #include - #include "libtorrent/aux_/disable_warnings_pop.hpp" #include "libtorrent/identify_client.hpp" @@ -141,7 +139,9 @@ namespace // must be ordered alphabetically map_entry name_map[] = { - {"A", "ABC"} + {"7T", "aTorrent for android"} + , {"A", "ABC"} + , {"AB", "AnyEvent BitTorrent"} , {"AG", "Ares"} , {"AR", "Arctic Torrent"} , {"AT", "Artemis"} @@ -343,6 +343,8 @@ namespace namespace libtorrent { +#ifndef TORRENT_NO_DEPRECATE + boost::optional client_fingerprint(peer_id const& p) { // look for azureus style id @@ -360,6 +362,8 @@ namespace libtorrent return f; } +#endif + std::string identify_client(peer_id const& p) { char const* PID = p.data(); diff --git a/test/test_primitives.cpp b/test/test_primitives.cpp index ee5ff0d81..e1282f1c3 100644 --- a/test/test_primitives.cpp +++ b/test/test_primitives.cpp @@ -34,6 +34,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "libtorrent/broadcast_socket.hpp" #include "libtorrent/socket_io.hpp" // for print_endpoint #include "libtorrent/announce_entry.hpp" +#include "libtorrent/fingerprint.hpp" #include "test.hpp" #include "setup_transfer.hpp" @@ -159,5 +160,12 @@ TORRENT_TEST(primitives) // test endpoint_to_bytes TEST_EQUAL(endpoint_to_bytes(udp::endpoint(address_v4::from_string("10.11.12.13"), 8080)), "\x0a\x0b\x0c\x0d\x1f\x90"); TEST_EQUAL(endpoint_to_bytes(udp::endpoint(address_v4::from_string("16.5.127.1"), 12345)), "\x10\x05\x7f\x01\x30\x39"); + + // test gen_fingerprint + TEST_EQUAL(generate_fingerprint("AB", 1, 2, 3, 4), "-AB1234-"); + TEST_EQUAL(generate_fingerprint("AB", 1, 2), "-AB1200-"); + TEST_EQUAL(generate_fingerprint("..", 1, 10), "-..1A00-"); + TEST_EQUAL(generate_fingerprint("CZ", 1, 15), "-CZ1F00-"); + TEST_EQUAL(generate_fingerprint("CZ", 1, 15, 16, 17), "-CZ1FGH-"); }