func (r *PEXReactor) OnStop() {
	r.BaseReactor.OnStop()
	r.book.Stop()
}
OnStop implements BaseService
package pex
import (
	"fmt"
	"reflect"
	"sort"
	"sync"
	"time"
	amino "github.com/tendermint/go-amino"
	cmn "github.com/tendermint/tendermint/libs/common"
	"github.com/tendermint/tendermint/p2p"
	"github.com/tendermint/tendermint/p2p/conn"
)
type Peer = p2p.Peer
const (
	PexChannel = byte(0x00)
	maxAddressSize = 256
	maxMsgSize = maxAddressSize * maxGetSelection
	defaultEnsurePeersPeriod   = 30 * time.Second
	defaultMinNumOutboundPeers = p2p.DefaultMinNumOutboundPeers
	defaultSeedDisconnectWaitPeriod = 3 * time.Hour
	defaultCrawlPeerInterval = 2 * time.Minute  
	defaultCrawlPeersPeriod = 30 * time.Second  
	maxAttemptsToDial = 16  
	biasToSelectNewPeers = 30  
)
type PEXReactor struct {
	p2p.BaseReactor
	book              AddrBook
	config            *PEXReactorConfig
	ensurePeersPeriod time.Duration  
	requestsSent         *cmn.CMap  
	lastReceivedRequests *cmn.CMap  
	attemptsToDial sync.Map  
}
func (r *PEXReactor) minReceiveRequestInterval() time.Duration {
	return r.ensurePeersPeriod / 3
}
type PEXReactorConfig struct {
	SeedMode bool
	Seeds []string
}
type _attemptsToDial struct {
	number     int
	lastDialed time.Time
}
func NewPEXReactor(b AddrBook, config *PEXReactorConfig) *PEXReactor {
	r := &PEXReactor{
		book:                 b,
		config:               config,
		ensurePeersPeriod:    defaultEnsurePeersPeriod,
		requestsSent:         cmn.NewCMap(),
		lastReceivedRequests: cmn.NewCMap(),
	}
	r.BaseReactor = *p2p.NewBaseReactor("PEXReactor", r)
	return r
}
func (r *PEXReactor) OnStart() error {
	if err := r.BaseReactor.OnStart(); err != nil {
		return err
	}
	err := r.book.Start()
	if err != nil && err != cmn.ErrAlreadyStarted {
		return err
	}
	if err := r.checkSeeds(); err != nil {
		return err
	}
	if r.config.SeedMode {
		go r.crawlPeersRoutine()
	} else {
		go r.ensurePeersRoutine()
	}
	return nil
}