func()

in garbage/nethttp.go [7157:7277]


func (pc *persistConn) readLoop() {

	eofc := make(chan struct{})
	defer close(eofc)

	testHookMu.Lock()
	testHookReadLoopBeforeNextRead := testHookReadLoopBeforeNextRead
	testHookMu.Unlock()

	alive := true
	for alive {
		pb, err := pc.br.Peek(1)

		pc.lk.Lock()
		if pc.numExpectedResponses == 0 {
			if !pc.closed {
				pc.closeLocked()
				if len(pb) > 0 {
					log.Printf("Unsolicited response received on idle HTTP channel starting with %q; err=%v",
						string(pb), err)
				}
			}
			pc.lk.Unlock()
			return
		}
		pc.lk.Unlock()

		rc := <-pc.reqch

		var resp *Response
		if err == nil {
			resp, err = ReadResponse(pc.br, rc.req)
			if err == nil && resp.StatusCode == 100 {

				resp, err = ReadResponse(pc.br, rc.req)
			}
		}

		if resp != nil {
			resp.TLS = pc.tlsState
		}

		hasBody := resp != nil && rc.req.Method != "HEAD" && resp.ContentLength != 0

		if err != nil {
			pc.close()
		} else {
			if rc.addedGzip && hasBody && resp.Header.Get("Content-Encoding") == "gzip" {
				resp.Header.Del("Content-Encoding")
				resp.Header.Del("Content-Length")
				resp.ContentLength = -1
				resp.Body = &gzipReader{body: resp.Body}
			}
			resp.Body = &bodyEOFSignal{body: resp.Body}
		}

		if err != nil || resp.Close || rc.req.Close || resp.StatusCode <= 199 {

			alive = false
		}

		var waitForBodyRead chan bool // channel is nil when there's no body
		if hasBody {
			waitForBodyRead = make(chan bool, 2)
			resp.Body.(*bodyEOFSignal).earlyCloseFn = func() error {
				waitForBodyRead <- false
				return nil
			}
			resp.Body.(*bodyEOFSignal).fn = func(err error) error {
				isEOF := err == io.EOF
				waitForBodyRead <- isEOF
				if isEOF {
					<-eofc
				} else if err != nil && pc.isCanceled() {
					return errRequestCanceled
				}
				return err
			}
		} else {

			pc.t.setReqCanceler(rc.req, nil)
		}

		pc.lk.Lock()
		pc.numExpectedResponses--
		pc.lk.Unlock()

		rc.ch <- responseAndError{resp, err}

		if hasBody {

			select {
			case <-rc.req.Cancel:
				alive = false
				pc.t.CancelRequest(rc.req)
			case bodyEOF := <-waitForBodyRead:
				pc.t.setReqCanceler(rc.req, nil)
				alive = alive &&
					bodyEOF &&
					!pc.sawEOF &&
					pc.wroteRequest() &&
					pc.t.putIdleConn(pc)
				if bodyEOF {
					eofc <- struct{}{}
				}
			case <-pc.closech:
				alive = false
			}
		} else {
			alive = alive &&
				!pc.sawEOF &&
				pc.wroteRequest() &&
				pc.t.putIdleConn(pc)
		}

		if hook := testHookReadLoopBeforeNextRead; hook != nil {
			hook()
		}
	}
	pc.close()
}