diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/command_line.cpp | 7 | ||||
-rw-r--r-- | src/common/password.cpp | 7 | ||||
-rw-r--r-- | src/cryptonote_basic/CMakeLists.txt | 6 | ||||
-rw-r--r-- | src/cryptonote_basic/miner.cpp | 38 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 48 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_defs.h | 4 | ||||
-rw-r--r-- | src/cryptonote_protocol/cryptonote_protocol_handler.inl | 55 | ||||
-rw-r--r-- | src/daemon/rpc_command_executor.cpp | 43 | ||||
-rw-r--r-- | src/p2p/net_node.h | 42 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 215 | ||||
-rw-r--r-- | src/p2p/net_node_common.h | 18 | ||||
-rw-r--r-- | src/p2p/net_peerlist.h | 78 | ||||
-rw-r--r-- | src/p2p/net_peerlist_boost_serialization.h | 35 | ||||
-rw-r--r-- | src/p2p/p2p_protocol_defs.h | 121 | ||||
-rw-r--r-- | src/rpc/core_rpc_server.cpp | 40 | ||||
-rw-r--r-- | src/rpc/core_rpc_server_commands_defs.h | 28 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 4 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 5 | ||||
-rw-r--r-- | src/wallet/wallet_errors.h | 10 |
19 files changed, 565 insertions, 239 deletions
diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp index f71b3e576..8c2796bbe 100644 --- a/src/common/command_line.cpp +++ b/src/common/command_line.cpp @@ -37,6 +37,10 @@ #include "cryptonote_config.h" #include "string_tools.h" +#ifdef HAVE_READLINE + #include "readline_buffer.h" +#endif + namespace command_line { namespace @@ -49,6 +53,9 @@ namespace command_line std::string input_line(const std::string& prompt) { +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif std::cout << prompt; std::string buf; diff --git a/src/common/password.cpp b/src/common/password.cpp index bdc9c69c0..5c04023f4 100644 --- a/src/common/password.cpp +++ b/src/common/password.cpp @@ -42,6 +42,10 @@ #include <unistd.h> #endif +#ifdef HAVE_READLINE + #include "readline_buffer.h" +#endif + namespace { #if defined(_WIN32) @@ -238,6 +242,9 @@ namespace tools boost::optional<password_container> password_container::prompt(const bool verify, const char *message) { +#ifdef HAVE_READLINE + rdln::suspend_readline pause_readline; +#endif password_container pass1{}; password_container pass2{}; if (is_cin_tty() ? read_from_tty(verify, message, pass1.m_password, pass2.m_password) : read_from_file(pass1.m_password)) diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt index ec7aa251f..1503b277e 100644 --- a/src/cryptonote_basic/CMakeLists.txt +++ b/src/cryptonote_basic/CMakeLists.txt @@ -26,6 +26,12 @@ # 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. +if(APPLE) + find_library(IOKIT_LIBRARY IOKit) + mark_as_advanced(IOKIT_LIBRARY) + list(APPEND EXTRA_LIBRARIES ${IOKIT_LIBRARY}) +endif() + set(cryptonote_basic_sources account.cpp checkpoints.cpp diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp index eeb7b6094..6928a0ded 100644 --- a/src/cryptonote_basic/miner.cpp +++ b/src/cryptonote_basic/miner.cpp @@ -43,6 +43,16 @@ #include "storages/portable_storage_template_helper.h" #include "boost/logic/tribool.hpp" +#ifdef __APPLE__ + #include <sys/times.h> + #include <IOKit/IOKitLib.h> + #include <IOKit/ps/IOPSKeys.h> + #include <IOKit/ps/IOPowerSources.h> + #include <mach/mach_host.h> + #include <AvailabilityMacros.h> + #include <TargetConditionals.h> +#endif + #undef MONERO_DEFAULT_LOG_CATEGORY #define MONERO_DEFAULT_LOG_CATEGORY "miner" @@ -757,6 +767,23 @@ namespace cryptonote return true; + #elif defined(__APPLE__) + + mach_msg_type_number_t count; + kern_return_t status; + host_cpu_load_info_data_t stats; + count = HOST_CPU_LOAD_INFO_COUNT; + status = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&stats, &count); + if(status != KERN_SUCCESS) + { + return false; + } + + idle_time = stats.cpu_ticks[CPU_STATE_IDLE]; + total_time = idle_time + stats.cpu_ticks[CPU_STATE_USER] + stats.cpu_ticks[CPU_STATE_SYSTEM]; + + return true; + #endif return false; // unsupported systemm.. @@ -779,7 +806,7 @@ namespace cryptonote return true; } - #elif defined(__linux__) && defined(_SC_CLK_TCK) + #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) struct tms tms; if ( times(&tms) != (clock_t)-1 ) @@ -808,6 +835,15 @@ namespace cryptonote return boost::logic::tribool(power_status.ACLineStatus != 1); } + #elif defined(__APPLE__) + + #if TARGET_OS_MAC && (!defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7) + return boost::logic::tribool(IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited); + #else + // iOS or OSX <10.7 + return boost::logic::tribool(boost::logic::indeterminate); + #endif + #elif defined(__linux__) // i've only tested on UBUNTU, these paths might be different on other systems diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 515918cfa..589162a3e 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -556,8 +556,9 @@ namespace cryptonote CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); const uint64_t now = time(NULL); + std::map<uint64_t, txpool_histo> agebytes; stats.txs_total = m_blockchain.get_txpool_tx_count(); - m_blockchain.for_all_txpool_txes([&stats, now](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ + m_blockchain.for_all_txpool_txes([&stats, now, &agebytes](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata *bd){ stats.bytes_total += meta.blob_size; if (!stats.bytes_min || meta.blob_size < stats.bytes_min) stats.bytes_min = meta.blob_size; @@ -572,8 +573,53 @@ namespace cryptonote stats.num_10m++; if (meta.last_failed_height) stats.num_failing++; + uint64_t age = now - meta.receive_time; + agebytes[age].txs++; + agebytes[age].bytes += meta.blob_size; return true; }); + if (stats.txs_total > 1) + { + /* looking for 98th percentile */ + size_t end = stats.txs_total * 0.02; + uint64_t delta, factor; + std::map<uint64_t, txpool_histo>::iterator it, i2; + if (end) + { + /* If enough txs, spread the first 98% of results across + * the first 9 bins, drop final 2% in last bin. + */ + it=agebytes.end(); + for (size_t n=0; n <= end; n++, it--); + stats.histo_98pc = it->first; + factor = 9; + delta = it->first; + stats.histo.resize(10); + } else + { + /* If not enough txs, don't reserve the last slot; + * spread evenly across all 10 bins. + */ + stats.histo_98pc = 0; + it = agebytes.end(); + factor = stats.txs_total > 9 ? 10 : stats.txs_total; + delta = now - stats.oldest; + stats.histo.resize(factor); + } + if (!delta) + delta = 1; + for (i2 = agebytes.begin(); i2 != it; i2++) + { + size_t i = (i2->first * factor - 1) / delta; + stats.histo[i].txs += i2->second.txs; + stats.histo[i].bytes += i2->second.bytes; + } + for (; i2 != agebytes.end(); i2++) + { + stats.histo[factor].txs += i2->second.txs; + stats.histo[factor].bytes += i2->second.bytes; + } + } } //------------------------------------------------------------------ //TODO: investigate whether boolean return is appropriate diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h index fd5b980b8..6f6c1a803 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_defs.h +++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h @@ -49,6 +49,8 @@ namespace cryptonote bool localhost; bool local_ip; + std::string address; + std::string host; std::string ip; std::string port; @@ -76,6 +78,8 @@ namespace cryptonote KV_SERIALIZE(incoming) KV_SERIALIZE(localhost) KV_SERIALIZE(local_ip) + KV_SERIALIZE(address) + KV_SERIALIZE(host) KV_SERIALIZE(ip) KV_SERIALIZE(port) KV_SERIALIZE(peer_id) diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 8b41ce514..0b99aa7bd 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -134,17 +134,12 @@ namespace cryptonote << std::setw(13) << "Up(now)" << ENDL; - uint32_t ip; m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id, uint32_t support_flags) { - bool local_ip = false; - ip = ntohl(cntxt.m_remote_ip); - // TODO: local ip in calss A, B - if (ip > 3232235520 && ip < 3232301055) // 192.168.x.x - local_ip = true; + bool local_ip = cntxt.m_remote_address.is_local(); auto connection_time = time(NULL) - cntxt.m_started; ss << std::setw(30) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") + - epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port) + cntxt.m_remote_address.str() << std::setw(20) << std::hex << peer_id << std::setw(20) << std::hex << support_flags << std::setw(30) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")" @@ -155,7 +150,7 @@ namespace cryptonote << std::setw(10) << std::fixed << (connection_time == 0 ? 0.0 : cntxt.m_send_cnt / connection_time / 1024) << std::setw(13) << std::fixed << cntxt.m_current_speed_up / 1024 << (local_ip ? "[LAN]" : "") - << std::left << (ip == LOCALHOST_INT ? "[LOCALHOST]" : "") // 127.0.0.1 + << std::left << (cntxt.m_remote_address.is_loopback() ? "[LOCALHOST]" : "") // 127.0.0.1 << ENDL; if (connection_time > 1) @@ -193,8 +188,15 @@ namespace cryptonote cnx.incoming = cntxt.m_is_income ? true : false; - cnx.ip = epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip); - cnx.port = std::to_string(cntxt.m_remote_port); + cnx.address = cntxt.m_remote_address.str(); + cnx.host = cntxt.m_remote_address.host_str(); + cnx.ip = ""; + cnx.port = ""; + if (cntxt.m_remote_address.type() == typeid(epee::net_utils::ipv4_network_address)) + { + cnx.ip = cnx.host; + cnx.port = std::to_string(cntxt.m_remote_address.as<epee::net_utils::ipv4_network_address>().port()); + } std::stringstream peer_id_str; peer_id_str << std::hex << peer_id; @@ -212,25 +214,8 @@ namespace cryptonote cnx.live_time = timestamp - cntxt.m_started; - uint32_t ip; - ip = ntohl(cntxt.m_remote_ip); - if (ip == LOCALHOST_INT) - { - cnx.localhost = true; - } - else - { - cnx.localhost = false; - } - - if (ip > 3232235520 && ip < 3232301055) // 192.168.x.x - { - cnx.local_ip = true; - } - else - { - cnx.local_ip = false; - } + cnx.localhost = cntxt.m_remote_address.is_loopback(); + cnx.local_ip = cntxt.m_remote_address.is_local(); auto connection_time = time(NULL) - cntxt.m_started; if (connection_time == 0) @@ -662,9 +647,6 @@ namespace cryptonote return 1; } - for (auto txidx: arg.missing_tx_indices) - MDEBUG(" tx " << b.tx_hashes[txidx]); - std::vector<crypto::hash> txids; NOTIFY_NEW_FLUFFY_BLOCK::request fluffy_response; fluffy_response.b.block = t_serializable_object_to_blob(b); @@ -674,6 +656,7 @@ namespace cryptonote { if(tx_idx < b.tx_hashes.size()) { + MDEBUG(" tx " << b.tx_hashes[tx_idx]); txids.push_back(b.tx_hashes[tx_idx]); } else @@ -990,7 +973,7 @@ namespace cryptonote { LOG_PRINT_CCONTEXT_L1("Block verification failed, dropping connection"); m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); + m_p2p->add_host_fail(context.m_remote_address); m_core.cleanup_handle_incoming_blocks(); return 1; } @@ -998,7 +981,7 @@ namespace cryptonote { LOG_PRINT_CCONTEXT_L1("Block received at sync phase was marked as orphaned, dropping connection"); m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); + m_p2p->add_host_fail(context.m_remote_address); m_core.cleanup_handle_incoming_blocks(); return 1; } @@ -1150,7 +1133,7 @@ skip: { LOG_ERROR_CCONTEXT("sent empty m_block_ids, dropping connection"); m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); + m_p2p->add_host_fail(context.m_remote_address); return 1; } @@ -1159,7 +1142,7 @@ skip: LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: " << epee::string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection"); m_p2p->drop_connection(context); - m_p2p->add_ip_fail(context.m_remote_ip); + m_p2p->add_host_fail(context.m_remote_address); return 1; } diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp index d5bde7f09..1c9cd714d 100644 --- a/src/daemon/rpc_command_executor.cpp +++ b/src/daemon/rpc_command_executor.cpp @@ -92,6 +92,19 @@ namespace { return s + " " + (t > now ? "in the future" : "ago"); } + std::string get_time_hms(time_t t) + { + unsigned int hours, minutes, seconds; + char buffer[24]; + hours = t / 3600; + t %= 3600; + minutes = t / 60; + t %= 60; + seconds = t; + snprintf(buffer, sizeof(buffer), "%02u:%02u:%02u", hours, minutes, seconds); + return std::string(buffer); + } + std::string make_error(const std::string &base, const std::string &status) { if (status == CORE_RPC_STATUS_OK) @@ -939,7 +952,35 @@ bool t_rpc_command_executor::print_transaction_pool_stats() { tools::msg_writer() << n_transactions << " tx(es), " << res.pool_stats.bytes_total << " bytes total (min " << res.pool_stats.bytes_min << ", max " << res.pool_stats.bytes_max << ", avg " << avg_bytes << ")" << std::endl << "fees " << cryptonote::print_money(res.pool_stats.fee_total) << " (avg " << cryptonote::print_money(n_transactions ? res.pool_stats.fee_total / n_transactions : 0) << " per tx" << ", " << cryptonote::print_money(res.pool_stats.bytes_total ? res.pool_stats.fee_total / res.pool_stats.bytes_total : 0) << " per byte )" << std::endl - << res.pool_stats.num_not_relayed << " not relayed, " << res.pool_stats.num_failing << " failing, " << res.pool_stats.num_10m << " older than 10 minutes (oldest " << (res.pool_stats.oldest == 0 ? "-" : get_human_time_ago(res.pool_stats.oldest, now)) << ")" << std::endl; + << res.pool_stats.num_not_relayed << " not relayed, " << res.pool_stats.num_failing << " failing, " << res.pool_stats.num_10m << " older than 10 minutes (oldest " << (res.pool_stats.oldest == 0 ? "-" : get_human_time_ago(res.pool_stats.oldest, now)) << ")"; + + if (n_transactions > 1 && res.pool_stats.histo.size()) + { + std::vector<uint64_t> times; + uint64_t numer; + size_t i, n = res.pool_stats.histo.size(), denom; + times.resize(n); + if (res.pool_stats.histo_98pc) + { + numer = res.pool_stats.histo_98pc; + denom = n-1; + for (i=0; i<denom; i++) + times[i] = i * numer / denom; + times[i] = res.pool_stats.oldest; + } else + { + numer = now - res.pool_stats.oldest; + denom = n; + for (i=0; i<denom; i++) + times[i] = i * numer / denom; + } + tools::msg_writer() << " Age Txes Bytes"; + for (i=0; i<n; i++) + { + tools::msg_writer() << get_time_hms(times[i]) << setw(8) << res.pool_stats.histo[i].txs << setw(12) << res.pool_stats.histo[i].bytes; + } + } + tools::msg_writer(); return true; } diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h index 13cd3f5b0..8798a52e0 100644 --- a/src/p2p/net_node.h +++ b/src/p2p/net_node.h @@ -123,9 +123,9 @@ namespace nodetool size_t get_outgoing_connections_count(); peerlist_manager& get_peerlist_manager(){return m_peerlist;} void delete_connections(size_t count); - virtual bool block_ip(uint32_t adress, time_t seconds = P2P_IP_BLOCKTIME); - virtual bool unblock_ip(uint32_t address); - virtual std::map<uint32_t, time_t> get_blocked_ips() { CRITICAL_REGION_LOCAL(m_blocked_ips_lock); return m_blocked_ips; } + virtual bool block_host(const epee::net_utils::network_address &adress, time_t seconds = P2P_IP_BLOCKTIME); + virtual bool unblock_host(const epee::net_utils::network_address &address); + virtual std::map<std::string, time_t> get_blocked_hosts() { CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); return m_blocked_hosts; } private: const std::vector<std::string> m_seed_nodes_list = { "seeds.moneroseeds.se" @@ -186,11 +186,11 @@ namespace nodetool virtual bool drop_connection(const epee::net_utils::connection_context_base& context); virtual void request_callback(const epee::net_utils::connection_context_base& context); virtual void for_each_connection(std::function<bool(typename t_payload_net_handler::connection_context&, peerid_type, uint32_t)> f); - virtual bool add_ip_fail(uint32_t address); + virtual bool add_host_fail(const epee::net_utils::network_address &address); //----------------- i_connection_filter -------------------------------------------------------- - virtual bool is_remote_ip_allowed(uint32_t adress); + virtual bool is_remote_host_allowed(const epee::net_utils::network_address &address); //----------------------------------------------------------------------------------------------- - bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr); + bool parse_peer_from_string(epee::net_utils::network_address& pe, const std::string& node_addr, uint16_t default_port = 0); bool handle_command_line( const boost::program_options::variables_map& vm ); @@ -209,18 +209,18 @@ namespace nodetool bool make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist); bool make_new_connection_from_peerlist(bool use_white_list); - bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, PeerType peer_type = white, uint64_t first_seen_stamp = 0); + bool try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, PeerType peer_type = white, uint64_t first_seen_stamp = 0); size_t get_random_index_with_fixed_probability(size_t max_index); bool is_peer_used(const peerlist_entry& peer); bool is_peer_used(const anchor_peerlist_entry& peer); - bool is_addr_connected(const net_address& peer); + bool is_addr_connected(const epee::net_utils::network_address& peer); template<class t_callback> bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb); bool try_get_support_flags(const p2p_connection_context& context, std::function<void(p2p_connection_context&, const uint32_t&)> f); bool make_expected_connections_count(PeerType peer_type, size_t expected_connections); - void cache_connect_fail_info(const net_address& addr); - bool is_addr_recently_failed(const net_address& addr); - bool is_priority_node(const net_address& na); + void cache_connect_fail_info(const epee::net_utils::network_address& addr); + bool is_addr_recently_failed(const epee::net_utils::network_address& addr); + bool is_priority_node(const epee::net_utils::network_address& na); std::set<std::string> get_seed_nodes(bool testnet) const; template <class Container> @@ -236,9 +236,9 @@ namespace nodetool bool set_rate_down_limit(const boost::program_options::variables_map& vm, int64_t limit); bool set_rate_limit(const boost::program_options::variables_map& vm, int64_t limit); - bool has_too_many_connections(const uint32_t ip); + bool has_too_many_connections(const epee::net_utils::network_address &address); - bool check_connection_and_handshake_with_peer(const net_address& na, uint64_t last_seen_stamp); + bool check_connection_and_handshake_with_peer(const epee::net_utils::network_address& na, uint64_t last_seen_stamp); bool gray_peerlist_housekeeping(); void kill() { ///< will be called e.g. from deinit() @@ -308,23 +308,23 @@ namespace nodetool #ifdef ALLOW_DEBUG_COMMANDS uint64_t m_last_stat_request_time; #endif - std::list<net_address> m_priority_peers; - std::vector<net_address> m_exclusive_peers; - std::vector<net_address> m_seed_nodes; + std::list<epee::net_utils::network_address> m_priority_peers; + std::vector<epee::net_utils::network_address> m_exclusive_peers; + std::vector<epee::net_utils::network_address> m_seed_nodes; std::list<nodetool::peerlist_entry> m_command_line_peers; uint64_t m_peer_livetime; //keep connections to initiate some interactions net_server m_net_server; boost::uuids::uuid m_network_id; - std::map<net_address, time_t> m_conn_fails_cache; + std::map<epee::net_utils::network_address, time_t> m_conn_fails_cache; epee::critical_section m_conn_fails_cache_lock; - epee::critical_section m_blocked_ips_lock; - std::map<uint32_t, time_t> m_blocked_ips; + epee::critical_section m_blocked_hosts_lock; + std::map<std::string, time_t> m_blocked_hosts; - epee::critical_section m_ip_fails_score_lock; - std::map<uint32_t, uint64_t> m_ip_fails_score; + epee::critical_section m_host_fails_score_lock; + std::map<std::string, uint64_t> m_host_fails_score; bool m_testnet; }; diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl index 5c903b1f5..47582cb96 100644 --- a/src/p2p/net_node.inl +++ b/src/p2p/net_node.inl @@ -200,16 +200,16 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_remote_ip_allowed(uint32_t addr) + bool node_server<t_payload_net_handler>::is_remote_host_allowed(const epee::net_utils::network_address &address) { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - auto it = m_blocked_ips.find(addr); - if(it == m_blocked_ips.end()) + CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); + auto it = m_blocked_hosts.find(address.host_str()); + if(it == m_blocked_hosts.end()) return true; if(time(nullptr) >= it->second) { - m_blocked_ips.erase(it); - MCLOG_CYAN(el::Level::Info, "global", "IP " << epee::string_tools::get_ip_string_from_int32(addr) << " unblocked."); + m_blocked_hosts.erase(it); + MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked."); return true; } return false; @@ -229,16 +229,16 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::block_ip(uint32_t addr, time_t seconds) + bool node_server<t_payload_net_handler>::block_host(const epee::net_utils::network_address &addr, time_t seconds) { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - m_blocked_ips[addr] = time(nullptr) + seconds; + CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); + m_blocked_hosts[addr.host_str()] = time(nullptr) + seconds; // drop any connection to that IP std::list<boost::uuids::uuid> conns; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - if (cntxt.m_remote_ip == addr) + if (cntxt.m_remote_address.is_same_host(addr)) { conns.push_back(cntxt.m_connection_id); } @@ -247,42 +247,42 @@ namespace nodetool for (const auto &c: conns) m_net_server.get_config_object().close(c); - MCLOG_CYAN(el::Level::Info, "global", "IP " << epee::string_tools::get_ip_string_from_int32(addr) << " blocked."); + MCLOG_CYAN(el::Level::Info, "global", "Host " << addr.host_str() << " blocked."); return true; } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::unblock_ip(uint32_t addr) + bool node_server<t_payload_net_handler>::unblock_host(const epee::net_utils::network_address &address) { - CRITICAL_REGION_LOCAL(m_blocked_ips_lock); - auto i = m_blocked_ips.find(addr); - if (i == m_blocked_ips.end()) + CRITICAL_REGION_LOCAL(m_blocked_hosts_lock); + auto i = m_blocked_hosts.find(address.host_str()); + if (i == m_blocked_hosts.end()) return false; - m_blocked_ips.erase(i); - MCLOG_CYAN(el::Level::Info, "global", "IP " << epee::string_tools::get_ip_string_from_int32(addr) << " unblocked."); + m_blocked_hosts.erase(i); + MCLOG_CYAN(el::Level::Info, "global", "Host " << address.host_str() << " unblocked."); return true; } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::add_ip_fail(uint32_t address) + bool node_server<t_payload_net_handler>::add_host_fail(const epee::net_utils::network_address &address) { - CRITICAL_REGION_LOCAL(m_ip_fails_score_lock); - uint64_t fails = ++m_ip_fails_score[address]; - MDEBUG("IP " << epee::string_tools::get_ip_string_from_int32(address) << " fail score=" << fails); + CRITICAL_REGION_LOCAL(m_host_fails_score_lock); + uint64_t fails = ++m_host_fails_score[address.host_str()]; + MDEBUG("Host " << address.host_str() << " fail score=" << fails); if(fails > P2P_IP_FAILS_BEFORE_BLOCK) { - auto it = m_ip_fails_score.find(address); - CHECK_AND_ASSERT_MES(it != m_ip_fails_score.end(), false, "internal error"); + auto it = m_host_fails_score.find(address.host_str()); + CHECK_AND_ASSERT_MES(it != m_host_fails_score.end(), false, "internal error"); it->second = P2P_IP_FAILS_BEFORE_BLOCK/2; - block_ip(address); + block_host(address); } return true; } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr) + bool node_server<t_payload_net_handler>::parse_peer_from_string(epee::net_utils::network_address& pe, const std::string& node_addr, uint16_t default_port) { - return epee::string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr); + return epee::net_utils::create_network_address(pe, node_addr, default_port); } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> @@ -306,10 +306,9 @@ namespace nodetool { nodetool::peerlist_entry pe = AUTO_VAL_INIT(pe); pe.id = crypto::rand<uint64_t>(); - bool r = parse_peer_from_string(pe.adr, pr_str); + const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; + bool r = parse_peer_from_string(pe.adr, pr_str, default_port); CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - if (pe.adr.port == 0) - pe.adr.port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; m_command_line_peers.push_back(pe); } } @@ -359,7 +358,7 @@ namespace nodetool } //----------------------------------------------------------------------------------- inline void append_net_address( - std::vector<net_address> & seed_nodes + std::vector<epee::net_utils::network_address> & seed_nodes , std::string const & addr ) { @@ -383,15 +382,14 @@ namespace nodetool ip::tcp::endpoint endpoint = *i; if (endpoint.address().is_v4()) { - nodetool::net_address na; - na.ip = boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_ulong()); - na.port = endpoint.port(); + epee::net_utils::network_address na(new epee::net_utils::ipv4_network_address(boost::asio::detail::socket_ops::host_to_network_long(endpoint.address().to_v4().to_ulong()), endpoint.port())); seed_nodes.push_back(na); - MINFO("Added seed node: " << endpoint.address().to_v4().to_string(ec) << ':' << na.port); + MINFO("Added seed node: " << na.str()); } else { - MDEBUG("IPv6 doesn't supported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); + MERROR("IPv6 unsupported, skip '" << host << "' -> " << endpoint.address().to_v6().to_string(ec)); + throw std::runtime_error("IPv6 unsupported"); } } } @@ -752,10 +750,10 @@ namespace nodetool return; } - if(!handle_remote_peerlist(rsp.local_peerlist, rsp.node_data.local_time, context)) + if(!handle_remote_peerlist(rsp.local_peerlist_new, rsp.node_data.local_time, context)) { LOG_ERROR_CC(context, "COMMAND_HANDSHAKE: failed to handle_remote_peerlist(...), closing connection."); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); return; } hsh_result = true; @@ -769,7 +767,7 @@ namespace nodetool } pi = context.peer_id = rsp.node_data.peer_id; - m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_ip, context.m_remote_port); + m_peerlist.set_peer_just_seen(rsp.node_data.peer_id, context.m_remote_address); if(rsp.node_data.peer_id == m_config.m_peer_id) { @@ -820,14 +818,14 @@ namespace nodetool return; } - if(!handle_remote_peerlist(rsp.local_peerlist, rsp.local_time, context)) + if(!handle_remote_peerlist(rsp.local_peerlist_new, rsp.local_time, context)) { LOG_WARNING_CC(context, "COMMAND_TIMED_SYNC: failed to handle_remote_peerlist(...), closing connection."); m_net_server.get_config_object().close(context.m_connection_id ); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); } if(!context.m_is_income) - m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_ip, context.m_remote_port); + m_peerlist.set_peer_just_seen(context.peer_id, context.m_remote_address); m_payload_handler.process_payload_sync_data(rsp.payload_data, context, false); }); @@ -862,7 +860,7 @@ namespace nodetool bool used = false; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr.ip == cntxt.m_remote_ip && peer.adr.port == cntxt.m_remote_port)) + if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address)) { used = true; return false;//stop enumerating @@ -884,7 +882,7 @@ namespace nodetool m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr.ip == cntxt.m_remote_ip && peer.adr.port == cntxt.m_remote_port)) + if(cntxt.peer_id == peer.id || (!cntxt.m_is_income && peer.adr == cntxt.m_remote_address)) { used = true; @@ -898,12 +896,12 @@ namespace nodetool } //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_addr_connected(const net_address& peer) + bool node_server<t_payload_net_handler>::is_addr_connected(const epee::net_utils::network_address& peer) { bool connected = false; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - if(!cntxt.m_is_income && peer.ip == cntxt.m_remote_ip && peer.port == cntxt.m_remote_port) + if(!cntxt.m_is_income && peer == cntxt.m_remote_address) { connected = true; return false;//stop enumerating @@ -924,7 +922,7 @@ namespace nodetool } while(0) template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp) + bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const epee::net_utils::network_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, PeerType peer_type, uint64_t first_seen_stamp) { if (m_current_number_of_out_peers == m_config.m_net_config.connections_count) // out peers limit { @@ -936,23 +934,24 @@ namespace nodetool m_current_number_of_out_peers --; // atomic variable, update time = 1s return false; } - MDEBUG("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":" - << epee::string_tools::num_to_string_fast(na.port) << "(peer_type=" << peer_type << ", last_seen: " + MDEBUG("Connecting to " << na.str() << "(peer_type=" << peer_type << ", last_seen: " << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never") << ")..."); + CHECK_AND_ASSERT_MES(na.type() == typeid(epee::net_utils::ipv4_network_address), false, + "Only IPv4 addresses are supported here, got " << na.type().name()); + const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>(); + typename net_server::t_connection_context con = AUTO_VAL_INIT(con); - bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(na.ip), - epee::string_tools::num_to_string_fast(na.port), + bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), + epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, con); if(!res) { bool is_priority = is_priority_node(na); - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " - << epee::string_tools::get_ip_string_from_int32(na.ip) - << ":" << epee::string_tools::num_to_string_fast(na.port) + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str() /*<< ", try " << try_count*/); //m_peerlist.set_peer_unreachable(pe); return false; @@ -965,8 +964,7 @@ namespace nodetool { bool is_priority = is_priority_node(na); LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " - << epee::string_tools::get_ip_string_from_int32(na.ip) - << ":" << epee::string_tools::num_to_string_fast(na.port) + << na.str() /*<< ", try " << try_count*/); return false; } @@ -999,25 +997,26 @@ namespace nodetool } template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::check_connection_and_handshake_with_peer(const net_address& na, uint64_t last_seen_stamp) + bool node_server<t_payload_net_handler>::check_connection_and_handshake_with_peer(const epee::net_utils::network_address& na, uint64_t last_seen_stamp) { - LOG_PRINT_L1("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":" - << epee::string_tools::num_to_string_fast(na.port) << "(last_seen: " + LOG_PRINT_L1("Connecting to " << na.str() << "(last_seen: " << (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never") << ")..."); + CHECK_AND_ASSERT_MES(na.type() == typeid(epee::net_utils::ipv4_network_address), false, + "Only IPv4 addresses are supported here, got " << na.type().name()); + const epee::net_utils::ipv4_network_address &ipv4 = na.as<epee::net_utils::ipv4_network_address>(); + typename net_server::t_connection_context con = AUTO_VAL_INIT(con); - bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(na.ip), - epee::string_tools::num_to_string_fast(na.port), + bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(ipv4.ip()), + epee::string_tools::num_to_string_fast(ipv4.port()), m_config.m_net_config.connection_timeout, con); if (!res) { bool is_priority = is_priority_node(na); - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " - << epee::string_tools::get_ip_string_from_int32(na.ip) - << ":" << epee::string_tools::num_to_string_fast(na.port)); + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to " << na.str()); return false; } @@ -1028,9 +1027,7 @@ namespace nodetool if (!res) { bool is_priority = is_priority_node(na); - LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " - << epee::string_tools::get_ip_string_from_int32(na.ip) - << ":" << epee::string_tools::num_to_string_fast(na.port)); + LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer " << na.str()); return false; } @@ -1046,7 +1043,7 @@ namespace nodetool //----------------------------------------------------------------------------------- template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_addr_recently_failed(const net_address& addr) + bool node_server<t_payload_net_handler>::is_addr_recently_failed(const epee::net_utils::network_address& addr) { CRITICAL_REGION_LOCAL(m_conn_fails_cache_lock); auto it = m_conn_fails_cache.find(addr); @@ -1063,14 +1060,14 @@ namespace nodetool bool node_server<t_payload_net_handler>::make_new_connection_from_anchor_peerlist(const std::vector<anchor_peerlist_entry>& anchor_peerlist) { for (const auto& pe: anchor_peerlist) { - _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port)); + _note("Considering connecting (out) to peer: " << pe.id << " " << pe.adr.str()); if(is_peer_used(pe)) { _note("Peer is used"); continue; } - if(!is_remote_ip_allowed(pe.adr.ip)) { + if(!is_remote_host_allowed(pe.adr)) { continue; } @@ -1078,8 +1075,7 @@ namespace nodetool continue; } - MDEBUG("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) - << ":" << boost::lexical_cast<std::string>(pe.adr.port) + MDEBUG("Selected peer: " << pe.id << " " << pe.adr.str() << "[peer_type=" << anchor << "] first_seen: " << epee::misc_utils::get_time_interval_string(time(NULL) - pe.first_seen)); @@ -1130,21 +1126,20 @@ namespace nodetool ++try_count; - _note("Considering connecting (out) to peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port)); + _note("Considering connecting (out) to peer: " << pe.id << " " << pe.adr.str()); if(is_peer_used(pe)) { _note("Peer is used"); continue; } - if(!is_remote_ip_allowed(pe.adr.ip)) + if(!is_remote_host_allowed(pe.adr)) continue; if(is_addr_recently_failed(pe.adr)) continue; - MDEBUG("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) - << ":" << boost::lexical_cast<std::string>(pe.adr.port) + MDEBUG("Selected peer: " << pe.id << " " << pe.adr.str() << "[peer_list=" << (use_white_list ? white : gray) << "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never")); @@ -1325,7 +1320,7 @@ namespace nodetool { if(be.last_seen > local_time) { - MWARNING("FOUND FUTURE peerlist for entry " << epee::string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); + MWARNING("FOUND FUTURE peerlist for entry " << be.adr.str() << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time); return false; } be.last_seen += delta; @@ -1421,8 +1416,7 @@ namespace nodetool m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { connection_entry ce; - ce.adr.ip = cntxt.m_remote_ip; - ce.adr.port = cntxt.m_remote_port; + ce.adr = cntxt.m_remote_address; ce.id = cntxt.peer_id; ce.is_income = cntxt.m_is_income; rsp.connections_list.push_back(ce); @@ -1512,19 +1506,24 @@ namespace nodetool if(!node_data.my_port) return false; - uint32_t actual_ip = context.m_remote_ip; - if(!m_peerlist.is_ip_allowed(actual_ip)) + CHECK_AND_ASSERT_MES(context.m_remote_address.type() == typeid(epee::net_utils::ipv4_network_address), false, + "Only IPv4 addresses are supported here, got " << context.m_remote_address.type().name()); + + const epee::net_utils::network_address na = context.m_remote_address; + uint32_t actual_ip = na.as<const epee::net_utils::ipv4_network_address>().ip(); + if(!m_peerlist.is_host_allowed(context.m_remote_address)) return false; std::string ip = epee::string_tools::get_ip_string_from_int32(actual_ip); std::string port = epee::string_tools::num_to_string_fast(node_data.my_port); + epee::net_utils::network_address address(new epee::net_utils::ipv4_network_address(actual_ip, node_data.my_port)); peerid_type pr = node_data.peer_id; - bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ ip, port, pr, this]( + bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ address, pr, this]( const typename net_server::t_connection_context& ping_context, const boost::system::error_code& ec)->bool { if(ec) { - LOG_WARNING_CC(ping_context, "back ping connect failed to " << ip << ":" << port); + LOG_WARNING_CC(ping_context, "back ping connect failed to " << address.str()); return false; } COMMAND_PING::request req; @@ -1543,13 +1542,13 @@ namespace nodetool { if(code <= 0) { - LOG_ERROR_CC(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << epee::levin::get_err_descr(code) << ")"); + LOG_ERROR_CC(ping_context, "Failed to invoke COMMAND_PING to " << address.str() << "(" << code << ", " << epee::levin::get_err_descr(code) << ")"); return; } if(rsp.status != PING_OK_RESPONSE_STATUS_TEXT || pr != rsp.peer_id) { - LOG_ERROR_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << ip << ":" << port << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << rsp.peer_id); + LOG_ERROR_CC(ping_context, "back ping invoke wrong response \"" << rsp.status << "\" from" << address.str() << ", hsh_peer_id=" << pr_ << ", rsp.peer_id=" << rsp.peer_id); m_net_server.get_config_object().close(ping_context.m_connection_id); return; } @@ -1559,7 +1558,7 @@ namespace nodetool if(!inv_call_res) { - LOG_ERROR_CC(ping_context, "back ping invoke failed to " << ip << ":" << port); + LOG_ERROR_CC(ping_context, "back ping invoke failed to " << address.str()); m_net_server.get_config_object().close(ping_context.m_connection_id); return false; } @@ -1610,7 +1609,7 @@ namespace nodetool //fill response rsp.local_time = time(NULL); - m_peerlist.get_peerlist_head(rsp.local_peerlist); + m_peerlist.get_peerlist_head(rsp.local_peerlist_new); m_payload_handler.get_payload_sync_data(rsp.payload_data); LOG_DEBUG_CC(context, "COMMAND_TIMED_SYNC"); return 1; @@ -1624,7 +1623,7 @@ namespace nodetool LOG_INFO_CC(context, "WRONG NETWORK AGENT CONNECTED! id=" << epee::string_tools::get_str_from_guid_a(arg.node_data.network_id)); drop_connection(context); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); return 1; } @@ -1632,7 +1631,7 @@ namespace nodetool { LOG_ERROR_CC(context, "COMMAND_HANDSHAKE came not from incoming connection"); drop_connection(context); - add_ip_fail(context.m_remote_ip); + add_host_fail(context.m_remote_address); return 1; } @@ -1650,9 +1649,9 @@ namespace nodetool return 1; } - if(has_too_many_connections(context.m_remote_ip)) + if(has_too_many_connections(context.m_remote_address)) { - LOG_PRINT_CCONTEXT_L1("CONNECTION FROM " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << " REFUSED, too many connections from the same address"); + LOG_PRINT_CCONTEXT_L1("CONNECTION FROM " << context.m_remote_address.host_str() << " REFUSED, too many connections from the same address"); drop_connection(context); return 1; } @@ -1667,16 +1666,18 @@ namespace nodetool //try ping to be sure that we can add this peer to peer_list try_ping(arg.node_data, context, [peer_id_l, port_l, context, this]() { + CHECK_AND_ASSERT_MES(context.m_remote_address.type() == typeid(epee::net_utils::ipv4_network_address), void(), + "Only IPv4 addresses are supported here, got " << context.m_remote_address.type().name()); //called only(!) if success pinged, update local peerlist peerlist_entry pe; - pe.adr.ip = context.m_remote_ip; - pe.adr.port = port_l; + const epee::net_utils::network_address na = context.m_remote_address; + pe.adr.reset(new epee::net_utils::ipv4_network_address(na.as<epee::net_utils::ipv4_network_address>().ip(), port_l)); time_t last_seen; time(&last_seen); pe.last_seen = static_cast<int64_t>(last_seen); pe.id = peer_id_l; this->m_peerlist.append_with_peer_white(pe); - LOG_DEBUG_CC(context, "PING SUCCESS " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l); + LOG_DEBUG_CC(context, "PING SUCCESS " << context.m_remote_address.host_str() << ":" << port_l); }); } @@ -1686,7 +1687,7 @@ namespace nodetool }); //fill response - m_peerlist.get_peerlist_head(rsp.local_peerlist); + m_peerlist.get_peerlist_head(rsp.local_peerlist_new); get_local_node_data(rsp.node_data); m_payload_handler.get_payload_sync_data(rsp.payload_data); LOG_DEBUG_CC(context, "COMMAND_HANDSHAKE"); @@ -1726,7 +1727,7 @@ namespace nodetool std::stringstream ss; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - ss << epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port + ss << cntxt.m_remote_address.str() << " \t\tpeer_id " << cntxt.peer_id << " \t\tconn_id " << epee::string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT") << std::endl; @@ -1746,9 +1747,8 @@ namespace nodetool void node_server<t_payload_net_handler>::on_connection_close(p2p_connection_context& context) { if (!m_net_server.is_stop_signal_sent() && !context.m_is_income) { - nodetool::net_address na = AUTO_VAL_INIT(na); - na.ip = context.m_remote_ip; - na.port = context.m_remote_port; + epee::net_utils::network_address na = AUTO_VAL_INIT(na); + na = context.m_remote_address; m_peerlist.remove_from_peer_anchor(na); } @@ -1757,7 +1757,7 @@ namespace nodetool } template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::is_priority_node(const net_address& na) + bool node_server<t_payload_net_handler>::is_priority_node(const epee::net_utils::network_address& na) { return (std::find(m_priority_peers.begin(), m_priority_peers.end(), na) != m_priority_peers.end()) || (std::find(m_exclusive_peers.begin(), m_exclusive_peers.end(), na) != m_exclusive_peers.end()); } @@ -1765,7 +1765,7 @@ namespace nodetool template<class t_payload_net_handler> template <class Container> bool node_server<t_payload_net_handler>::connect_to_peerlist(const Container& peers) { - for(const net_address& na: peers) + for(const epee::net_utils::network_address& na: peers) { if(m_net_server.is_stop_signal_sent()) return false; @@ -1786,11 +1786,10 @@ namespace nodetool for(const std::string& pr_str: perrs) { - nodetool::net_address na = AUTO_VAL_INIT(na); - bool r = parse_peer_from_string(na, pr_str); + epee::net_utils::network_address na = AUTO_VAL_INIT(na); + const uint16_t default_port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; + bool r = parse_peer_from_string(na, pr_str, default_port); CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str); - if (na.port == 0) - na.port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT; container.push_back(na); } @@ -1884,14 +1883,14 @@ namespace nodetool } template<class t_payload_net_handler> - bool node_server<t_payload_net_handler>::has_too_many_connections(const uint32_t ip) + bool node_server<t_payload_net_handler>::has_too_many_connections(const epee::net_utils::network_address &address) { const uint8_t max_connections = 1; uint8_t count = 0; m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt) { - if (cntxt.m_is_income && cntxt.m_remote_ip == ip) { + if (cntxt.m_is_income && cntxt.m_remote_address.is_same_host(address)) { count++; if (count > max_connections) { @@ -1919,14 +1918,14 @@ namespace nodetool if (!success) { m_peerlist.remove_from_peer_gray(pe); - LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << " Peer ID: " << std::hex << pe.id); + LOG_PRINT_L2("PEER EVICTED FROM GRAY PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << std::hex << pe.id); return true; } m_peerlist.set_peer_just_seen(pe.id, pe.adr); - LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << " Peer ID: " << std::hex << pe.id); + LOG_PRINT_L2("PEER PROMOTED TO WHITE PEER LIST IP address: " << pe.adr.host_str() << " Peer ID: " << std::hex << pe.id); return true; } diff --git a/src/p2p/net_node_common.h b/src/p2p/net_node_common.h index 6aba7aa24..42de2655d 100644 --- a/src/p2p/net_node_common.h +++ b/src/p2p/net_node_common.h @@ -51,10 +51,10 @@ namespace nodetool virtual void request_callback(const epee::net_utils::connection_context_base& context)=0; virtual uint64_t get_connections_count()=0; virtual void for_each_connection(std::function<bool(t_connection_context&, peerid_type, uint32_t)> f)=0; - virtual bool block_ip(uint32_t adress, time_t seconds = 0)=0; - virtual bool unblock_ip(uint32_t adress)=0; - virtual std::map<uint32_t, time_t> get_blocked_ips()=0; - virtual bool add_ip_fail(uint32_t adress)=0; + virtual bool block_host(const epee::net_utils::network_address &address, time_t seconds = 0)=0; + virtual bool unblock_host(const epee::net_utils::network_address &address)=0; + virtual std::map<std::string, time_t> get_blocked_hosts()=0; + virtual bool add_host_fail(const epee::net_utils::network_address &address)=0; }; template<class t_connection_context> @@ -93,19 +93,19 @@ namespace nodetool { return false; } - virtual bool block_ip(uint32_t adress, time_t seconds) + virtual bool block_host(const epee::net_utils::network_address &address, time_t seconds) { return true; } - virtual bool unblock_ip(uint32_t adress) + virtual bool unblock_host(const epee::net_utils::network_address &address) { return true; } - virtual std::map<uint32_t, time_t> get_blocked_ips() + virtual std::map<std::string, time_t> get_blocked_hosts() { - return std::map<uint32_t, time_t>(); + return std::map<std::string, time_t>(); } - virtual bool add_ip_fail(uint32_t adress) + virtual bool add_host_fail(const epee::net_utils::network_address &address) { return true; } diff --git a/src/p2p/net_peerlist.h b/src/p2p/net_peerlist.h index de0f51cc3..a30a05422 100644 --- a/src/p2p/net_peerlist.h +++ b/src/p2p/net_peerlist.h @@ -54,7 +54,7 @@ #include "net_peerlist_boost_serialization.h" -#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 5 +#define CURRENT_PEERLIST_STORAGE_ARCHIVE_VER 6 namespace nodetool { @@ -78,14 +78,13 @@ namespace nodetool bool append_with_peer_white(const peerlist_entry& pr); bool append_with_peer_gray(const peerlist_entry& pr); bool append_with_peer_anchor(const anchor_peerlist_entry& ple); - bool set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port); - bool set_peer_just_seen(peerid_type peer, const net_address& addr); + bool set_peer_just_seen(peerid_type peer, const epee::net_utils::network_address& addr); bool set_peer_unreachable(const peerlist_entry& pr); - bool is_ip_allowed(uint32_t ip); + bool is_host_allowed(const epee::net_utils::network_address &address); bool get_random_gray_peer(peerlist_entry& pe); bool remove_from_peer_gray(const peerlist_entry& pe); bool get_and_empty_anchor_peerlist(std::vector<anchor_peerlist_entry>& apl); - bool remove_from_peer_anchor(const net_address& addr); + bool remove_from_peer_anchor(const epee::net_utils::network_address& addr); private: struct by_time{}; @@ -130,7 +129,7 @@ namespace nodetool peerlist_entry, boost::multi_index::indexed_by< // access by peerlist_entry::net_adress - boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >, + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,epee::net_utils::network_address,&peerlist_entry::adr> >, // sort by peerlist_entry::last_seen< boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > @@ -142,7 +141,7 @@ namespace nodetool // access by peerlist_entry::id< boost::multi_index::ordered_unique<boost::multi_index::tag<by_id>, boost::multi_index::member<peerlist_entry,uint64_t,&peerlist_entry::id> >, // access by peerlist_entry::net_adress - boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,net_address,&peerlist_entry::adr> >, + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<peerlist_entry,epee::net_utils::network_address,&peerlist_entry::adr> >, // sort by peerlist_entry::last_seen< boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<peerlist_entry,int64_t,&peerlist_entry::last_seen> > > @@ -152,16 +151,45 @@ namespace nodetool anchor_peerlist_entry, boost::multi_index::indexed_by< // access by anchor_peerlist_entry::net_adress - boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<anchor_peerlist_entry,net_address,&anchor_peerlist_entry::adr> >, + boost::multi_index::ordered_unique<boost::multi_index::tag<by_addr>, boost::multi_index::member<anchor_peerlist_entry,epee::net_utils::network_address,&anchor_peerlist_entry::adr> >, // sort by anchor_peerlist_entry::first_seen boost::multi_index::ordered_non_unique<boost::multi_index::tag<by_time>, boost::multi_index::member<anchor_peerlist_entry,int64_t,&anchor_peerlist_entry::first_seen> > > > anchor_peers_indexed; public: + template <class Archive, class List, class Element, class t_version_type> + void serialize_peers(Archive &a, List &list, Element ple, const t_version_type ver) + { + if (typename Archive::is_saving()) + { + uint64_t size = list.size(); + a & size; + for (auto p: list) + { + a & p; + } + } + else + { + uint64_t size; + a & size; + list.clear(); + while (size--) + { + a & ple; + list.insert(ple); + } + } + } + template <class Archive, class t_version_type> void serialize(Archive &a, const t_version_type ver) { + // at v6, we drop existing peerlists, because annoying change + if (ver < 6) + return; + if(ver < 3) return; CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -174,14 +202,25 @@ namespace nodetool return; } +#if 0 + // trouble loading more than one peer, can't find why a & m_peers_white; a & m_peers_gray; +#else + serialize_peers(a, m_peers_white, peerlist_entry(), ver); + serialize_peers(a, m_peers_gray, peerlist_entry(), ver); +#endif if(ver < 5) { return; } +#if 0 + // trouble loading more than one peer, can't find why a & m_peers_anchor; +#else + serialize_peers(a, m_peers_anchor, anchor_peerlist_entry(), ver); +#endif } private: @@ -284,13 +323,13 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::is_ip_allowed(uint32_t ip) + bool peerlist_manager::is_host_allowed(const epee::net_utils::network_address &address) { //never allow loopback ip - if(epee::net_utils::is_ip_loopback(ip)) + if(address.is_loopback()) return false; - if(!m_allow_local_ip && epee::net_utils::is_ip_local(ip)) + if(!m_allow_local_ip && address.is_local()) return false; return true; @@ -336,16 +375,7 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::set_peer_just_seen(peerid_type peer, uint32_t ip, uint32_t port) - { - net_address addr; - addr.ip = ip; - addr.port = port; - return set_peer_just_seen(peer, addr); - } - //-------------------------------------------------------------------------------------------------- - inline - bool peerlist_manager::set_peer_just_seen(peerid_type peer, const net_address& addr) + bool peerlist_manager::set_peer_just_seen(peerid_type peer, const epee::net_utils::network_address& addr) { TRY_ENTRY(); CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -362,7 +392,7 @@ namespace nodetool bool peerlist_manager::append_with_peer_white(const peerlist_entry& ple) { TRY_ENTRY(); - if(!is_ip_allowed(ple.adr.ip)) + if(!is_host_allowed(ple.adr)) return true; CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -392,7 +422,7 @@ namespace nodetool bool peerlist_manager::append_with_peer_gray(const peerlist_entry& ple) { TRY_ENTRY(); - if(!is_ip_allowed(ple.adr.ip)) + if(!is_host_allowed(ple.adr)) return true; CRITICAL_REGION_LOCAL(m_peerlist_lock); @@ -496,7 +526,7 @@ namespace nodetool } //-------------------------------------------------------------------------------------------------- inline - bool peerlist_manager::remove_from_peer_anchor(const net_address& addr) + bool peerlist_manager::remove_from_peer_anchor(const epee::net_utils::network_address& addr) { TRY_ENTRY(); diff --git a/src/p2p/net_peerlist_boost_serialization.h b/src/p2p/net_peerlist_boost_serialization.h index 6891ac80c..0a21895cf 100644 --- a/src/p2p/net_peerlist_boost_serialization.h +++ b/src/p2p/net_peerlist_boost_serialization.h @@ -30,16 +30,43 @@ #pragma once +#include "net/net_utils_base.h" + namespace boost { namespace serialization { - //BOOST_CLASS_VERSION(odetool::net_adress, 1) + enum { sertype_ipv4_address }; + static inline uint8_t get_type(const epee::net_utils::network_address &na) + { + if (na.type() == typeid(epee::net_utils::ipv4_network_address)) + return sertype_ipv4_address; + throw std::runtime_error("Unsupported network address type"); + return 0; + } + template <class Archive, class ver_type> + inline void serialize(Archive &a, epee::net_utils::network_address& na, const ver_type ver) + { + uint8_t type; + if (typename Archive::is_saving()) + type = get_type(na); + a & type; + switch (type) + { + case sertype_ipv4_address: + if (!typename Archive::is_saving()) + na.reset(new epee::net_utils::ipv4_network_address(0, 0)); + a & na.as<epee::net_utils::ipv4_network_address>(); + break; + default: + throw std::runtime_error("Unsupported network address type"); + } + } template <class Archive, class ver_type> - inline void serialize(Archive &a, nodetool::net_address& na, const ver_type ver) + inline void serialize(Archive &a, epee::net_utils::ipv4_network_address& na, const ver_type ver) { - a & na.ip; - a & na.port; + a & na.m_ip; + a & na.m_port; } diff --git a/src/p2p/p2p_protocol_defs.h b/src/p2p/p2p_protocol_defs.h index 5ec012714..d60990f8a 100644 --- a/src/p2p/p2p_protocol_defs.h +++ b/src/p2p/p2p_protocol_defs.h @@ -32,6 +32,7 @@ #include <boost/uuid/uuid.hpp> #include "serialization/keyvalue_serialization.h" +#include "net/net_utils_base.h" #include "misc_language.h" #include "cryptonote_config.h" #include "crypto/crypto.h" @@ -43,46 +44,64 @@ namespace nodetool #pragma pack (push, 1) - struct net_address + struct network_address_old { uint32_t ip; uint32_t port; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(ip) + KV_SERIALIZE(port) + END_KV_SERIALIZE_MAP() }; - struct peerlist_entry + template<typename AddressType> + struct peerlist_entry_base { - net_address adr; + AddressType adr; peerid_type id; int64_t last_seen; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(adr) + KV_SERIALIZE(id) + KV_SERIALIZE(last_seen) + END_KV_SERIALIZE_MAP() }; + typedef peerlist_entry_base<epee::net_utils::network_address> peerlist_entry; - struct anchor_peerlist_entry + template<typename AddressType> + struct anchor_peerlist_entry_base { - net_address adr; + AddressType adr; peerid_type id; int64_t first_seen; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(adr) + KV_SERIALIZE(id) + KV_SERIALIZE(first_seen) + END_KV_SERIALIZE_MAP() }; + typedef anchor_peerlist_entry_base<epee::net_utils::network_address> anchor_peerlist_entry; - struct connection_entry + template<typename AddressType> + struct connection_entry_base { - net_address adr; + AddressType adr; peerid_type id; bool is_income; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(adr) + KV_SERIALIZE(id) + KV_SERIALIZE(is_income) + END_KV_SERIALIZE_MAP() }; + typedef connection_entry_base<epee::net_utils::network_address> connection_entry; #pragma pack(pop) - inline - bool operator < (const net_address& a, const net_address& b) - { - return epee::misc_utils::is_less_as_pod(a, b); - } - - inline - bool operator == (const net_address& a, const net_address& b) - { - return memcmp(&a, &b, sizeof(a)) == 0; - } inline std::string print_peerlist_to_string(const std::list<peerlist_entry>& pl) { @@ -92,7 +111,7 @@ namespace nodetool ss << std::setfill ('0') << std::setw (8) << std::hex << std::noshowbase; for(const peerlist_entry& pe: pl) { - ss << pe.id << "\t" << epee::string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port) << " \tlast_seen: " << epee::misc_utils::get_time_interval_string(now_time - pe.last_seen) << std::endl; + ss << pe.id << "\t" << pe.adr->str() << " \tlast_seen: " << epee::misc_utils::get_time_interval_string(now_time - pe.last_seen) << std::endl; } return ss.str(); } @@ -157,12 +176,40 @@ namespace nodetool { basic_node_data node_data; t_playload_type payload_data; - std::list<peerlist_entry> local_peerlist; + std::list<peerlist_entry> local_peerlist_new; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(node_data) KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) + if (is_store) + { + // saving: save both, so old and new peers can understand it + KV_SERIALIZE(local_peerlist_new) + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + for (const auto &p: this_ref.local_peerlist_new) + { + if (p.adr.type() == typeid(epee::net_utils::ipv4_network_address)) + { + const epee::net_utils::network_address &na = p.adr; + const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>(); + local_peerlist.push_back(peerlist_entry_base<network_address_old>({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen})); + } + else + MDEBUG("Not including in legacy peer list: " << p.adr.str()); + } + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + } + else + { + // loading: load old list only if there is no new one + if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new")) + { + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + for (const auto &p: local_peerlist) + ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({new epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); + } + } END_KV_SERIALIZE_MAP() }; }; @@ -188,12 +235,40 @@ namespace nodetool { uint64_t local_time; t_playload_type payload_data; - std::list<peerlist_entry> local_peerlist; + std::list<peerlist_entry> local_peerlist_new; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(local_time) KV_SERIALIZE(payload_data) - KV_SERIALIZE_CONTAINER_POD_AS_BLOB(local_peerlist) + if (is_store) + { + // saving: save both, so old and new peers can understand it + KV_SERIALIZE(local_peerlist_new) + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + for (const auto &p: this_ref.local_peerlist_new) + { + if (p.adr.type() == typeid(epee::net_utils::ipv4_network_address)) + { + const epee::net_utils::network_address &na = p.adr; + const epee::net_utils::ipv4_network_address &ipv4 = na.as<const epee::net_utils::ipv4_network_address>(); + local_peerlist.push_back(peerlist_entry_base<network_address_old>({{ipv4.ip(), ipv4.port()}, p.id, p.last_seen})); + } + else + MDEBUG("Not including in legacy peer list: " << p.adr.str()); + } + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + } + else + { + // loading: load old list only if there is no new one + if (!epee::serialization::selector<is_store>::serialize(this_ref.local_peerlist_new, stg, hparent_section, "local_peerlist_new")) + { + std::list<peerlist_entry_base<network_address_old>> local_peerlist; + epee::serialization::selector<is_store>::serialize_stl_container_pod_val_as_blob(local_peerlist, stg, hparent_section, "local_peerlist"); + for (const auto &p: local_peerlist) + ((response&)this_ref).local_peerlist_new.push_back(peerlist_entry({new epee::net_utils::ipv4_network_address(p.adr.ip, p.adr.port), p.id, p.last_seen})); + } + } END_KV_SERIALIZE_MAP() }; }; diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 43891458c..7dc5a1fd9 100644 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -736,12 +736,20 @@ namespace cryptonote for (auto & entry : white_list) { - res.white_list.emplace_back(entry.id, entry.adr.ip, entry.adr.port, entry.last_seen); + if (entry.adr.type() == typeid(epee::net_utils::ipv4_network_address)) + res.white_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(), + entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen); + else + res.white_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen); } for (auto & entry : gray_list) { - res.gray_list.emplace_back(entry.id, entry.adr.ip, entry.adr.port, entry.last_seen); + if (entry.adr.type() == typeid(epee::net_utils::ipv4_network_address)) + res.gray_list.emplace_back(entry.id, entry.adr.as<epee::net_utils::ipv4_network_address>().ip(), + entry.adr.as<epee::net_utils::ipv4_network_address>().port(), entry.last_seen); + else + res.gray_list.emplace_back(entry.id, entry.adr.str(), entry.last_seen); } res.status = CORE_RPC_STATUS_OK; @@ -1308,12 +1316,16 @@ namespace cryptonote } auto now = time(nullptr); - std::map<uint32_t, time_t> blocked_ips = m_p2p.get_blocked_ips(); - for (std::map<uint32_t, time_t>::const_iterator i = blocked_ips.begin(); i != blocked_ips.end(); ++i) + std::map<std::string, time_t> blocked_hosts = m_p2p.get_blocked_hosts(); + for (std::map<std::string, time_t>::const_iterator i = blocked_hosts.begin(); i != blocked_hosts.end(); ++i) { if (i->second > now) { COMMAND_RPC_GETBANS::ban b; - b.ip = i->first; + b.host = i->first; + b.ip = 0; + uint32_t ip; + if (epee::string_tools::get_ip_int32_from_string(ip, i->first)) + b.ip = ip; b.seconds = i->second - now; res.bans.push_back(b); } @@ -1334,10 +1346,24 @@ namespace cryptonote for (auto i = req.bans.begin(); i != req.bans.end(); ++i) { + epee::net_utils::network_address na; + if (!i->host.empty()) + { + if (!epee::net_utils::create_network_address(na, i->host)) + { + error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM; + error_resp.message = "Unsupported host type"; + return false; + } + } + else + { + na.reset(new epee::net_utils::ipv4_network_address(i->ip, 0)); + } if (i->ban) - m_p2p.block_ip(i->ip, i->seconds); + m_p2p.block_host(na, i->seconds); else - m_p2p.unblock_ip(i->ip); + m_p2p.unblock_host(na); } res.status = CORE_RPC_STATUS_OK; diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 8b5f189ca..7a1f5a963 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -49,7 +49,7 @@ namespace cryptonote // advance which version they will stop working with // Don't go over 32767 for any of these #define CORE_RPC_VERSION_MAJOR 1 -#define CORE_RPC_VERSION_MINOR 11 +#define CORE_RPC_VERSION_MINOR 12 #define MAKE_CORE_RPC_VERSION(major,minor) (((major)<<16)|(minor)) #define CORE_RPC_VERSION MAKE_CORE_RPC_VERSION(CORE_RPC_VERSION_MAJOR, CORE_RPC_VERSION_MINOR) @@ -861,18 +861,23 @@ namespace cryptonote struct peer { uint64_t id; + std::string host; uint32_t ip; uint16_t port; uint64_t last_seen; peer() = default; + peer(uint64_t id, const std::string &host, uint64_t last_seen) + : id(id), host(host), ip(0), port(0), last_seen(last_seen) + {} peer(uint64_t id, uint32_t ip, uint16_t port, uint64_t last_seen) - : id(id), ip(ip), port(port), last_seen(last_seen) + : id(id), host(std::to_string(ip)), ip(ip), port(port), last_seen(last_seen) {} BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(id) + KV_SERIALIZE(host) KV_SERIALIZE(ip) KV_SERIALIZE(port) KV_SERIALIZE(last_seen) @@ -1047,6 +1052,17 @@ namespace cryptonote }; }; + struct txpool_histo + { + uint32_t txs; + uint64_t bytes; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(txs) + KV_SERIALIZE(bytes) + END_KV_SERIALIZE_MAP() + }; + struct txpool_stats { uint64_t bytes_total; @@ -1058,6 +1074,8 @@ namespace cryptonote uint32_t num_failing; uint32_t num_10m; uint32_t num_not_relayed; + uint64_t histo_98pc; + std::vector<txpool_histo> histo; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(bytes_total) @@ -1069,6 +1087,8 @@ namespace cryptonote KV_SERIALIZE(num_failing) KV_SERIALIZE(num_10m) KV_SERIALIZE(num_not_relayed) + KV_SERIALIZE(histo_98pc) + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(histo) END_KV_SERIALIZE_MAP() }; @@ -1271,10 +1291,12 @@ namespace cryptonote { struct ban { + std::string host; uint32_t ip; uint32_t seconds; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(host) KV_SERIALIZE(ip) KV_SERIALIZE(seconds) END_KV_SERIALIZE_MAP() @@ -1302,11 +1324,13 @@ namespace cryptonote { struct ban { + std::string host; uint32_t ip; bool ban; uint32_t seconds; BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(host) KV_SERIALIZE(ip) KV_SERIALIZE(ban) KV_SERIALIZE(seconds) diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 96ba04c47..ee2b6055c 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -511,6 +511,7 @@ bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils:: { if(m_http_client.is_connected()) m_http_client.disconnect(); + m_is_initialized = true; m_upper_transaction_size_limit = upper_transaction_size_limit; m_daemon_address = std::move(daemon_address); m_daemon_login = std::move(daemon_login); @@ -1845,6 +1846,7 @@ void wallet2::detach_blockchain(uint64_t height) //---------------------------------------------------------------------------------------------------- bool wallet2::deinit() { + m_is_initialized=false; return true; } //---------------------------------------------------------------------------------------------------- @@ -2361,6 +2363,8 @@ bool wallet2::prepare_file_names(const std::string& file_path) //---------------------------------------------------------------------------------------------------- bool wallet2::check_connection(uint32_t *version, uint32_t timeout) { + THROW_WALLET_EXCEPTION_IF(!m_is_initialized, error::wallet_not_initialized); + boost::lock_guard<boost::mutex> lock(m_daemon_rpc_mutex); if(!m_http_client.is_connected()) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index bde233b33..e7692badb 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -105,7 +105,7 @@ namespace tools }; private: - wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {} + wallet2(const wallet2&) : m_run(true), m_callback(0), m_testnet(false), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_is_initialized(false),m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {} public: static const char* tr(const char* str); @@ -129,7 +129,7 @@ namespace tools //! Just parses variables. static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm); - wallet2(bool testnet = false, bool restricted = false) : m_run(true), m_callback(0), m_testnet(testnet), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_restricted(restricted), is_old_file_format(false), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {} + wallet2(bool testnet = false, bool restricted = false) : m_run(true), m_callback(0), m_testnet(testnet), m_always_confirm_transfers(true), m_print_ring_members(false), m_store_tx_info(true), m_default_mixin(0), m_default_priority(0), m_refresh_type(RefreshOptimizeCoinbase), m_auto_refresh(true), m_refresh_from_block_height(0), m_confirm_missing_payment_id(true), m_ask_password(true), m_min_output_count(0), m_min_output_value(0), m_merge_destinations(false), m_is_initialized(false), m_restricted(restricted), is_old_file_format(false), m_node_rpc_proxy(m_http_client, m_daemon_rpc_mutex) {} struct transfer_details { @@ -695,6 +695,7 @@ namespace tools uint32_t m_min_output_count; uint64_t m_min_output_value; bool m_merge_destinations; + bool m_is_initialized; NodeRPCProxy m_node_rpc_proxy; std::unordered_set<crypto::hash> m_scanned_pool_txs[2]; }; diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h index 3e3578149..16807e045 100644 --- a/src/wallet/wallet_errors.h +++ b/src/wallet/wallet_errors.h @@ -49,6 +49,7 @@ namespace tools // wallet_runtime_error * // wallet_internal_error // unexpected_txin_type + // wallet_not_initialized // std::logic_error // wallet_logic_error * // file_exists @@ -177,6 +178,15 @@ namespace tools cryptonote::transaction m_tx; }; //---------------------------------------------------------------------------------------------------- + struct wallet_not_initialized : public wallet_internal_error + { + explicit wallet_not_initialized(std::string&& loc) + : wallet_internal_error(std::move(loc), "wallet is not initialized") + { + } + }; + + //---------------------------------------------------------------------------------------------------- const char* const file_error_messages[] = { "file already exists", "file not found", |