github.com/status-im/status-go@v1.1.0/peers/cotopicpool.go (about)

     1  package peers
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/ethereum/go-ethereum/p2p"
     8  	"github.com/ethereum/go-ethereum/p2p/enode"
     9  
    10  	"github.com/status-im/status-go/params"
    11  	"github.com/status-im/status-go/signal"
    12  )
    13  
    14  // Verifier verifies if a give node is trusted.
    15  type Verifier interface {
    16  	VerifyNode(context.Context, enode.ID) bool
    17  }
    18  
    19  // MailServerDiscoveryTopic topic name for mailserver discovery.
    20  const MailServerDiscoveryTopic = "whispermail"
    21  
    22  // MailServerDiscoveryLimits default mailserver discovery limits.
    23  var MailServerDiscoveryLimits = params.Limits{Min: 3, Max: 3}
    24  
    25  // cacheOnlyTopicPool handles a mail server topic pool.
    26  type cacheOnlyTopicPool struct {
    27  	*TopicPool
    28  	verifier Verifier
    29  }
    30  
    31  // newCacheOnlyTopicPool returns instance of CacheOnlyTopicPool.
    32  func newCacheOnlyTopicPool(t *TopicPool, verifier Verifier) *cacheOnlyTopicPool {
    33  	return &cacheOnlyTopicPool{
    34  		TopicPool: t,
    35  		verifier:  verifier,
    36  	}
    37  }
    38  
    39  // MaxReached checks if the max allowed peers is reached or not. When true
    40  // peerpool will stop the discovery process on this TopicPool.
    41  // Main difference with basic TopicPool is we want to stop discovery process
    42  // when the number of cached peers eq/exceeds the max limit.
    43  func (t *cacheOnlyTopicPool) MaxReached() bool {
    44  	t.mu.RLock()
    45  	defer t.mu.RUnlock()
    46  	if t.limits.Max == 0 {
    47  		return true
    48  	}
    49  	peers := t.cache.GetPeersRange(t.topic, t.limits.Max)
    50  	return len(peers) >= t.limits.Max
    51  }
    52  
    53  var sendEnodeDiscovered = signal.SendEnodeDiscovered
    54  
    55  // ConfirmAdded calls base TopicPool ConfirmAdded method and sends a signal
    56  // confirming the enode has been discovered.
    57  func (t *cacheOnlyTopicPool) ConfirmAdded(server *p2p.Server, nodeID enode.ID) {
    58  	trusted := t.verifier.VerifyNode(context.TODO(), nodeID)
    59  	if trusted {
    60  		// add to cache only if trusted
    61  		t.TopicPool.ConfirmAdded(server, nodeID)
    62  		sendEnodeDiscovered(nodeID.String(), string(t.topic))
    63  		t.subtractToLimits()
    64  	}
    65  
    66  	// If a peer was trusted, it was moved to connectedPeers,
    67  	// signal was sent and we can safely remove it.
    68  	if peer, ok := t.connectedPeers[nodeID]; ok {
    69  		// NOTE: removeServerPeer removes the server peer immediately.
    70  		// which means the next discovery.summary is not going to include
    71  		// the peer.
    72  		// We leave some time so that we ensure the signal is propagated
    73  		go func() {
    74  			time.Sleep(200)
    75  			t.removeServerPeer(server, peer)
    76  		}()
    77  		// Delete it from `connectedPeers` immediately to
    78  		// prevent removing it from the cache which logic is
    79  		// implemented in TopicPool.
    80  		delete(t.connectedPeers, nodeID)
    81  	}
    82  
    83  	// It a peer was not trusted, it is still in pendingPeers.
    84  	// We should remove it from the p2p.Server.
    85  	if peer, ok := t.pendingPeers[nodeID]; ok {
    86  		// NOTE: removeServerPeer removes the server peer immediately.
    87  		// which means the next discovery.summary is not going to include
    88  		// the peer.
    89  		// We leave some time so that we ensure the signal is propagated
    90  		go func() {
    91  			time.Sleep(200)
    92  			t.removeServerPeer(server, peer.peerInfo)
    93  		}()
    94  
    95  		// Delete it from `connectedPeers` immediately to
    96  		// prevent removing it from the cache which logic is
    97  		// implemented in TopicPool.
    98  		delete(t.pendingPeers, nodeID)
    99  	}
   100  }
   101  
   102  // subtractToLimits subtracts one to topic pool limits.
   103  func (t *cacheOnlyTopicPool) subtractToLimits() {
   104  	t.mu.Lock()
   105  	defer t.mu.Unlock()
   106  
   107  	if t.limits.Max > 0 {
   108  		t.limits.Max = t.limits.Max - 1
   109  	}
   110  	if t.limits.Min > 0 {
   111  		t.limits.Min = t.limits.Min - 1
   112  	}
   113  }