blob: 6c349f3ec647381bb63890955968351620fd9b12 [file] [log] [blame]
William Kurkianea869482019-04-09 15:16:11 -04001// 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// TODO: turn off the serve goroutine when idle, so
6// an idle conn only has the readFrames goroutine active. (which could
7// also be optimized probably to pin less memory in crypto/tls). This
8// would involve tracking when the serve goroutine is active (atomic
9// int32 read/CAS probably?) and starting it up when frames arrive,
10// and shutting it down when all handlers exit. the occasional PING
11// packets could use time.AfterFunc to call sc.wakeStartServeLoop()
12// (which is a no-op if already running) and then queue the PING write
13// as normal. The serve loop would then exit in most cases (if no
14// Handlers running) and not be woken up again until the PING packet
15// returns.
16
17// TODO (maybe): add a mechanism for Handlers to going into
18// half-closed-local mode (rw.(io.Closer) test?) but not exit their
19// handler, and continue to be able to read from the
20// Request.Body. This would be a somewhat semantic change from HTTP/1
21// (or at least what we expose in net/http), so I'd probably want to
22// add it there too. For now, this package says that returning from
23// the Handler ServeHTTP function means you're both done reading and
24// done writing, without a way to stop just one or the other.
25
26package http2
27
28import (
29 "bufio"
30 "bytes"
31 "context"
32 "crypto/tls"
33 "errors"
34 "fmt"
35 "io"
36 "log"
37 "math"
38 "net"
39 "net/http"
40 "net/textproto"
41 "net/url"
42 "os"
43 "reflect"
44 "runtime"
45 "strconv"
46 "strings"
47 "sync"
48 "time"
49
50 "golang.org/x/net/http/httpguts"
51 "golang.org/x/net/http2/hpack"
52)
53
54const (
David Bainbridge788e5202019-10-21 18:49:40 +000055 prefaceTimeout = 10 * time.Second
56 firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway
57 handlerChunkWriteSize = 4 << 10
58 defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?
59 maxQueuedControlFrames = 10000
William Kurkianea869482019-04-09 15:16:11 -040060)
61
62var (
63 errClientDisconnected = errors.New("client disconnected")
64 errClosedBody = errors.New("body closed by handler")
65 errHandlerComplete = errors.New("http2: request body closed due to handler exiting")
66 errStreamClosed = errors.New("http2: stream closed")
67)
68
69var responseWriterStatePool = sync.Pool{
70 New: func() interface{} {
71 rws := &responseWriterState{}
72 rws.bw = bufio.NewWriterSize(chunkWriter{rws}, handlerChunkWriteSize)
73 return rws
74 },
75}
76
77// Test hooks.
78var (
79 testHookOnConn func()
80 testHookGetServerConn func(*serverConn)
81 testHookOnPanicMu *sync.Mutex // nil except in tests
82 testHookOnPanic func(sc *serverConn, panicVal interface{}) (rePanic bool)
83)
84
85// Server is an HTTP/2 server.
86type Server struct {
87 // MaxHandlers limits the number of http.Handler ServeHTTP goroutines
88 // which may run at a time over all connections.
89 // Negative or zero no limit.
90 // TODO: implement
91 MaxHandlers int
92
93 // MaxConcurrentStreams optionally specifies the number of
94 // concurrent streams that each client may have open at a
95 // time. This is unrelated to the number of http.Handler goroutines
96 // which may be active globally, which is MaxHandlers.
97 // If zero, MaxConcurrentStreams defaults to at least 100, per
98 // the HTTP/2 spec's recommendations.
99 MaxConcurrentStreams uint32
100
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530101 // MaxDecoderHeaderTableSize optionally specifies the http2
102 // SETTINGS_HEADER_TABLE_SIZE to send in the initial settings frame. It
103 // informs the remote endpoint of the maximum size of the header compression
104 // table used to decode header blocks, in octets. If zero, the default value
105 // of 4096 is used.
106 MaxDecoderHeaderTableSize uint32
107
108 // MaxEncoderHeaderTableSize optionally specifies an upper limit for the
109 // header compression table used for encoding request headers. Received
110 // SETTINGS_HEADER_TABLE_SIZE settings are capped at this limit. If zero,
111 // the default value of 4096 is used.
112 MaxEncoderHeaderTableSize uint32
113
William Kurkianea869482019-04-09 15:16:11 -0400114 // MaxReadFrameSize optionally specifies the largest frame
115 // this server is willing to read. A valid value is between
116 // 16k and 16M, inclusive. If zero or otherwise invalid, a
117 // default value is used.
118 MaxReadFrameSize uint32
119
120 // PermitProhibitedCipherSuites, if true, permits the use of
121 // cipher suites prohibited by the HTTP/2 spec.
122 PermitProhibitedCipherSuites bool
123
124 // IdleTimeout specifies how long until idle clients should be
125 // closed with a GOAWAY frame. PING frames are not considered
126 // activity for the purposes of IdleTimeout.
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530127 // If zero or negative, there is no timeout.
William Kurkianea869482019-04-09 15:16:11 -0400128 IdleTimeout time.Duration
129
130 // MaxUploadBufferPerConnection is the size of the initial flow
131 // control window for each connections. The HTTP/2 spec does not
132 // allow this to be smaller than 65535 or larger than 2^32-1.
133 // If the value is outside this range, a default value will be
134 // used instead.
135 MaxUploadBufferPerConnection int32
136
137 // MaxUploadBufferPerStream is the size of the initial flow control
138 // window for each stream. The HTTP/2 spec does not allow this to
139 // be larger than 2^32-1. If the value is zero or larger than the
140 // maximum, a default value will be used instead.
141 MaxUploadBufferPerStream int32
142
143 // NewWriteScheduler constructs a write scheduler for a connection.
144 // If nil, a default scheduler is chosen.
145 NewWriteScheduler func() WriteScheduler
146
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530147 // CountError, if non-nil, is called on HTTP/2 server errors.
148 // It's intended to increment a metric for monitoring, such
149 // as an expvar or Prometheus metric.
150 // The errType consists of only ASCII word characters.
151 CountError func(errType string)
152
William Kurkianea869482019-04-09 15:16:11 -0400153 // Internal state. This is a pointer (rather than embedded directly)
154 // so that we don't embed a Mutex in this struct, which will make the
155 // struct non-copyable, which might break some callers.
156 state *serverInternalState
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530157
158 // Synchronization group used for testing.
159 // Outside of tests, this is nil.
160 group synctestGroupInterface
161}
162
163func (s *Server) markNewGoroutine() {
164 if s.group != nil {
165 s.group.Join()
166 }
167}
168
169func (s *Server) now() time.Time {
170 if s.group != nil {
171 return s.group.Now()
172 }
173 return time.Now()
174}
175
176// newTimer creates a new time.Timer, or a synthetic timer in tests.
177func (s *Server) newTimer(d time.Duration) timer {
178 if s.group != nil {
179 return s.group.NewTimer(d)
180 }
181 return timeTimer{time.NewTimer(d)}
182}
183
184// afterFunc creates a new time.AfterFunc timer, or a synthetic timer in tests.
185func (s *Server) afterFunc(d time.Duration, f func()) timer {
186 if s.group != nil {
187 return s.group.AfterFunc(d, f)
188 }
189 return timeTimer{time.AfterFunc(d, f)}
William Kurkianea869482019-04-09 15:16:11 -0400190}
191
192func (s *Server) initialConnRecvWindowSize() int32 {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530193 if s.MaxUploadBufferPerConnection >= initialWindowSize {
William Kurkianea869482019-04-09 15:16:11 -0400194 return s.MaxUploadBufferPerConnection
195 }
196 return 1 << 20
197}
198
199func (s *Server) initialStreamRecvWindowSize() int32 {
200 if s.MaxUploadBufferPerStream > 0 {
201 return s.MaxUploadBufferPerStream
202 }
203 return 1 << 20
204}
205
206func (s *Server) maxReadFrameSize() uint32 {
207 if v := s.MaxReadFrameSize; v >= minMaxFrameSize && v <= maxFrameSize {
208 return v
209 }
210 return defaultMaxReadFrameSize
211}
212
213func (s *Server) maxConcurrentStreams() uint32 {
214 if v := s.MaxConcurrentStreams; v > 0 {
215 return v
216 }
217 return defaultMaxStreams
218}
219
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530220func (s *Server) maxDecoderHeaderTableSize() uint32 {
221 if v := s.MaxDecoderHeaderTableSize; v > 0 {
222 return v
223 }
224 return initialHeaderTableSize
225}
226
227func (s *Server) maxEncoderHeaderTableSize() uint32 {
228 if v := s.MaxEncoderHeaderTableSize; v > 0 {
229 return v
230 }
231 return initialHeaderTableSize
232}
233
David Bainbridge788e5202019-10-21 18:49:40 +0000234// maxQueuedControlFrames is the maximum number of control frames like
235// SETTINGS, PING and RST_STREAM that will be queued for writing before
236// the connection is closed to prevent memory exhaustion attacks.
237func (s *Server) maxQueuedControlFrames() int {
238 // TODO: if anybody asks, add a Server field, and remember to define the
239 // behavior of negative values.
240 return maxQueuedControlFrames
241}
242
William Kurkianea869482019-04-09 15:16:11 -0400243type serverInternalState struct {
244 mu sync.Mutex
245 activeConns map[*serverConn]struct{}
246}
247
248func (s *serverInternalState) registerConn(sc *serverConn) {
249 if s == nil {
250 return // if the Server was used without calling ConfigureServer
251 }
252 s.mu.Lock()
253 s.activeConns[sc] = struct{}{}
254 s.mu.Unlock()
255}
256
257func (s *serverInternalState) unregisterConn(sc *serverConn) {
258 if s == nil {
259 return // if the Server was used without calling ConfigureServer
260 }
261 s.mu.Lock()
262 delete(s.activeConns, sc)
263 s.mu.Unlock()
264}
265
266func (s *serverInternalState) startGracefulShutdown() {
267 if s == nil {
268 return // if the Server was used without calling ConfigureServer
269 }
270 s.mu.Lock()
271 for sc := range s.activeConns {
272 sc.startGracefulShutdown()
273 }
274 s.mu.Unlock()
275}
276
277// ConfigureServer adds HTTP/2 support to a net/http Server.
278//
279// The configuration conf may be nil.
280//
281// ConfigureServer must be called before s begins serving.
282func ConfigureServer(s *http.Server, conf *Server) error {
283 if s == nil {
284 panic("nil *http.Server")
285 }
286 if conf == nil {
287 conf = new(Server)
288 }
289 conf.state = &serverInternalState{activeConns: make(map[*serverConn]struct{})}
290 if h1, h2 := s, conf; h2.IdleTimeout == 0 {
291 if h1.IdleTimeout != 0 {
292 h2.IdleTimeout = h1.IdleTimeout
293 } else {
294 h2.IdleTimeout = h1.ReadTimeout
295 }
296 }
297 s.RegisterOnShutdown(conf.state.startGracefulShutdown)
298
299 if s.TLSConfig == nil {
300 s.TLSConfig = new(tls.Config)
khenaidoo106c61a2021-08-11 18:05:46 -0400301 } else if s.TLSConfig.CipherSuites != nil && s.TLSConfig.MinVersion < tls.VersionTLS13 {
302 // If they already provided a TLS 1.0–1.2 CipherSuite list, return an
303 // error if it is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or
304 // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.
William Kurkianea869482019-04-09 15:16:11 -0400305 haveRequired := false
khenaidoo106c61a2021-08-11 18:05:46 -0400306 for _, cs := range s.TLSConfig.CipherSuites {
William Kurkianea869482019-04-09 15:16:11 -0400307 switch cs {
308 case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
309 // Alternative MTI cipher to not discourage ECDSA-only servers.
310 // See http://golang.org/cl/30721 for further information.
311 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:
312 haveRequired = true
313 }
William Kurkianea869482019-04-09 15:16:11 -0400314 }
315 if !haveRequired {
khenaidoo106c61a2021-08-11 18:05:46 -0400316 return fmt.Errorf("http2: TLSConfig.CipherSuites is missing an HTTP/2-required AES_128_GCM_SHA256 cipher (need at least one of TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 or TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256)")
William Kurkianea869482019-04-09 15:16:11 -0400317 }
318 }
319
320 // Note: not setting MinVersion to tls.VersionTLS12,
321 // as we don't want to interfere with HTTP/1.1 traffic
322 // on the user's server. We enforce TLS 1.2 later once
323 // we accept a connection. Ideally this should be done
324 // during next-proto selection, but using TLS <1.2 with
325 // HTTP/2 is still the client's bug.
326
327 s.TLSConfig.PreferServerCipherSuites = true
328
khenaidoo106c61a2021-08-11 18:05:46 -0400329 if !strSliceContains(s.TLSConfig.NextProtos, NextProtoTLS) {
William Kurkianea869482019-04-09 15:16:11 -0400330 s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, NextProtoTLS)
331 }
khenaidoo106c61a2021-08-11 18:05:46 -0400332 if !strSliceContains(s.TLSConfig.NextProtos, "http/1.1") {
333 s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, "http/1.1")
334 }
William Kurkianea869482019-04-09 15:16:11 -0400335
336 if s.TLSNextProto == nil {
337 s.TLSNextProto = map[string]func(*http.Server, *tls.Conn, http.Handler){}
338 }
339 protoHandler := func(hs *http.Server, c *tls.Conn, h http.Handler) {
340 if testHookOnConn != nil {
341 testHookOnConn()
342 }
Abhilash S.L3b494632019-07-16 15:51:09 +0530343 // The TLSNextProto interface predates contexts, so
344 // the net/http package passes down its per-connection
345 // base context via an exported but unadvertised
346 // method on the Handler. This is for internal
347 // net/http<=>http2 use only.
348 var ctx context.Context
349 type baseContexter interface {
350 BaseContext() context.Context
351 }
352 if bc, ok := h.(baseContexter); ok {
353 ctx = bc.BaseContext()
354 }
William Kurkianea869482019-04-09 15:16:11 -0400355 conf.ServeConn(c, &ServeConnOpts{
Abhilash S.L3b494632019-07-16 15:51:09 +0530356 Context: ctx,
William Kurkianea869482019-04-09 15:16:11 -0400357 Handler: h,
358 BaseConfig: hs,
359 })
360 }
361 s.TLSNextProto[NextProtoTLS] = protoHandler
362 return nil
363}
364
365// ServeConnOpts are options for the Server.ServeConn method.
366type ServeConnOpts struct {
Abhilash S.L3b494632019-07-16 15:51:09 +0530367 // Context is the base context to use.
368 // If nil, context.Background is used.
369 Context context.Context
370
William Kurkianea869482019-04-09 15:16:11 -0400371 // BaseConfig optionally sets the base configuration
372 // for values. If nil, defaults are used.
373 BaseConfig *http.Server
374
375 // Handler specifies which handler to use for processing
376 // requests. If nil, BaseConfig.Handler is used. If BaseConfig
377 // or BaseConfig.Handler is nil, http.DefaultServeMux is used.
378 Handler http.Handler
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530379
380 // UpgradeRequest is an initial request received on a connection
381 // undergoing an h2c upgrade. The request body must have been
382 // completely read from the connection before calling ServeConn,
383 // and the 101 Switching Protocols response written.
384 UpgradeRequest *http.Request
385
386 // Settings is the decoded contents of the HTTP2-Settings header
387 // in an h2c upgrade request.
388 Settings []byte
389
390 // SawClientPreface is set if the HTTP/2 connection preface
391 // has already been read from the connection.
392 SawClientPreface bool
William Kurkianea869482019-04-09 15:16:11 -0400393}
394
Abhilash S.L3b494632019-07-16 15:51:09 +0530395func (o *ServeConnOpts) context() context.Context {
David Bainbridge788e5202019-10-21 18:49:40 +0000396 if o != nil && o.Context != nil {
Abhilash S.L3b494632019-07-16 15:51:09 +0530397 return o.Context
398 }
399 return context.Background()
400}
401
William Kurkianea869482019-04-09 15:16:11 -0400402func (o *ServeConnOpts) baseConfig() *http.Server {
403 if o != nil && o.BaseConfig != nil {
404 return o.BaseConfig
405 }
406 return new(http.Server)
407}
408
409func (o *ServeConnOpts) handler() http.Handler {
410 if o != nil {
411 if o.Handler != nil {
412 return o.Handler
413 }
414 if o.BaseConfig != nil && o.BaseConfig.Handler != nil {
415 return o.BaseConfig.Handler
416 }
417 }
418 return http.DefaultServeMux
419}
420
421// ServeConn serves HTTP/2 requests on the provided connection and
422// blocks until the connection is no longer readable.
423//
424// ServeConn starts speaking HTTP/2 assuming that c has not had any
425// reads or writes. It writes its initial settings frame and expects
426// to be able to read the preface and settings frame from the
427// client. If c has a ConnectionState method like a *tls.Conn, the
428// ConnectionState is used to verify the TLS ciphersuite and to set
429// the Request.TLS field in Handlers.
430//
431// ServeConn does not support h2c by itself. Any h2c support must be
432// implemented in terms of providing a suitably-behaving net.Conn.
433//
434// The opts parameter is optional. If nil, default values are used.
435func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530436 s.serveConn(c, opts, nil)
437}
438
439func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn)) {
William Kurkianea869482019-04-09 15:16:11 -0400440 baseCtx, cancel := serverConnBaseContext(c, opts)
441 defer cancel()
442
443 sc := &serverConn{
444 srv: s,
445 hs: opts.baseConfig(),
446 conn: c,
447 baseCtx: baseCtx,
448 remoteAddrStr: c.RemoteAddr().String(),
449 bw: newBufferedWriter(c),
450 handler: opts.handler(),
451 streams: make(map[uint32]*stream),
452 readFrameCh: make(chan readFrameResult),
453 wantWriteFrameCh: make(chan FrameWriteRequest, 8),
454 serveMsgCh: make(chan interface{}, 8),
455 wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync
456 bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way
457 doneServing: make(chan struct{}),
458 clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"
459 advMaxStreams: s.maxConcurrentStreams(),
460 initialStreamSendWindowSize: initialWindowSize,
461 maxFrameSize: initialMaxFrameSize,
William Kurkianea869482019-04-09 15:16:11 -0400462 serveG: newGoroutineLock(),
463 pushEnabled: true,
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530464 sawClientPreface: opts.SawClientPreface,
William Kurkianea869482019-04-09 15:16:11 -0400465 }
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530466 if newf != nil {
467 newf(sc)
468 }
William Kurkianea869482019-04-09 15:16:11 -0400469
470 s.state.registerConn(sc)
471 defer s.state.unregisterConn(sc)
472
473 // The net/http package sets the write deadline from the
474 // http.Server.WriteTimeout during the TLS handshake, but then
475 // passes the connection off to us with the deadline already set.
476 // Write deadlines are set per stream in serverConn.newStream.
477 // Disarm the net.Conn write deadline here.
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530478 if sc.hs.WriteTimeout > 0 {
William Kurkianea869482019-04-09 15:16:11 -0400479 sc.conn.SetWriteDeadline(time.Time{})
480 }
481
482 if s.NewWriteScheduler != nil {
483 sc.writeSched = s.NewWriteScheduler()
484 } else {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530485 sc.writeSched = newRoundRobinWriteScheduler()
William Kurkianea869482019-04-09 15:16:11 -0400486 }
487
488 // These start at the RFC-specified defaults. If there is a higher
489 // configured value for inflow, that will be updated when we send a
490 // WINDOW_UPDATE shortly after sending SETTINGS.
491 sc.flow.add(initialWindowSize)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530492 sc.inflow.init(initialWindowSize)
William Kurkianea869482019-04-09 15:16:11 -0400493 sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530494 sc.hpackEncoder.SetMaxDynamicTableSizeLimit(s.maxEncoderHeaderTableSize())
William Kurkianea869482019-04-09 15:16:11 -0400495
496 fr := NewFramer(sc.bw, c)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530497 if s.CountError != nil {
498 fr.countError = s.CountError
499 }
500 fr.ReadMetaHeaders = hpack.NewDecoder(s.maxDecoderHeaderTableSize(), nil)
William Kurkianea869482019-04-09 15:16:11 -0400501 fr.MaxHeaderListSize = sc.maxHeaderListSize()
502 fr.SetMaxReadFrameSize(s.maxReadFrameSize())
503 sc.framer = fr
504
505 if tc, ok := c.(connectionStater); ok {
506 sc.tlsState = new(tls.ConnectionState)
507 *sc.tlsState = tc.ConnectionState()
508 // 9.2 Use of TLS Features
509 // An implementation of HTTP/2 over TLS MUST use TLS
510 // 1.2 or higher with the restrictions on feature set
511 // and cipher suite described in this section. Due to
512 // implementation limitations, it might not be
513 // possible to fail TLS negotiation. An endpoint MUST
514 // immediately terminate an HTTP/2 connection that
515 // does not meet the TLS requirements described in
516 // this section with a connection error (Section
517 // 5.4.1) of type INADEQUATE_SECURITY.
518 if sc.tlsState.Version < tls.VersionTLS12 {
519 sc.rejectConn(ErrCodeInadequateSecurity, "TLS version too low")
520 return
521 }
522
523 if sc.tlsState.ServerName == "" {
524 // Client must use SNI, but we don't enforce that anymore,
525 // since it was causing problems when connecting to bare IP
526 // addresses during development.
527 //
528 // TODO: optionally enforce? Or enforce at the time we receive
529 // a new request, and verify the ServerName matches the :authority?
530 // But that precludes proxy situations, perhaps.
531 //
532 // So for now, do nothing here again.
533 }
534
535 if !s.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {
536 // "Endpoints MAY choose to generate a connection error
537 // (Section 5.4.1) of type INADEQUATE_SECURITY if one of
538 // the prohibited cipher suites are negotiated."
539 //
540 // We choose that. In my opinion, the spec is weak
541 // here. It also says both parties must support at least
542 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no
543 // excuses here. If we really must, we could allow an
544 // "AllowInsecureWeakCiphers" option on the server later.
545 // Let's see how it plays out first.
546 sc.rejectConn(ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite))
547 return
548 }
549 }
550
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530551 if opts.Settings != nil {
552 fr := &SettingsFrame{
553 FrameHeader: FrameHeader{valid: true},
554 p: opts.Settings,
555 }
556 if err := fr.ForeachSetting(sc.processSetting); err != nil {
557 sc.rejectConn(ErrCodeProtocol, "invalid settings")
558 return
559 }
560 opts.Settings = nil
561 }
562
William Kurkianea869482019-04-09 15:16:11 -0400563 if hook := testHookGetServerConn; hook != nil {
564 hook(sc)
565 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530566
567 if opts.UpgradeRequest != nil {
568 sc.upgradeRequest(opts.UpgradeRequest)
569 opts.UpgradeRequest = nil
570 }
571
William Kurkianea869482019-04-09 15:16:11 -0400572 sc.serve()
573}
574
575func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {
Abhilash S.L3b494632019-07-16 15:51:09 +0530576 ctx, cancel = context.WithCancel(opts.context())
William Kurkianea869482019-04-09 15:16:11 -0400577 ctx = context.WithValue(ctx, http.LocalAddrContextKey, c.LocalAddr())
578 if hs := opts.baseConfig(); hs != nil {
579 ctx = context.WithValue(ctx, http.ServerContextKey, hs)
580 }
581 return
582}
583
584func (sc *serverConn) rejectConn(err ErrCode, debug string) {
585 sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)
586 // ignoring errors. hanging up anyway.
587 sc.framer.WriteGoAway(0, err, []byte(debug))
588 sc.bw.Flush()
589 sc.conn.Close()
590}
591
592type serverConn struct {
593 // Immutable:
594 srv *Server
595 hs *http.Server
596 conn net.Conn
597 bw *bufferedWriter // writing to conn
598 handler http.Handler
599 baseCtx context.Context
600 framer *Framer
601 doneServing chan struct{} // closed when serverConn.serve ends
602 readFrameCh chan readFrameResult // written by serverConn.readFrames
603 wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve
604 wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes
605 bodyReadCh chan bodyReadMsg // from handlers -> serve
606 serveMsgCh chan interface{} // misc messages & code to send to / run on the serve loop
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530607 flow outflow // conn-wide (not stream-specific) outbound flow control
608 inflow inflow // conn-wide inbound flow control
William Kurkianea869482019-04-09 15:16:11 -0400609 tlsState *tls.ConnectionState // shared by all handlers, like net/http
610 remoteAddrStr string
611 writeSched WriteScheduler
612
613 // Everything following is owned by the serve loop; use serveG.check():
614 serveG goroutineLock // used to verify funcs are on serve()
615 pushEnabled bool
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530616 sawClientPreface bool // preface has already been read, used in h2c upgrade
William Kurkianea869482019-04-09 15:16:11 -0400617 sawFirstSettings bool // got the initial SETTINGS frame after the preface
618 needToSendSettingsAck bool
619 unackedSettings int // how many SETTINGS have we sent without ACKs?
David Bainbridge788e5202019-10-21 18:49:40 +0000620 queuedControlFrames int // control frames in the writeSched queue
William Kurkianea869482019-04-09 15:16:11 -0400621 clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)
622 advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client
623 curClientStreams uint32 // number of open streams initiated by the client
624 curPushedStreams uint32 // number of open streams initiated by server push
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530625 curHandlers uint32 // number of running handler goroutines
William Kurkianea869482019-04-09 15:16:11 -0400626 maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests
627 maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes
628 streams map[uint32]*stream
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530629 unstartedHandlers []unstartedHandler
William Kurkianea869482019-04-09 15:16:11 -0400630 initialStreamSendWindowSize int32
631 maxFrameSize int32
William Kurkianea869482019-04-09 15:16:11 -0400632 peerMaxHeaderListSize uint32 // zero means unknown (default)
633 canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530634 canonHeaderKeysSize int // canonHeader keys size in bytes
William Kurkianea869482019-04-09 15:16:11 -0400635 writingFrame bool // started writing a frame (on serve goroutine or separate)
636 writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh
637 needsFrameFlush bool // last frame write wasn't a flush
638 inGoAway bool // we've started to or sent GOAWAY
639 inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop
640 needToSendGoAway bool // we need to schedule a GOAWAY frame write
641 goAwayCode ErrCode
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530642 shutdownTimer timer // nil until used
643 idleTimer timer // nil if unused
William Kurkianea869482019-04-09 15:16:11 -0400644
645 // Owned by the writeFrameAsync goroutine:
646 headerWriteBuf bytes.Buffer
647 hpackEncoder *hpack.Encoder
648
649 // Used by startGracefulShutdown.
650 shutdownOnce sync.Once
651}
652
653func (sc *serverConn) maxHeaderListSize() uint32 {
654 n := sc.hs.MaxHeaderBytes
655 if n <= 0 {
656 n = http.DefaultMaxHeaderBytes
657 }
658 // http2's count is in a slightly different unit and includes 32 bytes per pair.
659 // So, take the net/http.Server value and pad it up a bit, assuming 10 headers.
660 const perFieldOverhead = 32 // per http2 spec
661 const typicalHeaders = 10 // conservative
662 return uint32(n + typicalHeaders*perFieldOverhead)
663}
664
665func (sc *serverConn) curOpenStreams() uint32 {
666 sc.serveG.check()
667 return sc.curClientStreams + sc.curPushedStreams
668}
669
670// stream represents a stream. This is the minimal metadata needed by
671// the serve goroutine. Most of the actual stream state is owned by
672// the http.Handler's goroutine in the responseWriter. Because the
673// responseWriter's responseWriterState is recycled at the end of a
674// handler, this struct intentionally has no pointer to the
675// *responseWriter{,State} itself, as the Handler ending nils out the
676// responseWriter's state field.
677type stream struct {
678 // immutable:
679 sc *serverConn
680 id uint32
681 body *pipe // non-nil if expecting DATA frames
682 cw closeWaiter // closed wait stream transitions to closed state
683 ctx context.Context
684 cancelCtx func()
685
686 // owned by serverConn's serve loop:
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530687 bodyBytes int64 // body bytes seen so far
688 declBodyBytes int64 // or -1 if undeclared
689 flow outflow // limits writing from Handler to client
690 inflow inflow // what the client is allowed to POST/etc to us
William Kurkianea869482019-04-09 15:16:11 -0400691 state streamState
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530692 resetQueued bool // RST_STREAM queued for write; set by sc.resetStream
693 gotTrailerHeader bool // HEADER frame for trailers was seen
694 wroteHeaders bool // whether we wrote headers (not status 100)
695 readDeadline timer // nil if unused
696 writeDeadline timer // nil if unused
697 closeErr error // set before cw is closed
William Kurkianea869482019-04-09 15:16:11 -0400698
699 trailer http.Header // accumulated trailers
700 reqTrailer http.Header // handler's Request.Trailer
701}
702
703func (sc *serverConn) Framer() *Framer { return sc.framer }
704func (sc *serverConn) CloseConn() error { return sc.conn.Close() }
705func (sc *serverConn) Flush() error { return sc.bw.Flush() }
706func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {
707 return sc.hpackEncoder, &sc.headerWriteBuf
708}
709
710func (sc *serverConn) state(streamID uint32) (streamState, *stream) {
711 sc.serveG.check()
712 // http://tools.ietf.org/html/rfc7540#section-5.1
713 if st, ok := sc.streams[streamID]; ok {
714 return st.state, st
715 }
716 // "The first use of a new stream identifier implicitly closes all
717 // streams in the "idle" state that might have been initiated by
718 // that peer with a lower-valued stream identifier. For example, if
719 // a client sends a HEADERS frame on stream 7 without ever sending a
720 // frame on stream 5, then stream 5 transitions to the "closed"
721 // state when the first frame for stream 7 is sent or received."
722 if streamID%2 == 1 {
723 if streamID <= sc.maxClientStreamID {
724 return stateClosed, nil
725 }
726 } else {
727 if streamID <= sc.maxPushPromiseID {
728 return stateClosed, nil
729 }
730 }
731 return stateIdle, nil
732}
733
734// setConnState calls the net/http ConnState hook for this connection, if configured.
735// Note that the net/http package does StateNew and StateClosed for us.
736// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.
737func (sc *serverConn) setConnState(state http.ConnState) {
738 if sc.hs.ConnState != nil {
739 sc.hs.ConnState(sc.conn, state)
740 }
741}
742
743func (sc *serverConn) vlogf(format string, args ...interface{}) {
744 if VerboseLogs {
745 sc.logf(format, args...)
746 }
747}
748
749func (sc *serverConn) logf(format string, args ...interface{}) {
750 if lg := sc.hs.ErrorLog; lg != nil {
751 lg.Printf(format, args...)
752 } else {
753 log.Printf(format, args...)
754 }
755}
756
757// errno returns v's underlying uintptr, else 0.
758//
759// TODO: remove this helper function once http2 can use build
760// tags. See comment in isClosedConnError.
761func errno(v error) uintptr {
762 if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr {
763 return uintptr(rv.Uint())
764 }
765 return 0
766}
767
768// isClosedConnError reports whether err is an error from use of a closed
769// network connection.
770func isClosedConnError(err error) bool {
771 if err == nil {
772 return false
773 }
774
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530775 if errors.Is(err, net.ErrClosed) {
William Kurkianea869482019-04-09 15:16:11 -0400776 return true
777 }
778
779 // TODO(bradfitz): x/tools/cmd/bundle doesn't really support
780 // build tags, so I can't make an http2_windows.go file with
781 // Windows-specific stuff. Fix that and move this, once we
782 // have a way to bundle this into std's net/http somehow.
783 if runtime.GOOS == "windows" {
784 if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {
785 if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" {
786 const WSAECONNABORTED = 10053
787 const WSAECONNRESET = 10054
788 if n := errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED {
789 return true
790 }
791 }
792 }
793 }
794 return false
795}
796
797func (sc *serverConn) condlogf(err error, format string, args ...interface{}) {
798 if err == nil {
799 return
800 }
801 if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {
802 // Boring, expected errors.
803 sc.vlogf(format, args...)
804 } else {
805 sc.logf(format, args...)
806 }
807}
808
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530809// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size
810// of the entries in the canonHeader cache.
811// This should be larger than the size of unique, uncommon header keys likely to
812// be sent by the peer, while not so high as to permit unreasonable memory usage
813// if the peer sends an unbounded number of unique header keys.
814const maxCachedCanonicalHeadersKeysSize = 2048
815
William Kurkianea869482019-04-09 15:16:11 -0400816func (sc *serverConn) canonicalHeader(v string) string {
817 sc.serveG.check()
818 buildCommonHeaderMapsOnce()
819 cv, ok := commonCanonHeader[v]
820 if ok {
821 return cv
822 }
823 cv, ok = sc.canonHeader[v]
824 if ok {
825 return cv
826 }
827 if sc.canonHeader == nil {
828 sc.canonHeader = make(map[string]string)
829 }
830 cv = http.CanonicalHeaderKey(v)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530831 size := 100 + len(v)*2 // 100 bytes of map overhead + key + value
832 if sc.canonHeaderKeysSize+size <= maxCachedCanonicalHeadersKeysSize {
833 sc.canonHeader[v] = cv
834 sc.canonHeaderKeysSize += size
835 }
William Kurkianea869482019-04-09 15:16:11 -0400836 return cv
837}
838
839type readFrameResult struct {
840 f Frame // valid until readMore is called
841 err error
842
843 // readMore should be called once the consumer no longer needs or
844 // retains f. After readMore, f is invalid and more frames can be
845 // read.
846 readMore func()
847}
848
849// readFrames is the loop that reads incoming frames.
850// It takes care to only read one frame at a time, blocking until the
851// consumer is done with the frame.
852// It's run on its own goroutine.
853func (sc *serverConn) readFrames() {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530854 sc.srv.markNewGoroutine()
855 gate := make(chan struct{})
856 gateDone := func() { gate <- struct{}{} }
William Kurkianea869482019-04-09 15:16:11 -0400857 for {
858 f, err := sc.framer.ReadFrame()
859 select {
860 case sc.readFrameCh <- readFrameResult{f, err, gateDone}:
861 case <-sc.doneServing:
862 return
863 }
864 select {
865 case <-gate:
866 case <-sc.doneServing:
867 return
868 }
869 if terminalReadFrameError(err) {
870 return
871 }
872 }
873}
874
875// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
876type frameWriteResult struct {
khenaidoo106c61a2021-08-11 18:05:46 -0400877 _ incomparable
William Kurkianea869482019-04-09 15:16:11 -0400878 wr FrameWriteRequest // what was written (or attempted)
879 err error // result of the writeFrame call
880}
881
882// writeFrameAsync runs in its own goroutine and writes a single frame
883// and then reports when it's done.
884// At most one goroutine can be running writeFrameAsync at a time per
885// serverConn.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530886func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530887 sc.srv.markNewGoroutine()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530888 var err error
889 if wd == nil {
890 err = wr.write.writeFrame(sc)
891 } else {
892 err = sc.framer.endWrite()
893 }
khenaidoo106c61a2021-08-11 18:05:46 -0400894 sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}
William Kurkianea869482019-04-09 15:16:11 -0400895}
896
897func (sc *serverConn) closeAllStreamsOnConnClose() {
898 sc.serveG.check()
899 for _, st := range sc.streams {
900 sc.closeStream(st, errClientDisconnected)
901 }
902}
903
904func (sc *serverConn) stopShutdownTimer() {
905 sc.serveG.check()
906 if t := sc.shutdownTimer; t != nil {
907 t.Stop()
908 }
909}
910
911func (sc *serverConn) notePanic() {
912 // Note: this is for serverConn.serve panicking, not http.Handler code.
913 if testHookOnPanicMu != nil {
914 testHookOnPanicMu.Lock()
915 defer testHookOnPanicMu.Unlock()
916 }
917 if testHookOnPanic != nil {
918 if e := recover(); e != nil {
919 if testHookOnPanic(sc, e) {
920 panic(e)
921 }
922 }
923 }
924}
925
926func (sc *serverConn) serve() {
927 sc.serveG.check()
928 defer sc.notePanic()
929 defer sc.conn.Close()
930 defer sc.closeAllStreamsOnConnClose()
931 defer sc.stopShutdownTimer()
932 defer close(sc.doneServing) // unblocks handlers trying to send
933
934 if VerboseLogs {
935 sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)
936 }
937
938 sc.writeFrame(FrameWriteRequest{
939 write: writeSettings{
940 {SettingMaxFrameSize, sc.srv.maxReadFrameSize()},
941 {SettingMaxConcurrentStreams, sc.advMaxStreams},
942 {SettingMaxHeaderListSize, sc.maxHeaderListSize()},
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530943 {SettingHeaderTableSize, sc.srv.maxDecoderHeaderTableSize()},
William Kurkianea869482019-04-09 15:16:11 -0400944 {SettingInitialWindowSize, uint32(sc.srv.initialStreamRecvWindowSize())},
945 },
946 })
947 sc.unackedSettings++
948
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530949 // Each connection starts with initialWindowSize inflow tokens.
William Kurkianea869482019-04-09 15:16:11 -0400950 // If a higher value is configured, we add more tokens.
951 if diff := sc.srv.initialConnRecvWindowSize() - initialWindowSize; diff > 0 {
952 sc.sendWindowUpdate(nil, int(diff))
953 }
954
955 if err := sc.readPreface(); err != nil {
956 sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)
957 return
958 }
959 // Now that we've got the preface, get us out of the
960 // "StateNew" state. We can't go directly to idle, though.
961 // Active means we read some data and anticipate a request. We'll
962 // do another Active when we get a HEADERS frame.
963 sc.setConnState(http.StateActive)
964 sc.setConnState(http.StateIdle)
965
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530966 if sc.srv.IdleTimeout > 0 {
967 sc.idleTimer = sc.srv.afterFunc(sc.srv.IdleTimeout, sc.onIdleTimer)
William Kurkianea869482019-04-09 15:16:11 -0400968 defer sc.idleTimer.Stop()
969 }
970
971 go sc.readFrames() // closed by defer sc.conn.Close above
972
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +0530973 settingsTimer := sc.srv.afterFunc(firstSettingsTimeout, sc.onSettingsTimer)
William Kurkianea869482019-04-09 15:16:11 -0400974 defer settingsTimer.Stop()
975
976 loopNum := 0
977 for {
978 loopNum++
979 select {
980 case wr := <-sc.wantWriteFrameCh:
981 if se, ok := wr.write.(StreamError); ok {
982 sc.resetStream(se)
983 break
984 }
985 sc.writeFrame(wr)
986 case res := <-sc.wroteFrameCh:
987 sc.wroteFrame(res)
988 case res := <-sc.readFrameCh:
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530989 // Process any written frames before reading new frames from the client since a
990 // written frame could have triggered a new stream to be started.
991 if sc.writingFrameAsync {
992 select {
993 case wroteRes := <-sc.wroteFrameCh:
994 sc.wroteFrame(wroteRes)
995 default:
996 }
997 }
William Kurkianea869482019-04-09 15:16:11 -0400998 if !sc.processFrameFromReader(res) {
999 return
1000 }
1001 res.readMore()
1002 if settingsTimer != nil {
1003 settingsTimer.Stop()
1004 settingsTimer = nil
1005 }
1006 case m := <-sc.bodyReadCh:
1007 sc.noteBodyRead(m.st, m.n)
1008 case msg := <-sc.serveMsgCh:
1009 switch v := msg.(type) {
1010 case func(int):
1011 v(loopNum) // for testing
1012 case *serverMessage:
1013 switch v {
1014 case settingsTimerMsg:
1015 sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())
1016 return
1017 case idleTimerMsg:
1018 sc.vlogf("connection is idle")
1019 sc.goAway(ErrCodeNo)
1020 case shutdownTimerMsg:
1021 sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())
1022 return
1023 case gracefulShutdownMsg:
1024 sc.startGracefulShutdownInternal()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301025 case handlerDoneMsg:
1026 sc.handlerDone()
William Kurkianea869482019-04-09 15:16:11 -04001027 default:
1028 panic("unknown timer")
1029 }
1030 case *startPushRequest:
1031 sc.startPush(v)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301032 case func(*serverConn):
1033 v(sc)
William Kurkianea869482019-04-09 15:16:11 -04001034 default:
1035 panic(fmt.Sprintf("unexpected type %T", v))
1036 }
1037 }
1038
David Bainbridge788e5202019-10-21 18:49:40 +00001039 // If the peer is causing us to generate a lot of control frames,
1040 // but not reading them from us, assume they are trying to make us
1041 // run out of memory.
1042 if sc.queuedControlFrames > sc.srv.maxQueuedControlFrames() {
1043 sc.vlogf("http2: too many control frames in send queue, closing connection")
1044 return
1045 }
1046
William Kurkianea869482019-04-09 15:16:11 -04001047 // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY
1048 // with no error code (graceful shutdown), don't start the timer until
1049 // all open streams have been completed.
1050 sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame
1051 gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0
1052 if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {
1053 sc.shutDownIn(goAwayTimeout)
1054 }
1055 }
1056}
1057
William Kurkianea869482019-04-09 15:16:11 -04001058type serverMessage int
1059
1060// Message values sent to serveMsgCh.
1061var (
1062 settingsTimerMsg = new(serverMessage)
1063 idleTimerMsg = new(serverMessage)
1064 shutdownTimerMsg = new(serverMessage)
1065 gracefulShutdownMsg = new(serverMessage)
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301066 handlerDoneMsg = new(serverMessage)
William Kurkianea869482019-04-09 15:16:11 -04001067)
1068
1069func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }
1070func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }
1071func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }
1072
1073func (sc *serverConn) sendServeMsg(msg interface{}) {
1074 sc.serveG.checkNotOn() // NOT
1075 select {
1076 case sc.serveMsgCh <- msg:
1077 case <-sc.doneServing:
1078 }
1079}
1080
1081var errPrefaceTimeout = errors.New("timeout waiting for client preface")
1082
1083// readPreface reads the ClientPreface greeting from the peer or
1084// returns errPrefaceTimeout on timeout, or an error if the greeting
1085// is invalid.
1086func (sc *serverConn) readPreface() error {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301087 if sc.sawClientPreface {
1088 return nil
1089 }
William Kurkianea869482019-04-09 15:16:11 -04001090 errc := make(chan error, 1)
1091 go func() {
1092 // Read the client preface
1093 buf := make([]byte, len(ClientPreface))
1094 if _, err := io.ReadFull(sc.conn, buf); err != nil {
1095 errc <- err
1096 } else if !bytes.Equal(buf, clientPreface) {
1097 errc <- fmt.Errorf("bogus greeting %q", buf)
1098 } else {
1099 errc <- nil
1100 }
1101 }()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301102 timer := sc.srv.newTimer(prefaceTimeout) // TODO: configurable on *Server?
William Kurkianea869482019-04-09 15:16:11 -04001103 defer timer.Stop()
1104 select {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301105 case <-timer.C():
William Kurkianea869482019-04-09 15:16:11 -04001106 return errPrefaceTimeout
1107 case err := <-errc:
1108 if err == nil {
1109 if VerboseLogs {
1110 sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr())
1111 }
1112 }
1113 return err
1114 }
1115}
1116
1117var errChanPool = sync.Pool{
1118 New: func() interface{} { return make(chan error, 1) },
1119}
1120
1121var writeDataPool = sync.Pool{
1122 New: func() interface{} { return new(writeData) },
1123}
1124
1125// writeDataFromHandler writes DATA response frames from a handler on
1126// the given stream.
1127func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {
1128 ch := errChanPool.Get().(chan error)
1129 writeArg := writeDataPool.Get().(*writeData)
1130 *writeArg = writeData{stream.id, data, endStream}
1131 err := sc.writeFrameFromHandler(FrameWriteRequest{
1132 write: writeArg,
1133 stream: stream,
1134 done: ch,
1135 })
1136 if err != nil {
1137 return err
1138 }
1139 var frameWriteDone bool // the frame write is done (successfully or not)
1140 select {
1141 case err = <-ch:
1142 frameWriteDone = true
1143 case <-sc.doneServing:
1144 return errClientDisconnected
1145 case <-stream.cw:
1146 // If both ch and stream.cw were ready (as might
1147 // happen on the final Write after an http.Handler
1148 // ends), prefer the write result. Otherwise this
1149 // might just be us successfully closing the stream.
1150 // The writeFrameAsync and serve goroutines guarantee
1151 // that the ch send will happen before the stream.cw
1152 // close.
1153 select {
1154 case err = <-ch:
1155 frameWriteDone = true
1156 default:
1157 return errStreamClosed
1158 }
1159 }
1160 errChanPool.Put(ch)
1161 if frameWriteDone {
1162 writeDataPool.Put(writeArg)
1163 }
1164 return err
1165}
1166
1167// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts
1168// if the connection has gone away.
1169//
1170// This must not be run from the serve goroutine itself, else it might
1171// deadlock writing to sc.wantWriteFrameCh (which is only mildly
1172// buffered and is read by serve itself). If you're on the serve
1173// goroutine, call writeFrame instead.
1174func (sc *serverConn) writeFrameFromHandler(wr FrameWriteRequest) error {
1175 sc.serveG.checkNotOn() // NOT
1176 select {
1177 case sc.wantWriteFrameCh <- wr:
1178 return nil
1179 case <-sc.doneServing:
1180 // Serve loop is gone.
1181 // Client has closed their connection to the server.
1182 return errClientDisconnected
1183 }
1184}
1185
1186// writeFrame schedules a frame to write and sends it if there's nothing
1187// already being written.
1188//
1189// There is no pushback here (the serve goroutine never blocks). It's
1190// the http.Handlers that block, waiting for their previous frames to
1191// make it onto the wire
1192//
1193// If you're not on the serve goroutine, use writeFrameFromHandler instead.
1194func (sc *serverConn) writeFrame(wr FrameWriteRequest) {
1195 sc.serveG.check()
1196
1197 // If true, wr will not be written and wr.done will not be signaled.
1198 var ignoreWrite bool
1199
1200 // We are not allowed to write frames on closed streams. RFC 7540 Section
1201 // 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on
1202 // a closed stream." Our server never sends PRIORITY, so that exception
1203 // does not apply.
1204 //
1205 // The serverConn might close an open stream while the stream's handler
1206 // is still running. For example, the server might close a stream when it
1207 // receives bad data from the client. If this happens, the handler might
1208 // attempt to write a frame after the stream has been closed (since the
1209 // handler hasn't yet been notified of the close). In this case, we simply
1210 // ignore the frame. The handler will notice that the stream is closed when
1211 // it waits for the frame to be written.
1212 //
1213 // As an exception to this rule, we allow sending RST_STREAM after close.
1214 // This allows us to immediately reject new streams without tracking any
1215 // state for those streams (except for the queued RST_STREAM frame). This
1216 // may result in duplicate RST_STREAMs in some cases, but the client should
1217 // ignore those.
1218 if wr.StreamID() != 0 {
1219 _, isReset := wr.write.(StreamError)
1220 if state, _ := sc.state(wr.StreamID()); state == stateClosed && !isReset {
1221 ignoreWrite = true
1222 }
1223 }
1224
1225 // Don't send a 100-continue response if we've already sent headers.
1226 // See golang.org/issue/14030.
1227 switch wr.write.(type) {
1228 case *writeResHeaders:
1229 wr.stream.wroteHeaders = true
1230 case write100ContinueHeadersFrame:
1231 if wr.stream.wroteHeaders {
1232 // We do not need to notify wr.done because this frame is
1233 // never written with wr.done != nil.
1234 if wr.done != nil {
1235 panic("wr.done != nil for write100ContinueHeadersFrame")
1236 }
1237 ignoreWrite = true
1238 }
1239 }
1240
1241 if !ignoreWrite {
David Bainbridge788e5202019-10-21 18:49:40 +00001242 if wr.isControl() {
1243 sc.queuedControlFrames++
1244 // For extra safety, detect wraparounds, which should not happen,
1245 // and pull the plug.
1246 if sc.queuedControlFrames < 0 {
1247 sc.conn.Close()
1248 }
1249 }
William Kurkianea869482019-04-09 15:16:11 -04001250 sc.writeSched.Push(wr)
1251 }
1252 sc.scheduleFrameWrite()
1253}
1254
1255// startFrameWrite starts a goroutine to write wr (in a separate
1256// goroutine since that might block on the network), and updates the
1257// serve goroutine's state about the world, updated from info in wr.
1258func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
1259 sc.serveG.check()
1260 if sc.writingFrame {
1261 panic("internal error: can only be writing one frame at a time")
1262 }
1263
1264 st := wr.stream
1265 if st != nil {
1266 switch st.state {
1267 case stateHalfClosedLocal:
1268 switch wr.write.(type) {
1269 case StreamError, handlerPanicRST, writeWindowUpdate:
1270 // RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE
1271 // in this state. (We never send PRIORITY from the server, so that is not checked.)
1272 default:
1273 panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))
1274 }
1275 case stateClosed:
1276 panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))
1277 }
1278 }
1279 if wpp, ok := wr.write.(*writePushPromise); ok {
1280 var err error
1281 wpp.promisedID, err = wpp.allocatePromisedID()
1282 if err != nil {
1283 sc.writingFrameAsync = false
1284 wr.replyToWriter(err)
1285 return
1286 }
1287 }
1288
1289 sc.writingFrame = true
1290 sc.needsFrameFlush = true
1291 if wr.write.staysWithinBuffer(sc.bw.Available()) {
1292 sc.writingFrameAsync = false
1293 err := wr.write.writeFrame(sc)
khenaidoo106c61a2021-08-11 18:05:46 -04001294 sc.wroteFrame(frameWriteResult{wr: wr, err: err})
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301295 } else if wd, ok := wr.write.(*writeData); ok {
1296 // Encode the frame in the serve goroutine, to ensure we don't have
1297 // any lingering asynchronous references to data passed to Write.
1298 // See https://go.dev/issue/58446.
1299 sc.framer.startWriteDataPadded(wd.streamID, wd.endStream, wd.p, nil)
1300 sc.writingFrameAsync = true
1301 go sc.writeFrameAsync(wr, wd)
William Kurkianea869482019-04-09 15:16:11 -04001302 } else {
1303 sc.writingFrameAsync = true
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301304 go sc.writeFrameAsync(wr, nil)
William Kurkianea869482019-04-09 15:16:11 -04001305 }
1306}
1307
1308// errHandlerPanicked is the error given to any callers blocked in a read from
1309// Request.Body when the main goroutine panics. Since most handlers read in the
1310// main ServeHTTP goroutine, this will show up rarely.
1311var errHandlerPanicked = errors.New("http2: handler panicked")
1312
1313// wroteFrame is called on the serve goroutine with the result of
1314// whatever happened on writeFrameAsync.
1315func (sc *serverConn) wroteFrame(res frameWriteResult) {
1316 sc.serveG.check()
1317 if !sc.writingFrame {
1318 panic("internal error: expected to be already writing a frame")
1319 }
1320 sc.writingFrame = false
1321 sc.writingFrameAsync = false
1322
1323 wr := res.wr
1324
1325 if writeEndsStream(wr.write) {
1326 st := wr.stream
1327 if st == nil {
1328 panic("internal error: expecting non-nil stream")
1329 }
1330 switch st.state {
1331 case stateOpen:
1332 // Here we would go to stateHalfClosedLocal in
1333 // theory, but since our handler is done and
1334 // the net/http package provides no mechanism
1335 // for closing a ResponseWriter while still
1336 // reading data (see possible TODO at top of
1337 // this file), we go into closed state here
1338 // anyway, after telling the peer we're
1339 // hanging up on them. We'll transition to
1340 // stateClosed after the RST_STREAM frame is
1341 // written.
1342 st.state = stateHalfClosedLocal
1343 // Section 8.1: a server MAY request that the client abort
1344 // transmission of a request without error by sending a
1345 // RST_STREAM with an error code of NO_ERROR after sending
1346 // a complete response.
1347 sc.resetStream(streamError(st.id, ErrCodeNo))
1348 case stateHalfClosedRemote:
1349 sc.closeStream(st, errHandlerComplete)
1350 }
1351 } else {
1352 switch v := wr.write.(type) {
1353 case StreamError:
1354 // st may be unknown if the RST_STREAM was generated to reject bad input.
1355 if st, ok := sc.streams[v.StreamID]; ok {
1356 sc.closeStream(st, v)
1357 }
1358 case handlerPanicRST:
1359 sc.closeStream(wr.stream, errHandlerPanicked)
1360 }
1361 }
1362
1363 // Reply (if requested) to unblock the ServeHTTP goroutine.
1364 wr.replyToWriter(res.err)
1365
1366 sc.scheduleFrameWrite()
1367}
1368
1369// scheduleFrameWrite tickles the frame writing scheduler.
1370//
1371// If a frame is already being written, nothing happens. This will be called again
1372// when the frame is done being written.
1373//
David Bainbridge788e5202019-10-21 18:49:40 +00001374// If a frame isn't being written and we need to send one, the best frame
1375// to send is selected by writeSched.
William Kurkianea869482019-04-09 15:16:11 -04001376//
1377// If a frame isn't being written and there's nothing else to send, we
1378// flush the write buffer.
1379func (sc *serverConn) scheduleFrameWrite() {
1380 sc.serveG.check()
1381 if sc.writingFrame || sc.inFrameScheduleLoop {
1382 return
1383 }
1384 sc.inFrameScheduleLoop = true
1385 for !sc.writingFrameAsync {
1386 if sc.needToSendGoAway {
1387 sc.needToSendGoAway = false
1388 sc.startFrameWrite(FrameWriteRequest{
1389 write: &writeGoAway{
1390 maxStreamID: sc.maxClientStreamID,
1391 code: sc.goAwayCode,
1392 },
1393 })
1394 continue
1395 }
1396 if sc.needToSendSettingsAck {
1397 sc.needToSendSettingsAck = false
1398 sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})
1399 continue
1400 }
1401 if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {
1402 if wr, ok := sc.writeSched.Pop(); ok {
David Bainbridge788e5202019-10-21 18:49:40 +00001403 if wr.isControl() {
1404 sc.queuedControlFrames--
1405 }
William Kurkianea869482019-04-09 15:16:11 -04001406 sc.startFrameWrite(wr)
1407 continue
1408 }
1409 }
1410 if sc.needsFrameFlush {
1411 sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}})
1412 sc.needsFrameFlush = false // after startFrameWrite, since it sets this true
1413 continue
1414 }
1415 break
1416 }
1417 sc.inFrameScheduleLoop = false
1418}
1419
1420// startGracefulShutdown gracefully shuts down a connection. This
1421// sends GOAWAY with ErrCodeNo to tell the client we're gracefully
1422// shutting down. The connection isn't closed until all current
1423// streams are done.
1424//
1425// startGracefulShutdown returns immediately; it does not wait until
1426// the connection has shut down.
1427func (sc *serverConn) startGracefulShutdown() {
1428 sc.serveG.checkNotOn() // NOT
1429 sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })
1430}
1431
khenaidoo106c61a2021-08-11 18:05:46 -04001432// After sending GOAWAY with an error code (non-graceful shutdown), the
1433// connection will close after goAwayTimeout.
1434//
William Kurkianea869482019-04-09 15:16:11 -04001435// If we close the connection immediately after sending GOAWAY, there may
1436// be unsent data in our kernel receive buffer, which will cause the kernel
1437// to send a TCP RST on close() instead of a FIN. This RST will abort the
1438// connection immediately, whether or not the client had received the GOAWAY.
1439//
1440// Ideally we should delay for at least 1 RTT + epsilon so the client has
1441// a chance to read the GOAWAY and stop sending messages. Measuring RTT
1442// is hard, so we approximate with 1 second. See golang.org/issue/18701.
1443//
1444// This is a var so it can be shorter in tests, where all requests uses the
1445// loopback interface making the expected RTT very small.
1446//
1447// TODO: configurable?
1448var goAwayTimeout = 1 * time.Second
1449
1450func (sc *serverConn) startGracefulShutdownInternal() {
1451 sc.goAway(ErrCodeNo)
1452}
1453
1454func (sc *serverConn) goAway(code ErrCode) {
1455 sc.serveG.check()
1456 if sc.inGoAway {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301457 if sc.goAwayCode == ErrCodeNo {
1458 sc.goAwayCode = code
1459 }
William Kurkianea869482019-04-09 15:16:11 -04001460 return
1461 }
1462 sc.inGoAway = true
1463 sc.needToSendGoAway = true
1464 sc.goAwayCode = code
1465 sc.scheduleFrameWrite()
1466}
1467
1468func (sc *serverConn) shutDownIn(d time.Duration) {
1469 sc.serveG.check()
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301470 sc.shutdownTimer = sc.srv.afterFunc(d, sc.onShutdownTimer)
William Kurkianea869482019-04-09 15:16:11 -04001471}
1472
1473func (sc *serverConn) resetStream(se StreamError) {
1474 sc.serveG.check()
1475 sc.writeFrame(FrameWriteRequest{write: se})
1476 if st, ok := sc.streams[se.StreamID]; ok {
1477 st.resetQueued = true
1478 }
1479}
1480
1481// processFrameFromReader processes the serve loop's read from readFrameCh from the
1482// frame-reading goroutine.
1483// processFrameFromReader returns whether the connection should be kept open.
1484func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {
1485 sc.serveG.check()
1486 err := res.err
1487 if err != nil {
1488 if err == ErrFrameTooLarge {
1489 sc.goAway(ErrCodeFrameSize)
1490 return true // goAway will close the loop
1491 }
1492 clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err)
1493 if clientGone {
1494 // TODO: could we also get into this state if
1495 // the peer does a half close
1496 // (e.g. CloseWrite) because they're done
1497 // sending frames but they're still wanting
1498 // our open replies? Investigate.
1499 // TODO: add CloseWrite to crypto/tls.Conn first
1500 // so we have a way to test this? I suppose
1501 // just for testing we could have a non-TLS mode.
1502 return false
1503 }
1504 } else {
1505 f := res.f
1506 if VerboseLogs {
1507 sc.vlogf("http2: server read frame %v", summarizeFrame(f))
1508 }
1509 err = sc.processFrame(f)
1510 if err == nil {
1511 return true
1512 }
1513 }
1514
1515 switch ev := err.(type) {
1516 case StreamError:
1517 sc.resetStream(ev)
1518 return true
1519 case goAwayFlowError:
1520 sc.goAway(ErrCodeFlowControl)
1521 return true
1522 case ConnectionError:
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301523 if res.f != nil {
1524 if id := res.f.Header().StreamID; id > sc.maxClientStreamID {
1525 sc.maxClientStreamID = id
1526 }
1527 }
William Kurkianea869482019-04-09 15:16:11 -04001528 sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)
1529 sc.goAway(ErrCode(ev))
1530 return true // goAway will handle shutdown
1531 default:
1532 if res.err != nil {
1533 sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)
1534 } else {
1535 sc.logf("http2: server closing client connection: %v", err)
1536 }
1537 return false
1538 }
1539}
1540
1541func (sc *serverConn) processFrame(f Frame) error {
1542 sc.serveG.check()
1543
1544 // First frame received must be SETTINGS.
1545 if !sc.sawFirstSettings {
1546 if _, ok := f.(*SettingsFrame); !ok {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301547 return sc.countError("first_settings", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001548 }
1549 sc.sawFirstSettings = true
1550 }
1551
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301552 // Discard frames for streams initiated after the identified last
1553 // stream sent in a GOAWAY, or all frames after sending an error.
1554 // We still need to return connection-level flow control for DATA frames.
1555 // RFC 9113 Section 6.8.
1556 if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || f.Header().StreamID > sc.maxClientStreamID) {
1557
1558 if f, ok := f.(*DataFrame); ok {
1559 if !sc.inflow.take(f.Length) {
1560 return sc.countError("data_flow", streamError(f.Header().StreamID, ErrCodeFlowControl))
1561 }
1562 sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
1563 }
1564 return nil
1565 }
1566
William Kurkianea869482019-04-09 15:16:11 -04001567 switch f := f.(type) {
1568 case *SettingsFrame:
1569 return sc.processSettings(f)
1570 case *MetaHeadersFrame:
1571 return sc.processHeaders(f)
1572 case *WindowUpdateFrame:
1573 return sc.processWindowUpdate(f)
1574 case *PingFrame:
1575 return sc.processPing(f)
1576 case *DataFrame:
1577 return sc.processData(f)
1578 case *RSTStreamFrame:
1579 return sc.processResetStream(f)
1580 case *PriorityFrame:
1581 return sc.processPriority(f)
1582 case *GoAwayFrame:
1583 return sc.processGoAway(f)
1584 case *PushPromiseFrame:
1585 // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
1586 // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301587 return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001588 default:
1589 sc.vlogf("http2: server ignoring frame: %v", f.Header())
1590 return nil
1591 }
1592}
1593
1594func (sc *serverConn) processPing(f *PingFrame) error {
1595 sc.serveG.check()
1596 if f.IsAck() {
1597 // 6.7 PING: " An endpoint MUST NOT respond to PING frames
1598 // containing this flag."
1599 return nil
1600 }
1601 if f.StreamID != 0 {
1602 // "PING frames are not associated with any individual
1603 // stream. If a PING frame is received with a stream
1604 // identifier field value other than 0x0, the recipient MUST
1605 // respond with a connection error (Section 5.4.1) of type
1606 // PROTOCOL_ERROR."
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301607 return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001608 }
1609 sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})
1610 return nil
1611}
1612
1613func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
1614 sc.serveG.check()
1615 switch {
1616 case f.StreamID != 0: // stream-level flow control
1617 state, st := sc.state(f.StreamID)
1618 if state == stateIdle {
1619 // Section 5.1: "Receiving any frame other than HEADERS
1620 // or PRIORITY on a stream in this state MUST be
1621 // treated as a connection error (Section 5.4.1) of
1622 // type PROTOCOL_ERROR."
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301623 return sc.countError("stream_idle", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001624 }
1625 if st == nil {
1626 // "WINDOW_UPDATE can be sent by a peer that has sent a
1627 // frame bearing the END_STREAM flag. This means that a
1628 // receiver could receive a WINDOW_UPDATE frame on a "half
1629 // closed (remote)" or "closed" stream. A receiver MUST
1630 // NOT treat this as an error, see Section 5.1."
1631 return nil
1632 }
1633 if !st.flow.add(int32(f.Increment)) {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301634 return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl))
William Kurkianea869482019-04-09 15:16:11 -04001635 }
1636 default: // connection-level flow control
1637 if !sc.flow.add(int32(f.Increment)) {
1638 return goAwayFlowError{}
1639 }
1640 }
1641 sc.scheduleFrameWrite()
1642 return nil
1643}
1644
1645func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
1646 sc.serveG.check()
1647
1648 state, st := sc.state(f.StreamID)
1649 if state == stateIdle {
1650 // 6.4 "RST_STREAM frames MUST NOT be sent for a
1651 // stream in the "idle" state. If a RST_STREAM frame
1652 // identifying an idle stream is received, the
1653 // recipient MUST treat this as a connection error
1654 // (Section 5.4.1) of type PROTOCOL_ERROR.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301655 return sc.countError("reset_idle_stream", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001656 }
1657 if st != nil {
1658 st.cancelCtx()
1659 sc.closeStream(st, streamError(f.StreamID, f.ErrCode))
1660 }
1661 return nil
1662}
1663
1664func (sc *serverConn) closeStream(st *stream, err error) {
1665 sc.serveG.check()
1666 if st.state == stateIdle || st.state == stateClosed {
1667 panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))
1668 }
1669 st.state = stateClosed
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301670 if st.readDeadline != nil {
1671 st.readDeadline.Stop()
1672 }
William Kurkianea869482019-04-09 15:16:11 -04001673 if st.writeDeadline != nil {
1674 st.writeDeadline.Stop()
1675 }
1676 if st.isPushed() {
1677 sc.curPushedStreams--
1678 } else {
1679 sc.curClientStreams--
1680 }
1681 delete(sc.streams, st.id)
1682 if len(sc.streams) == 0 {
1683 sc.setConnState(http.StateIdle)
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301684 if sc.srv.IdleTimeout > 0 && sc.idleTimer != nil {
William Kurkianea869482019-04-09 15:16:11 -04001685 sc.idleTimer.Reset(sc.srv.IdleTimeout)
1686 }
1687 if h1ServerKeepAlivesDisabled(sc.hs) {
1688 sc.startGracefulShutdownInternal()
1689 }
1690 }
1691 if p := st.body; p != nil {
1692 // Return any buffered unread bytes worth of conn-level flow control.
1693 // See golang.org/issue/16481
1694 sc.sendWindowUpdate(nil, p.Len())
1695
1696 p.CloseWithError(err)
1697 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301698 if e, ok := err.(StreamError); ok {
1699 if e.Cause != nil {
1700 err = e.Cause
1701 } else {
1702 err = errStreamClosed
1703 }
1704 }
1705 st.closeErr = err
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301706 st.cancelCtx()
William Kurkianea869482019-04-09 15:16:11 -04001707 st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc
1708 sc.writeSched.CloseStream(st.id)
1709}
1710
1711func (sc *serverConn) processSettings(f *SettingsFrame) error {
1712 sc.serveG.check()
1713 if f.IsAck() {
1714 sc.unackedSettings--
1715 if sc.unackedSettings < 0 {
1716 // Why is the peer ACKing settings we never sent?
1717 // The spec doesn't mention this case, but
1718 // hang up on them anyway.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301719 return sc.countError("ack_mystery", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001720 }
1721 return nil
1722 }
1723 if f.NumSettings() > 100 || f.HasDuplicates() {
1724 // This isn't actually in the spec, but hang up on
1725 // suspiciously large settings frames or those with
1726 // duplicate entries.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301727 return sc.countError("settings_big_or_dups", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001728 }
1729 if err := f.ForeachSetting(sc.processSetting); err != nil {
1730 return err
1731 }
David Bainbridge788e5202019-10-21 18:49:40 +00001732 // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be
1733 // acknowledged individually, even if multiple are received before the ACK.
William Kurkianea869482019-04-09 15:16:11 -04001734 sc.needToSendSettingsAck = true
1735 sc.scheduleFrameWrite()
1736 return nil
1737}
1738
1739func (sc *serverConn) processSetting(s Setting) error {
1740 sc.serveG.check()
1741 if err := s.Valid(); err != nil {
1742 return err
1743 }
1744 if VerboseLogs {
1745 sc.vlogf("http2: server processing setting %v", s)
1746 }
1747 switch s.ID {
1748 case SettingHeaderTableSize:
William Kurkianea869482019-04-09 15:16:11 -04001749 sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)
1750 case SettingEnablePush:
1751 sc.pushEnabled = s.Val != 0
1752 case SettingMaxConcurrentStreams:
1753 sc.clientMaxStreams = s.Val
1754 case SettingInitialWindowSize:
1755 return sc.processSettingInitialWindowSize(s.Val)
1756 case SettingMaxFrameSize:
1757 sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^31
1758 case SettingMaxHeaderListSize:
1759 sc.peerMaxHeaderListSize = s.Val
1760 default:
1761 // Unknown setting: "An endpoint that receives a SETTINGS
1762 // frame with any unknown or unsupported identifier MUST
1763 // ignore that setting."
1764 if VerboseLogs {
1765 sc.vlogf("http2: server ignoring unknown setting %v", s)
1766 }
1767 }
1768 return nil
1769}
1770
1771func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
1772 sc.serveG.check()
1773 // Note: val already validated to be within range by
1774 // processSetting's Valid call.
1775
1776 // "A SETTINGS frame can alter the initial flow control window
1777 // size for all current streams. When the value of
1778 // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST
1779 // adjust the size of all stream flow control windows that it
1780 // maintains by the difference between the new value and the
1781 // old value."
1782 old := sc.initialStreamSendWindowSize
1783 sc.initialStreamSendWindowSize = int32(val)
1784 growth := int32(val) - old // may be negative
1785 for _, st := range sc.streams {
1786 if !st.flow.add(growth) {
1787 // 6.9.2 Initial Flow Control Window Size
1788 // "An endpoint MUST treat a change to
1789 // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow
1790 // control window to exceed the maximum size as a
1791 // connection error (Section 5.4.1) of type
1792 // FLOW_CONTROL_ERROR."
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301793 return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl))
William Kurkianea869482019-04-09 15:16:11 -04001794 }
1795 }
1796 return nil
1797}
1798
1799func (sc *serverConn) processData(f *DataFrame) error {
1800 sc.serveG.check()
khenaidoo106c61a2021-08-11 18:05:46 -04001801 id := f.Header().StreamID
William Kurkianea869482019-04-09 15:16:11 -04001802
khenaidoo106c61a2021-08-11 18:05:46 -04001803 data := f.Data()
William Kurkianea869482019-04-09 15:16:11 -04001804 state, st := sc.state(id)
1805 if id == 0 || state == stateIdle {
khenaidoo106c61a2021-08-11 18:05:46 -04001806 // Section 6.1: "DATA frames MUST be associated with a
1807 // stream. If a DATA frame is received whose stream
1808 // identifier field is 0x0, the recipient MUST respond
1809 // with a connection error (Section 5.4.1) of type
1810 // PROTOCOL_ERROR."
1811 //
William Kurkianea869482019-04-09 15:16:11 -04001812 // Section 5.1: "Receiving any frame other than HEADERS
1813 // or PRIORITY on a stream in this state MUST be
1814 // treated as a connection error (Section 5.4.1) of
1815 // type PROTOCOL_ERROR."
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301816 return sc.countError("data_on_idle", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001817 }
khenaidoo106c61a2021-08-11 18:05:46 -04001818
1819 // "If a DATA frame is received whose stream is not in "open"
1820 // or "half closed (local)" state, the recipient MUST respond
1821 // with a stream error (Section 5.4.2) of type STREAM_CLOSED."
William Kurkianea869482019-04-09 15:16:11 -04001822 if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued {
1823 // This includes sending a RST_STREAM if the stream is
1824 // in stateHalfClosedLocal (which currently means that
1825 // the http.Handler returned, so it's done reading &
1826 // done writing). Try to stop the client from sending
1827 // more DATA.
1828
1829 // But still enforce their connection-level flow control,
1830 // and return any flow control bytes since we're not going
1831 // to consume them.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301832 if !sc.inflow.take(f.Length) {
1833 return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
William Kurkianea869482019-04-09 15:16:11 -04001834 }
William Kurkianea869482019-04-09 15:16:11 -04001835 sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
1836
1837 if st != nil && st.resetQueued {
1838 // Already have a stream error in flight. Don't send another.
1839 return nil
1840 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301841 return sc.countError("closed", streamError(id, ErrCodeStreamClosed))
William Kurkianea869482019-04-09 15:16:11 -04001842 }
1843 if st.body == nil {
1844 panic("internal error: should have a body in this state")
1845 }
1846
1847 // Sender sending more than they'd declared?
1848 if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301849 if !sc.inflow.take(f.Length) {
1850 return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
1851 }
1852 sc.sendWindowUpdate(nil, int(f.Length)) // conn-level
1853
William Kurkianea869482019-04-09 15:16:11 -04001854 st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))
1855 // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
1856 // value of a content-length header field does not equal the sum of the
1857 // DATA frame payload lengths that form the body.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301858 return sc.countError("send_too_much", streamError(id, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001859 }
1860 if f.Length > 0 {
1861 // Check whether the client has flow control quota.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301862 if !takeInflows(&sc.inflow, &st.inflow, f.Length) {
1863 return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
William Kurkianea869482019-04-09 15:16:11 -04001864 }
William Kurkianea869482019-04-09 15:16:11 -04001865
1866 if len(data) > 0 {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301867 st.bodyBytes += int64(len(data))
William Kurkianea869482019-04-09 15:16:11 -04001868 wrote, err := st.body.Write(data)
1869 if err != nil {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301870 // The handler has closed the request body.
1871 // Return the connection-level flow control for the discarded data,
1872 // but not the stream-level flow control.
khenaidoo106c61a2021-08-11 18:05:46 -04001873 sc.sendWindowUpdate(nil, int(f.Length)-wrote)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301874 return nil
William Kurkianea869482019-04-09 15:16:11 -04001875 }
1876 if wrote != len(data) {
1877 panic("internal error: bad Writer")
1878 }
William Kurkianea869482019-04-09 15:16:11 -04001879 }
1880
1881 // Return any padded flow control now, since we won't
1882 // refund it later on body reads.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301883 // Call sendWindowUpdate even if there is no padding,
1884 // to return buffered flow control credit if the sent
1885 // window has shrunk.
1886 pad := int32(f.Length) - int32(len(data))
1887 sc.sendWindowUpdate32(nil, pad)
1888 sc.sendWindowUpdate32(st, pad)
William Kurkianea869482019-04-09 15:16:11 -04001889 }
1890 if f.StreamEnded() {
1891 st.endStream()
1892 }
1893 return nil
1894}
1895
1896func (sc *serverConn) processGoAway(f *GoAwayFrame) error {
1897 sc.serveG.check()
1898 if f.ErrCode != ErrCodeNo {
1899 sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f)
1900 } else {
1901 sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)
1902 }
1903 sc.startGracefulShutdownInternal()
1904 // http://tools.ietf.org/html/rfc7540#section-6.8
1905 // We should not create any new streams, which means we should disable push.
1906 sc.pushEnabled = false
1907 return nil
1908}
1909
1910// isPushed reports whether the stream is server-initiated.
1911func (st *stream) isPushed() bool {
1912 return st.id%2 == 0
1913}
1914
1915// endStream closes a Request.Body's pipe. It is called when a DATA
1916// frame says a request body is over (or after trailers).
1917func (st *stream) endStream() {
1918 sc := st.sc
1919 sc.serveG.check()
1920
1921 if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {
1922 st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",
1923 st.declBodyBytes, st.bodyBytes))
1924 } else {
1925 st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest)
1926 st.body.CloseWithError(io.EOF)
1927 }
1928 st.state = stateHalfClosedRemote
1929}
1930
1931// copyTrailersToHandlerRequest is run in the Handler's goroutine in
1932// its Request.Body.Read just before it gets io.EOF.
1933func (st *stream) copyTrailersToHandlerRequest() {
1934 for k, vv := range st.trailer {
1935 if _, ok := st.reqTrailer[k]; ok {
1936 // Only copy it over it was pre-declared.
1937 st.reqTrailer[k] = vv
1938 }
1939 }
1940}
1941
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301942// onReadTimeout is run on its own goroutine (from time.AfterFunc)
1943// when the stream's ReadTimeout has fired.
1944func (st *stream) onReadTimeout() {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05301945 if st.body != nil {
1946 // Wrap the ErrDeadlineExceeded to avoid callers depending on us
1947 // returning the bare error.
1948 st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))
1949 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301950}
1951
William Kurkianea869482019-04-09 15:16:11 -04001952// onWriteTimeout is run on its own goroutine (from time.AfterFunc)
1953// when the stream's WriteTimeout has fired.
1954func (st *stream) onWriteTimeout() {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301955 st.sc.writeFrameFromHandler(FrameWriteRequest{write: StreamError{
1956 StreamID: st.id,
1957 Code: ErrCodeInternal,
1958 Cause: os.ErrDeadlineExceeded,
1959 }})
William Kurkianea869482019-04-09 15:16:11 -04001960}
1961
1962func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
1963 sc.serveG.check()
1964 id := f.StreamID
William Kurkianea869482019-04-09 15:16:11 -04001965 // http://tools.ietf.org/html/rfc7540#section-5.1.1
1966 // Streams initiated by a client MUST use odd-numbered stream
1967 // identifiers. [...] An endpoint that receives an unexpected
1968 // stream identifier MUST respond with a connection error
1969 // (Section 5.4.1) of type PROTOCOL_ERROR.
1970 if id%2 != 1 {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301971 return sc.countError("headers_even", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04001972 }
1973 // A HEADERS frame can be used to create a new stream or
1974 // send a trailer for an open one. If we already have a stream
1975 // open, let it process its own HEADERS frame (trailers at this
1976 // point, if it's valid).
1977 if st := sc.streams[f.StreamID]; st != nil {
1978 if st.resetQueued {
1979 // We're sending RST_STREAM to close the stream, so don't bother
1980 // processing this frame.
1981 return nil
1982 }
1983 // RFC 7540, sec 5.1: If an endpoint receives additional frames, other than
1984 // WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in
1985 // this state, it MUST respond with a stream error (Section 5.4.2) of
1986 // type STREAM_CLOSED.
1987 if st.state == stateHalfClosedRemote {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301988 return sc.countError("headers_half_closed", streamError(id, ErrCodeStreamClosed))
William Kurkianea869482019-04-09 15:16:11 -04001989 }
1990 return st.processTrailerHeaders(f)
1991 }
1992
1993 // [...] The identifier of a newly established stream MUST be
1994 // numerically greater than all streams that the initiating
1995 // endpoint has opened or reserved. [...] An endpoint that
1996 // receives an unexpected stream identifier MUST respond with
1997 // a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
1998 if id <= sc.maxClientStreamID {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05301999 return sc.countError("stream_went_down", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002000 }
2001 sc.maxClientStreamID = id
2002
2003 if sc.idleTimer != nil {
2004 sc.idleTimer.Stop()
2005 }
2006
2007 // http://tools.ietf.org/html/rfc7540#section-5.1.2
2008 // [...] Endpoints MUST NOT exceed the limit set by their peer. An
2009 // endpoint that receives a HEADERS frame that causes their
2010 // advertised concurrent stream limit to be exceeded MUST treat
2011 // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR
2012 // or REFUSED_STREAM.
2013 if sc.curClientStreams+1 > sc.advMaxStreams {
2014 if sc.unackedSettings == 0 {
2015 // They should know better.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302016 return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002017 }
2018 // Assume it's a network race, where they just haven't
2019 // received our last SETTINGS update. But actually
2020 // this can't happen yet, because we don't yet provide
2021 // a way for users to adjust server parameters at
2022 // runtime.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302023 return sc.countError("over_max_streams_race", streamError(id, ErrCodeRefusedStream))
William Kurkianea869482019-04-09 15:16:11 -04002024 }
2025
2026 initialState := stateOpen
2027 if f.StreamEnded() {
2028 initialState = stateHalfClosedRemote
2029 }
2030 st := sc.newStream(id, 0, initialState)
2031
2032 if f.HasPriority() {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302033 if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
William Kurkianea869482019-04-09 15:16:11 -04002034 return err
2035 }
2036 sc.writeSched.AdjustStream(st.id, f.Priority)
2037 }
2038
2039 rw, req, err := sc.newWriterAndRequest(st, f)
2040 if err != nil {
2041 return err
2042 }
2043 st.reqTrailer = req.Trailer
2044 if st.reqTrailer != nil {
2045 st.trailer = make(http.Header)
2046 }
2047 st.body = req.Body.(*requestBody).pipe // may be nil
2048 st.declBodyBytes = req.ContentLength
2049
2050 handler := sc.handler.ServeHTTP
2051 if f.Truncated {
2052 // Their header list was too long. Send a 431 error.
2053 handler = handleHeaderListTooLong
2054 } else if err := checkValidHTTP2RequestHeaders(req.Header); err != nil {
2055 handler = new400Handler(err)
2056 }
2057
2058 // The net/http package sets the read deadline from the
2059 // http.Server.ReadTimeout during the TLS handshake, but then
2060 // passes the connection off to us with the deadline already
2061 // set. Disarm it here after the request headers are read,
2062 // similar to how the http1 server works. Here it's
2063 // technically more like the http1 Server's ReadHeaderTimeout
2064 // (in Go 1.8), though. That's a more sane option anyway.
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302065 if sc.hs.ReadTimeout > 0 {
William Kurkianea869482019-04-09 15:16:11 -04002066 sc.conn.SetReadDeadline(time.Time{})
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302067 st.readDeadline = sc.srv.afterFunc(sc.hs.ReadTimeout, st.onReadTimeout)
William Kurkianea869482019-04-09 15:16:11 -04002068 }
2069
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302070 return sc.scheduleHandler(id, rw, req, handler)
William Kurkianea869482019-04-09 15:16:11 -04002071}
2072
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302073func (sc *serverConn) upgradeRequest(req *http.Request) {
2074 sc.serveG.check()
2075 id := uint32(1)
2076 sc.maxClientStreamID = id
2077 st := sc.newStream(id, 0, stateHalfClosedRemote)
2078 st.reqTrailer = req.Trailer
2079 if st.reqTrailer != nil {
2080 st.trailer = make(http.Header)
2081 }
2082 rw := sc.newResponseWriter(st, req)
2083
2084 // Disable any read deadline set by the net/http package
2085 // prior to the upgrade.
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302086 if sc.hs.ReadTimeout > 0 {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302087 sc.conn.SetReadDeadline(time.Time{})
2088 }
2089
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302090 // This is the first request on the connection,
2091 // so start the handler directly rather than going
2092 // through scheduleHandler.
2093 sc.curHandlers++
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302094 go sc.runHandler(rw, req, sc.handler.ServeHTTP)
2095}
2096
William Kurkianea869482019-04-09 15:16:11 -04002097func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
2098 sc := st.sc
2099 sc.serveG.check()
2100 if st.gotTrailerHeader {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302101 return sc.countError("dup_trailers", ConnectionError(ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002102 }
2103 st.gotTrailerHeader = true
2104 if !f.StreamEnded() {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302105 return sc.countError("trailers_not_ended", streamError(st.id, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002106 }
2107
2108 if len(f.PseudoFields()) > 0 {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302109 return sc.countError("trailers_pseudo", streamError(st.id, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002110 }
2111 if st.trailer != nil {
2112 for _, hf := range f.RegularFields() {
2113 key := sc.canonicalHeader(hf.Name)
2114 if !httpguts.ValidTrailerHeader(key) {
2115 // TODO: send more details to the peer somehow. But http2 has
2116 // no way to send debug data at a stream level. Discuss with
2117 // HTTP folk.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302118 return sc.countError("trailers_bogus", streamError(st.id, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002119 }
2120 st.trailer[key] = append(st.trailer[key], hf.Value)
2121 }
2122 }
2123 st.endStream()
2124 return nil
2125}
2126
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302127func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
William Kurkianea869482019-04-09 15:16:11 -04002128 if streamID == p.StreamDep {
2129 // Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
2130 // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
2131 // Section 5.3.3 says that a stream can depend on one of its dependencies,
2132 // so it's only self-dependencies that are forbidden.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302133 return sc.countError("priority", streamError(streamID, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002134 }
2135 return nil
2136}
2137
2138func (sc *serverConn) processPriority(f *PriorityFrame) error {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302139 if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
William Kurkianea869482019-04-09 15:16:11 -04002140 return err
2141 }
2142 sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
2143 return nil
2144}
2145
2146func (sc *serverConn) newStream(id, pusherID uint32, state streamState) *stream {
2147 sc.serveG.check()
2148 if id == 0 {
2149 panic("internal error: cannot create stream with id 0")
2150 }
2151
2152 ctx, cancelCtx := context.WithCancel(sc.baseCtx)
2153 st := &stream{
2154 sc: sc,
2155 id: id,
2156 state: state,
2157 ctx: ctx,
2158 cancelCtx: cancelCtx,
2159 }
2160 st.cw.Init()
2161 st.flow.conn = &sc.flow // link to conn-level counter
2162 st.flow.add(sc.initialStreamSendWindowSize)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302163 st.inflow.init(sc.srv.initialStreamRecvWindowSize())
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302164 if sc.hs.WriteTimeout > 0 {
2165 st.writeDeadline = sc.srv.afterFunc(sc.hs.WriteTimeout, st.onWriteTimeout)
William Kurkianea869482019-04-09 15:16:11 -04002166 }
2167
2168 sc.streams[id] = st
2169 sc.writeSched.OpenStream(st.id, OpenStreamOptions{PusherID: pusherID})
2170 if st.isPushed() {
2171 sc.curPushedStreams++
2172 } else {
2173 sc.curClientStreams++
2174 }
2175 if sc.curOpenStreams() == 1 {
2176 sc.setConnState(http.StateActive)
2177 }
2178
2179 return st
2180}
2181
2182func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*responseWriter, *http.Request, error) {
2183 sc.serveG.check()
2184
2185 rp := requestParam{
2186 method: f.PseudoValue("method"),
2187 scheme: f.PseudoValue("scheme"),
2188 authority: f.PseudoValue("authority"),
2189 path: f.PseudoValue("path"),
2190 }
2191
2192 isConnect := rp.method == "CONNECT"
2193 if isConnect {
2194 if rp.path != "" || rp.scheme != "" || rp.authority == "" {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302195 return nil, nil, sc.countError("bad_connect", streamError(f.StreamID, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002196 }
2197 } else if rp.method == "" || rp.path == "" || (rp.scheme != "https" && rp.scheme != "http") {
2198 // See 8.1.2.6 Malformed Requests and Responses:
2199 //
2200 // Malformed requests or responses that are detected
2201 // MUST be treated as a stream error (Section 5.4.2)
2202 // of type PROTOCOL_ERROR."
2203 //
2204 // 8.1.2.3 Request Pseudo-Header Fields
2205 // "All HTTP/2 requests MUST include exactly one valid
2206 // value for the :method, :scheme, and :path
2207 // pseudo-header fields"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302208 return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002209 }
2210
2211 rp.header = make(http.Header)
2212 for _, hf := range f.RegularFields() {
2213 rp.header.Add(sc.canonicalHeader(hf.Name), hf.Value)
2214 }
2215 if rp.authority == "" {
2216 rp.authority = rp.header.Get("Host")
2217 }
2218
2219 rw, req, err := sc.newWriterAndRequestNoBody(st, rp)
2220 if err != nil {
2221 return nil, nil, err
2222 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302223 bodyOpen := !f.StreamEnded()
William Kurkianea869482019-04-09 15:16:11 -04002224 if bodyOpen {
2225 if vv, ok := rp.header["Content-Length"]; ok {
khenaidoo106c61a2021-08-11 18:05:46 -04002226 if cl, err := strconv.ParseUint(vv[0], 10, 63); err == nil {
2227 req.ContentLength = int64(cl)
2228 } else {
2229 req.ContentLength = 0
2230 }
William Kurkianea869482019-04-09 15:16:11 -04002231 } else {
2232 req.ContentLength = -1
2233 }
2234 req.Body.(*requestBody).pipe = &pipe{
2235 b: &dataBuffer{expected: req.ContentLength},
2236 }
2237 }
2238 return rw, req, nil
2239}
2240
2241type requestParam struct {
2242 method string
2243 scheme, authority, path string
2244 header http.Header
2245}
2246
2247func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*responseWriter, *http.Request, error) {
2248 sc.serveG.check()
2249
2250 var tlsState *tls.ConnectionState // nil if not scheme https
2251 if rp.scheme == "https" {
2252 tlsState = sc.tlsState
2253 }
2254
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302255 needsContinue := httpguts.HeaderValuesContainsToken(rp.header["Expect"], "100-continue")
William Kurkianea869482019-04-09 15:16:11 -04002256 if needsContinue {
2257 rp.header.Del("Expect")
2258 }
2259 // Merge Cookie headers into one "; "-delimited value.
2260 if cookies := rp.header["Cookie"]; len(cookies) > 1 {
2261 rp.header.Set("Cookie", strings.Join(cookies, "; "))
2262 }
2263
2264 // Setup Trailers
2265 var trailer http.Header
2266 for _, v := range rp.header["Trailer"] {
2267 for _, key := range strings.Split(v, ",") {
khenaidoo106c61a2021-08-11 18:05:46 -04002268 key = http.CanonicalHeaderKey(textproto.TrimString(key))
William Kurkianea869482019-04-09 15:16:11 -04002269 switch key {
2270 case "Transfer-Encoding", "Trailer", "Content-Length":
2271 // Bogus. (copy of http1 rules)
2272 // Ignore.
2273 default:
2274 if trailer == nil {
2275 trailer = make(http.Header)
2276 }
2277 trailer[key] = nil
2278 }
2279 }
2280 }
2281 delete(rp.header, "Trailer")
2282
2283 var url_ *url.URL
2284 var requestURI string
2285 if rp.method == "CONNECT" {
2286 url_ = &url.URL{Host: rp.authority}
2287 requestURI = rp.authority // mimic HTTP/1 server behavior
2288 } else {
2289 var err error
2290 url_, err = url.ParseRequestURI(rp.path)
2291 if err != nil {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302292 return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol))
William Kurkianea869482019-04-09 15:16:11 -04002293 }
2294 requestURI = rp.path
2295 }
2296
2297 body := &requestBody{
2298 conn: sc,
2299 stream: st,
2300 needsContinue: needsContinue,
2301 }
2302 req := &http.Request{
2303 Method: rp.method,
2304 URL: url_,
2305 RemoteAddr: sc.remoteAddrStr,
2306 Header: rp.header,
2307 RequestURI: requestURI,
2308 Proto: "HTTP/2.0",
2309 ProtoMajor: 2,
2310 ProtoMinor: 0,
2311 TLS: tlsState,
2312 Host: rp.authority,
2313 Body: body,
2314 Trailer: trailer,
2315 }
2316 req = req.WithContext(st.ctx)
2317
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302318 rw := sc.newResponseWriter(st, req)
2319 return rw, req, nil
2320}
2321
2322func (sc *serverConn) newResponseWriter(st *stream, req *http.Request) *responseWriter {
William Kurkianea869482019-04-09 15:16:11 -04002323 rws := responseWriterStatePool.Get().(*responseWriterState)
2324 bwSave := rws.bw
2325 *rws = responseWriterState{} // zero all the fields
2326 rws.conn = sc
2327 rws.bw = bwSave
2328 rws.bw.Reset(chunkWriter{rws})
2329 rws.stream = st
2330 rws.req = req
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302331 return &responseWriter{rws: rws}
William Kurkianea869482019-04-09 15:16:11 -04002332}
2333
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302334type unstartedHandler struct {
2335 streamID uint32
2336 rw *responseWriter
2337 req *http.Request
2338 handler func(http.ResponseWriter, *http.Request)
2339}
2340
2341// scheduleHandler starts a handler goroutine,
2342// or schedules one to start as soon as an existing handler finishes.
2343func (sc *serverConn) scheduleHandler(streamID uint32, rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) error {
2344 sc.serveG.check()
2345 maxHandlers := sc.advMaxStreams
2346 if sc.curHandlers < maxHandlers {
2347 sc.curHandlers++
2348 go sc.runHandler(rw, req, handler)
2349 return nil
2350 }
2351 if len(sc.unstartedHandlers) > int(4*sc.advMaxStreams) {
2352 return sc.countError("too_many_early_resets", ConnectionError(ErrCodeEnhanceYourCalm))
2353 }
2354 sc.unstartedHandlers = append(sc.unstartedHandlers, unstartedHandler{
2355 streamID: streamID,
2356 rw: rw,
2357 req: req,
2358 handler: handler,
2359 })
2360 return nil
2361}
2362
2363func (sc *serverConn) handlerDone() {
2364 sc.serveG.check()
2365 sc.curHandlers--
2366 i := 0
2367 maxHandlers := sc.advMaxStreams
2368 for ; i < len(sc.unstartedHandlers); i++ {
2369 u := sc.unstartedHandlers[i]
2370 if sc.streams[u.streamID] == nil {
2371 // This stream was reset before its goroutine had a chance to start.
2372 continue
2373 }
2374 if sc.curHandlers >= maxHandlers {
2375 break
2376 }
2377 sc.curHandlers++
2378 go sc.runHandler(u.rw, u.req, u.handler)
2379 sc.unstartedHandlers[i] = unstartedHandler{} // don't retain references
2380 }
2381 sc.unstartedHandlers = sc.unstartedHandlers[i:]
2382 if len(sc.unstartedHandlers) == 0 {
2383 sc.unstartedHandlers = nil
2384 }
2385}
2386
William Kurkianea869482019-04-09 15:16:11 -04002387// Run on its own goroutine.
2388func (sc *serverConn) runHandler(rw *responseWriter, req *http.Request, handler func(http.ResponseWriter, *http.Request)) {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302389 sc.srv.markNewGoroutine()
2390 defer sc.sendServeMsg(handlerDoneMsg)
William Kurkianea869482019-04-09 15:16:11 -04002391 didPanic := true
2392 defer func() {
2393 rw.rws.stream.cancelCtx()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302394 if req.MultipartForm != nil {
2395 req.MultipartForm.RemoveAll()
2396 }
William Kurkianea869482019-04-09 15:16:11 -04002397 if didPanic {
2398 e := recover()
2399 sc.writeFrameFromHandler(FrameWriteRequest{
2400 write: handlerPanicRST{rw.rws.stream.id},
2401 stream: rw.rws.stream,
2402 })
2403 // Same as net/http:
2404 if e != nil && e != http.ErrAbortHandler {
2405 const size = 64 << 10
2406 buf := make([]byte, size)
2407 buf = buf[:runtime.Stack(buf, false)]
2408 sc.logf("http2: panic serving %v: %v\n%s", sc.conn.RemoteAddr(), e, buf)
2409 }
2410 return
2411 }
2412 rw.handlerDone()
2413 }()
2414 handler(rw, req)
2415 didPanic = false
2416}
2417
2418func handleHeaderListTooLong(w http.ResponseWriter, r *http.Request) {
2419 // 10.5.1 Limits on Header Block Size:
2420 // .. "A server that receives a larger header block than it is
2421 // willing to handle can send an HTTP 431 (Request Header Fields Too
2422 // Large) status code"
2423 const statusRequestHeaderFieldsTooLarge = 431 // only in Go 1.6+
2424 w.WriteHeader(statusRequestHeaderFieldsTooLarge)
2425 io.WriteString(w, "<h1>HTTP Error 431</h1><p>Request Header Field(s) Too Large</p>")
2426}
2427
2428// called from handler goroutines.
2429// h may be nil.
2430func (sc *serverConn) writeHeaders(st *stream, headerData *writeResHeaders) error {
2431 sc.serveG.checkNotOn() // NOT on
2432 var errc chan error
2433 if headerData.h != nil {
2434 // If there's a header map (which we don't own), so we have to block on
2435 // waiting for this frame to be written, so an http.Flush mid-handler
2436 // writes out the correct value of keys, before a handler later potentially
2437 // mutates it.
2438 errc = errChanPool.Get().(chan error)
2439 }
2440 if err := sc.writeFrameFromHandler(FrameWriteRequest{
2441 write: headerData,
2442 stream: st,
2443 done: errc,
2444 }); err != nil {
2445 return err
2446 }
2447 if errc != nil {
2448 select {
2449 case err := <-errc:
2450 errChanPool.Put(errc)
2451 return err
2452 case <-sc.doneServing:
2453 return errClientDisconnected
2454 case <-st.cw:
2455 return errStreamClosed
2456 }
2457 }
2458 return nil
2459}
2460
2461// called from handler goroutines.
2462func (sc *serverConn) write100ContinueHeaders(st *stream) {
2463 sc.writeFrameFromHandler(FrameWriteRequest{
2464 write: write100ContinueHeadersFrame{st.id},
2465 stream: st,
2466 })
2467}
2468
2469// A bodyReadMsg tells the server loop that the http.Handler read n
2470// bytes of the DATA from the client on the given stream.
2471type bodyReadMsg struct {
2472 st *stream
2473 n int
2474}
2475
2476// called from handler goroutines.
2477// Notes that the handler for the given stream ID read n bytes of its body
2478// and schedules flow control tokens to be sent.
2479func (sc *serverConn) noteBodyReadFromHandler(st *stream, n int, err error) {
2480 sc.serveG.checkNotOn() // NOT on
2481 if n > 0 {
2482 select {
2483 case sc.bodyReadCh <- bodyReadMsg{st, n}:
2484 case <-sc.doneServing:
2485 }
2486 }
2487}
2488
2489func (sc *serverConn) noteBodyRead(st *stream, n int) {
2490 sc.serveG.check()
2491 sc.sendWindowUpdate(nil, n) // conn-level
2492 if st.state != stateHalfClosedRemote && st.state != stateClosed {
2493 // Don't send this WINDOW_UPDATE if the stream is closed
2494 // remotely.
2495 sc.sendWindowUpdate(st, n)
2496 }
2497}
2498
2499// st may be nil for conn-level
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302500func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
2501 sc.sendWindowUpdate(st, int(n))
William Kurkianea869482019-04-09 15:16:11 -04002502}
2503
2504// st may be nil for conn-level
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302505func (sc *serverConn) sendWindowUpdate(st *stream, n int) {
William Kurkianea869482019-04-09 15:16:11 -04002506 sc.serveG.check()
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302507 var streamID uint32
2508 var send int32
2509 if st == nil {
2510 send = sc.inflow.add(n)
2511 } else {
2512 streamID = st.id
2513 send = st.inflow.add(n)
2514 }
2515 if send == 0 {
William Kurkianea869482019-04-09 15:16:11 -04002516 return
2517 }
William Kurkianea869482019-04-09 15:16:11 -04002518 sc.writeFrame(FrameWriteRequest{
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302519 write: writeWindowUpdate{streamID: streamID, n: uint32(send)},
William Kurkianea869482019-04-09 15:16:11 -04002520 stream: st,
2521 })
William Kurkianea869482019-04-09 15:16:11 -04002522}
2523
2524// requestBody is the Handler's Request.Body type.
2525// Read and Close may be called concurrently.
2526type requestBody struct {
khenaidoo106c61a2021-08-11 18:05:46 -04002527 _ incomparable
William Kurkianea869482019-04-09 15:16:11 -04002528 stream *stream
2529 conn *serverConn
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302530 closeOnce sync.Once // for use by Close only
2531 sawEOF bool // for use by Read only
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302532 pipe *pipe // non-nil if we have an HTTP entity message body
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302533 needsContinue bool // need to send a 100-continue
William Kurkianea869482019-04-09 15:16:11 -04002534}
2535
2536func (b *requestBody) Close() error {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302537 b.closeOnce.Do(func() {
2538 if b.pipe != nil {
2539 b.pipe.BreakWithError(errClosedBody)
2540 }
2541 })
William Kurkianea869482019-04-09 15:16:11 -04002542 return nil
2543}
2544
2545func (b *requestBody) Read(p []byte) (n int, err error) {
2546 if b.needsContinue {
2547 b.needsContinue = false
2548 b.conn.write100ContinueHeaders(b.stream)
2549 }
2550 if b.pipe == nil || b.sawEOF {
2551 return 0, io.EOF
2552 }
2553 n, err = b.pipe.Read(p)
2554 if err == io.EOF {
2555 b.sawEOF = true
2556 }
2557 if b.conn == nil && inTests {
2558 return
2559 }
2560 b.conn.noteBodyReadFromHandler(b.stream, n, err)
2561 return
2562}
2563
2564// responseWriter is the http.ResponseWriter implementation. It's
2565// intentionally small (1 pointer wide) to minimize garbage. The
2566// responseWriterState pointer inside is zeroed at the end of a
2567// request (in handlerDone) and calls on the responseWriter thereafter
2568// simply crash (caller's mistake), but the much larger responseWriterState
2569// and buffers are reused between multiple requests.
2570type responseWriter struct {
2571 rws *responseWriterState
2572}
2573
2574// Optional http.ResponseWriter interfaces implemented.
2575var (
2576 _ http.CloseNotifier = (*responseWriter)(nil)
2577 _ http.Flusher = (*responseWriter)(nil)
2578 _ stringWriter = (*responseWriter)(nil)
2579)
2580
2581type responseWriterState struct {
2582 // immutable within a request:
2583 stream *stream
2584 req *http.Request
William Kurkianea869482019-04-09 15:16:11 -04002585 conn *serverConn
2586
2587 // TODO: adjust buffer writing sizes based on server config, frame size updates from peer, etc
2588 bw *bufio.Writer // writing to a chunkWriter{this *responseWriterState}
2589
2590 // mutated by http.Handler goroutine:
2591 handlerHeader http.Header // nil until called
2592 snapHeader http.Header // snapshot of handlerHeader at WriteHeader time
2593 trailers []string // set in writeChunk
2594 status int // status code passed to WriteHeader
2595 wroteHeader bool // WriteHeader called (explicitly or implicitly). Not necessarily sent to user yet.
2596 sentHeader bool // have we sent the header frame?
2597 handlerDone bool // handler has finished
William Kurkianea869482019-04-09 15:16:11 -04002598
2599 sentContentLen int64 // non-zero if handler set a Content-Length header
2600 wroteBytes int64
2601
2602 closeNotifierMu sync.Mutex // guards closeNotifierCh
2603 closeNotifierCh chan bool // nil until first used
2604}
2605
2606type chunkWriter struct{ rws *responseWriterState }
2607
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302608func (cw chunkWriter) Write(p []byte) (n int, err error) {
2609 n, err = cw.rws.writeChunk(p)
2610 if err == errStreamClosed {
2611 // If writing failed because the stream has been closed,
2612 // return the reason it was closed.
2613 err = cw.rws.stream.closeErr
2614 }
2615 return n, err
2616}
William Kurkianea869482019-04-09 15:16:11 -04002617
Abhilash S.L3b494632019-07-16 15:51:09 +05302618func (rws *responseWriterState) hasTrailers() bool { return len(rws.trailers) > 0 }
2619
2620func (rws *responseWriterState) hasNonemptyTrailers() bool {
2621 for _, trailer := range rws.trailers {
2622 if _, ok := rws.handlerHeader[trailer]; ok {
2623 return true
2624 }
2625 }
2626 return false
2627}
William Kurkianea869482019-04-09 15:16:11 -04002628
2629// declareTrailer is called for each Trailer header when the
2630// response header is written. It notes that a header will need to be
2631// written in the trailers at the end of the response.
2632func (rws *responseWriterState) declareTrailer(k string) {
2633 k = http.CanonicalHeaderKey(k)
2634 if !httpguts.ValidTrailerHeader(k) {
2635 // Forbidden by RFC 7230, section 4.1.2.
2636 rws.conn.logf("ignoring invalid trailer %q", k)
2637 return
2638 }
2639 if !strSliceContains(rws.trailers, k) {
2640 rws.trailers = append(rws.trailers, k)
2641 }
2642}
2643
2644// writeChunk writes chunks from the bufio.Writer. But because
2645// bufio.Writer may bypass its chunking, sometimes p may be
2646// arbitrarily large.
2647//
2648// writeChunk is also responsible (on the first chunk) for sending the
2649// HEADER response.
2650func (rws *responseWriterState) writeChunk(p []byte) (n int, err error) {
2651 if !rws.wroteHeader {
2652 rws.writeHeader(200)
2653 }
2654
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302655 if rws.handlerDone {
2656 rws.promoteUndeclaredTrailers()
2657 }
2658
William Kurkianea869482019-04-09 15:16:11 -04002659 isHeadResp := rws.req.Method == "HEAD"
2660 if !rws.sentHeader {
2661 rws.sentHeader = true
2662 var ctype, clen string
2663 if clen = rws.snapHeader.Get("Content-Length"); clen != "" {
2664 rws.snapHeader.Del("Content-Length")
khenaidoo106c61a2021-08-11 18:05:46 -04002665 if cl, err := strconv.ParseUint(clen, 10, 63); err == nil {
2666 rws.sentContentLen = int64(cl)
William Kurkianea869482019-04-09 15:16:11 -04002667 } else {
2668 clen = ""
2669 }
2670 }
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302671 _, hasContentLength := rws.snapHeader["Content-Length"]
2672 if !hasContentLength && clen == "" && rws.handlerDone && bodyAllowedForStatus(rws.status) && (len(p) > 0 || !isHeadResp) {
William Kurkianea869482019-04-09 15:16:11 -04002673 clen = strconv.Itoa(len(p))
2674 }
2675 _, hasContentType := rws.snapHeader["Content-Type"]
khenaidoo106c61a2021-08-11 18:05:46 -04002676 // If the Content-Encoding is non-blank, we shouldn't
2677 // sniff the body. See Issue golang.org/issue/31753.
2678 ce := rws.snapHeader.Get("Content-Encoding")
2679 hasCE := len(ce) > 0
2680 if !hasCE && !hasContentType && bodyAllowedForStatus(rws.status) && len(p) > 0 {
William Kurkianea869482019-04-09 15:16:11 -04002681 ctype = http.DetectContentType(p)
2682 }
2683 var date string
2684 if _, ok := rws.snapHeader["Date"]; !ok {
2685 // TODO(bradfitz): be faster here, like net/http? measure.
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302686 date = rws.conn.srv.now().UTC().Format(http.TimeFormat)
William Kurkianea869482019-04-09 15:16:11 -04002687 }
2688
2689 for _, v := range rws.snapHeader["Trailer"] {
2690 foreachHeaderElement(v, rws.declareTrailer)
2691 }
2692
2693 // "Connection" headers aren't allowed in HTTP/2 (RFC 7540, 8.1.2.2),
2694 // but respect "Connection" == "close" to mean sending a GOAWAY and tearing
2695 // down the TCP connection when idle, like we do for HTTP/1.
2696 // TODO: remove more Connection-specific header fields here, in addition
2697 // to "Connection".
2698 if _, ok := rws.snapHeader["Connection"]; ok {
2699 v := rws.snapHeader.Get("Connection")
2700 delete(rws.snapHeader, "Connection")
2701 if v == "close" {
2702 rws.conn.startGracefulShutdown()
2703 }
2704 }
2705
2706 endStream := (rws.handlerDone && !rws.hasTrailers() && len(p) == 0) || isHeadResp
2707 err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
2708 streamID: rws.stream.id,
2709 httpResCode: rws.status,
2710 h: rws.snapHeader,
2711 endStream: endStream,
2712 contentType: ctype,
2713 contentLength: clen,
2714 date: date,
2715 })
2716 if err != nil {
William Kurkianea869482019-04-09 15:16:11 -04002717 return 0, err
2718 }
2719 if endStream {
2720 return 0, nil
2721 }
2722 }
2723 if isHeadResp {
2724 return len(p), nil
2725 }
2726 if len(p) == 0 && !rws.handlerDone {
2727 return 0, nil
2728 }
2729
Abhilash S.L3b494632019-07-16 15:51:09 +05302730 // only send trailers if they have actually been defined by the
2731 // server handler.
2732 hasNonemptyTrailers := rws.hasNonemptyTrailers()
2733 endStream := rws.handlerDone && !hasNonemptyTrailers
William Kurkianea869482019-04-09 15:16:11 -04002734 if len(p) > 0 || endStream {
2735 // only send a 0 byte DATA frame if we're ending the stream.
2736 if err := rws.conn.writeDataFromHandler(rws.stream, p, endStream); err != nil {
William Kurkianea869482019-04-09 15:16:11 -04002737 return 0, err
2738 }
2739 }
2740
Abhilash S.L3b494632019-07-16 15:51:09 +05302741 if rws.handlerDone && hasNonemptyTrailers {
William Kurkianea869482019-04-09 15:16:11 -04002742 err = rws.conn.writeHeaders(rws.stream, &writeResHeaders{
2743 streamID: rws.stream.id,
2744 h: rws.handlerHeader,
2745 trailers: rws.trailers,
2746 endStream: true,
2747 })
William Kurkianea869482019-04-09 15:16:11 -04002748 return len(p), err
2749 }
2750 return len(p), nil
2751}
2752
2753// TrailerPrefix is a magic prefix for ResponseWriter.Header map keys
2754// that, if present, signals that the map entry is actually for
2755// the response trailers, and not the response headers. The prefix
2756// is stripped after the ServeHTTP call finishes and the values are
2757// sent in the trailers.
2758//
2759// This mechanism is intended only for trailers that are not known
2760// prior to the headers being written. If the set of trailers is fixed
2761// or known before the header is written, the normal Go trailers mechanism
2762// is preferred:
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302763//
2764// https://golang.org/pkg/net/http/#ResponseWriter
2765// https://golang.org/pkg/net/http/#example_ResponseWriter_trailers
William Kurkianea869482019-04-09 15:16:11 -04002766const TrailerPrefix = "Trailer:"
2767
2768// promoteUndeclaredTrailers permits http.Handlers to set trailers
2769// after the header has already been flushed. Because the Go
2770// ResponseWriter interface has no way to set Trailers (only the
2771// Header), and because we didn't want to expand the ResponseWriter
2772// interface, and because nobody used trailers, and because RFC 7230
2773// says you SHOULD (but not must) predeclare any trailers in the
2774// header, the official ResponseWriter rules said trailers in Go must
2775// be predeclared, and then we reuse the same ResponseWriter.Header()
2776// map to mean both Headers and Trailers. When it's time to write the
2777// Trailers, we pick out the fields of Headers that were declared as
2778// trailers. That worked for a while, until we found the first major
2779// user of Trailers in the wild: gRPC (using them only over http2),
2780// and gRPC libraries permit setting trailers mid-stream without
David Bainbridge788e5202019-10-21 18:49:40 +00002781// predeclaring them. So: change of plans. We still permit the old
William Kurkianea869482019-04-09 15:16:11 -04002782// way, but we also permit this hack: if a Header() key begins with
2783// "Trailer:", the suffix of that key is a Trailer. Because ':' is an
2784// invalid token byte anyway, there is no ambiguity. (And it's already
2785// filtered out) It's mildly hacky, but not terrible.
2786//
2787// This method runs after the Handler is done and promotes any Header
2788// fields to be trailers.
2789func (rws *responseWriterState) promoteUndeclaredTrailers() {
2790 for k, vv := range rws.handlerHeader {
2791 if !strings.HasPrefix(k, TrailerPrefix) {
2792 continue
2793 }
2794 trailerKey := strings.TrimPrefix(k, TrailerPrefix)
2795 rws.declareTrailer(trailerKey)
2796 rws.handlerHeader[http.CanonicalHeaderKey(trailerKey)] = vv
2797 }
2798
2799 if len(rws.trailers) > 1 {
2800 sorter := sorterPool.Get().(*sorter)
2801 sorter.SortStrings(rws.trailers)
2802 sorterPool.Put(sorter)
2803 }
2804}
2805
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302806func (w *responseWriter) SetReadDeadline(deadline time.Time) error {
2807 st := w.rws.stream
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302808 if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302809 // If we're setting a deadline in the past, reset the stream immediately
2810 // so writes after SetWriteDeadline returns will fail.
2811 st.onReadTimeout()
2812 return nil
2813 }
2814 w.rws.conn.sendServeMsg(func(sc *serverConn) {
2815 if st.readDeadline != nil {
2816 if !st.readDeadline.Stop() {
2817 // Deadline already exceeded, or stream has been closed.
2818 return
2819 }
2820 }
2821 if deadline.IsZero() {
2822 st.readDeadline = nil
2823 } else if st.readDeadline == nil {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302824 st.readDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onReadTimeout)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302825 } else {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302826 st.readDeadline.Reset(deadline.Sub(sc.srv.now()))
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302827 }
2828 })
2829 return nil
2830}
2831
2832func (w *responseWriter) SetWriteDeadline(deadline time.Time) error {
2833 st := w.rws.stream
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302834 if !deadline.IsZero() && deadline.Before(w.rws.conn.srv.now()) {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302835 // If we're setting a deadline in the past, reset the stream immediately
2836 // so writes after SetWriteDeadline returns will fail.
2837 st.onWriteTimeout()
2838 return nil
2839 }
2840 w.rws.conn.sendServeMsg(func(sc *serverConn) {
2841 if st.writeDeadline != nil {
2842 if !st.writeDeadline.Stop() {
2843 // Deadline already exceeded, or stream has been closed.
2844 return
2845 }
2846 }
2847 if deadline.IsZero() {
2848 st.writeDeadline = nil
2849 } else if st.writeDeadline == nil {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302850 st.writeDeadline = sc.srv.afterFunc(deadline.Sub(sc.srv.now()), st.onWriteTimeout)
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302851 } else {
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302852 st.writeDeadline.Reset(deadline.Sub(sc.srv.now()))
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302853 }
2854 })
2855 return nil
2856}
2857
William Kurkianea869482019-04-09 15:16:11 -04002858func (w *responseWriter) Flush() {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302859 w.FlushError()
2860}
2861
2862func (w *responseWriter) FlushError() error {
William Kurkianea869482019-04-09 15:16:11 -04002863 rws := w.rws
2864 if rws == nil {
2865 panic("Header called after Handler finished")
2866 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302867 var err error
William Kurkianea869482019-04-09 15:16:11 -04002868 if rws.bw.Buffered() > 0 {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302869 err = rws.bw.Flush()
William Kurkianea869482019-04-09 15:16:11 -04002870 } else {
2871 // The bufio.Writer won't call chunkWriter.Write
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302872 // (writeChunk with zero bytes), so we have to do it
William Kurkianea869482019-04-09 15:16:11 -04002873 // ourselves to force the HTTP response header and/or
2874 // final DATA frame (with END_STREAM) to be sent.
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302875 _, err = chunkWriter{rws}.Write(nil)
2876 if err == nil {
2877 select {
2878 case <-rws.stream.cw:
2879 err = rws.stream.closeErr
2880 default:
2881 }
2882 }
William Kurkianea869482019-04-09 15:16:11 -04002883 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302884 return err
William Kurkianea869482019-04-09 15:16:11 -04002885}
2886
2887func (w *responseWriter) CloseNotify() <-chan bool {
2888 rws := w.rws
2889 if rws == nil {
2890 panic("CloseNotify called after Handler finished")
2891 }
2892 rws.closeNotifierMu.Lock()
2893 ch := rws.closeNotifierCh
2894 if ch == nil {
2895 ch = make(chan bool, 1)
2896 rws.closeNotifierCh = ch
2897 cw := rws.stream.cw
2898 go func() {
2899 cw.Wait() // wait for close
2900 ch <- true
2901 }()
2902 }
2903 rws.closeNotifierMu.Unlock()
2904 return ch
2905}
2906
2907func (w *responseWriter) Header() http.Header {
2908 rws := w.rws
2909 if rws == nil {
2910 panic("Header called after Handler finished")
2911 }
2912 if rws.handlerHeader == nil {
2913 rws.handlerHeader = make(http.Header)
2914 }
2915 return rws.handlerHeader
2916}
2917
2918// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
2919func checkWriteHeaderCode(code int) {
2920 // Issue 22880: require valid WriteHeader status codes.
2921 // For now we only enforce that it's three digits.
2922 // In the future we might block things over 599 (600 and above aren't defined
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302923 // at http://httpwg.org/specs/rfc7231.html#status.codes).
William Kurkianea869482019-04-09 15:16:11 -04002924 // But for now any three digits.
2925 //
2926 // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
2927 // no equivalent bogus thing we can realistically send in HTTP/2,
2928 // so we'll consistently panic instead and help people find their bugs
2929 // early. (We can't return an error from WriteHeader even if we wanted to.)
2930 if code < 100 || code > 999 {
2931 panic(fmt.Sprintf("invalid WriteHeader code %v", code))
2932 }
2933}
2934
2935func (w *responseWriter) WriteHeader(code int) {
2936 rws := w.rws
2937 if rws == nil {
2938 panic("WriteHeader called after Handler finished")
2939 }
2940 rws.writeHeader(code)
2941}
2942
2943func (rws *responseWriterState) writeHeader(code int) {
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302944 if rws.wroteHeader {
2945 return
2946 }
2947
2948 checkWriteHeaderCode(code)
2949
2950 // Handle informational headers
2951 if code >= 100 && code <= 199 {
2952 // Per RFC 8297 we must not clear the current header map
2953 h := rws.handlerHeader
2954
2955 _, cl := h["Content-Length"]
2956 _, te := h["Transfer-Encoding"]
2957 if cl || te {
2958 h = h.Clone()
2959 h.Del("Content-Length")
2960 h.Del("Transfer-Encoding")
William Kurkianea869482019-04-09 15:16:11 -04002961 }
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302962
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302963 rws.conn.writeHeaders(rws.stream, &writeResHeaders{
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302964 streamID: rws.stream.id,
2965 httpResCode: code,
2966 h: h,
2967 endStream: rws.handlerDone && !rws.hasTrailers(),
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05302968 })
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05302969
2970 return
2971 }
2972
2973 rws.wroteHeader = true
2974 rws.status = code
2975 if len(rws.handlerHeader) > 0 {
2976 rws.snapHeader = cloneHeader(rws.handlerHeader)
William Kurkianea869482019-04-09 15:16:11 -04002977 }
2978}
2979
2980func cloneHeader(h http.Header) http.Header {
2981 h2 := make(http.Header, len(h))
2982 for k, vv := range h {
2983 vv2 := make([]string, len(vv))
2984 copy(vv2, vv)
2985 h2[k] = vv2
2986 }
2987 return h2
2988}
2989
2990// The Life Of A Write is like this:
2991//
2992// * Handler calls w.Write or w.WriteString ->
2993// * -> rws.bw (*bufio.Writer) ->
2994// * (Handler might call Flush)
2995// * -> chunkWriter{rws}
2996// * -> responseWriterState.writeChunk(p []byte)
2997// * -> responseWriterState.writeChunk (most of the magic; see comment there)
2998func (w *responseWriter) Write(p []byte) (n int, err error) {
2999 return w.write(len(p), p, "")
3000}
3001
3002func (w *responseWriter) WriteString(s string) (n int, err error) {
3003 return w.write(len(s), nil, s)
3004}
3005
3006// either dataB or dataS is non-zero.
3007func (w *responseWriter) write(lenData int, dataB []byte, dataS string) (n int, err error) {
3008 rws := w.rws
3009 if rws == nil {
3010 panic("Write called after Handler finished")
3011 }
3012 if !rws.wroteHeader {
3013 w.WriteHeader(200)
3014 }
3015 if !bodyAllowedForStatus(rws.status) {
3016 return 0, http.ErrBodyNotAllowed
3017 }
3018 rws.wroteBytes += int64(len(dataB)) + int64(len(dataS)) // only one can be set
3019 if rws.sentContentLen != 0 && rws.wroteBytes > rws.sentContentLen {
3020 // TODO: send a RST_STREAM
3021 return 0, errors.New("http2: handler wrote more than declared Content-Length")
3022 }
3023
3024 if dataB != nil {
3025 return rws.bw.Write(dataB)
3026 } else {
3027 return rws.bw.WriteString(dataS)
3028 }
3029}
3030
3031func (w *responseWriter) handlerDone() {
3032 rws := w.rws
William Kurkianea869482019-04-09 15:16:11 -04003033 rws.handlerDone = true
3034 w.Flush()
3035 w.rws = nil
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05303036 responseWriterStatePool.Put(rws)
William Kurkianea869482019-04-09 15:16:11 -04003037}
3038
3039// Push errors.
3040var (
3041 ErrRecursivePush = errors.New("http2: recursive push not allowed")
3042 ErrPushLimitReached = errors.New("http2: push would exceed peer's SETTINGS_MAX_CONCURRENT_STREAMS")
3043)
3044
3045var _ http.Pusher = (*responseWriter)(nil)
3046
3047func (w *responseWriter) Push(target string, opts *http.PushOptions) error {
3048 st := w.rws.stream
3049 sc := st.sc
3050 sc.serveG.checkNotOn()
3051
3052 // No recursive pushes: "PUSH_PROMISE frames MUST only be sent on a peer-initiated stream."
3053 // http://tools.ietf.org/html/rfc7540#section-6.6
3054 if st.isPushed() {
3055 return ErrRecursivePush
3056 }
3057
3058 if opts == nil {
3059 opts = new(http.PushOptions)
3060 }
3061
3062 // Default options.
3063 if opts.Method == "" {
3064 opts.Method = "GET"
3065 }
3066 if opts.Header == nil {
3067 opts.Header = http.Header{}
3068 }
3069 wantScheme := "http"
3070 if w.rws.req.TLS != nil {
3071 wantScheme = "https"
3072 }
3073
3074 // Validate the request.
3075 u, err := url.Parse(target)
3076 if err != nil {
3077 return err
3078 }
3079 if u.Scheme == "" {
3080 if !strings.HasPrefix(target, "/") {
3081 return fmt.Errorf("target must be an absolute URL or an absolute path: %q", target)
3082 }
3083 u.Scheme = wantScheme
3084 u.Host = w.rws.req.Host
3085 } else {
3086 if u.Scheme != wantScheme {
3087 return fmt.Errorf("cannot push URL with scheme %q from request with scheme %q", u.Scheme, wantScheme)
3088 }
3089 if u.Host == "" {
3090 return errors.New("URL must have a host")
3091 }
3092 }
3093 for k := range opts.Header {
3094 if strings.HasPrefix(k, ":") {
3095 return fmt.Errorf("promised request headers cannot include pseudo header %q", k)
3096 }
3097 // These headers are meaningful only if the request has a body,
3098 // but PUSH_PROMISE requests cannot have a body.
3099 // http://tools.ietf.org/html/rfc7540#section-8.2
3100 // Also disallow Host, since the promised URL must be absolute.
khenaidoo106c61a2021-08-11 18:05:46 -04003101 if asciiEqualFold(k, "content-length") ||
3102 asciiEqualFold(k, "content-encoding") ||
3103 asciiEqualFold(k, "trailer") ||
3104 asciiEqualFold(k, "te") ||
3105 asciiEqualFold(k, "expect") ||
3106 asciiEqualFold(k, "host") {
William Kurkianea869482019-04-09 15:16:11 -04003107 return fmt.Errorf("promised request headers cannot include %q", k)
3108 }
3109 }
3110 if err := checkValidHTTP2RequestHeaders(opts.Header); err != nil {
3111 return err
3112 }
3113
3114 // The RFC effectively limits promised requests to GET and HEAD:
3115 // "Promised requests MUST be cacheable [GET, HEAD, or POST], and MUST be safe [GET or HEAD]"
3116 // http://tools.ietf.org/html/rfc7540#section-8.2
3117 if opts.Method != "GET" && opts.Method != "HEAD" {
3118 return fmt.Errorf("method %q must be GET or HEAD", opts.Method)
3119 }
3120
3121 msg := &startPushRequest{
3122 parent: st,
3123 method: opts.Method,
3124 url: u,
3125 header: cloneHeader(opts.Header),
3126 done: errChanPool.Get().(chan error),
3127 }
3128
3129 select {
3130 case <-sc.doneServing:
3131 return errClientDisconnected
3132 case <-st.cw:
3133 return errStreamClosed
3134 case sc.serveMsgCh <- msg:
3135 }
3136
3137 select {
3138 case <-sc.doneServing:
3139 return errClientDisconnected
3140 case <-st.cw:
3141 return errStreamClosed
3142 case err := <-msg.done:
3143 errChanPool.Put(msg.done)
3144 return err
3145 }
3146}
3147
3148type startPushRequest struct {
3149 parent *stream
3150 method string
3151 url *url.URL
3152 header http.Header
3153 done chan error
3154}
3155
3156func (sc *serverConn) startPush(msg *startPushRequest) {
3157 sc.serveG.check()
3158
3159 // http://tools.ietf.org/html/rfc7540#section-6.6.
3160 // PUSH_PROMISE frames MUST only be sent on a peer-initiated stream that
3161 // is in either the "open" or "half-closed (remote)" state.
3162 if msg.parent.state != stateOpen && msg.parent.state != stateHalfClosedRemote {
David Bainbridge788e5202019-10-21 18:49:40 +00003163 // responseWriter.Push checks that the stream is peer-initiated.
William Kurkianea869482019-04-09 15:16:11 -04003164 msg.done <- errStreamClosed
3165 return
3166 }
3167
3168 // http://tools.ietf.org/html/rfc7540#section-6.6.
3169 if !sc.pushEnabled {
3170 msg.done <- http.ErrNotSupported
3171 return
3172 }
3173
3174 // PUSH_PROMISE frames must be sent in increasing order by stream ID, so
3175 // we allocate an ID for the promised stream lazily, when the PUSH_PROMISE
3176 // is written. Once the ID is allocated, we start the request handler.
3177 allocatePromisedID := func() (uint32, error) {
3178 sc.serveG.check()
3179
3180 // Check this again, just in case. Technically, we might have received
3181 // an updated SETTINGS by the time we got around to writing this frame.
3182 if !sc.pushEnabled {
3183 return 0, http.ErrNotSupported
3184 }
3185 // http://tools.ietf.org/html/rfc7540#section-6.5.2.
3186 if sc.curPushedStreams+1 > sc.clientMaxStreams {
3187 return 0, ErrPushLimitReached
3188 }
3189
3190 // http://tools.ietf.org/html/rfc7540#section-5.1.1.
3191 // Streams initiated by the server MUST use even-numbered identifiers.
3192 // A server that is unable to establish a new stream identifier can send a GOAWAY
3193 // frame so that the client is forced to open a new connection for new streams.
3194 if sc.maxPushPromiseID+2 >= 1<<31 {
3195 sc.startGracefulShutdownInternal()
3196 return 0, ErrPushLimitReached
3197 }
3198 sc.maxPushPromiseID += 2
3199 promisedID := sc.maxPushPromiseID
3200
3201 // http://tools.ietf.org/html/rfc7540#section-8.2.
3202 // Strictly speaking, the new stream should start in "reserved (local)", then
3203 // transition to "half closed (remote)" after sending the initial HEADERS, but
3204 // we start in "half closed (remote)" for simplicity.
3205 // See further comments at the definition of stateHalfClosedRemote.
3206 promised := sc.newStream(promisedID, msg.parent.id, stateHalfClosedRemote)
3207 rw, req, err := sc.newWriterAndRequestNoBody(promised, requestParam{
3208 method: msg.method,
3209 scheme: msg.url.Scheme,
3210 authority: msg.url.Host,
3211 path: msg.url.RequestURI(),
3212 header: cloneHeader(msg.header), // clone since handler runs concurrently with writing the PUSH_PROMISE
3213 })
3214 if err != nil {
3215 // Should not happen, since we've already validated msg.url.
3216 panic(fmt.Sprintf("newWriterAndRequestNoBody(%+v): %v", msg.url, err))
3217 }
3218
Akash Reddy Kankanalad9ec4822025-06-10 22:59:53 +05303219 sc.curHandlers++
William Kurkianea869482019-04-09 15:16:11 -04003220 go sc.runHandler(rw, req, sc.handler.ServeHTTP)
3221 return promisedID, nil
3222 }
3223
3224 sc.writeFrame(FrameWriteRequest{
3225 write: &writePushPromise{
3226 streamID: msg.parent.id,
3227 method: msg.method,
3228 url: msg.url,
3229 h: msg.header,
3230 allocatePromisedID: allocatePromisedID,
3231 },
3232 stream: msg.parent,
3233 done: msg.done,
3234 })
3235}
3236
3237// foreachHeaderElement splits v according to the "#rule" construction
3238// in RFC 7230 section 7 and calls fn for each non-empty element.
3239func foreachHeaderElement(v string, fn func(string)) {
3240 v = textproto.TrimString(v)
3241 if v == "" {
3242 return
3243 }
3244 if !strings.Contains(v, ",") {
3245 fn(v)
3246 return
3247 }
3248 for _, f := range strings.Split(v, ",") {
3249 if f = textproto.TrimString(f); f != "" {
3250 fn(f)
3251 }
3252 }
3253}
3254
3255// From http://httpwg.org/specs/rfc7540.html#rfc.section.8.1.2.2
3256var connHeaders = []string{
3257 "Connection",
3258 "Keep-Alive",
3259 "Proxy-Connection",
3260 "Transfer-Encoding",
3261 "Upgrade",
3262}
3263
3264// checkValidHTTP2RequestHeaders checks whether h is a valid HTTP/2 request,
3265// per RFC 7540 Section 8.1.2.2.
3266// The returned error is reported to users.
3267func checkValidHTTP2RequestHeaders(h http.Header) error {
3268 for _, k := range connHeaders {
3269 if _, ok := h[k]; ok {
3270 return fmt.Errorf("request header %q is not valid in HTTP/2", k)
3271 }
3272 }
3273 te := h["Te"]
3274 if len(te) > 0 && (len(te) > 1 || (te[0] != "trailers" && te[0] != "")) {
3275 return errors.New(`request header "TE" may only be "trailers" in HTTP/2`)
3276 }
3277 return nil
3278}
3279
3280func new400Handler(err error) http.HandlerFunc {
3281 return func(w http.ResponseWriter, r *http.Request) {
3282 http.Error(w, err.Error(), http.StatusBadRequest)
3283 }
3284}
3285
3286// h1ServerKeepAlivesDisabled reports whether hs has its keep-alives
3287// disabled. See comments on h1ServerShutdownChan above for why
3288// the code is written this way.
3289func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
3290 var x interface{} = hs
3291 type I interface {
3292 doKeepAlives() bool
3293 }
3294 if hs, ok := x.(I); ok {
3295 return !hs.doKeepAlives()
3296 }
3297 return false
3298}
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +05303299
3300func (sc *serverConn) countError(name string, err error) error {
3301 if sc == nil || sc.srv == nil {
3302 return err
3303 }
3304 f := sc.srv.CountError
3305 if f == nil {
3306 return err
3307 }
3308 var typ string
3309 var code ErrCode
3310 switch e := err.(type) {
3311 case ConnectionError:
3312 typ = "conn"
3313 code = ErrCode(e)
3314 case StreamError:
3315 typ = "stream"
3316 code = ErrCode(e.Code)
3317 default:
3318 return err
3319 }
3320 codeStr := errCodeName[code]
3321 if codeStr == "" {
3322 codeStr = strconv.Itoa(int(code))
3323 }
3324 f(fmt.Sprintf("%s_%s_%s", typ, codeStr, name))
3325 return err
3326}