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  }