github.com/oskarth/go-ethereum@v1.6.8-0.20191013093314-dac24a9d3494/swarm/network/simulation/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 simulation
    18  
    19  import (
    20  	"strings"
    21  
    22  	"github.com/ethereum/go-ethereum/p2p/enode"
    23  )
    24  
    25  // ConnectToPivotNode connects the node with provided NodeID
    26  // to the pivot node, already set by Simulation.SetPivotNode method.
    27  // It is useful when constructing a star network topology
    28  // when simulation adds and removes nodes dynamically.
    29  func (s *Simulation) ConnectToPivotNode(id enode.ID) (err error) {
    30  	pid := s.PivotNodeID()
    31  	if pid == nil {
    32  		return ErrNoPivotNode
    33  	}
    34  	return s.connect(*pid, id)
    35  }
    36  
    37  // ConnectToLastNode connects the node with provided NodeID
    38  // to the last node that is up, and avoiding connection to self.
    39  // It is useful when constructing a chain network topology
    40  // when simulation adds and removes nodes dynamically.
    41  func (s *Simulation) ConnectToLastNode(id enode.ID) (err error) {
    42  	ids := s.UpNodeIDs()
    43  	l := len(ids)
    44  	if l < 2 {
    45  		return nil
    46  	}
    47  	lid := ids[l-1]
    48  	if lid == id {
    49  		lid = ids[l-2]
    50  	}
    51  	return s.connect(lid, id)
    52  }
    53  
    54  // ConnectToRandomNode connects the node with provieded NodeID
    55  // to a random node that is up.
    56  func (s *Simulation) ConnectToRandomNode(id enode.ID) (err error) {
    57  	n := s.RandomUpNode(id)
    58  	if n == nil {
    59  		return ErrNodeNotFound
    60  	}
    61  	return s.connect(n.ID, id)
    62  }
    63  
    64  // ConnectNodesFull connects all nodes one to another.
    65  // It provides a complete connectivity in the network
    66  // which should be rarely needed.
    67  func (s *Simulation) ConnectNodesFull(ids []enode.ID) (err error) {
    68  	if ids == nil {
    69  		ids = s.UpNodeIDs()
    70  	}
    71  	l := len(ids)
    72  	for i := 0; i < l; i++ {
    73  		for j := i + 1; j < l; j++ {
    74  			err = s.connect(ids[i], ids[j])
    75  			if err != nil {
    76  				return err
    77  			}
    78  		}
    79  	}
    80  	return nil
    81  }
    82  
    83  // ConnectNodesChain connects all nodes in a chain topology.
    84  // If ids argument is nil, all nodes that are up will be connected.
    85  func (s *Simulation) ConnectNodesChain(ids []enode.ID) (err error) {
    86  	if ids == nil {
    87  		ids = s.UpNodeIDs()
    88  	}
    89  	l := len(ids)
    90  	for i := 0; i < l-1; i++ {
    91  		err = s.connect(ids[i], ids[i+1])
    92  		if err != nil {
    93  			return err
    94  		}
    95  	}
    96  	return nil
    97  }
    98  
    99  // ConnectNodesRing connects all nodes in a ring topology.
   100  // If ids argument is nil, all nodes that are up will be connected.
   101  func (s *Simulation) ConnectNodesRing(ids []enode.ID) (err error) {
   102  	if ids == nil {
   103  		ids = s.UpNodeIDs()
   104  	}
   105  	l := len(ids)
   106  	if l < 2 {
   107  		return nil
   108  	}
   109  	for i := 0; i < l-1; i++ {
   110  		err = s.connect(ids[i], ids[i+1])
   111  		if err != nil {
   112  			return err
   113  		}
   114  	}
   115  	return s.connect(ids[l-1], ids[0])
   116  }
   117  
   118  // ConnectNodesStar connects all nodes in a star topology
   119  // with the center at provided NodeID.
   120  // If ids argument is nil, all nodes that are up will be connected.
   121  func (s *Simulation) ConnectNodesStar(id enode.ID, ids []enode.ID) (err error) {
   122  	if ids == nil {
   123  		ids = s.UpNodeIDs()
   124  	}
   125  	l := len(ids)
   126  	for i := 0; i < l; i++ {
   127  		if id == ids[i] {
   128  			continue
   129  		}
   130  		err = s.connect(id, ids[i])
   131  		if err != nil {
   132  			return err
   133  		}
   134  	}
   135  	return nil
   136  }
   137  
   138  // ConnectNodesStarPivot connects all nodes in a star topology
   139  // with the center at already set pivot node.
   140  // If ids argument is nil, all nodes that are up will be connected.
   141  func (s *Simulation) ConnectNodesStarPivot(ids []enode.ID) (err error) {
   142  	id := s.PivotNodeID()
   143  	if id == nil {
   144  		return ErrNoPivotNode
   145  	}
   146  	return s.ConnectNodesStar(*id, ids)
   147  }
   148  
   149  // connect connects two nodes but ignores already connected error.
   150  func (s *Simulation) connect(oneID, otherID enode.ID) error {
   151  	return ignoreAlreadyConnectedErr(s.Net.Connect(oneID, otherID))
   152  }
   153  
   154  func ignoreAlreadyConnectedErr(err error) error {
   155  	if err == nil || strings.Contains(err.Error(), "already connected") {
   156  		return nil
   157  	}
   158  	return err
   159  }