From 10f5418ce7dd1110075e09a420cb9a6490c2c17b Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 1 Jul 2008 08:04:12 +0000 Subject: [PATCH] switched extension handshake parsing over to use lazy_bdecode for improved performance --- docs/libtorrent_plugins.rst | 2 +- include/libtorrent/extensions.hpp | 3 +- src/bt_peer_connection.cpp | 71 +++++++++++-------------------- src/logger.cpp | 5 +-- src/metadata_transfer.cpp | 13 +++--- src/ut_metadata.cpp | 20 +++++---- src/ut_pex.cpp | 14 +++--- 7 files changed, 56 insertions(+), 72 deletions(-) diff --git a/docs/libtorrent_plugins.rst b/docs/libtorrent_plugins.rst index 6583193d4..5dc3b5e5e 100644 --- a/docs/libtorrent_plugins.rst +++ b/docs/libtorrent_plugins.rst @@ -188,7 +188,7 @@ peer_plugin virtual void add_handshake(entry&); virtual bool on_handshake(char const* reserved_bits); - virtual bool on_extension_handshake(entry const& h); + virtual bool on_extension_handshake(lazy_entry const& h); virtual bool on_choke(); virtual bool on_unchoke(); diff --git a/include/libtorrent/extensions.hpp b/include/libtorrent/extensions.hpp index 3e85b125b..b06a0fc74 100644 --- a/include/libtorrent/extensions.hpp +++ b/include/libtorrent/extensions.hpp @@ -56,6 +56,7 @@ namespace libtorrent struct peer_request; class peer_connection; class entry; + struct lazy_entry; struct disk_buffer_holder; struct bitfield; @@ -107,7 +108,7 @@ namespace libtorrent // supported by this peer. It will result in this peer_plugin // being removed from the peer_connection and destructed. // this is not called for web seeds - virtual bool on_extension_handshake(entry const& h) { return true; } + virtual bool on_extension_handshake(lazy_entry const& h) { return true; } // returning true from any of the message handlers // indicates that the plugin has handeled the message. diff --git a/src/bt_peer_connection.cpp b/src/bt_peer_connection.cpp index d83fdfa3b..4a48b7ae3 100644 --- a/src/bt_peer_connection.cpp +++ b/src/bt_peer_connection.cpp @@ -1246,9 +1246,9 @@ namespace libtorrent buffer::const_interval recv_buffer = receive_buffer(); - entry root; - root = bdecode(recv_buffer.begin + 2, recv_buffer.end); - if (root.type() == entry::undefined_t) + lazy_entry root; + lazy_bdecode(recv_buffer.begin + 2, recv_buffer.end, root); + if (root.type() != lazy_entry::dict_t) { #ifdef TORRENT_VERBOSE_LOGGING (*m_logger) << "invalid extended handshake\n"; @@ -1257,9 +1257,7 @@ namespace libtorrent } #ifdef TORRENT_VERBOSE_LOGGING - std::stringstream ext; - root.print(ext); - (*m_logger) << "<== EXTENDED HANDSHAKE: \n" << ext.str(); + (*m_logger) << "<== EXTENDED HANDSHAKE: \n" << root; #endif #ifndef TORRENT_DISABLE_EXTENSIONS @@ -1276,56 +1274,39 @@ namespace libtorrent #endif // there is supposed to be a remote listen port - if (entry* listen_port = root.find_key("p")) + int listen_port = root.dict_find_int_value("p"); + if (listen_port > 0 && peer_info_struct() != 0) { - if (listen_port->type() == entry::int_t - && peer_info_struct() != 0) - { - t->get_policy().update_peer_port(int(listen_port->integer()) - , peer_info_struct(), peer_info::incoming); - } + t->get_policy().update_peer_port(listen_port + , peer_info_struct(), peer_info::incoming); } // there should be a version too // but where do we put that info? - if (entry* client_info = root.find_key("v")) - { - if (client_info->type() == entry::string_t) - m_client_version = client_info->string(); - } + std::string client_info = root.dict_find_string_value("v"); + if (!client_info.empty()) m_client_version = client_info; - if (entry* reqq = root.find_key("reqq")) - { - if (reqq->type() == entry::int_t) - m_max_out_request_queue = int(reqq->integer()); - if (m_max_out_request_queue < 1) - m_max_out_request_queue = 1; - } + int reqq = root.dict_find_int_value("reqq"); + if (reqq > 0) m_max_out_request_queue = reqq; - if (entry* upload_only = root.find_key("upload_only")) - { - if (upload_only->type() == entry::int_t && upload_only->integer() != 0) - set_upload_only(true); - } + if (root.dict_find_int_value("upload_only")) + set_upload_only(true); - if (entry* myip = root.find_key("yourip")) + std::string myip = root.dict_find_string_value("yourip"); + if (!myip.empty()) { // TODO: don't trust this blindly - if (myip->type() == entry::string_t) + if (myip.size() == address_v4::bytes_type::static_size) { - std::string const& my_ip = myip->string().c_str(); - if (my_ip.size() == address_v4::bytes_type::static_size) - { - address_v4::bytes_type bytes; - std::copy(my_ip.begin(), my_ip.end(), bytes.begin()); - m_ses.set_external_address(address_v4(bytes)); - } - else if (my_ip.size() == address_v6::bytes_type::static_size) - { - address_v6::bytes_type bytes; - std::copy(my_ip.begin(), my_ip.end(), bytes.begin()); - m_ses.set_external_address(address_v6(bytes)); - } + address_v4::bytes_type bytes; + std::copy(myip.begin(), myip.end(), bytes.begin()); + m_ses.set_external_address(address_v4(bytes)); + } + else if (myip.size() == address_v6::bytes_type::static_size) + { + address_v6::bytes_type bytes; + std::copy(myip.begin(), myip.end(), bytes.begin()); + m_ses.set_external_address(address_v6(bytes)); } } diff --git a/src/logger.cpp b/src/logger.cpp index b33816a59..1ecba5045 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -81,11 +81,10 @@ namespace virtual void add_handshake(entry&) {} // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { log_timestamp(); - m_file << "<== EXTENSION_HANDSHAKE\n"; - h.print(m_file); + m_file << "<== EXTENSION_HANDSHAKE\n" << h; return true; } diff --git a/src/metadata_transfer.cpp b/src/metadata_transfer.cpp index 8938cfb7b..8e27eeabf 100644 --- a/src/metadata_transfer.cpp +++ b/src/metadata_transfer.cpp @@ -278,15 +278,16 @@ namespace libtorrent { namespace } // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { m_message_index = 0; - entry const* messages = h.find_key("m"); - if (!messages || messages->type() != entry::dictionary_t) return false; + if (h.type() != lazy_entry::dict_t) return false; + lazy_entry const* messages = h.dict_find("m"); + if (!messages || messages->type() != lazy_entry::dict_t) return false; - entry const* index = messages->find_key("LT_metadata"); - if (!index || index->type() != entry::int_t) return false; - m_message_index = int(index->integer()); + int index = messages->dict_find_int_value("LT_metadata", -1); + if (index == -1) return false; + m_message_index = index; return true; } diff --git a/src/ut_metadata.cpp b/src/ut_metadata.cpp index 0a1f139d7..17246e5b6 100644 --- a/src/ut_metadata.cpp +++ b/src/ut_metadata.cpp @@ -235,18 +235,20 @@ namespace libtorrent { namespace } // called when the extension handshake from the other end is received - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { - entry const* metadata_size = h.find_key("metadata_size"); - if (metadata_size && metadata_size->type() == entry::int_t) - m_tp.metadata_size(metadata_size->integer()); + m_message_index = 0; + if (h.type() != lazy_entry::dict_t) return false; + lazy_entry const* messages = h.dict_find("m"); + if (!messages || messages->type() != lazy_entry::dict_t) return false; - entry const* messages = h.find_key("m"); - if (!messages || messages->type() != entry::dictionary_t) return false; + int index = messages->dict_find_int_value("ut_metadata", -1); + if (index == -1) return false; + m_message_index = index; - entry const* index = messages->find_key("ut_metadata"); - if (!index || index->type() != entry::int_t) return false; - m_message_index = int(index->integer()); + int metadata_size = h.dict_find_int_value("metadata_size"); + if (metadata_size > 0) + m_tp.metadata_size(metadata_size); return true; } diff --git a/src/ut_pex.cpp b/src/ut_pex.cpp index 4341564f7..f27dddc94 100644 --- a/src/ut_pex.cpp +++ b/src/ut_pex.cpp @@ -196,16 +196,16 @@ namespace libtorrent { namespace messages[extension_name] = extension_index; } - virtual bool on_extension_handshake(entry const& h) + virtual bool on_extension_handshake(lazy_entry const& h) { m_message_index = 0; - entry const* messages = h.find_key("m"); - if (!messages || messages->type() != entry::dictionary_t) return false; + if (h.type() != lazy_entry::dict_t) return false; + lazy_entry const* messages = h.dict_find("m"); + if (!messages || messages->type() != lazy_entry::dict_t) return false; - entry const* index = messages->find_key(extension_name); - if (!index || index->type() != entry::int_t) return false; - - m_message_index = int(index->integer()); + int index = messages->dict_find_int_value(extension_name, -1); + if (index == -1) return false; + m_message_index = index; return true; }