1package quic 2 3import ( 4 "context" 5 "io" 6 "net" 7 "time" 8 9 "github.com/lucas-clemente/quic-go/internal/handshake" 10 "github.com/lucas-clemente/quic-go/internal/protocol" 11 "github.com/lucas-clemente/quic-go/logging" 12 "github.com/lucas-clemente/quic-go/quictrace" 13) 14 15// RetireBugBackwardsCompatibilityMode controls a backwards compatibility mode, necessary due to a bug in 16// quic-go v0.17.2 (and earlier), where under certain circumstances, an endpoint would retire the connection 17// ID it is currently using. See https://github.com/lucas-clemente/quic-go/issues/2658. 18// The bug has now been fixed, and new deployments have nothing to worry about. 19// Deployments that already have quic-go <= v0.17.2 deployed should active RetireBugBackwardsCompatibilityMode. 20// If activated, quic-go will take steps to avoid the bug from triggering when connected to endpoints that are still 21// running quic-go <= v0.17.2. 22// This flag will be removed in a future version of quic-go. 23var RetireBugBackwardsCompatibilityMode bool 24 25// The StreamID is the ID of a QUIC stream. 26type StreamID = protocol.StreamID 27 28// A VersionNumber is a QUIC version number. 29type VersionNumber = protocol.VersionNumber 30 31const ( 32 // VersionDraft29 is IETF QUIC draft-29 33 VersionDraft29 = protocol.VersionDraft29 34 // VersionDraft32 is IETF QUIC draft-32 35 VersionDraft32 = protocol.VersionDraft32 36) 37 38// A Token can be used to verify the ownership of the client address. 39type Token struct { 40 // IsRetryToken encodes how the client received the token. There are two ways: 41 // * In a Retry packet sent when trying to establish a new connection. 42 // * In a NEW_TOKEN frame on a previous connection. 43 IsRetryToken bool 44 RemoteAddr string 45 SentTime time.Time 46} 47 48// A ClientToken is a token received by the client. 49// It can be used to skip address validation on future connection attempts. 50type ClientToken struct { 51 data []byte 52} 53 54type TokenStore interface { 55 // Pop searches for a ClientToken associated with the given key. 56 // Since tokens are not supposed to be reused, it must remove the token from the cache. 57 // It returns nil when no token is found. 58 Pop(key string) (token *ClientToken) 59 60 // Put adds a token to the cache with the given key. It might get called 61 // multiple times in a connection. 62 Put(key string, token *ClientToken) 63} 64 65// An ErrorCode is an application-defined error code. 66// Valid values range between 0 and MAX_UINT62. 67type ErrorCode = protocol.ApplicationErrorCode 68 69// Stream is the interface implemented by QUIC streams 70type Stream interface { 71 ReceiveStream 72 SendStream 73 // SetDeadline sets the read and write deadlines associated 74 // with the connection. It is equivalent to calling both 75 // SetReadDeadline and SetWriteDeadline. 76 SetDeadline(t time.Time) error 77} 78 79// A ReceiveStream is a unidirectional Receive Stream. 80type ReceiveStream interface { 81 // StreamID returns the stream ID. 82 StreamID() StreamID 83 // Read reads data from the stream. 84 // Read can be made to time out and return a net.Error with Timeout() == true 85 // after a fixed time limit; see SetDeadline and SetReadDeadline. 86 // If the stream was canceled by the peer, the error implements the StreamError 87 // interface, and Canceled() == true. 88 // If the session was closed due to a timeout, the error satisfies 89 // the net.Error interface, and Timeout() will be true. 90 io.Reader 91 // CancelRead aborts receiving on this stream. 92 // It will ask the peer to stop transmitting stream data. 93 // Read will unblock immediately, and future Read calls will fail. 94 // When called multiple times or after reading the io.EOF it is a no-op. 95 CancelRead(ErrorCode) 96 // SetReadDeadline sets the deadline for future Read calls and 97 // any currently-blocked Read call. 98 // A zero value for t means Read will not time out. 99 100 SetReadDeadline(t time.Time) error 101} 102 103// A SendStream is a unidirectional Send Stream. 104type SendStream interface { 105 // StreamID returns the stream ID. 106 StreamID() StreamID 107 // Write writes data to the stream. 108 // Write can be made to time out and return a net.Error with Timeout() == true 109 // after a fixed time limit; see SetDeadline and SetWriteDeadline. 110 // If the stream was canceled by the peer, the error implements the StreamError 111 // interface, and Canceled() == true. 112 // If the session was closed due to a timeout, the error satisfies 113 // the net.Error interface, and Timeout() will be true. 114 io.Writer 115 // Close closes the write-direction of the stream. 116 // Future calls to Write are not permitted after calling Close. 117 // It must not be called concurrently with Write. 118 // It must not be called after calling CancelWrite. 119 io.Closer 120 // CancelWrite aborts sending on this stream. 121 // Data already written, but not yet delivered to the peer is not guaranteed to be delivered reliably. 122 // Write will unblock immediately, and future calls to Write will fail. 123 // When called multiple times or after closing the stream it is a no-op. 124 CancelWrite(ErrorCode) 125 // The context is canceled as soon as the write-side of the stream is closed. 126 // This happens when Close() or CancelWrite() is called, or when the peer 127 // cancels the read-side of their stream. 128 // Warning: This API should not be considered stable and might change soon. 129 Context() context.Context 130 // SetWriteDeadline sets the deadline for future Write calls 131 // and any currently-blocked Write call. 132 // Even if write times out, it may return n > 0, indicating that 133 // some of the data was successfully written. 134 // A zero value for t means Write will not time out. 135 SetWriteDeadline(t time.Time) error 136} 137 138// StreamError is returned by Read and Write when the peer cancels the stream. 139type StreamError interface { 140 error 141 Canceled() bool 142 ErrorCode() ErrorCode 143} 144 145type ConnectionState = handshake.ConnectionState 146 147// A Session is a QUIC connection between two peers. 148type Session interface { 149 // AcceptStream returns the next stream opened by the peer, blocking until one is available. 150 // If the session was closed due to a timeout, the error satisfies 151 // the net.Error interface, and Timeout() will be true. 152 AcceptStream(context.Context) (Stream, error) 153 // AcceptUniStream returns the next unidirectional stream opened by the peer, blocking until one is available. 154 // If the session was closed due to a timeout, the error satisfies 155 // the net.Error interface, and Timeout() will be true. 156 AcceptUniStream(context.Context) (ReceiveStream, error) 157 // OpenStream opens a new bidirectional QUIC stream. 158 // There is no signaling to the peer about new streams: 159 // The peer can only accept the stream after data has been sent on the stream. 160 // If the error is non-nil, it satisfies the net.Error interface. 161 // When reaching the peer's stream limit, err.Temporary() will be true. 162 // If the session was closed due to a timeout, Timeout() will be true. 163 OpenStream() (Stream, error) 164 // OpenStreamSync opens a new bidirectional QUIC stream. 165 // It blocks until a new stream can be opened. 166 // If the error is non-nil, it satisfies the net.Error interface. 167 // If the session was closed due to a timeout, Timeout() will be true. 168 OpenStreamSync(context.Context) (Stream, error) 169 // OpenUniStream opens a new outgoing unidirectional QUIC stream. 170 // If the error is non-nil, it satisfies the net.Error interface. 171 // When reaching the peer's stream limit, Temporary() will be true. 172 // If the session was closed due to a timeout, Timeout() will be true. 173 OpenUniStream() (SendStream, error) 174 // OpenUniStreamSync opens a new outgoing unidirectional QUIC stream. 175 // It blocks until a new stream can be opened. 176 // If the error is non-nil, it satisfies the net.Error interface. 177 // If the session was closed due to a timeout, Timeout() will be true. 178 OpenUniStreamSync(context.Context) (SendStream, error) 179 // LocalAddr returns the local address. 180 LocalAddr() net.Addr 181 // RemoteAddr returns the address of the peer. 182 RemoteAddr() net.Addr 183 // Close the connection with an error. 184 // The error string will be sent to the peer. 185 CloseWithError(ErrorCode, string) error 186 // The context is cancelled when the session is closed. 187 // Warning: This API should not be considered stable and might change soon. 188 Context() context.Context 189 // ConnectionState returns basic details about the QUIC connection. 190 // It blocks until the handshake completes. 191 // Warning: This API should not be considered stable and might change soon. 192 ConnectionState() ConnectionState 193} 194 195// An EarlySession is a session that is handshaking. 196// Data sent during the handshake is encrypted using the forward secure keys. 197// When using client certificates, the client's identity is only verified 198// after completion of the handshake. 199type EarlySession interface { 200 Session 201 202 // Blocks until the handshake completes (or fails). 203 // Data sent before completion of the handshake is encrypted with 1-RTT keys. 204 // Note that the client's identity hasn't been verified yet. 205 HandshakeComplete() context.Context 206} 207 208// Config contains all configuration data needed for a QUIC server or client. 209type Config struct { 210 // The QUIC versions that can be negotiated. 211 // If not set, it uses all versions available. 212 // Warning: This API should not be considered stable and will change soon. 213 Versions []VersionNumber 214 // The length of the connection ID in bytes. 215 // It can be 0, or any value between 4 and 18. 216 // If not set, the interpretation depends on where the Config is used: 217 // If used for dialing an address, a 0 byte connection ID will be used. 218 // If used for a server, or dialing on a packet conn, a 4 byte connection ID will be used. 219 // When dialing on a packet conn, the ConnectionIDLength value must be the same for every Dial call. 220 ConnectionIDLength int 221 // HandshakeTimeout is the maximum duration that the cryptographic handshake may take. 222 // If the timeout is exceeded, the connection is closed. 223 // If this value is zero, the timeout is set to 10 seconds. 224 HandshakeTimeout time.Duration 225 // MaxIdleTimeout is the maximum duration that may pass without any incoming network activity. 226 // The actual value for the idle timeout is the minimum of this value and the peer's. 227 // This value only applies after the handshake has completed. 228 // If the timeout is exceeded, the connection is closed. 229 // If this value is zero, the timeout is set to 30 seconds. 230 MaxIdleTimeout time.Duration 231 // AcceptToken determines if a Token is accepted. 232 // It is called with token = nil if the client didn't send a token. 233 // If not set, a default verification function is used: 234 // * it verifies that the address matches, and 235 // * if the token is a retry token, that it was issued within the last 5 seconds 236 // * else, that it was issued within the last 24 hours. 237 // This option is only valid for the server. 238 AcceptToken func(clientAddr net.Addr, token *Token) bool 239 // The TokenStore stores tokens received from the server. 240 // Tokens are used to skip address validation on future connection attempts. 241 // The key used to store tokens is the ServerName from the tls.Config, if set 242 // otherwise the token is associated with the server's IP address. 243 TokenStore TokenStore 244 // MaxReceiveStreamFlowControlWindow is the maximum stream-level flow control window for receiving data. 245 // If this value is zero, it will default to 1 MB for the server and 6 MB for the client. 246 MaxReceiveStreamFlowControlWindow uint64 247 // MaxReceiveConnectionFlowControlWindow is the connection-level flow control window for receiving data. 248 // If this value is zero, it will default to 1.5 MB for the server and 15 MB for the client. 249 MaxReceiveConnectionFlowControlWindow uint64 250 // MaxIncomingStreams is the maximum number of concurrent bidirectional streams that a peer is allowed to open. 251 // Values above 2^60 are invalid. 252 // If not set, it will default to 100. 253 // If set to a negative value, it doesn't allow any bidirectional streams. 254 MaxIncomingStreams int64 255 // MaxIncomingUniStreams is the maximum number of concurrent unidirectional streams that a peer is allowed to open. 256 // Values above 2^60 are invalid. 257 // If not set, it will default to 100. 258 // If set to a negative value, it doesn't allow any unidirectional streams. 259 MaxIncomingUniStreams int64 260 // The StatelessResetKey is used to generate stateless reset tokens. 261 // If no key is configured, sending of stateless resets is disabled. 262 StatelessResetKey []byte 263 // KeepAlive defines whether this peer will periodically send a packet to keep the connection alive. 264 KeepAlive bool 265 // QUIC Event Tracer (see https://github.com/google/quic-trace). 266 // Warning: Support for quic-trace will soon be dropped in favor of qlog. 267 // It is disabled by default. Use the "quictrace" build tag to enable (e.g. go build -tags quictrace). 268 QuicTracer quictrace.Tracer 269 Tracer logging.Tracer 270} 271 272// A Listener for incoming QUIC connections 273type Listener interface { 274 // Close the server. All active sessions will be closed. 275 Close() error 276 // Addr returns the local network addr that the server is listening on. 277 Addr() net.Addr 278 // Accept returns new sessions. It should be called in a loop. 279 Accept(context.Context) (Session, error) 280} 281 282// An EarlyListener listens for incoming QUIC connections, 283// and returns them before the handshake completes. 284type EarlyListener interface { 285 // Close the server. All active sessions will be closed. 286 Close() error 287 // Addr returns the local network addr that the server is listening on. 288 Addr() net.Addr 289 // Accept returns new early sessions. It should be called in a loop. 290 Accept(context.Context) (EarlySession, error) 291} 292