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"},
{750300, "5117631dbeb5c14748a91127a515ecbf13f6849e14fda7ee03cd55da41f1710c"},
{780000, "8dd55a9bae429e3685b90317281e633917023d3512eb7f37372209d1a5fc1070"},
{785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"}
{785500, "de1a487d70964d25ed6f7de196866f357a293e867ee81313e7fd0352d0126bdd"},
{789000, "acef490bbccce3b7b7ae8554a414f55413fbf4ca1472c6359b126a4439bd9f01"}
};
} // 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);
virtual bool addObserver(ICryptonoteProtocolObserver* observer);
virtual bool removeObserver(ICryptonoteProtocolObserver* observer);
virtual bool addObserver(ICryptonoteProtocolObserver* observer) override;
virtual bool removeObserver(ICryptonoteProtocolObserver* observer) override;
void set_p2p_endpoint(i_p2p_endpoint* p2p);
// ICore& get_core() { return m_core; }
@ -69,8 +69,8 @@ namespace CryptoNote
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);
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 uint64_t getObservedHeight() const;
virtual size_t getPeerCount() const override;
virtual uint64_t getObservedHeight() const override;
void requestMissingPoolTransactions(const cryptonote_connection_context& context);
private:

View file

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

View file

@ -102,7 +102,7 @@ namespace CryptoNote
// debug functions
bool log_peerlist();
bool log_connections();
virtual uint64_t get_connections_count();
virtual uint64_t get_connections_count() override;
size_t get_outgoing_connections_count();
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 ConnectionContainer::iterator ConnectionIterator;
ConnectionContainer m_raw_connections;
ConnectionContainer m_connections;
void acceptLoop();

View file

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