diff --git a/ChangeLog b/ChangeLog index c18182465..32c68346c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -31,6 +31,8 @@ * almost completely changed the storage interface (for custom storage) * added support for hashing pieces in multiple threads + * support read-only DHT nodes + * remove unused partial hash DHT lookups * remove potentially privacy leaking extension (non-anonymous mode) * peer-id connection ordering fix in anonymous mode * mingw fixes diff --git a/include/libtorrent/kademlia/node.hpp b/include/libtorrent/kademlia/node.hpp index abe1669c6..795645bf8 100644 --- a/include/libtorrent/kademlia/node.hpp +++ b/include/libtorrent/kademlia/node.hpp @@ -285,7 +285,7 @@ public: protected: - void lookup_peers(sha1_hash const& info_hash, int prefix, entry& reply + void lookup_peers(sha1_hash const& info_hash, entry& reply , bool noseed, bool scrape) const; bool lookup_torrents(sha1_hash const& target, entry& reply , char* tags) const; diff --git a/src/kademlia/node.cpp b/src/kademlia/node.cpp index 87dcbe87f..1261e8042 100644 --- a/src/kademlia/node.cpp +++ b/src/kademlia/node.cpp @@ -494,7 +494,7 @@ void node_impl::status(session_status& s) } } -void node_impl::lookup_peers(sha1_hash const& info_hash, int prefix, entry& reply +void node_impl::lookup_peers(sha1_hash const& info_hash, entry& reply , bool noseed, bool scrape) const { if (m_post_alert) @@ -505,13 +505,7 @@ void node_impl::lookup_peers(sha1_hash const& info_hash, int prefix, entry& repl table_t::const_iterator i = m_map.lower_bound(info_hash); if (i == m_map.end()) return; - if (i->first != info_hash && prefix == 20) return; - if (prefix != 20) - { - sha1_hash mask = sha1_hash::max(); - mask <<= (20 - prefix) * 8; - if ((i->first & mask) != (info_hash & mask)) return; - } + if (i->first != info_hash) return; torrent_entry const& v = i->second; @@ -709,13 +703,14 @@ void node_impl::incoming_request(msg const& m, entry& e) key_desc_t top_desc[] = { {"q", lazy_entry::string_t, 0, 0}, + {"ro", lazy_entry::int_t, 0, key_desc_t::optional}, {"a", lazy_entry::dict_t, 0, key_desc_t::parse_children}, {"id", lazy_entry::string_t, 20, key_desc_t::last_child}, }; - lazy_entry const* top_level[3]; + lazy_entry const* top_level[4]; char error_string[200]; - if (!verify_message(&m.message, top_desc, top_level, 3, error_string, sizeof(error_string))) + if (!verify_message(&m.message, top_desc, top_level, 4, error_string, sizeof(error_string))) { incoming_error(e, error_string); return; @@ -725,9 +720,9 @@ void node_impl::incoming_request(msg const& m, entry& e) char const* query = top_level[0]->string_cstr(); - lazy_entry const* arg_ent = top_level[1]; - - node_id id(top_level[2]->string_ptr()); + lazy_entry const* arg_ent = top_level[2]; + bool read_only = top_level[1] && top_level[1]->int_value() != 0; + node_id id(top_level[3]->string_ptr()); // if this nodes ID doesn't match its IP, tell it what // its IP is with an error @@ -738,7 +733,8 @@ void node_impl::incoming_request(msg const& m, entry& e) return; } - m_table.heard_about(id, m.addr); + if (!read_only) + m_table.heard_about(id, m.addr); entry& reply = e["r"]; m_rpc.add_our_id(reply); @@ -756,13 +752,12 @@ void node_impl::incoming_request(msg const& m, entry& e) { key_desc_t msg_desc[] = { {"info_hash", lazy_entry::string_t, 20, 0}, - {"ifhpfxl", lazy_entry::int_t, 0, key_desc_t::optional}, {"noseed", lazy_entry::int_t, 0, key_desc_t::optional}, {"scrape", lazy_entry::int_t, 0, key_desc_t::optional}, }; - lazy_entry const* msg_keys[4]; - if (!verify_message(arg_ent, msg_desc, msg_keys, 4, error_string, sizeof(error_string))) + lazy_entry const* msg_keys[3]; + if (!verify_message(arg_ent, msg_desc, msg_keys, 3, error_string, sizeof(error_string))) { incoming_error(e, error_string); return; @@ -778,15 +773,11 @@ void node_impl::incoming_request(msg const& m, entry& e) m_table.find_node(info_hash, n, 0); write_nodes_entry(reply, n); - int prefix = msg_keys[1] ? int(msg_keys[1]->int_value()) : 20; - if (prefix > 20) prefix = 20; - else if (prefix < 4) prefix = 4; - bool noseed = false; bool scrape = false; - if (msg_keys[2] && msg_keys[2]->int_value() != 0) noseed = true; - if (msg_keys[3] && msg_keys[3]->int_value() != 0) scrape = true; - lookup_peers(info_hash, prefix, reply, noseed, scrape); + if (msg_keys[1] && msg_keys[1]->int_value() != 0) noseed = true; + if (msg_keys[2] && msg_keys[2]->int_value() != 0) scrape = true; + lookup_peers(info_hash, reply, noseed, scrape); #ifdef TORRENT_DHT_VERBOSE_LOGGING if (reply.find_key("values")) { @@ -810,7 +801,7 @@ void node_impl::incoming_request(msg const& m, entry& e) m_counters.inc_stats_counter(counters::dht_find_node_in); sha1_hash target(msg_keys[0]->string_ptr()); - // TODO: 1 find_node should write directly to the response entry + // TODO: 2 find_node should write directly to the response entry nodes_t n; m_table.find_node(target, n, 0); write_nodes_entry(reply, n); diff --git a/src/udp_socket.cpp b/src/udp_socket.cpp index 8fe6d2672..fbc6b9f9a 100644 --- a/src/udp_socket.cpp +++ b/src/udp_socket.cpp @@ -679,12 +679,24 @@ void udp_socket::set_buf_size(int s) close(); } + int size = m_buf_size; + + // don't shrink the size of the receive buffer + error_code ec; + boost::asio::socket_base::receive_buffer_size recv_size; + m_ipv4_sock.get_option(recv_size, ec); + if (!ec) size = (std::max)(recv_size.value(), size); +#if TORRENT_USE_IPV6 + m_ipv6_sock.get_option(recv_size, ec); + if (!ec) size = (std::max)(recv_size.value(), size); +#endif + error_code ignore_errors; // set the internal buffer sizes as well - m_ipv4_sock.set_option(boost::asio::socket_base::receive_buffer_size(m_buf_size) + m_ipv4_sock.set_option(boost::asio::socket_base::receive_buffer_size(size) , ignore_errors); #if TORRENT_USE_IPV6 - m_ipv6_sock.set_option(boost::asio::socket_base::receive_buffer_size(m_buf_size) + m_ipv6_sock.set_option(boost::asio::socket_base::receive_buffer_size(size) , ignore_errors); #endif } diff --git a/test/test_metadata_extension.cpp b/test/test_metadata_extension.cpp index af8c851e1..3f6b8c12a 100644 --- a/test/test_metadata_extension.cpp +++ b/test/test_metadata_extension.cpp @@ -58,11 +58,12 @@ void test_transfer(int flags using namespace libtorrent; namespace lt = libtorrent; - fprintf(stderr, "test transfer: timeout=%d %s%s%s\n" + fprintf(stderr, "test transfer: timeout=%d %s%s%s%s\n" , timeout , (flags & clear_files) ? "clear-files " : "" , (flags & disconnect) ? "disconnect " : "" - , (flags & full_encryption) ? "encryption " : ""); + , (flags & full_encryption) ? "encryption " : "" + , (flags & reverse) ? "reverse " : ""); // these are declared before the session objects // so that they are destructed last. This enables @@ -89,12 +90,27 @@ void test_transfer(int flags lt::session* downloader = &ses2; lt::session* seed = &ses1; + boost::tie(tor1, tor2, ignore) = setup_transfer(seed, downloader, NULL + , flags & clear_files, true, false, "_meta"); + if (flags & reverse) { - std::swap(downloader, seed); + error_code ec; + int port = seed->listen_port(); + fprintf(stderr, "%s: downloader: connecting peer port: %d\n" + , time_now_string(), port); + tor2.connect_peer(tcp::endpoint(address::from_string("127.0.0.1", ec) + , port)); + } + else + { + error_code ec; + int port = downloader->listen_port(); + fprintf(stderr, "%s: seed: connecting peer port: %d\n" + , time_now_string(), port); + tor1.connect_peer(tcp::endpoint(address::from_string("127.0.0.1", ec) + , port)); } - - boost::tie(tor1, tor2, ignore) = setup_transfer(seed, downloader, NULL, flags & clear_files, true, true, "_meta"); for (int i = 0; i < timeout * 10; ++i) { diff --git a/test/test_utp.cpp b/test/test_utp.cpp index 44a0bb91c..aa50b8bb0 100644 --- a/test/test_utp.cpp +++ b/test/test_utp.cpp @@ -95,7 +95,7 @@ void test_transfer() boost::tie(tor1, tor2, ignore) = setup_transfer(&ses1, &ses2, 0 , true, false, true, "_utp", 0, &t, false, &atp); - for (int i = 0; i < 300; ++i) + for (int i = 0; i < 6; ++i) { print_alerts(ses1, "ses1", true, true, true); print_alerts(ses2, "ses2", true, true, true);