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

import (
	"context"
	"errors"
	"fmt"
	"net"
	"net/http/httptrace"
	"net/url"
	"sync"
)

// A ClientConn is a client connection to an HTTP server.
//
// Unlike a [Transport], a ClientConn represents a single connection.
// Most users should use a Transport rather than creating client connections directly.
type ClientConn struct {
	cc genericClientConn

	stateHookMu      sync.Mutex
	userStateHook    func(*ClientConn)
	stateHookRunning bool
	lastAvailable    int
	lastInFlight     int
	lastClosed       bool
}

// newClientConner is the interface implemented by HTTP/2 transports to create new client conns.
//
// The http package (this package) needs a way to ask the http2 package to
// create a client connection.
//
// Transport.TLSNextProto["h2"] contains a function which appears to do this,
// but for historical reasons it does not: The TLSNextProto function adds a
// *tls.Conn to the http2.Transport's connection pool and returns a RoundTripper
// which is backed by that connection pool. NewClientConn needs a way to get a
// single client connection out of the http2 package.
//
// The http2 package registers a RoundTripper with Transport.RegisterProtocol.
// If this RoundTripper implements newClientConner, then Transport.NewClientConn will use
// it to create new HTTP/2 client connections.
type newClientConner interface {
	// NewClientConn creates a new client connection from a net.Conn.
	//
	// The RoundTripper returned by NewClientConn must implement genericClientConn.
	// (We don't define NewClientConn as returning genericClientConn,
	// because either we'd need to make genericClientConn an exported type
	// or define it as a type alias. Neither is particularly appealing.)
	//
	// The state hook passed here is the internal state hook
	// (ClientConn.maybeRunStateHook). The internal state hook calls
	// the user state hook (if any), which is set by the user with
	// ClientConn.SetStateHook.
	//
	// The client connection should arrange to call the internal state hook
	// when the connection closes, when requests complete, and when the
	// connection concurrency limit changes.
	//
	// The client connection must call the internal state hook when the connection state
	// changes asynchronously, such as when a request completes.
	//
	// The internal state hook need not be called after synchronous changes to the state:
	// Close, Reserve, Release, and RoundTrip calls which don't start a request
	// do not need to call the hook.
	//
	// The general idea is that if we call (for example) Close,
	// we know that the connection state has probably changed and we
	// don't need the state hook to tell us that.
	// However, if the connection closes asynchronously
	// (because, for example, the other end of the conn closed it),
	// the state hook needs to inform us.
	NewClientConn(nc net.Conn, internalStateHook func()) (RoundTripper, error)
}

// genericClientConn is an interface implemented by HTTP/2 client conns
// returned from newClientConner.NewClientConn.
//
// See the newClientConner doc comment for more information.
type genericClientConn interface {
	Close() error
	Err() error
	RoundTrip(req *Request) (*Response, error)
	Reserve() error
	Release()
	Available() int
	InFlight() int
}

// NewClientConn creates a new client connection to the given address.
//
// If scheme is "http", the connection is unencrypted.
// If scheme is "https", the connection uses TLS.
//
// The protocol used for the new connection is determined by the scheme,
// Transport.Protocols configuration field, and protocols supported by the
// server. See Transport.Protocols for more details.
//
// If Transport.Proxy is set and indicates that a request sent to the given
// address should use a proxy, the new connection uses that proxy.
//
// NewClientConn always creates a new connection,
// even if the Transport has an existing cached connection to the given host.
//
// The new connection is not added to the Transport's connection cache,
// and will not be used by [Transport.RoundTrip].
// It does not count against the MaxIdleConns and MaxConnsPerHost limits.
//
// The caller is responsible for closing the new connection.
func (t *Transport) NewClientConn(ctx context.Context, scheme, address string) (*ClientConn, error) {
	t.nextProtoOnce.Do(t.onceSetNextProtoDefaults)

	if t.h2Config != nil {
		// Handle x/net/http2.Transport.NewClientConn passing us a net.Conn
		// to create a ClientConn from.
		if cc, err := t.http2NewClientConnFromContext(ctx); err != errors.ErrUnsupported {
			return cc, err
		}
	}

	switch scheme {
	case "http", "https":
	default:
		return nil, fmt.Errorf("net/http: invalid scheme %q", scheme)
	}

	host, port, err := net.SplitHostPort(address)
	if err != nil {
		return nil, err
	}
	if port == "" {
		port = schemePort(scheme)
	}

	var proxyURL *url.URL
	if t.Proxy != nil {
		// Transport.Proxy takes a *Request, so create a fake one to pass it.
		req := &Request{
			ctx:    ctx,
			Method: "GET",
			URL: &url.URL{
				Scheme: scheme,
				Host:   host,
				Path:   "/",
			},
			Proto:      "HTTP/1.1",
			ProtoMajor: 1,
			ProtoMinor: 1,
			Header:     make(Header),
			Body:       NoBody,
			Host:       host,
		}
		var err error
		proxyURL, err = t.Proxy(req)
		if err != nil {
			return nil, err
		}
	}

	cm := connectMethod{
		targetScheme: scheme,
		targetAddr:   net.JoinHostPort(host, port),
		proxyURL:     proxyURL,
	}

	// The state hook is a bit tricky:
	// The persistConn has a state hook which calls ClientConn.maybeRunStateHook,
	// which in turn calls the user-provided state hook (if any).
	//
	// ClientConn.maybeRunStateHook handles debouncing hook calls for both
	// HTTP/1 and HTTP/2.
	//
	// Since there's no need to change the persistConn's hook, we set it at creation time.
	cc := &ClientConn{}
	const isClientConn = true
	pconn, err := t.dialConn(ctx, cm, isClientConn, cc.maybeRunStateHook)
	if err != nil {
		return nil, err
	}

	// Note that cc.maybeRunStateHook may have been called
	// in the short window between dialConn and now.
	// This is fine.
	cc.stateHookMu.Lock()
	defer cc.stateHookMu.Unlock()
	if pconn.alt != nil {
		// If pconn.alt is set, this is a connection implemented in another package
		// (probably x/net/http2) or the bundled copy in h2_bundle.go.
		gc, ok := pconn.alt.(genericClientConn)
		if !ok {
			return nil, errors.New("http: NewClientConn returned something that is not a ClientConn")
		}
		cc.cc = gc
		cc.lastAvailable = gc.Available()
	} else {
		// This is an HTTP/1 connection.
		pconn.availch = make(chan struct{}, 1)
		pconn.availch <- struct{}{}
		cc.cc = http1ClientConn{pconn}
		cc.lastAvailable = 1
	}
	return cc, nil
}

