github.com/nitinawathare/ethereumassignment3@v0.0.0-20211021213010-f07344c2b868/go-ethereum/swarm/network/stream/peer.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum 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-ethereum 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-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package stream
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"sync"
    24  	"time"
    25  
    26  	"github.com/ethereum/go-ethereum/metrics"
    27  	"github.com/ethereum/go-ethereum/p2p/protocols"
    28  	"github.com/ethereum/go-ethereum/swarm/log"
    29  	pq "github.com/ethereum/go-ethereum/swarm/network/priorityqueue"
    30  	"github.com/ethereum/go-ethereum/swarm/network/stream/intervals"
    31  	"github.com/ethereum/go-ethereum/swarm/spancontext"
    32  	"github.com/ethereum/go-ethereum/swarm/state"
    33  	"github.com/ethereum/go-ethereum/swarm/storage"
    34  	"github.com/ethereum/go-ethereum/swarm/tracing"
    35  	opentracing "github.com/opentracing/opentracing-go"
    36  )
    37  
    38  type notFoundError struct {
    39  	t string
    40  	s Stream
    41  }
    42  
    43  func newNotFoundError(t string, s Stream) *notFoundError {
    44  	return &notFoundError{t: t, s: s}
    45  }
    46  
    47  func (e *notFoundError) Error() string {
    48  	return fmt.Sprintf("%s not found for stream %q", e.t, e.s)
    49  }
    50  
    51  // ErrMaxPeerServers will be returned if peer server limit is reached.
    52  // It will be sent in the SubscribeErrorMsg.
    53  var ErrMaxPeerServers = errors.New("max peer servers")
    54  
    55  // Peer is the Peer extension for the streaming protocol
    56  type Peer struct {
    57  	*protocols.Peer
    58  	streamer *Registry
    59  	pq       *pq.PriorityQueue
    60  	serverMu sync.RWMutex
    61  	clientMu sync.RWMutex // protects both clients and clientParams
    62  	servers  map[Stream]*server
    63  	clients  map[Stream]*client
    64  	// clientParams map keeps required client arguments
    65  	// that are set on Registry.Subscribe and used
    66  	// on creating a new client in offered hashes handler.
    67  	clientParams map[Stream]*clientParams
    68  	quit         chan struct{}
    69  }
    70  
    71  type WrappedPriorityMsg struct {
    72  	Context context.Context
    73  	Msg     interface{}
    74  }
    75  
    76  // NewPeer is the constructor for Peer
    77  func NewPeer(peer *protocols.Peer, streamer *Registry) *Peer {
    78  	p := &Peer{
    79  		Peer:         peer,
    80  		pq:           pq.New(int(PriorityQueue), PriorityQueueCap),
    81  		streamer:     streamer,
    82  		servers:      make(map[Stream]*server),
    83  		clients:      make(map[Stream]*client),
    84  		clientParams: make(map[Stream]*clientParams),
    85  		quit:         make(chan struct{}),
    86  	}
    87  	ctx, cancel := context.WithCancel(context.Background())
    88  	go p.pq.Run(ctx, func(i interface{}) {
    89  		wmsg := i.(WrappedPriorityMsg)
    90  		err := p.Send(wmsg.Context, wmsg.Msg)
    91  		if err != nil {
    92  			log.Error("Message send error, dropping peer", "peer", p.ID(), "err", err)
    93  			p.Drop(err)
    94  		}
    95  	})
    96  
    97  	// basic monitoring for pq contention
    98  	go func(pq *pq.PriorityQueue) {
    99  		ticker := time.NewTicker(5 * time.Second)
   100  		defer ticker.Stop()
   101  		for {
   102  			select {
   103  			case <-ticker.C:
   104  				var lenMaxi int
   105  				var capMaxi int
   106  				for k := range pq.Queues {
   107  					if lenMaxi < len(pq.Queues[k]) {
   108  						lenMaxi = len(pq.Queues[k])
   109  					}
   110  
   111  					if capMaxi < cap(pq.Queues[k]) {
   112  						capMaxi = cap(pq.Queues[k])
   113  					}
   114  				}
   115  
   116  				metrics.GetOrRegisterGauge(fmt.Sprintf("pq_len_%s", p.ID().TerminalString()), nil).Update(int64(lenMaxi))
   117  				metrics.GetOrRegisterGauge(fmt.Sprintf("pq_cap_%s", p.ID().TerminalString()), nil).Update(int64(capMaxi))
   118  			case <-p.quit:
   119  				return
   120  			}
   121  		}
   122  	}(p.pq)
   123  
   124  	go func() {
   125  		<-p.quit
   126  
   127  		cancel()
   128  	}()
   129  	return p
   130  }
   131  
   132  // Deliver sends a storeRequestMsg protocol message to the peer
   133  // Depending on the `syncing` parameter we send different message types
   134  func (p *Peer) Deliver(ctx context.Context, chunk storage.Chunk, priority uint8, syncing bool) error {
   135  	var msg interface{}
   136  
   137  	spanName := "send.chunk.delivery"
   138  
   139  	//we send different types of messages if delivery is for syncing or retrievals,
   140  	//even if handling and content of the message are the same,
   141  	//because swap accounting decides which messages need accounting based on the message type
   142  	if syncing {
   143  		msg = &ChunkDeliveryMsgSyncing{
   144  			Addr:  chunk.Address(),
   145  			SData: chunk.Data(),
   146  		}
   147  		spanName += ".syncing"
   148  	} else {
   149  		msg = &ChunkDeliveryMsgRetrieval{
   150  			Addr:  chunk.Address(),
   151  			SData: chunk.Data(),
   152  		}
   153  		spanName += ".retrieval"
   154  	}
   155  
   156  	ctx = context.WithValue(ctx, "stream_send_tag", nil)
   157  	return p.SendPriority(ctx, msg, priority)
   158  }
   159  
   160  // SendPriority sends message to the peer using the outgoing priority queue
   161  func (p *Peer) SendPriority(ctx context.Context, msg interface{}, priority uint8) error {
   162  	defer metrics.GetOrRegisterResettingTimer(fmt.Sprintf("peer.sendpriority_t.%d", priority), nil).UpdateSince(time.Now())
   163  	ctx = tracing.StartSaveSpan(ctx)
   164  	metrics.GetOrRegisterCounter(fmt.Sprintf("peer.sendpriority.%d", priority), nil).Inc(1)
   165  	wmsg := WrappedPriorityMsg{
   166  		Context: ctx,
   167  		Msg:     msg,
   168  	}
   169  	err := p.pq.Push(wmsg, int(priority))
   170  	if err != nil {
   171  		log.Error("err on p.pq.Push", "err", err, "peer", p.ID())
   172  	}
   173  	return err
   174  }
   175  
   176  // SendOfferedHashes sends OfferedHashesMsg protocol msg
   177  func (p *Peer) SendOfferedHashes(s *server, f, t uint64) error {
   178  	var sp opentracing.Span
   179  	ctx, sp := spancontext.StartSpan(
   180  		context.TODO(),
   181  		"send.offered.hashes",
   182  	)
   183  	defer sp.Finish()
   184  
   185  	defer metrics.GetOrRegisterResettingTimer("send.offered.hashes", nil).UpdateSince(time.Now())
   186  
   187  	hashes, from, to, proof, err := s.setNextBatch(f, t)
   188  	if err != nil {
   189  		return err
   190  	}
   191  	// true only when quitting
   192  	if len(hashes) == 0 {
   193  		return nil
   194  	}
   195  	if proof == nil {
   196  		proof = &HandoverProof{
   197  			Handover: &Handover{},
   198  		}
   199  	}
   200  	s.currentBatch = hashes
   201  	msg := &OfferedHashesMsg{
   202  		HandoverProof: proof,
   203  		Hashes:        hashes,
   204  		From:          from,
   205  		To:            to,
   206  		Stream:        s.stream,
   207  	}
   208  	log.Trace("Swarm syncer offer batch", "peer", p.ID(), "stream", s.stream, "len", len(hashes), "from", from, "to", to)
   209  	ctx = context.WithValue(ctx, "stream_send_tag", "send.offered.hashes")
   210  	return p.SendPriority(ctx, msg, s.priority)
   211  }
   212  
   213  func (p *Peer) getServer(s Stream) (*server, error) {
   214  	p.serverMu.RLock()
   215  	defer p.serverMu.RUnlock()
   216  
   217  	server := p.servers[s]
   218  	if server == nil {
   219  		return nil, newNotFoundError("server", s)
   220  	}
   221  	return server, nil
   222  }
   223  
   224  func (p *Peer) setServer(s Stream, o Server, priority uint8) (*server, error) {
   225  	p.serverMu.Lock()
   226  	defer p.serverMu.Unlock()
   227  
   228  	if p.servers[s] != nil {
   229  		return nil, fmt.Errorf("server %s already registered", s)
   230  	}
   231  
   232  	if p.streamer.maxPeerServers > 0 && len(p.servers) >= p.streamer.maxPeerServers {
   233  		return nil, ErrMaxPeerServers
   234  	}
   235  
   236  	sessionIndex, err := o.SessionIndex()
   237  	if err != nil {
   238  		return nil, err
   239  	}
   240  	os := &server{
   241  		Server:       o,
   242  		stream:       s,
   243  		priority:     priority,
   244  		sessionIndex: sessionIndex,
   245  	}
   246  	p.servers[s] = os
   247  	return os, nil
   248  }
   249  
   250  func (p *Peer) removeServer(s Stream) error {
   251  	p.serverMu.Lock()
   252  	defer p.serverMu.Unlock()
   253  
   254  	server, ok := p.servers[s]
   255  	if !ok {
   256  		return newNotFoundError("server", s)
   257  	}
   258  	server.Close()
   259  	delete(p.servers, s)
   260  	return nil
   261  }
   262  
   263  func (p *Peer) getClient(ctx context.Context, s Stream) (c *client, err error) {
   264  	var params *clientParams
   265  	func() {
   266  		p.clientMu.RLock()
   267  		defer p.clientMu.RUnlock()
   268  
   269  		c = p.clients[s]
   270  		if c != nil {
   271  			return
   272  		}
   273  		params = p.clientParams[s]
   274  	}()
   275  	if c != nil {
   276  		return c, nil
   277  	}
   278  
   279  	if params != nil {
   280  		//debug.PrintStack()
   281  		if err := params.waitClient(ctx); err != nil {
   282  			return nil, err
   283  		}
   284  	}
   285  
   286  	p.clientMu.RLock()
   287  	defer p.clientMu.RUnlock()
   288  
   289  	c = p.clients[s]
   290  	if c != nil {
   291  		return c, nil
   292  	}
   293  	return nil, newNotFoundError("client", s)
   294  }
   295  
   296  func (p *Peer) getOrSetClient(s Stream, from, to uint64) (c *client, created bool, err error) {
   297  	p.clientMu.Lock()
   298  	defer p.clientMu.Unlock()
   299  
   300  	c = p.clients[s]
   301  	if c != nil {
   302  		return c, false, nil
   303  	}
   304  
   305  	f, err := p.streamer.GetClientFunc(s.Name)
   306  	if err != nil {
   307  		return nil, false, err
   308  	}
   309  
   310  	is, err := f(p, s.Key, s.Live)
   311  	if err != nil {
   312  		return nil, false, err
   313  	}
   314  
   315  	cp, err := p.getClientParams(s)
   316  	if err != nil {
   317  		return nil, false, err
   318  	}
   319  	defer func() {
   320  		if err == nil {
   321  			if err := p.removeClientParams(s); err != nil {
   322  				log.Error("stream set client: remove client params", "stream", s, "peer", p, "err", err)
   323  			}
   324  		}
   325  	}()
   326  
   327  	intervalsKey := peerStreamIntervalsKey(p, s)
   328  	if s.Live {
   329  		// try to find previous history and live intervals and merge live into history
   330  		historyKey := peerStreamIntervalsKey(p, NewStream(s.Name, s.Key, false))
   331  		historyIntervals := &intervals.Intervals{}
   332  		err := p.streamer.intervalsStore.Get(historyKey, historyIntervals)
   333  		switch err {
   334  		case nil:
   335  			liveIntervals := &intervals.Intervals{}
   336  			err := p.streamer.intervalsStore.Get(intervalsKey, liveIntervals)
   337  			switch err {
   338  			case nil:
   339  				historyIntervals.Merge(liveIntervals)
   340  				if err := p.streamer.intervalsStore.Put(historyKey, historyIntervals); err != nil {
   341  					log.Error("stream set client: put history intervals", "stream", s, "peer", p, "err", err)
   342  				}
   343  			case state.ErrNotFound:
   344  			default:
   345  				log.Error("stream set client: get live intervals", "stream", s, "peer", p, "err", err)
   346  			}
   347  		case state.ErrNotFound:
   348  		default:
   349  			log.Error("stream set client: get history intervals", "stream", s, "peer", p, "err", err)
   350  		}
   351  	}
   352  
   353  	if err := p.streamer.intervalsStore.Put(intervalsKey, intervals.NewIntervals(from)); err != nil {
   354  		return nil, false, err
   355  	}
   356  
   357  	next := make(chan error, 1)
   358  	c = &client{
   359  		Client:         is,
   360  		stream:         s,
   361  		priority:       cp.priority,
   362  		to:             cp.to,
   363  		next:           next,
   364  		quit:           make(chan struct{}),
   365  		intervalsStore: p.streamer.intervalsStore,
   366  		intervalsKey:   intervalsKey,
   367  	}
   368  	p.clients[s] = c
   369  	cp.clientCreated() // unblock all possible getClient calls that are waiting
   370  	next <- nil        // this is to allow wantedKeysMsg before first batch arrives
   371  	return c, true, nil
   372  }
   373  
   374  func (p *Peer) removeClient(s Stream) error {
   375  	p.clientMu.Lock()
   376  	defer p.clientMu.Unlock()
   377  
   378  	client, ok := p.clients[s]
   379  	if !ok {
   380  		return newNotFoundError("client", s)
   381  	}
   382  	client.close()
   383  	delete(p.clients, s)
   384  	return nil
   385  }
   386  
   387  func (p *Peer) setClientParams(s Stream, params *clientParams) error {
   388  	p.clientMu.Lock()
   389  	defer p.clientMu.Unlock()
   390  
   391  	if p.clients[s] != nil {
   392  		return fmt.Errorf("client %s already exists", s)
   393  	}
   394  	if p.clientParams[s] != nil {
   395  		return fmt.Errorf("client params %s already set", s)
   396  	}
   397  	p.clientParams[s] = params
   398  	return nil
   399  }
   400  
   401  func (p *Peer) getClientParams(s Stream) (*clientParams, error) {
   402  	params := p.clientParams[s]
   403  	if params == nil {
   404  		return nil, fmt.Errorf("client params '%v' not provided to peer %v", s, p.ID())
   405  	}
   406  	return params, nil
   407  }
   408  
   409  func (p *Peer) removeClientParams(s Stream) error {
   410  	_, ok := p.clientParams[s]
   411  	if !ok {
   412  		return newNotFoundError("client params", s)
   413  	}
   414  	delete(p.clientParams, s)
   415  	return nil
   416  }
   417  
   418  func (p *Peer) close() {
   419  	for _, s := range p.servers {
   420  		s.Close()
   421  	}
   422  }