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