peer: enforce strict timeout on opening handshake

This commit modifies the logic around the opening p2p handshake to
enforce a strict timeout around the receipt of the responding init
message. Before this commit, it was possible for the daemon and certain
RPC calls to deadlock as if a peer connected, but didn’t respond with
an init msg, then we’d be sitting there waiting for them to respond.
With this commit, we’ll now time out, kill the connection and then
possible attempt to re-connect if the connection was persistent.
This commit is contained in:
Olaoluwa Osuntokun 2017-03-29 18:33:20 -07:00
parent 98d5dde9b2
commit 0e96d273d9
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
2 changed files with 23 additions and 6 deletions

26
peer.go
View File

@ -296,11 +296,31 @@ func (p *peer) Start() error {
// Before we launch any of the helper goroutines off the peer struct,
// we'll first ensure proper adherance to the p2p protocl. The init
// message MUST be sent before any other message.
msg, _, err := p.readNextMessage()
if err != nil {
return err
readErr := make(chan error, 1)
msgChan := make(chan lnwire.Message, 1)
go func() {
msg, _, err := p.readNextMessage()
if err != nil {
readErr <- err
msgChan <- nil
}
readErr <- nil
msgChan <- msg
}()
select {
// In order to avoid blocking indefinately, we'll give the other peer
// an upper timeout of 5 seconds to respond before we bail out early.
case <-time.After(time.Second * 5):
return fmt.Errorf("peer did not complete handshake within 5 " +
"seconds")
case err := <-readErr:
if err != nil {
return err
}
}
msg := <-msgChan
if msg, ok := msg.(*lnwire.Init); ok {
if err := p.handleInitMsg(msg); err != nil {
return err

View File

@ -550,9 +550,6 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq, inbound
if err := p.Start(); err != nil {
srvrLog.Errorf("unable to start peer: %v", err)
if p.connReq != nil {
s.connMgr.Remove(p.connReq.ID())
}
p.Disconnect()
return
}