// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package http3

import (
	"context"
	"crypto/tls"
	"errors"
	"fmt"
	"maps"
	"net"
	"net/http"
	"net/textproto"
	"os"
	"slices"
	"strconv"
	"strings"
	"sync"
	"time"

	"net/http/internal/httpcommon"

	"golang.org/x/net/http/httpguts"
	"golang.org/x/net/quic"
)

// A server is an HTTP/3 server.
// The zero value for server is a valid server.
type server struct {
	srv1 *http.Server
	opts ServerOpts

	initOnce sync.Once

	// connClosed is used to signal that a connection has been unregistered
	// from activeConns. That way, when shutting down gracefully, the server
	// can avoid busy-waiting for activeConns to be empty.
	connClosed  chan any
	mu          sync.Mutex // Guards fields below.
	activeConns map[*serverConn]struct{}
}

// netHTTPServer implements the net/http.http3Server interface,
// allowing our HTTP/3 server to integrate with net/http.
type netHTTPServer struct {
	*server
}

// Implement net.Listener, so we can pass a netHTTPServer to net/http.Server.Serve.
func (netHTTPServer) Accept() (net.Conn, error) { return nil, net.ErrClosed }
func (netHTTPServer) Close() error              { return nil }
func (netHTTPServer) Addr() net.Addr            { return nil }

// ServeHTTP3 starts serving HTTP/3 on a UDP port.
//
// The ctx parameter is used as the base context for request handlers
// for requests receieved via this port.
func (s netHTTPServer) ServeHTTP3(ctx context.Context, conn net.PacketConn, tlsConfig *tls.Config, h http.Handler) error {
	s.init()
	e, err := quic.NewEndpoint(conn, newQUICConfig(s.opts.QUICConfig, tlsConfig))
	if err != nil {
		return err
	}
	return s.serve(ctx, e, h)
}

// Shutdown shuts down the server.
func (s netHTTPServer) Shutdown(ctx context.Context) error {
	s.shutdown(ctx)
	return nil
}

type ServerOpts struct {
	// QUICConfig is the QUIC configuration used by the server.
	// QUICConfig may be nil and should not be modified after calling
	// RegisterServer.
	// If QUICConfig.TLSConfig is nil, the TLSConfig of the net/http Server
	// given to RegisterServer will be used.
	QUICConfig *quic.Config
}

// RegisterServer adds HTTP/3 support to a net/http Server.
//
// RegisterServer must be called before s begins serving, and only affects
// s.ListenAndServeTLS.
func RegisterServer(s *http.Server, opts ServerOpts) error {
	if err := s.Serve(netHTTPServer{&server{
		opts: opts,
		srv1: s,
	}}); err != nil {
		return errors.New("http3: net/http does not support HTTP/3")
	}
	return nil
}

func (s *server) init() {
	s.initOnce.Do(func() {
		s.activeConns = make(map[*serverConn]struct{})
		s.connClosed = make(chan any, 1)
	})
}

// serve accepts incoming connections on the QUIC endpoint e,
// and handles requests from those connections.
func (s *server) serve(ctx context.Context, e *quic.Endpoint, h http.Handler) error {
	s.init()
	defer e.Close(canceledCtx)
	for {
		qconn, err := e.Accept(ctx)
		if err != nil {
			return err
		}
		go s.newServerConn(ctx, qconn, h)
	}
}

// shutdown attempts a graceful shutdown for the server.
func (s *server) shutdown(ctx context.Context) {
	// Set a reasonable default in case ctx is nil.
	if ctx == nil {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(context.Background(), time.Second)
		defer cancel()
	}

	// Send GOAWAY frames to all active connections to give a chance for them
	// to gracefully terminate.
	s.mu.Lock()
	for sc := range s.activeConns {
		// TODO: Modify x/net/quic stream API so that write errors from context
		// deadline are sticky.
		go sc.sendGoaway()
	}
	s.mu.Unlock()

	// Complete shutdown as soon as there are no more active connections or ctx
	// is done, whichever comes first.
	defer func() {
		s.mu.Lock()
		defer s.mu.Unlock()
		for sc := range s.activeConns {
			sc.abort(&connectionError{
				code:    errH3NoError,
				message: "server is shutting down",
			})
		}
	}()
	noMoreConns := func() bool {
		s.mu.Lock()
		defer s.mu.Unlock()
		return len(s.activeConns) == 0
	}
	for {
		if noMoreConns() {
			return
		}
		select {
		case <-ctx.Done():
			return
		case <-s.connClosed:
		}
	}
}

