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.

263 lines
5.5 KiB

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