You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
5.0 KiB

Close and retry a RemoteSigner on err (#2923) * Close and recreate a RemoteSigner on err * Update changelog * Address Anton's comments / suggestions: - update changelog - restart TCPVal - shut down on `ErrUnexpectedResponse` * re-init remote signer client with fresh connection if Ping fails - add/update TODOs in secret connection - rename tcp.go -> tcp_client.go, same with ipc to clarify their purpose * account for `conn returned by waitConnection can be `nil` - also add TODO about RemoteSigner conn field * Tests for retrying: IPC / TCP - shorter info log on success - set conn and use it in tests to close conn * Tests for retrying: IPC / TCP - shorter info log on success - set conn and use it in tests to close conn - add rwmutex for conn field in IPC * comments and doc.go * fix ipc tests. fixes #2677 * use constants for tests * cleanup some error statements * fixes #2784, race in tests * remove print statement * minor fixes from review * update comment on sts spec * cosmetics * p2p/conn: add failing tests * p2p/conn: make SecretConnection thread safe * changelog * IPCVal signer refactor - use a .reset() method - don't use embedded RemoteSignerClient - guard RemoteSignerClient with mutex - drop the .conn - expose Close() on RemoteSignerClient * apply IPCVal refactor to TCPVal * remove mtx from RemoteSignerClient * consolidate IPCVal and TCPVal, fixes #3104 - done in tcp_client.go - now called SocketVal - takes a listener in the constructor - make tcpListener and unixListener contain all the differences * delete ipc files * introduce unix and tcp dialer for RemoteSigner * rename files - drop tcp_ prefix - rename priv_validator.go to file.go * bring back listener options * fix node * fix priv_val_server * fix node test * minor cleanup and comments
6 years ago
  1. package privval
  2. import (
  3. "net"
  4. "time"
  5. "github.com/tendermint/tendermint/crypto/ed25519"
  6. p2pconn "github.com/tendermint/tendermint/p2p/conn"
  7. )
  8. const (
  9. defaultAcceptDeadlineSeconds = 3
  10. defaultConnDeadlineSeconds = 3
  11. )
  12. // timeoutError can be used to check if an error returned from the netp package
  13. // was due to a timeout.
  14. type timeoutError interface {
  15. Timeout() bool
  16. }
  17. //------------------------------------------------------------------
  18. // TCP Listener
  19. // TCPListenerOption sets an optional parameter on the tcpListener.
  20. type TCPListenerOption func(*tcpListener)
  21. // TCPListenerAcceptDeadline sets the deadline for the listener.
  22. // A zero time value disables the deadline.
  23. func TCPListenerAcceptDeadline(deadline time.Duration) TCPListenerOption {
  24. return func(tl *tcpListener) { tl.acceptDeadline = deadline }
  25. }
  26. // TCPListenerConnDeadline sets the read and write deadline for connections
  27. // from external signing processes.
  28. func TCPListenerConnDeadline(deadline time.Duration) TCPListenerOption {
  29. return func(tl *tcpListener) { tl.connDeadline = deadline }
  30. }
  31. // tcpListener implements net.Listener.
  32. var _ net.Listener = (*tcpListener)(nil)
  33. // tcpListener wraps a *net.TCPListener to standardise protocol timeouts
  34. // and potentially other tuning parameters. It also returns encrypted connections.
  35. type tcpListener struct {
  36. *net.TCPListener
  37. secretConnKey ed25519.PrivKeyEd25519
  38. acceptDeadline time.Duration
  39. connDeadline time.Duration
  40. }
  41. // NewTCPListener returns a listener that accepts authenticated encrypted connections
  42. // using the given secretConnKey and the default timeout values.
  43. func NewTCPListener(ln net.Listener, secretConnKey ed25519.PrivKeyEd25519) *tcpListener {
  44. return &tcpListener{
  45. TCPListener: ln.(*net.TCPListener),
  46. secretConnKey: secretConnKey,
  47. acceptDeadline: time.Second * defaultAcceptDeadlineSeconds,
  48. connDeadline: time.Second * defaultConnDeadlineSeconds,
  49. }
  50. }
  51. // Accept implements net.Listener.
  52. func (ln *tcpListener) Accept() (net.Conn, error) {
  53. err := ln.SetDeadline(time.Now().Add(ln.acceptDeadline))
  54. if err != nil {
  55. return nil, err
  56. }
  57. tc, err := ln.AcceptTCP()
  58. if err != nil {
  59. return nil, err
  60. }
  61. // Wrap the conn in our timeout and encryption wrappers
  62. timeoutConn := newTimeoutConn(tc, ln.connDeadline)
  63. secretConn, err := p2pconn.MakeSecretConnection(timeoutConn, ln.secretConnKey)
  64. if err != nil {
  65. return nil, err
  66. }
  67. return secretConn, nil
  68. }
  69. //------------------------------------------------------------------
  70. // Unix Listener
  71. // unixListener implements net.Listener.
  72. var _ net.Listener = (*unixListener)(nil)
  73. type UnixListenerOption func(*unixListener)
  74. // UnixListenerAcceptDeadline sets the deadline for the listener.
  75. // A zero time value disables the deadline.
  76. func UnixListenerAcceptDeadline(deadline time.Duration) UnixListenerOption {
  77. return func(ul *unixListener) { ul.acceptDeadline = deadline }
  78. }
  79. // UnixListenerConnDeadline sets the read and write deadline for connections
  80. // from external signing processes.
  81. func UnixListenerConnDeadline(deadline time.Duration) UnixListenerOption {
  82. return func(ul *unixListener) { ul.connDeadline = deadline }
  83. }
  84. // unixListener wraps a *net.UnixListener to standardise protocol timeouts
  85. // and potentially other tuning parameters. It returns unencrypted connections.
  86. type unixListener struct {
  87. *net.UnixListener
  88. acceptDeadline time.Duration
  89. connDeadline time.Duration
  90. }
  91. // NewUnixListener returns a listener that accepts unencrypted connections
  92. // using the default timeout values.
  93. func NewUnixListener(ln net.Listener) *unixListener {
  94. return &unixListener{
  95. UnixListener: ln.(*net.UnixListener),
  96. acceptDeadline: time.Second * defaultAcceptDeadlineSeconds,
  97. connDeadline: time.Second * defaultConnDeadlineSeconds,
  98. }
  99. }
  100. // Accept implements net.Listener.
  101. func (ln *unixListener) Accept() (net.Conn, error) {
  102. err := ln.SetDeadline(time.Now().Add(ln.acceptDeadline))
  103. if err != nil {
  104. return nil, err
  105. }
  106. tc, err := ln.AcceptUnix()
  107. if err != nil {
  108. return nil, err
  109. }
  110. // Wrap the conn in our timeout wrapper
  111. conn := newTimeoutConn(tc, ln.connDeadline)
  112. // TODO: wrap in something that authenticates
  113. // with a MAC - https://github.com/tendermint/tendermint/issues/3099
  114. return conn, nil
  115. }
  116. //------------------------------------------------------------------
  117. // Connection
  118. // timeoutConn implements net.Conn.
  119. var _ net.Conn = (*timeoutConn)(nil)
  120. // timeoutConn wraps a net.Conn to standardise protocol timeouts / deadline resets.
  121. type timeoutConn struct {
  122. net.Conn
  123. connDeadline time.Duration
  124. }
  125. // newTimeoutConn returns an instance of newTCPTimeoutConn.
  126. func newTimeoutConn(
  127. conn net.Conn,
  128. connDeadline time.Duration) *timeoutConn {
  129. return &timeoutConn{
  130. conn,
  131. connDeadline,
  132. }
  133. }
  134. // Read implements net.Conn.
  135. func (c timeoutConn) Read(b []byte) (n int, err error) {
  136. // Reset deadline
  137. c.Conn.SetReadDeadline(time.Now().Add(c.connDeadline))
  138. return c.Conn.Read(b)
  139. }
  140. // Write implements net.Conn.
  141. func (c timeoutConn) Write(b []byte) (n int, err error) {
  142. // Reset deadline
  143. c.Conn.SetWriteDeadline(time.Now().Add(c.connDeadline))
  144. return c.Conn.Write(b)
  145. }