1// Copyright 2014 The Go Authors. All rights reserved.2// Use of this source code is governed by a BSD-style3// license that can be found in the LICENSE file.45// TODO: turn off the serve goroutine when idle, so6// an idle conn only has the readFrames goroutine active. (which could7// also be optimized probably to pin less memory in crypto/tls). This8// would involve tracking when the serve goroutine is active (atomic9// int32 read/CAS probably?) and starting it up when frames arrive,10// and shutting it down when all handlers exit. the occasional PING11// packets could use time.AfterFunc to call sc.wakeStartServeLoop()12// (which is a no-op if already running) and then queue the PING write13// as normal. The serve loop would then exit in most cases (if no14// Handlers running) and not be woken up again until the PING packet15// returns.1617// TODO (maybe): add a mechanism for Handlers to going into18// half-closed-local mode (rw.(io.Closer) test?) but not exit their19// handler, and continue to be able to read from the20// Request.Body. This would be a somewhat semantic change from HTTP/121// (or at least what we expose in net/http), so I'd probably want to22// add it there too. For now, this package says that returning from23// the Handler ServeHTTP function means you're both done reading and24// done writing, without a way to stop just one or the other.2526package http22728import (29 "bufio"30 "bytes"31 "context"32 "crypto/rand"33 "crypto/tls"34 "errors"35 "fmt"36 "io"37 "log"38 "math"39 "net"40 "net/http/internal"41 "net/http/internal/httpcommon"42 "net/textproto"43 "net/url"44 "os"45 "reflect"46 "runtime"47 "slices"48 "strconv"49 "strings"50 "sync"51 "time"5253 "golang.org/x/net/http/httpguts"54 "golang.org/x/net/http2/hpack"55)5657const (58 prefaceTimeout = 10 * time.Second59 firstSettingsTimeout = 2 * time.Second // should be in-flight with preface anyway60 handlerChunkWriteSize = 4 << 1061 defaultMaxStreams = 250 // TODO: make this 100 as the GFE seems to?6263 // maxQueuedControlFrames is the maximum number of control frames like64 // SETTINGS, PING and RST_STREAM that will be queued for writing before65 // the connection is closed to prevent memory exhaustion attacks.66 maxQueuedControlFrames = 1000067)6869var (70 errClientDisconnected = errors.New("client disconnected")71 errClosedBody = errors.New("body closed by handler")72 errHandlerComplete = errors.New("http2: request body closed due to handler exiting")73 errStreamClosed = errors.New("http2: stream closed")74)7576var responseWriterStatePool = sync.Pool{77 New: func() any {78 return &responseWriterState{}79 },80}8182// handlerWriterPool is a pool of the bufio.Writers used by83// responseWriterState (rws.bw) to buffer handler response writes.84//85// The buffers are acquired from the pool lazily on the first buffered86// write and, notably, are returned to it by Flush when empty, so that a87// handler that's parked mid-response for a long time (e.g. streaming a88// long poll) doesn't pin a buffer per stream.89var handlerWriterPool = sync.Pool{90 New: func() any {91 return bufio.NewWriterSize(nil, handlerChunkWriteSize)92 },93}9495// Test hooks.96var (97 testHookOnConn func()98 testHookOnPanicMu *sync.Mutex // nil except in tests99 testHookOnPanic func(sc *serverConn, panicVal any) (rePanic bool)100)101102// Server is an HTTP/2 server.103type Server struct {104 mu sync.Mutex105 activeConns map[*serverConn]struct{}106107 // Pool of error channels. This is per-Server rather than global108 // because channels can't be reused across synctest bubbles.109 errChanPool sync.Pool110}111112func (s *Server) registerConn(sc *serverConn) {113 if s == nil {114 return // if the Server was used without calling ConfigureServer115 }116 s.mu.Lock()117 s.activeConns[sc] = struct{}{}118 s.mu.Unlock()119}120121func (s *Server) unregisterConn(sc *serverConn) {122 if s == nil {123 return // if the Server was used without calling ConfigureServer124 }125 s.mu.Lock()126 delete(s.activeConns, sc)127 s.mu.Unlock()128}129130func (s *Server) startGracefulShutdown() {131 if s == nil {132 return // if the Server was used without calling ConfigureServer133 }134 s.mu.Lock()135 for sc := range s.activeConns {136 sc.startGracefulShutdown()137 }138 s.mu.Unlock()139}140141// Global error channel pool used for uninitialized Servers.142// We use a per-Server pool when possible to avoid using channels across synctest bubbles.143var errChanPool = sync.Pool{144 New: func() any { return make(chan error, 1) },145}146147func (s *Server) getErrChan() chan error {148 if s == nil {149 return errChanPool.Get().(chan error) // Server used without calling ConfigureServer150 }151 return s.errChanPool.Get().(chan error)152}153154func (s *Server) putErrChan(ch chan error) {155 if s == nil {156 errChanPool.Put(ch) // Server used without calling ConfigureServer157 return158 }159 s.errChanPool.Put(ch)160}161162func (s *Server) Configure(conf ServerConfig, tcfg *tls.Config) error {163 s.activeConns = make(map[*serverConn]struct{})164 s.errChanPool = sync.Pool{New: func() any { return make(chan error, 1) }}165166 if tcfg.CipherSuites != nil && tcfg.MinVersion < tls.VersionTLS13 {167 // If they already provided a TLS 1.0–1.2 CipherSuite list, return an168 // error if it is missing ECDHE_RSA_WITH_AES_128_GCM_SHA256 or169 // ECDHE_ECDSA_WITH_AES_128_GCM_SHA256.170 haveRequired := false171 for _, cs := range tcfg.CipherSuites {172 switch cs {173 case tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,174 // Alternative MTI cipher to not discourage ECDSA-only servers.175 // See http://golang.org/cl/30721 for further information.176 tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256:177 haveRequired = true178 }179 }180 if !haveRequired {181 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)")182 }183 }184185 // Note: not setting MinVersion to tls.VersionTLS12,186 // as we don't want to interfere with HTTP/1.1 traffic187 // on the user's server. We enforce TLS 1.2 later once188 // we accept a connection. Ideally this should be done189 // during next-proto selection, but using TLS <1.2 with190 // HTTP/2 is still the client's bug.191192 return nil193}194195func (s *Server) GracefulShutdown() {196 s.startGracefulShutdown()197}198199// ServeConnOpts are options for the Server.ServeConn method.200type ServeConnOpts struct {201 // Context is the base context to use.202 // If nil, context.Background is used.203 Context context.Context204205 // BaseConfig optionally sets the base configuration206 // for values. If nil, defaults are used.207 BaseConfig ServerConfig208209 // Handler specifies which handler to use for processing210 // requests. If nil, BaseConfig.Handler is used. If BaseConfig211 // or BaseConfig.Handler is nil, http.DefaultServeMux is used.212 Handler Handler213214 // Settings is the decoded contents of the HTTP2-Settings header215 // in an h2c upgrade request.216 Settings []byte217218 UpgradeRequest *ServerRequest219220 // SawClientPreface is set if the HTTP/2 connection preface221 // has already been read from the connection.222 SawClientPreface bool223}224225func (o *ServeConnOpts) context() context.Context {226 if o != nil && o.Context != nil {227 return o.Context228 }229 return context.Background()230}231232// ServeConn serves HTTP/2 requests on the provided connection and233// blocks until the connection is no longer readable.234//235// ServeConn starts speaking HTTP/2 assuming that c has not had any236// reads or writes. It writes its initial settings frame and expects237// to be able to read the preface and settings frame from the238// client. If c has a ConnectionState method like a *tls.Conn, the239// ConnectionState is used to verify the TLS ciphersuite and to set240// the Request.TLS field in Handlers.241//242// ServeConn does not support h2c by itself. Any h2c support must be243// implemented in terms of providing a suitably-behaving net.Conn.244//245// The opts parameter is optional. If nil, default values are used.246func (s *Server) ServeConn(c net.Conn, opts *ServeConnOpts) {247 if opts == nil {248 opts = &ServeConnOpts{}249 }250251 var newf func(*serverConn)252 if inTests {253 // Fetch NewConnContextKey if set, leave newf as nil otherwise.254 newf, _ = opts.Context.Value(NewConnContextKey).(func(*serverConn))255 }256257 s.serveConn(c, opts, newf)258}259260type contextKey string261262var (263 NewConnContextKey = new("NewConnContextKey")264 ConnectionStateContextKey = new("ConnectionStateContextKey")265)266267func (s *Server) serveConn(c net.Conn, opts *ServeConnOpts, newf func(*serverConn)) {268 baseCtx, cancel := serverConnBaseContext(c, opts)269 defer cancel()270271 conf := configFromServer(opts.BaseConfig)272 sc := &serverConn{273 srv: s,274 hs: opts.BaseConfig,275 conn: c,276 baseCtx: baseCtx,277 remoteAddrStr: c.RemoteAddr().String(),278 bw: newBufferedWriter(c, conf.WriteByteTimeout),279 handler: opts.Handler,280 streams: make(map[uint32]*stream),281 readFrameCh: make(chan readFrameResult),282 wantWriteFrameCh: make(chan FrameWriteRequest, 8),283 serveMsgCh: make(chan any, 8),284 wroteFrameCh: make(chan frameWriteResult, 1), // buffered; one send in writeFrameAsync285 bodyReadCh: make(chan bodyReadMsg), // buffering doesn't matter either way286 doneServing: make(chan struct{}),287 clientMaxStreams: math.MaxUint32, // Section 6.5.2: "Initially, there is no limit to this value"288 advMaxStreams: uint32(conf.MaxConcurrentStreams),289 initialStreamSendWindowSize: initialWindowSize,290 initialStreamRecvWindowSize: int32(conf.MaxReceiveBufferPerStream),291 maxFrameSize: initialMaxFrameSize,292 pingTimeout: conf.PingTimeout,293 countErrorFunc: conf.CountError,294 serveG: newGoroutineLock(),295 pushEnabled: true,296 sawClientPreface: opts.SawClientPreface,297 }298 if newf != nil {299 newf(sc)300 }301302 s.registerConn(sc)303 defer s.unregisterConn(sc)304305 switch {306 case sc.hs.DisableClientPriority():307 sc.writeSched = newRoundRobinWriteScheduler()308 default:309 sc.writeSched = newPriorityWriteSchedulerRFC9218()310 }311312 // These start at the RFC-specified defaults. If there is a higher313 // configured value for inflow, that will be updated when we send a314 // WINDOW_UPDATE shortly after sending SETTINGS.315 sc.flow.add(initialWindowSize)316 sc.inflow.init(initialWindowSize)317 sc.hpackEncoder = hpack.NewEncoder(&sc.headerWriteBuf)318 sc.hpackEncoder.SetMaxDynamicTableSizeLimit(uint32(conf.MaxEncoderHeaderTableSize))319320 fr := NewFramer(sc.bw, c)321 if conf.CountError != nil {322 fr.countError = conf.CountError323 }324 fr.ReadMetaHeaders = hpack.NewDecoder(uint32(conf.MaxDecoderHeaderTableSize), nil)325 fr.MaxHeaderListSize = sc.maxHeaderListSize()326 fr.MaxHeaderValueCount = sc.hs.MaxHeaderValueCount()327 fr.SetMaxReadFrameSize(uint32(conf.MaxReadFrameSize))328 sc.framer = fr329330 if tc, ok := c.(connectionStater); ok {331 sc.tlsState = new(tls.ConnectionState)332 *sc.tlsState = tc.ConnectionState()333334 // Optionally override the ConnectionState in tests.335 if inTests {336 f, ok := opts.Context.Value(ConnectionStateContextKey).(func() tls.ConnectionState)337 if ok {338 *sc.tlsState = f()339 }340 }341342 // 9.2 Use of TLS Features343 // An implementation of HTTP/2 over TLS MUST use TLS344 // 1.2 or higher with the restrictions on feature set345 // and cipher suite described in this section. Due to346 // implementation limitations, it might not be347 // possible to fail TLS negotiation. An endpoint MUST348 // immediately terminate an HTTP/2 connection that349 // does not meet the TLS requirements described in350 // this section with a connection error (Section351 // 5.4.1) of type INADEQUATE_SECURITY.352 if sc.tlsState.Version < tls.VersionTLS12 {353 sc.rejectConn(ErrCodeInadequateSecurity, "TLS version too low")354 return355 }356357 if sc.tlsState.ServerName == "" {358 // Client must use SNI, but we don't enforce that anymore,359 // since it was causing problems when connecting to bare IP360 // addresses during development.361 //362 // TODO: optionally enforce? Or enforce at the time we receive363 // a new request, and verify the ServerName matches the :authority?364 // But that precludes proxy situations, perhaps.365 //366 // So for now, do nothing here again.367 }368369 if !conf.PermitProhibitedCipherSuites && isBadCipher(sc.tlsState.CipherSuite) {370 // "Endpoints MAY choose to generate a connection error371 // (Section 5.4.1) of type INADEQUATE_SECURITY if one of372 // the prohibited cipher suites are negotiated."373 //374 // We choose that. In my opinion, the spec is weak375 // here. It also says both parties must support at least376 // TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 so there's no377 // excuses here. If we really must, we could allow an378 // "AllowInsecureWeakCiphers" option on the server later.379 // Let's see how it plays out first.380 sc.rejectConn(ErrCodeInadequateSecurity, fmt.Sprintf("Prohibited TLS 1.2 Cipher Suite: %x", sc.tlsState.CipherSuite))381 return382 }383 }384385 if opts.Settings != nil {386 fr := &SettingsFrame{387 FrameHeader: FrameHeader{valid: true},388 p: opts.Settings,389 }390 if err := fr.ForeachSetting(sc.processSetting); err != nil {391 sc.rejectConn(ErrCodeProtocol, "invalid settings")392 return393 }394 opts.Settings = nil395 }396397 if opts.UpgradeRequest != nil {398 sc.upgradeRequest(opts.UpgradeRequest)399 opts.UpgradeRequest = nil400 }401402 sc.serve(conf)403}404405func serverConnBaseContext(c net.Conn, opts *ServeConnOpts) (ctx context.Context, cancel func()) {406 return context.WithCancel(opts.context())407}408409func (sc *serverConn) rejectConn(err ErrCode, debug string) {410 sc.vlogf("http2: server rejecting conn: %v, %s", err, debug)411 // ignoring errors. hanging up anyway.412 sc.framer.WriteGoAway(0, err, []byte(debug))413 sc.bw.Flush()414 sc.conn.Close()415}416417type serverConn struct {418 // Immutable:419 srv *Server420 hs ServerConfig421 conn net.Conn422 bw *bufferedWriter // writing to conn423 handler Handler424 baseCtx context.Context425 framer *Framer426 doneServing chan struct{} // closed when serverConn.serve ends427 readFrameCh chan readFrameResult // written by serverConn.readFrames428 wantWriteFrameCh chan FrameWriteRequest // from handlers -> serve429 wroteFrameCh chan frameWriteResult // from writeFrameAsync -> serve, tickles more frame writes430 bodyReadCh chan bodyReadMsg // from handlers -> serve431 serveMsgCh chan any // misc messages & code to send to / run on the serve loop432 flow outflow // conn-wide (not stream-specific) outbound flow control433 inflow inflow // conn-wide inbound flow control434 tlsState *tls.ConnectionState // shared by all handlers, like net/http435 remoteAddrStr string436 writeSched WriteScheduler437 countErrorFunc func(errType string)438439 // Everything following is owned by the serve loop; use serveG.check():440 serveG goroutineLock // used to verify funcs are on serve()441 pushEnabled bool442 sawClientPreface bool // preface has already been read, used in h2c upgrade443 sawFirstSettings bool // got the initial SETTINGS frame after the preface444 needToSendSettingsAck bool445 unackedSettings int // how many SETTINGS have we sent without ACKs?446 queuedControlFrames int // control frames in the writeSched queue447 clientMaxStreams uint32 // SETTINGS_MAX_CONCURRENT_STREAMS from client (our PUSH_PROMISE limit)448 advMaxStreams uint32 // our SETTINGS_MAX_CONCURRENT_STREAMS advertised the client449 curClientStreams uint32 // number of open streams initiated by the client450 curPushedStreams uint32 // number of open streams initiated by server push451 curHandlers uint32 // number of running handler goroutines452 maxClientStreamID uint32 // max ever seen from client (odd), or 0 if there have been no client requests453 maxPushPromiseID uint32 // ID of the last push promise (even), or 0 if there have been no pushes454 streams map[uint32]*stream455 unstartedHandlers []unstartedHandler456 initialStreamSendWindowSize int32457 initialStreamRecvWindowSize int32458 maxFrameSize int32459 peerMaxHeaderListSize uint32 // zero means unknown (default)460 canonHeader map[string]string // http2-lower-case -> Go-Canonical-Case461 canonHeaderKeysSize int // canonHeader keys size in bytes462 writingFrame bool // started writing a frame (on serve goroutine or separate)463 writingFrameAsync bool // started a frame on its own goroutine but haven't heard back on wroteFrameCh464 needsFrameFlush bool // last frame write wasn't a flush465 inGoAway bool // we've started to or sent GOAWAY466 inFrameScheduleLoop bool // whether we're in the scheduleFrameWrite loop467 needToSendGoAway bool // we need to schedule a GOAWAY frame write468 pingSent bool469 sentPingData [8]byte470 goAwayCode ErrCode471 shutdownTimer *time.Timer // nil until used472 idleTimer *time.Timer // nil if unused473 readIdleTimeout time.Duration474 pingTimeout time.Duration475 readIdleTimer *time.Timer // nil if unused476477 // Owned by the writeFrameAsync goroutine:478 headerWriteBuf bytes.Buffer479 hpackEncoder *hpack.Encoder480481 // Used by startGracefulShutdown.482 shutdownOnce sync.Once483484 // Used for RFC 9218 prioritization.485 hasIntermediary bool // connection is done via an intermediary / proxy486 priorityAware bool // the client has sent priority signal, meaning that it is aware of it.487}488489func (sc *serverConn) writeSchedIgnoresRFC7540() bool {490 switch sc.writeSched.(type) {491 case *priorityWriteSchedulerRFC9218:492 return true493 case *roundRobinWriteScheduler:494 return true495 default:496 return false497 }498}499500const DefaultMaxHeaderBytes = 1 << 20 // keep this in sync with net/http501502func (sc *serverConn) maxHeaderListSize() uint32 {503 n := sc.hs.MaxHeaderBytes()504 if n <= 0 {505 n = DefaultMaxHeaderBytes506 }507 return uint32(adjustHTTP1MaxHeaderSize(int64(n)))508}509510func (sc *serverConn) curOpenStreams() uint32 {511 sc.serveG.check()512 return sc.curClientStreams + sc.curPushedStreams513}514515// stream represents a stream. This is the minimal metadata needed by516// the serve goroutine. Most of the actual stream state is owned by517// the http.Handler's goroutine in the responseWriter. Because the518// responseWriter's responseWriterState is recycled at the end of a519// handler, this struct intentionally has no pointer to the520// *responseWriter{,State} itself, as the Handler ending nils out the521// responseWriter's state field.522type stream struct {523 // immutable:524 sc *serverConn525 id uint32526 body *pipe // non-nil if expecting DATA frames527 cw closeWaiter // closed wait stream transitions to closed state528 ctx context.Context529 cancelCtx func()530531 // owned by serverConn's serve loop:532 bodyBytes int64 // body bytes seen so far533 declBodyBytes int64 // or -1 if undeclared534 flow outflow // limits writing from Handler to client535 inflow inflow // what the client is allowed to POST/etc to us536 state streamState537 resetQueued bool // RST_STREAM queued for write; set by sc.resetStream538 gotTrailerHeader bool // HEADER frame for trailers was seen539 wroteHeaders bool // whether we wrote headers (not status 100)540 readDeadline *time.Timer // nil if unused541 writeDeadline *time.Timer // nil if unused542 closeErr error // set before cw is closed543544 trailer Header // accumulated trailers545 reqTrailer Header // handler's Request.Trailer546}547548func (sc *serverConn) Framer() *Framer { return sc.framer }549func (sc *serverConn) CloseConn() error { return sc.conn.Close() }550func (sc *serverConn) Flush() error { return sc.bw.Flush() }551func (sc *serverConn) HeaderEncoder() (*hpack.Encoder, *bytes.Buffer) {552 return sc.hpackEncoder, &sc.headerWriteBuf553}554555func (sc *serverConn) state(streamID uint32) (streamState, *stream) {556 sc.serveG.check()557 // http://tools.ietf.org/html/rfc7540#section-5.1558 if st, ok := sc.streams[streamID]; ok {559 return st.state, st560 }561 // "The first use of a new stream identifier implicitly closes all562 // streams in the "idle" state that might have been initiated by563 // that peer with a lower-valued stream identifier. For example, if564 // a client sends a HEADERS frame on stream 7 without ever sending a565 // frame on stream 5, then stream 5 transitions to the "closed"566 // state when the first frame for stream 7 is sent or received."567 if streamID%2 == 1 {568 if streamID <= sc.maxClientStreamID {569 return stateClosed, nil570 }571 } else {572 if streamID <= sc.maxPushPromiseID {573 return stateClosed, nil574 }575 }576 return stateIdle, nil577}578579// setConnState calls the net/http ConnState hook for this connection, if configured.580// Note that the net/http package does StateNew and StateClosed for us.581// There is currently no plan for StateHijacked or hijacking HTTP/2 connections.582func (sc *serverConn) setConnState(state ConnState) {583 sc.hs.ConnState(sc.conn, state)584}585586func (sc *serverConn) vlogf(format string, args ...any) {587 if VerboseLogs {588 sc.logf(format, args...)589 }590}591592func (sc *serverConn) logf(format string, args ...any) {593 if lg := sc.hs.ErrorLog(); lg != nil {594 lg.Printf(format, args...)595 } else {596 log.Printf(format, args...)597 }598}599600// errno returns v's underlying uintptr, else 0.601//602// TODO: remove this helper function once http2 can use build603// tags. See comment in isClosedConnError.604func errno(v error) uintptr {605 if rv := reflect.ValueOf(v); rv.Kind() == reflect.Uintptr {606 return uintptr(rv.Uint())607 }608 return 0609}610611// isClosedConnError reports whether err is an error from use of a closed612// network connection.613func isClosedConnError(err error) bool {614 if err == nil {615 return false616 }617618 if errors.Is(err, net.ErrClosed) {619 return true620 }621622 // TODO(bradfitz): x/tools/cmd/bundle doesn't really support623 // build tags, so I can't make an http2_windows.go file with624 // Windows-specific stuff. Fix that and move this, once we625 // have a way to bundle this into std's net/http somehow.626 if runtime.GOOS == "windows" {627 if oe, ok := err.(*net.OpError); ok && oe.Op == "read" {628 if se, ok := oe.Err.(*os.SyscallError); ok && se.Syscall == "wsarecv" {629 const WSAECONNABORTED = 10053630 const WSAECONNRESET = 10054631 if n := errno(se.Err); n == WSAECONNRESET || n == WSAECONNABORTED {632 return true633 }634 }635 }636 }637 return false638}639640func (sc *serverConn) condlogf(err error, format string, args ...any) {641 if err == nil {642 return643 }644 if err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err) || err == errPrefaceTimeout {645 // Boring, expected errors.646 sc.vlogf(format, args...)647 } else {648 sc.logf(format, args...)649 }650}651652// maxCachedCanonicalHeadersKeysSize is an arbitrarily-chosen limit on the size653// of the entries in the canonHeader cache.654// This should be larger than the size of unique, uncommon header keys likely to655// be sent by the peer, while not so high as to permit unreasonable memory usage656// if the peer sends an unbounded number of unique header keys.657const maxCachedCanonicalHeadersKeysSize = 2048658659func (sc *serverConn) canonicalHeader(v string) string {660 sc.serveG.check()661 cv, ok := httpcommon.CachedCanonicalHeader(v)662 if ok {663 return cv664 }665 cv, ok = sc.canonHeader[v]666 if ok {667 return cv668 }669 if sc.canonHeader == nil {670 sc.canonHeader = make(map[string]string)671 }672 cv = textproto.CanonicalMIMEHeaderKey(v)673 size := 100 + len(v)*2 // 100 bytes of map overhead + key + value674 if sc.canonHeaderKeysSize+size <= maxCachedCanonicalHeadersKeysSize {675 sc.canonHeader[v] = cv676 sc.canonHeaderKeysSize += size677 }678 return cv679}680681type readFrameResult struct {682 f Frame // valid until readMore is called683 err error684685 // readMore should be called once the consumer no longer needs or686 // retains f. After readMore, f is invalid and more frames can be687 // read.688 readMore func()689}690691// readFrames is the loop that reads incoming frames.692// It takes care to only read one frame at a time, blocking until the693// consumer is done with the frame.694// It's run on its own goroutine.695func (sc *serverConn) readFrames() {696 gate := make(chan struct{})697 gateDone := func() { gate <- struct{}{} }698 for {699 f, err := sc.framer.ReadFrame()700 select {701 case sc.readFrameCh <- readFrameResult{f, err, gateDone}:702 case <-sc.doneServing:703 return704 }705 select {706 case <-gate:707 case <-sc.doneServing:708 return709 }710 if terminalReadFrameError(err) {711 return712 }713 }714}715716// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.717type frameWriteResult struct {718 _ incomparable719 wr FrameWriteRequest // what was written (or attempted)720 err error // result of the writeFrame call721}722723// writeFrameAsync runs in its own goroutine and writes a single frame724// and then reports when it's done.725// At most one goroutine can be running writeFrameAsync at a time per726// serverConn.727func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest, wd *writeData) {728 var err error729 if wd == nil {730 err = wr.write.writeFrame(sc)731 } else {732 err = sc.framer.endWrite()733 }734 sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}735}736737func (sc *serverConn) closeAllStreamsOnConnClose() {738 sc.serveG.check()739 for _, st := range sc.streams {740 sc.closeStream(st, errClientDisconnected)741 }742}743744func (sc *serverConn) stopShutdownTimer() {745 sc.serveG.check()746 if t := sc.shutdownTimer; t != nil {747 t.Stop()748 }749}750751func (sc *serverConn) notePanic() {752 // Note: this is for serverConn.serve panicking, not http.Handler code.753 if testHookOnPanicMu != nil {754 testHookOnPanicMu.Lock()755 defer testHookOnPanicMu.Unlock()756 }757 if testHookOnPanic != nil {758 if e := recover(); e != nil {759 if testHookOnPanic(sc, e) {760 panic(e)761 }762 }763 }764}765766func (sc *serverConn) serve(conf Config) {767 sc.serveG.check()768 defer sc.notePanic()769 defer sc.conn.Close()770 defer sc.closeAllStreamsOnConnClose()771 defer sc.stopShutdownTimer()772 defer close(sc.doneServing) // unblocks handlers trying to send773774 if VerboseLogs {775 sc.vlogf("http2: server connection from %v on %p", sc.conn.RemoteAddr(), sc.hs)776 }777778 settings := writeSettings{779 {SettingMaxFrameSize, uint32(conf.MaxReadFrameSize)},780 {SettingMaxConcurrentStreams, sc.advMaxStreams},781 {SettingMaxHeaderListSize, sc.maxHeaderListSize()},782 {SettingHeaderTableSize, uint32(conf.MaxDecoderHeaderTableSize)},783 {SettingInitialWindowSize, uint32(sc.initialStreamRecvWindowSize)},784 }785 if !disableExtendedConnectProtocol {786 settings = append(settings, Setting{SettingEnableConnectProtocol, 1})787 }788 if sc.writeSchedIgnoresRFC7540() {789 settings = append(settings, Setting{SettingNoRFC7540Priorities, 1})790 }791 sc.writeFrame(FrameWriteRequest{792 write: settings,793 })794 sc.unackedSettings++795796 // Each connection starts with initialWindowSize inflow tokens.797 // If a higher value is configured, we add more tokens.798 if diff := conf.MaxReceiveBufferPerConnection - initialWindowSize; diff > 0 {799 sc.sendWindowUpdate(nil, int(diff))800 }801802 if err := sc.readPreface(); err != nil {803 sc.condlogf(err, "http2: server: error reading preface from client %v: %v", sc.conn.RemoteAddr(), err)804 return805 }806 // Now that we've got the preface, get us out of the807 // "StateNew" state. We can't go directly to idle, though.808 // Active means we read some data and anticipate a request. We'll809 // do another Active when we get a HEADERS frame.810 sc.setConnState(ConnStateActive)811 sc.setConnState(ConnStateIdle)812813 if idle := sc.hs.IdleTimeout(); idle > 0 {814 sc.idleTimer = time.AfterFunc(idle, sc.onIdleTimer)815 defer sc.idleTimer.Stop()816 }817818 if conf.SendPingTimeout > 0 {819 sc.readIdleTimeout = conf.SendPingTimeout820 sc.readIdleTimer = time.AfterFunc(conf.SendPingTimeout, sc.onReadIdleTimer)821 defer sc.readIdleTimer.Stop()822 }823824 go sc.readFrames() // closed by defer sc.conn.Close above825826 settingsTimer := time.AfterFunc(firstSettingsTimeout, sc.onSettingsTimer)827 defer settingsTimer.Stop()828829 lastFrameTime := time.Now()830 loopNum := 0831 for {832 loopNum++833 select {834 case wr := <-sc.wantWriteFrameCh:835 if se, ok := wr.write.(StreamError); ok {836 sc.resetStream(se)837 break838 }839 sc.writeFrame(wr)840 case res := <-sc.wroteFrameCh:841 sc.wroteFrame(res)842 case res := <-sc.readFrameCh:843 lastFrameTime = time.Now()844 // Process any written frames before reading new frames from the client since a845 // written frame could have triggered a new stream to be started.846 if sc.writingFrameAsync {847 select {848 case wroteRes := <-sc.wroteFrameCh:849 sc.wroteFrame(wroteRes)850 default:851 }852 }853 if !sc.processFrameFromReader(res) {854 return855 }856 res.readMore()857 if settingsTimer != nil {858 settingsTimer.Stop()859 settingsTimer = nil860 }861 case m := <-sc.bodyReadCh:862 sc.noteBodyRead(m.st, m.n)863 case msg := <-sc.serveMsgCh:864 switch v := msg.(type) {865 case func(int):866 v(loopNum) // for testing867 case *serverMessage:868 switch v {869 case settingsTimerMsg:870 sc.logf("timeout waiting for SETTINGS frames from %v", sc.conn.RemoteAddr())871 return872 case idleTimerMsg:873 sc.vlogf("connection is idle")874 sc.goAway(ErrCodeNo)875 case readIdleTimerMsg:876 sc.handlePingTimer(lastFrameTime)877 case shutdownTimerMsg:878 sc.vlogf("GOAWAY close timer fired; closing conn from %v", sc.conn.RemoteAddr())879 return880 case gracefulShutdownMsg:881 sc.startGracefulShutdownInternal()882 case handlerDoneMsg:883 sc.handlerDone()884 default:885 panic("unknown timer")886 }887 case *startPushRequest:888 sc.startPush(v)889 case func(*serverConn):890 v(sc)891 default:892 panic(fmt.Sprintf("unexpected type %T", v))893 }894 }895896 // If the peer is causing us to generate a lot of control frames,897 // but not reading them from us, assume they are trying to make us898 // run out of memory.899 if sc.queuedControlFrames > maxQueuedControlFrames {900 sc.vlogf("http2: too many control frames in send queue, closing connection")901 return902 }903904 // Start the shutdown timer after sending a GOAWAY. When sending GOAWAY905 // with no error code (graceful shutdown), don't start the timer until906 // all open streams have been completed.907 sentGoAway := sc.inGoAway && !sc.needToSendGoAway && !sc.writingFrame908 gracefulShutdownComplete := sc.goAwayCode == ErrCodeNo && sc.curOpenStreams() == 0909 if sentGoAway && sc.shutdownTimer == nil && (sc.goAwayCode != ErrCodeNo || gracefulShutdownComplete) {910 sc.shutDownIn(goAwayTimeout)911 }912 }913}914915func (sc *serverConn) handlePingTimer(lastFrameReadTime time.Time) {916 if sc.pingSent {917 sc.logf("timeout waiting for PING response")918 if f := sc.countErrorFunc; f != nil {919 f("conn_close_lost_ping")920 }921 sc.conn.Close()922 return923 }924925 pingAt := lastFrameReadTime.Add(sc.readIdleTimeout)926 now := time.Now()927 if pingAt.After(now) {928 // We received frames since arming the ping timer.929 // Reset it for the next possible timeout.930 sc.readIdleTimer.Reset(pingAt.Sub(now))931 return932 }933934 sc.pingSent = true935 // Ignore crypto/rand.Read errors: It generally can't fail, and worse case if it does936 // is we send a PING frame containing 0s.937 _, _ = rand.Read(sc.sentPingData[:])938 sc.writeFrame(FrameWriteRequest{939 write: &writePing{data: sc.sentPingData},940 })941 sc.readIdleTimer.Reset(sc.pingTimeout)942}943944type serverMessage int945946// Message values sent to serveMsgCh.947var (948 settingsTimerMsg = new(serverMessage)949 idleTimerMsg = new(serverMessage)950 readIdleTimerMsg = new(serverMessage)951 shutdownTimerMsg = new(serverMessage)952 gracefulShutdownMsg = new(serverMessage)953 handlerDoneMsg = new(serverMessage)954)955956func (sc *serverConn) onSettingsTimer() { sc.sendServeMsg(settingsTimerMsg) }957func (sc *serverConn) onIdleTimer() { sc.sendServeMsg(idleTimerMsg) }958func (sc *serverConn) onReadIdleTimer() { sc.sendServeMsg(readIdleTimerMsg) }959func (sc *serverConn) onShutdownTimer() { sc.sendServeMsg(shutdownTimerMsg) }960961func (sc *serverConn) sendServeMsg(msg any) {962 sc.serveG.checkNotOn() // NOT963 select {964 case sc.serveMsgCh <- msg:965 case <-sc.doneServing:966 }967}968969var errPrefaceTimeout = errors.New("timeout waiting for client preface")970971// readPreface reads the ClientPreface greeting from the peer or972// returns errPrefaceTimeout on timeout, or an error if the greeting973// is invalid.974func (sc *serverConn) readPreface() error {975 if sc.sawClientPreface {976 return nil977 }978 errc := make(chan error, 1)979 go func() {980 // Read the client preface981 buf := make([]byte, len(ClientPreface))982 if _, err := io.ReadFull(sc.conn, buf); err != nil {983 errc <- err984 } else if !bytes.Equal(buf, clientPreface) {985 errc <- fmt.Errorf("bogus greeting %q", buf)986 } else {987 errc <- nil988 }989 }()990 timer := time.NewTimer(prefaceTimeout) // TODO: configurable on *Server?991 defer timer.Stop()992 select {993 case <-timer.C:994 return errPrefaceTimeout995 case err := <-errc:996 if err == nil {997 if VerboseLogs {998 sc.vlogf("http2: server: client %v said hello", sc.conn.RemoteAddr())999 }1000 }1001 return err1002 }1003}10041005var writeDataPool = sync.Pool{1006 New: func() any { return new(writeData) },1007}10081009// writeDataFromHandler writes DATA response frames from a handler on1010// the given stream.1011func (sc *serverConn) writeDataFromHandler(stream *stream, data []byte, endStream bool) error {1012 ch := sc.srv.getErrChan()1013 writeArg := writeDataPool.Get().(*writeData)1014 *writeArg = writeData{stream.id, data, endStream}1015 err := sc.writeFrameFromHandler(FrameWriteRequest{1016 write: writeArg,1017 stream: stream,1018 done: ch,1019 })1020 if err != nil {1021 return err1022 }1023 var frameWriteDone bool // the frame write is done (successfully or not)1024 select {1025 case err = <-ch:1026 frameWriteDone = true1027 case <-sc.doneServing:1028 return errClientDisconnected1029 case <-stream.cw:1030 // If both ch and stream.cw were ready (as might1031 // happen on the final Write after an http.Handler1032 // ends), prefer the write result. Otherwise this1033 // might just be us successfully closing the stream.1034 // The writeFrameAsync and serve goroutines guarantee1035 // that the ch send will happen before the stream.cw1036 // close.1037 select {1038 case err = <-ch:1039 frameWriteDone = true1040 default:1041 return errStreamClosed1042 }1043 }1044 sc.srv.putErrChan(ch)1045 if frameWriteDone {1046 writeDataPool.Put(writeArg)1047 }1048 return err1049}10501051// writeFrameFromHandler sends wr to sc.wantWriteFrameCh, but aborts1052// if the connection has gone away.1053//1054// This must not be run from the serve goroutine itself, else it might1055// deadlock writing to sc.wantWriteFrameCh (which is only mildly1056// buffered and is read by serve itself). If you're on the serve1057// goroutine, call writeFrame instead.1058func (sc *serverConn) writeFrameFromHandler(wr FrameWriteRequest) error {1059 sc.serveG.checkNotOn() // NOT1060 select {1061 case sc.wantWriteFrameCh <- wr:1062 return nil1063 case <-sc.doneServing:1064 // Serve loop is gone.1065 // Client has closed their connection to the server.1066 return errClientDisconnected1067 }1068}10691070// writeFrame schedules a frame to write and sends it if there's nothing1071// already being written.1072//1073// There is no pushback here (the serve goroutine never blocks). It's1074// the http.Handlers that block, waiting for their previous frames to1075// make it onto the wire1076//1077// If you're not on the serve goroutine, use writeFrameFromHandler instead.1078func (sc *serverConn) writeFrame(wr FrameWriteRequest) {1079 sc.serveG.check()10801081 // If true, wr will not be written and wr.done will not be signaled.1082 var ignoreWrite bool10831084 // We are not allowed to write frames on closed streams. RFC 7540 Section1085 // 5.1.1 says: "An endpoint MUST NOT send frames other than PRIORITY on1086 // a closed stream." Our server never sends PRIORITY, so that exception1087 // does not apply.1088 //1089 // The serverConn might close an open stream while the stream's handler1090 // is still running. For example, the server might close a stream when it1091 // receives bad data from the client. If this happens, the handler might1092 // attempt to write a frame after the stream has been closed (since the1093 // handler hasn't yet been notified of the close). In this case, we simply1094 // ignore the frame. The handler will notice that the stream is closed when1095 // it waits for the frame to be written.1096 //1097 // As an exception to this rule, we allow sending RST_STREAM after close.1098 // This allows us to immediately reject new streams without tracking any1099 // state for those streams (except for the queued RST_STREAM frame). This1100 // may result in duplicate RST_STREAMs in some cases, but the client should1101 // ignore those.1102 if wr.StreamID() != 0 {1103 _, isReset := wr.write.(StreamError)1104 if state, _ := sc.state(wr.StreamID()); state == stateClosed && !isReset {1105 ignoreWrite = true1106 }1107 }11081109 // Don't send a 100-continue response if we've already sent headers.1110 // See golang.org/issue/14030.1111 switch wr.write.(type) {1112 case *writeResHeaders:1113 wr.stream.wroteHeaders = true1114 case write100ContinueHeadersFrame:1115 if wr.stream.wroteHeaders {1116 // We do not need to notify wr.done because this frame is1117 // never written with wr.done != nil.1118 if wr.done != nil {1119 panic("wr.done != nil for write100ContinueHeadersFrame")1120 }1121 ignoreWrite = true1122 }1123 }11241125 if !ignoreWrite {1126 if wr.isControl() {1127 sc.queuedControlFrames++1128 // For extra safety, detect wraparounds, which should not happen,1129 // and pull the plug.1130 if sc.queuedControlFrames < 0 {1131 sc.conn.Close()1132 }1133 }1134 sc.writeSched.Push(wr)1135 }1136 sc.scheduleFrameWrite()1137}11381139// startFrameWrite starts a goroutine to write wr (in a separate1140// goroutine since that might block on the network), and updates the1141// serve goroutine's state about the world, updated from info in wr.1142func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {1143 sc.serveG.check()1144 if sc.writingFrame {1145 panic("internal error: can only be writing one frame at a time")1146 }11471148 st := wr.stream1149 if st != nil {1150 switch st.state {1151 case stateHalfClosedLocal:1152 switch wr.write.(type) {1153 case StreamError, handlerPanicRST, writeWindowUpdate:1154 // RFC 7540 Section 5.1 allows sending RST_STREAM, PRIORITY, and WINDOW_UPDATE1155 // in this state. (We never send PRIORITY from the server, so that is not checked.)1156 default:1157 panic(fmt.Sprintf("internal error: attempt to send frame on a half-closed-local stream: %v", wr))1158 }1159 case stateClosed:1160 panic(fmt.Sprintf("internal error: attempt to send frame on a closed stream: %v", wr))1161 }1162 }1163 if wpp, ok := wr.write.(*writePushPromise); ok {1164 var err error1165 wpp.promisedID, err = wpp.allocatePromisedID()1166 if err != nil {1167 sc.writingFrameAsync = false1168 wr.replyToWriter(err)1169 return1170 }1171 }11721173 sc.writingFrame = true1174 sc.needsFrameFlush = true1175 if wr.write.staysWithinBuffer(sc.bw.Available()) {1176 sc.writingFrameAsync = false1177 err := wr.write.writeFrame(sc)1178 sc.wroteFrame(frameWriteResult{wr: wr, err: err})1179 } else if wd, ok := wr.write.(*writeData); ok {1180 // Encode the frame in the serve goroutine, to ensure we don't have1181 // any lingering asynchronous references to data passed to Write.1182 // See https://go.dev/issue/58446.1183 sc.framer.startWriteDataPadded(wd.streamID, wd.endStream, wd.p, nil)1184 sc.writingFrameAsync = true1185 go sc.writeFrameAsync(wr, wd)1186 } else {1187 sc.writingFrameAsync = true1188 go sc.writeFrameAsync(wr, nil)1189 }1190}11911192// errHandlerPanicked is the error given to any callers blocked in a read from1193// Request.Body when the main goroutine panics. Since most handlers read in the1194// main ServeHTTP goroutine, this will show up rarely.1195var errHandlerPanicked = errors.New("http2: handler panicked")11961197// wroteFrame is called on the serve goroutine with the result of1198// whatever happened on writeFrameAsync.1199func (sc *serverConn) wroteFrame(res frameWriteResult) {1200 sc.serveG.check()1201 if !sc.writingFrame {1202 panic("internal error: expected to be already writing a frame")1203 }1204 sc.writingFrame = false1205 sc.writingFrameAsync = false12061207 if res.err != nil {1208 sc.conn.Close()1209 }12101211 wr := res.wr12121213 if writeEndsStream(wr.write) {1214 st := wr.stream1215 if st == nil {1216 panic("internal error: expecting non-nil stream")1217 }1218 switch st.state {1219 case stateOpen:1220 // Here we would go to stateHalfClosedLocal in1221 // theory, but since our handler is done and1222 // the net/http package provides no mechanism1223 // for closing a ResponseWriter while still1224 // reading data (see possible TODO at top of1225 // this file), we go into closed state here1226 // anyway, after telling the peer we're1227 // hanging up on them. We'll transition to1228 // stateClosed after the RST_STREAM frame is1229 // written.1230 st.state = stateHalfClosedLocal1231 // Section 8.1: a server MAY request that the client abort1232 // transmission of a request without error by sending a1233 // RST_STREAM with an error code of NO_ERROR after sending1234 // a complete response.1235 sc.resetStream(streamError(st.id, ErrCodeNo))1236 case stateHalfClosedRemote:1237 sc.closeStream(st, errHandlerComplete)1238 }1239 } else {1240 switch v := wr.write.(type) {1241 case StreamError:1242 // st may be unknown if the RST_STREAM was generated to reject bad input.1243 if st, ok := sc.streams[v.StreamID]; ok {1244 sc.closeStream(st, v)1245 }1246 case handlerPanicRST:1247 sc.closeStream(wr.stream, errHandlerPanicked)1248 }1249 }12501251 // Reply (if requested) to unblock the ServeHTTP goroutine.1252 wr.replyToWriter(res.err)12531254 sc.scheduleFrameWrite()1255}12561257// scheduleFrameWrite tickles the frame writing scheduler.1258//1259// If a frame is already being written, nothing happens. This will be called again1260// when the frame is done being written.1261//1262// If a frame isn't being written and we need to send one, the best frame1263// to send is selected by writeSched.1264//1265// If a frame isn't being written and there's nothing else to send, we1266// flush the write buffer.1267func (sc *serverConn) scheduleFrameWrite() {1268 sc.serveG.check()1269 if sc.writingFrame || sc.inFrameScheduleLoop {1270 return1271 }1272 sc.inFrameScheduleLoop = true1273 for !sc.writingFrameAsync {1274 if sc.needToSendGoAway {1275 sc.needToSendGoAway = false1276 sc.startFrameWrite(FrameWriteRequest{1277 write: &writeGoAway{1278 maxStreamID: sc.maxClientStreamID,1279 code: sc.goAwayCode,1280 },1281 })1282 continue1283 }1284 if sc.needToSendSettingsAck {1285 sc.needToSendSettingsAck = false1286 sc.startFrameWrite(FrameWriteRequest{write: writeSettingsAck{}})1287 continue1288 }1289 if !sc.inGoAway || sc.goAwayCode == ErrCodeNo {1290 if wr, ok := sc.writeSched.Pop(); ok {1291 if wr.isControl() {1292 sc.queuedControlFrames--1293 }1294 sc.startFrameWrite(wr)1295 continue1296 }1297 }1298 if sc.needsFrameFlush {1299 sc.startFrameWrite(FrameWriteRequest{write: flushFrameWriter{}})1300 sc.needsFrameFlush = false // after startFrameWrite, since it sets this true1301 continue1302 }1303 break1304 }1305 sc.inFrameScheduleLoop = false1306}13071308// startGracefulShutdown gracefully shuts down a connection. This1309// sends GOAWAY with ErrCodeNo to tell the client we're gracefully1310// shutting down. The connection isn't closed until all current1311// streams are done.1312//1313// startGracefulShutdown returns immediately; it does not wait until1314// the connection has shut down.1315func (sc *serverConn) startGracefulShutdown() {1316 sc.serveG.checkNotOn() // NOT1317 sc.shutdownOnce.Do(func() { sc.sendServeMsg(gracefulShutdownMsg) })1318}13191320// After sending GOAWAY with an error code (non-graceful shutdown), the1321// connection will close after goAwayTimeout.1322//1323// If we close the connection immediately after sending GOAWAY, there may1324// be unsent data in our kernel receive buffer, which will cause the kernel1325// to send a TCP RST on close() instead of a FIN. This RST will abort the1326// connection immediately, whether or not the client had received the GOAWAY.1327//1328// Ideally we should delay for at least 1 RTT + epsilon so the client has1329// a chance to read the GOAWAY and stop sending messages. Measuring RTT1330// is hard, so we approximate with 1 second. See golang.org/issue/18701.1331//1332// This is a var so it can be shorter in tests, where all requests uses the1333// loopback interface making the expected RTT very small.1334//1335// TODO: configurable?1336var goAwayTimeout = 1 * time.Second13371338func (sc *serverConn) startGracefulShutdownInternal() {1339 sc.goAway(ErrCodeNo)1340}13411342func (sc *serverConn) goAway(code ErrCode) {1343 sc.serveG.check()1344 if sc.inGoAway {1345 if sc.goAwayCode == ErrCodeNo {1346 sc.goAwayCode = code1347 }1348 return1349 }1350 sc.inGoAway = true1351 sc.needToSendGoAway = true1352 sc.goAwayCode = code1353 sc.scheduleFrameWrite()1354}13551356func (sc *serverConn) shutDownIn(d time.Duration) {1357 sc.serveG.check()1358 sc.shutdownTimer = time.AfterFunc(d, sc.onShutdownTimer)1359}13601361func (sc *serverConn) resetStream(se StreamError) {1362 sc.serveG.check()1363 sc.writeFrame(FrameWriteRequest{write: se})1364 if st, ok := sc.streams[se.StreamID]; ok {1365 st.resetQueued = true1366 }1367}13681369// processFrameFromReader processes the serve loop's read from readFrameCh from the1370// frame-reading goroutine.1371// processFrameFromReader returns whether the connection should be kept open.1372func (sc *serverConn) processFrameFromReader(res readFrameResult) bool {1373 sc.serveG.check()1374 err := res.err1375 if err != nil {1376 if err == ErrFrameTooLarge {1377 sc.goAway(ErrCodeFrameSize)1378 return true // goAway will close the loop1379 }1380 clientGone := err == io.EOF || err == io.ErrUnexpectedEOF || isClosedConnError(err)1381 if clientGone {1382 // TODO: could we also get into this state if1383 // the peer does a half close1384 // (e.g. CloseWrite) because they're done1385 // sending frames but they're still wanting1386 // our open replies? Investigate.1387 // TODO: add CloseWrite to crypto/tls.Conn first1388 // so we have a way to test this? I suppose1389 // just for testing we could have a non-TLS mode.1390 return false1391 }1392 } else {1393 f := res.f1394 if VerboseLogs {1395 sc.vlogf("http2: server read frame %v", summarizeFrame(f))1396 }1397 err = sc.processFrame(f)1398 if err == nil {1399 return true1400 }1401 }14021403 switch ev := err.(type) {1404 case StreamError:1405 sc.resetStream(ev)1406 return true1407 case goAwayFlowError:1408 sc.goAway(ErrCodeFlowControl)1409 return true1410 case ConnectionError:1411 if res.f != nil {1412 if id := res.f.Header().StreamID; id > sc.maxClientStreamID {1413 sc.maxClientStreamID = id1414 }1415 }1416 sc.logf("http2: server connection error from %v: %v", sc.conn.RemoteAddr(), ev)1417 sc.goAway(ErrCode(ev))1418 return true // goAway will handle shutdown1419 default:1420 if res.err != nil {1421 sc.vlogf("http2: server closing client connection; error reading frame from client %s: %v", sc.conn.RemoteAddr(), err)1422 } else {1423 sc.logf("http2: server closing client connection: %v", err)1424 }1425 return false1426 }1427}14281429func (sc *serverConn) processFrame(f Frame) error {1430 sc.serveG.check()14311432 // First frame received must be SETTINGS.1433 if !sc.sawFirstSettings {1434 if _, ok := f.(*SettingsFrame); !ok {1435 return sc.countError("first_settings", ConnectionError(ErrCodeProtocol))1436 }1437 sc.sawFirstSettings = true1438 }14391440 // Discard frames for streams initiated after the identified last1441 // stream sent in a GOAWAY, or all frames after sending an error.1442 // We still need to return connection-level flow control for DATA frames.1443 // RFC 9113 Section 6.8.1444 if sc.inGoAway && (sc.goAwayCode != ErrCodeNo || f.Header().StreamID > sc.maxClientStreamID) {14451446 if f, ok := f.(*DataFrame); ok {1447 if !sc.inflow.take(f.Length) {1448 return sc.countError("data_flow", streamError(f.Header().StreamID, ErrCodeFlowControl))1449 }1450 sc.sendWindowUpdate(nil, int(f.Length)) // conn-level1451 }1452 return nil1453 }14541455 switch f := f.(type) {1456 case *SettingsFrame:1457 return sc.processSettings(f)1458 case *MetaHeadersFrame:1459 return sc.processHeaders(f)1460 case *WindowUpdateFrame:1461 return sc.processWindowUpdate(f)1462 case *PingFrame:1463 return sc.processPing(f)1464 case *DataFrame:1465 return sc.processData(f)1466 case *RSTStreamFrame:1467 return sc.processResetStream(f)1468 case *PriorityFrame:1469 return sc.processPriority(f)1470 case *GoAwayFrame:1471 return sc.processGoAway(f)1472 case *PushPromiseFrame:1473 // A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE1474 // frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.1475 return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))1476 case *PriorityUpdateFrame:1477 return sc.processPriorityUpdate(f)1478 default:1479 sc.vlogf("http2: server ignoring frame: %v", f.Header())1480 return nil1481 }1482}14831484func (sc *serverConn) processPing(f *PingFrame) error {1485 sc.serveG.check()1486 if f.IsAck() {1487 if sc.pingSent && sc.sentPingData == f.Data {1488 // This is a response to a PING we sent.1489 sc.pingSent = false1490 sc.readIdleTimer.Reset(sc.readIdleTimeout)1491 }1492 // 6.7 PING: " An endpoint MUST NOT respond to PING frames1493 // containing this flag."1494 return nil1495 }1496 if f.StreamID != 0 {1497 // "PING frames are not associated with any individual1498 // stream. If a PING frame is received with a stream1499 // identifier field value other than 0x0, the recipient MUST1500 // respond with a connection error (Section 5.4.1) of type1501 // PROTOCOL_ERROR."1502 return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))1503 }1504 sc.writeFrame(FrameWriteRequest{write: writePingAck{f}})1505 return nil1506}15071508func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {1509 sc.serveG.check()1510 switch {1511 case f.StreamID != 0: // stream-level flow control1512 state, st := sc.state(f.StreamID)1513 if state == stateIdle {1514 // Section 5.1: "Receiving any frame other than HEADERS1515 // or PRIORITY on a stream in this state MUST be1516 // treated as a connection error (Section 5.4.1) of1517 // type PROTOCOL_ERROR."1518 return sc.countError("stream_idle", ConnectionError(ErrCodeProtocol))1519 }1520 if st == nil {1521 // "WINDOW_UPDATE can be sent by a peer that has sent a1522 // frame bearing the END_STREAM flag. This means that a1523 // receiver could receive a WINDOW_UPDATE frame on a "half1524 // closed (remote)" or "closed" stream. A receiver MUST1525 // NOT treat this as an error, see Section 5.1."1526 return nil1527 }1528 if !st.flow.add(int32(f.Increment)) {1529 return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl))1530 }1531 default: // connection-level flow control1532 if !sc.flow.add(int32(f.Increment)) {1533 return goAwayFlowError{}1534 }1535 }1536 sc.scheduleFrameWrite()1537 return nil1538}15391540func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {1541 sc.serveG.check()15421543 state, st := sc.state(f.StreamID)1544 if state == stateIdle {1545 // 6.4 "RST_STREAM frames MUST NOT be sent for a1546 // stream in the "idle" state. If a RST_STREAM frame1547 // identifying an idle stream is received, the1548 // recipient MUST treat this as a connection error1549 // (Section 5.4.1) of type PROTOCOL_ERROR.1550 return sc.countError("reset_idle_stream", ConnectionError(ErrCodeProtocol))1551 }1552 if st != nil {1553 st.cancelCtx()1554 sc.closeStream(st, streamError(f.StreamID, f.ErrCode))1555 }1556 return nil1557}15581559func (sc *serverConn) closeStream(st *stream, err error) {1560 sc.serveG.check()1561 if st.state == stateIdle || st.state == stateClosed {1562 panic(fmt.Sprintf("invariant; can't close stream in state %v", st.state))1563 }1564 st.state = stateClosed1565 if st.readDeadline != nil {1566 st.readDeadline.Stop()1567 }1568 if st.writeDeadline != nil {1569 st.writeDeadline.Stop()1570 }1571 if st.isPushed() {1572 sc.curPushedStreams--1573 } else {1574 sc.curClientStreams--1575 }1576 delete(sc.streams, st.id)1577 if len(sc.streams) == 0 {1578 sc.setConnState(ConnStateIdle)1579 idleTimeout := sc.hs.IdleTimeout()1580 if idleTimeout > 0 && sc.idleTimer != nil {1581 sc.idleTimer.Reset(idleTimeout)1582 }1583 if h1ServerKeepAlivesDisabled(sc.hs) {1584 sc.startGracefulShutdownInternal()1585 }1586 }1587 if p := st.body; p != nil {1588 // Return any buffered unread bytes worth of conn-level flow control.1589 // See golang.org/issue/164811590 sc.sendWindowUpdate(nil, p.Len())15911592 p.CloseWithError(err)1593 }1594 if e, ok := err.(StreamError); ok {1595 if e.Cause != nil {1596 err = e.Cause1597 } else {1598 err = errStreamClosed1599 }1600 }1601 st.closeErr = err1602 st.cancelCtx()1603 st.cw.Close() // signals Handler's CloseNotifier, unblocks writes, etc1604 sc.writeSched.CloseStream(st.id)1605}16061607func (sc *serverConn) processSettings(f *SettingsFrame) error {1608 sc.serveG.check()1609 if f.IsAck() {1610 sc.unackedSettings--1611 if sc.unackedSettings < 0 {1612 // Why is the peer ACKing settings we never sent?1613 // The spec doesn't mention this case, but1614 // hang up on them anyway.1615 return sc.countError("ack_mystery", ConnectionError(ErrCodeProtocol))1616 }1617 return nil1618 }1619 if f.NumSettings() > 100 || f.HasDuplicates() {1620 // This isn't actually in the spec, but hang up on1621 // suspiciously large settings frames or those with1622 // duplicate entries.1623 return sc.countError("settings_big_or_dups", ConnectionError(ErrCodeProtocol))1624 }1625 if err := f.ForeachSetting(sc.processSetting); err != nil {1626 return err1627 }1628 // TODO: judging by RFC 7540, Section 6.5.3 each SETTINGS frame should be1629 // acknowledged individually, even if multiple are received before the ACK.1630 sc.needToSendSettingsAck = true1631 sc.scheduleFrameWrite()1632 return nil1633}16341635func (sc *serverConn) processSetting(s Setting) error {1636 sc.serveG.check()1637 if err := s.Valid(); err != nil {1638 return err1639 }1640 if VerboseLogs {1641 sc.vlogf("http2: server processing setting %v", s)1642 }1643 switch s.ID {1644 case SettingHeaderTableSize:1645 sc.hpackEncoder.SetMaxDynamicTableSize(s.Val)1646 case SettingEnablePush:1647 sc.pushEnabled = s.Val != 01648 case SettingMaxConcurrentStreams:1649 sc.clientMaxStreams = s.Val1650 case SettingInitialWindowSize:1651 return sc.processSettingInitialWindowSize(s.Val)1652 case SettingMaxFrameSize:1653 sc.maxFrameSize = int32(s.Val) // the maximum valid s.Val is < 2^311654 case SettingMaxHeaderListSize:1655 sc.peerMaxHeaderListSize = s.Val1656 case SettingEnableConnectProtocol:1657 // Receipt of this parameter by a server does not1658 // have any impact1659 case SettingNoRFC7540Priorities:1660 if s.Val > 1 {1661 return ConnectionError(ErrCodeProtocol)1662 }1663 default:1664 // Unknown setting: "An endpoint that receives a SETTINGS1665 // frame with any unknown or unsupported identifier MUST1666 // ignore that setting."1667 if VerboseLogs {1668 sc.vlogf("http2: server ignoring unknown setting %v", s)1669 }1670 }1671 return nil1672}16731674func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {1675 sc.serveG.check()1676 // Note: val already validated to be within range by1677 // processSetting's Valid call.16781679 // "A SETTINGS frame can alter the initial flow control window1680 // size for all current streams. When the value of1681 // SETTINGS_INITIAL_WINDOW_SIZE changes, a receiver MUST1682 // adjust the size of all stream flow control windows that it1683 // maintains by the difference between the new value and the1684 // old value."1685 old := sc.initialStreamSendWindowSize1686 sc.initialStreamSendWindowSize = int32(val)1687 growth := int32(val) - old // may be negative1688 for _, st := range sc.streams {1689 if !st.flow.add(growth) {1690 // 6.9.2 Initial Flow Control Window Size1691 // "An endpoint MUST treat a change to1692 // SETTINGS_INITIAL_WINDOW_SIZE that causes any flow1693 // control window to exceed the maximum size as a1694 // connection error (Section 5.4.1) of type1695 // FLOW_CONTROL_ERROR."1696 return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl))1697 }1698 }1699 return nil1700}17011702func (sc *serverConn) processData(f *DataFrame) error {1703 sc.serveG.check()1704 id := f.Header().StreamID17051706 data := f.Data()1707 state, st := sc.state(id)1708 if id == 0 || state == stateIdle {1709 // Section 6.1: "DATA frames MUST be associated with a1710 // stream. If a DATA frame is received whose stream1711 // identifier field is 0x0, the recipient MUST respond1712 // with a connection error (Section 5.4.1) of type1713 // PROTOCOL_ERROR."1714 //1715 // Section 5.1: "Receiving any frame other than HEADERS1716 // or PRIORITY on a stream in this state MUST be1717 // treated as a connection error (Section 5.4.1) of1718 // type PROTOCOL_ERROR."1719 return sc.countError("data_on_idle", ConnectionError(ErrCodeProtocol))1720 }17211722 // "If a DATA frame is received whose stream is not in "open"1723 // or "half closed (local)" state, the recipient MUST respond1724 // with a stream error (Section 5.4.2) of type STREAM_CLOSED."1725 if st == nil || state != stateOpen || st.gotTrailerHeader || st.resetQueued {1726 // This includes sending a RST_STREAM if the stream is1727 // in stateHalfClosedLocal (which currently means that1728 // the http.Handler returned, so it's done reading &1729 // done writing). Try to stop the client from sending1730 // more DATA.17311732 // But still enforce their connection-level flow control,1733 // and return any flow control bytes since we're not going1734 // to consume them.1735 if !sc.inflow.take(f.Length) {1736 return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))1737 }1738 sc.sendWindowUpdate(nil, int(f.Length)) // conn-level17391740 if st != nil && st.resetQueued {1741 // Already have a stream error in flight. Don't send another.1742 return nil1743 }1744 return sc.countError("closed", streamError(id, ErrCodeStreamClosed))1745 }1746 if st.body == nil {1747 panic("internal error: should have a body in this state")1748 }17491750 // Sender sending more than they'd declared?1751 if st.declBodyBytes != -1 && st.bodyBytes+int64(len(data)) > st.declBodyBytes {1752 if !sc.inflow.take(f.Length) {1753 return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))1754 }1755 sc.sendWindowUpdate(nil, int(f.Length)) // conn-level17561757 st.body.CloseWithError(fmt.Errorf("sender tried to send more than declared Content-Length of %d bytes", st.declBodyBytes))1758 // RFC 7540, sec 8.1.2.6: A request or response is also malformed if the1759 // value of a content-length header field does not equal the sum of the1760 // DATA frame payload lengths that form the body.1761 return sc.countError("send_too_much", streamError(id, ErrCodeProtocol))1762 }1763 if f.Length > 0 {1764 // Check whether the client has flow control quota.1765 if !takeInflows(&sc.inflow, &st.inflow, f.Length) {1766 return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))1767 }17681769 if len(data) > 0 {1770 st.bodyBytes += int64(len(data))1771 wrote, err := st.body.Write(data)1772 if err != nil {1773 // The handler has closed the request body.1774 // Return the connection-level flow control for the discarded data,1775 // but not the stream-level flow control.1776 sc.sendWindowUpdate(nil, int(f.Length)-wrote)1777 return nil1778 }1779 if wrote != len(data) {1780 panic("internal error: bad Writer")1781 }1782 }17831784 // Return any padded flow control now, since we won't1785 // refund it later on body reads.1786 // Call sendWindowUpdate even if there is no padding,1787 // to return buffered flow control credit if the sent1788 // window has shrunk.1789 pad := int32(f.Length) - int32(len(data))1790 sc.sendWindowUpdate32(nil, pad)1791 sc.sendWindowUpdate32(st, pad)1792 }1793 if f.StreamEnded() {1794 st.endStream()1795 }1796 return nil1797}17981799func (sc *serverConn) processGoAway(f *GoAwayFrame) error {1800 sc.serveG.check()1801 if f.ErrCode != ErrCodeNo {1802 sc.logf("http2: received GOAWAY %+v, starting graceful shutdown", f)1803 } else {1804 sc.vlogf("http2: received GOAWAY %+v, starting graceful shutdown", f)1805 }1806 sc.startGracefulShutdownInternal()1807 // http://tools.ietf.org/html/rfc7540#section-6.81808 // We should not create any new streams, which means we should disable push.1809 sc.pushEnabled = false1810 return nil1811}18121813// isPushed reports whether the stream is server-initiated.1814func (st *stream) isPushed() bool {1815 return st.id%2 == 01816}18171818// endStream closes a Request.Body's pipe. It is called when a DATA1819// frame says a request body is over (or after trailers).1820func (st *stream) endStream() {1821 sc := st.sc1822 sc.serveG.check()18231824 if st.declBodyBytes != -1 && st.declBodyBytes != st.bodyBytes {1825 st.body.CloseWithError(fmt.Errorf("request declared a Content-Length of %d but only wrote %d bytes",1826 st.declBodyBytes, st.bodyBytes))1827 } else {1828 st.body.closeWithErrorAndCode(io.EOF, st.copyTrailersToHandlerRequest)1829 st.body.CloseWithError(io.EOF)1830 }1831 st.state = stateHalfClosedRemote1832}18331834// copyTrailersToHandlerRequest is run in the Handler's goroutine in1835// its Request.Body.Read just before it gets io.EOF.1836func (st *stream) copyTrailersToHandlerRequest() {1837 for k, vv := range st.trailer {1838 if _, ok := st.reqTrailer[k]; ok {1839 // Only copy it over it was pre-declared.1840 st.reqTrailer[k] = vv1841 }1842 }1843}18441845// onReadTimeout is run on its own goroutine (from time.AfterFunc)1846// when the stream's ReadTimeout has fired.1847func (st *stream) onReadTimeout() {1848 if st.body != nil {1849 // Wrap the ErrDeadlineExceeded to avoid callers depending on us1850 // returning the bare error.1851 st.body.CloseWithError(fmt.Errorf("%w", os.ErrDeadlineExceeded))1852 }1853}18541855// onWriteTimeout is run on its own goroutine (from time.AfterFunc)1856// when the stream's WriteTimeout has fired.1857func (st *stream) onWriteTimeout() {1858 st.sc.writeFrameFromHandler(FrameWriteRequest{write: StreamError{1859 StreamID: st.id,1860 Code: ErrCodeInternal,1861 Cause: os.ErrDeadlineExceeded,1862 }})1863}18641865func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {1866 sc.serveG.check()1867 id := f.StreamID1868 // http://tools.ietf.org/html/rfc7540#section-5.1.11869 // Streams initiated by a client MUST use odd-numbered stream1870 // identifiers. [...] An endpoint that receives an unexpected1871 // stream identifier MUST respond with a connection error1872 // (Section 5.4.1) of type PROTOCOL_ERROR.1873 if id%2 != 1 {1874 return sc.countError("headers_even", ConnectionError(ErrCodeProtocol))1875 }1876 // A HEADERS frame can be used to create a new stream or1877 // send a trailer for an open one. If we already have a stream1878 // open, let it process its own HEADERS frame (trailers at this1879 // point, if it's valid).1880 if st := sc.streams[f.StreamID]; st != nil {1881 if st.resetQueued {1882 // We're sending RST_STREAM to close the stream, so don't bother1883 // processing this frame.1884 return nil1885 }1886 // RFC 7540, sec 5.1: If an endpoint receives additional frames, other than1887 // WINDOW_UPDATE, PRIORITY, or RST_STREAM, for a stream that is in1888 // this state, it MUST respond with a stream error (Section 5.4.2) of1889 // type STREAM_CLOSED.1890 if st.state == stateHalfClosedRemote {1891 return sc.countError("headers_half_closed", streamError(id, ErrCodeStreamClosed))1892 }1893 return st.processTrailerHeaders(f)1894 }18951896 // [...] The identifier of a newly established stream MUST be1897 // numerically greater than all streams that the initiating1898 // endpoint has opened or reserved. [...] An endpoint that1899 // receives an unexpected stream identifier MUST respond with1900 // a connection error (Section 5.4.1) of type PROTOCOL_ERROR.1901 if id <= sc.maxClientStreamID {1902 return sc.countError("stream_went_down", ConnectionError(ErrCodeProtocol))1903 }1904 sc.maxClientStreamID = id19051906 if sc.idleTimer != nil {1907 sc.idleTimer.Stop()1908 }19091910 // http://tools.ietf.org/html/rfc7540#section-5.1.21911 // [...] Endpoints MUST NOT exceed the limit set by their peer. An1912 // endpoint that receives a HEADERS frame that causes their1913 // advertised concurrent stream limit to be exceeded MUST treat1914 // this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR1915 // or REFUSED_STREAM.1916 if sc.curClientStreams+1 > sc.advMaxStreams {1917 if sc.unackedSettings == 0 {1918 // They should know better.1919 return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))1920 }1921 // Assume it's a network race, where they just haven't1922 // received our last SETTINGS update. But actually1923 // this can't happen yet, because we don't yet provide1924 // a way for users to adjust server parameters at1925 // runtime.1926 return sc.countError("over_max_streams_race", streamError(id, ErrCodeRefusedStream))1927 }19281929 initialState := stateOpen1930 if f.StreamEnded() {1931 initialState = stateHalfClosedRemote1932 }19331934 // We are handling two special cases here:1935 // 1. When a request is sent via an intermediary, we force priority to be1936 // u=3,i. This is essentially a round-robin behavior, and is done to ensure1937 // fairness between, for example, multiple clients using the same proxy.1938 // 2. Until a client has shown that it is aware of RFC 9218, we make its1939 // streams non-incremental by default. This is done to preserve the1940 // historical behavior of handling streams in a round-robin manner, rather1941 // than one-by-one to completion.1942 initialPriority := defaultRFC9218Priority(sc.priorityAware && !sc.hasIntermediary)1943 if _, ok := sc.writeSched.(*priorityWriteSchedulerRFC9218); ok && !sc.hasIntermediary {1944 headerPriority, priorityAware, hasIntermediary := f.rfc9218Priority(sc.priorityAware)1945 initialPriority = headerPriority1946 sc.hasIntermediary = hasIntermediary1947 if priorityAware {1948 sc.priorityAware = true1949 }1950 }1951 st := sc.newStream(id, 0, initialState, initialPriority)19521953 if f.HasPriority() {1954 if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {1955 return err1956 }1957 if !sc.writeSchedIgnoresRFC7540() {1958 sc.writeSched.AdjustStream(st.id, f.Priority)1959 }1960 }19611962 rw, req, err := sc.newWriterAndRequest(st, f)1963 if err != nil {1964 return err1965 }1966 st.reqTrailer = req.Trailer1967 if st.reqTrailer != nil {1968 st.trailer = make(Header)1969 }1970 st.body = req.Body.(*requestBody).pipe // may be nil1971 st.declBodyBytes = req.ContentLength19721973 handler := sc.handler.ServeHTTP1974 if f.Truncated {1975 // Their header list was too long. Send a 431 error.1976 handler = handleHeaderListTooLong1977 } else if err := checkValidHTTP2RequestHeaders(req.Header); err != nil {1978 handler = serve400Handler{err}.ServeHTTP1979 }19801981 if sc.hs.ReadTimeout() > 0 {1982 st.readDeadline = time.AfterFunc(sc.hs.ReadTimeout(), st.onReadTimeout)1983 }19841985 return sc.scheduleHandler(id, rw, req, handler)1986}19871988func (sc *serverConn) upgradeRequest(req *ServerRequest) {1989 sc.serveG.check()1990 id := uint32(1)1991 sc.maxClientStreamID = id1992 st := sc.newStream(id, 0, stateHalfClosedRemote, defaultRFC9218Priority(sc.priorityAware && !sc.hasIntermediary))1993 st.reqTrailer = req.Trailer1994 if st.reqTrailer != nil {1995 st.trailer = make(Header)1996 }1997 rw := sc.newResponseWriter(st)1998 rw.rws.req = *req1999 req = &rw.rws.req
Findings
✓ No findings reported for this file.