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 }