1// Copyright 2014 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package http2
6
7import (
8	"errors"
9	"fmt"
10)
11
12// An ErrCode is an unsigned 32-bit error code as defined in the HTTP/2 spec.
13type ErrCode uint32
14
15const (
16	ErrCodeNo                 ErrCode = 0x0
17	ErrCodeProtocol           ErrCode = 0x1
18	ErrCodeInternal           ErrCode = 0x2
19	ErrCodeFlowControl        ErrCode = 0x3
20	ErrCodeSettingsTimeout    ErrCode = 0x4
21	ErrCodeStreamClosed       ErrCode = 0x5
22	ErrCodeFrameSize          ErrCode = 0x6
23	ErrCodeRefusedStream      ErrCode = 0x7
24	ErrCodeCancel             ErrCode = 0x8
25	ErrCodeCompression        ErrCode = 0x9
26	ErrCodeConnect            ErrCode = 0xa
27	ErrCodeEnhanceYourCalm    ErrCode = 0xb
28	ErrCodeInadequateSecurity ErrCode = 0xc
29	ErrCodeHTTP11Required     ErrCode = 0xd
30)
31
32var errCodeName = map[ErrCode]string{
33	ErrCodeNo:                 "NO_ERROR",
34	ErrCodeProtocol:           "PROTOCOL_ERROR",
35	ErrCodeInternal:           "INTERNAL_ERROR",
36	ErrCodeFlowControl:        "FLOW_CONTROL_ERROR",
37	ErrCodeSettingsTimeout:    "SETTINGS_TIMEOUT",
38	ErrCodeStreamClosed:       "STREAM_CLOSED",
39	ErrCodeFrameSize:          "FRAME_SIZE_ERROR",
40	ErrCodeRefusedStream:      "REFUSED_STREAM",
41	ErrCodeCancel:             "CANCEL",
42	ErrCodeCompression:        "COMPRESSION_ERROR",
43	ErrCodeConnect:            "CONNECT_ERROR",
44	ErrCodeEnhanceYourCalm:    "ENHANCE_YOUR_CALM",
45	ErrCodeInadequateSecurity: "INADEQUATE_SECURITY",
46	ErrCodeHTTP11Required:     "HTTP_1_1_REQUIRED",
47}
48
49func (e ErrCode) String() string {
50	if s, ok := errCodeName[e]; ok {
51		return s
52	}
53	return fmt.Sprintf("unknown error code 0x%x", uint32(e))
54}
55
56// ConnectionError is an error that results in the termination of the
57// entire connection.
58type ConnectionError ErrCode
59
60func (e ConnectionError) Error() string { return fmt.Sprintf("connection error: %s", ErrCode(e)) }
61
62// StreamError is an error that only affects one stream within an
63// HTTP/2 connection.
64type StreamError struct {
65	StreamID uint32
66	Code     ErrCode
67	Cause    error // optional additional detail
68}
69
70func streamError(id uint32, code ErrCode) StreamError {
71	return StreamError{StreamID: id, Code: code}
72}
73
74func (e StreamError) Error() string {
75	if e.Cause != nil {
76		return fmt.Sprintf("stream error: stream ID %d; %v; %v", e.StreamID, e.Code, e.Cause)
77	}
78	return fmt.Sprintf("stream error: stream ID %d; %v", e.StreamID, e.Code)
79}
80
81// 6.9.1 The Flow Control Window
82// "If a sender receives a WINDOW_UPDATE that causes a flow control
83// window to exceed this maximum it MUST terminate either the stream
84// or the connection, as appropriate. For streams, [...]; for the
85// connection, a GOAWAY frame with a FLOW_CONTROL_ERROR code."
86type goAwayFlowError struct{}
87
88func (goAwayFlowError) Error() string { return "connection exceeded flow control window size" }
89
90// connError represents an HTTP/2 ConnectionError error code, along
91// with a string (for debugging) explaining why.
92//
93// Errors of this type are only returned by the frame parser functions
94// and converted into ConnectionError(Code), after stashing away
95// the Reason into the Framer's errDetail field, accessible via
96// the (*Framer).ErrorDetail method.
97type connError struct {
98	Code   ErrCode // the ConnectionError error code
99	Reason string  // additional reason
100}
101
102func (e connError) Error() string {
103	return fmt.Sprintf("http2: connection error: %v: %v", e.Code, e.Reason)
104}
105
106type pseudoHeaderError string
107
108func (e pseudoHeaderError) Error() string {
109	return fmt.Sprintf("invalid pseudo-header %q", string(e))
110}
111
112type duplicatePseudoHeaderError string
113
114func (e duplicatePseudoHeaderError) Error() string {
115	return fmt.Sprintf("duplicate pseudo-header %q", string(e))
116}
117
118type headerFieldNameError string
119
120func (e headerFieldNameError) Error() string {
121	return fmt.Sprintf("invalid header field name %q", string(e))
122}
123
124type headerFieldValueError string
125
126func (e headerFieldValueError) Error() string {
127	return fmt.Sprintf("invalid header field value %q", string(e))
128}
129
130var (
131	errMixPseudoHeaderTypes = errors.New("mix of request and response pseudo headers")
132	errPseudoAfterRegular   = errors.New("pseudo header field after regular")
133)
134