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