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