| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| //go:build go1.21 |
| |
| package quic |
| |
| import ( |
| "time" |
| ) |
| |
| // QUIC versions. |
| // We only support v1 at this time. |
| const ( |
| quicVersion1 = 1 |
| quicVersion2 = 0x6b3343cf // https://www.rfc-editor.org/rfc/rfc9369 |
| ) |
| |
| // connIDLen is the length in bytes of connection IDs chosen by this package. |
| // Since 1-RTT packets don't include a connection ID length field, |
| // we use a consistent length for all our IDs. |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-5.1-6 |
| const connIDLen = 8 |
| |
| // Local values of various transport parameters. |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2 |
| const ( |
| defaultMaxIdleTimeout = 30 * time.Second // max_idle_timeout |
| |
| // The max_udp_payload_size transport parameter is the size of our |
| // network receive buffer. |
| // |
| // Set this to the largest UDP packet that can be sent over |
| // Ethernet without using jumbo frames: 1500 byte Ethernet frame, |
| // minus 20 byte IPv4 header and 8 byte UDP header. |
| // |
| // The maximum possible UDP payload is 65527 bytes. Supporting this |
| // without wasting memory in unused receive buffers will require some |
| // care. For now, just limit ourselves to the most common case. |
| maxUDPPayloadSize = 1472 |
| |
| ackDelayExponent = 3 // ack_delay_exponent |
| maxAckDelay = 25 * time.Millisecond // max_ack_delay |
| |
| // The active_conn_id_limit transport parameter is the maximum |
| // number of connection IDs from the peer we're willing to store. |
| // |
| // maxPeerActiveConnIDLimit is the maximum number of connection IDs |
| // we're willing to send to the peer. |
| // |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-18.2-6.2.1 |
| activeConnIDLimit = 2 |
| maxPeerActiveConnIDLimit = 4 |
| ) |
| |
| // Time limit for completing the handshake. |
| const defaultHandshakeTimeout = 10 * time.Second |
| |
| // Keep-alive ping frequency. |
| const defaultKeepAlivePeriod = 0 |
| |
| // Local timer granularity. |
| // https://www.rfc-editor.org/rfc/rfc9002.html#section-6.1.2-6 |
| const timerGranularity = 1 * time.Millisecond |
| |
| // The smallest allowed maximum datagram size. |
| // https://www.rfc-editor.org/rfc/rfc9000#section-14 |
| const smallestMaxDatagramSize = 1200 |
| |
| // Minimum size of a UDP datagram sent by a client carrying an Initial packet, |
| // or a server containing an ack-eliciting Initial packet. |
| // https://www.rfc-editor.org/rfc/rfc9000#section-14.1 |
| const paddedInitialDatagramSize = smallestMaxDatagramSize |
| |
| // Maximum number of streams of a given type which may be created. |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-4.6-2 |
| const maxStreamsLimit = 1 << 60 |
| |
| // Maximum number of streams we will allow the peer to create implicitly. |
| // A stream ID that is used out of order results in all streams of that type |
| // with lower-numbered IDs also being opened. To limit the amount of work we |
| // will do in response to a single frame, we cap the peer's stream limit to |
| // this value. |
| const implicitStreamLimit = 100 |
| |
| // A connSide distinguishes between the client and server sides of a connection. |
| type connSide int8 |
| |
| const ( |
| clientSide = connSide(iota) |
| serverSide |
| ) |
| |
| func (s connSide) String() string { |
| switch s { |
| case clientSide: |
| return "client" |
| case serverSide: |
| return "server" |
| default: |
| return "BUG" |
| } |
| } |
| |
| func (s connSide) peer() connSide { |
| if s == clientSide { |
| return serverSide |
| } else { |
| return clientSide |
| } |
| } |
| |
| // A numberSpace is the context in which a packet number applies. |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-12.3-7 |
| type numberSpace byte |
| |
| const ( |
| initialSpace = numberSpace(iota) |
| handshakeSpace |
| appDataSpace |
| numberSpaceCount |
| ) |
| |
| func (n numberSpace) String() string { |
| switch n { |
| case initialSpace: |
| return "Initial" |
| case handshakeSpace: |
| return "Handshake" |
| case appDataSpace: |
| return "AppData" |
| default: |
| return "BUG" |
| } |
| } |
| |
| // A streamType is the type of a stream: bidirectional or unidirectional. |
| type streamType uint8 |
| |
| const ( |
| bidiStream = streamType(iota) |
| uniStream |
| streamTypeCount |
| ) |
| |
| func (s streamType) String() string { |
| switch s { |
| case bidiStream: |
| return "bidi" |
| case uniStream: |
| return "uni" |
| default: |
| return "BUG" |
| } |
| } |
| |
| // A streamID is a QUIC stream ID. |
| // https://www.rfc-editor.org/rfc/rfc9000.html#section-2.1 |
| type streamID uint64 |
| |
| // The two least significant bits of a stream ID indicate the initiator |
| // and directionality of the stream. The upper bits are the stream number. |
| // Each of the four possible combinations of initiator and direction |
| // each has a distinct number space. |
| const ( |
| clientInitiatedStreamBit = 0x0 |
| serverInitiatedStreamBit = 0x1 |
| initiatorStreamBitMask = 0x1 |
| |
| bidiStreamBit = 0x0 |
| uniStreamBit = 0x2 |
| dirStreamBitMask = 0x2 |
| ) |
| |
| func newStreamID(initiator connSide, typ streamType, num int64) streamID { |
| id := streamID(num << 2) |
| if typ == uniStream { |
| id |= uniStreamBit |
| } |
| if initiator == serverSide { |
| id |= serverInitiatedStreamBit |
| } |
| return id |
| } |
| |
| func (s streamID) initiator() connSide { |
| if s&initiatorStreamBitMask == serverInitiatedStreamBit { |
| return serverSide |
| } |
| return clientSide |
| } |
| |
| func (s streamID) num() int64 { |
| return int64(s) >> 2 |
| } |
| |
| func (s streamID) streamType() streamType { |
| if s&dirStreamBitMask == uniStreamBit { |
| return uniStream |
| } |
| return bidiStream |
| } |
| |
| // packetFate is the fate of a sent packet: Either acknowledged by the peer, |
| // or declared lost. |
| type packetFate byte |
| |
| const ( |
| packetLost = packetFate(iota) |
| packetAcked |
| ) |