github.com/divan/go-ethereum@v1.8.14-0.20180820134928-1de9ada4016d/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  	"fmt"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/ethereum/go-ethereum/metrics"
    26  	"github.com/ethereum/go-ethereum/p2p/protocols"
    27  	"github.com/ethereum/go-ethereum/swarm/log"
    28  	pq "github.com/ethereum/go-ethereum/swarm/network/priorityqueue"
    29  	"github.com/ethereum/go-ethereum/swarm/network/stream/intervals"
    30  	"github.com/ethereum/go-ethereum/swarm/spancontext"
    31  	"github.com/ethereum/go-ethereum/swarm/state"
    32  	"github.com/ethereum/go-ethereum/swarm/storage"
    33  	opentracing "github.com/opentracing/opentracing-go"
    34  )
    35  
    36  var sendTimeout = 30 * time.Second
    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  // Peer is the Peer extension for the streaming protocol
    52  type Peer struct {
    53  	*protocols.Peer
    54  	streamer *Registry
    55  	pq       *pq.PriorityQueue
    56  	serverMu sync.RWMutex
    57  	clientMu sync.RWMutex // protects both clients and clientParams
    58  	servers  map[Stream]*server
    59  	clients  map[Stream]*client
    60  	// clientParams map keeps required client arguments
    61  	// that are set on Registry.Subscribe and used
    62  	// on creating a new client in offered hashes handler.
    63  	clientParams map[Stream]*clientParams
    64  	quit         chan struct{}
    65  }
    66  
    67  type WrappedPriorityMsg struct {
    68  	Context context.Context
    69  	Msg     interface{}
    70  }
    71  
    72  // NewPeer is the constructor for Peer
    73  func NewPeer(peer *protocols.Peer, streamer *Registry) *Peer {
    74  	p := &Peer{
    75  		Peer:         peer,
    76  		pq:           pq.New(int(PriorityQueue), PriorityQueueCap),
    77  		streamer:     streamer,
    78  		servers:      make(map[Stream]*server),
    79  		clients:      make(map[Stream]*client),
    80  		clientParams: make(map[Stream]*clientParams),
    81  		quit:         make(chan struct{}),
    82  	}
    83  	ctx, cancel := context.WithCancel(context.Background())
    84  	go p.pq.Run(ctx, func(i interface{}) {
    85  		wmsg := i.(WrappedPriorityMsg)
    86  		p.Send(wmsg.Context, wmsg.Msg)
    87  	})
    88  	go func() {
    89  		<-p.quit
    90  		cancel()
    91  	}()
    92  	return p
    93  }
    94  
    95  // Deliver sends a storeRequestMsg protocol message to the peer
    96  func (p *Peer) Deliver(ctx context.Context, chunk *storage.Chunk, priority uint8) error {
    97  	var sp opentracing.Span
    98  	ctx, sp = spancontext.StartSpan(
    99  		ctx,
   100  		"send.chunk.delivery")
   101  	defer sp.Finish()
   102  
   103  	msg := &ChunkDeliveryMsg{
   104  		Addr:  chunk.Addr,
   105  		SData: chunk.SData,
   106  	}
   107  	return p.SendPriority(ctx, msg, priority)
   108  }
   109  
   110  // SendPriority sends message to the peer using the outgoing priority queue
   111  func (p *Peer) SendPriority(ctx context.Context, msg interface{}, priority uint8) error {
   112  	defer metrics.GetOrRegisterResettingTimer(fmt.Sprintf("peer.sendpriority_t.%d", priority), nil).UpdateSince(time.Now())
   113  	metrics.GetOrRegisterCounter(fmt.Sprintf("peer.sendpriority.%d", priority), nil).Inc(1)
   114  	cctx, cancel := context.WithTimeout(context.Background(), sendTimeout)
   115  	defer cancel()
   116  	wmsg := WrappedPriorityMsg{
   117  		Context: ctx,
   118  		Msg:     msg,
   119  	}
   120  	return p.pq.Push(cctx, wmsg, int(priority))
   121  }
   122  
   123  // SendOfferedHashes sends OfferedHashesMsg protocol msg
   124  func (p *Peer) SendOfferedHashes(s *server, f, t uint64) error {
   125  	var sp opentracing.Span
   126  	ctx, sp := spancontext.StartSpan(
   127  		context.TODO(),
   128  		"send.offered.hashes")
   129  	defer sp.Finish()
   130  
   131  	hashes, from, to, proof, err := s.SetNextBatch(f, t)
   132  	if err != nil {
   133  		return err
   134  	}
   135  	// true only when quiting
   136  	if len(hashes) == 0 {
   137  		return nil
   138  	}
   139  	if proof == nil {
   140  		proof = &HandoverProof{
   141  			Handover: &Handover{},
   142  		}
   143  	}
   144  	s.currentBatch = hashes
   145  	msg := &OfferedHashesMsg{
   146  		HandoverProof: proof,
   147  		Hashes:        hashes,
   148  		From:          from,
   149  		To:            to,
   150  		Stream:        s.stream,
   151  	}
   152  	log.Trace("Swarm syncer offer batch", "peer", p.ID(), "stream", s.stream, "len", len(hashes), "from", from, "to", to)
   153  	return p.SendPriority(ctx, msg, s.priority)
   154  }
   155  
   156  func (p *Peer) getServer(s Stream) (*server, error) {
   157  	p.serverMu.RLock()
   158  	defer p.serverMu.RUnlock()
   159  
   160  	server := p.servers[s]
   161  	if server == nil {
   162  		return nil, newNotFoundError("server", s)
   163  	}
   164  	return server, nil
   165  }
   166  
   167  func (p *Peer) setServer(s Stream, o Server, priority uint8) (*server, error) {
   168  	p.serverMu.Lock()
   169  	defer p.serverMu.Unlock()
   170  
   171  	if p.servers[s] != nil {
   172  		return nil, fmt.Errorf("server %s already registered", s)
   173  	}
   174  	os := &server{
   175  		Server:   o,
   176  		stream:   s,
   177  		priority: priority,
   178  	}
   179  	p.servers[s] = os
   180  	return os, nil
   181  }
   182  
   183  func (p *Peer) removeServer(s Stream) error {
   184  	p.serverMu.Lock()
   185  	defer p.serverMu.Unlock()
   186  
   187  	server, ok := p.servers[s]
   188  	if !ok {
   189  		return newNotFoundError("server", s)
   190  	}
   191  	server.Close()
   192  	delete(p.servers, s)
   193  	return nil
   194  }
   195  
   196  func (p *Peer) getClient(ctx context.Context, s Stream) (c *client, err error) {
   197  	var params *clientParams
   198  	func() {
   199  		p.clientMu.RLock()
   200  		defer p.clientMu.RUnlock()
   201  
   202  		c = p.clients[s]
   203  		if c != nil {
   204  			return
   205  		}
   206  		params = p.clientParams[s]
   207  	}()
   208  	if c != nil {
   209  		return c, nil
   210  	}
   211  
   212  	if params != nil {
   213  		//debug.PrintStack()
   214  		if err := params.waitClient(ctx); err != nil {
   215  			return nil, err
   216  		}
   217  	}
   218  
   219  	p.clientMu.RLock()
   220  	defer p.clientMu.RUnlock()
   221  
   222  	c = p.clients[s]
   223  	if c != nil {
   224  		return c, nil
   225  	}
   226  	return nil, newNotFoundError("client", s)
   227  }
   228  
   229  func (p *Peer) getOrSetClient(s Stream, from, to uint64) (c *client, created bool, err error) {
   230  	p.clientMu.Lock()
   231  	defer p.clientMu.Unlock()
   232  
   233  	c = p.clients[s]
   234  	if c != nil {
   235  		return c, false, nil
   236  	}
   237  
   238  	f, err := p.streamer.GetClientFunc(s.Name)
   239  	if err != nil {
   240  		return nil, false, err
   241  	}
   242  
   243  	is, err := f(p, s.Key, s.Live)
   244  	if err != nil {
   245  		return nil, false, err
   246  	}
   247  
   248  	cp, err := p.getClientParams(s)
   249  	if err != nil {
   250  		return nil, false, err
   251  	}
   252  	defer func() {
   253  		if err == nil {
   254  			if err := p.removeClientParams(s); err != nil {
   255  				log.Error("stream set client: remove client params", "stream", s, "peer", p, "err", err)
   256  			}
   257  		}
   258  	}()
   259  
   260  	intervalsKey := peerStreamIntervalsKey(p, s)
   261  	if s.Live {
   262  		// try to find previous history and live intervals and merge live into history
   263  		historyKey := peerStreamIntervalsKey(p, NewStream(s.Name, s.Key, false))
   264  		historyIntervals := &intervals.Intervals{}
   265  		err := p.streamer.intervalsStore.Get(historyKey, historyIntervals)
   266  		switch err {
   267  		case nil:
   268  			liveIntervals := &intervals.Intervals{}
   269  			err := p.streamer.intervalsStore.Get(intervalsKey, liveIntervals)
   270  			switch err {
   271  			case nil:
   272  				historyIntervals.Merge(liveIntervals)
   273  				if err := p.streamer.intervalsStore.Put(historyKey, historyIntervals); err != nil {
   274  					log.Error("stream set client: put history intervals", "stream", s, "peer", p, "err", err)
   275  				}
   276  			case state.ErrNotFound:
   277  			default:
   278  				log.Error("stream set client: get live intervals", "stream", s, "peer", p, "err", err)
   279  			}
   280  		case state.ErrNotFound:
   281  		default:
   282  			log.Error("stream set client: get history intervals", "stream", s, "peer", p, "err", err)
   283  		}
   284  	}
   285  
   286  	if err := p.streamer.intervalsStore.Put(intervalsKey, intervals.NewIntervals(from)); err != nil {
   287  		return nil, false, err
   288  	}
   289  
   290  	next := make(chan error, 1)
   291  	c = &client{
   292  		Client:         is,
   293  		stream:         s,
   294  		priority:       cp.priority,
   295  		to:             cp.to,
   296  		next:           next,
   297  		quit:           make(chan struct{}),
   298  		intervalsStore: p.streamer.intervalsStore,
   299  		intervalsKey:   intervalsKey,
   300  	}
   301  	p.clients[s] = c
   302  	cp.clientCreated() // unblock all possible getClient calls that are waiting
   303  	next <- nil        // this is to allow wantedKeysMsg before first batch arrives
   304  	return c, true, nil
   305  }
   306  
   307  func (p *Peer) removeClient(s Stream) error {
   308  	p.clientMu.Lock()
   309  	defer p.clientMu.Unlock()
   310  
   311  	client, ok := p.clients[s]
   312  	if !ok {
   313  		return newNotFoundError("client", s)
   314  	}
   315  	client.close()
   316  	return nil
   317  }
   318  
   319  func (p *Peer) setClientParams(s Stream, params *clientParams) error {
   320  	p.clientMu.Lock()
   321  	defer p.clientMu.Unlock()
   322  
   323  	if p.clients[s] != nil {
   324  		return fmt.Errorf("client %s already exists", s)
   325  	}
   326  	if p.clientParams[s] != nil {
   327  		return fmt.Errorf("client params %s already set", s)
   328  	}
   329  	p.clientParams[s] = params
   330  	return nil
   331  }
   332  
   333  func (p *Peer) getClientParams(s Stream) (*clientParams, error) {
   334  	params := p.clientParams[s]
   335  	if params == nil {
   336  		return nil, fmt.Errorf("client params '%v' not provided to peer %v", s, p.ID())
   337  	}
   338  	return params, nil
   339  }
   340  
   341  func (p *Peer) removeClientParams(s Stream) error {
   342  	_, ok := p.clientParams[s]
   343  	if !ok {
   344  		return newNotFoundError("client params", s)
   345  	}
   346  	delete(p.clientParams, s)
   347  	return nil
   348  }
   349  
   350  func (p *Peer) close() {
   351  	for _, s := range p.servers {
   352  		s.Close()
   353  	}
   354  }