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.

272 lines
6.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package p2p
  2. import (
  3. "bytes"
  4. "errors"
  5. "fmt"
  6. "sync/atomic"
  7. "time"
  8. "github.com/tendermint/tendermint/binary"
  9. . "github.com/tendermint/tendermint/common"
  10. )
  11. var pexErrInvalidMessage = errors.New("Invalid PEX message")
  12. const (
  13. PexChannel = byte(0x00)
  14. ensurePeersPeriodSeconds = 30
  15. minNumOutboundPeers = 10
  16. maxNumPeers = 50
  17. )
  18. /*
  19. PEXReactor handles PEX (peer exchange) and ensures that an
  20. adequate number of peers are connected to the switch.
  21. */
  22. type PEXReactor struct {
  23. sw *Switch
  24. quit chan struct{}
  25. started uint32
  26. stopped uint32
  27. book *AddrBook
  28. }
  29. func NewPEXReactor(book *AddrBook) *PEXReactor {
  30. pexR := &PEXReactor{
  31. quit: make(chan struct{}),
  32. book: book,
  33. }
  34. return pexR
  35. }
  36. // Implements Reactor
  37. func (pexR *PEXReactor) Start(sw *Switch) {
  38. if atomic.CompareAndSwapUint32(&pexR.started, 0, 1) {
  39. log.Info("Starting PEXReactor")
  40. pexR.sw = sw
  41. go pexR.ensurePeersRoutine()
  42. }
  43. }
  44. // Implements Reactor
  45. func (pexR *PEXReactor) Stop() {
  46. if atomic.CompareAndSwapUint32(&pexR.stopped, 0, 1) {
  47. log.Info("Stopping PEXReactor")
  48. close(pexR.quit)
  49. }
  50. }
  51. // Implements Reactor
  52. func (pexR *PEXReactor) GetChannels() []*ChannelDescriptor {
  53. return []*ChannelDescriptor{
  54. &ChannelDescriptor{
  55. Id: PexChannel,
  56. Priority: 1,
  57. },
  58. }
  59. }
  60. // Implements Reactor
  61. func (pexR *PEXReactor) AddPeer(peer *Peer) {
  62. if peer.IsOutbound() {
  63. pexR.SendAddrs(peer, pexR.book.OurAddresses())
  64. if pexR.book.NeedMoreAddrs() {
  65. pexR.RequestPEX(peer)
  66. }
  67. }
  68. }
  69. // Implements Reactor
  70. func (pexR *PEXReactor) RemovePeer(peer *Peer, reason interface{}) {
  71. // TODO
  72. }
  73. // Implements Reactor
  74. // Handles incoming PEX messages.
  75. func (pexR *PEXReactor) Receive(chId byte, src *Peer, msgBytes []byte) {
  76. // decode message
  77. msg, err := DecodeMessage(msgBytes)
  78. if err != nil {
  79. log.Warn("Error decoding message", "error", err)
  80. return
  81. }
  82. log.Info("Received message", "msg", msg)
  83. switch msg.(type) {
  84. case *pexHandshakeMessage:
  85. chainId := msg.(*pexHandshakeMessage).ChainId
  86. if chainId != pexR.sw.chainId {
  87. err := fmt.Sprintf("Peer is on a different chain/network. Got %s, expected %s", chainId, pexR.sw.chainId)
  88. pexR.sw.StopPeerForError(src, err)
  89. }
  90. case *pexRequestMessage:
  91. // src requested some peers.
  92. // TODO: prevent abuse.
  93. pexR.SendAddrs(src, pexR.book.GetSelection())
  94. case *pexAddrsMessage:
  95. // We received some peer addresses from src.
  96. // TODO: prevent abuse.
  97. // (We don't want to get spammed with bad peers)
  98. srcAddr := src.Connection().RemoteAddress
  99. for _, addr := range msg.(*pexAddrsMessage).Addrs {
  100. pexR.book.AddAddress(addr, srcAddr)
  101. }
  102. default:
  103. // Ignore unknown message.
  104. }
  105. }
  106. // Asks peer for more addresses.
  107. func (pexR *PEXReactor) RequestPEX(peer *Peer) {
  108. peer.Send(PexChannel, &pexRequestMessage{})
  109. }
  110. func (pexR *PEXReactor) SendAddrs(peer *Peer, addrs []*NetAddress) {
  111. peer.Send(PexChannel, &pexAddrsMessage{Addrs: addrs})
  112. }
  113. // Ensures that sufficient peers are connected. (continuous)
  114. func (pexR *PEXReactor) ensurePeersRoutine() {
  115. // fire once immediately.
  116. pexR.ensurePeers()
  117. // fire periodically
  118. timer := NewRepeatTimer("pex", ensurePeersPeriodSeconds*time.Second)
  119. FOR_LOOP:
  120. for {
  121. select {
  122. case <-timer.Ch:
  123. pexR.ensurePeers()
  124. case <-pexR.quit:
  125. break FOR_LOOP
  126. }
  127. }
  128. // Cleanup
  129. timer.Stop()
  130. }
  131. // Ensures that sufficient peers are connected. (once)
  132. func (pexR *PEXReactor) ensurePeers() {
  133. numOutPeers, _, numDialing := pexR.sw.NumPeers()
  134. numToDial := minNumOutboundPeers - (numOutPeers + numDialing)
  135. log.Debug("Ensure peers", "numOutPeers", numOutPeers, "numDialing", numDialing, "numToDial", numToDial)
  136. if numToDial <= 0 {
  137. return
  138. }
  139. toDial := NewCMap()
  140. // Try to pick numToDial addresses to dial.
  141. // TODO: improve logic.
  142. for i := 0; i < numToDial; i++ {
  143. newBias := MinInt(numOutPeers, 8)*10 + 10
  144. var picked *NetAddress
  145. // Try to fetch a new peer 3 times.
  146. // This caps the maximum number of tries to 3 * numToDial.
  147. for j := 0; j < 3; j++ {
  148. try := pexR.book.PickAddress(newBias)
  149. if try == nil {
  150. break
  151. }
  152. alreadySelected := toDial.Has(try.String())
  153. alreadyDialing := pexR.sw.IsDialing(try)
  154. alreadyConnected := pexR.sw.Peers().Has(try.String())
  155. if alreadySelected || alreadyDialing || alreadyConnected {
  156. log.Debug("Cannot dial address", "addr", try,
  157. "alreadySelected", alreadySelected,
  158. "alreadyDialing", alreadyDialing,
  159. "alreadyConnected", alreadyConnected)
  160. continue
  161. } else {
  162. log.Debug("Will dial address", "addr", try)
  163. picked = try
  164. break
  165. }
  166. }
  167. if picked == nil {
  168. continue
  169. }
  170. toDial.Set(picked.String(), picked)
  171. }
  172. // Dial picked addresses
  173. for _, item := range toDial.Values() {
  174. picked := item.(*NetAddress)
  175. go func() {
  176. _, err := pexR.sw.DialPeerWithAddress(picked)
  177. if err != nil {
  178. pexR.book.MarkAttempt(picked)
  179. }
  180. }()
  181. }
  182. }
  183. //-----------------------------------------------------------------------------
  184. // Messages
  185. const (
  186. msgTypeUnknown = byte(0x00)
  187. msgTypeRequest = byte(0x01)
  188. msgTypeAddrs = byte(0x02)
  189. msgTypeHandshake = byte(0x03)
  190. )
  191. // TODO: check for unnecessary extra bytes at the end.
  192. func DecodeMessage(bz []byte) (msg interface{}, err error) {
  193. n := new(int64)
  194. msgType := bz[0]
  195. r := bytes.NewReader(bz)
  196. // log.Debug(Fmt("decoding msg bytes: %X", bz))
  197. switch msgType {
  198. case msgTypeHandshake:
  199. msg = binary.ReadBinary(&pexHandshakeMessage{}, r, n, &err)
  200. case msgTypeRequest:
  201. msg = &pexRequestMessage{}
  202. case msgTypeAddrs:
  203. msg = binary.ReadBinary(&pexAddrsMessage{}, r, n, &err)
  204. default:
  205. msg = nil
  206. }
  207. return
  208. }
  209. /*
  210. A pexHandshakeMessage contains the peer's chainId
  211. */
  212. type pexHandshakeMessage struct {
  213. ChainId string
  214. }
  215. func (m *pexHandshakeMessage) TypeByte() byte { return msgTypeHandshake }
  216. func (m *pexHandshakeMessage) String() string {
  217. return "[pexHandshake]"
  218. }
  219. /*
  220. A pexRequestMessage requests additional peer addresses.
  221. */
  222. type pexRequestMessage struct {
  223. }
  224. func (m *pexRequestMessage) TypeByte() byte { return msgTypeRequest }
  225. func (m *pexRequestMessage) String() string {
  226. return "[pexRequest]"
  227. }
  228. /*
  229. A message with announced peer addresses.
  230. */
  231. type pexAddrsMessage struct {
  232. Addrs []*NetAddress
  233. }
  234. func (m *pexAddrsMessage) TypeByte() byte { return msgTypeAddrs }
  235. func (m *pexAddrsMessage) String() string {
  236. return fmt.Sprintf("[pexAddrs %v]", m.Addrs)
  237. }