// Copyright 2009 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 httputil

import (
	
	
	
	
	
	
	
)

var (
	// Deprecated: No longer used.
	ErrPersistEOF = &http.ProtocolError{ErrorString: "persistent connection closed"}

	// Deprecated: No longer used.
	ErrClosed = &http.ProtocolError{ErrorString: "connection closed by user"}

	// Deprecated: No longer used.
	ErrPipeline = &http.ProtocolError{ErrorString: "pipeline error"}
)

// This is an API usage error - the local side is closed.
// ErrPersistEOF (above) reports that the remote side is closed.
var errClosed = errors.New("i/o operation on closed connection")

// ServerConn is an artifact of Go's early HTTP implementation.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Server in package [net/http] instead.
type ServerConn struct {
	mu              sync.Mutex // read-write protects the following fields
	c               net.Conn
	r               *bufio.Reader
	re, we          error // read/write errors
	lastbody        io.ReadCloser
	nread, nwritten int
	pipereq         map[*http.Request]uint

	pipe textproto.Pipeline
}

// NewServerConn is an artifact of Go's early HTTP implementation.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Server in package [net/http] instead.
func ( net.Conn,  *bufio.Reader) *ServerConn {
	if  == nil {
		 = bufio.NewReader()
	}
	return &ServerConn{c: , r: , pipereq: make(map[*http.Request]uint)}
}

// Hijack detaches the [ServerConn] and returns the underlying connection as well
// as the read-side bufio which may have some left over data. Hijack may be
// called before Read has signaled the end of the keep-alive logic. The user
// should not call Hijack while [ServerConn.Read] or [ServerConn.Write] is in progress.
func ( *ServerConn) () (net.Conn, *bufio.Reader) {
	.mu.Lock()
	defer .mu.Unlock()
	 := .c
	 := .r
	.c = nil
	.r = nil
	return , 
}

// Close calls [ServerConn.Hijack] and then also closes the underlying connection.
func ( *ServerConn) () error {
	,  := .Hijack()
	if  != nil {
		return .Close()
	}
	return nil
}

// Read returns the next request on the wire. An [ErrPersistEOF] is returned if
// it is gracefully determined that there are no more requests (e.g. after the
// first request on an HTTP/1.0 connection, or after a Connection:close on a
// HTTP/1.1 connection).
func ( *ServerConn) () (*http.Request, error) {
	var  *http.Request
	var  error

	// Ensure ordered execution of Reads and Writes
	 := .pipe.Next()
	.pipe.StartRequest()
	defer func() {
		.pipe.EndRequest()
		if  == nil {
			.pipe.StartResponse()
			.pipe.EndResponse()
		} else {
			// Remember the pipeline id of this request
			.mu.Lock()
			.pipereq[] = 
			.mu.Unlock()
		}
	}()

	.mu.Lock()
	if .we != nil { // no point receiving if write-side broken or closed
		defer .mu.Unlock()
		return nil, .we
	}
	if .re != nil {
		defer .mu.Unlock()
		return nil, .re
	}
	if .r == nil { // connection closed by user in the meantime
		defer .mu.Unlock()
		return nil, errClosed
	}
	 := .r
	 := .lastbody
	.lastbody = nil
	.mu.Unlock()

	// Make sure body is fully consumed, even if user does not call body.Close
	if  != nil {
		// body.Close is assumed to be idempotent and multiple calls to
		// it should return the error that its first invocation
		// returned.
		 = .Close()
		if  != nil {
			.mu.Lock()
			defer .mu.Unlock()
			.re = 
			return nil, 
		}
	}

	,  = http.ReadRequest()
	.mu.Lock()
	defer .mu.Unlock()
	if  != nil {
		if  == io.ErrUnexpectedEOF {
			// A close from the opposing client is treated as a
			// graceful close, even if there was some unparse-able
			// data before the close.
			.re = ErrPersistEOF
			return nil, .re
		} else {
			.re = 
			return , 
		}
	}
	.lastbody = .Body
	.nread++
	if .Close {
		.re = ErrPersistEOF
		return , .re
	}
	return , 
}

// Pending returns the number of unanswered requests
// that have been received on the connection.
func ( *ServerConn) () int {
	.mu.Lock()
	defer .mu.Unlock()
	return .nread - .nwritten
}

// Write writes resp in response to req. To close the connection gracefully, set the
// Response.Close field to true. Write should be considered operational until
// it returns an error, regardless of any errors returned on the [ServerConn.Read] side.
func ( *ServerConn) ( *http.Request,  *http.Response) error {

	// Retrieve the pipeline ID of this request/response pair
	.mu.Lock()
	,  := .pipereq[]
	delete(.pipereq, )
	if ! {
		.mu.Unlock()
		return ErrPipeline
	}
	.mu.Unlock()

	// Ensure pipeline order
	.pipe.StartResponse()
	defer .pipe.EndResponse()

	.mu.Lock()
	if .we != nil {
		defer .mu.Unlock()
		return .we
	}
	if .c == nil { // connection closed by user in the meantime
		defer .mu.Unlock()
		return ErrClosed
	}
	 := .c
	if .nread <= .nwritten {
		defer .mu.Unlock()
		return errors.New("persist server pipe count")
	}
	if .Close {
		// After signaling a keep-alive close, any pipelined unread
		// requests will be lost. It is up to the user to drain them
		// before signaling.
		.re = ErrPersistEOF
	}
	.mu.Unlock()

	 := .Write()
	.mu.Lock()
	defer .mu.Unlock()
	if  != nil {
		.we = 
		return 
	}
	.nwritten++

	return nil
}