func (s *server) registerConn(sc *serverConn) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.activeConns[sc] = struct{}{}
}

func (s *server) unregisterConn(sc *serverConn) {
	s.mu.Lock()
	delete(s.activeConns, sc)
	s.mu.Unlock()
	select {
	case s.connClosed <- struct{}{}:
	default:
		// Channel already full. No need to send more values since we are just
		// using this channel as a simpler sync.Cond.
	}
}

func (s *server) readHeaderTimeout() time.Duration {
	if s.srv1 == nil || s.srv1.ReadHeaderTimeout == 0 {
		return s.readTimeout()
	}
	return s.srv1.ReadHeaderTimeout
}

func (s *server) readTimeout() time.Duration {
	if s.srv1 == nil {
		return 0
	}
	return s.srv1.ReadTimeout
}

func (s *server) writeTimeout() time.Duration {
	if s.srv1 == nil {
		return 0
	}
	return s.srv1.WriteTimeout
}

// TODO: this is currently unused, enforce it.
func (s *server) idleTimeout() time.Duration {
	if s.srv1 == nil || s.srv1.IdleTimeout == 0 {
		return s.readTimeout()
	}
	return s.srv1.IdleTimeout
}

type serverConn struct {
	qconn    *quic.Conn
	srv      *server
	baseCtx  context.Context
	handler  http.Handler
	tlsState *tls.ConnectionState

	genericConn // for handleUnidirectionalStream
	enc         qpackEncoder
	dec         qpackDecoder

	maxHeaderBytes      int64
	maxHeaderValueCount int64

	// For handling shutdown.
	controlStream      *stream
	mu                 sync.Mutex // Guards everything below.
	maxRequestStreamID int64
	goawaySent         bool
}

// newServerConn handles a new connection.
// The baseCtx parameter is the base context for request handlers on this connection.
func (s *server) newServerConn(baseCtx context.Context, qconn *quic.Conn, h http.Handler) {
	if localAddr := qconn.LocalAddr(); localAddr.IsValid() {
		baseCtx = context.WithValue(baseCtx, http.LocalAddrContextKey, net.UDPAddrFromAddrPort(localAddr))
	}
	baseCtx, cancel := context.WithCancel(baseCtx)
	defer cancel()

	sc := &serverConn{
		qconn:               qconn,
		srv:                 s,
		baseCtx:             baseCtx,
		handler:             h,
		tlsState:            new(qconn.ConnectionState()),
		maxHeaderBytes:      int64(s.srv1.MaxHeaderBytes),
		maxHeaderValueCount: int64(s.srv1.MaxHeaderValueCount),
	}

	// Should we permit disabling these limits? For now, we do not.
	if sc.maxHeaderBytes <= 0 {
		sc.maxHeaderBytes = int64(http.DefaultMaxHeaderBytes)
	}
	if sc.maxHeaderValueCount <= 0 {
		sc.maxHeaderValueCount = int64(http.DefaultMaxHeaderValueCount)
	}

	s.registerConn(sc)
	defer s.unregisterConn(sc)
	sc.enc.init()

	// Create control stream and send SETTINGS frame.
	// TODO: Time out on creating stream.
	var err error
	sc.controlStream, err = newConnStream(context.Background(), sc.qconn, streamTypeControl)
	if err != nil {
		return
	}
	sc.controlStream.writeSettings(
		settingsMaxFieldSectionSize, sc.maxHeaderBytes,
	)
	sc.controlStream.Flush()

	sc.acceptStreams(sc.qconn, sc)
}

