Home | History | Annotate | Download | only in utility
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_
      6 #define MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_
      7 
      8 #include <vector>
      9 
     10 #include "base/basictypes.h"
     11 #include "base/memory/linked_ptr.h"
     12 #include "base/memory/ref_counted.h"
     13 #include "base/memory/scoped_ptr.h"
     14 #include "base/memory/weak_ptr.h"
     15 #include "base/single_thread_task_runner.h"
     16 #include "media/cast/net/cast_transport_config.h"
     17 #include "net/base/ip_endpoint.h"
     18 #include "third_party/mt19937ar/mt19937ar.h"
     19 
     20 namespace net {
     21 class NetLog;
     22 };
     23 
     24 namespace base {
     25 class TickClock;
     26 };
     27 
     28 namespace media {
     29 namespace cast {
     30 namespace test {
     31 
     32 class PacketPipe {
     33  public:
     34   PacketPipe();
     35   virtual ~PacketPipe();
     36   virtual void Send(scoped_ptr<Packet> packet) = 0;
     37   // Allows injection of fake test runner for testing.
     38   virtual void InitOnIOThread(
     39       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     40       base::TickClock* clock);
     41   virtual void AppendToPipe(scoped_ptr<PacketPipe> pipe);
     42  protected:
     43   scoped_ptr<PacketPipe> pipe_;
     44   // Allows injection of fake task runner for testing.
     45   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
     46   base::TickClock* clock_;
     47 };
     48 
     49 // Implements a Interrupted Poisson Process for packet delivery.
     50 // The process has 2 states: ON and OFF, the rate of switching between
     51 // these two states are defined.
     52 // When in ON state packets are sent according to a defined rate.
     53 // When in OFF state packets are not sent.
     54 // The rate above is the average rate of a poisson distribution.
     55 class InterruptedPoissonProcess {
     56  public:
     57   InterruptedPoissonProcess(
     58       const std::vector<double>& average_rates,
     59       double coef_burstiness,
     60       double coef_variance,
     61       uint32 rand_seed);
     62   ~InterruptedPoissonProcess();
     63 
     64   scoped_ptr<PacketPipe> NewBuffer(size_t size);
     65 
     66  private:
     67   class InternalBuffer;
     68 
     69   // |task_runner| is the executor of the IO thread.
     70   // |clock| is the system clock.
     71   void InitOnIOThread(
     72       const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
     73       base::TickClock* clock);
     74 
     75   base::TimeDelta NextEvent(double rate);
     76   double RandDouble();
     77   void ComputeRates();
     78   void UpdateRates();
     79   void SwitchOff();
     80   void SwitchOn();
     81   void SendPacket();
     82 
     83   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
     84   base::TickClock* clock_;
     85   const std::vector<double> average_rates_;
     86   const double coef_burstiness_;
     87   const double coef_variance_;
     88   int rate_index_;
     89 
     90   // The following rates are per milliseconds.
     91   double send_rate_;
     92   double switch_off_rate_;
     93   double switch_on_rate_;
     94   bool on_state_;
     95 
     96   std::vector<base::WeakPtr<InternalBuffer> > send_buffers_;
     97 
     98   // Fast pseudo random number generator.
     99   MersenneTwister mt_rand_;
    100 
    101   base::WeakPtrFactory<InterruptedPoissonProcess> weak_factory_;
    102 
    103   DISALLOW_COPY_AND_ASSIGN(InterruptedPoissonProcess);
    104 };
    105 
    106 // A UDPProxy will set up a UDP socket and bind to |local_port|.
    107 // Packets send to that port will be forwarded to |destination|.
    108 // Packets send from |destination| to |local_port| will be returned
    109 // to whoever sent a packet to |local_port| last. (Not counting packets
    110 // from |destination|.) The UDPProxy will run a separate thread to
    111 // do the forwarding of packets, and will keep doing so until destroyed.
    112 // You can insert delays and packet drops by supplying a PacketPipe.
    113 // The PacketPipes may also be NULL if you just want to forward packets.
    114 class UDPProxy {
    115  public:
    116   virtual ~UDPProxy() {}
    117   static scoped_ptr<UDPProxy> Create(const net::IPEndPoint& local_port,
    118                                      const net::IPEndPoint& destination,
    119                                      scoped_ptr<PacketPipe> to_dest_pipe,
    120                                      scoped_ptr<PacketPipe> from_dest_pipe,
    121                                      net::NetLog* net_log);
    122 };
    123 
    124 // The following functions create PacketPipes which can be linked
    125 // together (with AppendToPipe) and passed into UdpProxy::Create below.
    126 
    127 // This PacketPipe emulates a buffer of a given size. Limits our output
    128 // from the buffer at a rate given by |bandwidth| (in megabits per second).
    129 // Packets entering the buffer will be dropped if there is not enough
    130 // room for them.
    131 scoped_ptr<PacketPipe> NewBuffer(size_t buffer_size, double bandwidth);
    132 
    133 // Randomly drops |drop_fraction|*100% of packets.
    134 scoped_ptr<PacketPipe> NewRandomDrop(double drop_fraction);
    135 
    136 // Delays each packet by |delay_seconds|.
    137 scoped_ptr<PacketPipe> NewConstantDelay(double delay_seconds);
    138 
    139 // Delays packets by a random amount between zero and |delay|.
    140 // This PacketPipe can reorder packets.
    141 scoped_ptr<PacketPipe> NewRandomUnsortedDelay(double delay);
    142 
    143 // Duplicates every packet, one is transmitted immediately,
    144 // one is transmitted after a random delay between |delay_min|
    145 // and |delay_min + random_delay|.
    146 // This PacketPipe will reorder packets.
    147 scoped_ptr<PacketPipe> NewDuplicateAndDelay(double delay_min,
    148                                             double random_delay);
    149 
    150 // This PacketPipe inserts a random delay between each packet.
    151 // This PacketPipe cannot re-order packets. The delay between each
    152 // packet is asically |min_delay| + random( |random_delay| )
    153 // However, every now and then a delay of |big_delay| will be
    154 // inserted (roughly every |seconds_between_big_delay| seconds).
    155 scoped_ptr<PacketPipe> NewRandomSortedDelay(double random_delay,
    156                                             double big_delay,
    157                                             double seconds_between_big_delay);
    158 
    159 // This PacketPipe emulates network outages. It basically waits
    160 // for 0-2*|average_work_time| seconds, then kills the network for
    161 // 0-|2*average_outage_time| seconds. Then it starts over again.
    162 scoped_ptr<PacketPipe> NewNetworkGlitchPipe(double average_work_time,
    163                                             double average_outage_time);
    164 
    165 // This method builds a stack of PacketPipes to emulate a reasonably
    166 // good network. ~50mbit, ~3ms latency, no packet loss unless saturated.
    167 scoped_ptr<PacketPipe> GoodNetwork();
    168 
    169 // This method builds a stack of PacketPipes to emulate a reasonably
    170 // good wifi network. ~20mbit, 1% packet loss, ~3ms latency.
    171 scoped_ptr<PacketPipe> WifiNetwork();
    172 
    173 // This method builds a stack of PacketPipes to emulate a
    174 // bad wifi network. ~5mbit, 5% packet loss, ~7ms latency
    175 // 40ms dropouts every ~2 seconds. Can reorder packets.
    176 scoped_ptr<PacketPipe> BadNetwork();
    177 
    178 // This method builds a stack of PacketPipes to emulate a crappy wifi network.
    179 // ~2mbit, 20% packet loss, ~40ms latency and packets can get reordered.
    180 // 300ms drouputs every ~2 seconds.
    181 scoped_ptr<PacketPipe> EvilNetwork();
    182 
    183 }  // namespace test
    184 }  // namespace cast
    185 }  // namespace media
    186 
    187 #endif  // MEDIA_CAST_TEST_UTILITY_UDP_PROXY_H_
    188