github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/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 package http2 17 18 import ( 19 "bufio" 20 "fmt" 21 "io" 22 "net/http" 23 "os" 24 "strconv" 25 "strings" 26 "sync" 27 ) 28 29 var VerboseLogs = strings.Contains(os.Getenv("GODEBUG"), "h2debug=1") 30 31 const ( 32 // ClientPreface is the string that must be sent by new 33 // connections from clients. 34 ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" 35 36 // SETTINGS_MAX_FRAME_SIZE default 37 // http://http2.github.io/http2-spec/#rfc.section.6.5.2 38 initialMaxFrameSize = 16384 39 40 // NextProtoTLS is the NPN/ALPN protocol negotiated during 41 // HTTP/2's TLS setup. 42 NextProtoTLS = "h2" 43 44 // http://http2.github.io/http2-spec/#SettingValues 45 initialHeaderTableSize = 4096 46 47 initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size 48 49 defaultMaxReadFrameSize = 1 << 20 50 ) 51 52 var ( 53 clientPreface = []byte(ClientPreface) 54 ) 55 56 type streamState int 57 58 const ( 59 stateIdle streamState = iota 60 stateOpen 61 stateHalfClosedLocal 62 stateHalfClosedRemote 63 stateResvLocal 64 stateResvRemote 65 stateClosed 66 ) 67 68 var stateName = [...]string{ 69 stateIdle: "Idle", 70 stateOpen: "Open", 71 stateHalfClosedLocal: "HalfClosedLocal", 72 stateHalfClosedRemote: "HalfClosedRemote", 73 stateResvLocal: "ResvLocal", 74 stateResvRemote: "ResvRemote", 75 stateClosed: "Closed", 76 } 77 78 func (st streamState) String() string { 79 return stateName[st] 80 } 81 82 // Setting is a setting parameter: which setting it is, and its value. 83 type Setting struct { 84 // ID is which setting is being set. 85 // See http://http2.github.io/http2-spec/#SettingValues 86 ID SettingID 87 88 // Val is the value. 89 Val uint32 90 } 91 92 func (s Setting) String() string { 93 return fmt.Sprintf("[%v = %d]", s.ID, s.Val) 94 } 95 96 // Valid reports whether the setting is valid. 97 func (s Setting) Valid() error { 98 // Limits and error codes from 6.5.2 Defined SETTINGS Parameters 99 switch s.ID { 100 case SettingEnablePush: 101 if s.Val != 1 && s.Val != 0 { 102 return ConnectionError(ErrCodeProtocol) 103 } 104 case SettingInitialWindowSize: 105 if s.Val > 1<<31-1 { 106 return ConnectionError(ErrCodeFlowControl) 107 } 108 case SettingMaxFrameSize: 109 if s.Val < 16384 || s.Val > 1<<24-1 { 110 return ConnectionError(ErrCodeProtocol) 111 } 112 } 113 return nil 114 } 115 116 // A SettingID is an HTTP/2 setting as defined in 117 // http://http2.github.io/http2-spec/#iana-settings 118 type SettingID uint16 119 120 const ( 121 SettingHeaderTableSize SettingID = 0x1 122 SettingEnablePush SettingID = 0x2 123 SettingMaxConcurrentStreams SettingID = 0x3 124 SettingInitialWindowSize SettingID = 0x4 125 SettingMaxFrameSize SettingID = 0x5 126 SettingMaxHeaderListSize SettingID = 0x6 127 ) 128 129 var settingName = map[SettingID]string{ 130 SettingHeaderTableSize: "HEADER_TABLE_SIZE", 131 SettingEnablePush: "ENABLE_PUSH", 132 SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS", 133 SettingInitialWindowSize: "INITIAL_WINDOW_SIZE", 134 SettingMaxFrameSize: "MAX_FRAME_SIZE", 135 SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE", 136 } 137 138 func (s SettingID) String() string { 139 if v, ok := settingName[s]; ok { 140 return v 141 } 142 return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s)) 143 } 144 145 func validHeader(v string) bool { 146 if len(v) == 0 { 147 return false 148 } 149 for _, r := range v { 150 // "Just as in HTTP/1.x, header field names are 151 // strings of ASCII characters that are compared in a 152 // case-insensitive fashion. However, header field 153 // names MUST be converted to lowercase prior to their 154 // encoding in HTTP/2. " 155 if r >= 127 || ('A' <= r && r <= 'Z') { 156 return false 157 } 158 } 159 return true 160 } 161 162 var httpCodeStringCommon = map[int]string{} // n -> strconv.Itoa(n) 163 164 func init() { 165 for i := 100; i <= 999; i++ { 166 if v := http.StatusText(i); v != "" { 167 httpCodeStringCommon[i] = strconv.Itoa(i) 168 } 169 } 170 } 171 172 func httpCodeString(code int) string { 173 if s, ok := httpCodeStringCommon[code]; ok { 174 return s 175 } 176 return strconv.Itoa(code) 177 } 178 179 // from pkg io 180 type stringWriter interface { 181 WriteString(s string) (n int, err error) 182 } 183 184 // A gate lets two goroutines coordinate their activities. 185 type gate chan struct{} 186 187 func (g gate) Done() { g <- struct{}{} } 188 func (g gate) Wait() { <-g } 189 190 // A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed). 191 type closeWaiter chan struct{} 192 193 // Init makes a closeWaiter usable. 194 // It exists because so a closeWaiter value can be placed inside a 195 // larger struct and have the Mutex and Cond's memory in the same 196 // allocation. 197 func (cw *closeWaiter) Init() { 198 *cw = make(chan struct{}) 199 } 200 201 // Close marks the closeWaiter as closed and unblocks any waiters. 202 func (cw closeWaiter) Close() { 203 close(cw) 204 } 205 206 // Wait waits for the closeWaiter to become closed. 207 func (cw closeWaiter) Wait() { 208 <-cw 209 } 210 211 // bufferedWriter is a buffered writer that writes to w. 212 // Its buffered writer is lazily allocated as needed, to minimize 213 // idle memory usage with many connections. 214 type bufferedWriter struct { 215 w io.Writer // immutable 216 bw *bufio.Writer // non-nil when data is buffered 217 } 218 219 func newBufferedWriter(w io.Writer) *bufferedWriter { 220 return &bufferedWriter{w: w} 221 } 222 223 var bufWriterPool = sync.Pool{ 224 New: func() interface{} { 225 // TODO: pick something better? this is a bit under 226 // (3 x typical 1500 byte MTU) at least. 227 return bufio.NewWriterSize(nil, 4<<10) 228 }, 229 } 230 231 func (w *bufferedWriter) Write(p []byte) (n int, err error) { 232 if w.bw == nil { 233 bw := bufWriterPool.Get().(*bufio.Writer) 234 bw.Reset(w.w) 235 w.bw = bw 236 } 237 return w.bw.Write(p) 238 } 239 240 func (w *bufferedWriter) Flush() error { 241 bw := w.bw 242 if bw == nil { 243 return nil 244 } 245 err := bw.Flush() 246 bw.Reset(nil) 247 bufWriterPool.Put(bw) 248 w.bw = nil 249 return err 250 } 251 252 func mustUint31(v int32) uint32 { 253 if v < 0 || v > 2147483647 { 254 panic("out of range") 255 } 256 return uint32(v) 257 } 258 259 // bodyAllowedForStatus reports whether a given response status code 260 // permits a body. See RFC2616, section 4.4. 261 func bodyAllowedForStatus(status int) bool { 262 switch { 263 case status >= 100 && status <= 199: 264 return false 265 case status == 204: 266 return false 267 case status == 304: 268 return false 269 } 270 return true 271 }