github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/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 19:16:43</date> 10 //</624450113510576128> 11 12 13 package network 14 15 import ( 16 "context" 17 "fmt" 18 "sync" 19 20 "github.com/ethereum/go-ethereum/swarm/pot" 21 ) 22 23 //用于请求和中继节点地址记录的Discovery BZZ扩展 24 25 //Peer包装BZZPeer并嵌入Kademlia覆盖连接驱动程序 26 type Peer struct { 27 *BzzPeer 28 kad *Kademlia 29 sentPeers bool //是否已将对等机发送到该地址附近 30 mtx sync.RWMutex // 31 peers map[string]bool //跟踪发送到对等机的节点记录 32 depth uint8 //远程通知的接近顺序为饱和深度 33 } 34 35 //newpeer构造发现对等 36 func NewPeer(p *BzzPeer, kad *Kademlia) *Peer { 37 d := &Peer{ 38 kad: kad, 39 BzzPeer: p, 40 peers: make(map[string]bool), 41 } 42 //记录所见的远程信息,因此我们从不向对等端发送自己的记录。 43 d.seen(p.BzzAddr) 44 return d 45 } 46 47 //handlemsg是委托传入消息的消息处理程序 48 func (d *Peer) HandleMsg(ctx context.Context, msg interface{}) error { 49 switch msg := msg.(type) { 50 51 case *peersMsg: 52 return d.handlePeersMsg(msg) 53 54 case *subPeersMsg: 55 return d.handleSubPeersMsg(msg) 56 57 default: 58 return fmt.Errorf("unknown message type: %T", msg) 59 } 60 } 61 62 //如果饱和深度更改,notifydepth将向所有连接发送消息 63 func NotifyDepth(depth uint8, kad *Kademlia) { 64 f := func(val *Peer, po int) bool { 65 val.NotifyDepth(depth) 66 return true 67 } 68 kad.EachConn(nil, 255, f) 69 } 70 71 //notifypeer通知所有对等方新添加的节点 72 func NotifyPeer(p *BzzAddr, k *Kademlia) { 73 f := func(val *Peer, po int) bool { 74 val.NotifyPeer(p, uint8(po)) 75 return true 76 } 77 k.EachConn(p.Address(), 255, f) 78 } 79 80 //如果出现以下情况,notifypeer将通知远程节点(收件人)有关对等机的信息: 81 //对等方的采购订单在收件人的广告深度内 82 //或者对方比自己更接近对方 83 //除非在连接会话期间已通知 84 func (d *Peer) NotifyPeer(a *BzzAddr, po uint8) { 85 //立即返回 86 if (po < d.getDepth() && pot.ProxCmp(d.kad.BaseAddr(), d, a) != 1) || d.seen(a) { 87 return 88 } 89 resp := &peersMsg{ 90 Peers: []*BzzAddr{a}, 91 } 92 go d.Send(context.TODO(), resp) 93 } 94 95 //notifydepth向接收者发送一个子程序msg,通知他们 96 //饱和深度的变化 97 func (d *Peer) NotifyDepth(po uint8) { 98 go d.Send(context.TODO(), &subPeersMsg{Depth: po}) 99 } 100 101 /* 102 peersmsg是传递对等信息的消息 103 它始终是对peersrequestmsg的响应 104 105 对等地址的编码与DEVP2P基本协议对等机相同。 106 消息:[IP,端口,节点ID], 107 请注意,节点的文件存储地址不是nodeid,而是nodeid的哈希。 108 109 TODO: 110 为了减轻伪对等端消息的影响,请求应该被记住。 111 应检查响应的正确性。 112 113 如果响应中对等端的proxybin不正确,则发送方应 114 断开的 115 **/ 116 117 118 //peersmsg封装了一组对等地址 119 //用于交流已知的对等点 120 //与引导连接和更新对等集相关 121 type peersMsg struct { 122 Peers []*BzzAddr 123 } 124 125 //字符串漂亮打印一个peersmsg 126 func (msg peersMsg) String() string { 127 return fmt.Sprintf("%T: %v", msg, msg.Peers) 128 } 129 130 //接收对等集时协议调用的handlepeersmsg(用于目标地址) 131 //节点列表([]peeraddr in peerasmsg)使用 132 //寄存器接口方法 133 func (d *Peer) handlePeersMsg(msg *peersMsg) error { 134 //注册所有地址 135 if len(msg.Peers) == 0 { 136 return nil 137 } 138 139 for _, a := range msg.Peers { 140 d.seen(a) 141 NotifyPeer(a, d.kad) 142 } 143 return d.kad.Register(msg.Peers...) 144 } 145 146 //子进程消息正在通信对等进程覆盖表的深度。 147 type subPeersMsg struct { 148 Depth uint8 149 } 150 151 //字符串返回漂亮的打印机 152 func (msg subPeersMsg) String() string { 153 return fmt.Sprintf("%T: request peers > PO%02d. ", msg, msg.Depth) 154 } 155 156 func (d *Peer) handleSubPeersMsg(msg *subPeersMsg) error { 157 if !d.sentPeers { 158 d.setDepth(msg.Depth) 159 var peers []*BzzAddr 160 d.kad.EachConn(d.Over(), 255, func(p *Peer, po int) bool { 161 if pob, _ := Pof(d, d.kad.BaseAddr(), 0); pob > po { 162 return false 163 } 164 if !d.seen(p.BzzAddr) { 165 peers = append(peers, p.BzzAddr) 166 } 167 return true 168 }) 169 if len(peers) > 0 { 170 go d.Send(context.TODO(), &peersMsg{Peers: peers}) 171 } 172 } 173 d.sentPeers = true 174 return nil 175 } 176 177 //seen获取对等地址并检查是否已将其发送到对等。 178 //如果没有,则将对等机标记为已发送 179 func (d *Peer) seen(p *BzzAddr) bool { 180 d.mtx.Lock() 181 defer d.mtx.Unlock() 182 k := string(p.Address()) 183 if d.peers[k] { 184 return true 185 } 186 d.peers[k] = true 187 return false 188 } 189 190 func (d *Peer) getDepth() uint8 { 191 d.mtx.RLock() 192 defer d.mtx.RUnlock() 193 return d.depth 194 } 195 196 func (d *Peer) setDepth(depth uint8) { 197 d.mtx.Lock() 198 defer d.mtx.Unlock() 199 d.depth = depth 200 } 201