github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/swarm/network/simulation/events.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  //</624450114257162240>
    11  
    12  
    13  package simulation
    14  
    15  import (
    16  	"context"
    17  	"sync"
    18  
    19  	"github.com/ethereum/go-ethereum/p2p/enode"
    20  	"github.com/ethereum/go-ethereum/p2p/simulations"
    21  )
    22  
    23  //PeerEvent是Simulation.PeerEvents返回的通道类型。
    24  type PeerEvent struct {
    25  //node id是捕获事件的节点的ID。
    26  	NodeID enode.ID
    27  //PeerID是捕获事件的对等节点的ID。
    28  	PeerID enode.ID
    29  //事件是捕获的事件。
    30  	Event *simulations.Event
    31  //错误是事件监视期间可能发生的错误。
    32  	Error error
    33  }
    34  
    35  //PeerEventsFilter定义一个对PeerEvents的筛选器,以排除具有
    36  //定义的属性。使用PeerEventsFilter方法设置所需选项。
    37  type PeerEventsFilter struct {
    38  	eventType simulations.EventType
    39  
    40  	connUp *bool
    41  
    42  	msgReceive *bool
    43  	protocol   *string
    44  	msgCode    *uint64
    45  }
    46  
    47  //NewPeerEventsFilter返回新的PeerEventsFilter实例。
    48  func NewPeerEventsFilter() *PeerEventsFilter {
    49  	return &PeerEventsFilter{}
    50  }
    51  
    52  //连接将筛选器设置为两个节点连接时的事件。
    53  func (f *PeerEventsFilter) Connect() *PeerEventsFilter {
    54  	f.eventType = simulations.EventTypeConn
    55  	b := true
    56  	f.connUp = &b
    57  	return f
    58  }
    59  
    60  //DROP将筛选器设置为两个节点断开连接时的事件。
    61  func (f *PeerEventsFilter) Drop() *PeerEventsFilter {
    62  	f.eventType = simulations.EventTypeConn
    63  	b := false
    64  	f.connUp = &b
    65  	return f
    66  }
    67  
    68  //ReceivedMessages将筛选器设置为仅接收的消息。
    69  func (f *PeerEventsFilter) ReceivedMessages() *PeerEventsFilter {
    70  	f.eventType = simulations.EventTypeMsg
    71  	b := true
    72  	f.msgReceive = &b
    73  	return f
    74  }
    75  
    76  //sent messages将筛选器设置为只发送消息。
    77  func (f *PeerEventsFilter) SentMessages() *PeerEventsFilter {
    78  	f.eventType = simulations.EventTypeMsg
    79  	b := false
    80  	f.msgReceive = &b
    81  	return f
    82  }
    83  
    84  //协议将筛选器设置为仅一个消息协议。
    85  func (f *PeerEventsFilter) Protocol(p string) *PeerEventsFilter {
    86  	f.eventType = simulations.EventTypeMsg
    87  	f.protocol = &p
    88  	return f
    89  }
    90  
    91  //msg code将筛选器设置为仅一个msg代码。
    92  func (f *PeerEventsFilter) MsgCode(c uint64) *PeerEventsFilter {
    93  	f.eventType = simulations.EventTypeMsg
    94  	f.msgCode = &c
    95  	return f
    96  }
    97  
    98  //PeerEvents返回由管理PeerEvents捕获的事件通道
    99  //具有提供的nodeid的订阅节点。可以将其他筛选器设置为忽略
   100  //不相关的事件。
   101  func (s *Simulation) PeerEvents(ctx context.Context, ids []enode.ID, filters ...*PeerEventsFilter) <-chan PeerEvent {
   102  	eventC := make(chan PeerEvent)
   103  
   104  //等待组以确保已建立对管理对等事件的所有订阅
   105  //在此函数返回之前。
   106  	var subsWG sync.WaitGroup
   107  	for _, id := range ids {
   108  		s.shutdownWG.Add(1)
   109  		subsWG.Add(1)
   110  		go func(id enode.ID) {
   111  			defer s.shutdownWG.Done()
   112  
   113  			events := make(chan *simulations.Event)
   114  			sub := s.Net.Events().Subscribe(events)
   115  			defer sub.Unsubscribe()
   116  
   117  			subsWG.Done()
   118  
   119  			for {
   120  				select {
   121  				case <-ctx.Done():
   122  					if err := ctx.Err(); err != nil {
   123  						select {
   124  						case eventC <- PeerEvent{NodeID: id, Error: err}:
   125  						case <-s.Done():
   126  						}
   127  					}
   128  					return
   129  				case <-s.Done():
   130  					return
   131  				case e := <-events:
   132  //忽略控制事件
   133  					if e.Control {
   134  						continue
   135  					}
   136  match := len(filters) == 0 //如果没有匹配所有事件的筛选器
   137  					for _, f := range filters {
   138  						if f.eventType == simulations.EventTypeConn && e.Conn != nil {
   139  							if *f.connUp != e.Conn.Up {
   140  								continue
   141  							}
   142  //所有连接过滤器参数匹配,中断循环
   143  							match = true
   144  							break
   145  						}
   146  						if f.eventType == simulations.EventTypeMsg && e.Msg != nil {
   147  							if f.msgReceive != nil && *f.msgReceive != e.Msg.Received {
   148  								continue
   149  							}
   150  							if f.protocol != nil && *f.protocol != e.Msg.Protocol {
   151  								continue
   152  							}
   153  							if f.msgCode != nil && *f.msgCode != e.Msg.Code {
   154  								continue
   155  							}
   156  //所有消息过滤器参数匹配,中断循环
   157  							match = true
   158  							break
   159  						}
   160  					}
   161  					var peerID enode.ID
   162  					switch e.Type {
   163  					case simulations.EventTypeConn:
   164  						peerID = e.Conn.One
   165  						if peerID == id {
   166  							peerID = e.Conn.Other
   167  						}
   168  					case simulations.EventTypeMsg:
   169  						peerID = e.Msg.One
   170  						if peerID == id {
   171  							peerID = e.Msg.Other
   172  						}
   173  					}
   174  					if match {
   175  						select {
   176  						case eventC <- PeerEvent{NodeID: id, PeerID: peerID, Event: e}:
   177  						case <-ctx.Done():
   178  							if err := ctx.Err(); err != nil {
   179  								select {
   180  								case eventC <- PeerEvent{NodeID: id, PeerID: peerID, Error: err}:
   181  								case <-s.Done():
   182  								}
   183  							}
   184  							return
   185  						case <-s.Done():
   186  							return
   187  						}
   188  					}
   189  				case err := <-sub.Err():
   190  					if err != nil {
   191  						select {
   192  						case eventC <- PeerEvent{NodeID: id, Error: err}:
   193  						case <-ctx.Done():
   194  							if err := ctx.Err(); err != nil {
   195  								select {
   196  								case eventC <- PeerEvent{NodeID: id, Error: err}:
   197  								case <-s.Done():
   198  								}
   199  							}
   200  							return
   201  						case <-s.Done():
   202  							return
   203  						}
   204  					}
   205  				}
   206  			}
   207  		}(id)
   208  	}
   209  
   210  //等待所有订阅
   211  	subsWG.Wait()
   212  	return eventC
   213  }
   214