// 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"

	"golang.org/x/net/http/httpguts"
	"net/http/internal/httpcommon"
	"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

	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) {
	sc := &serverConn{
		qconn:          qconn,
		srv:            s,
		baseCtx:        baseCtx,
		handler:        h,
		maxHeaderBytes: int64(s.srv1.MaxHeaderBytes),
		// TODO: When we only support go1.27.
		//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)
	}
	// TODO: When we only support go1.27.
	// 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
}

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{}, &streamError{errH3RequestRejected, "headers too large"}
	}
	header := make(http.Header)
	valueCount := int64(0)
	totalSize := int64(0)
	var pHeader pseudoHeader
	var dec qpackDecoder
	var hasMethod, hasScheme, hasPath, hasAuthority bool
	if err := dec.decode(st, func(_ indexType, name, value string) error {
		totalSize += int64(len(name)) + int64(len(value)) + 32 // RFC 9114 Section 4.2.2
		valueCount++
		if totalSize > sc.maxHeaderBytes {
			return &streamError{errH3RequestRejected, "headers too large"}
		}
		// TODO: When we only support go1.27.
		//if valueCount > sc.maxHeaderValueCount {
		//	return &streamError{errH3RequestRejected, "headers too large"}
		//}
		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) 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",
			}
		}
		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)
	}

	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,
	}).WithContext(sc.baseCtx)

	rw := &responseWriter{
		st:             st,
		headers:        make(http.Header),
		trailer:        make(http.Header),
		bb:             make(bodyBuffer, 0, defaultBodyBufferCap),
		cannotHaveBody: req.Method == "HEAD",
		bw: &bodyWriter{
			st:     st,
			remain: -1,
			flush:  false,
			name:   "response",
			enc:    &sc.enc,
		},
	}

	if contentLength != 0 || len(reqInfo.Trailer) != 0 {
		req.Body = &serverRequestReader{
			rw: rw,
			br: bodyReader{
				st:            st,
				remain:        contentLength,
				trailer:       reqInfo.Trailer,
				filterTrailer: true,
			},
			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)
	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 {
		_, err := rw.bw.Write(rw.bb)
		rw.bb.discard()
		if err != nil {
			return err
		}
	}
	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()
}
