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