cmd, node, rpc: readd inproc RPC client, expose via node
This commit is contained in:
@ -89,7 +89,7 @@ func (api *PrivateAdminAPI) StartWS(host string, port int, cors string, apis str
|
||||
defer api.node.lock.Unlock()
|
||||
|
||||
if api.node.wsHandler != nil {
|
||||
return false, fmt.Errorf("WebSocker RPC already running on %s", api.node.wsEndpoint)
|
||||
return false, fmt.Errorf("WebSocket RPC already running on %s", api.node.wsEndpoint)
|
||||
}
|
||||
if err := api.node.startWS(fmt.Sprintf("%s:%d", host, port), api.node.rpcAPIs, strings.Split(apis, ","), cors); err != nil {
|
||||
return false, err
|
||||
|
55
node/node.go
55
node/node.go
@ -55,7 +55,9 @@ type Node struct {
|
||||
serviceFuncs []ServiceConstructor // Service constructors (in dependency order)
|
||||
services map[reflect.Type]Service // Currently running services
|
||||
|
||||
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
|
||||
|
||||
ipcEndpoint string // IPC endpoint to listen at (empty = IPC disabled)
|
||||
ipcListener net.Listener // IPC RPC listener socket to serve API requests
|
||||
ipcHandler *rpc.Server // IPC RPC request handler to process the API requests
|
||||
@ -217,16 +219,22 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
|
||||
apis = append(apis, service.APIs()...)
|
||||
}
|
||||
// Start the various API endpoints, terminating all in case of errors
|
||||
if err := n.startInProc(apis); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := n.startIPC(apis); err != nil {
|
||||
n.stopInProc()
|
||||
return err
|
||||
}
|
||||
if err := n.startHTTP(n.httpEndpoint, apis, n.httpWhitelist, n.httpCors); err != nil {
|
||||
n.stopIPC()
|
||||
n.stopInProc()
|
||||
return err
|
||||
}
|
||||
if err := n.startWS(n.wsEndpoint, apis, n.wsWhitelist, n.wsDomains); err != nil {
|
||||
n.stopHTTP()
|
||||
n.stopIPC()
|
||||
n.stopInProc()
|
||||
return err
|
||||
}
|
||||
// All API endpoints started successfully
|
||||
@ -234,6 +242,28 @@ func (n *Node) startRPC(services map[reflect.Type]Service) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// startInProc initializes an in-process RPC endpoint.
|
||||
func (n *Node) startInProc(apis []rpc.API) error {
|
||||
// Register all the APIs exposed by the services
|
||||
handler := rpc.NewServer()
|
||||
for _, api := range apis {
|
||||
if err := handler.RegisterName(api.Namespace, api.Service); err != nil {
|
||||
return err
|
||||
}
|
||||
glog.V(logger.Debug).Infof("InProc registered %T under '%s'", api.Service, api.Namespace)
|
||||
}
|
||||
n.inprocHandler = handler
|
||||
return nil
|
||||
}
|
||||
|
||||
// stopInProc terminates the in-process RPC endpoint.
|
||||
func (n *Node) stopInProc() {
|
||||
if n.inprocHandler != nil {
|
||||
n.inprocHandler.Stop()
|
||||
n.inprocHandler = nil
|
||||
}
|
||||
}
|
||||
|
||||
// startIPC initializes and starts the IPC RPC endpoint.
|
||||
func (n *Node) startIPC(apis []rpc.API) error {
|
||||
// Short circuit if the IPC endpoint isn't being exposed
|
||||
@ -468,6 +498,19 @@ func (n *Node) Restart() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Attach creates an RPC client attached to an in-process API handler.
|
||||
func (n *Node) Attach() (rpc.Client, error) {
|
||||
n.lock.RLock()
|
||||
defer n.lock.RUnlock()
|
||||
|
||||
// Short circuit if the node's not running
|
||||
if n.server == nil {
|
||||
return nil, ErrNodeStopped
|
||||
}
|
||||
// Otherwise attach to the API and return
|
||||
return rpc.NewInProcRPCClient(n.inprocHandler), nil
|
||||
}
|
||||
|
||||
// Server retrieves the currently running P2P network layer. This method is meant
|
||||
// only to inspect fields of the currently running server, life cycle management
|
||||
// should be left to this Node entity.
|
||||
@ -506,6 +549,16 @@ func (n *Node) IPCEndpoint() string {
|
||||
return n.ipcEndpoint
|
||||
}
|
||||
|
||||
// HTTPEndpoint retrieves the current HTTP endpoint used by the protocol stack.
|
||||
func (n *Node) HTTPEndpoint() string {
|
||||
return n.httpEndpoint
|
||||
}
|
||||
|
||||
// WSEndpoint retrieves the current WS endpoint used by the protocol stack.
|
||||
func (n *Node) WSEndpoint() string {
|
||||
return n.wsEndpoint
|
||||
}
|
||||
|
||||
// EventMux retrieves the event multiplexer used by all the network services in
|
||||
// the current protocol stack.
|
||||
func (n *Node) EventMux() *event.TypeMux {
|
||||
|
@ -18,9 +18,7 @@ package node
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
@ -37,7 +35,6 @@ var (
|
||||
|
||||
func testNodeConfig() *Config {
|
||||
return &Config{
|
||||
IPCPath: fmt.Sprintf("test-%d.ipc", rand.Int63()),
|
||||
PrivateKey: testNodeKey,
|
||||
Name: "test node",
|
||||
}
|
||||
@ -541,10 +538,11 @@ func TestAPIGather(t *testing.T) {
|
||||
defer stack.Stop()
|
||||
|
||||
// Connect to the RPC server and verify the various registered endpoints
|
||||
ipcClient, err := rpc.NewIPCClient(stack.IPCEndpoint())
|
||||
client, err := stack.Attach()
|
||||
if err != nil {
|
||||
t.Fatalf("failed to connect to the IPC API server: %v", err)
|
||||
t.Fatalf("failed to connect to the inproc API server: %v", err)
|
||||
}
|
||||
defer client.Close()
|
||||
|
||||
tests := []struct {
|
||||
Method string
|
||||
@ -556,11 +554,11 @@ func TestAPIGather(t *testing.T) {
|
||||
{"multi.v2.nested_theOneMethod", "multi.v2.nested"},
|
||||
}
|
||||
for i, test := range tests {
|
||||
if err := ipcClient.Send(rpc.JSONRequest{Id: new(int64), Version: "2.0", Method: test.Method}); err != nil {
|
||||
if err := client.Send(rpc.JSONRequest{Id: new(int64), Version: "2.0", Method: test.Method}); err != nil {
|
||||
t.Fatalf("test %d: failed to send API request: %v", i, err)
|
||||
}
|
||||
reply := new(rpc.JSONSuccessResponse)
|
||||
if err := ipcClient.Recv(reply); err != nil {
|
||||
if err := client.Recv(reply); err != nil {
|
||||
t.Fatalf("test %d: failed to read API reply: %v", i, err)
|
||||
}
|
||||
select {
|
||||
|
Reference in New Issue
Block a user