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 &notFoundError{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  }