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