// 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)
	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()
}
