github.com/danielpfeifer02/quic-go-prio-packs@v0.41.0-28/interface.go (about)

     1  package quic
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  	"errors"
     7  	"io"
     8  	"net"
     9  	"time"
    10  
    11  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/handshake"
    12  	"github.com/danielpfeifer02/quic-go-prio-packs/internal/protocol"
    13  	"github.com/danielpfeifer02/quic-go-prio-packs/logging"
    14  	"github.com/danielpfeifer02/quic-go-prio-packs/priority_setting"
    15  )
    16  
    17  // The StreamID is the ID of a QUIC stream.
    18  type StreamID = protocol.StreamID
    19  
    20  // PRIO_PACKS_TAG
    21  // Priority is the priority of a QUIC stream.
    22  type Priority = priority_setting.Priority
    23  
    24  // A Version is a QUIC version number.
    25  type Version = protocol.Version
    26  
    27  // A VersionNumber is a QUIC version number.
    28  // Deprecated: VersionNumber was renamed to Version.
    29  type VersionNumber = Version
    30  
    31  const (
    32  	// Version1 is RFC 9000
    33  	Version1 = protocol.Version1
    34  	// Version2 is RFC 9369
    35  	Version2 = protocol.Version2
    36  )
    37  
    38  // A ClientToken is a token received by the client.
    39  // It can be used to skip address validation on future connection attempts.
    40  type ClientToken struct {
    41  	data []byte
    42  }
    43  
    44  type TokenStore interface {
    45  	// Pop searches for a ClientToken associated with the given key.
    46  	// Since tokens are not supposed to be reused, it must remove the token from the cache.
    47  	// It returns nil when no token is found.
    48  	Pop(key string) (token *ClientToken)
    49  
    50  	// Put adds a token to the cache with the given key. It might get called
    51  	// multiple times in a connection.
    52  	Put(key string, token *ClientToken)
    53  }
    54  
    55  // Err0RTTRejected is the returned from:
    56  // * Open{Uni}Stream{Sync}
    57  // * Accept{Uni}Stream
    58  // * Stream.Read and Stream.Write
    59  // when the server rejects a 0-RTT connection attempt.
    60  var Err0RTTRejected = errors.New("0-RTT rejected")
    61  
    62  // ConnectionTracingKey can be used to associate a ConnectionTracer with a Connection.
    63  // It is set on the Connection.Context() context,
    64  // as well as on the context passed to logging.Tracer.NewConnectionTracer.
    65  var ConnectionTracingKey = connTracingCtxKey{}
    66  
    67  type connTracingCtxKey struct{}
    68  
    69  // QUICVersionContextKey can be used to find out the QUIC version of a TLS handshake from the
    70  // context returned by tls.Config.ClientHelloInfo.Context.
    71  var QUICVersionContextKey = handshake.QUICVersionContextKey
    72  
    73  // Stream is the interface implemented by QUIC streams
    74  // In addition to the errors listed on the Connection,
    75  // calls to stream functions can return a StreamError if the stream is canceled.
    76  type Stream interface {
    77  	ReceiveStream
    78  	SendStream
    79  	// SetDeadline sets the read and write deadlines associated
    80  	// with the connection. It is equivalent to calling both
    81  	// SetReadDeadline and SetWriteDeadline.
    82  	SetDeadline(t time.Time) error
    83  	// PRIO_PACKS_TAG
    84  	// Priority returns the stream specific priority used for potential adaptive streaming
    85  	Priority() Priority
    86  	// PRIO_PACKS_TAG
    87  	// SetPriority sets the stream specific priority used for potential adaptive streaming
    88  	SetPriority(Priority)
    89  }
    90  
    91  // A ReceiveStream is a unidirectional Receive Stream.
    92  type ReceiveStream interface {
    93  	// StreamID returns the stream ID.
    94  	StreamID() StreamID
    95  	// Read reads data from the stream.
    96  	// Read can be made to time out and return a net.Error with Timeout() == true
    97  	// after a fixed time limit; see SetDeadline and SetReadDeadline.
    98  	// If the stream was canceled by the peer, the error implements the StreamError
    99  	// interface, and Canceled() == true.
   100  	// If the connection was closed due to a timeout, the error satisfies
   101  	// the net.Error interface, and Timeout() will be true.
   102  	io.Reader
   103  	// CancelRead aborts receiving on this stream.
   104  	// It will ask the peer to stop transmitting stream data.
   105  	// Read will unblock immediately, and future Read calls will fail.
   106  	// When called multiple times or after reading the io.EOF it is a no-op.
   107  	CancelRead(StreamErrorCode)
   108  	// SetReadDeadline sets the deadline for future Read calls and
   109  	// any currently-blocked Read call.
   110  	// A zero value for t means Read will not time out.
   111  
   112  	SetReadDeadline(t time.Time) error
   113  	// PRIO_PACKS_TAG
   114  	// Priority returns the stream specific priority used for potential adaptive streaming
   115  	Priority() Priority
   116  	// PRIO_PACKS_TAG
   117  	// SetPriority sets the stream specific priority used for potential adaptive streaming
   118  	SetPriority(Priority)
   119  }
   120  
   121  // A SendStream is a unidirectional Send Stream.
   122  type SendStream interface {
   123  	// StreamID returns the stream ID.
   124  	StreamID() StreamID
   125  	// Write writes data to the stream.
   126  	// Write can be made to time out and return a net.Error with Timeout() == true
   127  	// after a fixed time limit; see SetDeadline and SetWriteDeadline.
   128  	// If the stream was canceled by the peer, the error implements the StreamError
   129  	// interface, and Canceled() == true.
   130  	// If the connection was closed due to a timeout, the error satisfies
   131  	// the net.Error interface, and Timeout() will be true.
   132  	io.Writer
   133  	// Close closes the write-direction of the stream.
   134  	// Future calls to Write are not permitted after calling Close.
   135  	// It must not be called concurrently with Write.
   136  	// It must not be called after calling CancelWrite.
   137  	io.Closer
   138  	// CancelWrite aborts sending on this stream.
   139  	// Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably.
   140  	// Write will unblock immediately, and future calls to Write will fail.
   141  	// When called multiple times or after closing the stream it is a no-op.
   142  	CancelWrite(StreamErrorCode)
   143  	// The Context is canceled as soon as the write-side of the stream is closed.
   144  	// This happens when Close() or CancelWrite() is called, or when the peer
   145  	// cancels the read-side of their stream.
   146  	// The cancellation cause is set to the error that caused the stream to
   147  	// close, or `context.Canceled` in case the stream is closed without error.
   148  	Context() context.Context
   149  	// SetWriteDeadline sets the deadline for future Write calls
   150  	// and any currently-blocked Write call.
   151  	// Even if write times out, it may return n > 0, indicating that
   152  	// some data was successfully written.
   153  	// A zero value for t means Write will not time out.
   154  	SetWriteDeadline(t time.Time) error
   155  	// PRIO_PACKS_TAG
   156  	// Priority returns the stream specific priority used for potential adaptive streaming
   157  	Priority() Priority
   158  	// PRIO_PACKS_TAG
   159  	// SetPriority sets the stream specific priority used for potential adaptive streaming
   160  	SetPriority(Priority)
   161  }
   162  
   163  // A Connection is a QUIC connection between two peers.
   164  // Calls to the connection (and to streams) can return the following types of errors:
   165  // * ApplicationError: for errors triggered by the application running on top of QUIC
   166  // * TransportError: for errors triggered by the QUIC transport (in many cases a misbehaving peer)
   167  // * IdleTimeoutError: when the peer goes away unexpectedly (this is a net.Error timeout error)
   168  // * HandshakeTimeoutError: when the cryptographic handshake takes too long (this is a net.Error timeout error)
   169  // * StatelessResetError: when we receive a stateless reset (this is a net.Error temporary error)
   170  // * VersionNegotiationError: returned by the client, when there's no version overlap between the peers
   171  type Connection interface {
   172  	// AcceptStream returns the next stream opened by the peer, blocking until one is available.
   173  	// If the connection was closed due to a timeout, the error satisfies
   174  	// the net.Error interface, and Timeout() will be true.
   175  	AcceptStream(context.Context) (Stream, error)
   176  	// AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available.
   177  	// If the connection was closed due to a timeout, the error satisfies
   178  	// the net.Error interface, and Timeout() will be true.
   179  	AcceptUniStream(context.Context) (ReceiveStream, error)
   180  
   181  	// OpenStream opens a new bidirectional QUIC stream.
   182  	// There is no signaling to the peer about new streams:
   183  	// The peer can only accept the stream after data has been sent on the stream.
   184  	// If the error is non-nil, it satisfies the net.Error interface.
   185  	// When reaching the peer's stream limit, err.Temporary() will be true.
   186  	// If the connection was closed due to a timeout, Timeout() will be true.
   187  	OpenStream() (Stream, error)
   188  	// PRIO_PACKS_TAG
   189  	// same as OpenStream, but with priority
   190  	OpenStreamWithPriority(Priority) (Stream, error)
   191  
   192  	// OpenStreamSync opens a new bidirectional QUIC stream.
   193  	// It blocks until a new stream can be opened.
   194  	// There is no signaling to the peer about new streams:
   195  	// The peer can only accept the stream after data has been sent on the stream,
   196  	// or the stream has been reset or closed.
   197  	// If the error is non-nil, it satisfies the net.Error interface.
   198  	// If the connection was closed due to a timeout, Timeout() will be true.
   199  	OpenStreamSync(context.Context) (Stream, error)
   200  	// PRIO_PACKS_TAG
   201  	// same as OpenStreamSync, but with priority
   202  	OpenStreamSyncWithPriority(context.Context, Priority) (Stream, error)
   203  
   204  	// OpenUniStream opens a new outgoing unidirectional QUIC stream.
   205  	// If the error is non-nil, it satisfies the net.Error interface.
   206  	// When reaching the peer's stream limit, Temporary() will be true.
   207  	// If the connection was closed due to a timeout, Timeout() will be true.
   208  	OpenUniStream() (SendStream, error)
   209  	// PRIO_PACKS_TAG
   210  	// same as OpenUniStream, but with priotity
   211  	OpenUniStreamWithPriority(Priority) (SendStream, error)
   212  
   213  	// OpenUniStreamSync opens a new outgoing unidirectional QUIC stream.
   214  	// It blocks until a new stream can be opened.
   215  	// If the error is non-nil, it satisfies the net.Error interface.
   216  	// If the connection was closed due to a timeout, Timeout() will be true.
   217  	OpenUniStreamSync(context.Context) (SendStream, error)
   218  	// PRIO_PACKS_TAG
   219  	// same as OpenUniStreamSync, but with priority
   220  	OpenUniStreamSyncWithPriority(context.Context, Priority) (SendStream, error)
   221  
   222  	// LocalAddr returns the local address.
   223  	LocalAddr() net.Addr
   224  	// RemoteAddr returns the address of the peer.
   225  	RemoteAddr() net.Addr
   226  	// CloseWithError closes the connection with an error.
   227  	// The error string will be sent to the peer.
   228  	CloseWithError(ApplicationErrorCode, string) error
   229  	// Context returns a context that is cancelled when the connection is closed.
   230  	// The cancellation cause is set to the error that caused the connection to
   231  	// close, or `context.Canceled` in case the listener is closed first.
   232  	Context() context.Context
   233  	// ConnectionState returns basic details about the QUIC connection.
   234  	// Warning: This API should not be considered stable and might change soon.
   235  	ConnectionState() ConnectionState
   236  
   237  	// SendDatagram sends a message using a QUIC datagram, as specified in RFC 9221.
   238  	// There is no delivery guarantee for DATAGRAM frames, they are not retransmitted if lost.
   239  	// The payload of the datagram needs to fit into a single QUIC packet.
   240  	// In addition, a datagram may be dropped before being sent out if the available packet size suddenly decreases.
   241  	// If the payload is too large to be sent at the current time, a DatagramTooLargeError is returned.
   242  	SendDatagram(payload []byte) error
   243  
   244  	// DATAGRAM_PRIO_TAG
   245  	SendDatagramWithPriority(p []byte, prio priority_setting.Priority) error
   246  
   247  	// ReceiveDatagram gets a message received in a datagram, as specified in RFC 9221.
   248  	ReceiveDatagram(context.Context) ([]byte, error)
   249  
   250  	// PRIO_PACKS_TAG
   251  	// get the priority of a corresponding stream using the streamID
   252  	GetPriority(StreamID) Priority
   253  
   254  	// PACKET_NUMBER_TAG
   255  	// SetPacketNumber sets the packet number for the next packet sent on the connection.
   256  	// This is needed if bpf porgrams are sending packets.
   257  	SetPacketNumber(int64)
   258  	// SetHighestSent sets the highest packet number sent on the connection.
   259  	// This is needed if bpf porgrams are sending packets.
   260  	SetHighestSent(int64)
   261  	// (Un-)Locking the packet number setting so that it is not changed during actively checking
   262  	// a packet number of a packet.
   263  	Lock()
   264  	Unlock()
   265  
   266  	// BPF_MAP_TAG
   267  	GetDestConnID(Stream) ConnectionID
   268  }
   269  
   270  // An EarlyConnection is a connection that is handshaking.
   271  // Data sent during the handshake is encrypted using the forward secure keys.
   272  // When using client certificates, the client's identity is only verified
   273  // after completion of the handshake.
   274  type EarlyConnection interface {
   275  	Connection
   276  
   277  	// HandshakeComplete blocks until the handshake completes (or fails).
   278  	// For the client, data sent before completion of the handshake is encrypted with 0-RTT keys.
   279  	// For the server, data sent before completion of the handshake is encrypted with 1-RTT keys,
   280  	// however the client's identity is only verified once the handshake completes.
   281  	HandshakeComplete() <-chan struct{}
   282  
   283  	NextConnection() Connection
   284  }
   285  
   286  // StatelessResetKey is a key used to derive stateless reset tokens.
   287  type StatelessResetKey [32]byte
   288  
   289  // TokenGeneratorKey is a key used to encrypt session resumption tokens.
   290  type TokenGeneratorKey = handshake.TokenProtectorKey
   291  
   292  // A ConnectionID is a QUIC Connection ID, as defined in RFC 9000.
   293  // It is not able to handle QUIC Connection IDs longer than 20 bytes,
   294  // as they are allowed by RFC 8999.
   295  type ConnectionID = protocol.ConnectionID
   296  
   297  // ConnectionIDFromBytes interprets b as a Connection ID. It panics if b is
   298  // longer than 20 bytes.
   299  func ConnectionIDFromBytes(b []byte) ConnectionID {
   300  	return protocol.ParseConnectionID(b)
   301  }
   302  
   303  // A ConnectionIDGenerator is an interface that allows clients to implement their own format
   304  // for the Connection IDs that servers/clients use as SrcConnectionID in QUIC packets.
   305  //
   306  // Connection IDs generated by an implementation should always produce IDs of constant size.
   307  type ConnectionIDGenerator interface {
   308  	// GenerateConnectionID generates a new ConnectionID.
   309  	// Generated ConnectionIDs should be unique and observers should not be able to correlate two ConnectionIDs.
   310  	GenerateConnectionID() (ConnectionID, error)
   311  
   312  	// ConnectionIDLen tells what is the length of the ConnectionIDs generated by the implementation of
   313  	// this interface.
   314  	// Effectively, this means that implementations of ConnectionIDGenerator must always return constant-size
   315  	// connection IDs. Valid lengths are between 0 and 20 and calls to GenerateConnectionID.
   316  	// 0-length ConnectionsIDs can be used when an endpoint (server or client) does not require multiplexing connections
   317  	// in the presence of a connection migration environment.
   318  	ConnectionIDLen() int
   319  }
   320  
   321  // Config contains all configuration data needed for a QUIC server or client.
   322  type Config struct {
   323  	// GetConfigForClient is called for incoming connections.
   324  	// If the error is not nil, the connection attempt is refused.
   325  	GetConfigForClient func(info *ClientHelloInfo) (*Config, error)
   326  	// The QUIC versions that can be negotiated.
   327  	// If not set, it uses all versions available.
   328  	Versions []Version
   329  	// HandshakeIdleTimeout is the idle timeout before completion of the handshake.
   330  	// If we don't receive any packet from the peer within this time, the connection attempt is aborted.
   331  	// Additionally, if the handshake doesn't complete in twice this time, the connection attempt is also aborted.
   332  	// If this value is zero, the timeout is set to 5 seconds.
   333  	HandshakeIdleTimeout time.Duration
   334  	// MaxIdleTimeout is the maximum duration that may pass without any incoming network activity.
   335  	// The actual value for the idle timeout is the minimum of this value and the peer's.
   336  	// This value only applies after the handshake has completed.
   337  	// If the timeout is exceeded, the connection is closed.
   338  	// If this value is zero, the timeout is set to 30 seconds.
   339  	MaxIdleTimeout time.Duration
   340  	// The TokenStore stores tokens received from the server.
   341  	// Tokens are used to skip address validation on future connection attempts.
   342  	// The key used to store tokens is the ServerName from the tls.Config, if set
   343  	// otherwise the token is associated with the server's IP address.
   344  	TokenStore TokenStore
   345  	// InitialStreamReceiveWindow is the initial size of the stream-level flow control window for receiving data.
   346  	// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
   347  	// will increase the window up to MaxStreamReceiveWindow.
   348  	// If this value is zero, it will default to 512 KB.
   349  	// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
   350  	InitialStreamReceiveWindow uint64
   351  	// MaxStreamReceiveWindow is the maximum stream-level flow control window for receiving data.
   352  	// If this value is zero, it will default to 6 MB.
   353  	// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
   354  	MaxStreamReceiveWindow uint64
   355  	// InitialConnectionReceiveWindow is the initial size of the stream-level flow control window for receiving data.
   356  	// If the application is consuming data quickly enough, the flow control auto-tuning algorithm
   357  	// will increase the window up to MaxConnectionReceiveWindow.
   358  	// If this value is zero, it will default to 512 KB.
   359  	// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
   360  	InitialConnectionReceiveWindow uint64
   361  	// MaxConnectionReceiveWindow is the connection-level flow control window for receiving data.
   362  	// If this value is zero, it will default to 15 MB.
   363  	// Values larger than the maximum varint (quicvarint.Max) will be clipped to that value.
   364  	MaxConnectionReceiveWindow uint64
   365  	// AllowConnectionWindowIncrease is called every time the connection flow controller attempts
   366  	// to increase the connection flow control window.
   367  	// If set, the caller can prevent an increase of the window. Typically, it would do so to
   368  	// limit the memory usage.
   369  	// To avoid deadlocks, it is not valid to call other functions on the connection or on streams
   370  	// in this callback.
   371  	AllowConnectionWindowIncrease func(conn Connection, delta uint64) bool
   372  	// MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open.
   373  	// If not set, it will default to 100.
   374  	// If set to a negative value, it doesn't allow any bidirectional streams.
   375  	// Values larger than 2^60 will be clipped to that value.
   376  	MaxIncomingStreams int64
   377  	// MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open.
   378  	// If not set, it will default to 100.
   379  	// If set to a negative value, it doesn't allow any unidirectional streams.
   380  	// Values larger than 2^60 will be clipped to that value.
   381  	MaxIncomingUniStreams int64
   382  	// KeepAlivePeriod defines whether this peer will periodically send a packet to keep the connection alive.
   383  	// If set to 0, then no keep alive is sent. Otherwise, the keep alive is sent on that period (or at most
   384  	// every half of MaxIdleTimeout, whichever is smaller).
   385  	KeepAlivePeriod time.Duration
   386  	// DisablePathMTUDiscovery disables Path MTU Discovery (RFC 8899).
   387  	// This allows the sending of QUIC packets that fully utilize the available MTU of the path.
   388  	// Path MTU discovery is only available on systems that allow setting of the Don't Fragment (DF) bit.
   389  	// If unavailable or disabled, packets will be at most 1252 (IPv4) / 1232 (IPv6) bytes in size.
   390  	DisablePathMTUDiscovery bool
   391  	// Allow0RTT allows the application to decide if a 0-RTT connection attempt should be accepted.
   392  	// Only valid for the server.
   393  	Allow0RTT bool
   394  	// Enable QUIC datagram support (RFC 9221).
   395  	EnableDatagrams bool
   396  	Tracer          func(context.Context, logging.Perspective, ConnectionID) *logging.ConnectionTracer
   397  }
   398  
   399  type ClientHelloInfo struct {
   400  	RemoteAddr net.Addr
   401  }
   402  
   403  // ConnectionState records basic details about a QUIC connection
   404  type ConnectionState struct {
   405  	// TLS contains information about the TLS connection state, incl. the tls.ConnectionState.
   406  	TLS tls.ConnectionState
   407  	// SupportsDatagrams says if support for QUIC datagrams (RFC 9221) was negotiated.
   408  	// This requires both nodes to support and enable the datagram extensions (via Config.EnableDatagrams).
   409  	// If datagram support was negotiated, datagrams can be sent and received using the
   410  	// SendDatagram and ReceiveDatagram methods on the Connection.
   411  	SupportsDatagrams bool
   412  	// Used0RTT says if 0-RTT resumption was used.
   413  	Used0RTT bool
   414  	// Version is the QUIC version of the QUIC connection.
   415  	Version Version
   416  	// GSO says if generic segmentation offload is used
   417  	GSO bool
   418  }