]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/golang.org/x/net/http2/http2.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / golang.org / x / net / http2 / http2.go
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.
16 //
17 package http2 // import "golang.org/x/net/http2"
18
19 import (
20 "bufio"
21 "crypto/tls"
22 "errors"
23 "fmt"
24 "io"
25 "net/http"
26 "os"
27 "sort"
28 "strconv"
29 "strings"
30 "sync"
31
32 "golang.org/x/net/http/httpguts"
33 )
34
35 var (
36 VerboseLogs bool
37 logFrameWrites bool
38 logFrameReads bool
39 inTests bool
40 )
41
42 func init() {
43 e := os.Getenv("GODEBUG")
44 if strings.Contains(e, "http2debug=1") {
45 VerboseLogs = true
46 }
47 if strings.Contains(e, "http2debug=2") {
48 VerboseLogs = true
49 logFrameWrites = true
50 logFrameReads = true
51 }
52 }
53
54 const (
55 // ClientPreface is the string that must be sent by new
56 // connections from clients.
57 ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
58
59 // SETTINGS_MAX_FRAME_SIZE default
60 // http://http2.github.io/http2-spec/#rfc.section.6.5.2
61 initialMaxFrameSize = 16384
62
63 // NextProtoTLS is the NPN/ALPN protocol negotiated during
64 // HTTP/2's TLS setup.
65 NextProtoTLS = "h2"
66
67 // http://http2.github.io/http2-spec/#SettingValues
68 initialHeaderTableSize = 4096
69
70 initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
71
72 defaultMaxReadFrameSize = 1 << 20
73 )
74
75 var (
76 clientPreface = []byte(ClientPreface)
77 )
78
79 type streamState int
80
81 // HTTP/2 stream states.
82 //
83 // See http://tools.ietf.org/html/rfc7540#section-5.1.
84 //
85 // For simplicity, the server code merges "reserved (local)" into
86 // "half-closed (remote)". This is one less state transition to track.
87 // The only downside is that we send PUSH_PROMISEs slightly less
88 // liberally than allowable. More discussion here:
89 // https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
90 //
91 // "reserved (remote)" is omitted since the client code does not
92 // support server push.
93 const (
94 stateIdle streamState = iota
95 stateOpen
96 stateHalfClosedLocal
97 stateHalfClosedRemote
98 stateClosed
99 )
100
101 var stateName = [...]string{
102 stateIdle: "Idle",
103 stateOpen: "Open",
104 stateHalfClosedLocal: "HalfClosedLocal",
105 stateHalfClosedRemote: "HalfClosedRemote",
106 stateClosed: "Closed",
107 }
108
109 func (st streamState) String() string {
110 return stateName[st]
111 }
112
113 // Setting is a setting parameter: which setting it is, and its value.
114 type Setting struct {
115 // ID is which setting is being set.
116 // See http://http2.github.io/http2-spec/#SettingValues
117 ID SettingID
118
119 // Val is the value.
120 Val uint32
121 }
122
123 func (s Setting) String() string {
124 return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
125 }
126
127 // Valid reports whether the setting is valid.
128 func (s Setting) Valid() error {
129 // Limits and error codes from 6.5.2 Defined SETTINGS Parameters
130 switch s.ID {
131 case SettingEnablePush:
132 if s.Val != 1 && s.Val != 0 {
133 return ConnectionError(ErrCodeProtocol)
134 }
135 case SettingInitialWindowSize:
136 if s.Val > 1<<31-1 {
137 return ConnectionError(ErrCodeFlowControl)
138 }
139 case SettingMaxFrameSize:
140 if s.Val < 16384 || s.Val > 1<<24-1 {
141 return ConnectionError(ErrCodeProtocol)
142 }
143 }
144 return nil
145 }
146
147 // A SettingID is an HTTP/2 setting as defined in
148 // http://http2.github.io/http2-spec/#iana-settings
149 type SettingID uint16
150
151 const (
152 SettingHeaderTableSize SettingID = 0x1
153 SettingEnablePush SettingID = 0x2
154 SettingMaxConcurrentStreams SettingID = 0x3
155 SettingInitialWindowSize SettingID = 0x4
156 SettingMaxFrameSize SettingID = 0x5
157 SettingMaxHeaderListSize SettingID = 0x6
158 )
159
160 var settingName = map[SettingID]string{
161 SettingHeaderTableSize: "HEADER_TABLE_SIZE",
162 SettingEnablePush: "ENABLE_PUSH",
163 SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
164 SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
165 SettingMaxFrameSize: "MAX_FRAME_SIZE",
166 SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
167 }
168
169 func (s SettingID) String() string {
170 if v, ok := settingName[s]; ok {
171 return v
172 }
173 return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
174 }
175
176 var (
177 errInvalidHeaderFieldName = errors.New("http2: invalid header field name")
178 errInvalidHeaderFieldValue = errors.New("http2: invalid header field value")
179 )
180
181 // validWireHeaderFieldName reports whether v is a valid header field
182 // name (key). See httpguts.ValidHeaderName for the base rules.
183 //
184 // Further, http2 says:
185 // "Just as in HTTP/1.x, header field names are strings of ASCII
186 // characters that are compared in a case-insensitive
187 // fashion. However, header field names MUST be converted to
188 // lowercase prior to their encoding in HTTP/2. "
189 func validWireHeaderFieldName(v string) bool {
190 if len(v) == 0 {
191 return false
192 }
193 for _, r := range v {
194 if !httpguts.IsTokenRune(r) {
195 return false
196 }
197 if 'A' <= r && r <= 'Z' {
198 return false
199 }
200 }
201 return true
202 }
203
204 func httpCodeString(code int) string {
205 switch code {
206 case 200:
207 return "200"
208 case 404:
209 return "404"
210 }
211 return strconv.Itoa(code)
212 }
213
214 // from pkg io
215 type stringWriter interface {
216 WriteString(s string) (n int, err error)
217 }
218
219 // A gate lets two goroutines coordinate their activities.
220 type gate chan struct{}
221
222 func (g gate) Done() { g <- struct{}{} }
223 func (g gate) Wait() { <-g }
224
225 // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
226 type closeWaiter chan struct{}
227
228 // Init makes a closeWaiter usable.
229 // It exists because so a closeWaiter value can be placed inside a
230 // larger struct and have the Mutex and Cond's memory in the same
231 // allocation.
232 func (cw *closeWaiter) Init() {
233 *cw = make(chan struct{})
234 }
235
236 // Close marks the closeWaiter as closed and unblocks any waiters.
237 func (cw closeWaiter) Close() {
238 close(cw)
239 }
240
241 // Wait waits for the closeWaiter to become closed.
242 func (cw closeWaiter) Wait() {
243 <-cw
244 }
245
246 // bufferedWriter is a buffered writer that writes to w.
247 // Its buffered writer is lazily allocated as needed, to minimize
248 // idle memory usage with many connections.
249 type bufferedWriter struct {
250 w io.Writer // immutable
251 bw *bufio.Writer // non-nil when data is buffered
252 }
253
254 func newBufferedWriter(w io.Writer) *bufferedWriter {
255 return &bufferedWriter{w: w}
256 }
257
258 // bufWriterPoolBufferSize is the size of bufio.Writer's
259 // buffers created using bufWriterPool.
260 //
261 // TODO: pick a less arbitrary value? this is a bit under
262 // (3 x typical 1500 byte MTU) at least. Other than that,
263 // not much thought went into it.
264 const bufWriterPoolBufferSize = 4 << 10
265
266 var bufWriterPool = sync.Pool{
267 New: func() interface{} {
268 return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
269 },
270 }
271
272 func (w *bufferedWriter) Available() int {
273 if w.bw == nil {
274 return bufWriterPoolBufferSize
275 }
276 return w.bw.Available()
277 }
278
279 func (w *bufferedWriter) Write(p []byte) (n int, err error) {
280 if w.bw == nil {
281 bw := bufWriterPool.Get().(*bufio.Writer)
282 bw.Reset(w.w)
283 w.bw = bw
284 }
285 return w.bw.Write(p)
286 }
287
288 func (w *bufferedWriter) Flush() error {
289 bw := w.bw
290 if bw == nil {
291 return nil
292 }
293 err := bw.Flush()
294 bw.Reset(nil)
295 bufWriterPool.Put(bw)
296 w.bw = nil
297 return err
298 }
299
300 func mustUint31(v int32) uint32 {
301 if v < 0 || v > 2147483647 {
302 panic("out of range")
303 }
304 return uint32(v)
305 }
306
307 // bodyAllowedForStatus reports whether a given response status code
308 // permits a body. See RFC 7230, section 3.3.
309 func bodyAllowedForStatus(status int) bool {
310 switch {
311 case status >= 100 && status <= 199:
312 return false
313 case status == 204:
314 return false
315 case status == 304:
316 return false
317 }
318 return true
319 }
320
321 type httpError struct {
322 msg string
323 timeout bool
324 }
325
326 func (e *httpError) Error() string { return e.msg }
327 func (e *httpError) Timeout() bool { return e.timeout }
328 func (e *httpError) Temporary() bool { return true }
329
330 var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
331
332 type connectionStater interface {
333 ConnectionState() tls.ConnectionState
334 }
335
336 var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
337
338 type sorter struct {
339 v []string // owned by sorter
340 }
341
342 func (s *sorter) Len() int { return len(s.v) }
343 func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
344 func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
345
346 // Keys returns the sorted keys of h.
347 //
348 // The returned slice is only valid until s used again or returned to
349 // its pool.
350 func (s *sorter) Keys(h http.Header) []string {
351 keys := s.v[:0]
352 for k := range h {
353 keys = append(keys, k)
354 }
355 s.v = keys
356 sort.Sort(s)
357 return keys
358 }
359
360 func (s *sorter) SortStrings(ss []string) {
361 // Our sorter works on s.v, which sorter owns, so
362 // stash it away while we sort the user's buffer.
363 save := s.v
364 s.v = ss
365 sort.Sort(s)
366 s.v = save
367 }
368
369 // validPseudoPath reports whether v is a valid :path pseudo-header
370 // value. It must be either:
371 //
372 // *) a non-empty string starting with '/'
373 // *) the string '*', for OPTIONS requests.
374 //
375 // For now this is only used a quick check for deciding when to clean
376 // up Opaque URLs before sending requests from the Transport.
377 // See golang.org/issue/16847
378 //
379 // We used to enforce that the path also didn't start with "//", but
380 // Google's GFE accepts such paths and Chrome sends them, so ignore
381 // that part of the spec. See golang.org/issue/19103.
382 func validPseudoPath(v string) bool {
383 return (len(v) > 0 && v[0] == '/') || v == "*"
384 }