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