// ClientConn is an artifact of Go's early HTTP implementation.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use Client or Transport in package [net/http] instead.
type ClientConn struct {
	mu              sync.Mutex // read-write protects the following fields
	c               net.Conn
	r               *bufio.Reader
	re, we          error // read/write errors
	lastbody        io.ReadCloser
	nread, nwritten int
	pipereq         map[*http.Request]uint

	pipe     textproto.Pipeline
	writeReq func(*http.Request, io.Writer) error
}

// NewClientConn is an artifact of Go's early HTTP implementation.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Client or Transport in package [net/http] instead.
func ( net.Conn,  *bufio.Reader) *ClientConn {
	if  == nil {
		 = bufio.NewReader()
	}
	return &ClientConn{
		c:        ,
		r:        ,
		pipereq:  make(map[*http.Request]uint),
		writeReq: (*http.Request).Write,
	}
}

// NewProxyClientConn is an artifact of Go's early HTTP implementation.
// It is low-level, old, and unused by Go's current HTTP stack.
// We should have deleted it before Go 1.
//
// Deprecated: Use the Client or Transport in package [net/http] instead.
func ( net.Conn,  *bufio.Reader) *ClientConn {
	 := NewClientConn(, )
	.writeReq = (*http.Request).WriteProxy
	return 
}

// Hijack detaches the [ClientConn] and returns the underlying connection as well
// as the read-side bufio which may have some left over data. Hijack may be
// called before the user or Read have signaled the end of the keep-alive
// logic. The user should not call Hijack while [ClientConn.Read] or ClientConn.Write is in progress.
func ( *ClientConn) () ( net.Conn,  *bufio.Reader) {
	.mu.Lock()
	defer .mu.Unlock()
	 = .c
	 = .r
	.c = nil
	.r = nil
	return
}

// Close calls [ClientConn.Hijack] and then also closes the underlying connection.
func ( *ClientConn) () error {
	,  := .Hijack()
	if  != nil {
		return .Close()
	}
	return nil
}

// Write writes a request. An [ErrPersistEOF] error is returned if the connection
// has been closed in an HTTP keep-alive sense. If req.Close equals true, the
// keep-alive connection is logically closed after this request and the opposing
// server is informed. An ErrUnexpectedEOF indicates the remote closed the
// underlying TCP connection, which is usually considered as graceful close.
func ( *ClientConn) ( *http.Request) error {
	var  error

	// Ensure ordered execution of Writes
	 := .pipe.Next()
	.pipe.StartRequest()
	defer func() {
		.pipe.EndRequest()
		if  != nil {
			.pipe.StartResponse()
			.pipe.EndResponse()
		} else {
			// Remember the pipeline id of this request
			.mu.Lock()
			.pipereq[] = 
			.mu.Unlock()
		}
	}()

	.mu.Lock()
	if .re != nil { // no point sending if read-side closed or broken
		defer .mu.Unlock()
		return .re
	}
	if .we != nil {
		defer .mu.Unlock()
		return .we
	}
	if .c == nil { // connection closed by user in the meantime
		defer .mu.Unlock()
		return errClosed
	}
	 := .c
	if .Close {
		// We write the EOF to the write-side error, because there
		// still might be some pipelined reads
		.we = ErrPersistEOF
	}
	.mu.Unlock()

	 = .writeReq(, )
	.mu.Lock()
	defer .mu.Unlock()
	if  != nil {
		.we = 
		return 
	}
	.nwritten++

	return nil
}

// Pending returns the number of unanswered requests
// that have been sent on the connection.
func ( *ClientConn) () int {
	.mu.Lock()
	defer .mu.Unlock()
	return .nwritten - .nread
}

// Read reads the next response from the wire. A valid response might be
// returned together with an [ErrPersistEOF], which means that the remote
// requested that this be the last request serviced. Read can be called
// concurrently with [ClientConn.Write], but not with another Read.
func ( *ClientConn) ( *http.Request) ( *http.Response,  error) {
	// Retrieve the pipeline ID of this request/response pair
	.mu.Lock()
	,  := .pipereq[]
	delete(.pipereq, )
	if ! {
		.mu.Unlock()
		return nil, ErrPipeline
	}
	.mu.Unlock()

	// Ensure pipeline order
	.pipe.StartResponse()
	defer .pipe.EndResponse()

	.mu.Lock()
	if .re != nil {
		defer .mu.Unlock()
		return nil, .re
	}
	if .r == nil { // connection closed by user in the meantime
		defer .mu.Unlock()
		return nil, errClosed
	}
	 := .r
	 := .lastbody
	.lastbody = nil
	.mu.Unlock()

	// Make sure body is fully consumed, even if user does not call body.Close
	if  != nil {
		// body.Close is assumed to be idempotent and multiple calls to
		// it should return the error that its first invocation
		// returned.
		 = .Close()
		if  != nil {
			.mu.Lock()
			defer .mu.Unlock()
			.re = 
			return nil, 
		}
	}

	,  = http.ReadResponse(, )
	.mu.Lock()
	defer .mu.Unlock()
	if  != nil {
		.re = 
		return , 
	}
	.lastbody = .Body

	.nread++

	if .Close {
		.re = ErrPersistEOF // don't send any more requests
		return , .re
	}
	return , 
}

// Do is convenience method that writes a request and reads a response.
func ( *ClientConn) ( *http.Request) (*http.Response, error) {
	 := .Write()
	if  != nil {
		return nil, 
	}
	return .Read()
}