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