1
2
3
4
5
6
7
8
9
10
11
12
13
14 package http2
15
16 import (
17 "bufio"
18 "crypto/tls"
19 "errors"
20 "fmt"
21 "net"
22 "os"
23 "sort"
24 "strconv"
25 "strings"
26 "sync"
27 "time"
28
29 "golang.org/x/net/http/httpguts"
30 )
31
32 var (
33 VerboseLogs bool
34 logFrameWrites bool
35 logFrameReads bool
36
37
38
39
40
41
42
43
44 disableExtendedConnectProtocol = true
45
46 inTests = false
47 )
48
49 func init() {
50 e := os.Getenv("GODEBUG")
51 if strings.Contains(e, "http2debug=1") {
52 VerboseLogs = true
53 }
54 if strings.Contains(e, "http2debug=2") {
55 VerboseLogs = true
56 logFrameWrites = true
57 logFrameReads = true
58 }
59 if strings.Contains(e, "http2xconnect=1") {
60 disableExtendedConnectProtocol = false
61 }
62 }
63
64 const (
65
66
67 ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
68
69
70
71 initialMaxFrameSize = 16384
72
73
74
75 NextProtoTLS = "h2"
76
77
78 initialHeaderTableSize = 4096
79
80 initialWindowSize = 65535
81
82 defaultMaxReadFrameSize = 1 << 20
83 )
84
85 var (
86 clientPreface = []byte(ClientPreface)
87 )
88
89 type streamState int
90
91
92
93
94
95
96
97
98
99
100
101
102
103 const (
104 stateIdle streamState = iota
105 stateOpen
106 stateHalfClosedLocal
107 stateHalfClosedRemote
108 stateClosed
109 )
110
111 var stateName = [...]string{
112 stateIdle: "Idle",
113 stateOpen: "Open",
114 stateHalfClosedLocal: "HalfClosedLocal",
115 stateHalfClosedRemote: "HalfClosedRemote",
116 stateClosed: "Closed",
117 }
118
119 func (st streamState) String() string {
120 return stateName[st]
121 }
122
123
124 type Setting struct {
125
126
127 ID SettingID
128
129
130 Val uint32
131 }
132
133 func (s Setting) String() string {
134 return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
135 }
136
137
138 func (s Setting) Valid() error {
139
140 switch s.ID {
141 case SettingEnablePush:
142 if s.Val != 1 && s.Val != 0 {
143 return ConnectionError(ErrCodeProtocol)
144 }
145 case SettingInitialWindowSize:
146 if s.Val > 1<<31-1 {
147 return ConnectionError(ErrCodeFlowControl)
148 }
149 case SettingMaxFrameSize:
150 if s.Val < 16384 || s.Val > 1<<24-1 {
151 return ConnectionError(ErrCodeProtocol)
152 }
153 case SettingEnableConnectProtocol:
154 if s.Val != 1 && s.Val != 0 {
155 return ConnectionError(ErrCodeProtocol)
156 }
157 }
158 return nil
159 }
160
161
162
163 type SettingID uint16
164
165 const (
166 SettingHeaderTableSize SettingID = 0x1
167 SettingEnablePush SettingID = 0x2
168 SettingMaxConcurrentStreams SettingID = 0x3
169 SettingInitialWindowSize SettingID = 0x4
170 SettingMaxFrameSize SettingID = 0x5
171 SettingMaxHeaderListSize SettingID = 0x6
172 SettingEnableConnectProtocol SettingID = 0x8
173 SettingNoRFC7540Priorities SettingID = 0x9
174 )
175
176 var settingName = map[SettingID]string{
177 SettingHeaderTableSize: "HEADER_TABLE_SIZE",
178 SettingEnablePush: "ENABLE_PUSH",
179 SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
180 SettingInitialWindowSize: "INITIAL_WINDOW_SIZE",
181 SettingMaxFrameSize: "MAX_FRAME_SIZE",
182 SettingMaxHeaderListSize: "MAX_HEADER_LIST_SIZE",
183 SettingEnableConnectProtocol: "ENABLE_CONNECT_PROTOCOL",
184 SettingNoRFC7540Priorities: "NO_RFC7540_PRIORITIES",
185 }
186
187 func (s SettingID) String() string {
188 if v, ok := settingName[s]; ok {
189 return v
190 }
191 return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
192 }
193
194
195
196
197
198
199
200
201
202
203 func validWireHeaderFieldName(v string) bool {
204 if len(v) == 0 {
205 return false
206 }
207 for _, r := range v {
208 if !httpguts.IsTokenRune(r) {
209 return false
210 }
211 if 'A' <= r && r <= 'Z' {
212 return false
213 }
214 }
215 return true
216 }
217
218 func httpCodeString(code int) string {
219 switch code {
220 case 200:
221 return "200"
222 case 404:
223 return "404"
224 }
225 return strconv.Itoa(code)
226 }
227
228
229 type closeWaiter chan struct{}
230
231
232
233
234
235 func (cw *closeWaiter) Init() {
236 *cw = make(chan struct{})
237 }
238
239
240 func (cw closeWaiter) Close() {
241 close(cw)
242 }
243
244
245 func (cw closeWaiter) Wait() {
246 <-cw
247 }
248
249
250
251
252 type bufferedWriter struct {
253 _ incomparable
254 conn net.Conn
255 bw *bufio.Writer
256 byteTimeout time.Duration
257 werr error
258 }
259
260 func newBufferedWriter(conn net.Conn, timeout time.Duration) *bufferedWriter {
261 return &bufferedWriter{
262 conn: conn,
263 byteTimeout: timeout,
264 }
265 }
266
267
268
269
270
271
272
273 const bufWriterPoolBufferSize = 4 << 10
274
275 var bufWriterPool = sync.Pool{
276 New: func() interface{} {
277 return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
278 },
279 }
280
281 func (w *bufferedWriter) Available() int {
282 if w.bw == nil {
283 return bufWriterPoolBufferSize
284 }
285 return w.bw.Available()
286 }
287
288 func (w *bufferedWriter) Write(p []byte) (n int, err error) {
289 if w.werr != nil {
290 return 0, w.werr
291 }
292 if w.bw == nil {
293 bw := bufWriterPool.Get().(*bufio.Writer)
294 bw.Reset((*bufferedWriterTimeoutWriter)(w))
295 w.bw = bw
296 }
297 n, w.werr = w.bw.Write(p)
298 return n, w.werr
299 }
300
301 func (w *bufferedWriter) Flush() error {
302 bw := w.bw
303 if bw == nil {
304 return nil
305 }
306 if w.werr != nil {
307 return w.werr
308 }
309 w.werr = bw.Flush()
310 bw.Reset(nil)
311 bufWriterPool.Put(bw)
312 w.bw = nil
313 return w.werr
314 }
315
316 type bufferedWriterTimeoutWriter bufferedWriter
317
318 func (w *bufferedWriterTimeoutWriter) Write(p []byte) (n int, err error) {
319 return writeWithByteTimeout(w.conn, w.byteTimeout, p)
320 }
321
322
323
324
325 func writeWithByteTimeout(conn net.Conn, timeout time.Duration, p []byte) (n int, err error) {
326 if timeout <= 0 {
327 return conn.Write(p)
328 }
329 for {
330 conn.SetWriteDeadline(time.Now().Add(timeout))
331 nn, err := conn.Write(p[n:])
332 n += nn
333 if n == len(p) || nn == 0 || !errors.Is(err, os.ErrDeadlineExceeded) {
334
335
336 conn.SetWriteDeadline(time.Time{})
337 return n, err
338 }
339 }
340 }
341
342 func mustUint31(v int32) uint32 {
343 if v < 0 || v > 2147483647 {
344 panic("out of range")
345 }
346 return uint32(v)
347 }
348
349
350
351 func bodyAllowedForStatus(status int) bool {
352 switch {
353 case status >= 100 && status <= 199:
354 return false
355 case status == 204:
356 return false
357 case status == 304:
358 return false
359 }
360 return true
361 }
362
363 type httpError struct {
364 _ incomparable
365 msg string
366 timeout bool
367 }
368
369 func (e *httpError) Error() string { return e.msg }
370 func (e *httpError) Timeout() bool { return e.timeout }
371 func (e *httpError) Temporary() bool { return true }
372
373 var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
374
375 type connectionStater interface {
376 ConnectionState() tls.ConnectionState
377 }
378
379 var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
380
381 type sorter struct {
382 v []string
383 }
384
385 func (s *sorter) Len() int { return len(s.v) }
386 func (s *sorter) Swap(i, j int) { s.v[i], s.v[j] = s.v[j], s.v[i] }
387 func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
388
389
390
391
392
393 func (s *sorter) Keys(h Header) []string {
394 keys := s.v[:0]
395 for k := range h {
396 keys = append(keys, k)
397 }
398 s.v = keys
399 sort.Sort(s)
400 return keys
401 }
402
403 func (s *sorter) SortStrings(ss []string) {
404
405
406 save := s.v
407 s.v = ss
408 sort.Sort(s)
409 s.v = save
410 }
411
412
413
414
415 type incomparable [0]func()
416
View as plain text