blob: f7c1b765d7325bf3dd75da47bdf9e699f1087b3c [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.
package quic
import (
"time"
)
// 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 (
// 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
)
// A side distinguishes between the client and server sides of a connection.
type side int8
const (
clientSide = side(iota)
serverSide
)
func (s side) String() string {
switch s {
case clientSide:
return "client"
case serverSide:
return "server"
default:
return "BUG"
}
}
// 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
)
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
)
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 side, 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() side {
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
}