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
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.
16package http2
17
18import (
19	"bufio"
20	"crypto/tls"
21	"errors"
22	"fmt"
23	"io"
24	"net/http"
25	"os"
26	"sort"
27	"strconv"
28	"strings"
29	"sync"
30)
31
32var (
33	VerboseLogs    bool
34	logFrameWrites bool
35	logFrameReads  bool
36)
37
38func init() {
39	e := os.Getenv("GODEBUG")
40	if strings.Contains(e, "http2debug=1") {
41		VerboseLogs = true
42	}
43	if strings.Contains(e, "http2debug=2") {
44		VerboseLogs = true
45		logFrameWrites = true
46		logFrameReads = true
47	}
48}
49
50const (
51	// ClientPreface is the string that must be sent by new
52	// connections from clients.
53	ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
54
55	// SETTINGS_MAX_FRAME_SIZE default
56	// http://http2.github.io/http2-spec/#rfc.section.6.5.2
57	initialMaxFrameSize = 16384
58
59	// NextProtoTLS is the NPN/ALPN protocol negotiated during
60	// HTTP/2's TLS setup.
61	NextProtoTLS = "h2"
62
63	// http://http2.github.io/http2-spec/#SettingValues
64	initialHeaderTableSize = 4096
65
66	initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
67
68	defaultMaxReadFrameSize = 1 << 20
69)
70
71var (
72	clientPreface = []byte(ClientPreface)
73)
74
75type streamState int
76
77const (
78	stateIdle streamState = iota
79	stateOpen
80	stateHalfClosedLocal
81	stateHalfClosedRemote
82	stateResvLocal
83	stateResvRemote
84	stateClosed
85)
86
87var stateName = [...]string{
88	stateIdle:             "Idle",
89	stateOpen:             "Open",
90	stateHalfClosedLocal:  "HalfClosedLocal",
91	stateHalfClosedRemote: "HalfClosedRemote",
92	stateResvLocal:        "ResvLocal",
93	stateResvRemote:       "ResvRemote",
94	stateClosed:           "Closed",
95}
96
97func (st streamState) String() string {
98	return stateName[st]
99}
100
101// Setting is a setting parameter: which setting it is, and its value.
102type Setting struct {
103	// ID is which setting is being set.
104	// See http://http2.github.io/http2-spec/#SettingValues
105	ID SettingID
106
107	// Val is the value.
108	Val uint32
109}
110
111func (s Setting) String() string {
112	return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
113}
114
115// Valid reports whether the setting is valid.
116func (s Setting) Valid() error {
117	// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
118	switch s.ID {
119	case SettingEnablePush:
120		if s.Val != 1 && s.Val != 0 {
121			return ConnectionError(ErrCodeProtocol)
122		}
123	case SettingInitialWindowSize:
124		if s.Val > 1<<31-1 {
125			return ConnectionError(ErrCodeFlowControl)
126		}
127	case SettingMaxFrameSize:
128		if s.Val < 16384 || s.Val > 1<<24-1 {
129			return ConnectionError(ErrCodeProtocol)
130		}
131	}
132	return nil
133}
134
135// A SettingID is an HTTP/2 setting as defined in
136// http://http2.github.io/http2-spec/#iana-settings
137type SettingID uint16
138
139const (
140	SettingHeaderTableSize      SettingID = 0x1
141	SettingEnablePush           SettingID = 0x2
142	SettingMaxConcurrentStreams SettingID = 0x3
143	SettingInitialWindowSize    SettingID = 0x4
144	SettingMaxFrameSize         SettingID = 0x5
145	SettingMaxHeaderListSize    SettingID = 0x6
146)
147
148var settingName = map[SettingID]string{
149	SettingHeaderTableSize:      "HEADER_TABLE_SIZE",
150	SettingEnablePush:           "ENABLE_PUSH",
151	SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
152	SettingInitialWindowSize:    "INITIAL_WINDOW_SIZE",
153	SettingMaxFrameSize:         "MAX_FRAME_SIZE",
154	SettingMaxHeaderListSize:    "MAX_HEADER_LIST_SIZE",
155}
156
157func (s SettingID) String() string {
158	if v, ok := settingName[s]; ok {
159		return v
160	}
161	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
162}
163
164var (
165	errInvalidHeaderFieldName  = errors.New("http2: invalid header field name")
166	errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
167)
168
169// validHeaderFieldName reports whether v is a valid header field name (key).
170//  RFC 7230 says:
171//   header-field   = field-name ":" OWS field-value OWS
172//   field-name     = token
173//   tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." /
174//           "^" / "_" / "
175// Further, http2 says:
176//   "Just as in HTTP/1.x, header field names are strings of ASCII
177//   characters that are compared in a case-insensitive
178//   fashion. However, header field names MUST be converted to
179//   lowercase prior to their encoding in HTTP/2. "
180func validHeaderFieldName(v string) bool {
181	if len(v) == 0 {
182		return false
183	}
184	for _, r := range v {
185		if int(r) >= len(isTokenTable) || ('A' <= r && r <= 'Z') {
186			return false
187		}
188		if !isTokenTable[byte(r)] {
189			return false
190		}
191	}
192	return true
193}
194
195// validHeaderFieldValue reports whether v is a valid header field value.
196//
197// RFC 7230 says:
198//  field-value    = *( field-content / obs-fold )
199//  obj-fold       =  N/A to http2, and deprecated
200//  field-content  = field-vchar [ 1*( SP / HTAB ) field-vchar ]
201//  field-vchar    = VCHAR / obs-text
202//  obs-text       = %x80-FF
203//  VCHAR          = "any visible [USASCII] character"
204//
205// http2 further says: "Similarly, HTTP/2 allows header field values
206// that are not valid. While most of the values that can be encoded
207// will not alter header field parsing, carriage return (CR, ASCII
208// 0xd), line feed (LF, ASCII 0xa), and the zero character (NUL, ASCII
209// 0x0) might be exploited by an attacker if they are translated
210// verbatim. Any request or response that contains a character not
211// permitted in a header field value MUST be treated as malformed
212// (Section 8.1.2.6). Valid characters are defined by the
213// field-content ABNF rule in Section 3.2 of [RFC7230]."
214//
215// This function does not (yet?) properly handle the rejection of
216// strings that begin or end with SP or HTAB.
217func validHeaderFieldValue(v string) bool {
218	for i := 0; i < len(v); i++ {
219		if b := v[i]; b < ' ' && b != '\t' || b == 0x7f {
220			return false
221		}
222	}
223	return true
224}
225
226var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n)
227
228func init() {
229	for i := 100; i <= 999; i++ {
230		if v := http.StatusText(i); v != "" {
231			httpCodeStringCommon[i] = strconv.Itoa(i)
232		}
233	}
234}
235
236func httpCodeString(code int) string {
237	if s, ok := httpCodeStringCommon[code]; ok {
238		return s
239	}
240	return strconv.Itoa(code)
241}
242
243// from pkg io
244type stringWriter interface {
245	WriteString(s string) (n int, err error)
246}
247
248// A gate lets two goroutines coordinate their activities.
249type gate chan struct{}
250
251func (g gate) Done() { g <- struct{}{} }
252func (g gate) Wait() { <-g }
253
254// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
255type closeWaiter chan struct{}
256
257// Init makes a closeWaiter usable.
258// It exists because so a closeWaiter value can be placed inside a
259// larger struct and have the Mutex and Cond's memory in the same
260// allocation.
261func (cw *closeWaiter) Init() {
262	*cw = make(chan struct{})
263}
264
265// Close marks the closeWaiter as closed and unblocks any waiters.
266func (cw closeWaiter) Close() {
267	close(cw)
268}
269
270// Wait waits for the closeWaiter to become closed.
271func (cw closeWaiter) Wait() {
272	<-cw
273}
274
275// bufferedWriter is a buffered writer that writes to w.
276// Its buffered writer is lazily allocated as needed, to minimize
277// idle memory usage with many connections.
278type bufferedWriter struct {
279	w  io.Writer     // immutable
280	bw *bufio.Writer // non-nil when data is buffered
281}
282
283func newBufferedWriter(w io.Writer) *bufferedWriter {
284	return &bufferedWriter{w: w}
285}
286
287var bufWriterPool = sync.Pool{
288	New: func() interface{} {
289		// TODO: pick something better? this is a bit under
290		// (3 x typical 1500 byte MTU) at least.
291		return bufio.NewWriterSize(nil, 4<<10)
292	},
293}
294
295func (w *bufferedWriter) Write(p []byte) (n int, err error) {
296	if w.bw == nil {
297		bw := bufWriterPool.Get().(*bufio.Writer)
298		bw.Reset(w.w)
299		w.bw = bw
300	}
301	return w.bw.Write(p)
302}
303
304func (w *bufferedWriter) Flush() error {
305	bw := w.bw
306	if bw == nil {
307		return nil
308	}
309	err := bw.Flush()
310	bw.Reset(nil)
311	bufWriterPool.Put(bw)
312	w.bw = nil
313	return err
314}
315
316func mustUint31(v int32) uint32 {
317	if v < 0 || v > 2147483647 {
318		panic("out of range")
319	}
320	return uint32(v)
321}
322
323// bodyAllowedForStatus reports whether a given response status code
324// permits a body. See RFC2616, section 4.4.
325func bodyAllowedForStatus(status int) bool {
326	switch {
327	case status >= 100 && status <= 199:
328		return false
329	case status == 204:
330		return false
331	case status == 304:
332		return false
333	}
334	return true
335}
336
337type httpError struct {
338	msg     string
339	timeout bool
340}
341
342func (e *httpError) Error() string   { return e.msg }
343func (e *httpError) Timeout() bool   { return e.timeout }
344func (e *httpError) Temporary() bool { return true }
345
346var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
347
348var isTokenTable = [127]bool{
349	'!':  true,
350	'#':  true,
351	'$':  true,
352	'%':  true,
353	'&':  true,
354	'\'': true,
355	'*':  true,
356	'+':  true,
357	'-':  true,
358	'.':  true,
359	'0':  true,
360	'1':  true,
361	'2':  true,
362	'3':  true,
363	'4':  true,
364	'5':  true,
365	'6':  true,
366	'7':  true,
367	'8':  true,
368	'9':  true,
369	'A':  true,
370	'B':  true,
371	'C':  true,
372	'D':  true,
373	'E':  true,
374	'F':  true,
375	'G':  true,
376	'H':  true,
377	'I':  true,
378	'J':  true,
379	'K':  true,
380	'L':  true,
381	'M':  true,
382	'N':  true,
383	'O':  true,
384	'P':  true,
385	'Q':  true,
386	'R':  true,
387	'S':  true,
388	'T':  true,
389	'U':  true,
390	'W':  true,
391	'V':  true,
392	'X':  true,
393	'Y':  true,
394	'Z':  true,
395	'^':  true,
396	'_':  true,
397	'`':  true,
398	'a':  true,
399	'b':  true,
400	'c':  true,
401	'd':  true,
402	'e':  true,
403	'f':  true,
404	'g':  true,
405	'h':  true,
406	'i':  true,
407	'j':  true,
408	'k':  true,
409	'l':  true,
410	'm':  true,
411	'n':  true,
412	'o':  true,
413	'p':  true,
414	'q':  true,
415	'r':  true,
416	's':  true,
417	't':  true,
418	'u':  true,
419	'v':  true,
420	'w':  true,
421	'x':  true,
422	'y':  true,
423	'z':  true,
424	'|':  true,
425	'~':  true,
426}
427
428type connectionStater interface {
429	ConnectionState() tls.ConnectionState
430}
431
432var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
433
434type sorter struct {
435	v []string // owned by sorter
436}
437
438func (s *sorter) Len() int           { return len(s.v) }
439func (s *sorter) Swap(i, j int)      { s.v[i], s.v[j] = s.v[j], s.v[i] }
440func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
441
442// Keys returns the sorted keys of h.
443//
444// The returned slice is only valid until s used again or returned to
445// its pool.
446func (s *sorter) Keys(h http.Header) []string {
447	keys := s.v[:0]
448	for k := range h {
449		keys = append(keys, k)
450	}
451	s.v = keys
452	sort.Sort(s)
453	return keys
454}
455
456func (s *sorter) SortStrings(ss []string) {
457	// Our sorter works on s.v, which sorter owners, so
458	// stash it away while we sort the user's buffer.
459	save := s.v
460	s.v = ss
461	sort.Sort(s)
462	s.v = save
463}
464