// ServerConn is low-level and old. Applications should instead use Server
// in the net/http package.
type ServerConn struct {
- lk sync.Mutex // read-write protects the following fields
+ mu sync.Mutex // read-write protects the following fields
c net.Conn
r *bufio.Reader
re, we error // read/write errors
// called before Read has signaled the end of the keep-alive logic. The user
// should not call Hijack while Read or Write is in progress.
func (sc *ServerConn) Hijack() (c net.Conn, r *bufio.Reader) {
- sc.lk.Lock()
- defer sc.lk.Unlock()
+ sc.mu.Lock()
+ defer sc.mu.Unlock()
c = sc.c
r = sc.r
sc.c = nil
sc.pipe.EndResponse(id)
} else {
// Remember the pipeline id of this request
- sc.lk.Lock()
+ sc.mu.Lock()
sc.pipereq[req] = id
- sc.lk.Unlock()
+ sc.mu.Unlock()
}
}()
- sc.lk.Lock()
+ sc.mu.Lock()
if sc.we != nil { // no point receiving if write-side broken or closed
- defer sc.lk.Unlock()
+ defer sc.mu.Unlock()
return nil, sc.we
}
if sc.re != nil {
- defer sc.lk.Unlock()
+ defer sc.mu.Unlock()
return nil, sc.re
}
if sc.r == nil { // connection closed by user in the meantime
- defer sc.lk.Unlock()
+ defer sc.mu.Unlock()
return nil, errClosed
}
r := sc.r
lastbody := sc.lastbody
sc.lastbody = nil
- sc.lk.Unlock()
+ sc.mu.Unlock()
// Make sure body is fully consumed, even if user does not call body.Close
if lastbody != nil {
// returned.
err = lastbody.Close()
if err != nil {
- sc.lk.Lock()
- defer sc.lk.Unlock()
+ sc.mu.Lock()
+ defer sc.mu.Unlock()
sc.re = err
return nil, err
}
}
req, err = http.ReadRequest(r)
- sc.lk.Lock()
- defer sc.lk.Unlock()
+ sc.mu.Lock()
+ defer sc.mu.Unlock()
if err != nil {
if err == io.ErrUnexpectedEOF {
// A close from the opposing client is treated as a
// Pending returns the number of unanswered requests
// that have been received on the connection.
func (sc *ServerConn) Pending() int {
- sc.lk.Lock()
- defer sc.lk.Unlock()
+ sc.mu.Lock()
+ defer sc.mu.Unlock()
return sc.nread - sc.nwritten
}
func (sc *ServerConn) Write(req *http.Request, resp *http.Response) error {
// Retrieve the pipeline ID of this request/response pair
- sc.lk.Lock()
+ sc.mu.Lock()
id, ok := sc.pipereq[req]
delete(sc.pipereq, req)
if !ok {
- sc.lk.Unlock()
+ sc.mu.Unlock()
return ErrPipeline
}
- sc.lk.Unlock()
+ sc.mu.Unlock()
// Ensure pipeline order
sc.pipe.StartResponse(id)
defer sc.pipe.EndResponse(id)
- sc.lk.Lock()
+ sc.mu.Lock()
if sc.we != nil {
- defer sc.lk.Unlock()
+ defer sc.mu.Unlock()
return sc.we
}
if sc.c == nil { // connection closed by user in the meantime
- defer sc.lk.Unlock()
+ defer sc.mu.Unlock()
return ErrClosed
}
c := sc.c
if sc.nread <= sc.nwritten {
- defer sc.lk.Unlock()
+ defer sc.mu.Unlock()
return errors.New("persist server pipe count")
}
if resp.Close {
// before signaling.
sc.re = ErrPersistEOF
}
- sc.lk.Unlock()
+ sc.mu.Unlock()
err := resp.Write(c)
- sc.lk.Lock()
- defer sc.lk.Unlock()
+ sc.mu.Lock()
+ defer sc.mu.Unlock()
if err != nil {
sc.we = err
return err
// ClientConn is low-level and old. Applications should instead use
// Client or Transport in the net/http package.
type ClientConn struct {
- lk sync.Mutex // read-write protects the following fields
+ mu sync.Mutex // read-write protects the following fields
c net.Conn
r *bufio.Reader
re, we error // read/write errors
// called before the user or Read have signaled the end of the keep-alive
// logic. The user should not call Hijack while Read or Write is in progress.
func (cc *ClientConn) Hijack() (c net.Conn, r *bufio.Reader) {
- cc.lk.Lock()
- defer cc.lk.Unlock()
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
c = cc.c
r = cc.r
cc.c = nil
cc.pipe.EndResponse(id)
} else {
// Remember the pipeline id of this request
- cc.lk.Lock()
+ cc.mu.Lock()
cc.pipereq[req] = id
- cc.lk.Unlock()
+ cc.mu.Unlock()
}
}()
- cc.lk.Lock()
+ cc.mu.Lock()
if cc.re != nil { // no point sending if read-side closed or broken
- defer cc.lk.Unlock()
+ defer cc.mu.Unlock()
return cc.re
}
if cc.we != nil {
- defer cc.lk.Unlock()
+ defer cc.mu.Unlock()
return cc.we
}
if cc.c == nil { // connection closed by user in the meantime
- defer cc.lk.Unlock()
+ defer cc.mu.Unlock()
return errClosed
}
c := cc.c
// still might be some pipelined reads
cc.we = ErrPersistEOF
}
- cc.lk.Unlock()
+ cc.mu.Unlock()
err = cc.writeReq(req, c)
- cc.lk.Lock()
- defer cc.lk.Unlock()
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
if err != nil {
cc.we = err
return err
// Pending returns the number of unanswered requests
// that have been sent on the connection.
func (cc *ClientConn) Pending() int {
- cc.lk.Lock()
- defer cc.lk.Unlock()
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
return cc.nwritten - cc.nread
}
// concurrently with Write, but not with another Read.
func (cc *ClientConn) Read(req *http.Request) (resp *http.Response, err error) {
// Retrieve the pipeline ID of this request/response pair
- cc.lk.Lock()
+ cc.mu.Lock()
id, ok := cc.pipereq[req]
delete(cc.pipereq, req)
if !ok {
- cc.lk.Unlock()
+ cc.mu.Unlock()
return nil, ErrPipeline
}
- cc.lk.Unlock()
+ cc.mu.Unlock()
// Ensure pipeline order
cc.pipe.StartResponse(id)
defer cc.pipe.EndResponse(id)
- cc.lk.Lock()
+ cc.mu.Lock()
if cc.re != nil {
- defer cc.lk.Unlock()
+ defer cc.mu.Unlock()
return nil, cc.re
}
if cc.r == nil { // connection closed by user in the meantime
- defer cc.lk.Unlock()
+ defer cc.mu.Unlock()
return nil, errClosed
}
r := cc.r
lastbody := cc.lastbody
cc.lastbody = nil
- cc.lk.Unlock()
+ cc.mu.Unlock()
// Make sure body is fully consumed, even if user does not call body.Close
if lastbody != nil {
// returned.
err = lastbody.Close()
if err != nil {
- cc.lk.Lock()
- defer cc.lk.Unlock()
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
cc.re = err
return nil, err
}
}
resp, err = http.ReadResponse(r, req)
- cc.lk.Lock()
- defer cc.lk.Unlock()
+ cc.mu.Lock()
+ defer cc.mu.Unlock()
if err != nil {
cc.re = err
return resp, err
// whether or not a connection can be reused. Issue 7569.
writeErrCh chan error
- lk sync.Mutex // guards following fields
+ mu sync.Mutex // guards following fields
numExpectedResponses int
closed error // set non-nil when conn is closed, before closech is closed
broken bool // an error has happened on this connection; marked broken so it's not reused.
// isBroken reports whether this connection is in a known broken state.
func (pc *persistConn) isBroken() bool {
- pc.lk.Lock()
+ pc.mu.Lock()
b := pc.broken
- pc.lk.Unlock()
+ pc.mu.Unlock()
return b
}
// isCanceled reports whether this connection was closed due to CancelRequest.
func (pc *persistConn) isCanceled() bool {
- pc.lk.Lock()
- defer pc.lk.Unlock()
+ pc.mu.Lock()
+ defer pc.mu.Unlock()
return pc.canceled
}
// isReused reports whether this connection is in a known broken state.
func (pc *persistConn) isReused() bool {
- pc.lk.Lock()
+ pc.mu.Lock()
r := pc.reused
- pc.lk.Unlock()
+ pc.mu.Unlock()
return r
}
func (pc *persistConn) cancelRequest() {
- pc.lk.Lock()
- defer pc.lk.Unlock()
+ pc.mu.Lock()
+ defer pc.mu.Unlock()
pc.canceled = true
pc.closeLocked(errRequestCanceled)
}
err = beforeRespHeaderError{err}
}
- pc.lk.Lock()
+ pc.mu.Lock()
if pc.numExpectedResponses == 0 {
pc.readLoopPeekFailLocked(err)
- pc.lk.Unlock()
+ pc.mu.Unlock()
return
}
- pc.lk.Unlock()
+ pc.mu.Unlock()
rc := <-pc.reqch
return
}
- pc.lk.Lock()
+ pc.mu.Lock()
pc.numExpectedResponses--
- pc.lk.Unlock()
+ pc.mu.Unlock()
hasBody := rc.req.Method != "HEAD" && resp.ContentLength != 0
pc.t.putOrCloseIdleConn(pc)
return nil, errRequestCanceled
}
- pc.lk.Lock()
+ pc.mu.Lock()
pc.numExpectedResponses++
headerFn := pc.mutateHeaderFunc
- pc.lk.Unlock()
+ pc.mu.Unlock()
if headerFn != nil {
headerFn(req.extraHeaders())
// It differs from close in that it doesn't close the underlying
// connection for use when it's still being read.
func (pc *persistConn) markBroken() {
- pc.lk.Lock()
- defer pc.lk.Unlock()
+ pc.mu.Lock()
+ defer pc.mu.Unlock()
pc.broken = true
}
// markReused marks this connection as having been successfully used for a
// request and response.
func (pc *persistConn) markReused() {
- pc.lk.Lock()
+ pc.mu.Lock()
pc.reused = true
- pc.lk.Unlock()
+ pc.mu.Unlock()
}
// close closes the underlying TCP connection and closes
// The provided err is only for testing and debugging; in normal
// circumstances it should never be seen by users.
func (pc *persistConn) close(err error) {
- pc.lk.Lock()
- defer pc.lk.Unlock()
+ pc.mu.Lock()
+ defer pc.mu.Unlock()
pc.closeLocked(err)
}