github.com/ethersphere/bee/v2@v2.2.0/pkg/topology/kademlia/mock/kademlia.go (about) 1 // Copyright 2020 The Swarm Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package mock 6 7 import ( 8 "context" 9 "sync" 10 "time" 11 12 "github.com/ethersphere/bee/v2/pkg/p2p" 13 "github.com/ethersphere/bee/v2/pkg/swarm" 14 "github.com/ethersphere/bee/v2/pkg/topology" 15 ) 16 17 type AddrTuple struct { 18 Addr swarm.Address // the peer address 19 PO uint8 // the po 20 } 21 22 func WithEachPeerRevCalls(addrs ...AddrTuple) Option { 23 return optionFunc(func(m *Mock) { 24 for _, a := range addrs { 25 a := a 26 m.eachPeerRev = append(m.eachPeerRev, a) 27 } 28 }) 29 } 30 31 func WithDepth(d uint8) Option { 32 return optionFunc(func(m *Mock) { 33 m.depth = d 34 }) 35 } 36 37 func WithDepthCalls(d ...uint8) Option { 38 return optionFunc(func(m *Mock) { 39 m.depthReplies = d 40 }) 41 } 42 43 type Mock struct { 44 mtx sync.Mutex 45 peers []swarm.Address 46 eachPeerRev []AddrTuple 47 depth uint8 48 depthReplies []uint8 49 depthCalls int 50 trigs []chan struct{} 51 trigMtx sync.Mutex 52 } 53 54 func NewMockKademlia(o ...Option) *Mock { 55 m := &Mock{} 56 for _, v := range o { 57 v.apply(m) 58 } 59 60 return m 61 } 62 63 // AddPeers is called when a peers are added to the topology backlog 64 // for further processing by connectivity strategy. 65 func (m *Mock) AddPeers(addr ...swarm.Address) { 66 panic("not implemented") // TODO: Implement 67 } 68 69 func (m *Mock) ClosestPeer(addr swarm.Address, _ bool, _ topology.Select, skipPeers ...swarm.Address) (peerAddr swarm.Address, err error) { 70 panic("not implemented") // TODO: Implement 71 } 72 73 func (m *Mock) EachNeighbor(topology.EachPeerFunc) error { 74 panic("not implemented") // TODO: Implement 75 } 76 77 func (m *Mock) EachNeighborRev(topology.EachPeerFunc) error { 78 panic("not implemented") // TODO: Implement 79 } 80 81 func (m *Mock) UpdatePeerHealth(swarm.Address, bool, time.Duration) { 82 panic("not implemented") // TODO: Implement 83 } 84 85 // PeerIterator iterates from closest bin to farthest 86 func (m *Mock) SetStorageRadius(uint8) { 87 panic("not implemented") 88 } 89 90 func (m *Mock) AddRevPeers(addrs ...AddrTuple) { 91 m.mtx.Lock() 92 defer m.mtx.Unlock() 93 for _, a := range addrs { 94 a := a 95 m.eachPeerRev = append(m.eachPeerRev, a) 96 } 97 } 98 99 // EachConnectedPeer iterates from closest bin to farthest 100 func (m *Mock) EachConnectedPeer(f topology.EachPeerFunc, _ topology.Select) error { 101 m.mtx.Lock() 102 defer m.mtx.Unlock() 103 104 for i := len(m.peers) - 1; i > 0; i-- { 105 stop, _, err := f(m.peers[i], uint8(i)) 106 if stop { 107 return nil 108 } 109 if err != nil { 110 return err 111 } 112 } 113 return nil 114 } 115 116 // EachPeerRev iterates from farthest bin to closest 117 func (m *Mock) EachConnectedPeerRev(f topology.EachPeerFunc, _ topology.Select) error { 118 m.mtx.Lock() 119 defer m.mtx.Unlock() 120 for _, v := range m.eachPeerRev { 121 stop, _, err := f(v.Addr, v.PO) 122 if stop { 123 return nil 124 } 125 if err != nil { 126 return err 127 } 128 } 129 return nil 130 } 131 132 func (m *Mock) IsReachable() bool { 133 return true 134 } 135 136 func (m *Mock) NeighborhoodDepth() uint8 { 137 m.mtx.Lock() 138 defer m.mtx.Unlock() 139 140 m.depthCalls++ 141 if len(m.depthReplies) > 0 { 142 return m.depthReplies[m.depthCalls] 143 } 144 return m.depth 145 } 146 147 // Connected is called when a peer dials in. 148 func (m *Mock) Connected(_ context.Context, peer p2p.Peer, _ bool) error { 149 m.mtx.Lock() 150 m.peers = append(m.peers, peer.Address) 151 m.mtx.Unlock() 152 m.Trigger() 153 return nil 154 } 155 156 // Disconnected is called when a peer disconnects. 157 func (m *Mock) Disconnected(peer p2p.Peer) { 158 m.mtx.Lock() 159 defer m.mtx.Unlock() 160 161 m.peers = swarm.RemoveAddress(m.peers, peer.Address) 162 163 m.Trigger() 164 } 165 166 func (m *Mock) Announce(_ context.Context, _ swarm.Address, _ bool) error { 167 return nil 168 } 169 170 func (m *Mock) AnnounceTo(_ context.Context, _, _ swarm.Address, _ bool) error { 171 return nil 172 } 173 174 func (m *Mock) SubscribeTopologyChange() (c <-chan struct{}, unsubscribe func()) { 175 channel := make(chan struct{}, 1) 176 var closeOnce sync.Once 177 178 m.trigMtx.Lock() 179 defer m.trigMtx.Unlock() 180 m.trigs = append(m.trigs, channel) 181 182 unsubscribe = func() { 183 m.trigMtx.Lock() 184 defer m.trigMtx.Unlock() 185 186 for i, c := range m.trigs { 187 if c == channel { 188 m.trigs = append(m.trigs[:i], m.trigs[i+1:]...) 189 break 190 } 191 } 192 193 closeOnce.Do(func() { close(channel) }) 194 } 195 196 return channel, unsubscribe 197 } 198 199 func (m *Mock) Trigger() { 200 m.trigMtx.Lock() 201 defer m.trigMtx.Unlock() 202 203 for _, c := range m.trigs { 204 select { 205 case c <- struct{}{}: 206 default: 207 } 208 } 209 } 210 211 func (m *Mock) ResetPeers() { 212 m.mtx.Lock() 213 defer m.mtx.Unlock() 214 m.peers = nil 215 m.eachPeerRev = nil 216 } 217 218 func (d *Mock) Halt() {} 219 func (m *Mock) Close() error { return nil } 220 221 func (m *Mock) Snapshot() *topology.KadParams { 222 panic("not implemented") // TODO: Implement 223 } 224 225 type Option interface { 226 apply(*Mock) 227 } 228 type optionFunc func(*Mock) 229 230 func (f optionFunc) apply(r *Mock) { f(r) }