blob: 954793cfc060f2592f5f215769581d644b58337b [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 (
// A transportError is a transport error code from RFC 9000 Section 20.1.
// The transportError type doesn't implement the error interface to ensure we always
// distinguish between errors sent to and received from the peer.
// See the localTransportError and peerTransportError types below.
type transportError uint64
const (
errNo = transportError(0x00)
errInternal = transportError(0x01)
errConnectionRefused = transportError(0x02)
errFlowControl = transportError(0x03)
errStreamLimit = transportError(0x04)
errStreamState = transportError(0x05)
errFinalSize = transportError(0x06)
errFrameEncoding = transportError(0x07)
errTransportParameter = transportError(0x08)
errConnectionIDLimit = transportError(0x09)
errProtocolViolation = transportError(0x0a)
errInvalidToken = transportError(0x0b)
errApplicationError = transportError(0x0c)
errCryptoBufferExceeded = transportError(0x0d)
errKeyUpdateError = transportError(0x0e)
errAEADLimitReached = transportError(0x0f)
errNoViablePath = transportError(0x10)
errTLSBase = transportError(0x0100) // 0x0100-0x01ff; base + TLS code
func (e transportError) String() string {
switch e {
case errNo:
return "NO_ERROR"
case errInternal:
case errConnectionRefused:
case errFlowControl:
case errStreamLimit:
case errStreamState:
case errFinalSize:
case errFrameEncoding:
case errTransportParameter:
case errConnectionIDLimit:
case errProtocolViolation:
case errInvalidToken:
case errApplicationError:
case errCryptoBufferExceeded:
case errKeyUpdateError:
case errAEADLimitReached:
case errNoViablePath:
if e >= 0x0100 && e <= 0x01ff {
return fmt.Sprintf("CRYPTO_ERROR(%v)", uint64(e)&0xff)
return fmt.Sprintf("ERROR %d", uint64(e))
// A localTransportError is an error sent to the peer.
type localTransportError struct {
code transportError
reason string
func (e localTransportError) Error() string {
if e.reason == "" {
return fmt.Sprintf("closed connection: %v", e.code)
return fmt.Sprintf("closed connection: %v: %q", e.code, e.reason)
// A peerTransportError is an error received from the peer.
type peerTransportError struct {
code transportError
reason string
func (e peerTransportError) Error() string {
return fmt.Sprintf("peer closed connection: %v: %q", e.code, e.reason)
// A StreamErrorCode is an application protocol error code (RFC 9000, Section 20.2)
// indicating whay a stream is being closed.
type StreamErrorCode uint64
func (e StreamErrorCode) Error() string {
return fmt.Sprintf("stream error code %v", uint64(e))
// An ApplicationError is an application protocol error code (RFC 9000, Section 20.2).
// Application protocol errors may be sent when terminating a stream or connection.
type ApplicationError struct {
Code uint64
Reason string
func (e *ApplicationError) Error() string {
// TODO: Include the Reason string here, but sanitize it first.
return fmt.Sprintf("AppError %v", e.Code)
// Is reports a match if err is an *ApplicationError with a matching Code.
func (e *ApplicationError) Is(err error) bool {
e2, ok := err.(*ApplicationError)
return ok && e2.Code == e.Code