github.com/useflyent/fhttp@v0.0.0-20211004035111-333f430cfbbf/http2/http2.go (about) 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 "fmt" 23 "io" 24 "os" 25 "sort" 26 "strconv" 27 "strings" 28 "sync" 29 30 http "github.com/useflyent/fhttp" 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 // validWireHeaderFieldName reports whether v is a valid header field 177 // name (key). See httpguts.ValidHeaderName for the base rules. 178 // 179 // Further, http2 says: 180 // "Just as in HTTP/1.x, header field names are strings of ASCII 181 // characters that are compared in a case-insensitive 182 // fashion. However, header field names MUST be converted to 183 // lowercase prior to their encoding in HTTP/2. " 184 func validWireHeaderFieldName(v string) bool { 185 if len(v) == 0 { 186 return false 187 } 188 for _, r := range v { 189 if !httpguts.IsTokenRune(r) { 190 return false 191 } 192 if 'A' <= r && r <= 'Z' { 193 return false 194 } 195 } 196 return true 197 } 198 199 func httpCodeString(code int) string { 200 switch code { 201 case 200: 202 return "200" 203 case 404: 204 return "404" 205 } 206 return strconv.Itoa(code) 207 } 208 209 // from pkg io 210 type stringWriter interface { 211 WriteString(s string) (n int, err error) 212 } 213 214 // A gate lets two goroutines coordinate their activities. 215 type gate chan struct{} 216 217 func (g gate) Done() { g <- struct{}{} } 218 func (g gate) Wait() { <-g } 219 220 // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed). 221 type closeWaiter chan struct{} 222 223 // Init makes a closeWaiter usable. 224 // It exists because so a closeWaiter value can be placed inside a 225 // larger struct and have the Mutex and Cond's memory in the same 226 // allocation. 227 func (cw *closeWaiter) Init() { 228 *cw = make(chan struct{}) 229 } 230 231 // Close marks the closeWaiter as closed and unblocks any waiters. 232 func (cw closeWaiter) Close() { 233 close(cw) 234 } 235 236 // Wait waits for the closeWaiter to become closed. 237 func (cw closeWaiter) Wait() { 238 <-cw 239 } 240 241 // bufferedWriter is a buffered writer that writes to w. 242 // Its buffered writer is lazily allocated as needed, to minimize 243 // idle memory usage with many connections. 244 type bufferedWriter struct { 245 _ incomparable 246 w io.Writer // immutable 247 bw *bufio.Writer // non-nil when data is buffered 248 } 249 250 func newBufferedWriter(w io.Writer) *bufferedWriter { 251 return &bufferedWriter{w: w} 252 } 253 254 // bufWriterPoolBufferSize is the size of bufio.Writer's 255 // buffers created using bufWriterPool. 256 // 257 // TODO: pick a less arbitrary value? this is a bit under 258 // (3 x typical 1500 byte MTU) at least. Other than that, 259 // not much thought went into it. 260 const bufWriterPoolBufferSize = 4 << 10 261 262 var bufWriterPool = sync.Pool{ 263 New: func() interface{} { 264 return bufio.NewWriterSize(nil, bufWriterPoolBufferSize) 265 }, 266 } 267 268 func (w *bufferedWriter) Available() int { 269 if w.bw == nil { 270 return bufWriterPoolBufferSize 271 } 272 return w.bw.Available() 273 } 274 275 func (w *bufferedWriter) Write(p []byte) (n int, err error) { 276 if w.bw == nil { 277 bw := bufWriterPool.Get().(*bufio.Writer) 278 bw.Reset(w.w) 279 w.bw = bw 280 } 281 return w.bw.Write(p) 282 } 283 284 func (w *bufferedWriter) Flush() error { 285 bw := w.bw 286 if bw == nil { 287 return nil 288 } 289 err := bw.Flush() 290 bw.Reset(nil) 291 bufWriterPool.Put(bw) 292 w.bw = nil 293 return err 294 } 295 296 func mustUint31(v int32) uint32 { 297 if v < 0 || v > 2147483647 { 298 panic("out of range") 299 } 300 return uint32(v) 301 } 302 303 // bodyAllowedForStatus reports whether a given response status code 304 // permits a body. See RFC 7230, section 3.3. 305 func bodyAllowedForStatus(status int) bool { 306 switch { 307 case status >= 100 && status <= 199: 308 return false 309 case status == 204: 310 return false 311 case status == 304: 312 return false 313 } 314 return true 315 } 316 317 type httpError struct { 318 _ incomparable 319 msg string 320 timeout bool 321 } 322 323 func (e *httpError) Error() string { return e.msg } 324 func (e *httpError) Timeout() bool { return e.timeout } 325 func (e *httpError) Temporary() bool { return true } 326 327 var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true} 328 329 type connectionStater interface { 330 ConnectionState() tls.ConnectionState 331 } 332 333 var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }} 334 335 type sorter struct { 336 v []string // owned by sorter 337 } 338 339 func (s *sorter) Len() int { return len(s.v) } 340 func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] } 341 func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] } 342 343 // Keys returns the sorted keys of h. 344 // 345 // The returned slice is only valid until s used again or returned to 346 // its pool. 347 func (s *sorter) Keys(h http.Header) []string { 348 keys := s.v[:0] 349 for k := range h { 350 keys = append(keys, k) 351 } 352 s.v = keys 353 sort.Sort(s) 354 return keys 355 } 356 357 func (s *sorter) SortStrings(ss []string) { 358 // Our sorter works on s.v, which sorter owns, so 359 // stash it away while we sort the user's buffer. 360 save := s.v 361 s.v = ss 362 sort.Sort(s) 363 s.v = save 364 } 365 366 // validPseudoPath reports whether v is a valid :path pseudo-header 367 // value. It must be either: 368 // 369 // *) a non-empty string starting with '/' 370 // *) the string '*', for OPTIONS requests. 371 // 372 // For now this is only used a quick check for deciding when to clean 373 // up Opaque URLs before sending requests from the Transport. 374 // See golang.org/issue/16847 375 // 376 // We used to enforce that the path also didn't start with "//", but 377 // Google's GFE accepts such paths and Chrome sends them, so ignore 378 // that part of the spec. See golang.org/issue/19103. 379 func validPseudoPath(v string) bool { 380 return (len(v) > 0 && v[0] == '/') || v == "*" 381 } 382 383 // incomparable is a zero-width, non-comparable type. Adding it to a struct 384 // makes that struct also non-comparable, and generally doesn't add 385 // any size (as long as it's first). 386 type incomparable [0]func()