P2P network stability improvement
This commit is contained in:
parent
f697d93978
commit
b3a91f67d7
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
@ -640,34 +637,37 @@ namespace CryptoNote
|
||||||
try {
|
try {
|
||||||
System::TcpConnector connector(m_dispatcher);
|
System::TcpConnector connector(m_dispatcher);
|
||||||
|
|
||||||
System::Event timeoutEvent(m_dispatcher);
|
System::Event connectorTimeoutEvent(m_dispatcher);
|
||||||
System::Timer timeoutTimer(m_dispatcher);
|
System::Timer connectorTimeoutTimer(m_dispatcher);
|
||||||
|
|
||||||
m_dispatcher.spawn([&]() {
|
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);
|
||||||
|
System::Event handshakeFinishedEvent(m_dispatcher);
|
||||||
|
System::Timer handshakeTimeoutTimer(m_dispatcher);
|
||||||
|
m_dispatcher.spawn([&] {
|
||||||
try {
|
try {
|
||||||
CryptoNote::LevinProtocol proto(raw->second.connection);
|
handshakeTimeoutTimer.sleep(std::chrono::milliseconds(m_config.m_net_config.connection_timeout));
|
||||||
|
ctx.connection.stop();
|
||||||
|
} catch (std::exception& e) {
|
||||||
|
}
|
||||||
|
|
||||||
if (!handshake(proto, raw->second, just_take_peerlist)) {
|
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;
|
logger(WARNING) << "Failed to HANDSHAKE with peer " << na;
|
||||||
m_raw_connections.erase(raw);
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
} catch (...) {
|
|
||||||
m_raw_connections.erase(raw);
|
if (exceptionHolder != nullptr) {
|
||||||
throw;
|
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;
|
||||||
|
|
||||||
|
@ -855,8 +884,12 @@ namespace CryptoNote
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
bool node_server::idle_worker() {
|
bool node_server::idle_worker() {
|
||||||
|
try {
|
||||||
m_connections_maker_interval.call(std::bind(&node_server::connections_maker, 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));
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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 ")"
|
||||||
|
|
Loading…
Reference in a new issue