github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/message.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2014 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 package p2p 26 27 import ( 28 "bytes" 29 "errors" 30 "fmt" 31 "io" 32 "io/ioutil" 33 "sync/atomic" 34 "time" 35 36 "github.com/ethereum/go-ethereum/event" 37 "github.com/ethereum/go-ethereum/p2p/discover" 38 "github.com/ethereum/go-ethereum/rlp" 39 ) 40 41 //msg定义p2p消息的结构。 42 // 43 //注意,由于有效负载读卡器 44 //发送时消耗。无法创建消息和 45 //发送任意次数。如果要重用编码的 46 //结构,将有效负载编码为字节数组并创建 47 //用字节分隔消息。读卡器作为每次发送的有效负载。 48 type Msg struct { 49 Code uint64 50 Size uint32 //Paylod的规模 51 Payload io.Reader 52 ReceivedAt time.Time 53 } 54 55 //解码将消息的rlp内容解析为 56 //给定值,必须是指针。 57 // 58 //解码规则见RLP包。 59 func (msg Msg) Decode(val interface{}) error { 60 s := rlp.NewStream(msg.Payload, uint64(msg.Size)) 61 if err := s.Decode(val); err != nil { 62 return newPeerError(errInvalidMsg, "(code %x) (size %d) %v", msg.Code, msg.Size, err) 63 } 64 return nil 65 } 66 67 func (msg Msg) String() string { 68 return fmt.Sprintf("msg #%v (%v bytes)", msg.Code, msg.Size) 69 } 70 71 //丢弃将剩余的有效载荷数据读取到黑洞中。 72 func (msg Msg) Discard() error { 73 _, err := io.Copy(ioutil.Discard, msg.Payload) 74 return err 75 } 76 77 type MsgReader interface { 78 ReadMsg() (Msg, error) 79 } 80 81 type MsgWriter interface { 82 //writemsg发送消息。它将一直阻塞到消息 83 //另一端消耗了有效载荷。 84 // 85 //请注意,消息只能发送一次,因为它们 86 //有效负载读卡器已排空。 87 WriteMsg(Msg) error 88 } 89 90 //msgreadwriter提供对编码消息的读写。 91 //实现应该确保readmsg和writemsg可以 92 //从多个goroutine同时调用。 93 type MsgReadWriter interface { 94 MsgReader 95 MsgWriter 96 } 97 98 //send用给定的代码编写一个rlp编码的消息。 99 //数据应编码为RLP列表。 100 func Send(w MsgWriter, msgcode uint64, data interface{}) error { 101 size, r, err := rlp.EncodeToReader(data) 102 if err != nil { 103 return err 104 } 105 return w.WriteMsg(Msg{Code: msgcode, Size: uint32(size), Payload: r}) 106 } 107 108 //senditems用给定的代码和数据元素编写一个rlp。 109 //对于以下电话: 110 // 111 //发送项(W、代码、E1、E2、E3) 112 // 113 //消息有效负载将是包含以下项目的RLP列表: 114 // 115 //[E1,E2,E3] 116 // 117 func SendItems(w MsgWriter, msgcode uint64, elems ...interface{}) error { 118 return Send(w, msgcode, elems) 119 } 120 121 //eofsignal用eof信号包裹读卡器。EOF通道是 122 //当包装的读卡器返回错误或计数字节时关闭 123 //已经看过了。 124 type eofSignal struct { 125 wrapped io.Reader 126 count uint32 //剩余字节数 127 eof chan<- struct{} 128 } 129 130 //注意:使用eofsignal检测消息有效负载时 131 //已被读取,对于零大小的邮件可能不调用读取。 132 func (r *eofSignal) Read(buf []byte) (int, error) { 133 if r.count == 0 { 134 if r.eof != nil { 135 r.eof <- struct{}{} 136 r.eof = nil 137 } 138 return 0, io.EOF 139 } 140 141 max := len(buf) 142 if int(r.count) < len(buf) { 143 max = int(r.count) 144 } 145 n, err := r.wrapped.Read(buf[:max]) 146 r.count -= uint32(n) 147 if (err != nil || r.count == 0) && r.eof != nil { 148 r.eof <- struct{}{} //告诉对等机消息已被消耗 149 r.eof = nil 150 } 151 return n, err 152 } 153 154 //msgpipe创建消息管道。一端读取匹配 155 //写在另一个上面。管道为全双工,两端 156 //实现msgreadwriter。 157 func MsgPipe() (*MsgPipeRW, *MsgPipeRW) { 158 var ( 159 c1, c2 = make(chan Msg), make(chan Msg) 160 closing = make(chan struct{}) 161 closed = new(int32) 162 rw1 = &MsgPipeRW{c1, c2, closing, closed} 163 rw2 = &MsgPipeRW{c2, c1, closing, closed} 164 ) 165 return rw1, rw2 166 } 167 168 //errPipeClosed在 169 //管道已关闭。 170 var ErrPipeClosed = errors.New("p2p: read or write on closed message pipe") 171 172 //msgpiperw是msgreadwriter管道的端点。 173 type MsgPipeRW struct { 174 w chan<- Msg 175 r <-chan Msg 176 closing chan struct{} 177 closed *int32 178 } 179 180 //writemsg在管道上发送消息。 181 //它会一直阻塞,直到接收器消耗了消息有效负载。 182 func (p *MsgPipeRW) WriteMsg(msg Msg) error { 183 if atomic.LoadInt32(p.closed) == 0 { 184 consumed := make(chan struct{}, 1) 185 msg.Payload = &eofSignal{msg.Payload, msg.Size, consumed} 186 select { 187 case p.w <- msg: 188 if msg.Size > 0 { 189 //等待有效负载读取或丢弃 190 select { 191 case <-consumed: 192 case <-p.closing: 193 } 194 } 195 return nil 196 case <-p.closing: 197 } 198 } 199 return ErrPipeClosed 200 } 201 202 //readmsg返回在管道另一端发送的消息。 203 func (p *MsgPipeRW) ReadMsg() (Msg, error) { 204 if atomic.LoadInt32(p.closed) == 0 { 205 select { 206 case msg := <-p.r: 207 return msg, nil 208 case <-p.closing: 209 } 210 } 211 return Msg{}, ErrPipeClosed 212 } 213 214 //关闭取消阻止两端所有挂起的readmsg和writemsg调用 215 //管子的它们将返回errpipeClosed。关闭也 216 //中断对消息有效负载的任何读取。 217 func (p *MsgPipeRW) Close() error { 218 if atomic.AddInt32(p.closed, 1) != 1 { 219 //其他人已经关门了 220 atomic.StoreInt32(p.closed, 1) //避免溢出 221 return nil 222 } 223 close(p.closing) 224 return nil 225 } 226 227 //expectmsg从r读取消息并验证其 228 //代码和编码的rlp内容与提供的值匹配。 229 //如果内容为零,则丢弃有效负载,不进行验证。 230 func ExpectMsg(r MsgReader, code uint64, content interface{}) error { 231 msg, err := r.ReadMsg() 232 if err != nil { 233 return err 234 } 235 if msg.Code != code { 236 return fmt.Errorf("message code mismatch: got %d, expected %d", msg.Code, code) 237 } 238 if content == nil { 239 return msg.Discard() 240 } 241 contentEnc, err := rlp.EncodeToBytes(content) 242 if err != nil { 243 panic("content encode error: " + err.Error()) 244 } 245 if int(msg.Size) != len(contentEnc) { 246 return fmt.Errorf("message size mismatch: got %d, want %d", msg.Size, len(contentEnc)) 247 } 248 actualContent, err := ioutil.ReadAll(msg.Payload) 249 if err != nil { 250 return err 251 } 252 if !bytes.Equal(actualContent, contentEnc) { 253 return fmt.Errorf("message payload mismatch:\ngot: %x\nwant: %x", actualContent, contentEnc) 254 } 255 return nil 256 } 257 258 //msgeventer包装msgreadwriter并在每次发送消息时发送事件 259 //或收到 260 type msgEventer struct { 261 MsgReadWriter 262 263 feed *event.Feed 264 peerID discover.NodeID 265 Protocol string 266 } 267 268 //newmsgeventer返回一个msgeventer,它将消息事件发送到给定的 269 //喂养 270 func newMsgEventer(rw MsgReadWriter, feed *event.Feed, peerID discover.NodeID, proto string) *msgEventer { 271 return &msgEventer{ 272 MsgReadWriter: rw, 273 feed: feed, 274 peerID: peerID, 275 Protocol: proto, 276 } 277 } 278 279 //readmsg从基础msgreadwriter读取消息并发出 280 //“收到消息”事件 281 func (ev *msgEventer) ReadMsg() (Msg, error) { 282 msg, err := ev.MsgReadWriter.ReadMsg() 283 if err != nil { 284 return msg, err 285 } 286 ev.feed.Send(&PeerEvent{ 287 Type: PeerEventTypeMsgRecv, 288 Peer: ev.peerID, 289 Protocol: ev.Protocol, 290 MsgCode: &msg.Code, 291 MsgSize: &msg.Size, 292 }) 293 return msg, nil 294 } 295 296 //writemsg将消息写入基础msgreadwriter并发出 297 //“消息已发送”事件 298 func (ev *msgEventer) WriteMsg(msg Msg) error { 299 err := ev.MsgReadWriter.WriteMsg(msg) 300 if err != nil { 301 return err 302 } 303 ev.feed.Send(&PeerEvent{ 304 Type: PeerEventTypeMsgSend, 305 Peer: ev.peerID, 306 Protocol: ev.Protocol, 307 MsgCode: &msg.Code, 308 MsgSize: &msg.Size, 309 }) 310 return nil 311 } 312 313 //close如果实现IO.closer,则关闭基础msgreadwriter。 314 //界面 315 func (ev *msgEventer) Close() error { 316 if v, ok := ev.MsgReadWriter.(io.Closer); ok { 317 return v.Close() 318 } 319 return nil 320 }