go-ethereum/rpc/comms/ipc.go

139 lines
3.3 KiB
Go
Raw Normal View History

2015-07-07 03:54:22 +03:00
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
2015-07-07 03:54:22 +03:00
//
// The go-ethereum library is free software: you can redistribute it and/or modify
2015-07-07 03:54:22 +03:00
// 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,
2015-07-07 03:54:22 +03:00
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2015-07-07 03:54:22 +03:00
// 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 <http://www.gnu.org/licenses/>.
2015-07-07 03:54:22 +03:00
2015-06-08 11:41:04 +03:00
package comms
import (
2015-06-18 19:23:13 +03:00
"fmt"
"math/rand"
2015-06-18 19:23:13 +03:00
"net"
"os"
2015-06-18 19:23:13 +03:00
2015-06-19 13:32:40 +03:00
"encoding/json"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
2015-06-08 11:41:04 +03:00
"github.com/ethereum/go-ethereum/rpc/codec"
2015-06-18 19:23:13 +03:00
"github.com/ethereum/go-ethereum/rpc/shared"
2015-06-08 11:41:04 +03:00
)
type Stopper interface {
Stop()
}
type InitFunc func(conn net.Conn) (Stopper, shared.EthereumApi, error)
2015-06-08 11:41:04 +03:00
type IpcConfig struct {
Endpoint string
}
type ipcClient struct {
2015-06-18 19:23:13 +03:00
endpoint string
2015-06-25 14:18:10 +03:00
c net.Conn
2015-06-18 19:23:13 +03:00
codec codec.Codec
coder codec.ApiCoder
2015-06-08 11:41:04 +03:00
}
func (self *ipcClient) Close() {
2015-06-18 19:23:13 +03:00
self.coder.Close()
2015-06-08 11:41:04 +03:00
}
2015-08-24 13:22:12 +03:00
func (self *ipcClient) Send(msg interface{}) error {
2015-06-18 19:23:13 +03:00
var err error
2015-08-24 13:22:12 +03:00
if err = self.coder.WriteResponse(msg); err != nil {
if err = self.reconnect(); err == nil {
err = self.coder.WriteResponse(msg)
2015-06-18 19:23:13 +03:00
}
}
2015-08-07 10:56:49 +03:00
return err
2015-06-08 11:41:04 +03:00
}
func (self *ipcClient) Recv() (interface{}, error) {
2015-08-07 10:56:49 +03:00
return self.coder.ReadResponse()
2015-06-18 19:23:13 +03:00
}
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
}
2015-08-07 10:56:49 +03:00
if sucRes, ok := res.(*shared.SuccessResponse); ok {
2015-06-18 19:23:13 +03:00
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")
2015-06-08 11:41:04 +03:00
}
// Create a new IPC client, UNIX domain socket on posix, named pipe on Windows
func NewIpcClient(cfg IpcConfig, codec codec.Codec) (*ipcClient, error) {
return newIpcClient(cfg, codec)
}
// Start IPC server
func StartIpc(cfg IpcConfig, codec codec.Codec, initializer InitFunc) error {
l, err := ipcListen(cfg)
if err != nil {
return err
}
go ipcLoop(cfg, codec, initializer, l)
return nil
}
func ipcLoop(cfg IpcConfig, codec codec.Codec, initializer InitFunc, l net.Listener) {
glog.V(logger.Info).Infof("IPC service started (%s)\n", cfg.Endpoint)
defer os.Remove(cfg.Endpoint)
defer l.Close()
for {
conn, err := l.Accept()
if err != nil {
glog.V(logger.Debug).Infof("accept: %v", err)
return
}
id := newIpcConnId()
go func() {
defer conn.Close()
glog.V(logger.Debug).Infof("new connection with id %06d started", id)
stopper, api, err := initializer(conn)
if err != nil {
glog.V(logger.Error).Infof("Unable to initialize IPC connection: %v", err)
return
}
defer stopper.Stop()
handle(id, conn, api, codec)
}()
}
2015-06-08 11:41:04 +03:00
}
func newIpcConnId() int {
return rand.Int() % 1000000
}