Manage discovery from flags and refactor handling interrupt signals (#557)

This commit is contained in:
Adam Babik 2018-01-22 21:16:13 -08:00 committed by GitHub
parent cb0a889245
commit e214e1e270
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 59 deletions

View File

@ -5,11 +5,14 @@ import (
"fmt"
"log"
"os"
"os/signal"
"runtime"
"strings"
"time"
"github.com/status-im/status-go/cmd/statusd/debug"
"github.com/status-im/status-go/geth/api"
"github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/params"
)
@ -23,7 +26,8 @@ var (
nodeKeyFile = flag.String("nodekey", "", "P2P node key file (private key)")
dataDir = flag.String("datadir", params.DataDir, "Data directory for the databases and keystore")
networkID = flag.Int("networkid", params.RopstenNetworkID, "Network identifier (integer, 1=Homestead, 3=Ropsten, 4=Rinkeby, 777=StatusChain)")
whisperEnabled = flag.Bool("shh", false, "SHH protocol enabled")
lesEnabled = flag.Bool("les", false, "LES protocol enabled (default is disabled)")
whisperEnabled = flag.Bool("shh", false, "Whisper protocol enabled (default is disabled)")
swarmEnabled = flag.Bool("swarm", false, "Swarm protocol enabled")
httpEnabled = flag.Bool("http", false, "HTTP RPC endpoint enabled (default: false)")
httpPort = flag.Int("httpport", params.HTTPPort, "HTTP RPC server's listening port")
@ -33,10 +37,10 @@ var (
logLevel = flag.String("log", "INFO", `Log level, one of: "ERROR", "WARN", "INFO", "DEBUG", and "TRACE"`)
logFile = flag.String("logfile", "", "Path to the log file")
version = flag.Bool("version", false, "Print version")
lesEnabled = flag.Bool("les", true, "LES protocol enabled")
listenAddr = flag.String("listenaddr", ":30303", "IP address and port of this node (e.g. 127.0.0.1:30303)")
standalone = flag.Bool("standalone", true, "Don't actively connect to peers, wait for incoming connections")
bootnodes = flag.String("bootnodes", "", "A list of bootnodes separated by comma")
// shh stuff
identityFile = flag.String("shh.identityfile", "", "Protocol identity file (private key used for asymmetric encryption)")
@ -74,6 +78,9 @@ func main() {
return
}
// handle interrupt signals
go haltOnInterruptSignal(backend.NodeManager())
// wait till node is started
<-started
@ -132,6 +139,20 @@ func makeNodeConfig() (*params.NodeConfig, error) {
nodeConfig.LightEthConfig.Enabled = *lesEnabled
nodeConfig.SwarmConfig.Enabled = *swarmEnabled
if *standalone {
nodeConfig.BootClusterConfig.Enabled = false
nodeConfig.BootClusterConfig.BootNodes = nil
} else {
nodeConfig.Discovery = true
}
// Even if standalone is true and discovery is disabled,
// it's possible to use bootnodes in NodeManager.PopulateStaticPeers().
// TODO(adam): research if we need NodeManager.PopulateStaticPeers() at all.
if *bootnodes != "" {
nodeConfig.BootClusterConfig.BootNodes = strings.Split(*bootnodes, ",")
}
if *whisperEnabled {
return whisperConfig(nodeConfig)
}
@ -184,3 +205,28 @@ Options:
fmt.Fprintf(os.Stderr, usage) // nolint: gas
flag.PrintDefaults()
}
// haltOnInterruptSignal catches interrupt signal (SIGINT) and
// stops the node. It times out after 5 seconds
// if the node can not be stopped.
func haltOnInterruptSignal(nodeManager common.NodeManager) {
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, os.Interrupt)
defer signal.Stop(signalCh)
<-signalCh
log.Println("Got interrupt, shutting down...")
nodeStopped, err := nodeManager.StopNode()
if err != nil {
log.Printf("Failed to stop node: %v", err.Error())
os.Exit(1)
}
select {
case <-nodeStopped:
case <-time.After(time.Second * 5):
log.Printf("Stopping node timed out")
os.Exit(1)
}
}

View File

@ -64,11 +64,6 @@ func whisperConfig(nodeConfig *params.NodeConfig) (*params.NodeConfig, error) {
}
nodeConfig.HTTPHost = "0.0.0.0"
if *standalone {
nodeConfig.BootClusterConfig.Enabled = false
nodeConfig.BootClusterConfig.BootNodes = nil
}
return nodeConfig, nil
}

View File

@ -48,10 +48,7 @@ type NodeManager struct {
// NewNodeManager makes new instance of node manager
func NewNodeManager() *NodeManager {
m := &NodeManager{}
go HaltOnInterruptSignal(m) // allow interrupting running nodes
return m
return &NodeManager{}
}
// StartNode start Status node, fails if node is already started

View File

@ -17,9 +17,7 @@ import (
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/discv5"
"github.com/ethereum/go-ethereum/p2p/nat"
gethparams "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/whisper/mailserver"
"github.com/ethereum/go-ethereum/whisper/notifications"
whisper "github.com/ethereum/go-ethereum/whisper/whisperv5"
@ -93,11 +91,11 @@ func defaultEmbeddedNodeConfig(config *params.NodeConfig) *node.Config {
Name: config.Name,
Version: config.Version,
P2P: p2p.Config{
NoDiscovery: true,
NoDiscovery: !config.Discovery,
DiscoveryV5: true,
DiscoveryV5Addr: ":0",
BootstrapNodes: makeBootstrapNodes(),
BootstrapNodesV5: makeBootstrapNodesV5(),
BootstrapNodes: nil,
BootstrapNodesV5: nil,
ListenAddr: config.ListenAddr,
NAT: nat.Any(),
MaxPeers: config.MaxPeers,
@ -117,9 +115,8 @@ func defaultEmbeddedNodeConfig(config *params.NodeConfig) *node.Config {
nc.HTTPPort = config.HTTPPort
}
if !config.BootClusterConfig.Enabled {
nc.P2P.BootstrapNodes = nil
nc.P2P.BootstrapNodesV5 = nil
if config.Discovery {
nc.P2P.BootstrapNodes = makeBootstrapNodes(config.BootClusterConfig.BootNodes)
}
return nc
@ -215,11 +212,7 @@ func makeWSHost(config *params.NodeConfig) string {
}
// makeBootstrapNodes returns default (hence bootstrap) list of peers
func makeBootstrapNodes() []*discover.Node {
// on desktops params.TestnetBootnodes and params.MainBootnodes,
// on mobile client we deliberately keep this list empty
enodes := []string{}
func makeBootstrapNodes(enodes []string) []*discover.Node {
var bootstrapNodes []*discover.Node
for _, enode := range enodes {
bootstrapNodes = append(bootstrapNodes, discover.MustParseNode(enode))
@ -227,15 +220,3 @@ func makeBootstrapNodes() []*discover.Node {
return bootstrapNodes
}
// makeBootstrapNodesV5 returns default (hence bootstrap) list of peers
func makeBootstrapNodesV5() []*discv5.Node {
enodes := gethparams.DiscoveryV5Bootnodes
var bootstrapNodes []*discv5.Node
for _, enode := range enodes {
bootstrapNodes = append(bootstrapNodes, discv5.MustParseNode(enode))
}
return bootstrapNodes
}

View File

@ -2,11 +2,8 @@ package node
import (
"fmt"
"os"
osSignal "os/signal"
"github.com/status-im/status-go/geth/common"
"github.com/status-im/status-go/geth/log"
"github.com/status-im/status-go/geth/signal"
)
@ -26,23 +23,3 @@ func HaltOnPanic() {
common.Fatalf(err) // os.exit(1) is called internally
}
}
// HaltOnInterruptSignal stops node and panics if you press Ctrl-C enough times
func HaltOnInterruptSignal(nodeManager *NodeManager) {
sigc := make(chan os.Signal, 1)
osSignal.Notify(sigc, os.Interrupt)
defer osSignal.Stop(sigc)
<-sigc
if nodeManager.node == nil {
return
}
log.Info("Got interrupt, shutting down...")
go nodeManager.node.Stop() // nolint: errcheck
for i := 3; i > 0; i-- {
<-sigc
if i > 1 {
log.Info(fmt.Sprintf("Already shutting down, interrupt %d more times for panic.", i-1))
}
}
panic("interrupted!")
}

View File

@ -230,6 +230,9 @@ type NodeConfig struct {
// remote peer identification as well as network traffic encryption.
NodeKeyFile string
// Discovery set to true will enabled discovery protocol.
Discovery bool
// ListenAddr is an IP address and port of this node (e.g. 127.0.0.1:30303).
ListenAddr string