cubefs

Форк
0
385 строк · 9.5 Кб
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 // import "golang.org/x/net/http2"
17

18
import (
19
	"bufio"
20
	"crypto/tls"
21
	"fmt"
22
	"io"
23
	"net/http"
24
	"os"
25
	"sort"
26
	"strconv"
27
	"strings"
28
	"sync"
29

30
	"golang.org/x/net/http/httpguts"
31
)
32

33
var (
34
	VerboseLogs    bool
35
	logFrameWrites bool
36
	logFrameReads  bool
37
	inTests        bool
38
)
39

40
func init() {
41
	e := os.Getenv("GODEBUG")
42
	if strings.Contains(e, "http2debug=1") {
43
		VerboseLogs = true
44
	}
45
	if strings.Contains(e, "http2debug=2") {
46
		VerboseLogs = true
47
		logFrameWrites = true
48
		logFrameReads = true
49
	}
50
}
51

52
const (
53
	// ClientPreface is the string that must be sent by new
54
	// connections from clients.
55
	ClientPreface = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"
56

57
	// SETTINGS_MAX_FRAME_SIZE default
58
	// https://httpwg.org/specs/rfc7540.html#rfc.section.6.5.2
59
	initialMaxFrameSize = 16384
60

61
	// NextProtoTLS is the NPN/ALPN protocol negotiated during
62
	// HTTP/2's TLS setup.
63
	NextProtoTLS = "h2"
64

65
	// https://httpwg.org/specs/rfc7540.html#SettingValues
66
	initialHeaderTableSize = 4096
67

68
	initialWindowSize = 65535 // 6.9.2 Initial Flow Control Window Size
69

70
	defaultMaxReadFrameSize = 1 << 20
71
)
72

73
var (
74
	clientPreface = []byte(ClientPreface)
75
)
76

77
type streamState int
78

79
// HTTP/2 stream states.
80
//
81
// See http://tools.ietf.org/html/rfc7540#section-5.1.
82
//
83
// For simplicity, the server code merges "reserved (local)" into
84
// "half-closed (remote)". This is one less state transition to track.
85
// The only downside is that we send PUSH_PROMISEs slightly less
86
// liberally than allowable. More discussion here:
87
// https://lists.w3.org/Archives/Public/ietf-http-wg/2016JulSep/0599.html
88
//
89
// "reserved (remote)" is omitted since the client code does not
90
// support server push.
91
const (
92
	stateIdle streamState = iota
93
	stateOpen
94
	stateHalfClosedLocal
95
	stateHalfClosedRemote
96
	stateClosed
97
)
98

99
var stateName = [...]string{
100
	stateIdle:             "Idle",
101
	stateOpen:             "Open",
102
	stateHalfClosedLocal:  "HalfClosedLocal",
103
	stateHalfClosedRemote: "HalfClosedRemote",
104
	stateClosed:           "Closed",
105
}
106

107
func (st streamState) String() string {
108
	return stateName[st]
109
}
110

111
// Setting is a setting parameter: which setting it is, and its value.
112
type Setting struct {
113
	// ID is which setting is being set.
114
	// See https://httpwg.org/specs/rfc7540.html#SettingFormat
115
	ID SettingID
116

117
	// Val is the value.
118
	Val uint32
119
}
120

121
func (s Setting) String() string {
122
	return fmt.Sprintf("[%v = %d]", s.ID, s.Val)
123
}
124

125
// Valid reports whether the setting is valid.
126
func (s Setting) Valid() error {
127
	// Limits and error codes from 6.5.2 Defined SETTINGS Parameters
128
	switch s.ID {
129
	case SettingEnablePush:
130
		if s.Val != 1 && s.Val != 0 {
131
			return ConnectionError(ErrCodeProtocol)
132
		}
133
	case SettingInitialWindowSize:
134
		if s.Val > 1<<31-1 {
135
			return ConnectionError(ErrCodeFlowControl)
136
		}
137
	case SettingMaxFrameSize:
138
		if s.Val < 16384 || s.Val > 1<<24-1 {
139
			return ConnectionError(ErrCodeProtocol)
140
		}
141
	}
142
	return nil
143
}
144

