|
|
- package privval
-
- import (
- "net"
- "time"
-
- cmn "github.com/tendermint/tendermint/libs/common"
- "github.com/tendermint/tendermint/libs/log"
- "github.com/tendermint/tendermint/types"
- )
-
- // IPCValOption sets an optional parameter on the SocketPV.
- type IPCValOption func(*IPCVal)
-
- // IPCValConnTimeout sets the read and write timeout for connections
- // from external signing processes.
- func IPCValConnTimeout(timeout time.Duration) IPCValOption {
- return func(sc *IPCVal) { sc.connTimeout = timeout }
- }
-
- // IPCValHeartbeat sets the period on which to check the liveness of the
- // connected Signer connections.
- func IPCValHeartbeat(period time.Duration) IPCValOption {
- return func(sc *IPCVal) { sc.connHeartbeat = period }
- }
-
- // IPCVal implements PrivValidator, it uses a unix socket to request signatures
- // from an external process.
- type IPCVal struct {
- cmn.BaseService
- *RemoteSignerClient
-
- addr string
-
- connTimeout time.Duration
- connHeartbeat time.Duration
-
- conn net.Conn
- cancelPing chan struct{}
- pingTicker *time.Ticker
- }
-
- // Check that IPCVal implements PrivValidator.
- var _ types.PrivValidator = (*IPCVal)(nil)
-
- // NewIPCVal returns an instance of IPCVal.
- func NewIPCVal(
- logger log.Logger,
- socketAddr string,
- ) *IPCVal {
- sc := &IPCVal{
- addr: socketAddr,
- connTimeout: connTimeout,
- connHeartbeat: connHeartbeat,
- }
-
- sc.BaseService = *cmn.NewBaseService(logger, "IPCVal", sc)
-
- return sc
- }
-
- // OnStart implements cmn.Service.
- func (sc *IPCVal) OnStart() error {
- err := sc.connect()
- if err != nil {
- sc.Logger.Error("OnStart", "err", err)
- return err
- }
-
- sc.RemoteSignerClient = NewRemoteSignerClient(sc.conn)
-
- // Start a routine to keep the connection alive
- sc.cancelPing = make(chan struct{}, 1)
- sc.pingTicker = time.NewTicker(sc.connHeartbeat)
- go func() {
- for {
- select {
- case <-sc.pingTicker.C:
- err := sc.Ping()
- if err != nil {
- sc.Logger.Error("Ping", "err", err)
- }
- case <-sc.cancelPing:
- sc.pingTicker.Stop()
- return
- }
- }
- }()
-
- return nil
- }
-
- // OnStop implements cmn.Service.
- func (sc *IPCVal) OnStop() {
- if sc.cancelPing != nil {
- close(sc.cancelPing)
- }
-
- if sc.conn != nil {
- if err := sc.conn.Close(); err != nil {
- sc.Logger.Error("OnStop", "err", err)
- }
- }
- }
-
- func (sc *IPCVal) connect() error {
- la, err := net.ResolveUnixAddr("unix", sc.addr)
- if err != nil {
- return err
- }
-
- conn, err := net.DialUnix("unix", nil, la)
- if err != nil {
- return err
- }
-
- sc.conn = newTimeoutConn(conn, sc.connTimeout)
-
- return nil
- }
|