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 }