runNodeCmd.Flags().String("p2p.proxy_address", config.P2P.ProxyAddress, "Connect via SOCKS5 proxy (eg. 127.0.0.1:1086)")
runNodeCmd.Flags().String("p2p.proxy_username", config.P2P.ProxyUsername, "Username for proxy server")
runNodeCmd.Flags().String("p2p.proxy_password", config.P2P.ProxyPassword, "Password for proxy server")
+ runNodeCmd.Flags().String("p2p.keep_dial", config.P2P.KeepDial, "Peers addresses try keeping connecting to, separated by ',' (for example \"1.1.1.1:46657;2.2.2.2:46658\")")
// log flags
runNodeCmd.Flags().String("log_file", config.LogFile, "Log output file")
ProxyAddress string `mapstructure:"proxy_address"`
ProxyUsername string `mapstructure:"proxy_username"`
ProxyPassword string `mapstructure:"proxy_password"`
+ KeepDial string `mapstructure:"keep_dial"`
}
// Default configurable p2p parameters.
"net"
"path"
"strconv"
- "strings"
"time"
log "github.com/sirupsen/logrus"
errTimeout = errors.New("RPC timeout")
errClockWarp = errors.New("reply deadline too far in the future")
errClosed = errors.New("socket closed")
- errInvalidSeedIP = errors.New("seed ip is invalid")
- errInvalidSeedPort = errors.New("seed port is invalid")
)
// Timeouts
log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on query dns seeds")
}
- if config.P2P.Seeds != "" {
- codedSeeds := strings.Split(config.P2P.Seeds, ",")
- for _, codedSeed := range codedSeeds {
- ip, port, err := net.SplitHostPort(codedSeed)
- if err != nil {
- return nil, err
- }
-
- if validIP := net.ParseIP(ip); validIP == nil {
- return nil, errInvalidSeedIP
- }
-
- if _, err := strconv.ParseUint(port, 10, 16); err != nil {
- return nil, errInvalidSeedPort
- }
-
- seeds = append(seeds, codedSeed)
- }
- }
-
+ codedSeeds := netutil.CheckAndSplitAddresses(config.P2P.Seeds)
+ seeds = append(seeds, codedSeeds...)
if len(seeds) == 0 {
return ntab, nil
}
"strconv"
"time"
- cmn "github.com/tendermint/tmlibs/common"
"github.com/btcsuite/go-socks/socks"
+ cmn "github.com/tendermint/tmlibs/common"
)
// NetAddress defines information about a peer on the network
"fmt"
"net"
"sort"
+ "strconv"
"strings"
+
+ log "github.com/sirupsen/logrus"
)
var lan4, lan6, special4, special6 Netlist
+var (
+ logModule = "netutil"
+
+ errInvalidIP = errors.New("ip is invalid")
+ errInvalidPort = errors.New("port is invalid")
+)
+
func init() {
// Lists from RFC 5735, RFC 5156,
// https://www.iana.org/assignments/iana-ipv4-special-registry/
buf.WriteString("}")
return buf.String()
}
+
+func CheckAndSplitAddresses(addressesStr string) []string {
+ if addressesStr == "" {
+ return nil
+ }
+
+ var addresses []string
+ splits := strings.Split(addressesStr, ",")
+ for _, address := range splits {
+ ip, port, err := net.SplitHostPort(address)
+ if err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err, "address": address}).Warn("net.SplitHostPort")
+ continue
+ }
+
+ if validIP := net.ParseIP(ip); validIP == nil {
+ log.WithFields(log.Fields{"module": logModule, "err": errInvalidIP, "ip": ip}).Warn("net.ParseIP")
+ continue
+ }
+
+ if _, err := strconv.ParseUint(port, 10, 16); err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": errInvalidPort, "port": port}).Warn("strconv parse port")
+ continue
+ }
+
+ addresses = append(addresses, address)
+ }
+ return addresses
+}
"github.com/bytom/errors"
"github.com/bytom/p2p/connection"
"github.com/bytom/p2p/discover"
+ "github.com/bytom/p2p/netutil"
"github.com/bytom/p2p/trust"
"github.com/bytom/version"
)
wg.Done()
}
+func (sw *Switch) ensureKeepConnectPeers() {
+ keepDials := netutil.CheckAndSplitAddresses(sw.Config.P2P.KeepDial)
+ connectedPeers := make(map[string]struct{})
+ for _, peer := range sw.Peers().List() {
+ connectedPeers[peer.remoteAddrHost()] = struct{}{}
+ }
+
+ var wg sync.WaitGroup
+ for _, keepDial := range keepDials {
+ try, err := NewNetAddressString(keepDial)
+ if err != nil {
+ log.WithFields(log.Fields{"module": logModule, "err": err, "address": keepDial}).Warn("parse address to NetAddress")
+ continue
+ }
+
+ if sw.NodeInfo().ListenAddr == try.String() {
+ continue
+ }
+ if dialling := sw.IsDialing(try); dialling {
+ continue
+ }
+ if _, ok := connectedPeers[try.IP.String()]; ok {
+ continue
+ }
+
+ wg.Add(1)
+ go sw.dialPeerWorker(try, &wg)
+ }
+ wg.Wait()
+}
+
func (sw *Switch) ensureOutboundPeers() {
numOutPeers, _, numDialing := sw.NumPeers()
numToDial := (minNumOutboundPeers - (numOutPeers + numDialing))
}
func (sw *Switch) ensureOutboundPeersRoutine() {
+ sw.ensureKeepConnectPeers()
sw.ensureOutboundPeers()
ticker := time.NewTicker(10 * time.Second)
for {
select {
case <-ticker.C:
+ sw.ensureKeepConnectPeers()
sw.ensureOutboundPeers()
case <-sw.Quit:
return