github.com/okex/exchain@v1.8.0/libs/tendermint/privval/signer_endpoint.go (about)

     1  package privval
     2  
     3  import (
     4  	"fmt"
     5  	"net"
     6  	"sync"
     7  	"time"
     8  
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/okex/exchain/libs/tendermint/libs/service"
    12  )
    13  
    14  const (
    15  	defaultTimeoutReadWriteSeconds = 5
    16  )
    17  
    18  type signerEndpoint struct {
    19  	service.BaseService
    20  
    21  	connMtx sync.Mutex
    22  	conn    net.Conn
    23  
    24  	timeoutReadWrite time.Duration
    25  }
    26  
    27  // Close closes the underlying net.Conn.
    28  func (se *signerEndpoint) Close() error {
    29  	se.DropConnection()
    30  	return nil
    31  }
    32  
    33  // IsConnected indicates if there is an active connection
    34  func (se *signerEndpoint) IsConnected() bool {
    35  	se.connMtx.Lock()
    36  	defer se.connMtx.Unlock()
    37  	return se.isConnected()
    38  }
    39  
    40  // TryGetConnection retrieves a connection if it is already available
    41  func (se *signerEndpoint) GetAvailableConnection(connectionAvailableCh chan net.Conn) bool {
    42  	se.connMtx.Lock()
    43  	defer se.connMtx.Unlock()
    44  
    45  	// Is there a connection ready?
    46  	select {
    47  	case se.conn = <-connectionAvailableCh:
    48  		return true
    49  	default:
    50  	}
    51  	return false
    52  }
    53  
    54  // TryGetConnection retrieves a connection if it is already available
    55  func (se *signerEndpoint) WaitConnection(connectionAvailableCh chan net.Conn, maxWait time.Duration) error {
    56  	se.connMtx.Lock()
    57  	defer se.connMtx.Unlock()
    58  
    59  	select {
    60  	case se.conn = <-connectionAvailableCh:
    61  	case <-time.After(maxWait):
    62  		return ErrConnectionTimeout
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  // SetConnection replaces the current connection object
    69  func (se *signerEndpoint) SetConnection(newConnection net.Conn) {
    70  	se.connMtx.Lock()
    71  	defer se.connMtx.Unlock()
    72  	se.conn = newConnection
    73  }
    74  
    75  // IsConnected indicates if there is an active connection
    76  func (se *signerEndpoint) DropConnection() {
    77  	se.connMtx.Lock()
    78  	defer se.connMtx.Unlock()
    79  	se.dropConnection()
    80  }
    81  
    82  // ReadMessage reads a message from the endpoint
    83  func (se *signerEndpoint) ReadMessage() (msg SignerMessage, err error) {
    84  	se.connMtx.Lock()
    85  	defer se.connMtx.Unlock()
    86  
    87  	if !se.isConnected() {
    88  		return nil, fmt.Errorf("endpoint is not connected")
    89  	}
    90  
    91  	// Reset read deadline
    92  	deadline := time.Now().Add(se.timeoutReadWrite)
    93  
    94  	err = se.conn.SetReadDeadline(deadline)
    95  	if err != nil {
    96  		return
    97  	}
    98  
    99  	const maxRemoteSignerMsgSize = 1024 * 10
   100  	_, err = cdc.UnmarshalBinaryLengthPrefixedReader(se.conn, &msg, maxRemoteSignerMsgSize)
   101  	if _, ok := err.(timeoutError); ok {
   102  		if err != nil {
   103  			err = errors.Wrap(ErrReadTimeout, err.Error())
   104  		} else {
   105  			err = errors.Wrap(ErrReadTimeout, "Empty error")
   106  		}
   107  		se.Logger.Debug("Dropping [read]", "obj", se)
   108  		se.dropConnection()
   109  	}
   110  
   111  	return
   112  }
   113  
   114  // WriteMessage writes a message from the endpoint
   115  func (se *signerEndpoint) WriteMessage(msg SignerMessage) (err error) {
   116  	se.connMtx.Lock()
   117  	defer se.connMtx.Unlock()
   118  
   119  	if !se.isConnected() {
   120  		return errors.Wrap(ErrNoConnection, "endpoint is not connected")
   121  	}
   122  
   123  	// Reset read deadline
   124  	deadline := time.Now().Add(se.timeoutReadWrite)
   125  	err = se.conn.SetWriteDeadline(deadline)
   126  	if err != nil {
   127  		return
   128  	}
   129  
   130  	_, err = cdc.MarshalBinaryLengthPrefixedWriter(se.conn, msg)
   131  	if _, ok := err.(timeoutError); ok {
   132  		if err != nil {
   133  			err = errors.Wrap(ErrWriteTimeout, err.Error())
   134  		} else {
   135  			err = errors.Wrap(ErrWriteTimeout, "Empty error")
   136  		}
   137  		se.dropConnection()
   138  	}
   139  
   140  	return
   141  }
   142  
   143  func (se *signerEndpoint) isConnected() bool {
   144  	return se.conn != nil
   145  }
   146  
   147  func (se *signerEndpoint) dropConnection() {
   148  	if se.conn != nil {
   149  		if err := se.conn.Close(); err != nil {
   150  			se.Logger.Error("signerEndpoint::dropConnection", "err", err)
   151  		}
   152  		se.conn = nil
   153  	}
   154  }