TCPServer: removed unnecessary mutex

This commit is contained in:
SChernykh
2023-02-27 15:38:30 +01:00
parent 7a1afc7a95
commit 12a011a9ff
5 changed files with 172 additions and 185 deletions
+63 -75
View File
@@ -261,6 +261,8 @@ void P2PServer::on_connect_failed(bool is_v6, const raw_ip& ip, int port)
void P2PServer::update_peer_connections()
{
check_event_loop_thread(__func__);
const uint64_t cur_time = seconds_since_epoch();
const uint64_t last_updated = m_pool->side_chain().last_updated();
@@ -268,40 +270,37 @@ void P2PServer::update_peer_connections()
m_fastestPeer = nullptr;
unordered_set<raw_ip> connected_clients;
{
MutexLock lock(m_clientsListLock);
connected_clients.reserve(m_numConnections);
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
const int timeout = client->m_handshakeComplete ? 300 : 10;
if ((cur_time >= client->m_lastAlive + timeout) && (client->m_socks5ProxyState == Client::Socks5ProxyState::Default)) {
const uint64_t idle_time = static_cast<uint64_t>(cur_time - client->m_lastAlive);
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " has been idle for " << idle_time << " seconds, disconnecting");
connected_clients.reserve(m_numConnections);
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
const int timeout = client->m_handshakeComplete ? 300 : 10;
if ((cur_time >= client->m_lastAlive + timeout) && (client->m_socks5ProxyState == Client::Socks5ProxyState::Default)) {
const uint64_t idle_time = static_cast<uint64_t>(cur_time - client->m_lastAlive);
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " has been idle for " << idle_time << " seconds, disconnecting");
client->close();
continue;
}
if (client->m_handshakeComplete && client->m_lastBroadcastTimestamp) {
// - Side chain is at least 15 minutes newer (last_updated >= client->m_lastBroadcastTimestamp + 900)
// - It's been at least 10 seconds since side chain updated (cur_time >= last_updated + 10)
// - It's been at least 10 seconds since the last block request (peer is not syncing)
// - Peer should have sent a broadcast by now
if (last_updated && (cur_time >= std::max(last_updated, client->m_lastBlockrequestTimestamp) + 10) && (last_updated >= client->m_lastBroadcastTimestamp + 900)) {
const uint64_t dt = last_updated - client->m_lastBroadcastTimestamp;
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " is not broadcasting blocks (last update " << dt << " seconds ago)");
client->ban(DEFAULT_BAN_TIME);
remove_peer_from_list(client);
client->close();
continue;
}
}
if (client->m_handshakeComplete && client->m_lastBroadcastTimestamp) {
// - Side chain is at least 15 minutes newer (last_updated >= client->m_lastBroadcastTimestamp + 900)
// - It's been at least 10 seconds since side chain updated (cur_time >= last_updated + 10)
// - It's been at least 10 seconds since the last block request (peer is not syncing)
// - Peer should have sent a broadcast by now
if (last_updated && (cur_time >= std::max(last_updated, client->m_lastBlockrequestTimestamp) + 10) && (last_updated >= client->m_lastBroadcastTimestamp + 900)) {
const uint64_t dt = last_updated - client->m_lastBroadcastTimestamp;
LOGWARN(5, "peer " << static_cast<char*>(client->m_addrString) << " is not broadcasting blocks (last update " << dt << " seconds ago)");
client->ban(DEFAULT_BAN_TIME);
remove_peer_from_list(client);
client->close();
continue;
}
}
connected_clients.insert(client->m_addr);
if (client->is_good()) {
has_good_peers = true;
if ((client->m_pingTime >= 0) && (!m_fastestPeer || (m_fastestPeer->m_pingTime > client->m_pingTime))) {
m_fastestPeer = client;
}
connected_clients.insert(client->m_addr);
if (client->is_good()) {
has_good_peers = true;
if ((client->m_pingTime >= 0) && (!m_fastestPeer || (m_fastestPeer->m_pingTime > client->m_pingTime))) {
m_fastestPeer = client;
}
}
}
@@ -363,7 +362,7 @@ void P2PServer::update_peer_connections()
void P2PServer::update_peer_list()
{
MutexLock lock(m_clientsListLock);
check_event_loop_thread(__func__);
const uint64_t cur_time = seconds_since_epoch();
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
@@ -843,6 +842,8 @@ void P2PServer::broadcast(const PoolBlock& block, const PoolBlock* parent)
void P2PServer::on_broadcast()
{
check_event_loop_thread(__func__);
std::vector<Broadcast*> broadcast_queue;
broadcast_queue.reserve(2);
@@ -863,8 +864,6 @@ void P2PServer::on_broadcast()
}
});
MutexLock lock(m_clientsListLock);
for (P2PClient* client = static_cast<P2PClient*>(m_connectedClientsList->m_next); client != m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->is_good()) {
continue;
@@ -941,9 +940,7 @@ void P2PServer::on_broadcast()
uint64_t P2PServer::get_random64()
{
if (!server_event_loop_thread) {
LOGERR(1, "get_random64() was called from another thread, this is not thread safe");
}
check_event_loop_thread(__func__);
return m_rng();
}
@@ -965,9 +962,9 @@ void P2PServer::show_peers_async()
}
}
void P2PServer::show_peers()
void P2PServer::show_peers() const
{
MutexLock lock(m_clientsListLock);
check_event_loop_thread(__func__);
const uint64_t cur_time = seconds_since_epoch();
size_t n = 0;
@@ -1070,6 +1067,8 @@ void P2PServer::flush_cache()
void P2PServer::download_missing_blocks()
{
check_event_loop_thread(__func__);
if (!m_lookForMissingBlocks) {
return;
}
@@ -1083,8 +1082,6 @@ void P2PServer::download_missing_blocks()
return;
}
MutexLock lock(m_clientsListLock);
if (m_numConnections == 0) {
return;
}
@@ -1271,7 +1268,6 @@ bool P2PServer::P2PClient::on_connect()
}
// Don't allow multiple connections to/from the same IP (except localhost)
// server->m_clientsListLock is already locked here
if (!m_addr.is_localhost()) {
for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if ((client != this) && (client->m_addr == m_addr)) {
@@ -1757,6 +1753,8 @@ bool P2PServer::P2PClient::check_handshake_solution(const hash& solution, const
bool P2PServer::P2PClient::on_handshake_challenge(const uint8_t* buf)
{
check_event_loop_thread(__func__);
P2PServer* server = static_cast<P2PServer*>(m_owner);
uint8_t challenge[CHALLENGE_SIZE];
@@ -1772,23 +1770,14 @@ bool P2PServer::P2PClient::on_handshake_challenge(const uint8_t* buf)
m_peerId = peer_id;
bool same_peer = false;
{
MutexLock lock(server->m_clientsListLock);
for (const P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if ((client != this) && (client->m_peerId == peer_id)) {
LOGWARN(5, "tried to connect to the same peer twice: current connection " << static_cast<const char*>(client->m_addrString) << ", new connection " << static_cast<const char*>(m_addrString));
same_peer = true;
break;
}
for (const P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if ((client != this) && (client->m_peerId == peer_id)) {
LOGWARN(5, "tried to connect to the same peer twice: current connection " << static_cast<const char*>(client->m_addrString) << ", new connection " << static_cast<const char*>(m_addrString));
close();
return true;
}
}
if (same_peer) {
close();
return true;
}
send_handshake_solution(challenge);
return true;
}
@@ -2033,6 +2022,8 @@ bool P2PServer::P2PClient::on_block_broadcast(const uint8_t* buf, uint32_t size,
bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
{
check_event_loop_thread(__func__);
P2PServer* server = static_cast<P2PServer*>(m_owner);
const uint64_t cur_time = seconds_since_epoch();
const bool first = (m_prevIncomingPeerListRequest == 0);
@@ -2050,33 +2041,30 @@ bool P2PServer::P2PClient::on_peer_list_request(const uint8_t*)
Peer peers[PEER_LIST_RESPONSE_MAX_PEERS];
uint32_t num_selected_peers = 0;
{
MutexLock lock(server->m_clientsListLock);
// Send every 4th peer on average, selected at random
const uint32_t peers_to_send_target = std::min<uint32_t>(PEER_LIST_RESPONSE_MAX_PEERS, std::max<uint32_t>(1, server->m_numConnections / 4));
uint32_t n = 0;
// Send every 4th peer on average, selected at random
const uint32_t peers_to_send_target = std::min<uint32_t>(PEER_LIST_RESPONSE_MAX_PEERS, std::max<uint32_t>(1, server->m_numConnections / 4));
uint32_t n = 0;
for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->is_good() || (client->m_addr == m_addr)) {
continue;
}
for (P2PClient* client = static_cast<P2PClient*>(server->m_connectedClientsList->m_next); client != server->m_connectedClientsList; client = static_cast<P2PClient*>(client->m_next)) {
if (!client->is_good() || (client->m_addr == m_addr)) {
continue;
}
const Peer p{ client->m_isV6, client->m_addr, client->m_listenPort, 0, 0 };
++n;
const Peer p{ client->m_isV6, client->m_addr, client->m_listenPort, 0, 0 };
++n;
// Use https://en.wikipedia.org/wiki/Reservoir_sampling algorithm
if (num_selected_peers < peers_to_send_target) {
peers[num_selected_peers++] = p;
continue;
}
// Use https://en.wikipedia.org/wiki/Reservoir_sampling algorithm
if (num_selected_peers < peers_to_send_target) {
peers[num_selected_peers++] = p;
continue;
}
uint64_t k;
umul128(server->get_random64(), n, &k);
uint64_t k;
umul128(server->get_random64(), n, &k);
if (k < peers_to_send_target) {
peers[k] = p;
}
if (k < peers_to_send_target) {
peers[k] = p;
}
}