func (sc *serverConn) handleControlStream(st *stream) error {
	// "A SETTINGS frame MUST be sent as the first frame of each control stream [...]"
	// https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.4-2
	if err := st.readSettings(func(settingsType, settingsValue int64) error {
		switch settingsType {
		case settingsMaxFieldSectionSize:
			_ = settingsValue // TODO
		case settingsQPACKMaxTableCapacity:
			_ = settingsValue // TODO
		case settingsQPACKBlockedStreams:
			_ = settingsValue // TODO
		default:
			// Unknown settings types are ignored.
		}
		return nil
	}); err != nil {
		return err
	}

	for {
		ftype, err := st.readFrameHeader()
		if err != nil {
			return err
		}
		switch ftype {
		case frameTypeCancelPush:
			// "If a server receives a CANCEL_PUSH frame for a push ID
			// that has not yet been mentioned by a PUSH_PROMISE frame,
			// this MUST be treated as a connection error of type H3_ID_ERROR."
			// https://www.rfc-editor.org/rfc/rfc9114.html#section-7.2.3-8
			return &connectionError{
				code:    errH3IDError,
				message: "CANCEL_PUSH for unsent push ID",
			}
		case frameTypeGoaway:
			return errH3NoError
		default:
			// Unknown frames are ignored.
			if err := st.discardUnknownFrame(ftype); err != nil {
				return err
			}
		}
	}
}

func (sc *serverConn) handleEncoderStream(*stream) error {
	// TODO
	return nil
}

func (sc *serverConn) handleDecoderStream(*stream) error {
	// TODO
	return nil
}

func (sc *serverConn) handlePushStream(*stream) error {
	// "[...] if a server receives a client-initiated push stream,
	// this MUST be treated as a connection error of type H3_STREAM_CREATION_ERROR."
	// https://www.rfc-editor.org/rfc/rfc9114.html#section-6.2.2-3
	return &connectionError{
		code:    errH3StreamCreationError,
		message: "client created push stream",
	}
}

// hasDisallowedConnectionHeader reports whether h contains connection headers
// that are not allowed in HTTP/3:
//
// "An endpoint MUST NOT generate an HTTP/3 field section containing
// connection-specific fields; any message containing connection-specific
// fields MUST be treated as malformed."
//
// "The only exception to this is the TE header field, which MAY be present in
// an HTTP/3 request header; when it is, it MUST NOT contain any value other
// than "trailers"."
func hasDisallowedConnectionHeader(h http.Header) bool {
	neverAllowed := []string{
		"Connection",
		"Keep-Alive",
		"Proxy-Connection",
		"Transfer-Encoding",
		"Upgrade",
	}
	for _, k := range neverAllowed {
		if _, ok := h[k]; ok {
			return true
		}
	}
	if te, ok := h["Te"]; ok && (len(te) != 1 || te[0] != "trailers") {
		return true
	}
	return false
}

type pseudoHeader struct {
	method    string
	scheme    string
	path      string
	authority string
}

var errHeadersTooLarge = &streamError{errH3MessageError, "headers too large"}

const headerFieldOverhead = 32 // RFC 9114 Section 4.2.2

