P2P network stability improvement

This commit is contained in:
Antonio Juarez 2015-07-20 17:52:27 +01:00
parent f697d93978
commit b3a91f67d7
6 changed files with 87 additions and 50 deletions

View file

@ -153,7 +153,8 @@ const CheckpointData CHECKPOINTS[] = {
{713000, "a03f836c4a19f907cd6cac095eb6f56f5279ca2d1303fb7f826750dcb9025495"}, {713000, "a03f836c4a19f907cd6cac095eb6f56f5279ca2d1303fb7f826750dcb9025495"},
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"}, {750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"},
{780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"}, {780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"},
{785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"} {785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"},
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"}
}; };
} // CryptoNote } // CryptoNote

View file

@ -51,8 +51,8 @@ namespace CryptoNote
cryptonote_protocol_handler(const Currency& currency, System::Dispatcher& dispatcher, ICore& rcore, i_p2p_endpoint* p_net_layout, Logging::ILogger& log); cryptonote_protocol_handler(const Currency& currency, System::Dispatcher& dispatcher, ICore& rcore, i_p2p_endpoint* p_net_layout, Logging::ILogger& log);
virtual bool addObserver(ICryptonoteProtocolObserver* observer); virtual bool addObserver(ICryptonoteProtocolObserver* observer) override;
virtual bool removeObserver(ICryptonoteProtocolObserver* observer); virtual bool removeObserver(ICryptonoteProtocolObserver* observer) override;
void set_p2p_endpoint(i_p2p_endpoint* p2p); void set_p2p_endpoint(i_p2p_endpoint* p2p);
// ICore& get_core() { return m_core; } // ICore& get_core() { return m_core; }
@ -69,8 +69,8 @@ namespace CryptoNote
bool get_payload_sync_data(CORE_SYNC_DATA& hshd); bool get_payload_sync_data(CORE_SYNC_DATA& hshd);
bool process_payload_sync_data(const CORE_SYNC_DATA& hshd, cryptonote_connection_context& context, bool is_inital); bool process_payload_sync_data(const CORE_SYNC_DATA& hshd, cryptonote_connection_context& context, bool is_inital);
int handleCommand(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, cryptonote_connection_context& context, bool& handled); int handleCommand(bool is_notify, int command, const std::string& in_buff, std::string& buff_out, cryptonote_connection_context& context, bool& handled);
virtual size_t getPeerCount() const; virtual size_t getPeerCount() const override;
virtual uint64_t getObservedHeight() const; virtual uint64_t getObservedHeight() const override;
void requestMissingPoolTransactions(const cryptonote_connection_context& context); void requestMissingPoolTransactions(const cryptonote_connection_context& context);
private: private:

View file

