github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/hive.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 12:09:47</date>
    10  //</624342672273838080>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package network
    29  
    30  import (
    31  	"fmt"
    32  	"sync"
    33  	"time"
    34  
    35  	"github.com/ethereum/go-ethereum/common/hexutil"
    36  	"github.com/ethereum/go-ethereum/p2p"
    37  	"github.com/ethereum/go-ethereum/p2p/discover"
    38  	"github.com/ethereum/go-ethereum/swarm/log"
    39  	"github.com/ethereum/go-ethereum/swarm/state"
    40  )
    41  
    42  /*
    43  
    44  
    45  
    46  
    47  
    48  */
    49  
    50  
    51  //
    52  type Overlay interface {
    53  //
    54  	SuggestPeer() (OverlayAddr, int, bool)
    55  //
    56  	On(OverlayConn) (depth uint8, changed bool)
    57  	Off(OverlayConn)
    58  //
    59  	Register([]OverlayAddr) error
    60  //
    61  	EachConn([]byte, int, func(OverlayConn, int, bool) bool)
    62  //
    63  	EachAddr([]byte, int, func(OverlayAddr, int, bool) bool)
    64  //
    65  	String() string
    66  //
    67  	BaseAddr() []byte
    68  //
    69  	Healthy(*PeerPot) *Health
    70  }
    71  
    72  //
    73  type HiveParams struct {
    74  Discovery             bool  //
    75  PeersBroadcastSetSize uint8 //
    76  MaxPeersPerRequest    uint8 //
    77  	KeepAliveInterval     time.Duration
    78  }
    79  
    80  //
    81  func NewHiveParams() *HiveParams {
    82  	return &HiveParams{
    83  		Discovery:             true,
    84  		PeersBroadcastSetSize: 3,
    85  		MaxPeersPerRequest:    5,
    86  		KeepAliveInterval:     500 * time.Millisecond,
    87  	}
    88  }
    89  
    90  //
    91  type Hive struct {
    92  *HiveParams                      //
    93  Overlay                          //
    94  Store       state.Store          //
    95  addPeer     func(*discover.Node) //
    96  //
    97  	lock   sync.Mutex
    98  	ticker *time.Ticker
    99  }
   100  
   101  //
   102  //
   103  //
   104  //
   105  func NewHive(params *HiveParams, overlay Overlay, store state.Store) *Hive {
   106  	return &Hive{
   107  		HiveParams: params,
   108  		Overlay:    overlay,
   109  		Store:      store,
   110  	}
   111  }
   112  
   113  //
   114  //
   115  //
   116  func (h *Hive) Start(server *p2p.Server) error {
   117  	log.Info("Starting hive", "baseaddr", fmt.Sprintf("%x", h.BaseAddr()[:4]))
   118  //
   119  	if h.Store != nil {
   120  		log.Info("Detected an existing store. trying to load peers")
   121  		if err := h.loadPeers(); err != nil {
   122  			log.Error(fmt.Sprintf("%08x hive encoutered an error trying to load peers", h.BaseAddr()[:4]))
   123  			return err
   124  		}
   125  	}
   126  //
   127  	h.addPeer = server.AddPeer
   128  //
   129  	h.ticker = time.NewTicker(h.KeepAliveInterval)
   130  //
   131  	go h.connect()
   132  	return nil
   133  }
   134  
   135  //
   136  func (h *Hive) Stop() error {
   137  	log.Info(fmt.Sprintf("%08x hive stopping, saving peers", h.BaseAddr()[:4]))
   138  	h.ticker.Stop()
   139  	if h.Store != nil {
   140  		if err := h.savePeers(); err != nil {
   141  			return fmt.Errorf("could not save peers to persistence store: %v", err)
   142  		}
   143  		if err := h.Store.Close(); err != nil {
   144  			return fmt.Errorf("could not close file handle to persistence store: %v", err)
   145  		}
   146  	}
   147  	log.Info(fmt.Sprintf("%08x hive stopped, dropping peers", h.BaseAddr()[:4]))
   148  	h.EachConn(nil, 255, func(p OverlayConn, _ int, _ bool) bool {
   149  		log.Info(fmt.Sprintf("%08x dropping peer %08x", h.BaseAddr()[:4], p.Address()[:4]))
   150  		p.Drop(nil)
   151  		return true
   152  	})
   153  
   154  	log.Info(fmt.Sprintf("%08x all peers dropped", h.BaseAddr()[:4]))
   155  	return nil
   156  }
   157  
   158  //
   159  //
   160  //
   161  func (h *Hive) connect() {
   162  	for range h.ticker.C {
   163  
   164  		addr, depth, changed := h.SuggestPeer()
   165  		if h.Discovery && changed {
   166  			NotifyDepth(uint8(depth), h)
   167  		}
   168  		if addr == nil {
   169  			continue
   170  		}
   171  
   172  		log.Trace(fmt.Sprintf("%08x hive connect() suggested %08x", h.BaseAddr()[:4], addr.Address()[:4]))
   173  		under, err := discover.ParseNode(string(addr.(Addr).Under()))
   174  		if err != nil {
   175  			log.Warn(fmt.Sprintf("%08x unable to connect to bee %08x: invalid node URL: %v", h.BaseAddr()[:4], addr.Address()[:4], err))
   176  			continue
   177  		}
   178  		log.Trace(fmt.Sprintf("%08x attempt to connect to bee %08x", h.BaseAddr()[:4], addr.Address()[:4]))
   179  		h.addPeer(under)
   180  	}
   181  }
   182  
   183  //
   184  func (h *Hive) Run(p *BzzPeer) error {
   185  	dp := newDiscovery(p, h)
   186  	depth, changed := h.On(dp)
   187  //
   188  	if h.Discovery {
   189  		if changed {
   190  //
   191  			NotifyDepth(depth, h)
   192  		} else {
   193  //
   194  			dp.NotifyDepth(depth)
   195  		}
   196  	}
   197  	NotifyPeer(p.Off(), h)
   198  	defer h.Off(dp)
   199  	return dp.Run(dp.HandleMsg)
   200  }
   201  
   202  //
   203  //
   204  func (h *Hive) NodeInfo() interface{} {
   205  	return h.String()
   206  }
   207  
   208  //
   209  //
   210  func (h *Hive) PeerInfo(id discover.NodeID) interface{} {
   211  	addr := NewAddrFromNodeID(id)
   212  	return struct {
   213  		OAddr hexutil.Bytes
   214  		UAddr hexutil.Bytes
   215  	}{
   216  		OAddr: addr.OAddr,
   217  		UAddr: addr.UAddr,
   218  	}
   219  }
   220  
   221  //
   222  func ToAddr(pa OverlayPeer) *BzzAddr {
   223  	if addr, ok := pa.(*BzzAddr); ok {
   224  		return addr
   225  	}
   226  	if p, ok := pa.(*discPeer); ok {
   227  		return p.BzzAddr
   228  	}
   229  	return pa.(*BzzPeer).BzzAddr
   230  }
   231  
   232  //
   233  func (h *Hive) loadPeers() error {
   234  	var as []*BzzAddr
   235  	err := h.Store.Get("peers", &as)
   236  	if err != nil {
   237  		if err == state.ErrNotFound {
   238  			log.Info(fmt.Sprintf("hive %08x: no persisted peers found", h.BaseAddr()[:4]))
   239  			return nil
   240  		}
   241  		return err
   242  	}
   243  	log.Info(fmt.Sprintf("hive %08x: peers loaded", h.BaseAddr()[:4]))
   244  
   245  	return h.Register(toOverlayAddrs(as...))
   246  }
   247  
   248  //
   249  func toOverlayAddrs(as ...*BzzAddr) (oas []OverlayAddr) {
   250  	for _, a := range as {
   251  		oas = append(oas, OverlayAddr(a))
   252  	}
   253  	return
   254  }
   255  
   256  //
   257  func (h *Hive) savePeers() error {
   258  	var peers []*BzzAddr
   259  	h.Overlay.EachAddr(nil, 256, func(pa OverlayAddr, i int, _ bool) bool {
   260  		if pa == nil {
   261  			log.Warn(fmt.Sprintf("empty addr: %v", i))
   262  			return true
   263  		}
   264  		apa := ToAddr(pa)
   265  		log.Trace("saving peer", "peer", apa)
   266  		peers = append(peers, apa)
   267  		return true
   268  	})
   269  	if err := h.Store.Put("peers", peers); err != nil {
   270  		return fmt.Errorf("could not save peers: %v", err)
   271  	}
   272  	return nil
   273  }
   274