func (dhtm *dontHaveTimeoutMgr) UpdateMessageLatency(elapsed time.Duration) {
	dhtm.lk.Lock()
	defer dhtm.lk.Unlock()
	dhtm.messageLatency.update(elapsed)
	oldTimeout := dhtm.timeout
	dhtm.timeout = dhtm.calculateTimeoutFromMessageLatency()
	if dhtm.timeout < oldTimeout {
		dhtm.checkForTimeouts()
	}
}
UpdateMessageLatency is called when we receive a response from the peer.
It is the time between sending a request and receiving the corresponding
response.
package messagequeue
import (
	"context"
	"sync"
	"time"
	"github.com/benbjohnson/clock"
	cid "github.com/ipfs/go-cid"
	"github.com/libp2p/go-libp2p/p2p/protocol/ping"
)
const (
	dontHaveTimeout = 5 * time.Second
	maxExpectedWantProcessTime = 2 * time.Second
	maxTimeout = dontHaveTimeout + maxExpectedWantProcessTime
	pingLatencyMultiplier = 3
	messageLatencyAlpha = 0.5
	messageLatencyMultiplier = 2
)
type PeerConnection interface {
	Ping(context.Context) ping.Result
	Latency() time.Duration
}
type pendingWant struct {
	c      cid.Cid
	active bool
	sent   time.Time
}
type dontHaveTimeoutMgr struct {
	clock                      clock.Clock
	ctx                        context.Context
	shutdown                   func()
	peerConn                   PeerConnection
	onDontHaveTimeout          func([]cid.Cid)
	defaultTimeout             time.Duration
	maxTimeout                 time.Duration
	pingLatencyMultiplier      int
	messageLatencyMultiplier   int
	maxExpectedWantProcessTime time.Duration
	lk sync.RWMutex
	started bool
	activeWants map[cid.Cid]*pendingWant
	wantQueue []*pendingWant
	timeout time.Duration
	messageLatency *latencyEwma
	checkForTimeoutsTimer *clock.Timer
	timeoutsTriggered chan struct{}
}
func newDontHaveTimeoutMgr(pc PeerConnection, onDontHaveTimeout func([]cid.Cid), clock clock.Clock) *dontHaveTimeoutMgr {
	return newDontHaveTimeoutMgrWithParams(pc, onDontHaveTimeout, dontHaveTimeout, maxTimeout,
		pingLatencyMultiplier, messageLatencyMultiplier, maxExpectedWantProcessTime, clock, nil)
}
func newDontHaveTimeoutMgrWithParams(
	pc PeerConnection,
	onDontHaveTimeout func([]cid.Cid),
	defaultTimeout time.Duration,
	maxTimeout time.Duration,
	pingLatencyMultiplier int,
	messageLatencyMultiplier int,
	maxExpectedWantProcessTime time.Duration,
	clock clock.Clock,
	timeoutsTriggered chan struct{}) *dontHaveTimeoutMgr {
	ctx, shutdown := context.WithCancel(context.Background())
	mqp := &dontHaveTimeoutMgr{
		clock:                      clock,
		ctx:                        ctx,
		shutdown:                   shutdown,
		peerConn:                   pc,
		activeWants:                make(map[cid.Cid]*pendingWant),
		timeout:                    defaultTimeout,
		messageLatency:             &latencyEwma{alpha: messageLatencyAlpha},
		defaultTimeout:             defaultTimeout,
		maxTimeout:                 maxTimeout,
		pingLatencyMultiplier:      pingLatencyMultiplier,
		messageLatencyMultiplier:   messageLatencyMultiplier,
		maxExpectedWantProcessTime: maxExpectedWantProcessTime,
		onDontHaveTimeout:          onDontHaveTimeout,
		timeoutsTriggered:          timeoutsTriggered,
	}
	return mqp
}
func (dhtm *dontHaveTimeoutMgr) Shutdown() {
	dhtm.shutdown()
	dhtm.lk.Lock()
	defer dhtm.lk.Unlock()
	if dhtm.checkForTimeoutsTimer != nil {
		dhtm.checkForTimeoutsTimer.Stop()
	}
}
func (dhtm *dontHaveTimeoutMgr) Start() {
	dhtm.lk.Lock()
	defer dhtm.lk.Unlock()
	if dhtm.started {
		return
	}
	dhtm.started = true
	latency := dhtm.peerConn.Latency()
	if latency.Nanoseconds() > 0 {
		dhtm.timeout = dhtm.calculateTimeoutFromPingLatency(latency)
		return
	}
	go dhtm.measurePingLatency()
}