|
|
- package privval
-
- import (
- "io"
- "net"
- "time"
-
- cmn "github.com/tendermint/tendermint/libs/common"
- "github.com/tendermint/tendermint/libs/log"
- "github.com/tendermint/tendermint/types"
- )
-
- // IPCRemoteSignerOption sets an optional parameter on the IPCRemoteSigner.
- type IPCRemoteSignerOption func(*IPCRemoteSigner)
-
- // IPCRemoteSignerConnDeadline sets the read and write deadline for connections
- // from external signing processes.
- func IPCRemoteSignerConnDeadline(deadline time.Duration) IPCRemoteSignerOption {
- return func(ss *IPCRemoteSigner) { ss.connDeadline = deadline }
- }
-
- // IPCRemoteSignerConnRetries sets the amount of attempted retries to connect.
- func IPCRemoteSignerConnRetries(retries int) IPCRemoteSignerOption {
- return func(ss *IPCRemoteSigner) { ss.connRetries = retries }
- }
-
- // IPCRemoteSigner is a RPC implementation of PrivValidator that listens on a unix socket.
- type IPCRemoteSigner struct {
- cmn.BaseService
-
- addr string
- chainID string
- connDeadline time.Duration
- connRetries int
- privVal types.PrivValidator
-
- listener *net.UnixListener
- }
-
- // NewIPCRemoteSigner returns an instance of IPCRemoteSigner.
- func NewIPCRemoteSigner(
- logger log.Logger,
- chainID, socketAddr string,
- privVal types.PrivValidator,
- ) *IPCRemoteSigner {
- rs := &IPCRemoteSigner{
- addr: socketAddr,
- chainID: chainID,
- connDeadline: time.Second * defaultConnDeadlineSeconds,
- connRetries: defaultDialRetries,
- privVal: privVal,
- }
-
- rs.BaseService = *cmn.NewBaseService(logger, "IPCRemoteSigner", rs)
-
- return rs
- }
-
- // OnStart implements cmn.Service.
- func (rs *IPCRemoteSigner) OnStart() error {
- err := rs.listen()
- if err != nil {
- err = cmn.ErrorWrap(err, "listen")
- rs.Logger.Error("OnStart", "err", err)
- return err
- }
-
- go func() {
- for {
- conn, err := rs.listener.AcceptUnix()
- if err != nil {
- return
- }
- go rs.handleConnection(conn)
- }
- }()
-
- return nil
- }
-
- // OnStop implements cmn.Service.
- func (rs *IPCRemoteSigner) OnStop() {
- if rs.listener != nil {
- if err := rs.listener.Close(); err != nil {
- rs.Logger.Error("OnStop", "err", cmn.ErrorWrap(err, "closing listener failed"))
- }
- }
- }
-
- func (rs *IPCRemoteSigner) listen() error {
- la, err := net.ResolveUnixAddr("unix", rs.addr)
- if err != nil {
- return err
- }
-
- rs.listener, err = net.ListenUnix("unix", la)
-
- return err
- }
-
- func (rs *IPCRemoteSigner) handleConnection(conn net.Conn) {
- for {
- if !rs.IsRunning() {
- return // Ignore error from listener closing.
- }
-
- // Reset the connection deadline
- conn.SetDeadline(time.Now().Add(rs.connDeadline))
-
- req, err := readMsg(conn)
- if err != nil {
- if err != io.EOF {
- rs.Logger.Error("handleConnection", "err", err)
- }
- return
- }
-
- res, err := handleRequest(req, rs.chainID, rs.privVal)
-
- if err != nil {
- // only log the error; we'll reply with an error in res
- rs.Logger.Error("handleConnection", "err", err)
- }
-
- err = writeMsg(conn, res)
- if err != nil {
- rs.Logger.Error("handleConnection", "err", err)
- return
- }
- }
- }
|