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.

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