mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-25 14:16:44 +00:00
Merge 73c6f4b9e6 into f58ac2b46b
This commit is contained in:
commit
320ab1e875
9 changed files with 175 additions and 94 deletions
|
|
@ -59,6 +59,7 @@ Welcome to the Geth JavaScript console!
|
||||||
|
|
||||||
instance: Geth/v{{gethver}}/{{goos}}/{{gover}}
|
instance: Geth/v{{gethver}}/{{goos}}/{{gover}}
|
||||||
coinbase: {{.Etherbase}}
|
coinbase: {{.Etherbase}}
|
||||||
|
network: mainnet
|
||||||
at block: 0 ({{niltime}})
|
at block: 0 ({{niltime}})
|
||||||
datadir: {{.Datadir}}
|
datadir: {{.Datadir}}
|
||||||
modules:{{range apis}} {{.}}:1.0{{end}}
|
modules:{{range apis}} {{.}}:1.0{{end}}
|
||||||
|
|
@ -153,6 +154,7 @@ Welcome to the Geth JavaScript console!
|
||||||
|
|
||||||
instance: Geth/v{{gethver}}/{{goos}}/{{gover}}
|
instance: Geth/v{{gethver}}/{{goos}}/{{gover}}
|
||||||
coinbase: {{etherbase}}
|
coinbase: {{etherbase}}
|
||||||
|
network: mainnet
|
||||||
at block: 0 ({{niltime}}){{if ipc}}
|
at block: 0 ({{niltime}}){{if ipc}}
|
||||||
datadir: {{datadir}}{{end}}
|
datadir: {{datadir}}{{end}}
|
||||||
modules:{{range apis}} {{.}}:1.0{{end}}
|
modules:{{range apis}} {{.}}:1.0{{end}}
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ func main() {
|
||||||
func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node.Node, error) {
|
func MakeSystemNode(keydir string, privkey string, test *tests.BlockTest) (*node.Node, error) {
|
||||||
// Create a networkless protocol stack
|
// Create a networkless protocol stack
|
||||||
stack, err := node.New(&node.Config{
|
stack, err := node.New(&node.Config{
|
||||||
IPCPath: node.DefaultIPCEndpoint(),
|
IPCPath: []string{node.DefaultIPCEndpoint()},
|
||||||
HTTPHost: common.DefaultHTTPHost,
|
HTTPHost: common.DefaultHTTPHost,
|
||||||
HTTPPort: common.DefaultHTTPPort,
|
HTTPPort: common.DefaultHTTPPort,
|
||||||
HTTPModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
|
HTTPModules: []string{"admin", "db", "eth", "debug", "miner", "net", "shh", "txpool", "personal", "web3"},
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
|
@ -40,6 +41,11 @@ func NewRemoteRPCClient(ctx *cli.Context) (rpc.Client, error) {
|
||||||
// endpoint. It must start with either `ipc:` or `rpc:` (HTTP).
|
// endpoint. It must start with either `ipc:` or `rpc:` (HTTP).
|
||||||
func NewRemoteRPCClientFromString(endpoint string) (rpc.Client, error) {
|
func NewRemoteRPCClientFromString(endpoint string) (rpc.Client, error) {
|
||||||
if strings.HasPrefix(endpoint, "ipc:") {
|
if strings.HasPrefix(endpoint, "ipc:") {
|
||||||
|
if runtime.GOOS == "windows" && !strings.HasPrefix(endpoint, `ipc:\\.\pipe\`) {
|
||||||
|
// user supplied named pipe name, e.g: attach "namedpipename" instead
|
||||||
|
// of "attach ipc:\\.\pipe\namedpipename".
|
||||||
|
endpoint = `ipc:\\.\pipe\` + endpoint[4:]
|
||||||
|
}
|
||||||
return rpc.NewIPCClient(endpoint[4:])
|
return rpc.NewIPCClient(endpoint[4:])
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(endpoint, "rpc:") {
|
if strings.HasPrefix(endpoint, "rpc:") {
|
||||||
|
|
|
||||||
|
|
@ -276,8 +276,8 @@ var (
|
||||||
}
|
}
|
||||||
IPCPathFlag = DirectoryFlag{
|
IPCPathFlag = DirectoryFlag{
|
||||||
Name: "ipcpath",
|
Name: "ipcpath",
|
||||||
Usage: "Filename for IPC socket/pipe within the datadir (explicit paths escape it)",
|
Usage: "IPC endpoint location (explicit paths escape it)",
|
||||||
Value: DirectoryString{common.DefaultIPCSocket},
|
Value: DirectoryString{common.DefaultIPCEndpoint()},
|
||||||
}
|
}
|
||||||
WSEnabledFlag = cli.BoolFlag{
|
WSEnabledFlag = cli.BoolFlag{
|
||||||
Name: "ws",
|
Name: "ws",
|
||||||
|
|
@ -423,13 +423,27 @@ func MakeKeyStoreDir(datadir string, ctx *cli.Context) string {
|
||||||
return filepath.Join(datadir, "keystore")
|
return filepath.Join(datadir, "keystore")
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeIPCPath creates an IPC path configuration from the set command line flags,
|
// MakeIPCPaths creates an IPC path configuration from the set command line flags,
|
||||||
// returning an empty string if IPC was explicitly disabled, or the set path.
|
// returning an empty slice if IPC was explicitly disabled, or the paths to open
|
||||||
func MakeIPCPath(ctx *cli.Context) string {
|
// the IPC endpoint(s).
|
||||||
|
func MakeIPCPaths(ctx *cli.Context) []string {
|
||||||
if ctx.GlobalBool(IPCDisabledFlag.Name) {
|
if ctx.GlobalBool(IPCDisabledFlag.Name) {
|
||||||
return ""
|
return []string{}
|
||||||
}
|
}
|
||||||
return ctx.GlobalString(IPCPathFlag.Name)
|
|
||||||
|
// user overruled default location
|
||||||
|
if ctx.GlobalIsSet(IPCPathFlag.Name) {
|
||||||
|
return []string{ctx.GlobalString(IPCPathFlag.Name)}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return the old geth specific path and new more general default path.
|
||||||
|
// This is a temporary situation, the old path will be removed after a couple
|
||||||
|
// of weeks. This gives clients time to update and users the ability to use
|
||||||
|
// the latest geth version with default IPC setting as they are used to.
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return []string{`\\.\pipe\geth.ipc`, ctx.GlobalString(IPCPathFlag.Name)}
|
||||||
|
}
|
||||||
|
return []string{"geth.ipc", ctx.GlobalString(IPCPathFlag.Name)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeNodeKey creates a node key from set command line flags, either loading it
|
// MakeNodeKey creates a node key from set command line flags, either loading it
|
||||||
|
|
@ -655,7 +669,7 @@ func MakeSystemNode(name, version string, relconf release.Config, extra []byte,
|
||||||
NAT: MakeNAT(ctx),
|
NAT: MakeNAT(ctx),
|
||||||
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
MaxPeers: ctx.GlobalInt(MaxPeersFlag.Name),
|
||||||
MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name),
|
MaxPendingPeers: ctx.GlobalInt(MaxPendingPeersFlag.Name),
|
||||||
IPCPath: MakeIPCPath(ctx),
|
IPCPath: MakeIPCPaths(ctx),
|
||||||
HTTPHost: MakeHTTPRpcHost(ctx),
|
HTTPHost: MakeHTTPRpcHost(ctx),
|
||||||
HTTPPort: ctx.GlobalInt(RPCPortFlag.Name),
|
HTTPPort: ctx.GlobalInt(RPCPortFlag.Name),
|
||||||
HTTPCors: ctx.GlobalString(RPCCORSDomainFlag.Name),
|
HTTPCors: ctx.GlobalString(RPCCORSDomainFlag.Name),
|
||||||
|
|
|
||||||
|
|
@ -19,14 +19,16 @@ package common
|
||||||
import (
|
import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DefaultIPCSocket = "geth.ipc" // Default (relative) name of the IPC RPC socket
|
DefaultIPCSocket = "ipc.sock" // Default (relative) name of the IPC RPC unix socket
|
||||||
DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server
|
DefaultIPCNamedPipe = `\\.\pipe\ethereum` // Default name of the IPC RPC named pipe
|
||||||
DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server
|
DefaultHTTPHost = "localhost" // Default host interface for the HTTP RPC server
|
||||||
DefaultWSHost = "localhost" // Default host interface for the websocket RPC server
|
DefaultHTTPPort = 8545 // Default TCP port for the HTTP RPC server
|
||||||
DefaultWSPort = 8546 // Default TCP port for the websocket RPC server
|
DefaultWSHost = "localhost" // Default host interface for the websocket RPC server
|
||||||
|
DefaultWSPort = 8546 // Default TCP port for the websocket RPC server
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultDataDir is the default data directory to use for the databases and other
|
// DefaultDataDir is the default data directory to use for the databases and other
|
||||||
|
|
@ -46,3 +48,27 @@ func DefaultDataDir() string {
|
||||||
// As we cannot guess a stable location, return empty and handle later
|
// As we cannot guess a stable location, return empty and handle later
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultIPCEndpoint returns the default location where to open the IPC endpoint.
|
||||||
|
//
|
||||||
|
// On Windows this is DefaultIPCNamedPipe.
|
||||||
|
// On OSX this is DefaultDataDir/DefaultIPCSocket.
|
||||||
|
// Else this is $ENV{XDG_RUNTIME_DIR}/ethereum/DefaultIPCSocket, if $ENV{XDG_RUNTIME_DIR} is not set,
|
||||||
|
// or the ethereum sub directory could not be created this is DefaultDataDir/DefaultIPCSocket.
|
||||||
|
func DefaultIPCEndpoint() string {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
return DefaultIPCNamedPipe
|
||||||
|
}
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
return filepath.Join(DefaultDataDir(), DefaultIPCSocket)
|
||||||
|
}
|
||||||
|
if dir := os.Getenv("XDG_RUNTIME_DIR"); dir != "" {
|
||||||
|
dir = filepath.Join(dir, "ethereum")
|
||||||
|
// create "ethereum" subdirectory if it doesn't exist
|
||||||
|
if err := os.MkdirAll(dir, 0700); err == nil {
|
||||||
|
return filepath.Join(dir, DefaultIPCSocket)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filepath.Join(DefaultDataDir(), DefaultIPCSocket)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -247,8 +247,17 @@ func (c *Console) Welcome() {
|
||||||
// Print some generic Geth metadata
|
// Print some generic Geth metadata
|
||||||
fmt.Fprintf(c.printer, "Welcome to the Geth JavaScript console!\n\n")
|
fmt.Fprintf(c.printer, "Welcome to the Geth JavaScript console!\n\n")
|
||||||
c.jsre.Run(`
|
c.jsre.Run(`
|
||||||
|
var _network = 'private';
|
||||||
|
switch (eth.getBlock(0).hash.toLowerCase()) {
|
||||||
|
case '0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3':
|
||||||
|
_network = 'mainnet'; break
|
||||||
|
case '0x0cd786a2425d16f152c658316c423e6ce1181e15c3295826d7c9904cba9ce303':
|
||||||
|
_network = 'testnet'; break
|
||||||
|
}
|
||||||
|
|
||||||
console.log("instance: " + web3.version.node);
|
console.log("instance: " + web3.version.node);
|
||||||
console.log("coinbase: " + eth.coinbase);
|
console.log("coinbase: " + eth.coinbase);
|
||||||
|
console.log(" network: " + _network);
|
||||||
console.log("at block: " + eth.blockNumber + " (" + new Date(1000 * eth.getBlock(eth.blockNumber).timestamp) + ")");
|
console.log("at block: " + eth.blockNumber + " (" + new Date(1000 * eth.getBlock(eth.blockNumber).timestamp) + ")");
|
||||||
console.log(" datadir: " + admin.datadir);
|
console.log(" datadir: " + admin.datadir);
|
||||||
`)
|
`)
|
||||||
|
|
|
||||||
|
|
@ -53,11 +53,12 @@ type Config struct {
|
||||||
// in memory.
|
// in memory.
|
||||||
DataDir string
|
DataDir string
|
||||||
|
|
||||||
// IPCPath is the requested location to place the IPC endpoint. If the path is
|
// IPCPath is the requested location to place the IPC endpoint(s). If the path
|
||||||
// a simple file name, it is placed inside the data directory (or on the root
|
// is a simple file name, it is placed inside the data directory (or on the root
|
||||||
// pipe path on Windows), whereas if it's a resolvable path name (absolute or
|
// pipe path on Windows), whereas if it's a resolvable path name (absolute or
|
||||||
// relative), then that specific path is enforced. An empty path disables IPC.
|
// relative), then that specific path is enforced. A nil or empty slice
|
||||||
IPCPath string
|
// disables IPC.
|
||||||
|
IPCPath []string
|
||||||
|
|
||||||
// This field should be a valid secp256k1 private key that will be used for both
|
// This field should be a valid secp256k1 private key that will be used for both
|
||||||
// remote peer identification as well as network traffic encryption. If no key
|
// remote peer identification as well as network traffic encryption. If no key
|
||||||
|
|
@ -138,35 +139,39 @@ type Config struct {
|
||||||
WSModules []string
|
WSModules []string
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPCEndpoint resolves an IPC endpoint based on a configured value, taking into
|
// IPCEndpoints resolves the IPC endpoints based on a configured value, taking into
|
||||||
// account the set data folders as well as the designated platform we're currently
|
// account the set data folders as well as the designated platform we're currently
|
||||||
// running on.
|
// running on.
|
||||||
func (c *Config) IPCEndpoint() string {
|
func (c *Config) IPCEndpoints() []string {
|
||||||
// Short circuit if IPC has not been enabled
|
var endpoints []string
|
||||||
if c.IPCPath == "" {
|
for _, endpoint := range c.IPCPath {
|
||||||
return ""
|
if endpoint == "" {
|
||||||
}
|
endpoints = append(endpoints, "")
|
||||||
// On windows we can only use plain top-level pipes
|
} else if runtime.GOOS == "windows" {
|
||||||
if runtime.GOOS == "windows" {
|
// On windows we can only use plain top-level pipes
|
||||||
if strings.HasPrefix(c.IPCPath, `\\.\pipe\`) {
|
if strings.HasPrefix(endpoint, `\\.\pipe\`) {
|
||||||
return c.IPCPath
|
endpoints = append(endpoints, endpoint)
|
||||||
|
} else {
|
||||||
|
endpoints = append(endpoints, `\\.\pipe\`+endpoint)
|
||||||
|
}
|
||||||
|
} else if filepath.Base(endpoint) == endpoint { // Resolve names into the data directory full paths otherwise
|
||||||
|
if c.DataDir == "" {
|
||||||
|
endpoints = append(endpoints, filepath.Join(os.TempDir(), endpoint))
|
||||||
|
} else {
|
||||||
|
endpoints = append(endpoints, filepath.Join(c.DataDir, endpoint))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
endpoints = append(endpoints, endpoint)
|
||||||
}
|
}
|
||||||
return `\\.\pipe\` + c.IPCPath
|
|
||||||
}
|
}
|
||||||
// Resolve names into the data directory full paths otherwise
|
|
||||||
if filepath.Base(c.IPCPath) == c.IPCPath {
|
return endpoints
|
||||||
if c.DataDir == "" {
|
|
||||||
return filepath.Join(os.TempDir(), c.IPCPath)
|
|
||||||
}
|
|
||||||
return filepath.Join(c.DataDir, c.IPCPath)
|
|
||||||
}
|
|
||||||
return c.IPCPath
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultIPCEndpoint returns the IPC path used by default.
|
// DefaultIPCEndpoint returns the IPC path used by default.
|
||||||
func DefaultIPCEndpoint() string {
|
func DefaultIPCEndpoint() string {
|
||||||
config := &Config{DataDir: common.DefaultDataDir(), IPCPath: common.DefaultIPCSocket}
|
config := &Config{DataDir: common.DefaultDataDir(), IPCPath: []string{common.DefaultIPCEndpoint()}}
|
||||||
return config.IPCEndpoint()
|
return config.IPCEndpoints()[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPEndpoint resolves an HTTP endpoint based on the configured host interface
|
// HTTPEndpoint resolves an HTTP endpoint based on the configured host interface
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ func TestIPCPathResolution(t *testing.T) {
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
// Only run when platform/test match
|
// Only run when platform/test match
|
||||||
if (runtime.GOOS == "windows") == test.Windows {
|
if (runtime.GOOS == "windows") == test.Windows {
|
||||||
if endpoint := (&Config{DataDir: test.DataDir, IPCPath: test.IPCPath}).IPCEndpoint(); endpoint != test.Endpoint {
|
if endpoint := (&Config{DataDir: test.DataDir, IPCPath: []string{test.IPCPath}}).IPCEndpoints()[0]; endpoint != test.Endpoint {
|
||||||
t.Errorf("test %d: IPC endpoint mismatch: have %s, want %s", i, endpoint, test.Endpoint)
|
t.Errorf("test %d: IPC endpoint mismatch: have %s, want %s", i, endpoint, test.Endpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
127
node/node.go
127
node/node.go
|
|
@ -43,6 +43,17 @@ var (
|
||||||
datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
|
datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ipcService struct {
|
||||||
|
endpoint string // endpoints to listen at (empty = IPC disabled)
|
||||||
|
listener net.Listener // RPC listener sockets to serve API requests
|
||||||
|
handler *rpc.Server // RPC request handlers to process the API requests
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ipcService) stop() {
|
||||||
|
s.listener.Close()
|
||||||
|
s.handler.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
// Node represents a P2P node into which arbitrary (uniquely typed) services might
|
// Node represents a P2P node into which arbitrary (uniquely typed) services might
|
||||||
// be registered.
|
// be registered.
|
||||||
type Node struct {
|
type Node struct {
|
||||||
|
|
@ -58,9 +69,7 @@ type Node struct {
|
||||||
rpcAPIs []rpc.API // List of APIs currently provided by the node
|
rpcAPIs []rpc.API // List of APIs currently provided by the node
|
||||||
inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
|
inprocHandler *rpc.Server // In-process RPC request handler to process the API requests
|
||||||
|
|
||||||
ipcEndpoint string // IPC endpoint to listen at (empty = IPC disabled)
|
ipcServices []*ipcService // IPC services
|
||||||
ipcListener net.Listener // IPC RPC listener socket to serve API requests
|
|
||||||
ipcHandler *rpc.Server // IPC RPC request handler to process the API requests
|
|
||||||
|
|
||||||
httpHost string // HTTP hostname
|
httpHost string // HTTP hostname
|
||||||
httpPort int // HTTP post
|
httpPort int // HTTP post
|
||||||
|
|
@ -95,6 +104,12 @@ func New(conf *Config) (*Node, error) {
|
||||||
if conf.DataDir != "" {
|
if conf.DataDir != "" {
|
||||||
nodeDbPath = filepath.Join(conf.DataDir, datadirNodeDatabase)
|
nodeDbPath = filepath.Join(conf.DataDir, datadirNodeDatabase)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ipcServices := make([]*ipcService, len(conf.IPCEndpoints()))
|
||||||
|
for i, endpoint := range conf.IPCEndpoints() {
|
||||||
|
ipcServices[i] = &ipcService{endpoint: endpoint}
|
||||||
|
}
|
||||||
|
|
||||||
return &Node{
|
return &Node{
|
||||||
datadir: conf.DataDir,
|
datadir: conf.DataDir,
|
||||||
serverConfig: p2p.Config{
|
serverConfig: p2p.Config{
|
||||||
|
|
@ -113,7 +128,7 @@ func New(conf *Config) (*Node, error) {
|
||||||
MaxPendingPeers: conf.MaxPendingPeers,
|
MaxPendingPeers: conf.MaxPendingPeers,
|
||||||
},
|
},
|
||||||
serviceFuncs: []ServiceConstructor{},
|
serviceFuncs: []ServiceConstructor{},
|
||||||
ipcEndpoint: conf.IPCEndpoint(),
|
ipcServices: ipcServices,
|
||||||
httpHost: conf.HTTPHost,
|
httpHost: conf.HTTPHost,
|
||||||
httpPort: conf.HTTPPort,
|
httpPort: conf.HTTPPort,
|
||||||
httpEndpoint: conf.HTTPEndpoint(),
|
httpEndpoint: conf.HTTPEndpoint(),
|
||||||
|
|
@ -272,64 +287,65 @@ func (n *Node) stopInProc() {
|
||||||
|
|
||||||
// startIPC initializes and starts the IPC RPC endpoint.
|
// startIPC initializes and starts the IPC RPC endpoint.
|
||||||
func (n *Node) startIPC(apis []rpc.API) error {
|
func (n *Node) startIPC(apis []rpc.API) error {
|
||||||
// Short circuit if the IPC endpoint isn't being exposed
|
for i, _ := range n.ipcServices {
|
||||||
if n.ipcEndpoint == "" {
|
service := n.ipcServices[i]
|
||||||
return nil
|
|
||||||
}
|
// Register all the APIs exposed by the services
|
||||||
// Register all the APIs exposed by the services
|
handler := rpc.NewServer()
|
||||||
handler := rpc.NewServer()
|
|
||||||
for _, api := range apis {
|
for _, api := range apis {
|
||||||
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
|
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
glog.V(logger.Debug).Infof("IPC registered %T under '%s' on '%s'", api.Service, api.Namespace, service.endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
// All APIs registered, start the IPC listener
|
||||||
|
var (
|
||||||
|
listener net.Listener
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if listener, err = rpc.CreateIPCListener(service.endpoint); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
glog.V(logger.Debug).Infof("IPC registered %T under '%s'", api.Service, api.Namespace)
|
|
||||||
}
|
|
||||||
// All APIs registered, start the IPC listener
|
|
||||||
var (
|
|
||||||
listener net.Listener
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
if listener, err = rpc.CreateIPCListener(n.ipcEndpoint); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
glog.V(logger.Info).Infof("IPC endpoint opened: %s", n.ipcEndpoint)
|
|
||||||
|
|
||||||
for {
|
go func() {
|
||||||
conn, err := listener.Accept()
|
glog.V(logger.Info).Infof("IPC endpoint opened: %s", service.endpoint)
|
||||||
if err != nil {
|
|
||||||
// Terminate if the listener was closed
|
for {
|
||||||
n.lock.RLock()
|
conn, err := listener.Accept()
|
||||||
closed := n.ipcListener == nil
|
if err != nil {
|
||||||
n.lock.RUnlock()
|
// Terminate if the listener was closed
|
||||||
if closed {
|
n.lock.RLock()
|
||||||
return
|
closed := service.listener == nil
|
||||||
|
n.lock.RUnlock()
|
||||||
|
if closed {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Not closed, just some error; report and continue
|
||||||
|
glog.V(logger.Error).Infof("IPC accept failed: %v", err)
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
// Not closed, just some error; report and continue
|
go handler.ServeCodec(rpc.NewJSONCodec(conn), rpc.OptionMethodInvocation|rpc.OptionSubscriptions)
|
||||||
glog.V(logger.Error).Infof("IPC accept failed: %v", err)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
go handler.ServeCodec(rpc.NewJSONCodec(conn), rpc.OptionMethodInvocation|rpc.OptionSubscriptions)
|
}()
|
||||||
}
|
|
||||||
}()
|
service.listener = listener
|
||||||
// All listeners booted successfully
|
service.handler = handler
|
||||||
n.ipcListener = listener
|
}
|
||||||
n.ipcHandler = handler
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// stopIPC terminates the IPC RPC endpoint.
|
// stopIPC terminates the IPC RPC endpoint.
|
||||||
func (n *Node) stopIPC() {
|
func (n *Node) stopIPC() {
|
||||||
if n.ipcListener != nil {
|
for _, service := range n.ipcServices {
|
||||||
n.ipcListener.Close()
|
service.listener.Close()
|
||||||
n.ipcListener = nil
|
service.listener = nil
|
||||||
|
service.handler.Stop()
|
||||||
glog.V(logger.Info).Infof("IPC endpoint closed: %s", n.ipcEndpoint)
|
service.handler = nil
|
||||||
}
|
glog.V(logger.Info).Infof("IPC endpoint closed: %s", service.endpoint)
|
||||||
if n.ipcHandler != nil {
|
|
||||||
n.ipcHandler.Stop()
|
|
||||||
n.ipcHandler = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -550,9 +566,12 @@ func (n *Node) DataDir() string {
|
||||||
return n.datadir
|
return n.datadir
|
||||||
}
|
}
|
||||||
|
|
||||||
// IPCEndpoint retrieves the current IPC endpoint used by the protocol stack.
|
// IPCEndpoint retrieves the current IPC endpoints used by the protocol stack.
|
||||||
func (n *Node) IPCEndpoint() string {
|
func (n *Node) IPCEndpoint() (endpoints []string) {
|
||||||
return n.ipcEndpoint
|
for _, service := range n.ipcServices {
|
||||||
|
endpoints = append(endpoints, service.endpoint)
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// HTTPEndpoint retrieves the current HTTP endpoint used by the protocol stack.
|
// HTTPEndpoint retrieves the current HTTP endpoint used by the protocol stack.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue