Skip to content

Commit 61a6911

Browse files
committed
Merge pull request #1689 from fjl/discover-ignore-temp-errors
p2p, p2p/discover: small fixes
2 parents 382d35b + dd54fef commit 61a6911

File tree

4 files changed

+51
-11
lines changed

4 files changed

+51
-11
lines changed

p2p/discover/node.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ type Node struct {
4848
// In those tests, the content of sha will not actually correspond
4949
// with ID.
5050
sha common.Hash
51+
52+
// whether this node is currently being pinged in order to replace
53+
// it in a bucket
54+
contested bool
5155
}
5256

5357
func newNode(id NodeID, ip net.IP, udpPort, tcpPort uint16) *Node {

p2p/discover/table.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,24 +455,31 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
455455
func (tab *Table) add(new *Node) {
456456
b := tab.buckets[logdist(tab.self.sha, new.sha)]
457457
tab.mutex.Lock()
458+
defer tab.mutex.Unlock()
458459
if b.bump(new) {
459-
tab.mutex.Unlock()
460460
return
461461
}
462462
var oldest *Node
463463
if len(b.entries) == bucketSize {
464464
oldest = b.entries[bucketSize-1]
465+
if oldest.contested {
466+
// The node is already being replaced, don't attempt
467+
// to replace it.
468+
return
469+
}
470+
oldest.contested = true
465471
// Let go of the mutex so other goroutines can access
466472
// the table while we ping the least recently active node.
467473
tab.mutex.Unlock()
468-
if err := tab.ping(oldest.ID, oldest.addr()); err == nil {
474+
err := tab.ping(oldest.ID, oldest.addr())
475+
tab.mutex.Lock()
476+
oldest.contested = false
477+
if err == nil {
469478
// The node responded, don't replace it.
470479
return
471480
}
472-
tab.mutex.Lock()
473481
}
474482
added := b.replace(new, oldest)
475-
tab.mutex.Unlock()
476483
if added && tab.nodeAddedHook != nil {
477484
tab.nodeAddedHook(new)
478485
}

p2p/discover/udp.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ func encodePacket(priv *ecdsa.PrivateKey, ptype byte, req interface{}) ([]byte,
458458
return packet, nil
459459
}
460460

461+
type tempError interface {
462+
Temporary() bool
463+
}
464+
461465
// readLoop runs in its own goroutine. it handles incoming UDP packets.
462466
func (t *udp) readLoop() {
463467
defer t.conn.Close()
@@ -467,7 +471,13 @@ func (t *udp) readLoop() {
467471
buf := make([]byte, 1280)
468472
for {
469473
nbytes, from, err := t.conn.ReadFromUDP(buf)
470-
if err != nil {
474+
if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
475+
// Ignore temporary read errors.
476+
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
477+
continue
478+
} else if err != nil {
479+
// Shut down the loop for permament errors.
480+
glog.V(logger.Debug).Infof("Read error: %v", err)
471481
return
472482
}
473483
t.handlePacket(from, buf[:nbytes])

p2p/server.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -542,6 +542,10 @@ func (srv *Server) encHandshakeChecks(peers map[discover.NodeID]*Peer, c *conn)
542542
}
543543
}
544544

545+
type tempError interface {
546+
Temporary() bool
547+
}
548+
545549
// listenLoop runs in its own goroutine and accepts
546550
// inbound connections.
547551
func (srv *Server) listenLoop() {
@@ -561,16 +565,31 @@ func (srv *Server) listenLoop() {
561565
}
562566

563567
for {
568+
// Wait for a handshake slot before accepting.
564569
<-slots
565-
fd, err := srv.listener.Accept()
566-
if err != nil {
567-
return
570+
571+
var (
572+
fd net.Conn
573+
err error
574+
)
575+
for {
576+
fd, err = srv.listener.Accept()
577+
if tempErr, ok := err.(tempError); ok && tempErr.Temporary() {
578+
glog.V(logger.Debug).Infof("Temporary read error: %v", err)
579+
continue
580+
} else if err != nil {
581+
glog.V(logger.Debug).Infof("Read error: %v", err)
582+
return
583+
}
584+
break
568585
}
569-
mfd := newMeteredConn(fd, true)
586+
fd = newMeteredConn(fd, true)
587+
glog.V(logger.Debug).Infof("Accepted conn %v\n", fd.RemoteAddr())
570588

571-
glog.V(logger.Debug).Infof("Accepted conn %v\n", mfd.RemoteAddr())
589+
// Spawn the handler. It will give the slot back when the connection
590+
// has been established.
572591
go func() {
573-
srv.setupConn(mfd, inboundConn, nil)
592+
srv.setupConn(fd, inboundConn, nil)
574593
slots <- struct{}{}
575594
}()
576595
}

0 commit comments

Comments
 (0)