145
// A SettingID is an HTTP/2 setting as defined in
146
// https://httpwg.org/specs/rfc7540.html#iana-settings
147
type SettingID uint16
148

149
const (
150
	SettingHeaderTableSize      SettingID = 0x1
151
	SettingEnablePush           SettingID = 0x2
152
	SettingMaxConcurrentStreams SettingID = 0x3
153
	SettingInitialWindowSize    SettingID = 0x4
154
	SettingMaxFrameSize         SettingID = 0x5
155
	SettingMaxHeaderListSize    SettingID = 0x6
156
)
157

158
var settingName = map[SettingID]string{
159
	SettingHeaderTableSize:      "HEADER_TABLE_SIZE",
160
	SettingEnablePush:           "ENABLE_PUSH",
161
	SettingMaxConcurrentStreams: "MAX_CONCURRENT_STREAMS",
162
	SettingInitialWindowSize:    "INITIAL_WINDOW_SIZE",
163
	SettingMaxFrameSize:         "MAX_FRAME_SIZE",
164
	SettingMaxHeaderListSize:    "MAX_HEADER_LIST_SIZE",
165
}
166

167
func (s SettingID) String() string {
168
	if v, ok := settingName[s]; ok {
169
		return v
170
	}
171
	return fmt.Sprintf("UNKNOWN_SETTING_%d", uint16(s))
172
}
173

174
// validWireHeaderFieldName reports whether v is a valid header field
175
// name (key). See httpguts.ValidHeaderName for the base rules.
176
//
177
// Further, http2 says:
178
//
179
//	"Just as in HTTP/1.x, header field names are strings of ASCII
180
//	characters that are compared in a case-insensitive
181
//	fashion. However, header field names MUST be converted to
182
//	lowercase prior to their encoding in HTTP/2. "
183
func validWireHeaderFieldName(v string) bool {
184
	if len(v) == 0 {
185
		return false
186
	}
187
	for _, r := range v {
188
		if !httpguts.IsTokenRune(r) {
189
			return false
190
		}
191
		if 'A' <= r && r <= 'Z' {
192
			return false
193
		}
194
	}
195
	return true
196
}
197

198
func httpCodeString(code int) string {
199
	switch code {
200
	case 200:
201
		return "200"
202
	case 404:
203
		return "404"
204
	}
205
	return strconv.Itoa(code)
206
}
207

208
// from pkg io
209
type stringWriter interface {
210
	WriteString(s string) (n int, err error)
211
}
212

213
// A gate lets two goroutines coordinate their activities.
214
type gate chan struct{}
215

216
func (g gate) Done() { g <- struct{}{} }
217
func (g gate) Wait() { <-g }
218

219
// A closeWaiter is like a sync.WaitGroup but only goes 1 to 0 (open to closed).
220
type closeWaiter chan struct{}
221

222
// Init makes a closeWaiter usable.
223
// It exists because so a closeWaiter value can be placed inside a
224
// larger struct and have the Mutex and Cond's memory in the same
225
// allocation.
226
func (cw *closeWaiter) Init() {
227
	*cw = make(chan struct{})
228
}
229

230
// Close marks the closeWaiter as closed and unblocks any waiters.
231
func (cw closeWaiter) Close() {
232
	close(cw)
233
}
234

235
// Wait waits for the closeWaiter to become closed.
236
func (cw closeWaiter) Wait() {
237
	<-cw
238
}
239

240
// bufferedWriter is a buffered writer that writes to w.
241
// Its buffered writer is lazily allocated as needed, to minimize
242
// idle memory usage with many connections.
243
type bufferedWriter struct {
244
	_  incomparable
245
	w  io.Writer     // immutable
246
	bw *bufio.Writer // non-nil when data is buffered
247
}
248

249
func newBufferedWriter(w io.Writer) *bufferedWriter {
250
	return &bufferedWriter{w: w}
251
}
252

253
// bufWriterPoolBufferSize is the size of bufio.Writer's
254
// buffers created using bufWriterPool.
255
//
256
// TODO: pick a less arbitrary value? this is a bit under
257
// (3 x typical 1500 byte MTU) at least. Other than that,
258
// not much thought went into it.
259
const bufWriterPoolBufferSize = 4 << 10
260