func (sc *serverConn) parseHeader(st *stream) (http.Header, pseudoHeader, error) {
	ftype, err := st.readFrameHeader()
	if err != nil {
		return nil, pseudoHeader{}, err
	}
	if ftype != frameTypeHeaders {
		return nil, pseudoHeader{}, &streamError{errH3MessageError, "received other frames when expecting HEADERS"}
	}
	if st.lim > sc.maxHeaderBytes {
		// If the encoded headers exceed the limit, just reject the request out of hand.
		// This lets us safely check limits in the dec.decode callback below,
		// since the maximum Huffman expansion factor is only ~1.6x.
		return nil, pseudoHeader{}, errHeadersTooLarge
	}

	type headerBudget struct {
		size  int64 // Checked against MaxHeaderBytes
		count int64 // Checked against MaxHeaderValueCount
	}
	var headers, trailers headerBudget

	header := make(http.Header)
	var pHeader pseudoHeader
	var dec qpackDecoder
	var hasMethod, hasScheme, hasPath, hasAuthority bool
	if err := dec.decode(st, func(_ indexType, name, value string) error {
		var budget *headerBudget
		if name == "trailer" {
			budget = &trailers
			fieldCount := int64(strings.Count(value, ",") + 1)
			budget.count += fieldCount
			// Just do the math instead of parsing the declared trailers.
			// This does make us count whitespace against MaxHeaderBytes, but that's fine.
			budget.size += int64(len(value)) - fieldCount + 1 + fieldCount*headerFieldOverhead
		} else {
			budget = &headers
			budget.count++
			budget.size += int64(len(name)) + int64(len(value)) + headerFieldOverhead
		}
		if budget.size > sc.maxHeaderBytes {
			return errHeadersTooLarge
		}
		if budget.count > sc.maxHeaderValueCount {
			return errHeadersTooLarge
		}
		if !httpguts.ValidHeaderFieldValue(value) {
			return &streamError{errH3MessageError, "invalid field value"}
		}
		if name == "" || (name[0] == ':' && value == "") {
			// Reject 0-length pseudo-header values up front,
			// to avoid any confusion down the line between
			// "present but zero-length" and "absent".
			return &streamError{errH3MessageError, "invalid field"}
		}
		switch name {
		case ":method":
			if hasMethod {
				return &streamError{errH3MessageError, "duplicate :method"}
			}
			hasMethod = true
			pHeader.method = value
		case ":scheme":
			if hasScheme {
				return &streamError{errH3MessageError, "duplicate :scheme"}
			}
			hasScheme = true
			pHeader.scheme = value
		case ":path":
			if hasPath {
				return &streamError{errH3MessageError, "duplicate :path"}
			}
			hasPath = true
			pHeader.path = value
		case ":authority":
			if hasAuthority {
				return &streamError{errH3MessageError, "duplicate :authority"}
			}
			hasAuthority = true
			pHeader.authority = value
		default:
			if !validWireHeaderFieldName(name) {
				return &streamError{errH3MessageError, "invalid field name"}
			}
			header.Add(name, value)
		}
		return nil
	}); err != nil {
		return nil, pseudoHeader{}, err
	}
	if err := st.endFrame(); err != nil {
		return nil, pseudoHeader{}, err
	}
	if hasDisallowedConnectionHeader(header) {
		return nil, pseudoHeader{}, &streamError{errH3MessageError, "invalid connection-related header"}
	}

	// "All HTTP/3 requests MUST include exactly one value for the :method,
	// :scheme, and :path pseudo-header fields, unless the request is a CONNECT
	// request"
	//
	// "A CONNECT request MUST be constructed as follows:
	// - The :method pseudo-header field is set to "CONNECT"
	// - The :scheme and :path pseudo-header fields are omitted
	// - The :authority pseudo-header field contains the host and port to connect to"
	if !hasMethod {
		return nil, pseudoHeader{}, &streamError{errH3MessageError, "missing :method"}
	}
	if pHeader.method != "CONNECT" && (!hasScheme || !hasPath) {
		return nil, pseudoHeader{}, &streamError{errH3MessageError, "missing :scheme or :path for non-CONNECT requests"}
	}
	if pHeader.method == "CONNECT" && (hasScheme || hasPath || !hasAuthority) {
		return nil, pseudoHeader{}, &streamError{
			errH3MessageError, "CONNECT request must only have :method and :authority pseudo-headers",
		}
	}
	return header, pHeader, nil
}

func (sc *serverConn) sendGoaway() {
	sc.mu.Lock()
	if sc.goawaySent || sc.controlStream == nil {
		sc.mu.Unlock()
		return
	}
	sc.goawaySent = true
	sc.mu.Unlock()

	// No lock in this section in case writing to stream blocks. This is safe
	// since sc.maxRequestStreamID is only updated when sc.goawaySent is false.
	sc.controlStream.writeVarint(int64(frameTypeGoaway))
	sc.controlStream.writeVarint(int64(sizeVarint(uint64(sc.maxRequestStreamID))))
	sc.controlStream.writeVarint(sc.maxRequestStreamID)
	sc.controlStream.Flush()
}

// requestShouldGoAway returns true if st has a stream ID that is equal or
// greater than the ID we have sent in a GOAWAY frame, if any.
func (sc *serverConn) requestShouldGoaway(st *stream) bool {
	sc.mu.Lock()
	defer sc.mu.Unlock()
	if sc.goawaySent {
		return st.stream.ID() >= sc.maxRequestStreamID
	} else {
		sc.maxRequestStreamID = max(sc.maxRequestStreamID, st.stream.ID())
		return false
	}
}

func (sc *serverConn) newResponseWriter(st *stream, hasBody bool) *responseWriter {
	return &responseWriter{
		st:             st,
		headers:        make(http.Header),
		trailer:        make(http.Header),
		bb:             make(bodyBuffer, 0, defaultBodyBufferCap),
		cannotHaveBody: !hasBody,
		bw: &bodyWriter{
			st:     st,
			remain: -1,
			flush:  false,
			name:   "response",
			enc:    &sc.enc,
		},
	}
}

