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.0 KiB

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