github.com/etsc3259/etsc@v0.0.0-20190109113336-a9c2c10f9c95/swarm/network/stream/stream.go (about)

     1  // Copyright 2018 The go-etsc Authors
     2  // This file is part of the go-etsc library.
     3  //
     4  // The go-etsc 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-etsc 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-etsc library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package stream
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"math"
    24  	"sync"
    25  	"time"
    26  
    27  	"github.com/ETSC3259/etsc/metrics"
    28  	"github.com/ETSC3259/etsc/p2p"
    29  	"github.com/ETSC3259/etsc/p2p/enode"
    30  	"github.com/ETSC3259/etsc/p2p/protocols"
    31  	"github.com/ETSC3259/etsc/rpc"
    32  	"github.com/ETSC3259/etsc/swarm/log"
    33  	"github.com/ETSC3259/etsc/swarm/network"
    34  	"github.com/ETSC3259/etsc/swarm/network/stream/intervals"
    35  	"github.com/ETSC3259/etsc/swarm/pot"
    36  	"github.com/ETSC3259/etsc/swarm/state"
    37  	"github.com/ETSC3259/etsc/swarm/storage"
    38  )
    39  
    40  const (
    41  	Low uint8 = iota
    42  	Mid
    43  	High
    44  	Top
    45  	PriorityQueue    = 4    // number of priority queues - Low, Mid, High, Top
    46  	PriorityQueueCap = 4096 // queue capacity
    47  	HashSize         = 32
    48  )
    49  
    50  //Enumerate options for syncing and retrieval
    51  type SyncingOption int
    52  type RetrievalOption int
    53  
    54  //Syncing options
    55  const (
    56  	//Syncing disabled
    57  	SyncingDisabled SyncingOption = iota
    58  	//Register the client and the server but not subscribe
    59  	SyncingRegisterOnly
    60  	//Both client and server funcs are registered, subscribe sent automatically
    61  	SyncingAutoSubscribe
    62  )
    63  
    64  const (
    65  	//Retrieval disabled. Used mostly for tests to isolate syncing features (i.e. syncing only)
    66  	RetrievalDisabled RetrievalOption = iota
    67  	//Only the client side of the retrieve request is registered.
    68  	//(light nodes do not serve retrieve requests)
    69  	//once the client is registered, subscription to retrieve request stream is always sent
    70  	RetrievalClientOnly
    71  	//Both client and server funcs are registered, subscribe sent automatically
    72  	RetrievalEnabled
    73  )
    74  
    75  // Registry registry for outgoing and incoming streamer constructors
    76  type Registry struct {
    77  	addr           enode.ID
    78  	api            *API
    79  	skipCheck      bool
    80  	clientMu       sync.RWMutex
    81  	serverMu       sync.RWMutex
    82  	peersMu        sync.RWMutex
    83  	serverFuncs    map[string]func(*Peer, string, bool) (Server, error)
    84  	clientFuncs    map[string]func(*Peer, string, bool) (Client, error)
    85  	peers          map[enode.ID]*Peer
    86  	delivery       *Delivery
    87  	intervalsStore state.Store
    88  	autoRetrieval  bool //automatically subscribe to retrieve request stream
    89  	maxPeerServers int
    90  }
    91  
    92  // RegistryOptions holds optional values for NewRegistry constructor.
    93  type RegistryOptions struct {
    94  	SkipCheck       bool
    95  	Syncing         SyncingOption   //Defines syncing behavior
    96  	Retrieval       RetrievalOption //Defines retrieval behavior
    97  	SyncUpdateDelay time.Duration
    98  	MaxPeerServers  int // The limit of servers for each peer in registry
    99  }
   100  
   101  // NewRegistry is Streamer constructor
   102  func NewRegistry(localID enode.ID, delivery *Delivery, syncChunkStore storage.SyncChunkStore, intervalsStore state.Store, options *RegistryOptions) *Registry {
   103  	if options == nil {
   104  		options = &RegistryOptions{}
   105  	}
   106  	if options.SyncUpdateDelay <= 0 {
   107  		options.SyncUpdateDelay = 15 * time.Second
   108  	}
   109  	//check if retriaval has been disabled
   110  	retrieval := options.Retrieval != RetrievalDisabled
   111  
   112  	streamer := &Registry{
   113  		addr:           localID,
   114  		skipCheck:      options.SkipCheck,
   115  		serverFuncs:    make(map[string]func(*Peer, string, bool) (Server, error)),
   116  		clientFuncs:    make(map[string]func(*Peer, string, bool) (Client, error)),
   117  		peers:          make(map[enode.ID]*Peer),
   118  		delivery:       delivery,
   119  		intervalsStore: intervalsStore,
   120  		autoRetrieval:  retrieval,
   121  		maxPeerServers: options.MaxPeerServers,
   122  	}
   123  	streamer.api = NewAPI(streamer)
   124  	delivery.getPeer = streamer.getPeer
   125  
   126  	//if retrieval is enabled, register the server func, so that retrieve requests will be served (non-light nodes only)
   127  	if options.Retrieval == RetrievalEnabled {
   128  		streamer.RegisterServerFunc(swarmChunkServerStreamName, func(_ *Peer, _ string, live bool) (Server, error) {
   129  			if !live {
   130  				return nil, errors.New("only live retrieval requests supported")
   131  			}
   132  			return NewSwarmChunkServer(delivery.chunkStore), nil
   133  		})
   134  	}
   135  
   136  	//if retrieval is not disabled, register the client func (both light nodes and normal nodes can issue retrieve requests)
   137  	if options.Retrieval != RetrievalDisabled {
   138  		streamer.RegisterClientFunc(swarmChunkServerStreamName, func(p *Peer, t string, live bool) (Client, error) {
   139  			return NewSwarmSyncerClient(p, syncChunkStore, NewStream(swarmChunkServerStreamName, t, live))
   140  		})
   141  	}
   142  
   143  	//If syncing is not disabled, the syncing functions are registered (both client and server)
   144  	if options.Syncing != SyncingDisabled {
   145  		RegisterSwarmSyncerServer(streamer, syncChunkStore)
   146  		RegisterSwarmSyncerClient(streamer, syncChunkStore)
   147  	}
   148  
   149  	//if syncing is set to automatically subscribe to the syncing stream, start the subscription process
   150  	if options.Syncing == SyncingAutoSubscribe {
   151  		// latestIntC function ensures that
   152  		//   - receiving from the in chan is not blocked by processing inside the for loop
   153  		// 	 - the latest int value is delivered to the loop after the processing is done
   154  		// In context of NeighbourhoodDepthC:
   155  		// after the syncing is done updating inside the loop, we do not need to update on the intermediate
   156  		// depth changes, only to the latest one
   157  		latestIntC := func(in <-chan int) <-chan int {
   158  			out := make(chan int, 1)
   159  
   160  			go func() {
   161  				defer close(out)
   162  
   163  				for i := range in {
   164  					select {
   165  					case <-out:
   166  					default:
   167  					}
   168  					out <- i
   169  				}
   170  			}()
   171  
   172  			return out
   173  		}
   174  
   175  		go func() {
   176  			// wait for kademlia table to be healthy
   177  			time.Sleep(options.SyncUpdateDelay)
   178  
   179  			kad := streamer.delivery.kad
   180  			depthC := latestIntC(kad.NeighbourhoodDepthC())
   181  			addressBookSizeC := latestIntC(kad.AddrCountC())
   182  
   183  			// initial requests for syncing subscription to peers
   184  			streamer.updateSyncing()
   185  
   186  			for depth := range depthC {
   187  				log.Debug("Kademlia neighbourhood depth change", "depth", depth)
   188  
   189  				// Prevent too early sync subscriptions by waiting until there are no
   190  				// new peers connecting. Sync streams updating will be done after no
   191  				// peers are connected for at least SyncUpdateDelay period.
   192  				timer := time.NewTimer(options.SyncUpdateDelay)
   193  				// Hard limit to sync update delay, preventing long delays
   194  				// on a very dynamic network
   195  				maxTimer := time.NewTimer(3 * time.Minute)
   196  			loop:
   197  				for {
   198  					select {
   199  					case <-maxTimer.C:
   200  						// force syncing update when a hard timeout is reached
   201  						log.Trace("Sync subscriptions update on hard timeout")
   202  						// request for syncing subscription to new peers
   203  						streamer.updateSyncing()
   204  						break loop
   205  					case <-timer.C:
   206  						// start syncing as no new peers has been added to kademlia
   207  						// for some time
   208  						log.Trace("Sync subscriptions update")
   209  						// request for syncing subscription to new peers
   210  						streamer.updateSyncing()
   211  						break loop
   212  					case size := <-addressBookSizeC:
   213  						log.Trace("Kademlia address book size changed on depth change", "size", size)
   214  						// new peers has been added to kademlia,
   215  						// reset the timer to prevent early sync subscriptions
   216  						if !timer.Stop() {
   217  							<-timer.C
   218  						}
   219  						timer.Reset(options.SyncUpdateDelay)
   220  					}
   221  				}
   222  				timer.Stop()
   223  				maxTimer.Stop()
   224  			}
   225  		}()
   226  	}
   227  
   228  	return streamer
   229  }
   230  
   231  // RegisterClient registers an incoming streamer constructor
   232  func (r *Registry) RegisterClientFunc(stream string, f func(*Peer, string, bool) (Client, error)) {
   233  	r.clientMu.Lock()
   234  	defer r.clientMu.Unlock()
   235  
   236  	r.clientFuncs[stream] = f
   237  }
   238  
   239  // RegisterServer registers an outgoing streamer constructor
   240  func (r *Registry) RegisterServerFunc(stream string, f func(*Peer, string, bool) (Server, error)) {
   241  	r.serverMu.Lock()
   242  	defer r.serverMu.Unlock()
   243  
   244  	r.serverFuncs[stream] = f
   245  }
   246  
   247  // GetClient accessor for incoming streamer constructors
   248  func (r *Registry) GetClientFunc(stream string) (func(*Peer, string, bool) (Client, error), error) {
   249  	r.clientMu.RLock()
   250  	defer r.clientMu.RUnlock()
   251  
   252  	f := r.clientFuncs[stream]
   253  	if f == nil {
   254  		return nil, fmt.Errorf("stream %v not registered", stream)
   255  	}
   256  	return f, nil
   257  }
   258  
   259  // GetServer accessor for incoming streamer constructors
   260  func (r *Registry) GetServerFunc(stream string) (func(*Peer, string, bool) (Server, error), error) {
   261  	r.serverMu.RLock()
   262  	defer r.serverMu.RUnlock()
   263  
   264  	f := r.serverFuncs[stream]
   265  	if f == nil {
   266  		return nil, fmt.Errorf("stream %v not registered", stream)
   267  	}
   268  	return f, nil
   269  }
   270  
   271  func (r *Registry) RequestSubscription(peerId enode.ID, s Stream, h *Range, prio uint8) error {
   272  	// check if the stream is registered
   273  	if _, err := r.GetServerFunc(s.Name); err != nil {
   274  		return err
   275  	}
   276  
   277  	peer := r.getPeer(peerId)
   278  	if peer == nil {
   279  		return fmt.Errorf("peer not found %v", peerId)
   280  	}
   281  
   282  	if _, err := peer.getServer(s); err != nil {
   283  		if e, ok := err.(*notFoundError); ok && e.t == "server" {
   284  			// request subscription only if the server for this stream is not created
   285  			log.Debug("RequestSubscription ", "peer", peerId, "stream", s, "history", h)
   286  			return peer.Send(context.TODO(), &RequestSubscriptionMsg{
   287  				Stream:   s,
   288  				History:  h,
   289  				Priority: prio,
   290  			})
   291  		}
   292  		return err
   293  	}
   294  	log.Trace("RequestSubscription: already subscribed", "peer", peerId, "stream", s, "history", h)
   295  	return nil
   296  }
   297  
   298  // Subscribe initiates the streamer
   299  func (r *Registry) Subscribe(peerId enode.ID, s Stream, h *Range, priority uint8) error {
   300  	// check if the stream is registered
   301  	if _, err := r.GetClientFunc(s.Name); err != nil {
   302  		return err
   303  	}
   304  
   305  	peer := r.getPeer(peerId)
   306  	if peer == nil {
   307  		return fmt.Errorf("peer not found %v", peerId)
   308  	}
   309  
   310  	var to uint64
   311  	if !s.Live && h != nil {
   312  		to = h.To
   313  	}
   314  
   315  	err := peer.setClientParams(s, newClientParams(priority, to))
   316  	if err != nil {
   317  		return err
   318  	}
   319  	if s.Live && h != nil {
   320  		if err := peer.setClientParams(
   321  			getscistoryStream(s),
   322  			newClientParams(getscistoryPriority(priority), h.To),
   323  		); err != nil {
   324  			return err
   325  		}
   326  	}
   327  
   328  	msg := &SubscribeMsg{
   329  		Stream:   s,
   330  		History:  h,
   331  		Priority: priority,
   332  	}
   333  	log.Debug("Subscribe ", "peer", peerId, "stream", s, "history", h)
   334  
   335  	return peer.SendPriority(context.TODO(), msg, priority)
   336  }
   337  
   338  func (r *Registry) Unsubscribe(peerId enode.ID, s Stream) error {
   339  	peer := r.getPeer(peerId)
   340  	if peer == nil {
   341  		return fmt.Errorf("peer not found %v", peerId)
   342  	}
   343  
   344  	msg := &UnsubscribeMsg{
   345  		Stream: s,
   346  	}
   347  	log.Debug("Unsubscribe ", "peer", peerId, "stream", s)
   348  
   349  	if err := peer.Send(context.TODO(), msg); err != nil {
   350  		return err
   351  	}
   352  	return peer.removeClient(s)
   353  }
   354  
   355  // Quit sends the QuitMsg to the peer to remove the
   356  // stream peer client and terminate the streaming.
   357  func (r *Registry) Quit(peerId enode.ID, s Stream) error {
   358  	peer := r.getPeer(peerId)
   359  	if peer == nil {
   360  		log.Debug("stream quit: peer not found", "peer", peerId, "stream", s)
   361  		// if the peer is not found, abort the request
   362  		return nil
   363  	}
   364  
   365  	msg := &QuitMsg{
   366  		Stream: s,
   367  	}
   368  	log.Debug("Quit ", "peer", peerId, "stream", s)
   369  
   370  	return peer.Send(context.TODO(), msg)
   371  }
   372  
   373  func (r *Registry) NodeInfo() interface{} {
   374  	return nil
   375  }
   376  
   377  func (r *Registry) PeerInfo(id enode.ID) interface{} {
   378  	return nil
   379  }
   380  
   381  func (r *Registry) Close() error {
   382  	return r.intervalsStore.Close()
   383  }
   384  
   385  func (r *Registry) getPeer(peerId enode.ID) *Peer {
   386  	r.peersMu.RLock()
   387  	defer r.peersMu.RUnlock()
   388  
   389  	return r.peers[peerId]
   390  }
   391  
   392  func (r *Registry) setPeer(peer *Peer) {
   393  	r.peersMu.Lock()
   394  	r.peers[peer.ID()] = peer
   395  	metrics.GetOrRegisterGauge("registry.peers", nil).Update(int64(len(r.peers)))
   396  	r.peersMu.Unlock()
   397  }
   398  
   399  func (r *Registry) deletePeer(peer *Peer) {
   400  	r.peersMu.Lock()
   401  	delete(r.peers, peer.ID())
   402  	metrics.GetOrRegisterGauge("registry.peers", nil).Update(int64(len(r.peers)))
   403  	r.peersMu.Unlock()
   404  }
   405  
   406  func (r *Registry) peersCount() (c int) {
   407  	r.peersMu.Lock()
   408  	c = len(r.peers)
   409  	r.peersMu.Unlock()
   410  	return
   411  }
   412  
   413  // Run protocol run function
   414  func (r *Registry) Run(p *network.BzzPeer) error {
   415  	sp := NewPeer(p.Peer, r)
   416  	r.setPeer(sp)
   417  	defer r.deletePeer(sp)
   418  	defer close(sp.quit)
   419  	defer sp.close()
   420  
   421  	if r.autoRetrieval && !p.LightNode {
   422  		err := r.Subscribe(p.ID(), NewStream(swarmChunkServerStreamName, "", true), nil, Top)
   423  		if err != nil {
   424  			return err
   425  		}
   426  	}
   427  
   428  	return sp.Run(sp.HandleMsg)
   429  }
   430  
   431  // updateSyncing subscribes to SYNC streams by iterating over the
   432  // kademlia connections and bins. If there are existing SYNC streams
   433  // and they are no longer required after iteration, request to Quit
   434  // them will be send to appropriate peers.
   435  func (r *Registry) updateSyncing() {
   436  	kad := r.delivery.kad
   437  	// map of all SYNC streams for all peers
   438  	// used at the and of the function to remove servers
   439  	// that are not needed anymore
   440  	subs := make(map[enode.ID]map[Stream]struct{})
   441  	r.peersMu.RLock()
   442  	for id, peer := range r.peers {
   443  		peer.serverMu.RLock()
   444  		for stream := range peer.servers {
   445  			if stream.Name == "SYNC" {
   446  				if _, ok := subs[id]; !ok {
   447  					subs[id] = make(map[Stream]struct{})
   448  				}
   449  				subs[id][stream] = struct{}{}
   450  			}
   451  		}
   452  		peer.serverMu.RUnlock()
   453  	}
   454  	r.peersMu.RUnlock()
   455  
   456  	// request subscriptions for all nodes and bins
   457  	kad.EachBin(r.addr[:], pot.DefaultPof(256), 0, func(p *network.Peer, bin int) bool {
   458  		log.Debug(fmt.Sprintf("Requesting subscription by: registry %s from peer %s for bin: %d", r.addr, p.ID(), bin))
   459  
   460  		// bin is always less then 256 and it is safe to convert it to type uint8
   461  		stream := NewStream("SYNC", FormatSyncBinKey(uint8(bin)), true)
   462  		if streams, ok := subs[p.ID()]; ok {
   463  			// delete live and history streams from the map, so that it won't be removed with a Quit request
   464  			delete(streams, stream)
   465  			delete(streams, getscistoryStream(stream))
   466  		}
   467  		err := r.RequestSubscription(p.ID(), stream, NewRange(0, 0), High)
   468  		if err != nil {
   469  			log.Debug("Request subscription", "err", err, "peer", p.ID(), "stream", stream)
   470  			return false
   471  		}
   472  		return true
   473  	})
   474  
   475  	// remove SYNC servers that do not need to be subscribed
   476  	for id, streams := range subs {
   477  		if len(streams) == 0 {
   478  			continue
   479  		}
   480  		peer := r.getPeer(id)
   481  		if peer == nil {
   482  			continue
   483  		}
   484  		for stream := range streams {
   485  			log.Debug("Remove sync server", "peer", id, "stream", stream)
   486  			err := r.Quit(peer.ID(), stream)
   487  			if err != nil && err != p2p.ErrShuttingDown {
   488  				log.Error("quit", "err", err, "peer", peer.ID(), "stream", stream)
   489  			}
   490  		}
   491  	}
   492  }
   493  
   494  func (r *Registry) runProtocol(p *p2p.Peer, rw p2p.MsgReadWriter) error {
   495  	peer := protocols.NewPeer(p, rw, Spec)
   496  	bp := network.NewBzzPeer(peer)
   497  	np := network.NewPeer(bp, r.delivery.kad)
   498  	r.delivery.kad.On(np)
   499  	defer r.delivery.kad.Off(np)
   500  	return r.Run(bp)
   501  }
   502  
   503  // HandleMsg is the message handler that delegates incoming messages
   504  func (p *Peer) HandleMsg(ctx context.Context, msg interface{}) error {
   505  	switch msg := msg.(type) {
   506  
   507  	case *SubscribeMsg:
   508  		return p.handleSubscribeMsg(ctx, msg)
   509  
   510  	case *SubscribeErrorMsg:
   511  		return p.handleSubscribeErrorMsg(msg)
   512  
   513  	case *UnsubscribeMsg:
   514  		return p.handleUnsubscribeMsg(msg)
   515  
   516  	case *OfferedHashesMsg:
   517  		return p.handleOfferedHashesMsg(ctx, msg)
   518  
   519  	case *TakeoverProofMsg:
   520  		return p.handleTakeoverProofMsg(ctx, msg)
   521  
   522  	case *WantedHashesMsg:
   523  		return p.handleWantedHashesMsg(ctx, msg)
   524  
   525  	case *ChunkDeliveryMsgRetrieval:
   526  		//handling chunk delivery is the same for retrieval and syncing, so let's cast the msg
   527  		return p.streamer.delivery.handleChunkDeliveryMsg(ctx, p, ((*ChunkDeliveryMsg)(msg)))
   528  
   529  	case *ChunkDeliveryMsgSyncing:
   530  		//handling chunk delivery is the same for retrieval and syncing, so let's cast the msg
   531  		return p.streamer.delivery.handleChunkDeliveryMsg(ctx, p, ((*ChunkDeliveryMsg)(msg)))
   532  
   533  	case *RetrieveRequestMsg:
   534  		return p.streamer.delivery.handleRetrieveRequestMsg(ctx, p, msg)
   535  
   536  	case *RequestSubscriptionMsg:
   537  		return p.handleRequestSubscription(ctx, msg)
   538  
   539  	case *QuitMsg:
   540  		return p.handleQuitMsg(msg)
   541  
   542  	default:
   543  		return fmt.Errorf("unknown message type: %T", msg)
   544  	}
   545  }
   546  
   547  type server struct {
   548  	Server
   549  	stream       Stream
   550  	priority     uint8
   551  	currentBatch []byte
   552  	sessionIndex uint64
   553  }
   554  
   555  // setNextBatch adjusts passed interval based on session index and whether
   556  // stream is live or history. It calls Server SetNextBatch with adjusted
   557  // interval and returns batch hashes and their interval.
   558  func (s *server) setNextBatch(from, to uint64) ([]byte, uint64, uint64, *HandoverProof, error) {
   559  	if s.stream.Live {
   560  		if from == 0 {
   561  			from = s.sessionIndex
   562  		}
   563  		if to <= from || from >= s.sessionIndex {
   564  			to = math.MaxUint64
   565  		}
   566  	} else {
   567  		if (to < from && to != 0) || from > s.sessionIndex {
   568  			return nil, 0, 0, nil, nil
   569  		}
   570  		if to == 0 || to > s.sessionIndex {
   571  			to = s.sessionIndex
   572  		}
   573  	}
   574  	return s.SetNextBatch(from, to)
   575  }
   576  
   577  // Server interface for outgoing peer Streamer
   578  type Server interface {
   579  	// SessionIndex is called when a server is initialized
   580  	// to get the current cursor state of the stream data.
   581  	// Based on this index, live and history stream intervals
   582  	// will be adjusted before calling SetNextBatch.
   583  	SessionIndex() (uint64, error)
   584  	SetNextBatch(uint64, uint64) (hashes []byte, from uint64, to uint64, proof *HandoverProof, err error)
   585  	GetData(context.Context, []byte) ([]byte, error)
   586  	Close()
   587  }
   588  
   589  type client struct {
   590  	Client
   591  	stream    Stream
   592  	priority  uint8
   593  	sessionAt uint64
   594  	to        uint64
   595  	next      chan error
   596  	quit      chan struct{}
   597  
   598  	intervalsKey   string
   599  	intervalsStore state.Store
   600  }
   601  
   602  func peerStreamIntervalsKey(p *Peer, s Stream) string {
   603  	return p.ID().String() + s.String()
   604  }
   605  
   606  func (c client) AddInterval(start, end uint64) (err error) {
   607  	i := &intervals.Intervals{}
   608  	err = c.intervalsStore.Get(c.intervalsKey, i)
   609  	if err != nil {
   610  		return err
   611  	}
   612  	i.Add(start, end)
   613  	return c.intervalsStore.Put(c.intervalsKey, i)
   614  }
   615  
   616  func (c client) NextInterval() (start, end uint64, err error) {
   617  	i := &intervals.Intervals{}
   618  	err = c.intervalsStore.Get(c.intervalsKey, i)
   619  	if err != nil {
   620  		return 0, 0, err
   621  	}
   622  	start, end = i.Next()
   623  	return start, end, nil
   624  }
   625  
   626  // Client interface for incoming peer Streamer
   627  type Client interface {
   628  	NeedData(context.Context, []byte) func(context.Context) error
   629  	BatchDone(Stream, uint64, []byte, []byte) func() (*TakeoverProof, error)
   630  	Close()
   631  }
   632  
   633  func (c *client) nextBatch(from uint64) (nextFrom uint64, nextTo uint64) {
   634  	if c.to > 0 && from >= c.to {
   635  		return 0, 0
   636  	}
   637  	if c.stream.Live {
   638  		return from, 0
   639  	} else if from >= c.sessionAt {
   640  		if c.to > 0 {
   641  			return from, c.to
   642  		}
   643  		return from, math.MaxUint64
   644  	}
   645  	nextFrom, nextTo, err := c.NextInterval()
   646  	if err != nil {
   647  		log.Error("next intervals", "stream", c.stream)
   648  		return
   649  	}
   650  	if nextTo > c.to {
   651  		nextTo = c.to
   652  	}
   653  	if nextTo == 0 {
   654  		nextTo = c.sessionAt
   655  	}
   656  	return
   657  }
   658  
   659  func (c *client) batchDone(p *Peer, req *OfferedHashesMsg, hashes []byte) error {
   660  	if tf := c.BatchDone(req.Stream, req.From, hashes, req.Root); tf != nil {
   661  		tp, err := tf()
   662  		if err != nil {
   663  			return err
   664  		}
   665  		if err := p.SendPriority(context.TODO(), tp, c.priority); err != nil {
   666  			return err
   667  		}
   668  		if c.to > 0 && tp.Takeover.End >= c.to {
   669  			return p.streamer.Unsubscribe(p.Peer.ID(), req.Stream)
   670  		}
   671  		return nil
   672  	}
   673  	// TODO: make a test case for testing if the interval is added when the batch is done
   674  	if err := c.AddInterval(req.From, req.To); err != nil {
   675  		return err
   676  	}
   677  	return nil
   678  }
   679  
   680  func (c *client) close() {
   681  	select {
   682  	case <-c.quit:
   683  	default:
   684  		close(c.quit)
   685  	}
   686  	c.Close()
   687  }
   688  
   689  // clientParams store parameters for the new client
   690  // between a subscription and initial offered hashes request handling.
   691  type clientParams struct {
   692  	priority uint8
   693  	to       uint64
   694  	// signal when the client is created
   695  	clientCreatedC chan struct{}
   696  }
   697  
   698  func newClientParams(priority uint8, to uint64) *clientParams {
   699  	return &clientParams{
   700  		priority:       priority,
   701  		to:             to,
   702  		clientCreatedC: make(chan struct{}),
   703  	}
   704  }
   705  
   706  func (c *clientParams) waitClient(ctx context.Context) error {
   707  	select {
   708  	case <-ctx.Done():
   709  		return ctx.Err()
   710  	case <-c.clientCreatedC:
   711  		return nil
   712  	}
   713  }
   714  
   715  func (c *clientParams) clientCreated() {
   716  	close(c.clientCreatedC)
   717  }
   718  
   719  // Spec is the spec of the streamer protocol
   720  var Spec = &protocols.Spec{
   721  	Name:       "stream",
   722  	Version:    8,
   723  	MaxMsgSize: 10 * 1024 * 1024,
   724  	Messages: []interface{}{
   725  		UnsubscribeMsg{},
   726  		OfferedHashesMsg{},
   727  		WantedHashesMsg{},
   728  		TakeoverProofMsg{},
   729  		SubscribeMsg{},
   730  		RetrieveRequestMsg{},
   731  		ChunkDeliveryMsgRetrieval{},
   732  		SubscribeErrorMsg{},
   733  		RequestSubscriptionMsg{},
   734  		QuitMsg{},
   735  		ChunkDeliveryMsgSyncing{},
   736  	},
   737  }
   738  
   739  func (r *Registry) Protocols() []p2p.Protocol {
   740  	return []p2p.Protocol{
   741  		{
   742  			Name:    Spec.Name,
   743  			Version: Spec.Version,
   744  			Length:  Spec.Length(),
   745  			Run:     r.runProtocol,
   746  			// NodeInfo: ,
   747  			// PeerInfo: ,
   748  		},
   749  	}
   750  }
   751  
   752  func (r *Registry) APIs() []rpc.API {
   753  	return []rpc.API{
   754  		{
   755  			Namespace: "stream",
   756  			Version:   "3.0",
   757  			Service:   r.api,
   758  			Public:    true,
   759  		},
   760  	}
   761  }
   762  
   763  func (r *Registry) Start(server *p2p.Server) error {
   764  	log.Info("Streamer started")
   765  	return nil
   766  }
   767  
   768  func (r *Registry) Stop() error {
   769  	return nil
   770  }
   771  
   772  type Range struct {
   773  	From, To uint64
   774  }
   775  
   776  func NewRange(from, to uint64) *Range {
   777  	return &Range{
   778  		From: from,
   779  		To:   to,
   780  	}
   781  }
   782  
   783  func (r *Range) String() string {
   784  	return fmt.Sprintf("%v-%v", r.From, r.To)
   785  }
   786  
   787  func getscistoryPriority(priority uint8) uint8 {
   788  	if priority == 0 {
   789  		return 0
   790  	}
   791  	return priority - 1
   792  }
   793  
   794  func getscistoryStream(s Stream) Stream {
   795  	return NewStream(s.Name, s.Key, false)
   796  }
   797  
   798  type API struct {
   799  	streamer *Registry
   800  }
   801  
   802  func NewAPI(r *Registry) *API {
   803  	return &API{
   804  		streamer: r,
   805  	}
   806  }
   807  
   808  func (api *API) SubscribeStream(peerId enode.ID, s Stream, history *Range, priority uint8) error {
   809  	return api.streamer.Subscribe(peerId, s, history, priority)
   810  }
   811  
   812  func (api *API) UnsubscribeStream(peerId enode.ID, s Stream) error {
   813  	return api.streamer.Unsubscribe(peerId, s)
   814  }