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.

111 lines
2.9 KiB

7 years ago
  1. package p2p
  2. import (
  3. "math/rand"
  4. "net"
  5. crypto "github.com/tendermint/go-crypto"
  6. cfg "github.com/tendermint/tendermint/config"
  7. cmn "github.com/tendermint/tmlibs/common"
  8. "github.com/tendermint/tmlibs/log"
  9. )
  10. //------------------------------------------------------------------
  11. // Connects switches via arbitrary net.Conn. Used for testing.
  12. // MakeConnectedSwitches returns n switches, connected according to the connect func.
  13. // If connect==Connect2Switches, the switches will be fully connected.
  14. // initSwitch defines how the i'th switch should be initialized (ie. with what reactors).
  15. // NOTE: panics if any switch fails to start.
  16. func MakeConnectedSwitches(cfg *cfg.P2PConfig, n int, initSwitch func(int, *Switch) *Switch, connect func([]*Switch, int, int)) []*Switch {
  17. switches := make([]*Switch, n)
  18. for i := 0; i < n; i++ {
  19. switches[i] = makeSwitch(cfg, i, "testing", "123.123.123", initSwitch)
  20. }
  21. if err := StartSwitches(switches); err != nil {
  22. panic(err)
  23. }
  24. for i := 0; i < n; i++ {
  25. for j := i + 1; j < n; j++ {
  26. connect(switches, i, j)
  27. }
  28. }
  29. return switches
  30. }
  31. // Connect2Switches will connect switches i and j via net.Pipe().
  32. // Blocks until a connection is established.
  33. // NOTE: caller ensures i and j are within bounds.
  34. func Connect2Switches(switches []*Switch, i, j int) {
  35. switchI := switches[i]
  36. switchJ := switches[j]
  37. c1, c2 := netPipe()
  38. doneCh := make(chan struct{})
  39. go func() {
  40. err := switchI.addPeerWithConnection(c1)
  41. if err != nil {
  42. panic(err)
  43. }
  44. doneCh <- struct{}{}
  45. }()
  46. go func() {
  47. err := switchJ.addPeerWithConnection(c2)
  48. if err != nil {
  49. panic(err)
  50. }
  51. doneCh <- struct{}{}
  52. }()
  53. <-doneCh
  54. <-doneCh
  55. }
  56. func (sw *Switch) addPeerWithConnection(conn net.Conn) error {
  57. peer, err := newInboundPeer(conn, sw.reactorsByCh, sw.chDescs, sw.StopPeerForError, sw.nodeKey.PrivKey, sw.peerConfig)
  58. if err != nil {
  59. if err := conn.Close(); err != nil {
  60. sw.Logger.Error("Error closing connection", "err", err)
  61. }
  62. return err
  63. }
  64. peer.SetLogger(sw.Logger.With("peer", conn.RemoteAddr()))
  65. if err = sw.addPeer(peer); err != nil {
  66. peer.CloseConn()
  67. return err
  68. }
  69. return nil
  70. }
  71. // StartSwitches calls sw.Start() for each given switch.
  72. // It returns the first encountered error.
  73. func StartSwitches(switches []*Switch) error {
  74. for _, s := range switches {
  75. err := s.Start() // start switch and reactors
  76. if err != nil {
  77. return err
  78. }
  79. }
  80. return nil
  81. }
  82. func makeSwitch(cfg *cfg.P2PConfig, i int, network, version string, initSwitch func(int, *Switch) *Switch) *Switch {
  83. // new switch, add reactors
  84. // TODO: let the config be passed in?
  85. nodeKey := &NodeKey{
  86. PrivKey: crypto.GenPrivKeyEd25519().Wrap(),
  87. }
  88. s := initSwitch(i, NewSwitch(cfg))
  89. s.SetNodeInfo(&NodeInfo{
  90. PubKey: nodeKey.PubKey(),
  91. Moniker: cmn.Fmt("switch%d", i),
  92. Network: network,
  93. Version: version,
  94. ListenAddr: cmn.Fmt("%v:%v", network, rand.Intn(64512)+1023),
  95. })
  96. s.SetNodeKey(nodeKey)
  97. s.SetLogger(log.TestingLogger())
  98. return s
  99. }