|
|
- package privval
-
- import (
- "net"
- "time"
-
- "github.com/tendermint/tendermint/crypto/ed25519"
- p2pconn "github.com/tendermint/tendermint/p2p/conn"
- )
-
- const (
- defaultAcceptDeadlineSeconds = 3
- defaultConnDeadlineSeconds = 3
- )
-
- // timeoutError can be used to check if an error returned from the netp package
- // was due to a timeout.
- type timeoutError interface {
- Timeout() bool
- }
-
- //------------------------------------------------------------------
- // TCP Listener
-
- // TCPListenerOption sets an optional parameter on the tcpListener.
- type TCPListenerOption func(*tcpListener)
-
- // TCPListenerAcceptDeadline sets the deadline for the listener.
- // A zero time value disables the deadline.
- func TCPListenerAcceptDeadline(deadline time.Duration) TCPListenerOption {
- return func(tl *tcpListener) { tl.acceptDeadline = deadline }
- }
-
- // TCPListenerConnDeadline sets the read and write deadline for connections
- // from external signing processes.
- func TCPListenerConnDeadline(deadline time.Duration) TCPListenerOption {
- return func(tl *tcpListener) { tl.connDeadline = deadline }
- }
-
- // tcpListener implements net.Listener.
- var _ net.Listener = (*tcpListener)(nil)
-
- // tcpListener wraps a *net.TCPListener to standardise protocol timeouts
- // and potentially other tuning parameters. It also returns encrypted connections.
- type tcpListener struct {
- *net.TCPListener
-
- secretConnKey ed25519.PrivKeyEd25519
-
- acceptDeadline time.Duration
- connDeadline time.Duration
- }
-
- // NewTCPListener returns a listener that accepts authenticated encrypted connections
- // using the given secretConnKey and the default timeout values.
- func NewTCPListener(ln net.Listener, secretConnKey ed25519.PrivKeyEd25519) *tcpListener {
- return &tcpListener{
- TCPListener: ln.(*net.TCPListener),
- secretConnKey: secretConnKey,
- acceptDeadline: time.Second * defaultAcceptDeadlineSeconds,
- connDeadline: time.Second * defaultConnDeadlineSeconds,
- }
- }
-
- // Accept implements net.Listener.
- func (ln *tcpListener) Accept() (net.Conn, error) {
- err := ln.SetDeadline(time.Now().Add(ln.acceptDeadline))
- if err != nil {
- return nil, err
- }
-
- tc, err := ln.AcceptTCP()
- if err != nil {
- return nil, err
- }
-
- // Wrap the conn in our timeout and encryption wrappers
- timeoutConn := newTimeoutConn(tc, ln.connDeadline)
- secretConn, err := p2pconn.MakeSecretConnection(timeoutConn, ln.secretConnKey)
- if err != nil {
- return nil, err
- }
-
- return secretConn, nil
- }
-
- //------------------------------------------------------------------
- // Unix Listener
-
- // unixListener implements net.Listener.
- var _ net.Listener = (*unixListener)(nil)
-
- type UnixListenerOption func(*unixListener)
-
- // UnixListenerAcceptDeadline sets the deadline for the listener.
- // A zero time value disables the deadline.
- func UnixListenerAcceptDeadline(deadline time.Duration) UnixListenerOption {
- return func(ul *unixListener) { ul.acceptDeadline = deadline }
- }
-
- // UnixListenerConnDeadline sets the read and write deadline for connections
- // from external signing processes.
- func UnixListenerConnDeadline(deadline time.Duration) UnixListenerOption {
- return func(ul *unixListener) { ul.connDeadline = deadline }
- }
-
- // unixListener wraps a *net.UnixListener to standardise protocol timeouts
- // and potentially other tuning parameters. It returns unencrypted connections.
- type unixListener struct {
- *net.UnixListener
-
- acceptDeadline time.Duration
- connDeadline time.Duration
- }
-
- // NewUnixListener returns a listener that accepts unencrypted connections
- // using the default timeout values.
- func NewUnixListener(ln net.Listener) *unixListener {
- return &unixListener{
- UnixListener: ln.(*net.UnixListener),
- acceptDeadline: time.Second * defaultAcceptDeadlineSeconds,
- connDeadline: time.Second * defaultConnDeadlineSeconds,
- }
- }
-
- // Accept implements net.Listener.
- func (ln *unixListener) Accept() (net.Conn, error) {
- err := ln.SetDeadline(time.Now().Add(ln.acceptDeadline))
- if err != nil {
- return nil, err
- }
-
- tc, err := ln.AcceptUnix()
- if err != nil {
- return nil, err
- }
-
- // Wrap the conn in our timeout wrapper
- conn := newTimeoutConn(tc, ln.connDeadline)
-
- // TODO: wrap in something that authenticates
- // with a MAC - https://github.com/tendermint/tendermint/issues/3099
-
- return conn, nil
- }
-
- //------------------------------------------------------------------
- // Connection
-
- // timeoutConn implements net.Conn.
- var _ net.Conn = (*timeoutConn)(nil)
-
- // timeoutConn wraps a net.Conn to standardise protocol timeouts / deadline resets.
- type timeoutConn struct {
- net.Conn
-
- connDeadline time.Duration
- }
-
- // newTimeoutConn returns an instance of newTCPTimeoutConn.
- func newTimeoutConn(
- conn net.Conn,
- connDeadline time.Duration) *timeoutConn {
- return &timeoutConn{
- conn,
- connDeadline,
- }
- }
-
- // Read implements net.Conn.
- func (c timeoutConn) Read(b []byte) (n int, err error) {
- // Reset deadline
- c.Conn.SetReadDeadline(time.Now().Add(c.connDeadline))
-
- return c.Conn.Read(b)
- }
-
- // Write implements net.Conn.
- func (c timeoutConn) Write(b []byte) (n int, err error) {
- // Reset deadline
- c.Conn.SetWriteDeadline(time.Now().Add(c.connDeadline))
-
- return c.Conn.Write(b)
- }
|