github.com/pokt-network/tendermint@v0.32.11-0.20230426215212-59310158d3e9/privval/signer_listener_endpoint.go (about)

     1  package privval
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/tendermint/tendermint/libs/log"
    10  	"github.com/tendermint/tendermint/libs/service"
    11  )
    12  
    13  // SignerValidatorEndpointOption sets an optional parameter on the SocketVal.
    14  type SignerValidatorEndpointOption func(*SignerListenerEndpoint)
    15  
    16  // SignerListenerEndpoint listens for an external process to dial in
    17  // and keeps the connection alive by dropping and reconnecting
    18  type SignerListenerEndpoint struct {
    19  	signerEndpoint
    20  
    21  	listener              net.Listener
    22  	connectRequestCh      chan struct{}
    23  	connectionAvailableCh chan net.Conn
    24  
    25  	timeoutAccept time.Duration
    26  	pingTimer     *time.Ticker
    27  
    28  	instanceMtx sync.Mutex // Ensures instance public methods access, i.e. SendRequest
    29  }
    30  
    31  // NewSignerListenerEndpoint returns an instance of SignerListenerEndpoint.
    32  func NewSignerListenerEndpoint(
    33  	logger log.Logger,
    34  	listener net.Listener,
    35  ) *SignerListenerEndpoint {
    36  	sc := &SignerListenerEndpoint{
    37  		listener:      listener,
    38  		timeoutAccept: defaultTimeoutAcceptSeconds * time.Second,
    39  	}
    40  
    41  	sc.BaseService = *service.NewBaseService(logger, "SignerListenerEndpoint", sc)
    42  	sc.signerEndpoint.timeoutReadWrite = defaultTimeoutReadWriteSeconds * time.Second
    43  	return sc
    44  }
    45  
    46  // OnStart implements service.Service.
    47  func (sl *SignerListenerEndpoint) OnStart() error {
    48  	sl.connectRequestCh = make(chan struct{})
    49  	sl.connectionAvailableCh = make(chan net.Conn)
    50  
    51  	sl.pingTimer = time.NewTicker(defaultPingPeriodMilliseconds * time.Millisecond)
    52  
    53  	go sl.serviceLoop()
    54  	go sl.pingLoop()
    55  
    56  	sl.connectRequestCh <- struct{}{}
    57  
    58  	return nil
    59  }
    60  
    61  // OnStop implements service.Service
    62  func (sl *SignerListenerEndpoint) OnStop() {
    63  	sl.instanceMtx.Lock()
    64  	defer sl.instanceMtx.Unlock()
    65  	_ = sl.Close()
    66  
    67  	// Stop listening
    68  	if sl.listener != nil {
    69  		if err := sl.listener.Close(); err != nil {
    70  			sl.Logger.Error("Closing Listener", "err", err)
    71  			sl.listener = nil
    72  		}
    73  	}
    74  
    75  	sl.pingTimer.Stop()
    76  }
    77  
    78  // WaitForConnection waits maxWait for a connection or returns a timeout error
    79  func (sl *SignerListenerEndpoint) WaitForConnection(maxWait time.Duration) error {
    80  	sl.instanceMtx.Lock()
    81  	defer sl.instanceMtx.Unlock()
    82  	return sl.ensureConnection(maxWait)
    83  }
    84  
    85  // SendRequest ensures there is a connection, sends a request and waits for a response
    86  func (sl *SignerListenerEndpoint) SendRequest(request SignerMessage) (SignerMessage, error) {
    87  	sl.instanceMtx.Lock()
    88  	defer sl.instanceMtx.Unlock()
    89  
    90  	err := sl.ensureConnection(sl.timeoutAccept)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	err = sl.WriteMessage(request)
    96  	if err != nil {
    97  		return nil, err
    98  	}
    99  
   100  	res, err := sl.ReadMessage()
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  
   105  	return res, nil
   106  }
   107  
   108  func (sl *SignerListenerEndpoint) ensureConnection(maxWait time.Duration) error {
   109  	if sl.IsConnected() {
   110  		return nil
   111  	}
   112  
   113  	// Is there a connection ready? then use it
   114  	if sl.GetAvailableConnection(sl.connectionAvailableCh) {
   115  		return nil
   116  	}
   117  
   118  	// block until connected or timeout
   119  	sl.triggerConnect()
   120  	err := sl.WaitConnection(sl.connectionAvailableCh, maxWait)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func (sl *SignerListenerEndpoint) acceptNewConnection() (net.Conn, error) {
   129  	if !sl.IsRunning() || sl.listener == nil {
   130  		return nil, fmt.Errorf("endpoint is closing")
   131  	}
   132  
   133  	// wait for a new conn
   134  	sl.Logger.Info("SignerListener: Listening for new connection")
   135  	conn, err := sl.listener.Accept()
   136  	if err != nil {
   137  		return nil, err
   138  	}
   139  
   140  	return conn, nil
   141  }
   142  
   143  func (sl *SignerListenerEndpoint) triggerConnect() {
   144  	select {
   145  	case sl.connectRequestCh <- struct{}{}:
   146  	default:
   147  	}
   148  }
   149  
   150  func (sl *SignerListenerEndpoint) triggerReconnect() {
   151  	sl.DropConnection()
   152  	sl.triggerConnect()
   153  }
   154  
   155  func (sl *SignerListenerEndpoint) serviceLoop() {
   156  	for {
   157  		select {
   158  		case <-sl.connectRequestCh:
   159  			{
   160  				conn, err := sl.acceptNewConnection()
   161  				if err == nil {
   162  					sl.Logger.Info("SignerListener: Connected")
   163  
   164  					// We have a good connection, wait for someone that needs one otherwise cancellation
   165  					select {
   166  					case sl.connectionAvailableCh <- conn:
   167  					case <-sl.Quit():
   168  						return
   169  					}
   170  				}
   171  
   172  				select {
   173  				case sl.connectRequestCh <- struct{}{}:
   174  				default:
   175  				}
   176  			}
   177  		case <-sl.Quit():
   178  			return
   179  		}
   180  	}
   181  }
   182  
   183  func (sl *SignerListenerEndpoint) pingLoop() {
   184  	for {
   185  		select {
   186  		case <-sl.pingTimer.C:
   187  			{
   188  				_, err := sl.SendRequest(&PingRequest{})
   189  				if err != nil {
   190  					sl.Logger.Error("SignerListener: Ping timeout")
   191  					sl.triggerReconnect()
   192  				}
   193  			}
   194  		case <-sl.Quit():
   195  			return
   196  		}
   197  	}
   198  }