@ -66,7 +66,9 @@ std::string LevinProtocol::sendBuf(uint32_t command, const std::string& out, boo
std::string response; std::string response;
if (readResponse) { if (readResponse) {
m_conn.read(reinterpret_cast<uint8_t*>(&head), sizeof(head)); if (!readStrict(reinterpret_cast<uint8_t*>(&head), sizeof(head))) {
throw std::runtime_error("Levin::sendBuf, failed to read header, peer closed connection");
}
if (head.m_signature != LEVIN_SIGNATURE) { if (head.m_signature != LEVIN_SIGNATURE) {
throw std::runtime_error("Levin signature mismatch"); throw std::runtime_error("Levin signature mismatch");
@ -79,7 +81,9 @@ std::string LevinProtocol::sendBuf(uint32_t command, const std::string& out, boo
response.resize(head.m_cb); response.resize(head.m_cb);
if (response.size()) { if (response.size()) {
readStrict(&response[0], head.m_cb); if (!readStrict(&response[0], head.m_cb)) {
throw std::runtime_error("Levin::sendBuf, failed to read body, peer closed connection");
}
} }
} }

View file

@ -18,6 +18,7 @@
#include "net_node.h" #include "net_node.h"
#include <algorithm> #include <algorithm>
#include <exception>
#include <fstream> #include <fstream>
#include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_oarchive.hpp>
@ -435,11 +436,7 @@ namespace CryptoNote
m_idleTimer.stop(); m_idleTimer.stop();
m_timedSyncTimer.stop(); m_timedSyncTimer.stop();
logger(INFO) << "Stopping " << m_connections.size() + m_raw_connections.size() << " connections"; logger(INFO) << "Stopping " << m_connections.size() << " connections";
for (auto& conn : m_raw_connections) {
conn.second.connection.stop();
}
for (auto& conn : m_connections) { for (auto& conn : m_connections) {
conn.second.connection.stop(); conn.second.connection.stop();
@ -639,35 +636,38 @@ namespace CryptoNote
try { try {
System::TcpConnector connector(m_dispatcher); System::TcpConnector connector(m_dispatcher);
System::Event timeoutEvent(m_dispatcher);
System::Timer timeoutTimer(m_dispatcher);
m_dispatcher.spawn([&](){ System::Event connectorTimeoutEvent(m_dispatcher);
System::Timer connectorTimeoutTimer(m_dispatcher);
m_dispatcher.spawn([&]() {
try { try {
timeoutTimer.sleep(std::chrono::milliseconds(m_config.m_net_config.connection_timeout)); connectorTimeoutTimer.sleep(std::chrono::milliseconds(m_config.m_net_config.connection_timeout));
connector.stop(); connector.stop();
} catch (std::exception&) {} } catch (std::exception&) {
timeoutEvent.set(); }
connectorTimeoutEvent.set();
}); });
System::TcpConnection connection; System::TcpConnection connection;
try { try {
connection = connector.connect(System::Ipv4Address(Common::ipAddressToString(na.ip)), static_cast<uint16_t>(na.port)); connection =
connector.connect(System::Ipv4Address(Common::ipAddressToString(na.ip)), static_cast<uint16_t>(na.port));
} catch (System::InterruptedException&) { } catch (System::InterruptedException&) {
timeoutEvent.wait(); connectorTimeoutEvent.wait();
return false; return false;
} catch (std::exception&) { } catch (std::exception& e) {
timeoutTimer.stop(); connectorTimeoutTimer.stop();
timeoutEvent.wait(); connectorTimeoutEvent.wait();
throw; throw;
} }
p2p_connection_context ctx(m_dispatcher, std::move(connection)); p2p_connection_context ctx(m_dispatcher, std::move(connection));
timeoutTimer.stop(); connectorTimeoutTimer.stop();
timeoutEvent.wait(); connectorTimeoutEvent.wait();
// p2p_connection_context ctx(m_dispatcher, std::move(connector.connect())); // p2p_connection_context ctx(m_dispatcher, std::move(connector.connect()));
@ -677,39 +677,68 @@ namespace CryptoNote
ctx.m_is_income = false; ctx.m_is_income = false;
ctx.m_started = time(nullptr); ctx.m_started = time(nullptr);
auto raw = m_raw_connections.emplace(ctx.m_connection_id, std::move(ctx)).first; System::Event handshakeTimeoutFinishedEvent(m_dispatcher);
try { System::Event handshakeFinishedEvent(m_dispatcher);
CryptoNote::LevinProtocol proto(raw->second.connection); System::Timer handshakeTimeoutTimer(m_dispatcher);
m_dispatcher.spawn([&] {
if (!handshake(proto, raw->second, just_take_peerlist)) { try {
logger(WARNING) << "Failed to HANDSHAKE with peer " << na; handshakeTimeoutTimer.sleep(std::chrono::milliseconds(m_config.m_net_config.connection_timeout));
m_raw_connections.erase(raw); ctx.connection.stop();
return false; } catch (std::exception& e) {
} }
} catch (...) {
m_raw_connections.erase(raw); handshakeTimeoutFinishedEvent.set();
throw; });
CryptoNote::LevinProtocol proto(ctx.connection);
bool error = false;
std::exception_ptr exceptionHolder;
m_dispatcher.spawn([&] {
try {
if (!handshake(proto, ctx, just_take_peerlist)) {
logger(WARNING) << "Failed to HANDSHAKE with peer " << na;
error = true;
}
} catch (System::InterruptedException&) {
error = true;
handshakeFinishedEvent.set();
return;
} catch (...) {
exceptionHolder = std::current_exception();
}
handshakeTimeoutTimer.stop();
handshakeFinishedEvent.set();
});
handshakeFinishedEvent.wait();
handshakeTimeoutFinishedEvent.wait();
if (error) {
return false;
}
if (exceptionHolder != nullptr) {
std::rethrow_exception(exceptionHolder);
} }
if (just_take_peerlist) { if (just_take_peerlist) {
logger(Logging::DEBUGGING, Logging::BRIGHT_GREEN) << raw->second << "CONNECTION HANDSHAKED OK AND CLOSED."; logger(Logging::DEBUGGING, Logging::BRIGHT_GREEN) << ctx << "CONNECTION HANDSHAKED OK AND CLOSED.";
m_raw_connections.erase(raw);
return true; return true;
} }
peerlist_entry pe_local = boost::value_initialized<peerlist_entry>(); peerlist_entry pe_local = boost::value_initialized<peerlist_entry>();
pe_local.adr = na; pe_local.adr = na;
pe_local.id = raw->second.peer_id; pe_local.id = ctx.peer_id;
time(&pe_local.last_seen); time(&pe_local.last_seen);
m_peerlist.append_with_peer_white(pe_local); m_peerlist.append_with_peer_white(pe_local);
if (m_stop) { if (m_stop) {
m_raw_connections.erase(raw);
throw System::InterruptedException(); throw System::InterruptedException();
} }
auto iter = m_connections.emplace(raw->first, std::move(raw->second)).first; auto key = ctx.m_connection_id;
m_raw_connections.erase(raw); auto iter = m_connections.emplace(key, std::move(ctx)).first;
const boost::uuids::uuid& connectionId = iter->first; const boost::uuids::uuid& connectionId = iter->first;
p2p_connection_context& connectionContext = iter->second; p2p_connection_context& connectionContext = iter->second;
@ -784,7 +813,7 @@ namespace CryptoNote
size_t try_count = 0; size_t try_count = 0;
size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size(); size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size();
while(true) { while(true) {
if(try_to_connect_and_handshake_with_new_peer(m_seed_nodes[current_index], true)) if(try_to_connect_and_handshake_with_new_peer(m_seed_nodes[current_index], true))
break; break;
@ -855,8 +884,12 @@ namespace CryptoNote
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
bool node_server::idle_worker() { bool node_server::idle_worker() {
m_connections_maker_interval.call(std::bind(&node_server::connections_maker, this)); try {
m_peerlist_store_interval.call(std::bind(&node_server::store_config, this)); m_connections_maker_interval.call(std::bind(&node_server::connections_maker, this));
m_peerlist_store_interval.call(std::bind(&node_server::store_config, this));
} catch (std::exception& e) {
logger(DEBUGGING) << "exception in idle_worker: " << e.what();
}
return true; return true;
} }

View file

@ -102,7 +102,7 @@ namespace CryptoNote
// debug functions // debug functions
bool log_peerlist(); bool log_peerlist();
bool log_connections(); bool log_connections();
virtual uint64_t get_connections_count(); virtual uint64_t get_connections_count() override;
size_t get_outgoing_connections_count(); size_t get_outgoing_connections_count();
CryptoNote::peerlist_manager& get_peerlist_manager() { return m_peerlist; } CryptoNote::peerlist_manager& get_peerlist_manager() { return m_peerlist; }
@ -171,7 +171,6 @@ namespace CryptoNote
typedef std::unordered_map<boost::uuids::uuid, p2p_connection_context, boost::hash<boost::uuids::uuid>> ConnectionContainer; typedef std::unordered_map<boost::uuids::uuid, p2p_connection_context, boost::hash<boost::uuids::uuid>> ConnectionContainer;
typedef ConnectionContainer::iterator ConnectionIterator; typedef ConnectionContainer::iterator ConnectionIterator;
ConnectionContainer m_raw_connections;
ConnectionContainer m_connections; ConnectionContainer m_connections;
void acceptLoop(); void acceptLoop();

View file

@ -1,4 +1,4 @@
#define BUILD_COMMIT_ID "@VERSION@" #define BUILD_COMMIT_ID "@VERSION@"
#define PROJECT_VERSION "1.0.5" #define PROJECT_VERSION "1.0.5.1"
#define PROJECT_VERSION_BUILD_NO "503" #define PROJECT_VERSION_BUILD_NO "505"
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")" #define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")"