github.com/klaytn/klaytn@v1.12.1/networks/p2p/simulations/network.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from p2p/simulations/network.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package simulations
    22  
    23  import (
    24  	"bytes"
    25  	"context"
    26  	"encoding/json"
    27  	"fmt"
    28  	"strings"
    29  	"sync"
    30  	"time"
    31  
    32  	"github.com/klaytn/klaytn/event"
    33  	"github.com/klaytn/klaytn/networks/p2p"
    34  	"github.com/klaytn/klaytn/networks/p2p/discover"
    35  	"github.com/klaytn/klaytn/networks/p2p/simulations/adapters"
    36  )
    37  
    38  var DialBanTimeout = 200 * time.Millisecond
    39  
    40  // NetworkConfig defines configuration options for starting a Network
    41  type NetworkConfig struct {
    42  	ID             string `json:"id"`
    43  	DefaultService string `json:"default_service,omitempty"`
    44  }
    45  
    46  // Network models a p2p simulation network which consists of a collection of
    47  // simulated nodes and the connections which exist between them.
    48  //
    49  // The Network has a single NodeAdapter which is responsible for actually
    50  // starting nodes and connecting them together.
    51  //
    52  // The Network emits events when nodes are started and stopped, when they are
    53  // connected and disconnected, and also when messages are sent between nodes.
    54  type Network struct {
    55  	NetworkConfig
    56  
    57  	Nodes   []*Node `json:"nodes"`
    58  	nodeMap map[discover.NodeID]int
    59  
    60  	Conns   []*Conn `json:"conns"`
    61  	connMap map[string]int
    62  
    63  	nodeAdapter adapters.NodeAdapter
    64  	events      event.Feed
    65  	lock        sync.RWMutex
    66  	quitc       chan struct{}
    67  }
    68  
    69  // NewNetwork returns a Network which uses the given NodeAdapter and NetworkConfig
    70  func NewNetwork(nodeAdapter adapters.NodeAdapter, conf *NetworkConfig) *Network {
    71  	return &Network{
    72  		NetworkConfig: *conf,
    73  		nodeAdapter:   nodeAdapter,
    74  		nodeMap:       make(map[discover.NodeID]int),
    75  		connMap:       make(map[string]int),
    76  		quitc:         make(chan struct{}),
    77  	}
    78  }
    79  
    80  // Events returns the output event feed of the Network.
    81  func (net *Network) Events() *event.Feed {
    82  	return &net.events
    83  }
    84  
    85  // NewNodeWithConfig adds a new node to the network with the given config,
    86  // returning an error if a node with the same ID or name already exists
    87  func (net *Network) NewNodeWithConfig(conf *adapters.NodeConfig) (*Node, error) {
    88  	net.lock.Lock()
    89  	defer net.lock.Unlock()
    90  
    91  	if conf.Reachable == nil {
    92  		conf.Reachable = func(otherID discover.NodeID) bool {
    93  			_, err := net.InitConn(conf.ID, otherID)
    94  			if err != nil && bytes.Compare(conf.ID.Bytes(), otherID.Bytes()) < 0 {
    95  				return false
    96  			}
    97  			return true
    98  		}
    99  	}
   100  
   101  	// check the node doesn't already exist
   102  	if node := net.getNode(conf.ID); node != nil {
   103  		return nil, fmt.Errorf("node with ID %q already exists", conf.ID)
   104  	}
   105  	if node := net.getNodeByName(conf.Name); node != nil {
   106  		return nil, fmt.Errorf("node with name %q already exists", conf.Name)
   107  	}
   108  
   109  	// if no services are configured, use the default service
   110  	if len(conf.Services) == 0 {
   111  		conf.Services = []string{net.DefaultService}
   112  	}
   113  
   114  	// use the NodeAdapter to create the node
   115  	cnNode, err := net.nodeAdapter.NewNode(conf)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  	node := &Node{
   120  		Node:   cnNode,
   121  		Config: conf,
   122  	}
   123  	logger.Trace(fmt.Sprintf("node %v created", conf.ID))
   124  	net.nodeMap[conf.ID] = len(net.Nodes)
   125  	net.Nodes = append(net.Nodes, node)
   126  
   127  	// emit a "control" event
   128  	net.events.Send(ControlEvent(node))
   129  
   130  	return node, nil
   131  }
   132  
   133  // Config returns the network configuration
   134  func (net *Network) Config() *NetworkConfig {
   135  	return &net.NetworkConfig
   136  }
   137  
   138  // StartAll starts all nodes in the network
   139  func (net *Network) StartAll() error {
   140  	for _, node := range net.Nodes {
   141  		if node.Up {
   142  			continue
   143  		}
   144  		if err := net.Start(node.ID()); err != nil {
   145  			return err
   146  		}
   147  	}
   148  	return nil
   149  }
   150  
   151  // StopAll stops all nodes in the network
   152  func (net *Network) StopAll() error {
   153  	for _, node := range net.Nodes {
   154  		if !node.Up {
   155  			continue
   156  		}
   157  		if err := net.Stop(node.ID()); err != nil {
   158  			return err
   159  		}
   160  	}
   161  	return nil
   162  }
   163  
   164  // Start starts the node with the given ID
   165  func (net *Network) Start(id discover.NodeID) error {
   166  	return net.startWithSnapshots(id, nil)
   167  }
   168  
   169  // startWithSnapshots starts the node with the given ID using the give
   170  // snapshots
   171  func (net *Network) startWithSnapshots(id discover.NodeID, snapshots map[string][]byte) error {
   172  	net.lock.Lock()
   173  	defer net.lock.Unlock()
   174  	node := net.getNode(id)
   175  	if node == nil {
   176  		return fmt.Errorf("node %v does not exist", id)
   177  	}
   178  	if node.Up {
   179  		return fmt.Errorf("node %v already up", id)
   180  	}
   181  	logger.Trace(fmt.Sprintf("starting node %v: %v using %v", id, node.Up, net.nodeAdapter.Name()))
   182  	if err := node.Start(snapshots); err != nil {
   183  		logger.Warn(fmt.Sprintf("start up failed: %v", err))
   184  		return err
   185  	}
   186  	node.Up = true
   187  	logger.Info(fmt.Sprintf("started node %v: %v", id, node.Up))
   188  
   189  	net.events.Send(NewEvent(node))
   190  
   191  	// subscribe to peer events
   192  	client, err := node.Client()
   193  	if err != nil {
   194  		return fmt.Errorf("error getting rpc client  for node %v: %s", id, err)
   195  	}
   196  	events := make(chan *p2p.PeerEvent)
   197  	sub, err := client.Subscribe(context.Background(), "admin", events, "peerEvents")
   198  	if err != nil {
   199  		return fmt.Errorf("error getting peer events for node %v: %s", id, err)
   200  	}
   201  	go net.watchPeerEvents(id, events, sub)
   202  	return nil
   203  }
   204  
   205  // watchPeerEvents reads peer events from the given channel and emits
   206  // corresponding network events
   207  func (net *Network) watchPeerEvents(id discover.NodeID, events chan *p2p.PeerEvent, sub event.Subscription) {
   208  	defer func() {
   209  		sub.Unsubscribe()
   210  
   211  		// assume the node is now down
   212  		net.lock.Lock()
   213  		defer net.lock.Unlock()
   214  		node := net.getNode(id)
   215  		if node == nil {
   216  			logger.Error("Can not find node for id", "id", id)
   217  			return
   218  		}
   219  		node.Up = false
   220  		net.events.Send(NewEvent(node))
   221  	}()
   222  	for {
   223  		select {
   224  		case event, ok := <-events:
   225  			if !ok {
   226  				return
   227  			}
   228  			peer := event.Peer
   229  			switch event.Type {
   230  
   231  			case p2p.PeerEventTypeAdd:
   232  				net.DidConnect(id, peer)
   233  
   234  			case p2p.PeerEventTypeDrop:
   235  				net.DidDisconnect(id, peer)
   236  
   237  			case p2p.PeerEventTypeMsgSend:
   238  				net.DidSend(id, peer, event.Protocol, *event.MsgCode)
   239  
   240  			case p2p.PeerEventTypeMsgRecv:
   241  				net.DidReceive(peer, id, event.Protocol, *event.MsgCode)
   242  
   243  			}
   244  
   245  		case err := <-sub.Err():
   246  			if err != nil {
   247  				logger.Error(fmt.Sprintf("error getting peer events for node %v", id), "err", err)
   248  			}
   249  			return
   250  		}
   251  	}
   252  }
   253  
   254  // Stop stops the node with the given ID
   255  func (net *Network) Stop(id discover.NodeID) error {
   256  	net.lock.Lock()
   257  	defer net.lock.Unlock()
   258  	node := net.getNode(id)
   259  	if node == nil {
   260  		return fmt.Errorf("node %v does not exist", id)
   261  	}
   262  	if !node.Up {
   263  		return fmt.Errorf("node %v already down", id)
   264  	}
   265  	if err := node.Stop(); err != nil {
   266  		return err
   267  	}
   268  	node.Up = false
   269  	logger.Info(fmt.Sprintf("stop node %v: %v", id, node.Up))
   270  
   271  	net.events.Send(ControlEvent(node))
   272  	return nil
   273  }
   274  
   275  // TODO
   276  // Connect connects two nodes together by calling the "admin_addPeer" RPC
   277  // method on the "one" node so that it connects to the "other" node
   278  func (net *Network) Connect(oneID, otherID discover.NodeID) error {
   279  	logger.Debug(fmt.Sprintf("connecting %s to %s", oneID, otherID))
   280  	conn, err := net.InitConnEx(oneID, otherID)
   281  	// TODO: temporary remove
   282  	if err != nil {
   283  		return err
   284  	}
   285  	client, err := conn.one.Client()
   286  	if err != nil {
   287  		return err
   288  	}
   289  	net.events.Send(ControlEvent(conn))
   290  	return client.Call(nil, "admin_addPeer", string(conn.other.Addr()))
   291  }
   292  
   293  //
   294  // method on the "one" node that it connect to all "other" nodes
   295  func (net *Network) ConnectAll() error {
   296  	logger.Debug(fmt.Sprintf("connecting all nodes to all other nodes"))
   297  
   298  	for _, oneNode := range net.Nodes {
   299  		oneID := oneNode.ID()
   300  
   301  		go func() {
   302  			for _, otherNode := range net.Nodes {
   303  				otherID := otherNode.ID()
   304  				if strings.Compare(oneID.String(), otherID.String()) == 0 {
   305  					continue
   306  				}
   307  
   308  				err := net.Connect(oneID, otherID)
   309  				if err != nil {
   310  					logger.Error(fmt.Sprintf("Error in ConnectAll() : %s", err))
   311  					continue
   312  				}
   313  			}
   314  		}()
   315  
   316  	}
   317  	return nil
   318  }
   319  
   320  func (net *Network) DisconnectAll() error {
   321  	logger.Debug(fmt.Sprintf("Disconnecting all nodes to all other nodes"))
   322  
   323  	for _, oneNode := range net.Nodes {
   324  		oneID := oneNode.ID()
   325  
   326  		// Move to the goroutine
   327  		for _, otherNode := range net.Nodes {
   328  			otherID := otherNode.ID()
   329  			if strings.Compare(oneID.String(), otherID.String()) == 0 {
   330  				continue
   331  			}
   332  
   333  			err := net.Disconnect(oneID, otherID)
   334  			if err != nil {
   335  				logger.Error(fmt.Sprintf("Error in DisconnectAll() : %s", err))
   336  				continue
   337  			}
   338  		}
   339  	}
   340  	return nil
   341  }
   342  
   343  // this function does not remove peer, just close the connection for target
   344  func (net *Network) DisconnectOnly(one, other discover.NodeID) error {
   345  	node := net.getNode(one)
   346  	if node == nil {
   347  		return fmt.Errorf("node %v does not exist", one)
   348  	}
   349  	node.Node.DisconnectPeer(other)
   350  	return nil
   351  }
   352  
   353  type ConnResult struct {
   354  	succMap map[discover.NodeID]bool
   355  	mux     sync.Mutex
   356  }
   357  
   358  func (cr *ConnResult) reset() {
   359  	cr.mux.Lock()
   360  	defer cr.mux.Unlock()
   361  
   362  	for k := range cr.succMap {
   363  		delete(cr.succMap, k)
   364  	}
   365  }
   366  
   367  func (cr *ConnResult) disconnect(oneID discover.NodeID) {
   368  	cr.mux.Lock()
   369  	defer cr.mux.Unlock()
   370  
   371  	delete(cr.succMap, oneID)
   372  }
   373  
   374  func (cr *ConnResult) outCnt() {
   375  	logger.Debug(fmt.Sprintf("ConnResult = %v", len(cr.succMap)))
   376  }
   377  
   378  func (cr *ConnResult) output() {
   379  	cr.outCnt()
   380  	for k, v := range cr.succMap {
   381  		logger.Debug(fmt.Sprintf("## key = %v, value = %v", k, v))
   382  	}
   383  }
   384  
   385  var tcResult = &ConnResult{
   386  	succMap: make(map[discover.NodeID]bool),
   387  }
   388  
   389  // temporary function
   390  func (net *Network) CheckAllConnectDone(oneID discover.NodeID) {
   391  	tcResult.mux.Lock()
   392  	defer tcResult.mux.Unlock()
   393  
   394  	node := net.getNode(oneID)
   395  	if node == nil {
   396  		logger.Debug(fmt.Sprintf("### CheckComplation - cannot find nodeID %v", oneID))
   397  		return
   398  	}
   399  	peerCnt := node.Node.GetPeerCount()
   400  	targetCnt := len(net.Nodes) - 1
   401  	logger.Debug(fmt.Sprintf("### PeerCount: %d, targetCnt: %d", peerCnt, targetCnt))
   402  
   403  	if peerCnt == targetCnt {
   404  		if _, ok := tcResult.succMap[oneID]; !ok {
   405  			tcResult.succMap[oneID] = true
   406  			logger.Debug(fmt.Sprintf("#### PEER Connection done: Peer Count = %d, %v", peerCnt, node.Node.NodeInfo()))
   407  		}
   408  		if len(net.Nodes) == len(tcResult.succMap) {
   409  			logger.Debug(fmt.Sprintf("###### net(%p)Peer connection test succeed #####", net))
   410  
   411  			tcResult.output()
   412  		}
   413  	}
   414  }
   415  
   416  // Disconnect disconnects two nodes by calling the "admin_removePeer" RPC
   417  // method on the "one" node so that it disconnects from the "other" node
   418  func (net *Network) Disconnect(oneID, otherID discover.NodeID) error {
   419  	conn := net.GetConn(oneID, otherID)
   420  	if conn == nil {
   421  		return fmt.Errorf("connection between %v and %v does not exist", oneID, otherID)
   422  	}
   423  	if !conn.Up {
   424  		return fmt.Errorf("%v and %v already disconnected", oneID, otherID)
   425  	}
   426  	client, err := conn.one.Client()
   427  	if err != nil {
   428  		return err
   429  	}
   430  	net.events.Send(ControlEvent(conn))
   431  	return client.Call(nil, "admin_removePeer", string(conn.other.Addr()))
   432  }
   433  
   434  // DidConnect tracks the fact that the "one" node connected to the "other" node
   435  func (net *Network) DidConnect(one, other discover.NodeID) error {
   436  	net.lock.Lock()
   437  	defer net.lock.Unlock()
   438  	conn, err := net.getOrCreateConn(one, other)
   439  	if err != nil {
   440  		return fmt.Errorf("connection between %v and %v does not exist", one, other)
   441  	}
   442  	//if conn.Up {
   443  	// return fmt.Errorf("%v and %v already connected", one, other)
   444  	//}
   445  	conn.Up = true
   446  	net.events.Send(NewEvent(conn))
   447  
   448  	// TODO : CHECK ALLCONNECTION DONE
   449  	net.CheckAllConnectDone(one)
   450  	return nil
   451  }
   452  
   453  // DidDisconnect tracks the fact that the "one" node disconnected from the
   454  // "other" node
   455  func (net *Network) DidDisconnect(one, other discover.NodeID) error {
   456  	net.lock.Lock()
   457  	defer net.lock.Unlock()
   458  	conn := net.getConn(one, other)
   459  	if conn == nil {
   460  		return fmt.Errorf("connection between %v and %v does not exist", one, other)
   461  	}
   462  
   463  	//if !conn.Up {
   464  	//	return fmt.Errorf("%v and %v already disconnected", one, other)
   465  	//}
   466  	conn.Up = false
   467  	conn.initiated = time.Now().Add(-DialBanTimeout)
   468  	net.events.Send(NewEvent(conn))
   469  
   470  	//
   471  	tcResult.outCnt()
   472  	tcResult.disconnect(one)
   473  	tcResult.outCnt()
   474  
   475  	return nil
   476  }
   477  
   478  // DidSend tracks the fact that "sender" sent a message to "receiver"
   479  func (net *Network) DidSend(sender, receiver discover.NodeID, proto string, code uint64) error {
   480  	msg := &Msg{
   481  		One:      sender,
   482  		Other:    receiver,
   483  		Protocol: proto,
   484  		Code:     code,
   485  		Received: false,
   486  	}
   487  	net.events.Send(NewEvent(msg))
   488  	return nil
   489  }
   490  
   491  // DidReceive tracks the fact that "receiver" received a message from "sender"
   492  func (net *Network) DidReceive(sender, receiver discover.NodeID, proto string, code uint64) error {
   493  	msg := &Msg{
   494  		One:      sender,
   495  		Other:    receiver,
   496  		Protocol: proto,
   497  		Code:     code,
   498  		Received: true,
   499  	}
   500  	net.events.Send(NewEvent(msg))
   501  	return nil
   502  }
   503  
   504  // GetNode gets the node with the given ID, returning nil if the node does not
   505  // exist
   506  func (net *Network) GetNode(id discover.NodeID) *Node {
   507  	net.lock.Lock()
   508  	defer net.lock.Unlock()
   509  	return net.getNode(id)
   510  }
   511  
   512  // GetNode gets the node with the given name, returning nil if the node does
   513  // not exist
   514  func (net *Network) GetNodeByName(name string) *Node {
   515  	net.lock.Lock()
   516  	defer net.lock.Unlock()
   517  	return net.getNodeByName(name)
   518  }
   519  
   520  // GetNodes returns the existing nodes
   521  func (net *Network) GetNodes() (nodes []*Node) {
   522  	net.lock.Lock()
   523  	defer net.lock.Unlock()
   524  
   525  	nodes = append(nodes, net.Nodes...)
   526  	return nodes
   527  }
   528  
   529  func (net *Network) getNode(id discover.NodeID) *Node {
   530  	i, found := net.nodeMap[id]
   531  	if !found {
   532  		return nil
   533  	}
   534  	return net.Nodes[i]
   535  }
   536  
   537  func (net *Network) getNodeByName(name string) *Node {
   538  	for _, node := range net.Nodes {
   539  		if node.Config.Name == name {
   540  			return node
   541  		}
   542  	}
   543  	return nil
   544  }
   545  
   546  // GetConn returns the connection which exists between "one" and "other"
   547  // regardless of which node initiated the connection
   548  func (net *Network) GetConn(oneID, otherID discover.NodeID) *Conn {
   549  	net.lock.Lock()
   550  	defer net.lock.Unlock()
   551  	return net.getConn(oneID, otherID)
   552  }
   553  
   554  // GetOrCreateConn is like GetConn but creates the connection if it doesn't
   555  // already exist
   556  func (net *Network) GetOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
   557  	net.lock.Lock()
   558  	defer net.lock.Unlock()
   559  	return net.getOrCreateConn(oneID, otherID)
   560  }
   561  
   562  func (net *Network) getOrCreateConn(oneID, otherID discover.NodeID) (*Conn, error) {
   563  	if conn := net.getConn(oneID, otherID); conn != nil {
   564  		return conn, nil
   565  	}
   566  
   567  	one := net.getNode(oneID)
   568  	if one == nil {
   569  		return nil, fmt.Errorf("node %v does not exist", oneID)
   570  	}
   571  	other := net.getNode(otherID)
   572  	if other == nil {
   573  		return nil, fmt.Errorf("node %v does not exist", otherID)
   574  	}
   575  	conn := &Conn{
   576  		One:   oneID,
   577  		Other: otherID,
   578  		one:   one,
   579  		other: other,
   580  	}
   581  	label := ConnLabel(oneID, otherID)
   582  	net.connMap[label] = len(net.Conns)
   583  	net.Conns = append(net.Conns, conn)
   584  	return conn, nil
   585  }
   586  
   587  func (net *Network) getConn(oneID, otherID discover.NodeID) *Conn {
   588  	label := ConnLabel(oneID, otherID)
   589  	i, found := net.connMap[label]
   590  	if !found {
   591  		return nil
   592  	}
   593  	return net.Conns[i]
   594  }
   595  
   596  // InitConn(one, other) retrieves the connectiton model for the connection between
   597  // peers one and other, or creates a new one if it does not exist
   598  // the order of nodes does not matter, i.e., Conn(i,j) == Conn(j, i)
   599  // it checks if the connection is already up, and if the nodes are running
   600  // NOTE:
   601  // it also checks whether there has been recent attempt to connect the peers
   602  // this is cheating as the simulation is used as an oracle and know about
   603  // remote peers attempt to connect to a node which will then not initiate the connection
   604  func (net *Network) InitConn(oneID, otherID discover.NodeID) (*Conn, error) {
   605  	net.lock.Lock()
   606  	defer net.lock.Unlock()
   607  	if oneID == otherID {
   608  		return nil, fmt.Errorf("refusing to connect to self %v", oneID)
   609  	}
   610  	conn, err := net.getOrCreateConn(oneID, otherID)
   611  	if err != nil {
   612  		return nil, err
   613  	}
   614  	if conn.Up {
   615  		return nil, fmt.Errorf("%v and %v already connected", oneID, otherID)
   616  	}
   617  	if time.Since(conn.initiated) < DialBanTimeout {
   618  		return nil, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
   619  	}
   620  
   621  	err = conn.nodesUp()
   622  	if err != nil {
   623  		logger.Trace(fmt.Sprintf("nodes not up: %v", err))
   624  		return nil, fmt.Errorf("nodes not up: %v", err)
   625  	}
   626  	logger.Debug("InitConn - connection initiated")
   627  	conn.initiated = time.Now()
   628  	return conn, nil
   629  }
   630  
   631  // TODO
   632  // this function made for the testing
   633  func (net *Network) InitConnEx(oneID, otherID discover.NodeID) (*Conn, error) {
   634  	net.lock.Lock()
   635  	defer net.lock.Unlock()
   636  	if oneID == otherID {
   637  		return nil, fmt.Errorf("refusing to connect to self %v", oneID)
   638  	}
   639  	conn, err := net.getOrCreateConn(oneID, otherID)
   640  	if conn == nil {
   641  		return nil, err
   642  	}
   643  	//if conn.Up {
   644  	// return conn, fmt.Errorf("%v and %v already connected", oneID, otherID)
   645  	//}
   646  	//if time.Since(conn.initiated) < DialBanTimeout {
   647  	// return conn, fmt.Errorf("connection between %v and %v recently attempted", oneID, otherID)
   648  	//}
   649  
   650  	err = conn.nodesUp()
   651  	if err != nil {
   652  		logger.Trace(fmt.Sprintf("nodes not up: %v", err))
   653  		return nil, fmt.Errorf("nodes not up: %v", err)
   654  	}
   655  	logger.Debug("InitConn - connection initiated")
   656  	conn.initiated = time.Now()
   657  	return conn, nil
   658  }
   659  
   660  // Shutdown stops all nodes in the network and closes the quit channel
   661  func (net *Network) Shutdown() {
   662  	for _, node := range net.Nodes {
   663  		logger.Debug(fmt.Sprintf("stopping node %s", node.ID().TerminalString()))
   664  		if err := node.Stop(); err != nil {
   665  			logger.Warn(fmt.Sprintf("error stopping node %s", node.ID().TerminalString()), "err", err)
   666  		}
   667  	}
   668  	close(net.quitc)
   669  }
   670  
   671  // Reset resets all network properties:
   672  // emtpies the nodes and the connection list
   673  func (net *Network) Reset() {
   674  	net.lock.Lock()
   675  	defer net.lock.Unlock()
   676  
   677  	// re-initialize the maps
   678  	net.connMap = make(map[string]int)
   679  	net.nodeMap = make(map[discover.NodeID]int)
   680  
   681  	net.Nodes = nil
   682  	net.Conns = nil
   683  }
   684  
   685  // Node is a wrapper around adapters.Node which is used to track the status
   686  // of a node in the network
   687  type Node struct {
   688  	adapters.Node `json:"-"`
   689  
   690  	// Config if the config used to created the node
   691  	Config *adapters.NodeConfig `json:"config"`
   692  
   693  	// Up tracks whether or not the node is running
   694  	Up bool `json:"up"`
   695  }
   696  
   697  // ID returns the ID of the node
   698  func (n *Node) ID() discover.NodeID {
   699  	return n.Config.ID
   700  }
   701  
   702  // String returns a log-friendly string
   703  func (n *Node) String() string {
   704  	return fmt.Sprintf("Node %v", n.ID().TerminalString())
   705  }
   706  
   707  // NodeInfo returns information about the node
   708  func (n *Node) NodeInfo() *p2p.NodeInfo {
   709  	// avoid a panic if the node is not started yet
   710  	if n.Node == nil {
   711  		return nil
   712  	}
   713  	info := n.Node.NodeInfo()
   714  	info.Name = n.Config.Name
   715  	return info
   716  }
   717  
   718  // MarshalJSON implements the json.Marshaler interface so that the encoded
   719  // JSON includes the NodeInfo
   720  func (n *Node) MarshalJSON() ([]byte, error) {
   721  	return json.Marshal(struct {
   722  		Info   *p2p.NodeInfo        `json:"info,omitempty"`
   723  		Config *adapters.NodeConfig `json:"config,omitempty"`
   724  		Up     bool                 `json:"up"`
   725  	}{
   726  		Info:   n.NodeInfo(),
   727  		Config: n.Config,
   728  		Up:     n.Up,
   729  	})
   730  }
   731  
   732  // Conn represents a connection between two nodes in the network
   733  type Conn struct {
   734  	// One is the node which initiated the connection
   735  	One discover.NodeID `json:"one"`
   736  
   737  	// Other is the node which the connection was made to
   738  	Other discover.NodeID `json:"other"`
   739  
   740  	// Up tracks whether or not the connection is active
   741  	Up bool `json:"up"`
   742  	// Registers when the connection was grabbed to dial
   743  	initiated time.Time
   744  
   745  	one   *Node
   746  	other *Node
   747  }
   748  
   749  // nodesUp returns whether both nodes are currently up
   750  func (c *Conn) nodesUp() error {
   751  	if !c.one.Up {
   752  		return fmt.Errorf("one %v is not up", c.One)
   753  	}
   754  	if !c.other.Up {
   755  		return fmt.Errorf("other %v is not up", c.Other)
   756  	}
   757  	return nil
   758  }
   759  
   760  // String returns a log-friendly string
   761  func (c *Conn) String() string {
   762  	return fmt.Sprintf("Conn %v->%v", c.One.TerminalString(), c.Other.TerminalString())
   763  }
   764  
   765  // Msg represents a p2p message sent between two nodes in the network
   766  type Msg struct {
   767  	One      discover.NodeID `json:"one"`
   768  	Other    discover.NodeID `json:"other"`
   769  	Protocol string          `json:"protocol"`
   770  	Code     uint64          `json:"code"`
   771  	Received bool            `json:"received"`
   772  }
   773  
   774  // String returns a log-friendly string
   775  func (m *Msg) String() string {
   776  	return fmt.Sprintf("Msg(%d) %v->%v", m.Code, m.One.TerminalString(), m.Other.TerminalString())
   777  }
   778  
   779  // ConnLabel generates a deterministic string which represents a connection
   780  // between two nodes, used to compare if two connections are between the same
   781  // nodes
   782  func ConnLabel(source, target discover.NodeID) string {
   783  	var first, second discover.NodeID
   784  	if bytes.Compare(source.Bytes(), target.Bytes()) > 0 {
   785  		first = target
   786  		second = source
   787  	} else {
   788  		first = source
   789  		second = target
   790  	}
   791  	return fmt.Sprintf("%v-%v", first, second)
   792  }
   793  
   794  // Snapshot represents the state of a network at a single point in time and can
   795  // be used to restore the state of a network
   796  type Snapshot struct {
   797  	Nodes []NodeSnapshot `json:"nodes,omitempty"`
   798  	Conns []Conn         `json:"conns,omitempty"`
   799  }
   800  
   801  // NodeSnapshot represents the state of a node in the network
   802  type NodeSnapshot struct {
   803  	Node Node `json:"node,omitempty"`
   804  
   805  	// Snapshots is arbitrary data gathered from calling node.Snapshots()
   806  	Snapshots map[string][]byte `json:"snapshots,omitempty"`
   807  }
   808  
   809  // Snapshot creates a network snapshot
   810  func (net *Network) Snapshot() (*Snapshot, error) {
   811  	net.lock.Lock()
   812  	defer net.lock.Unlock()
   813  	snap := &Snapshot{
   814  		Nodes: make([]NodeSnapshot, len(net.Nodes)),
   815  		Conns: make([]Conn, len(net.Conns)),
   816  	}
   817  	for i, node := range net.Nodes {
   818  		snap.Nodes[i] = NodeSnapshot{Node: *node}
   819  		if !node.Up {
   820  			continue
   821  		}
   822  		snapshots, err := node.Snapshots()
   823  		if err != nil {
   824  			return nil, err
   825  		}
   826  		snap.Nodes[i].Snapshots = snapshots
   827  	}
   828  	for i, conn := range net.Conns {
   829  		snap.Conns[i] = *conn
   830  	}
   831  	return snap, nil
   832  }
   833  
   834  // Load loads a network snapshot
   835  func (net *Network) Load(snap *Snapshot) error {
   836  	for _, n := range snap.Nodes {
   837  		if _, err := net.NewNodeWithConfig(n.Node.Config); err != nil {
   838  			return err
   839  		}
   840  		if !n.Node.Up {
   841  			continue
   842  		}
   843  		if err := net.startWithSnapshots(n.Node.Config.ID, n.Snapshots); err != nil {
   844  			return err
   845  		}
   846  	}
   847  	for _, conn := range snap.Conns {
   848  
   849  		if !net.GetNode(conn.One).Up || !net.GetNode(conn.Other).Up {
   850  			// in this case, at least one of the nodes of a connection is not up,
   851  			// so it would result in the snapshot `Load` to fail
   852  			continue
   853  		}
   854  		if err := net.Connect(conn.One, conn.Other); err != nil {
   855  			return err
   856  		}
   857  	}
   858  	return nil
   859  }
   860  
   861  // Subscribe reads control events from a channel and executes them
   862  func (net *Network) Subscribe(events chan *Event) {
   863  	for {
   864  		select {
   865  		case event, ok := <-events:
   866  			if !ok {
   867  				return
   868  			}
   869  			if event.Control {
   870  				net.executeControlEvent(event)
   871  			}
   872  		case <-net.quitc:
   873  			return
   874  		}
   875  	}
   876  }
   877  
   878  func (net *Network) executeControlEvent(event *Event) {
   879  	logger.Trace("execute control event", "type", event.Type, "event", event)
   880  	switch event.Type {
   881  	case EventTypeNode:
   882  		if err := net.executeNodeEvent(event); err != nil {
   883  			logger.Error("error executing node event", "event", event, "err", err)
   884  		}
   885  	case EventTypeConn:
   886  		if err := net.executeConnEvent(event); err != nil {
   887  			logger.Error("error executing conn event", "event", event, "err", err)
   888  		}
   889  	case EventTypeMsg:
   890  		logger.Warn("ignoring control msg event")
   891  	}
   892  }
   893  
   894  func (net *Network) executeNodeEvent(e *Event) error {
   895  	if !e.Node.Up {
   896  		return net.Stop(e.Node.ID())
   897  	}
   898  
   899  	if _, err := net.NewNodeWithConfig(e.Node.Config); err != nil {
   900  		return err
   901  	}
   902  	return net.Start(e.Node.ID())
   903  }
   904  
   905  func (net *Network) executeConnEvent(e *Event) error {
   906  	if e.Conn.Up {
   907  		return net.Connect(e.Conn.One, e.Conn.Other)
   908  	} else {
   909  		return net.Disconnect(e.Conn.One, e.Conn.Other)
   910  	}
   911  }