Copyright 2015 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.
Transport code's client connection pooling.

package http2

import (
	
	
	
)
ClientConnPool manages a pool of HTTP/2 client connections.
type ClientConnPool interface {
	GetClientConn(req *http.Request, addr string) (*ClientConn, error)
	MarkDead(*ClientConn)
}
clientConnPoolIdleCloser is the interface implemented by ClientConnPool implementations which can close their idle connections.
TODO: use singleflight for dialing and addConnCalls?
type clientConnPool struct {
	t *Transport

TODO: add support for sharing conns based on cert names (e.g. share conn for googleapis.com and appspot.com)
	conns        map[string][]*ClientConn // key is host:port
	dialing      map[string]*dialCall     // currently in-flight dials
	keys         map[*ClientConn][]string
	addConnCalls map[string]*addConnCall // in-flight addConnIfNeede calls
}

func ( *clientConnPool) ( *http.Request,  string) (*ClientConn, error) {
	return .getClientConn(, , dialOnMiss)
}

const (
	dialOnMiss   = true
	noDialOnMiss = false
)
shouldTraceGetConn reports whether getClientConn should call any ClientTrace.GetConn hook associated with the http.Request. This complexity is needed to avoid double calls of the GetConn hook during the back-and-forth between net/http and x/net/http2 (when the net/http.Transport is upgraded to also speak http2), as well as support the case where x/net/http2 is being used directly.
If our Transport wasn't made via ConfigureTransport, always trace the GetConn hook if provided, because that means the http2 package is being used directly and it's the one dialing, as opposed to net/http.
	if ,  := .t.ConnPool.(noDialClientConnPool); ! {
		return true
Otherwise, only use the GetConn hook if this connection has been used previously for other requests. For fresh connections, the net/http package does the dialing.
	return !.freshConn
}

func ( *clientConnPool) ( *http.Request,  string,  bool) (*ClientConn, error) {
It gets its own connection.
		traceGetConn(, )
		const  = true
		,  := .t.dialClientConn(, )
		if  != nil {
			return nil, 
		}
		return , nil
	}
	.mu.Lock()
	for ,  := range .conns[] {
		if  := .idleState(); .canTakeNewRequest {
			if .shouldTraceGetConn() {
				traceGetConn(, )
			}
			.mu.Unlock()
			return , nil
		}
	}
	if ! {
		.mu.Unlock()
		return nil, ErrNoCachedConn
	}
	traceGetConn(, )
	 := .getStartDialLocked()
	.mu.Unlock()
	<-.done
	return .res, .err
}
dialCall is an in-flight Transport dial call to a host.
type dialCall struct {
	_    incomparable
	p    *clientConnPool
	done chan struct{} // closed when done
	res  *ClientConn   // valid after done is closed
	err  error         // valid after done is closed
}
requires p.mu is held.
A dial is already in-flight. Don't start another.
		return 
	}
	 := &dialCall{p: , done: make(chan struct{})}
	if .dialing == nil {
		.dialing = make(map[string]*dialCall)
	}
	.dialing[] = 
	go .dial()
	return 
}
run in its own goroutine.
func ( *dialCall) ( string) {
	const  = false // shared conn
	.res, .err = .p.t.dialClientConn(, )
	close(.done)

	.p.mu.Lock()
	delete(.p.dialing, )
	if .err == nil {
		.p.addConnLocked(, .res)
	}
	.p.mu.Unlock()
}
addConnIfNeeded makes a NewClientConn out of c if a connection for key doesn't already exist. It coalesces concurrent calls with the same key. This is used by the http1 Transport code when it creates a new connection. Because the http1 Transport doesn't de-dup TCP dials to outbound hosts (because it doesn't know the protocol), it can get into a situation where it has multiple TLS connections. This code decides which ones live or die. The return value used is whether c was used. c is never closed.
func ( *clientConnPool) ( string,  *Transport,  *tls.Conn) ( bool,  error) {
	.mu.Lock()
	for ,  := range .conns[] {
		if .CanTakeNewRequest() {
			.mu.Unlock()
			return false, nil
		}
	}
	,  := .addConnCalls[]
	if ! {
		if .addConnCalls == nil {
			.addConnCalls = make(map[string]*addConnCall)
		}
		 = &addConnCall{
			p:    ,
			done: make(chan struct{}),
		}
		.addConnCalls[] = 
		go .run(, , )
	}
	.mu.Unlock()

	<-.done
	if .err != nil {
		return false, .err
	}
	return !, nil
}

type addConnCall struct {
	_    incomparable
	p    *clientConnPool
	done chan struct{} // closed when done
	err  error
}

func ( *addConnCall) ( *Transport,  string,  *tls.Conn) {
	,  := .NewClientConn()

	 := .p
	.mu.Lock()
	if  != nil {
		.err = 
	} else {
		.addConnLocked(, )
	}
	delete(.addConnCalls, )
	.mu.Unlock()
	close(.done)
}
p.mu must be held
func ( *clientConnPool) ( string,  *ClientConn) {
	for ,  := range .conns[] {
		if  ==  {
			return
		}
	}
	if .conns == nil {
		.conns = make(map[string][]*ClientConn)
	}
	if .keys == nil {
		.keys = make(map[*ClientConn][]string)
	}
	.conns[] = append(.conns[], )
	.keys[] = append(.keys[], )
}

func ( *clientConnPool) ( *ClientConn) {
	.mu.Lock()
	defer .mu.Unlock()
	for ,  := range .keys[] {
		,  := .conns[]
		if ! {
			continue
		}
		 := filterOutClientConn(, )
		if len() > 0 {
			.conns[] = 
		} else {
			delete(.conns, )
		}
	}
	delete(.keys, )
}

func ( *clientConnPool) () {
	.mu.Lock()
TODO: don't close a cc if it was just added to the pool milliseconds ago and has never been used. There's currently a small race window with the HTTP/1 Transport's integration where it can add an idle conn just before using it, and somebody else can concurrently call CloseIdleConns and break some caller's RoundTrip.
	for ,  := range .conns {
		for ,  := range  {
			.closeIfIdle()
		}
	}
}

func ( []*ClientConn,  *ClientConn) []*ClientConn {
	 := [:0]
	for ,  := range  {
		if  !=  {
			 = append(, )
		}
If we filtered it out, zero out the last item to prevent the GC from seeing it.
	if len() != len() {
		[len()-1] = nil
	}
	return 
}
noDialClientConnPool is an implementation of http2.ClientConnPool which never dials. We let the HTTP/1.1 client dial and use its TLS connection instead.