// Close closes the connection.
// Outstanding RoundTrip calls are interrupted.
func (cc *ClientConn) Close() error {
	defer cc.maybeRunStateHook()
	return cc.cc.Close()
}

// Err reports any fatal connection errors.
// It returns nil if the connection is usable.
// If it returns non-nil, the connection can no longer be used.
func (cc *ClientConn) Err() error {
	return cc.cc.Err()
}

func validateClientConnRequest(req *Request) error {
	if req.URL == nil {
		return errors.New("http: nil Request.URL")
	}
	if req.Header == nil {
		return errors.New("http: nil Request.Header")
	}
	// Validate the outgoing headers.
	if err := validateHeaders(req.Header); err != "" {
		return fmt.Errorf("http: invalid header %s", err)
	}
	// Validate the outgoing trailers too.
	if err := validateHeaders(req.Trailer); err != "" {
		return fmt.Errorf("http: invalid trailer %s", err)
	}
	if req.Method != "" && !validMethod(req.Method) {
		return fmt.Errorf("http: invalid method %q", req.Method)
	}
	if req.URL.Host == "" {
		return errors.New("http: no Host in request URL")
	}
	return nil
}

// RoundTrip implements the [RoundTripper] interface.
//
// The request is sent on the client connection,
// regardless of the URL being requested or any proxy settings.
//
// If the connection is at its concurrency limit,
// RoundTrip waits for the connection to become available
// before sending the request.
func (cc *ClientConn) RoundTrip(req *Request) (*Response, error) {
	defer cc.maybeRunStateHook()
	if req.URL == nil && req.Method == ":ping" {
		// Undocumented feature for sending a PING frame to a HTTP/2 connection,
		// included to support x/net/http2.ClientConn.Ping.
		pinger, ok := cc.cc.(interface {
			Ping(context.Context) error
		})
		if !ok {
			return nil, errors.New("http: ClientConn does not support PING")
		}
		return nil, pinger.Ping(req.Context())
	}
	if err := validateClientConnRequest(req); err != nil {
		cc.Release()
		return nil, err
	}
	return cc.cc.RoundTrip(req)
}

// Available reports the number of requests that may be sent
// to the connection without blocking.
// It returns 0 if the connection is closed.
func (cc *ClientConn) Available() int {
	return cc.cc.Available()
}

// InFlight reports the number of requests in flight,
// including reserved requests.
// It returns 0 if the connection is closed.
func (cc *ClientConn) InFlight() int {
	return cc.cc.InFlight()
}

// Reserve reserves a concurrency slot on the connection.
// If Reserve returns nil, one additional RoundTrip call may be made
// without waiting for an existing request to complete.
//
// The reserved concurrency slot is accounted as an in-flight request.
// A successful call to RoundTrip will decrement the Available count
// and increment the InFlight count.
//
// Each successful call to Reserve should be followed by exactly one call
// to RoundTrip or Release, which will consume or release the reservation.
//
// If the connection is closed or at its concurrency limit,
// Reserve returns an error.
func (cc *ClientConn) Reserve() error {
	defer cc.maybeRunStateHook()
	return cc.cc.Reserve()
}

// Release releases an unused concurrency slot reserved by Reserve.
// If there are no reserved concurrency slots, it has no effect.
func (cc *ClientConn) Release() {
	defer cc.maybeRunStateHook()
	cc.cc.Release()
}

