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.

137 lines
2.8 KiB

11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
10 years ago
10 years ago
11 years ago
  1. package p2p
  2. import (
  3. "fmt"
  4. "io"
  5. "net"
  6. "sync/atomic"
  7. "github.com/tendermint/tendermint/binary"
  8. . "github.com/tendermint/tendermint/common"
  9. "github.com/tendermint/tendermint/types"
  10. )
  11. type Peer struct {
  12. outbound bool
  13. mconn *MConnection
  14. running uint32
  15. *types.NodeInfo
  16. Key string
  17. Data *CMap // User data.
  18. }
  19. // NOTE: blocking
  20. // Before creating a peer with newPeer(), perform a handshake on connection.
  21. func peerHandshake(conn net.Conn, ourNodeInfo *types.NodeInfo) (*types.NodeInfo, error) {
  22. var peerNodeInfo = new(types.NodeInfo)
  23. var err1 error
  24. var err2 error
  25. Parallel(
  26. func() {
  27. var n int64
  28. binary.WriteBinary(ourNodeInfo, conn, &n, &err1)
  29. },
  30. func() {
  31. var n int64
  32. binary.ReadBinary(peerNodeInfo, conn, &n, &err2)
  33. log.Info("Peer handshake", "peerNodeInfo", peerNodeInfo)
  34. })
  35. if err1 != nil {
  36. return nil, err1
  37. }
  38. if err2 != nil {
  39. return nil, err2
  40. }
  41. return peerNodeInfo, nil
  42. }
  43. // NOTE: call peerHandshake on conn before calling newPeer().
  44. func newPeer(conn net.Conn, peerNodeInfo *types.NodeInfo, outbound bool, reactorsByCh map[byte]Reactor, chDescs []*ChannelDescriptor, onPeerError func(*Peer, interface{})) *Peer {
  45. var p *Peer
  46. onReceive := func(chId byte, msgBytes []byte) {
  47. reactor := reactorsByCh[chId]
  48. if reactor == nil {
  49. panic(Fmt("Unknown channel %X", chId))
  50. }
  51. reactor.Receive(chId, p, msgBytes)
  52. }
  53. onError := func(r interface{}) {
  54. p.stop()
  55. onPeerError(p, r)
  56. }
  57. mconn := NewMConnection(conn, chDescs, onReceive, onError)
  58. p = &Peer{
  59. outbound: outbound,
  60. mconn: mconn,
  61. running: 0,
  62. NodeInfo: peerNodeInfo,
  63. Key: peerNodeInfo.UUID,
  64. Data: NewCMap(),
  65. }
  66. return p
  67. }
  68. func (p *Peer) start() {
  69. if atomic.CompareAndSwapUint32(&p.running, 0, 1) {
  70. log.Debug("Starting Peer", "peer", p)
  71. p.mconn.Start()
  72. }
  73. }
  74. func (p *Peer) stop() {
  75. if atomic.CompareAndSwapUint32(&p.running, 1, 0) {
  76. log.Debug("Stopping Peer", "peer", p)
  77. p.mconn.Stop()
  78. }
  79. }
  80. func (p *Peer) IsRunning() bool {
  81. return atomic.LoadUint32(&p.running) == 1
  82. }
  83. func (p *Peer) Connection() *MConnection {
  84. return p.mconn
  85. }
  86. func (p *Peer) IsOutbound() bool {
  87. return p.outbound
  88. }
  89. func (p *Peer) Send(chId byte, msg interface{}) bool {
  90. if atomic.LoadUint32(&p.running) == 0 {
  91. return false
  92. }
  93. return p.mconn.Send(chId, msg)
  94. }
  95. func (p *Peer) TrySend(chId byte, msg interface{}) bool {
  96. if atomic.LoadUint32(&p.running) == 0 {
  97. return false
  98. }
  99. return p.mconn.TrySend(chId, msg)
  100. }
  101. func (p *Peer) CanSend(chId byte) bool {
  102. if atomic.LoadUint32(&p.running) == 0 {
  103. return false
  104. }
  105. return p.mconn.CanSend(chId)
  106. }
  107. func (p *Peer) WriteTo(w io.Writer) (n int64, err error) {
  108. binary.WriteString(p.Key, w, &n, &err)
  109. return
  110. }
  111. func (p *Peer) String() string {
  112. if p.outbound {
  113. return fmt.Sprintf("Peer{->%v}", p.mconn)
  114. } else {
  115. return fmt.Sprintf("Peer{%v->}", p.mconn)
  116. }
  117. }
  118. func (p *Peer) Equals(other *Peer) bool {
  119. return p.Key == other.Key
  120. }