github.com/aaa256/atlantis@v0.0.0-20210707112435-42ee889287a2/swarm/network/stream/peer.go (about) 1 // Copyright 2018 The go-athereum Authors 2 // This file is part of the go-athereum library. 3 // 4 // The go-athereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-athereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-athereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package stream 18 19 import ( 20 "context" 21 "fmt" 22 "sync" 23 "time" 24 25 "github.com/athereum/go-athereum/metrics" 26 "github.com/athereum/go-athereum/p2p/protocols" 27 "github.com/athereum/go-athereum/swarm/log" 28 pq "github.com/athereum/go-athereum/swarm/network/priorityqueue" 29 "github.com/athereum/go-athereum/swarm/network/stream/intervals" 30 "github.com/athereum/go-athereum/swarm/state" 31 "github.com/athereum/go-athereum/swarm/storage" 32 ) 33 34 var sendTimeout = 30 * time.Second 35 36 type notFoundError struct { 37 t string 38 s Stream 39 } 40 41 func newNotFoundError(t string, s Stream) *notFoundError { 42 return ¬FoundError{t: t, s: s} 43 } 44 45 func (e *notFoundError) Error() string { 46 return fmt.Sprintf("%s not found for stream %q", e.t, e.s) 47 } 48 49 // Peer is the Peer extension for the streaming protocol 50 type Peer struct { 51 *protocols.Peer 52 streamer *Registry 53 pq *pq.PriorityQueue 54 serverMu sync.RWMutex 55 clientMu sync.RWMutex // protects both clients and clientParams 56 servers map[Stream]*server 57 clients map[Stream]*client 58 // clientParams map keeps required client arguments 59 // that are set on Registry.Subscribe and used 60 // on creating a new client in offered hashes handler. 61 clientParams map[Stream]*clientParams 62 quit chan struct{} 63 } 64 65 // NewPeer is the constructor for Peer 66 func NewPeer(peer *protocols.Peer, streamer *Registry) *Peer { 67 p := &Peer{ 68 Peer: peer, 69 pq: pq.New(int(PriorityQueue), PriorityQueueCap), 70 streamer: streamer, 71 servers: make(map[Stream]*server), 72 clients: make(map[Stream]*client), 73 clientParams: make(map[Stream]*clientParams), 74 quit: make(chan struct{}), 75 } 76 ctx, cancel := context.WithCancel(context.Background()) 77 go p.pq.Run(ctx, func(i interface{}) { p.Send(i) }) 78 go func() { 79 <-p.quit 80 cancel() 81 }() 82 return p 83 } 84 85 // Deliver sends a storeRequestMsg protocol message to the peer 86 func (p *Peer) Deliver(chunk *storage.Chunk, priority uint8) error { 87 msg := &ChunkDeliveryMsg{ 88 Addr: chunk.Addr, 89 SData: chunk.SData, 90 } 91 return p.SendPriority(msg, priority) 92 } 93 94 // SendPriority sends message to the peer using the outgoing priority queue 95 func (p *Peer) SendPriority(msg interface{}, priority uint8) error { 96 defer metrics.GetOrRegisterResettingTimer(fmt.Sprintf("peer.sendpriority_t.%d", priority), nil).UpdateSince(time.Now()) 97 metrics.GetOrRegisterCounter(fmt.Sprintf("peer.sendpriority.%d", priority), nil).Inc(1) 98 ctx, cancel := context.WithTimeout(context.Background(), sendTimeout) 99 defer cancel() 100 return p.pq.Push(ctx, msg, int(priority)) 101 } 102 103 // SendOfferedHashes sends OfferedHashesMsg protocol msg 104 func (p *Peer) SendOfferedHashes(s *server, f, t uint64) error { 105 hashes, from, to, proof, err := s.SetNextBatch(f, t) 106 if err != nil { 107 return err 108 } 109 // true only when quiting 110 if len(hashes) == 0 { 111 return nil 112 } 113 if proof == nil { 114 proof = &HandoverProof{ 115 Handover: &Handover{}, 116 } 117 } 118 s.currentBatch = hashes 119 msg := &OfferedHashesMsg{ 120 HandoverProof: proof, 121 Hashes: hashes, 122 From: from, 123 To: to, 124 Stream: s.stream, 125 } 126 log.Trace("Swarm syncer offer batch", "peer", p.ID(), "stream", s.stream, "len", len(hashes), "from", from, "to", to) 127 return p.SendPriority(msg, s.priority) 128 } 129 130 func (p *Peer) getServer(s Stream) (*server, error) { 131 p.serverMu.RLock() 132 defer p.serverMu.RUnlock() 133 134 server := p.servers[s] 135 if server == nil { 136 return nil, newNotFoundError("server", s) 137 } 138 return server, nil 139 } 140 141 func (p *Peer) setServer(s Stream, o Server, priority uint8) (*server, error) { 142 p.serverMu.Lock() 143 defer p.serverMu.Unlock() 144 145 if p.servers[s] != nil { 146 return nil, fmt.Errorf("server %s already registered", s) 147 } 148 os := &server{ 149 Server: o, 150 stream: s, 151 priority: priority, 152 } 153 p.servers[s] = os 154 return os, nil 155 } 156 157 func (p *Peer) removeServer(s Stream) error { 158 p.serverMu.Lock() 159 defer p.serverMu.Unlock() 160 161 server, ok := p.servers[s] 162 if !ok { 163 return newNotFoundError("server", s) 164 } 165 server.Close() 166 delete(p.servers, s) 167 return nil 168 } 169 170 func (p *Peer) getClient(ctx context.Context, s Stream) (c *client, err error) { 171 var params *clientParams 172 func() { 173 p.clientMu.RLock() 174 defer p.clientMu.RUnlock() 175 176 c = p.clients[s] 177 if c != nil { 178 return 179 } 180 params = p.clientParams[s] 181 }() 182 if c != nil { 183 return c, nil 184 } 185 186 if params != nil { 187 //debug.PrintStack() 188 if err := params.waitClient(ctx); err != nil { 189 return nil, err 190 } 191 } 192 193 p.clientMu.RLock() 194 defer p.clientMu.RUnlock() 195 196 c = p.clients[s] 197 if c != nil { 198 return c, nil 199 } 200 return nil, newNotFoundError("client", s) 201 } 202 203 func (p *Peer) getOrSetClient(s Stream, from, to uint64) (c *client, created bool, err error) { 204 p.clientMu.Lock() 205 defer p.clientMu.Unlock() 206 207 c = p.clients[s] 208 if c != nil { 209 return c, false, nil 210 } 211 212 f, err := p.streamer.GetClientFunc(s.Name) 213 if err != nil { 214 return nil, false, err 215 } 216 217 is, err := f(p, s.Key, s.Live) 218 if err != nil { 219 return nil, false, err 220 } 221 222 cp, err := p.getClientParams(s) 223 if err != nil { 224 return nil, false, err 225 } 226 defer func() { 227 if err == nil { 228 if err := p.removeClientParams(s); err != nil { 229 log.Error("stream set client: remove client params", "stream", s, "peer", p, "err", err) 230 } 231 } 232 }() 233 234 intervalsKey := peerStreamIntervalsKey(p, s) 235 if s.Live { 236 // try to find previous history and live intervals and merge live into history 237 historyKey := peerStreamIntervalsKey(p, NewStream(s.Name, s.Key, false)) 238 historyIntervals := &intervals.Intervals{} 239 err := p.streamer.intervalsStore.Get(historyKey, historyIntervals) 240 switch err { 241 case nil: 242 liveIntervals := &intervals.Intervals{} 243 err := p.streamer.intervalsStore.Get(intervalsKey, liveIntervals) 244 switch err { 245 case nil: 246 historyIntervals.Merge(liveIntervals) 247 if err := p.streamer.intervalsStore.Put(historyKey, historyIntervals); err != nil { 248 log.Error("stream set client: put history intervals", "stream", s, "peer", p, "err", err) 249 } 250 case state.ErrNotFound: 251 default: 252 log.Error("stream set client: get live intervals", "stream", s, "peer", p, "err", err) 253 } 254 case state.ErrNotFound: 255 default: 256 log.Error("stream set client: get history intervals", "stream", s, "peer", p, "err", err) 257 } 258 } 259 260 if err := p.streamer.intervalsStore.Put(intervalsKey, intervals.NewIntervals(from)); err != nil { 261 return nil, false, err 262 } 263 264 next := make(chan error, 1) 265 c = &client{ 266 Client: is, 267 stream: s, 268 priority: cp.priority, 269 to: cp.to, 270 next: next, 271 quit: make(chan struct{}), 272 intervalsStore: p.streamer.intervalsStore, 273 intervalsKey: intervalsKey, 274 } 275 p.clients[s] = c 276 cp.clientCreated() // unblock all possible getClient calls that are waiting 277 next <- nil // this is to allow wantedKeysMsg before first batch arrives 278 return c, true, nil 279 } 280 281 func (p *Peer) removeClient(s Stream) error { 282 p.clientMu.Lock() 283 defer p.clientMu.Unlock() 284 285 client, ok := p.clients[s] 286 if !ok { 287 return newNotFoundError("client", s) 288 } 289 client.close() 290 return nil 291 } 292 293 func (p *Peer) setClientParams(s Stream, params *clientParams) error { 294 p.clientMu.Lock() 295 defer p.clientMu.Unlock() 296 297 if p.clients[s] != nil { 298 return fmt.Errorf("client %s already exists", s) 299 } 300 if p.clientParams[s] != nil { 301 return fmt.Errorf("client params %s already set", s) 302 } 303 p.clientParams[s] = params 304 return nil 305 } 306 307 func (p *Peer) getClientParams(s Stream) (*clientParams, error) { 308 params := p.clientParams[s] 309 if params == nil { 310 return nil, fmt.Errorf("client params '%v' not provided to peer %v", s, p.ID()) 311 } 312 return params, nil 313 } 314 315 func (p *Peer) removeClientParams(s Stream) error { 316 _, ok := p.clientParams[s] 317 if !ok { 318 return newNotFoundError("client params", s) 319 } 320 delete(p.clientParams, s) 321 return nil 322 } 323 324 func (p *Peer) close() { 325 for _, s := range p.servers { 326 s.Close() 327 } 328 }