versionhandshake

package
v0.6.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 10, 2023 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package versionhandshake wraps a transport.{Connecter,AuthenticatedListener} to add an exchange of protocol version information on connection establishment.

The protocol version information (banner) is plain text, thus making it easy to diagnose issues with standard tools.

Index

Constants

View Source
const HandshakeMessageMaxLen = 16 * 4096
View Source
const MaxProtocolVersion = 9999

MaxProtocolVersion is the maximum allowed protocol version. This is a protocol constant, changing it may break the wire format.

Variables

This section is empty.

Functions

Types

type HandshakeConnecter

type HandshakeConnecter struct {
	// contains filtered or unexported fields
}

func Connecter

func Connecter(connecter transport.Connecter, timeout time.Duration) HandshakeConnecter

func (HandshakeConnecter) Connect

type HandshakeError

type HandshakeError struct {

	// If not nil, the underlying IO error that caused the handshake to fail.
	IOError error
	// contains filtered or unexported fields
}

A HandshakeError describes what went wrong during the handshake. It implements net.Error and is always temporary.

func DoHandshakeCurrentVersion

func DoHandshakeCurrentVersion(conn net.Conn, deadline time.Time) *HandshakeError

func DoHandshakeVersion

func DoHandshakeVersion(conn net.Conn, deadline time.Time, version int) (rErr *HandshakeError)

func (HandshakeError) Error

func (e HandshakeError) Error() string

func (HandshakeError) Temporary

func (e HandshakeError) Temporary() bool

When a net.Listener.Accept() returns an error, the server must decide whether to retry calling Accept() or not. On some platforms (e.g., Linux), Accept() can return errors related to the specific protocol connection that was supposed to be returned as asocket FD. Obviously, we want to ignore, maybe log, those errors and retry Accept() immediately to serve other connections. But there are also conditions where we get Accept() errors because the process has run out of file descriptors. In that case, retrying won't help. We need to close some file descriptor to make progress. Note that there could be lots of open file descriptors because we have accepted, and not yet closed, lots of connections in the past. And then, of course there can be errors where we just want to return, e.g., if there's a programming error and we're getting an EBADFD or whatever.

So, the serve loops in net/http.Server.Serve() or gRPC's server.Serve() must inspect the error and decide what to do. The vehicle for this is the

interface { Temporary() bool }

Behavior in both of the aforementioned Serve() loops:

  • if the error doesn't implement the interface, stop serving and return
  • `Temporary() == true`: retry with back-off
  • `Temporary() == false`: stop serving and return

So, to make this package's HandshakeListener work with these Serve() loops, we return Temporary() == true if the handshake fails. In the aforementioned categories, that's the case of a per-connection protocol error.

Note: the net.Error interface has deprecated the Temporary() method in go.dev/issue/45729, but there is no replacement for users of .Accept(). Existing users of .Accept() continue to check for the interface. So, we need to continue supporting Temporary() until there's a different mechanism for serve loops to decide whether to retry or not. The following mailing list post proposes to eliminate the retries completely, but it seems like the effort has stalled. https://groups.google.com/g/golang-nuts/c/-JcZzOkyqYI/m/xwaZzjCgAwAJ

func (HandshakeError) Timeout

func (e HandshakeError) Timeout() bool

If the underlying IOError was net.Error.Timeout(), Timeout() returns that value. Otherwise false.

type HandshakeListener

type HandshakeListener struct {
	// contains filtered or unexported fields
}

wrapper type that performs a a protocol version handshake before returning the connection

func (HandshakeListener) Accept

func (HandshakeListener) Addr

func (l HandshakeListener) Addr() net.Addr

func (HandshakeListener) Close

func (l HandshakeListener) Close() error

type HandshakeMessage

type HandshakeMessage struct {
	ProtocolVersion int
	Extensions      []string
}

func (*HandshakeMessage) DecodeReader

func (m *HandshakeMessage) DecodeReader(r io.Reader, maxLen int) error

func (*HandshakeMessage) Encode

func (m *HandshakeMessage) Encode() ([]byte, error)

Only returns *HandshakeError as error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL