src/net/http/internal/http2/server.go GO 3,270 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 3,270.
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.

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.