1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file. 4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#ifndef MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_ 6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#define MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_ 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <vector> 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/basictypes.h" 11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/linked_ptr.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/memory/ref_counted.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/memory/scoped_ptr.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/memory/weak_ptr.h" 15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/single_thread_task_runner.h" 16116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "media/cast/net/cast_transport_config.h" 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "net/base/ip_endpoint.h" 18116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "third_party/mt19937ar/mt19937ar.h" 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace net { 21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass NetLog; 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace base { 25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)class TickClock; 26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}; 27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace media { 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace cast { 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace test { 31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass PacketPipe { 33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public: 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch PacketPipe(); 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual ~PacketPipe(); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch virtual void Send(scoped_ptr<Packet> packet) = 0; 370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Allows injection of fake test runner for testing. 380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch virtual void InitOnIOThread( 39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::TickClock* clock); 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual void AppendToPipe(scoped_ptr<PacketPipe> pipe); 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch protected: 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<PacketPipe> pipe_; 44c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // Allows injection of fake task runner for testing. 45c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) base::TickClock* clock_; 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 49116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Implements a Interrupted Poisson Process for packet delivery. 50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// The process has 2 states: ON and OFF, the rate of switching between 51116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// these two states are defined. 52116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// When in ON state packets are sent according to a defined rate. 53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// When in OFF state packets are not sent. 54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// The rate above is the average rate of a poisson distribution. 55116680a4aac90f2aa7413d9095a592090648e557Ben Murdochclass InterruptedPoissonProcess { 56116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch public: 57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch InterruptedPoissonProcess( 58116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<double>& average_rates, 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double coef_burstiness, 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double coef_variance, 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch uint32 rand_seed); 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ~InterruptedPoissonProcess(); 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_ptr<PacketPipe> NewBuffer(size_t size); 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch private: 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch class InternalBuffer; 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |task_runner| is the executor of the IO thread. 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |clock| is the system clock. 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void InitOnIOThread( 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TickClock* clock); 74116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 75116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TimeDelta NextEvent(double rate); 76116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double RandDouble(); 77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void ComputeRates(); 78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void UpdateRates(); 79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void SwitchOff(); 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void SwitchOn(); 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch void SendPacket(); 82116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::TickClock* clock_; 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const std::vector<double> average_rates_; 86116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const double coef_burstiness_; 87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const double coef_variance_; 88116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int rate_index_; 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // The following rates are per milliseconds. 91116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double send_rate_; 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double switch_off_rate_; 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch double switch_on_rate_; 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool on_state_; 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<base::WeakPtr<InternalBuffer> > send_buffers_; 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Fast pseudo random number generator. 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch MersenneTwister mt_rand_; 100116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::WeakPtrFactory<InterruptedPoissonProcess> weak_factory_; 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DISALLOW_COPY_AND_ASSIGN(InterruptedPoissonProcess); 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// A UDPProxy will set up a UDP socket and bind to |local_port|. 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Packets send to that port will be forwarded to |destination|. 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Packets send from |destination| to |local_port| will be returned 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// to whoever sent a packet to |local_port| last. (Not counting packets 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// from |destination|.) The UDPProxy will run a separate thread to 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// do the forwarding of packets, and will keep doing so until destroyed. 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// You can insert delays and packet drops by supplying a PacketPipe. 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The PacketPipes may also be NULL if you just want to forward packets. 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass UDPProxy { 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch public: 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual ~UDPProxy() {} 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static scoped_ptr<UDPProxy> Create(const net::IPEndPoint& local_port, 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const net::IPEndPoint& destination, 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<PacketPipe> to_dest_pipe, 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<PacketPipe> from_dest_pipe, 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch net::NetLog* net_log); 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The following functions create PacketPipes which can be linked 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// together (with AppendToPipe) and passed into UdpProxy::Create below. 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This PacketPipe emulates a buffer of a given size. Limits our output 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// from the buffer at a rate given by |bandwidth| (in megabits per second). 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Packets entering the buffer will be dropped if there is not enough 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// room for them. 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<PacketPipe> NewBuffer(size_t buffer_size, double bandwidth); 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Randomly drops |drop_fraction|*100% of packets. 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<PacketPipe> NewRandomDrop(double drop_fraction); 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Delays each packet by |delay_seconds|. 137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<PacketPipe> NewConstantDelay(double delay_seconds); 138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Delays packets by a random amount between zero and |delay|. 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This PacketPipe can reorder packets. 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<PacketPipe> NewRandomUnsortedDelay(double delay); 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 14303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Duplicates every packet, one is transmitted immediately, 14403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// one is transmitted after a random delay between |delay_min| 14503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// and |delay_min + random_delay|. 14603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// This PacketPipe will reorder packets. 14703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)scoped_ptr<PacketPipe> NewDuplicateAndDelay(double delay_min, 14803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) double random_delay); 14903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This PacketPipe inserts a random delay between each packet. 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This PacketPipe cannot re-order packets. The delay between each 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// packet is asically |min_delay| + random( |random_delay| ) 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// However, every now and then a delay of |big_delay| will be 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// inserted (roughly every |seconds_between_big_delay| seconds). 1550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_ptr<PacketPipe> NewRandomSortedDelay(double random_delay, 1560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch double big_delay, 1570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch double seconds_between_big_delay); 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This PacketPipe emulates network outages. It basically waits 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// for 0-2*|average_work_time| seconds, then kills the network for 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// 0-|2*average_outage_time| seconds. Then it starts over again. 1620529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochscoped_ptr<PacketPipe> NewNetworkGlitchPipe(double average_work_time, 1630529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch double average_outage_time); 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This method builds a stack of PacketPipes to emulate a reasonably 1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// good network. ~50mbit, ~3ms latency, no packet loss unless saturated. 1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)scoped_ptr<PacketPipe> GoodNetwork(); 1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// This method builds a stack of PacketPipes to emulate a reasonably 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// good wifi network. ~20mbit, 1% packet loss, ~3ms latency. 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<PacketPipe> WifiNetwork(); 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 173010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// This method builds a stack of PacketPipes to emulate a 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// bad wifi network. ~5mbit, 5% packet loss, ~7ms latency 175010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// 40ms dropouts every ~2 seconds. Can reorder packets. 176010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)scoped_ptr<PacketPipe> BadNetwork(); 177010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// This method builds a stack of PacketPipes to emulate a crappy wifi network. 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// ~2mbit, 20% packet loss, ~40ms latency and packets can get reordered. 180010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// 300ms drouputs every ~2 seconds. 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochscoped_ptr<PacketPipe> EvilNetwork(); 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace test 184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace cast 185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace media 186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#endif // MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_ 188