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 }