|  | // Copyright (c) 2019 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "net/third_party/quiche/src/quic/quartc/test/random_delay_link.h" | 
|  |  | 
|  | #include <cmath> | 
|  | #include <cstdint> | 
|  |  | 
|  | #include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/simulator/link.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/simulator/port.h" | 
|  | #include "net/third_party/quiche/src/quic/test_tools/simulator/simulator.h" | 
|  |  | 
|  | namespace quic { | 
|  | namespace simulator { | 
|  | namespace { | 
|  |  | 
|  | // Number of buckets used to define an exponential distribution. | 
|  | constexpr int64_t kNumBuckets = static_cast<int64_t>(2) << 32; | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | RandomDelayLink::RandomDelayLink(Simulator* simulator, | 
|  | std::string name, | 
|  | UnconstrainedPortInterface* sink, | 
|  | QuicBandwidth bandwidth, | 
|  | QuicTime::Delta propagation_delay) | 
|  | : OneWayLink(simulator, name, sink, bandwidth, propagation_delay), | 
|  | median_random_delay_(QuicTime::Delta::Zero()) {} | 
|  |  | 
|  | RandomDelayLink::~RandomDelayLink() {} | 
|  |  | 
|  | QuicTime::Delta RandomDelayLink::GetRandomDelay( | 
|  | QuicTime::Delta /*transfer_time*/) { | 
|  | // Computes a random delay following an exponential distribution, with median | 
|  | // value |median_random_delay_|.  Choose a uniform random value between 1 and | 
|  | // kNumBuckets, convert this to an exponential, then scale it such that a | 
|  | // random value from the middle of the distribution (0.5) corresponds to | 
|  | // |median_random_delay_|. | 
|  | return std::log( | 
|  | static_cast<double>( | 
|  | simulator_->GetRandomGenerator()->RandUint64() % kNumBuckets + | 
|  | 1) / | 
|  | kNumBuckets) / | 
|  | std::log(0.5) * median_random_delay_; | 
|  | } | 
|  |  | 
|  | SymmetricRandomDelayLink::SymmetricRandomDelayLink( | 
|  | Simulator* simulator, | 
|  | std::string name, | 
|  | UnconstrainedPortInterface* sink_a, | 
|  | UnconstrainedPortInterface* sink_b, | 
|  | QuicBandwidth bandwidth, | 
|  | QuicTime::Delta propagation_delay) | 
|  | : a_to_b_link_(simulator, | 
|  | QuicStringPrintf("%s (A-to-B)", name.c_str()), | 
|  | sink_b, | 
|  | bandwidth, | 
|  | propagation_delay), | 
|  | b_to_a_link_(simulator, | 
|  | QuicStringPrintf("%s (B-to-A)", name.c_str()), | 
|  | sink_a, | 
|  | bandwidth, | 
|  | propagation_delay) {} | 
|  |  | 
|  | SymmetricRandomDelayLink::SymmetricRandomDelayLink( | 
|  | Endpoint* endpoint_a, | 
|  | Endpoint* endpoint_b, | 
|  | QuicBandwidth bandwidth, | 
|  | QuicTime::Delta propagation_delay) | 
|  | : SymmetricRandomDelayLink(endpoint_a->simulator(), | 
|  | QuicStringPrintf("Link [%s]<->[%s]", | 
|  | endpoint_a->name().c_str(), | 
|  | endpoint_b->name().c_str()), | 
|  | endpoint_a->GetRxPort(), | 
|  | endpoint_b->GetRxPort(), | 
|  | bandwidth, | 
|  | propagation_delay) { | 
|  | endpoint_a->SetTxPort(&a_to_b_link_); | 
|  | endpoint_b->SetTxPort(&b_to_a_link_); | 
|  | } | 
|  |  | 
|  | }  // namespace simulator | 
|  | }  // namespace quic |