// shouldRunStateHook returns the user's state hook if we should call it,
// or nil if we don't need to call it at this time.
func (cc *ClientConn) shouldRunStateHook(stopRunning bool) func(*ClientConn) {
	cc.stateHookMu.Lock()
	defer cc.stateHookMu.Unlock()
	if cc.cc == nil {
		return nil
	}
	if stopRunning {
		cc.stateHookRunning = false
	}
	if cc.userStateHook == nil {
		return nil
	}
	if cc.stateHookRunning {
		return nil
	}
	var (
		available = cc.Available()
		inFlight  = cc.InFlight()
		closed    = cc.Err() != nil
	)
	var hook func(*ClientConn)
	if available > cc.lastAvailable || inFlight < cc.lastInFlight || closed != cc.lastClosed {
		hook = cc.userStateHook
		cc.stateHookRunning = true
	}
	cc.lastAvailable = available
	cc.lastInFlight = inFlight
	cc.lastClosed = closed
	return hook
}

func (cc *ClientConn) maybeRunStateHook() {
	hook := cc.shouldRunStateHook(false)
	if hook == nil {
		return
	}
	// Run the hook synchronously.
	//
	// This means that if, for example, the user calls resp.Body.Close to finish a request,
	// the Close call will synchronously run the hook, giving the hook the chance to
	// return the ClientConn to a connection pool before the next request is made.
	hook(cc)
	// The connection state may have changed while the hook was running,
	// in which case we need to run it again.
	//
	// If we do need to run the hook again, do so in a new goroutine to avoid blocking
	// the current goroutine indefinitely.
	hook = cc.shouldRunStateHook(true)
	if hook != nil {
		go func() {
			for hook != nil {
				hook(cc)
				hook = cc.shouldRunStateHook(true)
			}
		}()
	}
}

// SetStateHook arranges for f to be called when the state of the connection changes.
// At most one call to f is made at a time.
// If the connection's state has changed since it was created,
// f is called immediately in a separate goroutine.
// f may be called synchronously from RoundTrip or Response.Body.Close.
//
// If SetStateHook is called multiple times, the new hook replaces the old one.
// If f is nil, no further calls will be made to f after SetStateHook returns.
//
// f is called when Available increases (more requests may be sent on the connection),
// InFlight decreases (existing requests complete), or Err begins returning non-nil
// (the connection is no longer usable).
func (cc *ClientConn) SetStateHook(f func(*ClientConn)) {
	cc.stateHookMu.Lock()
	cc.userStateHook = f
	cc.stateHookMu.Unlock()
	cc.maybeRunStateHook()
}

// http1ClientConn is a genericClientConn implementation backed by
// an HTTP/1 *persistConn (pconn.alt is nil).
type http1ClientConn struct {
	pconn *persistConn
}

func (cc http1ClientConn) RoundTrip(req *Request) (*Response, error) {
	ctx := req.Context()
	trace := httptrace.ContextClientTrace(ctx)

	// Convert Request.Cancel into context cancellation.
	ctx, cancel := context.WithCancelCause(req.Context())
	if req.Cancel != nil {
		go awaitLegacyCancel(ctx, cancel, req)
	}

	treq := &transportRequest{Request: req, trace: trace, ctx: ctx, cancel: cancel}
	resp, err := cc.pconn.roundTrip(treq)
	if err != nil {
		return nil, err
	}
	resp.Request = req
	return resp, nil
}

func (cc http1ClientConn) Close() error {
	cc.pconn.close(errors.New("ClientConn closed"))
	return nil
}

func (cc http1ClientConn) Err() error {
	select {
	case <-cc.pconn.closech:
		return cc.pconn.closed
	default:
		return nil
	}
}

func (cc http1ClientConn) Available() int {
	cc.pconn.mu.Lock()
	defer cc.pconn.mu.Unlock()
	if cc.pconn.closed != nil || cc.pconn.reserved || cc.pconn.inFlight {
		return 0
	}
	return 1
}

func (cc http1ClientConn) InFlight() int {
	cc.pconn.mu.Lock()
	defer cc.pconn.mu.Unlock()
	if cc.pconn.closed == nil && (cc.pconn.reserved || cc.pconn.inFlight) {
		return 1
	}
	return 0
}

func (cc http1ClientConn) Reserve() error {
	cc.pconn.mu.Lock()
	defer cc.pconn.mu.Unlock()
	if cc.pconn.closed != nil {
		return cc.pconn.closed
	}
	select {
	case <-cc.pconn.availch:
	default:
		return errors.New("connection is unavailable")
	}
	cc.pconn.reserved = true
	return nil
}

func (cc http1ClientConn) Release() {
	cc.pconn.mu.Lock()
	defer cc.pconn.mu.Unlock()
	if cc.pconn.reserved {
		select {
		case cc.pconn.availch <- struct{}{}:
		default:
			panic("cannot release reservation")
		}
		cc.pconn.reserved = false
	}
}
