Skip to content
This repository was archived by the owner on Oct 28, 2021. It is now read-only.

Check for existing RLPX handshake when connecting to a node#5599

Merged
halfalicious merged 3 commits intomasterfrom
concurrent-connections
May 14, 2019
Merged

Check for existing RLPX handshake when connecting to a node#5599
halfalicious merged 3 commits intomasterfrom
concurrent-connections

Conversation

@halfalicious
Copy link
Copy Markdown
Contributor

@halfalicious halfalicious commented May 12, 2019

Fix #5600

Check for existing RLPX handshake in Host::connect before attempting a new connection to a node - this is required because Host::connect only checks m_pendingPeerConns before starting a new connection, and entries are removed from m_pendingPeerConns after a new RLPX handshake has started rather than after the handshake has completed.

I've chosen to check for an existing RLPX handshake rather than garbage-collecting m_pendingPeerConns in Host::run since the former only adds cost during a new connection while the latter would add cost on every Host::run invocation.

@codecov-io
Copy link
Copy Markdown

codecov-io commented May 12, 2019

Codecov Report

Merging #5599 into master will increase coverage by <.01%.
The diff coverage is 46.15%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #5599      +/-   ##
==========================================
+ Coverage   62.21%   62.22%   +<.01%     
==========================================
  Files         347      347              
  Lines       29284    29296      +12     
  Branches     3309     3312       +3     
==========================================
+ Hits        18219    18228       +9     
- Misses       9876     9881       +5     
+ Partials     1189     1187       -2

@halfalicious halfalicious force-pushed the concurrent-connections branch from f2b0589 to fce88db Compare May 13, 2019 20:53
@halfalicious halfalicious changed the title Check for in-progress RLPX handshake during peering Check for existing RLPX handshake when connecting to a node May 13, 2019
@halfalicious halfalicious force-pushed the concurrent-connections branch from fce88db to 6b8d16a Compare May 13, 2019 20:58
@halfalicious
Copy link
Copy Markdown
Contributor Author

halfalicious commented May 13, 2019

Another approach would be to remove the peer entry from Host::m_pendingPeerConns once the RLPX handshake has been completed and a new session has been created in RLPXHandshake::transition:

LOG(m_logger) << p2pPacketTypeToString(HelloPacket)
<< " verified. Starting session with " << m_remote
<< "@" << m_socket->remoteEndpoint();
try
{
RLP rlp(
frame.cropped(1), RLP::ThrowOnFail | RLP::FailIfTooSmall);
m_host->startPeerSession(m_remote, rlp, move(m_io), m_socket);
}

However, I think this would be a little messier since it would require adding 2 functions to Host - 1 which enables peer lookup by node ID and returns std::shared_ptr<Peer> and another which removes an entry from m_pendingPeerConns given a std::shared_ptr<Peer>. This would also open us up to synchronization issues unless we protected m_pendingPeerConns and m_peers with synchronization primitives (which would add to the runtime cost of these functions).

@gumb0 / @chfast : Thoughts?

@halfalicious halfalicious requested review from chfast and gumb0 and removed request for chfast May 13, 2019 21:26
Host only checks in m_pendingPeerCons before attempting to open a new TCP connection to a node (in Host::connect) and start a new RLPX handshake - entries are removed from m_pendingPeerConns after the RLPX handshake has been started rather than when it is completed, which results in Host being able to initiate another TCP connection to the same node before the first RLPX handshake is complete.

To fix this, Host::connect also checks the RLPX handshake list (m_connecting) before starting a new connection.
@halfalicious halfalicious force-pushed the concurrent-connections branch from 81a7583 to 16dcdfc Compare May 13, 2019 22:19
Copy link
Copy Markdown
Member

@chfast chfast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@gumb0
Copy link
Copy Markdown
Member

gumb0 commented May 14, 2019

Hm, what about removing from Host::m_pendingPeerConns inside Host::startPeerSession (perhaps after adding to m_sessions) instead of at the end of after handshake start in Host::connect ) ?

Might still be messier, considering that we'd also need to somehow remove them when handshake failed...

libp2p/Host.cpp Outdated
}
}

bool Host::isConnecting(NodeID const& _id)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can it be const method? (make mutex mutable if needed)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should be more precisely called isHandshaking, because connection itself actually already exists during handshake

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to make mutex mutable, will do this and rename the method.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gumb0 Addressed

isHandshaking more accurately describes what the function is checking. Also make the function const (which requires making the x_connecting mutex mutable).
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Aleth tries to initiate another connection to node while RLPX handshake is still in progress

4 participants