16e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
26e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
36e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// found in the LICENSE file.
46e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
56e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <fcntl.h>
66e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <linux/if_tun.h>
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <linux/types.h>
86e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <math.h>
96e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <net/if.h>
106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <netinet/in.h>
116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <stdio.h>
126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <stdlib.h>
136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <sys/ioctl.h>
146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <sys/stat.h>
156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <sys/types.h>
166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <unistd.h>
176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <deque>
196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <map>
206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/at_exit.h"
226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/bind.h"
236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/command_line.h"
246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/logging.h"
256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/rand_util.h"
266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/synchronization/waitable_event.h"
276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/threading/thread.h"
286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/time/default_tick_clock.h"
296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "media/cast/test/utility/udp_proxy.h"
306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/base/io_buffer.h"
316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/base/net_errors.h"
326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "net/udp/udp_socket.h"
336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace media {
356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace cast {
366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)namespace test {
376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)const size_t kMaxPacketSize = 4096;
396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class SendToFDPipe : public PacketPipe {
416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  explicit SendToFDPipe(int fd) : fd_(fd) {
436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void Send(scoped_ptr<Packet> packet) OVERRIDE {
456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    while (1) {
466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      int written = write(
476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          fd_,
486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          reinterpret_cast<char*>(&packet->front()),
496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          packet->size());
506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (written < 0) {
516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        if (errno == EINTR) continue;
526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        perror("write");
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        exit(1);
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (written != static_cast<int>(packet->size())) {
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        fprintf(stderr, "Truncated write!\n");
576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        exit(1);
586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      }
596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      break;
606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int fd_;
646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class QueueManager : public base::MessageLoopForIO::Watcher {
676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  QueueManager(int input_fd,
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               int output_fd,
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)               scoped_ptr<PacketPipe> pipe) :
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      input_fd_(input_fd),
726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      packet_pipe_(pipe.Pass()) {
736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    CHECK(base::MessageLoopForIO::current()->WatchFileDescriptor(
756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        input_fd_, true, base::MessageLoopForIO::WATCH_READ,
766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        &read_socket_watcher_, this));
776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<PacketPipe> tmp(new SendToFDPipe(output_fd));
796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (packet_pipe_) {
806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      packet_pipe_->AppendToPipe(tmp.Pass());
816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    } else {
826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      packet_pipe_ = tmp.Pass();
836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    packet_pipe_->InitOnIOThread(base::MessageLoopProxy::current(),
856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                                 &tick_clock_);
866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual ~QueueManager() {
896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // MessageLoopForIO::Watcher methods
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    scoped_ptr<Packet> packet(new Packet(kMaxPacketSize));
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    int nread = read(input_fd_,
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                     reinterpret_cast<char*>(&packet->front()),
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                     kMaxPacketSize);
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (nread < 0) {
986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if (errno == EINTR) return;
996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      perror("read");
1006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      exit(1);
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    if (nread == 0) return;
1036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    packet->resize(nread);
1046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    packet_pipe_->Send(packet.Pass());
1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {
1076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    NOTREACHED();
1086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
1116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int input_fd_;
1126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<PacketPipe> packet_pipe_;
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::MessageLoopForIO::FileDescriptorWatcher read_socket_watcher_;
1146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::DefaultTickClock tick_clock_;
1156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
1166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace test
1186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace cast
1196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}  // namespace media
1206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)base::TimeTicks last_printout;
1226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ByteCounter {
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ByteCounter() : bytes_(0), packets_(0) {
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    push(base::TimeTicks::Now());
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::TimeDelta time_range() {
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return time_data_.back() - time_data_.front();
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void push(base::TimeTicks now) {
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    byte_data_.push_back(bytes_);
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    packet_data_.push_back(packets_);
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    time_data_.push_back(now);
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    while (time_range().InSeconds() > 10) {
1386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      byte_data_.pop_front();
1396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      packet_data_.pop_front();
1406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      time_data_.pop_front();
1416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
1426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  double megabits_per_second() {
1456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    double megabits = (byte_data_.back() - byte_data_.front()) * 8 / 1E6;
1466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return megabits / time_range().InSecondsF();
1476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  double packets_per_second() {
1506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    double packets = packet_data_.back()- packet_data_.front();
1516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return packets / time_range().InSecondsF();
1526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  void Increment(uint64 x) {
1556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bytes_ += x;
1566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    packets_ ++;
1576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
1606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  uint64 bytes_;
1616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  uint64 packets_;
1626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::deque<uint64> byte_data_;
1636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::deque<uint64> packet_data_;
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::deque<base::TimeTicks> time_data_;
1656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
1666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ByteCounter in_pipe_input_counter;
1686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ByteCounter in_pipe_output_counter;
1696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ByteCounter out_pipe_input_counter;
1706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)ByteCounter out_pipe_output_counter;
1716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)class ByteCounterPipe : public media::cast::test::PacketPipe {
1736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) public:
1746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ByteCounterPipe(ByteCounter* counter) : counter_(counter) {}
1756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  virtual void Send(scoped_ptr<media::cast::Packet> packet)
1766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      OVERRIDE {
1776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    counter_->Increment(packet->size());
1786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    pipe_->Send(packet.Pass());
1796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) private:
1816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ByteCounter* counter_;
1826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)};
1836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void SetupByteCounters(scoped_ptr<media::cast::test::PacketPipe>* pipe,
1856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       ByteCounter* pipe_input_counter,
1866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                       ByteCounter* pipe_output_counter) {
1876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  media::cast::test::PacketPipe* new_pipe =
1886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      new ByteCounterPipe(pipe_input_counter);
1896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  new_pipe->AppendToPipe(pipe->Pass());
1906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  new_pipe->AppendToPipe(
1916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      scoped_ptr<media::cast::test::PacketPipe>(
1926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          new ByteCounterPipe(pipe_output_counter)).Pass());
1936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  pipe->reset(new_pipe);
1946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void CheckByteCounters() {
1976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::TimeTicks now = base::TimeTicks::Now();
1986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  in_pipe_input_counter.push(now);
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  in_pipe_output_counter.push(now);
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  out_pipe_input_counter.push(now);
2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  out_pipe_output_counter.push(now);
2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if ((now - last_printout).InSeconds() >= 5) {
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    fprintf(stderr, "Sending  : %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            in_pipe_output_counter.megabits_per_second(),
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            in_pipe_input_counter.megabits_per_second(),
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            in_pipe_output_counter.packets_per_second(),
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            in_pipe_input_counter.packets_per_second());
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    fprintf(stderr, "Receiving: %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            out_pipe_output_counter.megabits_per_second(),
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            out_pipe_input_counter.megabits_per_second(),
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            out_pipe_output_counter.packets_per_second(),
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            out_pipe_input_counter.packets_per_second());
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    last_printout = now;
2156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::MessageLoopProxy::current()->PostDelayedTask(
2176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      FROM_HERE,
2186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::Bind(&CheckByteCounters),
2196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      base::TimeDelta::FromMilliseconds(100));
2206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)int tun_alloc(char *dev, int flags) {
2236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  struct ifreq ifr;
2246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int fd, err;
2256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const char *clonedev = "/dev/net/tun";
2266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  /* Arguments taken by the function:
2286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   *
2296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   * char *dev: the name of an interface (or '\0'). MUST have enough
2306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   *   space to hold the interface name if '\0' is passed
2316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   * int flags: interface flags (eg, IFF_TUN etc.)
2326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   */
2336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  /* open the clone device */
2356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if( (fd = open(clonedev, O_RDWR)) < 0 ) {
2366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return fd;
2376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  /* preparation of the struct ifr, of type "struct ifreq" */
2406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  memset(&ifr, 0, sizeof(ifr));
2416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ifr.ifr_flags = flags;   /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */
2436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (*dev) {
2456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    /* if a device name was specified, put it in the structure; otherwise,
2466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * the kernel will try to allocate the "next" device of the
2476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * specified type */
2486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    strncpy(ifr.ifr_name, dev, IFNAMSIZ);
2496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  /* try to create the device */
2526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) {
2536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    close(fd);
2546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return err;
2556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (!*dev) {
2586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    /* if the operation was successful, write back the name of the
2596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * interface to the variable "dev", so the caller can know
2606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * it. Note that the caller MUST reserve space in *dev (see calling
2616e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)     * code below) */
2626e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    strcpy(dev, ifr.ifr_name);
2636e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  /* this is the special file descriptor that the caller will use to talk
2666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)   * with the virtual interface */
2676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return fd;
2686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)int main(int argc, char **argv) {
2726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::AtExitManager exit_manager;
2736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CommandLine::Init(argc, argv);
2746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  InitLogging(logging::LoggingSettings());
2756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (argc < 4) {
2776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    fprintf(stderr, "Usage: tap_proxy tap1 tap2 type\n");
2786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    fprintf(stderr,
2796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            "Where 'type' is one of perfect, good, wifi, bad or evil\n");
2806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    exit(1);
2816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
2826e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2836e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  scoped_ptr<media::cast::test::PacketPipe> in_pipe, out_pipe;
2846e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string network_type = argv[3];
2856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (network_type == "perfect") {
2866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    // No action needed.
2876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (network_type == "good") {
2886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    in_pipe = media::cast::test::GoodNetwork().Pass();
2896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    out_pipe = media::cast::test::GoodNetwork().Pass();
2906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (network_type == "wifi") {
2916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    in_pipe = media::cast::test::WifiNetwork().Pass();
2926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    out_pipe = media::cast::test::WifiNetwork().Pass();
2936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (network_type == "bad") {
2946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    in_pipe = media::cast::test::BadNetwork().Pass();
2956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    out_pipe = media::cast::test::BadNetwork().Pass();
2966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else if (network_type == "evil") {
2976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    in_pipe = media::cast::test::EvilNetwork().Pass();
2986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    out_pipe = media::cast::test::EvilNetwork().Pass();
2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  } else {
3006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    fprintf(stderr, "Unknown network type.\n");
3016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    exit(1);
3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
3036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SetupByteCounters(&in_pipe, &in_pipe_input_counter, &in_pipe_output_counter);
3056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  SetupByteCounters(
3066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      &out_pipe, &out_pipe_input_counter, &out_pipe_output_counter);
3076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int fd1 = tun_alloc(argv[1], IFF_TAP);
3096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int fd2 = tun_alloc(argv[2], IFF_TAP);
3106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  base::MessageLoopForIO message_loop;
3126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  last_printout = base::TimeTicks::Now();
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  media::cast::test::QueueManager qm1(fd1, fd2, in_pipe.Pass());
3146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  media::cast::test::QueueManager qm2(fd2, fd1, out_pipe.Pass());
3156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  CheckByteCounters();
3166e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  printf("Press Ctrl-C when done.\n");
3176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  message_loop.Run();
3186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
319