github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/swarm/network/discovery.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  //</624342672139620352>
    11  
    12  //
    13  //
    14  //
    15  //
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  //
    25  //
    26  //
    27  
    28  package network
    29  
    30  import (
    31  	"context"
    32  	"fmt"
    33  	"sync"
    34  
    35  	"github.com/ethereum/go-ethereum/swarm/pot"
    36  )
    37  
    38  //
    39  
    40  //
    41  type discPeer struct {
    42  	*BzzPeer
    43  	overlay   Overlay
    44  sentPeers bool //
    45  	mtx       sync.RWMutex
    46  peers     map[string]bool //
    47  depth     uint8           //
    48  }
    49  
    50  //
    51  func newDiscovery(p *BzzPeer, o Overlay) *discPeer {
    52  	d := &discPeer{
    53  		overlay: o,
    54  		BzzPeer: p,
    55  		peers:   make(map[string]bool),
    56  	}
    57  //
    58  	d.seen(d)
    59  	return d
    60  }
    61  
    62  //
    63  func (d *discPeer) HandleMsg(ctx context.Context, msg interface{}) error {
    64  	switch msg := msg.(type) {
    65  
    66  	case *peersMsg:
    67  		return d.handlePeersMsg(msg)
    68  
    69  	case *subPeersMsg:
    70  		return d.handleSubPeersMsg(msg)
    71  
    72  	default:
    73  		return fmt.Errorf("unknown message type: %T", msg)
    74  	}
    75  }
    76  
    77  //
    78  func NotifyDepth(depth uint8, h Overlay) {
    79  	f := func(val OverlayConn, po int, _ bool) bool {
    80  		dp, ok := val.(*discPeer)
    81  		if ok {
    82  			dp.NotifyDepth(depth)
    83  		}
    84  		return true
    85  	}
    86  	h.EachConn(nil, 255, f)
    87  }
    88  
    89  //
    90  func NotifyPeer(p OverlayAddr, k Overlay) {
    91  	f := func(val OverlayConn, po int, _ bool) bool {
    92  		dp, ok := val.(*discPeer)
    93  		if ok {
    94  			dp.NotifyPeer(p, uint8(po))
    95  		}
    96  		return true
    97  	}
    98  	k.EachConn(p.Address(), 255, f)
    99  }
   100  
   101  //
   102  //
   103  //
   104  //
   105  func (d *discPeer) NotifyPeer(a OverlayAddr, po uint8) {
   106  //
   107  	if (po < d.getDepth() && pot.ProxCmp(d.localAddr, d, a) != 1) || d.seen(a) {
   108  		return
   109  	}
   110  //
   111  	resp := &peersMsg{
   112  		Peers: []*BzzAddr{ToAddr(a)},
   113  	}
   114  	go d.Send(context.TODO(), resp)
   115  }
   116  
   117  //
   118  //
   119  func (d *discPeer) NotifyDepth(po uint8) {
   120  //
   121  	go d.Send(context.TODO(), &subPeersMsg{Depth: po})
   122  }
   123  
   124  /*
   125  
   126  
   127  
   128  
   129  
   130  
   131  
   132  
   133  
   134  
   135  
   136  
   137  
   138  */
   139  
   140  
   141  //
   142  //
   143  //
   144  type peersMsg struct {
   145  	Peers []*BzzAddr
   146  }
   147  
   148  //
   149  func (msg peersMsg) String() string {
   150  	return fmt.Sprintf("%T: %v", msg, msg.Peers)
   151  }
   152  
   153  //
   154  //
   155  //
   156  func (d *discPeer) handlePeersMsg(msg *peersMsg) error {
   157  //
   158  	if len(msg.Peers) == 0 {
   159  		return nil
   160  	}
   161  
   162  	for _, a := range msg.Peers {
   163  		d.seen(a)
   164  		NotifyPeer(a, d.overlay)
   165  	}
   166  	return d.overlay.Register(toOverlayAddrs(msg.Peers...))
   167  }
   168  
   169  //
   170  type subPeersMsg struct {
   171  	Depth uint8
   172  }
   173  
   174  //
   175  func (msg subPeersMsg) String() string {
   176  	return fmt.Sprintf("%T: request peers > PO%02d. ", msg, msg.Depth)
   177  }
   178  
   179  func (d *discPeer) handleSubPeersMsg(msg *subPeersMsg) error {
   180  	if !d.sentPeers {
   181  		d.setDepth(msg.Depth)
   182  		var peers []*BzzAddr
   183  		d.overlay.EachConn(d.Over(), 255, func(p OverlayConn, po int, isproxbin bool) bool {
   184  			if pob, _ := pof(d, d.localAddr, 0); pob > po {
   185  				return false
   186  			}
   187  			if !d.seen(p) {
   188  				peers = append(peers, ToAddr(p.Off()))
   189  			}
   190  			return true
   191  		})
   192  		if len(peers) > 0 {
   193  //
   194  			go d.Send(context.TODO(), &peersMsg{Peers: peers})
   195  		}
   196  	}
   197  	d.sentPeers = true
   198  	return nil
   199  }
   200  
   201  //
   202  //
   203  func (d *discPeer) seen(p OverlayPeer) bool {
   204  	d.mtx.Lock()
   205  	defer d.mtx.Unlock()
   206  	k := string(p.Address())
   207  	if d.peers[k] {
   208  		return true
   209  	}
   210  	d.peers[k] = true
   211  	return false
   212  }
   213  
   214  func (d *discPeer) getDepth() uint8 {
   215  	d.mtx.RLock()
   216  	defer d.mtx.RUnlock()
   217  	return d.depth
   218  }
   219  func (d *discPeer) setDepth(depth uint8) {
   220  	d.mtx.Lock()
   221  	defer d.mtx.Unlock()
   222  	d.depth = depth
   223  }
   224