261
var bufWriterPool = sync.Pool{
262
	New: func() interface{} {
263
		return bufio.NewWriterSize(nil, bufWriterPoolBufferSize)
264
	},
265
}
266

267
func (w *bufferedWriter) Available() int {
268
	if w.bw == nil {
269
		return bufWriterPoolBufferSize
270
	}
271
	return w.bw.Available()
272
}
273

274
func (w *bufferedWriter) Write(p []byte) (n int, err error) {
275
	if w.bw == nil {
276
		bw := bufWriterPool.Get().(*bufio.Writer)
277
		bw.Reset(w.w)
278
		w.bw = bw
279
	}
280
	return w.bw.Write(p)
281
}
282

283
func (w *bufferedWriter) Flush() error {
284
	bw := w.bw
285
	if bw == nil {
286
		return nil
287
	}
288
	err := bw.Flush()
289
	bw.Reset(nil)
290
	bufWriterPool.Put(bw)
291
	w.bw = nil
292
	return err
293
}
294

295
func mustUint31(v int32) uint32 {
296
	if v < 0 || v > 2147483647 {
297
		panic("out of range")
298
	}
299
	return uint32(v)
300
}
301

302
// bodyAllowedForStatus reports whether a given response status code
303
// permits a body. See RFC 7230, section 3.3.
304
func bodyAllowedForStatus(status int) bool {
305
	switch {
306
	case status >= 100 && status <= 199:
307
		return false
308
	case status == 204:
309
		return false
310
	case status == 304:
311
		return false
312
	}
313
	return true
314
}
315

316
type httpError struct {
317
	_       incomparable
318
	msg     string
319
	timeout bool
320
}
321

322
func (e *httpError) Error() string   { return e.msg }
323
func (e *httpError) Timeout() bool   { return e.timeout }
324
func (e *httpError) Temporary() bool { return true }
325

326
var errTimeout error = &httpError{msg: "http2: timeout awaiting response headers", timeout: true}
327

328
type connectionStater interface {
329
	ConnectionState() tls.ConnectionState
330
}
331

332
var sorterPool = sync.Pool{New: func() interface{} { return new(sorter) }}
333

334
type sorter struct {
335
	v []string // owned by sorter
336
}
337

338
func (s *sorter) Len() int           { return len(s.v) }
339
func (s *sorter) Swap(i, j int)      { s.v[i], s.v[j] = s.v[j], s.v[i] }
340
func (s *sorter) Less(i, j int) bool { return s.v[i] < s.v[j] }
341

342
// Keys returns the sorted keys of h.
343
//
344
// The returned slice is only valid until s used again or returned to
345
// its pool.
346
func (s *sorter) Keys(h http.Header) []string {
347
	keys := s.v[:0]
348
	for k := range h {
349
		keys = append(keys, k)
350
	}
351
	s.v = keys
352
	sort.Sort(s)
353
	return keys
354
}
355

356
func (s *sorter) SortStrings(ss []string) {
357
	// Our sorter works on s.v, which sorter owns, so
358
	// stash it away while we sort the user's buffer.
359
	save := s.v
360
	s.v = ss
361
	sort.Sort(s)
362
	s.v = save
363
}
364

365
// validPseudoPath reports whether v is a valid :path pseudo-header
366
// value. It must be either:
367
//
368
//   - a non-empty string starting with '/'
369
//   - the string '*', for OPTIONS requests.
370
//
371
// For now this is only used a quick check for deciding when to clean
372
// up Opaque URLs before sending requests from the Transport.
373
// See golang.org/issue/16847
374
//
375
// We used to enforce that the path also didn't start with "//", but
376
// Google's GFE accepts such paths and Chrome sends them, so ignore
377
// that part of the spec. See golang.org/issue/19103.
378
func validPseudoPath(v string) bool {
379
	return (len(v) > 0 && v[0] == '/') || v == "*"
380
}
381

382
// incomparable is a zero-width, non-comparable type. Adding it to a struct
383
// makes that struct also non-comparable, and generally doesn't add
384
// any size (as long as it's first).
385
type incomparable [0]func()
386

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.