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.

156 lines
3.7 KiB

  1. package p2p
  2. import (
  3. "fmt"
  4. "net"
  5. crypto "github.com/tendermint/tendermint/crypto"
  6. cmn "github.com/tendermint/tmlibs/common"
  7. "github.com/tendermint/tmlibs/log"
  8. "github.com/tendermint/tendermint/config"
  9. "github.com/tendermint/tendermint/p2p/conn"
  10. )
  11. func AddPeerToSwitch(sw *Switch, peer Peer) {
  12. sw.peers.Add(peer)
  13. }
  14. func CreateRandomPeer(outbound bool) *peer {
  15. addr, netAddr := CreateRoutableAddr()
  16. p := &peer{
  17. peerConn: peerConn{
  18. outbound: outbound,
  19. },
  20. nodeInfo: NodeInfo{
  21. ID: netAddr.ID,
  22. ListenAddr: netAddr.DialString(),
  23. },
  24. mconn: &conn.MConnection{},
  25. }
  26. p.SetLogger(log.TestingLogger().With("peer", addr))
  27. return p
  28. }
  29. func CreateRoutableAddr() (addr string, netAddr *NetAddress) {
  30. for {
  31. var err error
  32. addr = cmn.Fmt("%X@%v.%v.%v.%v:26656", cmn.RandBytes(20), cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256, cmn.RandInt()%256)
  33. netAddr, err = NewNetAddressString(addr)
  34. if err != nil {
  35. panic(err)
  36. }
  37. if netAddr.Routable() {
  38. break
  39. }
  40. }
  41. return
  42. }
  43. //------------------------------------------------------------------
  44. // Connects switches via arbitrary net.Conn. Used for testing.
  45. const TEST_HOST = "localhost"
  46. // MakeConnectedSwitches returns n switches, connected according to the connect func.
  47. // If connect==Connect2Switches, the switches will be fully connected.
  48. // initSwitch defines how the i'th switch should be initialized (ie. with what reactors).
  49. // NOTE: panics if any switch fails to start.
  50. func MakeConnectedSwitches(cfg *config.P2PConfig, n int, initSwitch func(int, *Switch) *Switch, connect func([]*Switch, int, int)) []*Switch {
  51. switches := make([]*Switch, n)
  52. for i := 0; i < n; i++ {
  53. switches[i] = MakeSwitch(cfg, i, TEST_HOST, "123.123.123", initSwitch)
  54. }
  55. if err := StartSwitches(switches); err != nil {
  56. panic(err)
  57. }
  58. for i := 0; i < n; i++ {
  59. for j := i + 1; j < n; j++ {
  60. connect(switches, i, j)
  61. }
  62. }
  63. return switches
  64. }
  65. // Connect2Switches will connect switches i and j via net.Pipe().
  66. // Blocks until a connection is established.
  67. // NOTE: caller ensures i and j are within bounds.
  68. func Connect2Switches(switches []*Switch, i, j int) {
  69. switchI := switches[i]
  70. switchJ := switches[j]
  71. c1, c2 := conn.NetPipe()
  72. doneCh := make(chan struct{})
  73. go func() {
  74. err := switchI.addPeerWithConnection(c1)
  75. if err != nil {
  76. panic(err)
  77. }
  78. doneCh <- struct{}{}
  79. }()
  80. go func() {
  81. err := switchJ.addPeerWithConnection(c2)
  82. if err != nil {
  83. panic(err)
  84. }
  85. doneCh <- struct{}{}
  86. }()
  87. <-doneCh
  88. <-doneCh
  89. }
  90. func (sw *Switch) addPeerWithConnection(conn net.Conn) error {
  91. pc, err := newInboundPeerConn(conn, sw.config, sw.nodeKey.PrivKey)
  92. if err != nil {
  93. if err := conn.Close(); err != nil {
  94. sw.Logger.Error("Error closing connection", "err", err)
  95. }
  96. return err
  97. }
  98. if err = sw.addPeer(pc); err != nil {
  99. pc.CloseConn()
  100. return err
  101. }
  102. return nil
  103. }
  104. // StartSwitches calls sw.Start() for each given switch.
  105. // It returns the first encountered error.
  106. func StartSwitches(switches []*Switch) error {
  107. for _, s := range switches {
  108. err := s.Start() // start switch and reactors
  109. if err != nil {
  110. return err
  111. }
  112. }
  113. return nil
  114. }
  115. func MakeSwitch(cfg *config.P2PConfig, i int, network, version string, initSwitch func(int, *Switch) *Switch) *Switch {
  116. // new switch, add reactors
  117. // TODO: let the config be passed in?
  118. nodeKey := &NodeKey{
  119. PrivKey: crypto.GenPrivKeyEd25519(),
  120. }
  121. sw := NewSwitch(cfg)
  122. sw.SetLogger(log.TestingLogger())
  123. sw = initSwitch(i, sw)
  124. ni := NodeInfo{
  125. ID: nodeKey.ID(),
  126. Moniker: cmn.Fmt("switch%d", i),
  127. Network: network,
  128. Version: version,
  129. ListenAddr: fmt.Sprintf("127.0.0.1:%d", cmn.RandIntn(64512)+1023),
  130. }
  131. for ch := range sw.reactorsByCh {
  132. ni.Channels = append(ni.Channels, ch)
  133. }
  134. sw.SetNodeInfo(ni)
  135. sw.SetNodeKey(nodeKey)
  136. return sw
  137. }