blob: c7601c909ffb95d9a1987422099433b6d8a0bd5b [file] [log] [blame]
Holger Hildebrandtfa074992020-03-27 15:42:06 +00001// 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
5// Package http2 implements the HTTP/2 protocol.
6//
7// This package is low-level and intended to be used directly by very
8// few people. Most users will use it indirectly through the automatic
9// use by the net/http package (from Go 1.6 and later).
10// For use in earlier Go versions see ConfigureServer. (Transport support
11// requires Go 1.6 or later)
12//
13// See https://http2.github.io/ for more information on HTTP/2.
14//
15// See https://http2.golang.org/ for a test server running this code.
Holger Hildebrandtfa074992020-03-27 15:42:06 +000016package http2 // import "golang.org/x/net/http2"
17
18import (
19 "bufio"
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053020 "context"
Holger Hildebrandtfa074992020-03-27 15:42:06 +000021 "crypto/tls"
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053022 "errors"
Holger Hildebrandtfa074992020-03-27 15:42:06 +000023 "fmt"
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053024 "net"
Holger Hildebrandtfa074992020-03-27 15:42:06 +000025 "net/http"
26 "os"
27 "sort"
28 "strconv"
29 "strings"
30 "sync"
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053031 "time"
Holger Hildebrandtfa074992020-03-27 15:42:06 +000032
33 "golang.org/x/net/http/httpguts"
34)
35
36var (
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053037 VerboseLogs bool
38 logFrameWrites bool
39 logFrameReads bool
40 inTests bool
41 disableExtendedConnectProtocol bool
Holger Hildebrandtfa074992020-03-27 15:42:06 +000042)
43
44func init() {
45 e := os.Getenv("GODEBUG")
46 if strings.Contains(e, "http2debug=1") {
47 VerboseLogs = true
48 }
49 if strings.Contains(e, "http2debug=2") {
50 VerboseLogs = true
51 logFrameWrites = true
52 logFrameReads = true
53 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053054 if strings.Contains(e, "http2xconnect=0") {
55 disableExtendedConnectProtocol = true
56 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +000057}
58
59const (
60 // ClientPreface is the string that must be sent by new
61 // connections from clients.
62 ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
63
64 // SETTINGS_MAX_FRAME_SIZE default
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053065 // https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
Holger Hildebrandtfa074992020-03-27 15:42:06 +000066 initialMaxFrameSize = 16384
67
68 // NextProtoTLS is the NPN/ALPN protocol negotiated during
69 // HTTP/2's TLS setup.
70 NextProtoTLS = "h2"
71
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +053072 // https://httpwg.org/specs/rfc7540.html#SettingValues
Holger Hildebrandtfa074992020-03-27 15:42:06 +000073 initialHeaderTableSize = 4096
74
75 initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
76
77 defaultMaxReadFrameSize = 1 << 20
78)
79
80var (
81 clientPreface = []byte(ClientPreface)
82)
83
84type streamState int
85
86// HTTP/2 stream states.
87//
88// See http://tools.ietf.org/html/rfc7540#section-5.1.
89//
90// For simplicity, the server code merges "reserved (local)" into
91// "half-closed (remote)". This is one less state transition to track.
92// The only downside is that we send PUSH_PROMISEs slightly less
93// liberally than allowable. More discussion here:
94// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
95//
96// "reserved (remote)" is omitted since the client code does not
97// support server push.
98const (
99 stateIdle streamState = iota
100 stateOpen
101 stateHalfClosedLocal
102 stateHalfClosedRemote
103 stateClosed
104)
105
106var stateName = [...]string{
107 stateIdle: "Idle",
108 stateOpen: "Open",
109 stateHalfClosedLocal: "HalfClosedLocal",
110 stateHalfClosedRemote: "HalfClosedRemote",
111 stateClosed: "Closed",
112}
113
114func (st streamState) String() string {
115 return stateName[st]
116}
117
118// Setting is a setting parameter: which setting it is, and its value.
119type Setting struct {
120 // ID is which setting is being set.
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530121 // See https://httpwg.org/specs/rfc7540.html#SettingFormat
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000122 ID SettingID
123
124 // Val is the value.
125 Val uint32
126}
127
128func (s Setting) String() string {
129 return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
130}
131
132// Valid reports whether the setting is valid.
133func (s Setting) Valid() error {
134 // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
135 switch s.ID {
136 case SettingEnablePush:
137 if s.Val != 1 && s.Val != 0 {
138 return ConnectionError(ErrCodeProtocol)
139 }
140 case SettingInitialWindowSize:
141 if s.Val > 1<<31-1 {
142 return ConnectionError(ErrCodeFlowControl)
143 }
144 case SettingMaxFrameSize:
145 if s.Val < 16384 || s.Val > 1<<24-1 {
146 return ConnectionError(ErrCodeProtocol)
147 }
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530148 case SettingEnableConnectProtocol:
149 if s.Val != 1 && s.Val != 0 {
150 return ConnectionError(ErrCodeProtocol)
151 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000152 }
153 return nil
154}
155
156// A SettingID is an HTTP/2 setting as defined in
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530157// https://httpwg.org/specs/rfc7540.html#iana-settings
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000158type SettingID uint16
159
160const (
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530161 SettingHeaderTableSize SettingID = 0x1
162 SettingEnablePush SettingID = 0x2
163 SettingMaxConcurrentStreams SettingID = 0x3
164 SettingInitialWindowSize SettingID = 0x4
165 SettingMaxFrameSize SettingID = 0x5
166 SettingMaxHeaderListSize SettingID = 0x6
167 SettingEnableConnectProtocol SettingID = 0x8
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000168)
169
170var settingName = map[SettingID]string{
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530171 SettingHeaderTableSize: "HEADER_TABLE_SIZE",
172 SettingEnablePush: "ENABLE_PUSH",
173 SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
174 SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
175 SettingMaxFrameSize: "MAX_FRAME_SIZE",
176 SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
177 SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000178}
179
180func (s SettingID) String() string {
181 if v, ok := settingName[s]; ok {
182 return v
183 }
184 return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
185}
186
187// validWireHeaderFieldName reports whether v is a valid header field
188// name (key). See httpguts.ValidHeaderName for the base rules.
189//
190// Further, http2 says:
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530191//
192// "Just as in HTTP/1.x, header field names are strings of ASCII
193// characters that are compared in a case-insensitive
194// fashion. However, header field names MUST be converted to
195// lowercase prior to their encoding in HTTP/2. "
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000196func validWireHeaderFieldName(v string) bool {
197 if len(v) == 0 {
198 return false
199 }
200 for _, r := range v {
201 if !httpguts.IsTokenRune(r) {
202 return false
203 }
204 if 'A' <= r && r <= 'Z' {
205 return false
206 }
207 }
208 return true
209}
210
211func httpCodeString(code int) string {
212 switch code {
213 case 200:
214 return "200"
215 case 404:
216 return "404"
217 }
218 return strconv.Itoa(code)
219}
220
221// from pkg io
222type stringWriter interface {
223 WriteString(s string) (n int, err error)
224}
225
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000226// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
227type closeWaiter chan struct{}
228
229// Init makes a closeWaiter usable.
230// It exists because so a closeWaiter value can be placed inside a
231// larger struct and have the Mutex and Cond's memory in the same
232// allocation.
233func (cw *closeWaiter) Init() {
234 *cw = make(chan struct{})
235}
236
237// Close marks the closeWaiter as closed and unblocks any waiters.
238func (cw closeWaiter) Close() {
239 close(cw)
240}
241
242// Wait waits for the closeWaiter to become closed.
243func (cw closeWaiter) Wait() {
244 <-cw
245}
246
247// bufferedWriter is a buffered writer that writes to w.
248// Its buffered writer is lazily allocated as needed, to minimize
249// idle memory usage with many connections.
250type bufferedWriter struct {
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530251 _ incomparable
252 group synctestGroupInterface // immutable
253 conn net.Conn // immutable
254 bw *bufio.Writer // non-nil when data is buffered
255 byteTimeout time.Duration // immutable, WriteByteTimeout
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000256}
257
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530258func newBufferedWriter(group synctestGroupInterface, conn net.Conn, timeout time.Duration) *bufferedWriter {
259 return &bufferedWriter{
260 group: group,
261 conn: conn,
262 byteTimeout: timeout,
263 }
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000264}
265
266// bufWriterPoolBufferSize is the size of bufio.Writer's
267// buffers created using bufWriterPool.
268//
269// TODO: pick a less arbitrary value? this is a bit under
270// (3 x typical 1500 byte MTU) at least. Other than that,
271// not much thought went into it.
272const bufWriterPoolBufferSize = 4 << 10
273
274var bufWriterPool = sync.Pool{
275 New: func() interface{} {
276 return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
277 },
278}
279
280func (w *bufferedWriter) Available() int {
281 if w.bw == nil {
282 return bufWriterPoolBufferSize
283 }
284 return w.bw.Available()
285}
286
287func (w *bufferedWriter) Write(p []byte) (n int, err error) {
288 if w.bw == nil {
289 bw := bufWriterPool.Get().(*bufio.Writer)
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530290 bw.Reset((*bufferedWriterTimeoutWriter)(w))
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000291 w.bw = bw
292 }
293 return w.bw.Write(p)
294}
295
296func (w *bufferedWriter) Flush() error {
297 bw := w.bw
298 if bw == nil {
299 return nil
300 }
301 err := bw.Flush()
302 bw.Reset(nil)
303 bufWriterPool.Put(bw)
304 w.bw = nil
305 return err
306}
307
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530308type bufferedWriterTimeoutWriter bufferedWriter
309
310func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) {
311 return writeWithByteTimeout(w.group, w.conn, w.byteTimeout, p)
312}
313
314// writeWithByteTimeout writes to conn.
315// If more than timeout passes without any bytes being written to the connection,
316// the write fails.
317func writeWithByteTimeout(group synctestGroupInterface, conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
318 if timeout <= 0 {
319 return conn.Write(p)
320 }
321 for {
322 var now time.Time
323 if group == nil {
324 now = time.Now()
325 } else {
326 now = group.Now()
327 }
328 conn.SetWriteDeadline(now.Add(timeout))
329 nn, err := conn.Write(p[n:])
330 n += nn
331 if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) {
332 // Either we finished the write, made no progress, or hit the deadline.
333 // Whichever it is, we're done now.
334 conn.SetWriteDeadline(time.Time{})
335 return n, err
336 }
337 }
338}
339
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000340func mustUint31(v int32) uint32 {
341 if v < 0 || v > 2147483647 {
342 panic("out of range")
343 }
344 return uint32(v)
345}
346
347// bodyAllowedForStatus reports whether a given response status code
348// permits a body. See RFC 7230, section 3.3.
349func bodyAllowedForStatus(status int) bool {
350 switch {
351 case status >= 100 && status <= 199:
352 return false
353 case status == 204:
354 return false
355 case status == 304:
356 return false
357 }
358 return true
359}
360
361type httpError struct {
Andrea Campanellaaec20bd2021-02-25 12:41:34 +0100362 _ incomparable
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000363 msg string
364 timeout bool
365}
366
367func (e *httpError) Error() string { return e.msg }
368func (e *httpError) Timeout() bool { return e.timeout }
369func (e *httpError) Temporary() bool { return true }
370
371var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
372
373type connectionStater interface {
374 ConnectionState() tls.ConnectionState
375}
376
377var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
378
379type sorter struct {
380 v []string // owned by sorter
381}
382
383func (s *sorter) Len() int { return len(s.v) }
384func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
385func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
386
387// Keys returns the sorted keys of h.
388//
389// The returned slice is only valid until s used again or returned to
390// its pool.
391func (s *sorter) Keys(h http.Header) []string {
392 keys := s.v[:0]
393 for k := range h {
394 keys = append(keys, k)
395 }
396 s.v = keys
397 sort.Sort(s)
398 return keys
399}
400
401func (s *sorter) SortStrings(ss []string) {
402 // Our sorter works on s.v, which sorter owns, so
403 // stash it away while we sort the user's buffer.
404 save := s.v
405 s.v = ss
406 sort.Sort(s)
407 s.v = save
408}
409
410// validPseudoPath reports whether v is a valid :path pseudo-header
411// value. It must be either:
412//
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530413// - a non-empty string starting with '/'
414// - the string '*', for OPTIONS requests.
Holger Hildebrandtfa074992020-03-27 15:42:06 +0000415//
416// For now this is only used a quick check for deciding when to clean
417// up Opaque URLs before sending requests from the Transport.
418// See golang.org/issue/16847
419//
420// We used to enforce that the path also didn't start with "//", but
421// Google's GFE accepts such paths and Chrome sends them, so ignore
422// that part of the spec. See golang.org/issue/19103.
423func validPseudoPath(v string) bool {
424 return (len(v) > 0 && v[0] == '/') || v == "*"
425}
Andrea Campanellaaec20bd2021-02-25 12:41:34 +0100426
427// incomparable is a zero-width, non-comparable type. Adding it to a struct
428// makes that struct also non-comparable, and generally doesn't add
429// any size (as long as it's first).
430type incomparable [0]func()
Akash Reddy Kankanala92dfdf82025-03-23 22:07:09 +0530431
432// synctestGroupInterface is the methods of synctestGroup used by Server and Transport.
433// It's defined as an interface here to let us keep synctestGroup entirely test-only
434// and not a part of non-test builds.
435type synctestGroupInterface interface {
436 Join()
437 Now() time.Time
438 NewTimer(d time.Duration) timer
439 AfterFunc(d time.Duration, f func()) timer
440 ContextWithTimeout(ctx context.Context, d time.Duration) (context.Context, context.CancelFunc)
441}