func (sc *serverConn) handleRequestStream(st *stream) error {
	if sc.requestShouldGoaway(st) {
		return &streamError{
			code:    errH3RequestRejected,
			message: "GOAWAY request with equal or lower ID than the stream has been sent",
		}
	}

	readStartTime := time.Now()
	if t := sc.srv.readHeaderTimeout(); t > 0 {
		st.readDeadline.set(readStartTime.Add(t))
	}
	header, pHeader, err := sc.parseHeader(st)
	if err != nil {
		if errors.Is(err, os.ErrDeadlineExceeded) {
			return &streamError{
				code:    errH3RequestRejected,
				message: "exceeded deadline while parsing header",
			}
		}
		// To be consistent with HTTP/1 and HTTP/2, send status 431 when
		// headers are too large, rather than just resetting the stream.
		if err == errHeadersTooLarge {
			if t := sc.srv.writeTimeout(); t > 0 {
				st.writeDeadline.set(time.Now().Add(t))
			}
			rw := sc.newResponseWriter(st, false)
			rw.WriteHeader(http.StatusRequestHeaderFieldsTooLarge)
			return rw.close()
		}
		return err
	}

	if t := sc.srv.readTimeout(); t > 0 {
		st.readDeadline.set(readStartTime.Add(t))
	} else {
		st.readDeadline.set(time.Time{})
	}
	reqInfo := httpcommon.NewServerRequest(httpcommon.ServerRequestParam{
		Method:    pHeader.method,
		Scheme:    pHeader.scheme,
		Authority: pHeader.authority,
		Path:      pHeader.path,
		Header:    header,
	})
	if reqInfo.InvalidReason != "" {
		return &streamError{
			code:    errH3MessageError,
			message: reqInfo.InvalidReason,
		}
	}

	contentLength := int64(-1)
	if n, err := strconv.ParseUint(header.Get("Content-Length"), 10, 63); err == nil {
		contentLength = int64(n)
	}

	// TODO: Similar to HTTP/2, we probably should also cancel the ctx when the
	// peer cancels the request stream (STOP_SENDING). This is not yet possible
	// with the current API of the quic package.
	ctx, cancel := context.WithCancel(sc.baseCtx)
	defer cancel()
	req := (&http.Request{
		Proto:         "HTTP/3.0",
		Method:        pHeader.method,
		Host:          reqInfo.Host,
		URL:           reqInfo.URL,
		RequestURI:    reqInfo.RequestURI,
		Trailer:       reqInfo.Trailer,
		ProtoMajor:    3,
		RemoteAddr:    sc.qconn.RemoteAddr().String(),
		Header:        header,
		ContentLength: contentLength,
		TLS:           sc.tlsState,
	}).WithContext(ctx)

	rw := sc.newResponseWriter(st, req.Method != "HEAD")

	if contentLength != 0 || len(reqInfo.Trailer) != 0 {
		req.Body = &serverRequestReader{
			rw: rw,
			br: bodyReader{
				st:                  st,
				remain:              contentLength,
				trailer:             reqInfo.Trailer,
				filterTrailer:       true,
				maxHeaderBytes:      sc.maxHeaderBytes,
				maxHeaderValueCount: sc.maxHeaderValueCount,
			},
			needsContinue: reqInfo.NeedsContinue,
		}
		defer req.Body.Close()
	} else {
		req.Body = http.NoBody
	}

	// TODO: handle panic coming from the HTTP handler.
	if t := sc.srv.writeTimeout(); t > 0 {
		st.writeDeadline.set(time.Now().Add(t))
	}
	sc.handler.ServeHTTP(rw, req)
	cancel()
	return rw.close()
}

// abort closes the connection with an error.
func (sc *serverConn) abort(err error) {
	if e, ok := err.(*connectionError); ok {
		sc.qconn.Abort(&quic.ConnectionCloseError{
			Code:   uint64(e.code),
			Reason: e.message,
		})
	} else {
		sc.qconn.Abort(err)
	}
}

// responseCanHaveBody reports whether a given response status code permits a
// body. See RFC 7230, section 3.3.
func responseCanHaveBody(status int) bool {
	switch {
	case status >= 100 && status <= 199:
		return false
	case status == 204:
		return false
	case status == 304:
		return false
	}
	return true
}

// trailerPrefix is a magic prefix for [responseWriter.Header] map keys that,
// if present, signals that the map entry is actually for the response
// trailers, and not the response headers. See [net/http.TrailerPrefix] for
// details.
const trailerPrefix = "Trailer:"

