You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
6.7 KiB

p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: implement new Transport interface (#5791) This implements a new `Transport` interface and related types for the P2P refactor in #5670. Previously, `conn.MConnection` was very tightly coupled to the `Peer` implementation -- in order to allow alternative non-multiplexed transports (e.g. QUIC), MConnection has now been moved below the `Transport` interface, as `MConnTransport`, and decoupled from the peer. Since the `p2p` package is not covered by our Go API stability, this is not considered a breaking change, and not listed in the changelog. The initial approach was to implement the new interface in its final form (which also involved possible protocol changes, see https://github.com/tendermint/spec/pull/227). However, it turned out that this would require a large amount of changes to existing P2P code because of the previous tight coupling between `Peer` and `MConnection` and the reliance on subtleties in the MConnection behavior. Instead, I have broadened the `Transport` interface to expose much of the existing MConnection interface, preserved much of the existing MConnection logic and behavior in the transport implementation, and tried to make as few changes to the rest of the P2P stack as possible. We will instead reduce this interface gradually as we refactor other parts of the P2P stack. The low-level transport code and protocol (e.g. MConnection, SecretConnection and so on) has not been significantly changed, and refactoring this is not a priority until we come up with a plan for QUIC adoption, as we may end up discarding the MConnection code entirely. There are no tests of the new `MConnTransport`, as this code is likely to evolve as we proceed with the P2P refactor, but tests should be added before a final release. The E2E tests are sufficient for basic validation in the meanwhile.
4 years ago
p2p: file descriptor leaks (#3150) * close peer's connection to avoid fd leak Fixes #2967 * rename peer#Addr to RemoteAddr * fix test * fixes after Ethan's review * bring back the check * changelog entry * write a test for switch#acceptRoutine * increase timeouts? :( * remove extra assertNPeersWithTimeout * simplify test * assert number of peers (just to be safe) * Cleanup in OnStop * run tests with verbose flag on CircleCI * spawn a reading routine to prevent connection from closing * get port from the listener random port is faster, but often results in ``` panic: listen tcp 127.0.0.1:44068: bind: address already in use [recovered] panic: listen tcp 127.0.0.1:44068: bind: address already in use goroutine 79 [running]: testing.tRunner.func1(0xc0001bd600) /usr/local/go/src/testing/testing.go:792 +0x387 panic(0x974d20, 0xc0001b0500) /usr/local/go/src/runtime/panic.go:513 +0x1b9 github.com/tendermint/tendermint/p2p.MakeSwitch(0xc0000f42a0, 0x0, 0x9fb9cc, 0x9, 0x9fc346, 0xb, 0xb42128, 0x0, 0x0, 0x0, ...) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:182 +0xa28 github.com/tendermint/tendermint/p2p.MakeConnectedSwitches(0xc0000f42a0, 0x2, 0xb42128, 0xb41eb8, 0x4f1205, 0xc0001bed80, 0x4f16ed) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:75 +0xf9 github.com/tendermint/tendermint/p2p.MakeSwitchPair(0xbb8d20, 0xc0001bd600, 0xb42128, 0x2f7, 0x4f16c0) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:94 +0x4c github.com/tendermint/tendermint/p2p.TestSwitches(0xc0001bd600) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:117 +0x58 testing.tRunner(0xc0001bd600, 0xb42038) /usr/local/go/src/testing/testing.go:827 +0xbf created by testing.(*T).Run /usr/local/go/src/testing/testing.go:878 +0x353 exit status 2 FAIL github.com/tendermint/tendermint/p2p 0.350s ```
6 years ago
p2p: file descriptor leaks (#3150) * close peer's connection to avoid fd leak Fixes #2967 * rename peer#Addr to RemoteAddr * fix test * fixes after Ethan's review * bring back the check * changelog entry * write a test for switch#acceptRoutine * increase timeouts? :( * remove extra assertNPeersWithTimeout * simplify test * assert number of peers (just to be safe) * Cleanup in OnStop * run tests with verbose flag on CircleCI * spawn a reading routine to prevent connection from closing * get port from the listener random port is faster, but often results in ``` panic: listen tcp 127.0.0.1:44068: bind: address already in use [recovered] panic: listen tcp 127.0.0.1:44068: bind: address already in use goroutine 79 [running]: testing.tRunner.func1(0xc0001bd600) /usr/local/go/src/testing/testing.go:792 +0x387 panic(0x974d20, 0xc0001b0500) /usr/local/go/src/runtime/panic.go:513 +0x1b9 github.com/tendermint/tendermint/p2p.MakeSwitch(0xc0000f42a0, 0x0, 0x9fb9cc, 0x9, 0x9fc346, 0xb, 0xb42128, 0x0, 0x0, 0x0, ...) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:182 +0xa28 github.com/tendermint/tendermint/p2p.MakeConnectedSwitches(0xc0000f42a0, 0x2, 0xb42128, 0xb41eb8, 0x4f1205, 0xc0001bed80, 0x4f16ed) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:75 +0xf9 github.com/tendermint/tendermint/p2p.MakeSwitchPair(0xbb8d20, 0xc0001bd600, 0xb42128, 0x2f7, 0x4f16c0) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:94 +0x4c github.com/tendermint/tendermint/p2p.TestSwitches(0xc0001bd600) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:117 +0x58 testing.tRunner(0xc0001bd600, 0xb42038) /usr/local/go/src/testing/testing.go:827 +0xbf created by testing.(*T).Run /usr/local/go/src/testing/testing.go:878 +0x353 exit status 2 FAIL github.com/tendermint/tendermint/p2p 0.350s ```
6 years ago
p2p: file descriptor leaks (#3150) * close peer's connection to avoid fd leak Fixes #2967 * rename peer#Addr to RemoteAddr * fix test * fixes after Ethan's review * bring back the check * changelog entry * write a test for switch#acceptRoutine * increase timeouts? :( * remove extra assertNPeersWithTimeout * simplify test * assert number of peers (just to be safe) * Cleanup in OnStop * run tests with verbose flag on CircleCI * spawn a reading routine to prevent connection from closing * get port from the listener random port is faster, but often results in ``` panic: listen tcp 127.0.0.1:44068: bind: address already in use [recovered] panic: listen tcp 127.0.0.1:44068: bind: address already in use goroutine 79 [running]: testing.tRunner.func1(0xc0001bd600) /usr/local/go/src/testing/testing.go:792 +0x387 panic(0x974d20, 0xc0001b0500) /usr/local/go/src/runtime/panic.go:513 +0x1b9 github.com/tendermint/tendermint/p2p.MakeSwitch(0xc0000f42a0, 0x0, 0x9fb9cc, 0x9, 0x9fc346, 0xb, 0xb42128, 0x0, 0x0, 0x0, ...) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:182 +0xa28 github.com/tendermint/tendermint/p2p.MakeConnectedSwitches(0xc0000f42a0, 0x2, 0xb42128, 0xb41eb8, 0x4f1205, 0xc0001bed80, 0x4f16ed) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:75 +0xf9 github.com/tendermint/tendermint/p2p.MakeSwitchPair(0xbb8d20, 0xc0001bd600, 0xb42128, 0x2f7, 0x4f16c0) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:94 +0x4c github.com/tendermint/tendermint/p2p.TestSwitches(0xc0001bd600) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:117 +0x58 testing.tRunner(0xc0001bd600, 0xb42038) /usr/local/go/src/testing/testing.go:827 +0xbf created by testing.(*T).Run /usr/local/go/src/testing/testing.go:878 +0x353 exit status 2 FAIL github.com/tendermint/tendermint/p2p 0.350s ```
6 years ago
p2p: file descriptor leaks (#3150) * close peer's connection to avoid fd leak Fixes #2967 * rename peer#Addr to RemoteAddr * fix test * fixes after Ethan's review * bring back the check * changelog entry * write a test for switch#acceptRoutine * increase timeouts? :( * remove extra assertNPeersWithTimeout * simplify test * assert number of peers (just to be safe) * Cleanup in OnStop * run tests with verbose flag on CircleCI * spawn a reading routine to prevent connection from closing * get port from the listener random port is faster, but often results in ``` panic: listen tcp 127.0.0.1:44068: bind: address already in use [recovered] panic: listen tcp 127.0.0.1:44068: bind: address already in use goroutine 79 [running]: testing.tRunner.func1(0xc0001bd600) /usr/local/go/src/testing/testing.go:792 +0x387 panic(0x974d20, 0xc0001b0500) /usr/local/go/src/runtime/panic.go:513 +0x1b9 github.com/tendermint/tendermint/p2p.MakeSwitch(0xc0000f42a0, 0x0, 0x9fb9cc, 0x9, 0x9fc346, 0xb, 0xb42128, 0x0, 0x0, 0x0, ...) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:182 +0xa28 github.com/tendermint/tendermint/p2p.MakeConnectedSwitches(0xc0000f42a0, 0x2, 0xb42128, 0xb41eb8, 0x4f1205, 0xc0001bed80, 0x4f16ed) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/test_util.go:75 +0xf9 github.com/tendermint/tendermint/p2p.MakeSwitchPair(0xbb8d20, 0xc0001bd600, 0xb42128, 0x2f7, 0x4f16c0) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:94 +0x4c github.com/tendermint/tendermint/p2p.TestSwitches(0xc0001bd600) /home/vagrant/go/src/github.com/tendermint/tendermint/p2p/switch_test.go:117 +0x58 testing.tRunner(0xc0001bd600, 0xb42038) /usr/local/go/src/testing/testing.go:827 +0xbf created by testing.(*T).Run /usr/local/go/src/testing/testing.go:878 +0x353 exit status 2 FAIL github.com/tendermint/tendermint/p2p 0.350s ```
6 years ago
  1. package p2p
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "github.com/tendermint/tendermint/libs/log"
  7. tmnet "github.com/tendermint/tendermint/libs/net"
  8. tmrand "github.com/tendermint/tendermint/libs/rand"
  9. "github.com/tendermint/tendermint/config"
  10. "github.com/tendermint/tendermint/p2p/conn"
  11. )
  12. const testCh = 0x01
  13. //------------------------------------------------
  14. func AddPeerToSwitchPeerSet(sw *Switch, peer Peer) {
  15. sw.peers.Add(peer) //nolint:errcheck // ignore error
  16. }
  17. func CreateRandomPeer(outbound bool) Peer {
  18. addr, netAddr := CreateRoutableAddr()
  19. p := &peer{
  20. peerConn: peerConn{outbound: outbound},
  21. nodeInfo: NodeInfo{
  22. NodeID: netAddr.ID,
  23. ListenAddr: netAddr.DialString(),
  24. },
  25. metrics: NopMetrics(),
  26. }
  27. p.SetLogger(log.TestingLogger().With("peer", addr))
  28. return p
  29. }
  30. func CreateRoutableAddr() (addr string, netAddr *NetAddress) {
  31. for {
  32. var err error
  33. addr = fmt.Sprintf("%X@%v.%v.%v.%v:26656",
  34. tmrand.Bytes(20),
  35. tmrand.Int()%256,
  36. tmrand.Int()%256,
  37. tmrand.Int()%256,
  38. tmrand.Int()%256)
  39. netAddr, err = NewNetAddressString(addr)
  40. if err != nil {
  41. panic(err)
  42. }
  43. if netAddr.Routable() {
  44. break
  45. }
  46. }
  47. return
  48. }
  49. //------------------------------------------------------------------
  50. // Connects switches via arbitrary net.Conn. Used for testing.
  51. const TestHost = "localhost"
  52. // MakeConnectedSwitches returns n switches, connected according to the connect func.
  53. // If connect==Connect2Switches, the switches will be fully connected.
  54. // initSwitch defines how the i'th switch should be initialized (ie. with what reactors).
  55. // NOTE: panics if any switch fails to start.
  56. func MakeConnectedSwitches(cfg *config.P2PConfig,
  57. n int,
  58. initSwitch func(int, *Switch) *Switch,
  59. connect func([]*Switch, int, int),
  60. ) []*Switch {
  61. switches := make([]*Switch, n)
  62. for i := 0; i < n; i++ {
  63. switches[i] = MakeSwitch(cfg, i, TestHost, "123.123.123", initSwitch)
  64. }
  65. if err := StartSwitches(switches); err != nil {
  66. panic(err)
  67. }
  68. for i := 0; i < n; i++ {
  69. for j := i + 1; j < n; j++ {
  70. connect(switches, i, j)
  71. }
  72. }
  73. return switches
  74. }
  75. // Connect2Switches will connect switches i and j via net.Pipe().
  76. // Blocks until a connection is established.
  77. // NOTE: caller ensures i and j are within bounds.
  78. func Connect2Switches(switches []*Switch, i, j int) {
  79. switchI := switches[i]
  80. switchJ := switches[j]
  81. c1, c2 := conn.NetPipe()
  82. doneCh := make(chan struct{})
  83. go func() {
  84. err := switchI.addPeerWithConnection(c1)
  85. if err != nil {
  86. panic(err)
  87. }
  88. doneCh <- struct{}{}
  89. }()
  90. go func() {
  91. err := switchJ.addPeerWithConnection(c2)
  92. if err != nil {
  93. panic(err)
  94. }
  95. doneCh <- struct{}{}
  96. }()
  97. <-doneCh
  98. <-doneCh
  99. }
  100. func (sw *Switch) addPeerWithConnection(conn net.Conn) error {
  101. pc, err := testInboundPeerConn(sw.transport.(*MConnTransport), conn)
  102. if err != nil {
  103. if err := conn.Close(); err != nil {
  104. sw.Logger.Error("Error closing connection", "err", err)
  105. }
  106. return err
  107. }
  108. peerNodeInfo, _, err := pc.conn.Handshake(context.Background(), sw.nodeInfo, sw.nodeKey.PrivKey)
  109. if err != nil {
  110. if err := conn.Close(); err != nil {
  111. sw.Logger.Error("Error closing connection", "err", err)
  112. }
  113. return err
  114. }
  115. p := newPeer(
  116. peerNodeInfo,
  117. pc,
  118. sw.reactorsByCh,
  119. sw.StopPeerForError,
  120. )
  121. if err = sw.addPeer(p); err != nil {
  122. pc.CloseConn()
  123. return err
  124. }
  125. return nil
  126. }
  127. // StartSwitches calls sw.Start() for each given switch.
  128. // It returns the first encountered error.
  129. func StartSwitches(switches []*Switch) error {
  130. for _, s := range switches {
  131. err := s.Start() // start switch and reactors
  132. if err != nil {
  133. return err
  134. }
  135. }
  136. return nil
  137. }
  138. func MakeSwitch(
  139. cfg *config.P2PConfig,
  140. i int,
  141. network, version string,
  142. initSwitch func(int, *Switch) *Switch,
  143. opts ...SwitchOption,
  144. ) *Switch {
  145. nodeKey := GenNodeKey()
  146. nodeInfo := testNodeInfo(nodeKey.ID, fmt.Sprintf("node%d", i))
  147. addr, err := NewNetAddressString(
  148. IDAddressString(nodeKey.ID, nodeInfo.ListenAddr),
  149. )
  150. if err != nil {
  151. panic(err)
  152. }
  153. logger := log.TestingLogger().With("switch", i)
  154. t := NewMConnTransport(logger, MConnConfig(cfg),
  155. []*ChannelDescriptor{}, MConnTransportOptions{})
  156. // TODO: let the config be passed in?
  157. sw := initSwitch(i, NewSwitch(cfg, t, opts...))
  158. sw.SetLogger(log.TestingLogger().With("switch", i))
  159. sw.SetNodeKey(nodeKey)
  160. if err := t.Listen(addr.Endpoint()); err != nil {
  161. panic(err)
  162. }
  163. ni := nodeInfo
  164. ni.Channels = []byte{}
  165. for ch := range sw.reactorsByCh {
  166. ni.Channels = append(ni.Channels, ch)
  167. }
  168. nodeInfo = ni
  169. // TODO: We need to setup reactors ahead of time so the NodeInfo is properly
  170. // populated and we don't have to do those awkward overrides and setters.
  171. sw.SetNodeInfo(nodeInfo)
  172. return sw
  173. }
  174. func testInboundPeerConn(
  175. transport *MConnTransport,
  176. conn net.Conn,
  177. ) (peerConn, error) {
  178. return testPeerConn(transport, conn, false, false)
  179. }
  180. func testPeerConn(
  181. transport *MConnTransport,
  182. rawConn net.Conn,
  183. outbound, persistent bool,
  184. ) (pc peerConn, err error) {
  185. conn := newMConnConnection(transport.logger, rawConn, transport.mConnConfig, transport.channelDescs)
  186. return newPeerConn(outbound, persistent, conn), nil
  187. }
  188. //----------------------------------------------------------------
  189. // rand node info
  190. func testNodeInfo(id NodeID, name string) NodeInfo {
  191. return testNodeInfoWithNetwork(id, name, "testing")
  192. }
  193. func testNodeInfoWithNetwork(id NodeID, name, network string) NodeInfo {
  194. return NodeInfo{
  195. ProtocolVersion: defaultProtocolVersion,
  196. NodeID: id,
  197. ListenAddr: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
  198. Network: network,
  199. Version: "1.2.3-rc0-deadbeef",
  200. Channels: []byte{testCh},
  201. Moniker: name,
  202. Other: NodeInfoOther{
  203. TxIndex: "on",
  204. RPCAddress: fmt.Sprintf("127.0.0.1:%d", getFreePort()),
  205. },
  206. }
  207. }
  208. func getFreePort() int {
  209. port, err := tmnet.GetFreePort()
  210. if err != nil {
  211. panic(err)
  212. }
  213. return port
  214. }
  215. type AddrBookMock struct {
  216. Addrs map[string]struct{}
  217. OurAddrs map[string]struct{}
  218. PrivateAddrs map[string]struct{}
  219. }
  220. var _ AddrBook = (*AddrBookMock)(nil)
  221. func (book *AddrBookMock) AddAddress(addr *NetAddress, src *NetAddress) error {
  222. book.Addrs[addr.String()] = struct{}{}
  223. return nil
  224. }
  225. func (book *AddrBookMock) AddOurAddress(addr *NetAddress) { book.OurAddrs[addr.String()] = struct{}{} }
  226. func (book *AddrBookMock) OurAddress(addr *NetAddress) bool {
  227. _, ok := book.OurAddrs[addr.String()]
  228. return ok
  229. }
  230. func (book *AddrBookMock) MarkGood(NodeID) {}
  231. func (book *AddrBookMock) HasAddress(addr *NetAddress) bool {
  232. _, ok := book.Addrs[addr.String()]
  233. return ok
  234. }
  235. func (book *AddrBookMock) RemoveAddress(addr *NetAddress) {
  236. delete(book.Addrs, addr.String())
  237. }
  238. func (book *AddrBookMock) Save() {}
  239. func (book *AddrBookMock) AddPrivateIDs(addrs []string) {
  240. for _, addr := range addrs {
  241. book.PrivateAddrs[addr] = struct{}{}
  242. }
  243. }