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