type responseWriter struct {
	st             *stream
	bw             *bodyWriter
	mu             sync.Mutex
	headers        http.Header
	snapHeaders    http.Header // Snapshot of headers at WriteHeader time
	trailer        http.Header
	bb             bodyBuffer
	wroteHeader    bool  // Non-1xx header has been (logically) written.
	statusCode     int   // Non-1xx status of the response that will be sent in HEADERS frame. Zero means none has been set.
	sent100        bool  // Status 100 has been sent by the server.
	cannotHaveBody bool  // Response should not have a body (e.g. response to a HEAD request).
	bodyLenLeft    int64 // How much of the content body is left to be sent, set via "Content-Length" header. -1 if unknown.
}

func (rw *responseWriter) Header() http.Header {
	return rw.headers
}

// prepareTrailerForWriteLocked populates any pre-declared trailer header with
// its value, and passes it to bodyWriter so it can be written after body EOF.
// Caller must hold rw.mu.
func (rw *responseWriter) prepareTrailerForWriteLocked() {
	for name := range rw.trailer {
		if val, ok := rw.headers[name]; ok {
			rw.trailer[name] = val
		} else {
			delete(rw.trailer, name)
		}
	}
	for name, vals := range rw.headers {
		if name, found := strings.CutPrefix(name, trailerPrefix); found {
			name = textproto.CanonicalMIMEHeaderKey(textproto.TrimString(name))
			rw.trailer[name] = vals
		}
	}
	if len(rw.trailer) > 0 {
		rw.bw.trailer = rw.trailer
	}
}

// writeHeaderLockedOnce writes the final response header. If rw.wroteHeader is
// true, calling this method is a no-op. Sending informational status headers
// should be done using writeInfoHeaderLocked, rather than this method.
// Caller must hold rw.mu.
func (rw *responseWriter) writeHeaderLockedOnce() {
	if rw.wroteHeader {
		return
	}
	if !responseCanHaveBody(rw.statusCode) {
		rw.cannotHaveBody = true
	}
	// If there is any Trailer declared, save them so we know which trailers
	// have been pre-declared. Also, write back the extracted value, which is
	// canonicalized, for consistency.
	if _, ok := rw.snapHeaders["Trailer"]; ok {
		extractTrailerFromHeader(rw.snapHeaders, rw.trailer)
		rw.snapHeaders.Set("Trailer", strings.Join(slices.Sorted(maps.Keys(rw.trailer)), ", "))
	}

	rw.bb.inferHeader(rw.snapHeaders, rw.statusCode)
	encHeaders := rw.bw.enc.encode(func(f func(itype indexType, name, value string)) {
		f(mayIndex, ":status", strconv.Itoa(rw.statusCode))
		for name, values := range rw.snapHeaders {
			if !httpguts.ValidHeaderFieldName(name) {
				continue
			}
			for _, val := range values {
				if !httpguts.ValidHeaderFieldValue(val) {
					continue
				}
				// Issue #71374: Consider supporting never-indexed fields.
				f(mayIndex, name, val)
			}
		}
	})

	rw.st.writeVarint(int64(frameTypeHeaders))
	rw.st.writeVarint(int64(len(encHeaders)))
	rw.st.Write(encHeaders)
	rw.wroteHeader = true
}

// writeHeaderLocked writes informational status headers (i.e. status 1XX).
// If a non-informational status header has been written via
// writeHeaderLockedOnce, this method is a no-op.
// Caller must hold rw.mu.
func (rw *responseWriter) writeHeaderLocked(statusCode int) {
	if rw.wroteHeader {
		return
	}
	if statusCode == 100 {
		if rw.sent100 {
			return
		}
		rw.sent100 = true
	}
	encHeaders := rw.bw.enc.encode(func(f func(itype indexType, name, value string)) {
		f(mayIndex, ":status", strconv.Itoa(statusCode))
		for name, values := range rw.headers {
			if name == "Content-Length" || name == "Transfer-Encoding" {
				continue
			}
			if !httpguts.ValidHeaderFieldName(name) {
				continue
			}
			for _, val := range values {
				if !httpguts.ValidHeaderFieldValue(val) {
					continue
				}
				// Issue #71374: Consider supporting never-indexed fields.
				f(mayIndex, name, val)
			}
		}
	})
	rw.st.writeVarint(int64(frameTypeHeaders))
	rw.st.writeVarint(int64(len(encHeaders)))
	rw.st.Write(encHeaders)
}

