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