From eae81465c1c815c317cd30e4de6bdf4d59df2340 Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Thu, 15 Oct 2015 16:07:19 +0200 Subject: rpc: new RPC implementation with pub/sub support --- cmd/utils/api.go | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ cmd/utils/flags.go | 52 ++++++++++++++++++++++++++++++++++---- 2 files changed, 121 insertions(+), 5 deletions(-) create mode 100644 cmd/utils/api.go (limited to 'cmd/utils') diff --git a/cmd/utils/api.go b/cmd/utils/api.go new file mode 100644 index 000000000..59f0dab74 --- /dev/null +++ b/cmd/utils/api.go @@ -0,0 +1,74 @@ +// Copyright 2015 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package utils + +import ( + "fmt" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/node" + "github.com/ethereum/go-ethereum/p2p" + rpc "github.com/ethereum/go-ethereum/rpc/v2" +) + +// PublicWeb3API offers helper utils +type PublicWeb3API struct { + stack *node.Node +} + +// NewPublicWeb3API creates a new Web3Service instance +func NewPublicWeb3API(stack *node.Node) *PublicWeb3API { + return &PublicWeb3API{stack} +} + +// ClientVersion returns the node name +func (s *PublicWeb3API) ClientVersion() string { + return s.stack.Server().Name +} + +// Sha3 applies the ethereum sha3 implementation on the input. +// It assumes the input is hex encoded. +func (s *PublicWeb3API) Sha3(input string) string { + return common.ToHex(crypto.Sha3(common.FromHex(input))) +} + +// PublicNetAPI offers network related RPC methods +type PublicNetAPI struct { + net *p2p.Server + networkVersion int +} + +// NewPublicNetAPI creates a new net api instance. +func NewPublicNetAPI(net *p2p.Server, networkVersion int) *PublicNetAPI { + return &PublicNetAPI{net, networkVersion} +} + +// Listening returns an indication if the node is listening for network connections. +func (s *PublicNetAPI) Listening() bool { + return true // always listening +} + +// Peercount returns the number of connected peers +func (s *PublicNetAPI) PeerCount() *rpc.HexNumber { + return rpc.NewHexNumber(s.net.PeerCount()) +} + +// ProtocolVersion returns the current ethereum protocol version. +func (s *PublicNetAPI) Version() string { + return fmt.Sprintf("%d", s.networkVersion) +} diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 839ec3f02..1aa8f4e89 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -54,6 +54,7 @@ import ( "github.com/ethereum/go-ethereum/rpc/comms" "github.com/ethereum/go-ethereum/rpc/shared" "github.com/ethereum/go-ethereum/rpc/useragent" + rpc "github.com/ethereum/go-ethereum/rpc/v2" "github.com/ethereum/go-ethereum/whisper" "github.com/ethereum/go-ethereum/xeth" ) @@ -300,6 +301,10 @@ var ( Usage: "Filename for IPC socket/pipe", Value: DirectoryString{common.DefaultIpcPath()}, } + IPCExperimental = cli.BoolFlag{ + Name: "ipcexp", + Usage: "Enable the new RPC implementation", + } ExecFlag = cli.StringFlag{ Name: "exec", Usage: "Execute JavaScript statement (only in combination with console/attach)", @@ -690,6 +695,7 @@ func MakeSystemNode(name, version string, extra []byte, ctx *cli.Context) *node. Fatalf("Failed to register the Whisper service: %v", err) } } + return stack } @@ -773,17 +779,53 @@ func IpcSocketPath(ctx *cli.Context) (ipcpath string) { return } -// StartIPC starts a IPC JSON-RPC API server. func StartIPC(stack *node.Node, ctx *cli.Context) error { config := comms.IpcConfig{ Endpoint: IpcSocketPath(ctx), } - initializer := func(conn net.Conn) (comms.Stopper, shared.EthereumApi, error) { - var ethereum *eth.Ethereum - if err := stack.Service(ðereum); err != nil { - return nil, nil, err + var ethereum *eth.Ethereum + if err := stack.Service(ðereum); err != nil { + return err + } + + if ctx.GlobalIsSet(IPCExperimental.Name) { + listener, err := comms.CreateListener(config) + if err != nil { + return err + } + + server := rpc.NewServer() + + // register package API's this node provides + offered := stack.RPCAPIs() + for _, api := range offered { + server.RegisterName(api.Namespace, api.Service) + glog.V(logger.Debug).Infof("Register %T under namespace '%s' for IPC service\n", api.Service, api.Namespace) } + + web3 := NewPublicWeb3API(stack) + server.RegisterName("web3", web3) + net := NewPublicNetAPI(stack.Server(), ethereum.NetVersion()) + server.RegisterName("net", net) + + go func() { + glog.V(logger.Info).Infof("Start IPC server on %s\n", config.Endpoint) + for { + conn, err := listener.Accept() + if err != nil { + glog.V(logger.Error).Infof("Unable to accept connection - %v\n", err) + } + + codec := rpc.NewJSONCodec(conn) + go server.ServeCodec(codec) + } + }() + + return nil + } + + initializer := func(conn net.Conn) (comms.Stopper, shared.EthereumApi, error) { fe := useragent.NewRemoteFrontend(conn, ethereum.AccountManager()) xeth := xeth.New(stack, fe) apis, err := api.ParseApiString(ctx.GlobalString(IPCApiFlag.Name), codec.JSON, xeth, stack) -- cgit