func isInfoStatus(status int) bool {
	return status >= 100 && status < 200
}

// checkWriteHeaderCode is a copy of net/http's checkWriteHeaderCode.
func checkWriteHeaderCode(code int) {
	// Issue 22880: require valid WriteHeader status codes.
	// For now we only enforce that it's three digits.
	// In the future we might block things over 599 (600 and above aren't defined
	// at http://httpwg.org/specs/rfc7231.html#status.codes).
	// But for now any three digits.
	//
	// We used to send "HTTP/1.1 000 0" on the wire in responses but there's
	// no equivalent bogus thing we can realistically send in HTTP/3,
	// so we'll consistently panic instead and help people find their bugs
	// early. (We can't return an error from WriteHeader even if we wanted to.)
	if code < 100 || code > 999 {
		panic(fmt.Sprintf("invalid WriteHeader code %v", code))
	}
}

func (rw *responseWriter) WriteHeader(statusCode int) {
	// TODO: handle sending informational status headers (e.g. 103).
	rw.mu.Lock()
	defer rw.mu.Unlock()
	if rw.statusCode != 0 {
		return
	}
	checkWriteHeaderCode(statusCode)

	// Informational headers can be sent multiple times, and should be flushed
	// immediately.
	if isInfoStatus(statusCode) {
		rw.writeHeaderLocked(statusCode)
		rw.st.Flush()
		return
	}

	// Non-informational headers should only be set once, and should be
	// buffered.
	if n, err := strconv.ParseUint(rw.headers.Get("Content-Length"), 10, 63); err == nil {
		rw.bodyLenLeft = int64(n)
	} else {
		rw.headers.Del("Content-Length")
		rw.bodyLenLeft = -1 // Unknown.
	}
	rw.statusCode = statusCode
	rw.snapHeaders = rw.headers.Clone()
}

// trimWriteLocked trims a byte slice, b, such that the length of b will not
// exceed rw.bodyLenLeft. This method will update rw.bodyLenLeft when trimming
// b, and will also return whether b was trimmed or not.
// Caller must hold rw.mu.
func (rw *responseWriter) trimWriteLocked(b []byte) ([]byte, bool) {
	if rw.bodyLenLeft < 0 {
		return b, false
	}
	n := min(int64(len(b)), rw.bodyLenLeft)
	rw.bodyLenLeft -= n
	return b[:n], n != int64(len(b))
}

func (rw *responseWriter) Write(b []byte) (n int, err error) {
	// Calling Write implicitly calls WriteHeader(200) if WriteHeader has not
	// been called before.
	rw.WriteHeader(http.StatusOK)
	rw.mu.Lock()
	defer rw.mu.Unlock()

	if rw.statusCode == http.StatusNotModified {
		return 0, http.ErrBodyNotAllowed
	}

	b, trimmed := rw.trimWriteLocked(b)
	if trimmed {
		defer func() {
			err = http.ErrContentLength
		}()
	}

	// If b fits entirely in our body buffer, save it to the buffer and return
	// early so we can coalesce small writes.
	// As a special case, we always want to save b to the buffer even when b is
	// big if we had yet to write our header, so we can infer headers like
	// "Content-Type" with as much information as possible.
	initialBLen := len(b)
	initialBufLen := len(rw.bb)
	if !rw.wroteHeader || len(b) <= cap(rw.bb)-len(rw.bb) {
		b = rw.bb.write(b)
		if len(b) == 0 {
			return initialBLen, nil
		}
	}

	// Reaching this point means that our buffer has been sufficiently filled.
	// Therefore, we now want to:
	// 1. Infer and write response headers based on our body buffer, if not
	// done yet.
	// 2. Write our body buffer and the rest of b (if any).
	// 3. Reset the current body buffer so it can be used again.
	rw.writeHeaderLockedOnce()
	if rw.cannotHaveBody {
		return initialBLen, nil
	}
	if n, err := rw.bw.write(rw.bb, b); err != nil {
		return max(0, n-initialBufLen), err
	}
	rw.bb.discard()
	return initialBLen, nil
}

func (rw *responseWriter) SetReadDeadline(deadline time.Time) error {
	rw.st.readDeadline.set(deadline)
	return nil
}

func (rw *responseWriter) SetWriteDeadline(deadline time.Time) error {
	rw.st.writeDeadline.set(deadline)
	return nil
}

