blob: 3e62d7cd94d9c4569c5aed5d34f461e58a56dd2f [file] [log] [blame]
// 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) qlogString() string {
switch s {
case bidiStream:
return "bidirectional"
case uniStream:
return "unidirectional"
default:
return "BUG"
}
}
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
)