github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/swarm/network/simulation/events.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  //版权所有2018 Go Ethereum作者
    10  //此文件是Go以太坊库的一部分。
    11  //
    12  //Go-Ethereum库是免费软件:您可以重新分发它和/或修改
    13  //根据GNU发布的较低通用公共许可证的条款
    14  //自由软件基金会,或者许可证的第3版,或者
    15  //(由您选择)任何更高版本。
    16  //
    17  //
    18  //
    19  //
    20  //
    21  //
    22  //
    23  //
    24  
    25  package simulation
    26  
    27  import (
    28  	"context"
    29  	"sync"
    30  
    31  	"github.com/ethereum/go-ethereum/p2p/discover"
    32  
    33  	"github.com/ethereum/go-ethereum/p2p"
    34  )
    35  
    36  //
    37  type PeerEvent struct {
    38  //
    39  	NodeID discover.NodeID
    40  //
    41  	Event *p2p.PeerEvent
    42  //
    43  	Error error
    44  }
    45  
    46  //
    47  //
    48  type PeerEventsFilter struct {
    49  	t        *p2p.PeerEventType
    50  	protocol *string
    51  	msgCode  *uint64
    52  }
    53  
    54  //
    55  func NewPeerEventsFilter() *PeerEventsFilter {
    56  	return &PeerEventsFilter{}
    57  }
    58  
    59  //
    60  func (f *PeerEventsFilter) Type(t p2p.PeerEventType) *PeerEventsFilter {
    61  	f.t = &t
    62  	return f
    63  }
    64  
    65  //
    66  func (f *PeerEventsFilter) Protocol(p string) *PeerEventsFilter {
    67  	f.protocol = &p
    68  	return f
    69  }
    70  
    71  //
    72  func (f *PeerEventsFilter) MsgCode(c uint64) *PeerEventsFilter {
    73  	f.msgCode = &c
    74  	return f
    75  }
    76  
    77  //
    78  //
    79  //
    80  func (s *Simulation) PeerEvents(ctx context.Context, ids []discover.NodeID, filters ...*PeerEventsFilter) <-chan PeerEvent {
    81  	eventC := make(chan PeerEvent)
    82  
    83  //
    84  //
    85  	var subsWG sync.WaitGroup
    86  	for _, id := range ids {
    87  		s.shutdownWG.Add(1)
    88  		subsWG.Add(1)
    89  		go func(id discover.NodeID) {
    90  			defer s.shutdownWG.Done()
    91  
    92  			client, err := s.Net.GetNode(id).Client()
    93  			if err != nil {
    94  				subsWG.Done()
    95  				eventC <- PeerEvent{NodeID: id, Error: err}
    96  				return
    97  			}
    98  			events := make(chan *p2p.PeerEvent)
    99  			sub, err := client.Subscribe(ctx, "admin", events, "peerEvents")
   100  			if err != nil {
   101  				subsWG.Done()
   102  				eventC <- PeerEvent{NodeID: id, Error: err}
   103  				return
   104  			}
   105  			defer sub.Unsubscribe()
   106  
   107  			subsWG.Done()
   108  
   109  			for {
   110  				select {
   111  				case <-ctx.Done():
   112  					if err := ctx.Err(); err != nil {
   113  						select {
   114  						case eventC <- PeerEvent{NodeID: id, Error: err}:
   115  						case <-s.Done():
   116  						}
   117  					}
   118  					return
   119  				case <-s.Done():
   120  					return
   121  				case e := <-events:
   122  match := len(filters) == 0 //
   123  					for _, f := range filters {
   124  						if f.t != nil && *f.t != e.Type {
   125  							continue
   126  						}
   127  						if f.protocol != nil && *f.protocol != e.Protocol {
   128  							continue
   129  						}
   130  						if f.msgCode != nil && e.MsgCode != nil && *f.msgCode != *e.MsgCode {
   131  							continue
   132  						}
   133  //
   134  						match = true
   135  						break
   136  					}
   137  					if match {
   138  						select {
   139  						case eventC <- PeerEvent{NodeID: id, Event: e}:
   140  						case <-ctx.Done():
   141  							if err := ctx.Err(); err != nil {
   142  								select {
   143  								case eventC <- PeerEvent{NodeID: id, Error: err}:
   144  								case <-s.Done():
   145  								}
   146  							}
   147  							return
   148  						case <-s.Done():
   149  							return
   150  						}
   151  					}
   152  				case err := <-sub.Err():
   153  					if err != nil {
   154  						select {
   155  						case eventC <- PeerEvent{NodeID: id, Error: err}:
   156  						case <-ctx.Done():
   157  							if err := ctx.Err(); err != nil {
   158  								select {
   159  								case eventC <- PeerEvent{NodeID: id, Error: err}:
   160  								case <-s.Done():
   161  								}
   162  							}
   163  							return
   164  						case <-s.Done():
   165  							return
   166  						}
   167  					}
   168  				}
   169  			}
   170  		}(id)
   171  	}
   172  
   173  //
   174  	subsWG.Wait()
   175  	return eventC
   176  }