func (rw *responseWriter) EnableFullDuplex() error {
	return nil
}

func (rw *responseWriter) Flush() { rw.FlushError() }
func (rw *responseWriter) FlushError() error {
	// Calling Flush implicitly calls WriteHeader(200) if WriteHeader has not
	// been called before.
	rw.WriteHeader(http.StatusOK)
	rw.mu.Lock()
	defer rw.mu.Unlock()
	rw.writeHeaderLockedOnce()
	if !rw.cannotHaveBody {
		if _, err := rw.bw.Write(rw.bb); err != nil {
			return err
		}
		rw.bb.discard()
	}
	return rw.st.Flush()
}

func (rw *responseWriter) close() error {
	if errors.Is(rw.st.writeDeadline.err(), os.ErrDeadlineExceeded) {
		return &streamError{
			code:    errH3RequestCancelled,
			message: "exceeded deadline while writing response",
		}
	}

	retErr := rw.FlushError()
	rw.mu.Lock()
	defer rw.mu.Unlock()
	rw.prepareTrailerForWriteLocked()
	if err := rw.bw.Close(); retErr == nil {
		retErr = err
	}
	if errors.Is(retErr, os.ErrDeadlineExceeded) {
		return &streamError{
			code:    errH3RequestCancelled,
			message: retErr.Error(),
		}
	}
	return retErr
}

// defaultBodyBufferCap is the default number of bytes of body that we are
// willing to save in a buffer for the sake of inferring headers and coalescing
// small writes. 512 was chosen to be consistent with how much
// http.DetectContentType is willing to read.
const defaultBodyBufferCap = 512

// bodyBuffer is a buffer used to store body content of a response.
type bodyBuffer []byte

// write writes b to the buffer. It returns a new slice of b, which contains
// any remaining data that could not be written to the buffer, if any.
func (bb *bodyBuffer) write(b []byte) []byte {
	n := min(len(b), cap(*bb)-len(*bb))
	*bb = append(*bb, b[:n]...)
	return b[n:]
}

// discard resets the buffer so it can be used again.
func (bb *bodyBuffer) discard() {
	*bb = (*bb)[:0]
}

// inferHeader populates h with the header values that we can infer from our
// current buffer content, if not already explicitly set. This method should be
// called only once with as much body content as possible in the buffer, before
// a HEADERS frame is sent, and before discard has been called. Doing so
// properly is the responsibility of the caller.
func (bb *bodyBuffer) inferHeader(h http.Header, status int) {
	if _, ok := h["Date"]; !ok {
		h.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	}
	// If the Content-Encoding is non-blank, we shouldn't
	// sniff the body. See Issue golang.org/issue/31753.
	hasCE := len(h.Get("Content-Encoding")) > 0
	_, hasCT := h["Content-Type"]
	if !hasCE && !hasCT && responseCanHaveBody(status) && len(*bb) > 0 {
		h.Set("Content-Type", http.DetectContentType(*bb))
	}
	// We can technically infer Content-Length too here, as long as the entire
	// response body fits within hi.buf and does not require flushing. However,
	// we have chosen not to do so for now as Content-Length is not very
	// important for HTTP/3, and such inconsistent behavior might be confusing.
}

// serverRequestReader wraps around bodyReader, allowing Read and Close calls
// done from within a server handler to coordinate correctly with the
// responseWriter; for example, sending status 100 on Read when appropriate.
type serverRequestReader struct {
	rw            *responseWriter
	br            bodyReader
	needsContinue bool
}

// maybeSendContinue attempts to send a 100 Continue status code. It
// ensures that status 100 will only be sent once and when appropriate. If a
// non-1xx header has been set before 100 was ever set, it also ensures that
// all subsequent Read will fail.
func (srr *serverRequestReader) maybeSendContinue() {
	if !srr.needsContinue {
		return
	}
	srr.rw.mu.Lock()
	defer srr.rw.mu.Unlock()
	if srr.rw.sent100 {
		return
	}
	if srr.rw.statusCode != 0 {
		srr.br.Close()
		return
	}
	srr.rw.writeHeaderLocked(100)
	srr.rw.st.Flush()
}

func (srr *serverRequestReader) Read(p []byte) (int, error) {
	srr.maybeSendContinue()
	return srr.br.Read(p)
}

func (srr *serverRequestReader) Close() error {
	return srr.br.Close()
}
