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.

278 lines
6.1 KiB

10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
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. PeerManager handles PEX (peer exchange) and ensures that an
  21. adequate number of peers are connected to the switch.
  22. */
  23. type PeerManager struct {
  24. sw *Switch
  25. swEvents chan interface{}
  26. book *AddrBook
  27. quit chan struct{}
  28. started uint32
  29. stopped uint32
  30. }
  31. func NewPeerManager(sw *Switch, book *AddrBook) *PeerManager {
  32. swEvents := make(chan interface{})
  33. sw.AddEventListener("PeerManager.swEvents", swEvents)
  34. pm := &PeerManager{
  35. sw: sw,
  36. swEvents: swEvents,
  37. book: book,
  38. quit: make(chan struct{}),
  39. }
  40. return pm
  41. }
  42. func (pm *PeerManager) Start() {
  43. if atomic.CompareAndSwapUint32(&pm.started, 0, 1) {
  44. log.Info("Starting PeerManager")
  45. go pm.switchEventsHandler()
  46. go pm.requestHandler()
  47. go pm.ensurePeersHandler()
  48. }
  49. }
  50. func (pm *PeerManager) Stop() {
  51. if atomic.CompareAndSwapUint32(&pm.stopped, 0, 1) {
  52. log.Info("Stopping PeerManager")
  53. close(pm.quit)
  54. close(pm.swEvents)
  55. }
  56. }
  57. // Asks peer for more addresses.
  58. func (pm *PeerManager) RequestPEX(peer *Peer) {
  59. msg := &pexRequestMessage{}
  60. tm := TypedMessage{msgTypeRequest, msg}
  61. peer.TrySend(pexCh, tm.Bytes())
  62. }
  63. func (pm *PeerManager) SendAddrs(peer *Peer, addrs []*NetAddress) {
  64. msg := &pexAddrsMessage{Addrs: addrs}
  65. tm := TypedMessage{msgTypeAddrs, msg}
  66. peer.Send(pexCh, tm.Bytes())
  67. }
  68. // For new outbound peers, announce our listener addresses if any,
  69. // and if .book needs more addresses, ask for them.
  70. func (pm *PeerManager) switchEventsHandler() {
  71. for {
  72. swEvent, ok := <-pm.swEvents
  73. if !ok {
  74. break
  75. }
  76. switch swEvent.(type) {
  77. case SwitchEventNewPeer:
  78. event := swEvent.(SwitchEventNewPeer)
  79. if event.Peer.IsOutbound() {
  80. pm.SendAddrs(event.Peer, pm.book.OurAddresses())
  81. if pm.book.NeedMoreAddrs() {
  82. pm.RequestPEX(event.Peer)
  83. }
  84. }
  85. case SwitchEventDonePeer:
  86. // TODO
  87. }
  88. }
  89. }
  90. // Ensures that sufficient peers are connected. (continuous)
  91. func (pm *PeerManager) ensurePeersHandler() {
  92. // fire once immediately.
  93. pm.ensurePeers()
  94. // fire periodically
  95. timer := NewRepeatTimer(ensurePeersPeriodSeconds * time.Second)
  96. FOR_LOOP:
  97. for {
  98. select {
  99. case <-timer.Ch:
  100. pm.ensurePeers()
  101. case <-pm.quit:
  102. break FOR_LOOP
  103. }
  104. }
  105. // Cleanup
  106. timer.Stop()
  107. }
  108. // Ensures that sufficient peers are connected. (once)
  109. func (pm *PeerManager) ensurePeers() {
  110. numOutPeers, _, numDialing := pm.sw.NumPeers()
  111. numToDial := minNumOutboundPeers - (numOutPeers + numDialing)
  112. if numToDial <= 0 {
  113. return
  114. }
  115. toDial := NewCMap()
  116. // Try to pick numToDial addresses to dial.
  117. // TODO: improve logic.
  118. for i := 0; i < numToDial; i++ {
  119. newBias := MinInt(numOutPeers, 8)*10 + 10
  120. var picked *NetAddress
  121. // Try to fetch a new peer 3 times.
  122. // This caps the maximum number of tries to 3 * numToDial.
  123. for j := 0; i < 3; j++ {
  124. picked = pm.book.PickAddress(newBias)
  125. if picked == nil {
  126. return
  127. }
  128. if toDial.Has(picked.String()) ||
  129. pm.sw.IsDialing(picked) ||
  130. pm.sw.Peers().Has(picked) {
  131. continue
  132. } else {
  133. break
  134. }
  135. }
  136. if picked == nil {
  137. continue
  138. }
  139. toDial.Set(picked.String(), picked)
  140. }
  141. // Dial picked addresses
  142. for _, item := range toDial.Values() {
  143. picked := item.(*NetAddress)
  144. go func() {
  145. _, err := pm.sw.DialPeerWithAddress(picked)
  146. if err != nil {
  147. pm.book.MarkAttempt(picked)
  148. }
  149. }()
  150. }
  151. }
  152. // Handles incoming PEX messages.
  153. func (pm *PeerManager) requestHandler() {
  154. for {
  155. inBytes, ok := pm.sw.Receive(pexCh) // {Peer, Time, Packet}
  156. if !ok {
  157. // Client has stopped
  158. break
  159. }
  160. // decode message
  161. msg := decodeMessage(inBytes.Bytes)
  162. log.Info("requestHandler received %v", msg)
  163. switch msg.(type) {
  164. case *pexRequestMessage:
  165. // inBytes.MConn._peer requested some peers.
  166. // TODO: prevent abuse.
  167. addrs := pm.book.GetSelection()
  168. msg := &pexAddrsMessage{Addrs: addrs}
  169. tm := TypedMessage{msgTypeRequest, msg}
  170. queued := inBytes.MConn._peer.TrySend(pexCh, tm.Bytes())
  171. if !queued {
  172. // ignore
  173. }
  174. case *pexAddrsMessage:
  175. // We received some peer addresses from inBytes.MConn._peer.
  176. // TODO: prevent abuse.
  177. // (We don't want to get spammed with bad peers)
  178. srcAddr := inBytes.MConn._peer.RemoteAddress()
  179. for _, addr := range msg.(*pexAddrsMessage).Addrs {
  180. pm.book.AddAddress(addr, srcAddr)
  181. }
  182. default:
  183. // Ignore unknown message.
  184. // pm.sw.StopPeerForError(inBytes.MConn._peer, pexErrInvalidMessage)
  185. }
  186. }
  187. // Cleanup
  188. }
  189. //-----------------------------------------------------------------------------
  190. /* Messages */
  191. const (
  192. msgTypeUnknown = Byte(0x00)
  193. msgTypeRequest = Byte(0x01)
  194. msgTypeAddrs = Byte(0x02)
  195. )
  196. // TODO: check for unnecessary extra bytes at the end.
  197. func decodeMessage(bz ByteSlice) (msg interface{}) {
  198. // log.Debug("decoding msg bytes: %X", bz)
  199. switch Byte(bz[0]) {
  200. case msgTypeRequest:
  201. return &pexRequestMessage{}
  202. case msgTypeAddrs:
  203. return readPexAddrsMessage(bytes.NewReader(bz[1:]))
  204. default:
  205. return nil
  206. }
  207. }
  208. /*
  209. A pexRequestMessage requests additional peer addresses.
  210. */
  211. type pexRequestMessage struct {
  212. }
  213. func (m *pexRequestMessage) WriteTo(w io.Writer) (n int64, err error) {
  214. return // nothing to write.
  215. }
  216. func (m *pexRequestMessage) String() string {
  217. return "[pexRequest]"
  218. }
  219. /*
  220. A message with announced peer addresses.
  221. */
  222. type pexAddrsMessage struct {
  223. Addrs []*NetAddress
  224. }
  225. func readPexAddrsMessage(r io.Reader) *pexAddrsMessage {
  226. numAddrs := int(ReadUInt32(r))
  227. addrs := []*NetAddress{}
  228. for i := 0; i < numAddrs; i++ {
  229. addr := ReadNetAddress(r)
  230. addrs = append(addrs, addr)
  231. }
  232. return &pexAddrsMessage{
  233. Addrs: addrs,
  234. }
  235. }
  236. func (m *pexAddrsMessage) WriteTo(w io.Writer) (n int64, err error) {
  237. n, err = WriteTo(UInt32(len(m.Addrs)), w, n, err)
  238. for _, addr := range m.Addrs {
  239. n, err = WriteTo(addr, w, n, err)
  240. }
  241. return
  242. }
  243. func (m *pexAddrsMessage) String() string {
  244. return fmt.Sprintf("[pexAddrs %v]", m.Addrs)
  245. }