aboutsummaryrefslogtreecommitdiffstats
path: root/rpc/comms
diff options
context:
space:
mode:
Diffstat (limited to 'rpc/comms')
-rw-r--r--rpc/comms/comms.go27
-rw-r--r--rpc/comms/http.go3
-rw-r--r--rpc/comms/inproc.go18
-rw-r--r--rpc/comms/ipc.go68
-rw-r--r--rpc/comms/ipc_unix.go12
-rw-r--r--rpc/comms/ipc_windows.go10
6 files changed, 128 insertions, 10 deletions
diff --git a/rpc/comms/comms.go b/rpc/comms/comms.go
index 050e7b4e2..7aa94b1ea 100644
--- a/rpc/comms/comms.go
+++ b/rpc/comms/comms.go
@@ -4,12 +4,14 @@ import (
"io"
"net"
+ "fmt"
+ "strings"
+
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
"github.com/ethereum/go-ethereum/rpc/shared"
- "strings"
)
const (
@@ -26,7 +28,7 @@ var (
// List with API's which are offered over thr HTTP/RPC interface by default
DefaultHttpRpcApis = strings.Join([]string{
api.DbApiName, api.EthApiName, api.NetApiName, api.Web3ApiName,
- }, ",")
+ }, ",")
)
type EthereumClient interface {
@@ -36,6 +38,8 @@ type EthereumClient interface {
Send(interface{}) error
// Receive response
Recv() (interface{}, error)
+ // List with modules this client supports
+ SupportedModules() (map[string]string, error)
}
func handle(conn net.Conn, api api.EthereumApi, c codec.Codec) {
@@ -64,3 +68,22 @@ func handle(conn net.Conn, api api.EthereumApi, c codec.Codec) {
}
}
}
+
+// Endpoint must be in the form of:
+// ${protocol}:${path}
+// e.g. ipc:/tmp/geth.ipc
+// rpc:localhost:8545
+func ClientFromEndpoint(endpoint string, c codec.Codec) (EthereumClient, error) {
+ if strings.HasPrefix(endpoint, "ipc:") {
+ cfg := IpcConfig{
+ Endpoint: endpoint[4:],
+ }
+ return NewIpcClient(cfg, codec.JSON)
+ }
+
+ if strings.HasPrefix(endpoint, "rpc:") {
+
+ }
+
+ return nil, fmt.Errorf("Invalid endpoint")
+}
diff --git a/rpc/comms/http.go b/rpc/comms/http.go
index c0ea2cc78..04630d937 100644
--- a/rpc/comms/http.go
+++ b/rpc/comms/http.go
@@ -64,7 +64,6 @@ func StopHttp() {
}
}
-
type httpClient struct {
codec codec.ApiCoder
}
@@ -86,4 +85,4 @@ func (self *httpClient) Send(req interface{}) error {
func (self *httpClient) Recv() (interface{}, error) {
return nil, nil
-} \ No newline at end of file
+}
diff --git a/rpc/comms/inproc.go b/rpc/comms/inproc.go
index 1fdbf8ace..b9c4e93d9 100644
--- a/rpc/comms/inproc.go
+++ b/rpc/comms/inproc.go
@@ -51,3 +51,21 @@ func (self *InProcClient) Send(req interface{}) error {
func (self *InProcClient) Recv() (interface{}, error) {
return self.lastRes, self.lastErr
}
+
+func (self *InProcClient) SupportedModules() (map[string]string, error) {
+ req := shared.Request{
+ Id: 1,
+ Jsonrpc: "2.0",
+ Method: "modules",
+ }
+
+ if res, err := self.api.Execute(&req); err == nil {
+ if result, ok := res.(map[string]string); ok {
+ return result, nil
+ }
+ } else {
+ return nil, err
+ }
+
+ return nil, fmt.Errorf("Invalid response")
+}
diff --git a/rpc/comms/ipc.go b/rpc/comms/ipc.go
index a07203803..7e7375eaf 100644
--- a/rpc/comms/ipc.go
+++ b/rpc/comms/ipc.go
@@ -1,8 +1,13 @@
package comms
import (
+ "fmt"
+ "net"
+
"github.com/ethereum/go-ethereum/rpc/api"
"github.com/ethereum/go-ethereum/rpc/codec"
+ "github.com/ethereum/go-ethereum/rpc/shared"
+ "encoding/json"
)
type IpcConfig struct {
@@ -10,19 +15,74 @@ type IpcConfig struct {
}
type ipcClient struct {
- codec codec.ApiCoder
+ endpoint string
+ codec codec.Codec
+ coder codec.ApiCoder
}
func (self *ipcClient) Close() {
- self.codec.Close()
+ self.coder.Close()
}
func (self *ipcClient) Send(req interface{}) error {
- return self.codec.WriteResponse(req)
+ var err error
+ if r, ok := req.(*shared.Request); ok {
+ if err = self.coder.WriteResponse(r); err != nil {
+ if _, ok := err.(*net.OpError); ok { // connection lost, retry once
+ if err = self.reconnect(); err == nil {
+ err = self.coder.WriteResponse(r)
+ }
+ }
+ }
+ return err
+ }
+
+ return fmt.Errorf("Invalid request (%T)", req)
}
func (self *ipcClient) Recv() (interface{}, error) {
- return self.codec.ReadResponse()
+ res, err := self.coder.ReadResponse()
+ if err != nil {
+ return nil, err
+ }
+
+ if r, ok := res.(shared.SuccessResponse); ok {
+ return r.Result, nil
+ }
+
+ if r, ok := res.(shared.ErrorResponse); ok {
+ return r.Error, nil
+ }
+
+ return res, err
+}
+
+func (self *ipcClient) SupportedModules() (map[string]string, error) {
+ req := shared.Request{
+ Id: 1,
+ Jsonrpc: "2.0",
+ Method: "modules",
+ }
+
+ if err := self.coder.WriteResponse(req); err != nil {
+ return nil, err
+ }
+
+ res, err := self.coder.ReadResponse()
+ if err != nil {
+ return nil, err
+ }
+
+ if sucRes, ok := res.(shared.SuccessResponse); ok {
+ data, _ := json.Marshal(sucRes.Result)
+ modules := make(map[string]string)
+ err = json.Unmarshal(data, &modules)
+ if err == nil {
+ return modules, nil
+ }
+ }
+
+ return nil, fmt.Errorf("Invalid response")
}
// Create a new IPC client, UNIX domain socket on posix, named pipe on Windows
diff --git a/rpc/comms/ipc_unix.go b/rpc/comms/ipc_unix.go
index 131fb86f2..b5eec92db 100644
--- a/rpc/comms/ipc_unix.go
+++ b/rpc/comms/ipc_unix.go
@@ -18,7 +18,17 @@ func newIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
return nil, err
}
- return &ipcClient{codec.New(c)}, nil
+ return &ipcClient{cfg.Endpoint, codec, codec.New(c)}, nil
+}
+
+func (self *ipcClient) reconnect() error {
+ self.coder.Close()
+ c, err := net.DialUnix("unix", nil, &net.UnixAddr{self.endpoint, "unix"})
+ if err == nil {
+ self.coder = self.codec.New(c)
+ }
+
+ return err
}
func startIpc(cfg IpcConfig, codec codec.Codec, api api.EthereumApi) error {
diff --git a/rpc/comms/ipc_windows.go b/rpc/comms/ipc_windows.go
index c48dfb7fb..08f79274a 100644
--- a/rpc/comms/ipc_windows.go
+++ b/rpc/comms/ipc_windows.go
@@ -641,7 +641,15 @@ func newIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
return nil, err
}
- return &ipcClient{codec.New(c)}, nil
+ return &ipcClient{cfg.Endpoint, codec, codec.New(c)}, nil
+}
+
+func (self *ipcClient) reconnect() error {
+ c, err := Dial(self.endpoint)
+ if err == nil {
+ self.coder = self.codec.New(c)
+ }
+ return err
}
func startIpc(cfg IpcConfig, codec codec.Codec, api api.EthereumApi) error {