github.com/shyftnetwork/go-empyrean@v1.8.3-0.20191127201940-fbfca9338f04/p2p/simulations/connect.go (about)

     1  // Copyright 2018 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package simulations
    18  
    19  import (
    20  	"errors"
    21  	"strings"
    22  
    23  	"github.com/ShyftNetwork/go-empyrean/p2p/enode"
    24  )
    25  
    26  var (
    27  	ErrNodeNotFound = errors.New("node not found")
    28  )
    29  
    30  // ConnectToLastNode connects the node with provided NodeID
    31  // to the last node that is up, and avoiding connection to self.
    32  // It is useful when constructing a chain network topology
    33  // when Network adds and removes nodes dynamically.
    34  func (net *Network) ConnectToLastNode(id enode.ID) (err error) {
    35  	ids := net.getUpNodeIDs()
    36  	l := len(ids)
    37  	if l < 2 {
    38  		return nil
    39  	}
    40  	last := ids[l-1]
    41  	if last == id {
    42  		last = ids[l-2]
    43  	}
    44  	return net.connect(last, id)
    45  }
    46  
    47  // ConnectToRandomNode connects the node with provided NodeID
    48  // to a random node that is up.
    49  func (net *Network) ConnectToRandomNode(id enode.ID) (err error) {
    50  	selected := net.GetRandomUpNode(id)
    51  	if selected == nil {
    52  		return ErrNodeNotFound
    53  	}
    54  	return net.connect(selected.ID(), id)
    55  }
    56  
    57  // ConnectNodesFull connects all nodes one to another.
    58  // It provides a complete connectivity in the network
    59  // which should be rarely needed.
    60  func (net *Network) ConnectNodesFull(ids []enode.ID) (err error) {
    61  	if ids == nil {
    62  		ids = net.getUpNodeIDs()
    63  	}
    64  	for i, lid := range ids {
    65  		for _, rid := range ids[i+1:] {
    66  			if err = net.connect(lid, rid); err != nil {
    67  				return err
    68  			}
    69  		}
    70  	}
    71  	return nil
    72  }
    73  
    74  // ConnectNodesChain connects all nodes in a chain topology.
    75  // If ids argument is nil, all nodes that are up will be connected.
    76  func (net *Network) ConnectNodesChain(ids []enode.ID) (err error) {
    77  	if ids == nil {
    78  		ids = net.getUpNodeIDs()
    79  	}
    80  	l := len(ids)
    81  	for i := 0; i < l-1; i++ {
    82  		if err := net.connect(ids[i], ids[i+1]); err != nil {
    83  			return err
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  // ConnectNodesRing connects all nodes in a ring topology.
    90  // If ids argument is nil, all nodes that are up will be connected.
    91  func (net *Network) ConnectNodesRing(ids []enode.ID) (err error) {
    92  	if ids == nil {
    93  		ids = net.getUpNodeIDs()
    94  	}
    95  	l := len(ids)
    96  	if l < 2 {
    97  		return nil
    98  	}
    99  	if err := net.ConnectNodesChain(ids); err != nil {
   100  		return err
   101  	}
   102  	return net.connect(ids[l-1], ids[0])
   103  }
   104  
   105  // ConnectNodesStar connects all nodes into a star topology
   106  // If ids argument is nil, all nodes that are up will be connected.
   107  func (net *Network) ConnectNodesStar(ids []enode.ID, center enode.ID) (err error) {
   108  	if ids == nil {
   109  		ids = net.getUpNodeIDs()
   110  	}
   111  	for _, id := range ids {
   112  		if center == id {
   113  			continue
   114  		}
   115  		if err := net.connect(center, id); err != nil {
   116  			return err
   117  		}
   118  	}
   119  	return nil
   120  }
   121  
   122  // connect connects two nodes but ignores already connected error.
   123  func (net *Network) connect(oneID, otherID enode.ID) error {
   124  	return ignoreAlreadyConnectedErr(net.Connect(oneID, otherID))
   125  }
   126  
   127  func ignoreAlreadyConnectedErr(err error) error {
   128  	if err == nil || strings.Contains(err.Error(), "already connected") {
   129  		return nil
   130  	}
   131  	return err
   132  }