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.
10 #include "base/at_exit.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/logging.h"
14 #include "base/message_loop/message_loop.h"
15 #include "media/cast/test/utility/udp_proxy.h"
17 base::TimeTicks last_printout
;
21 ByteCounter() : bytes_(0), packets_(0) {
22 push(base::TimeTicks::Now());
25 base::TimeDelta
time_range() {
26 return time_data_
.back() - time_data_
.front();
29 void push(base::TimeTicks now
) {
30 byte_data_
.push_back(bytes_
);
31 packet_data_
.push_back(packets_
);
32 time_data_
.push_back(now
);
33 while (time_range().InSeconds() > 10) {
34 byte_data_
.pop_front();
35 packet_data_
.pop_front();
36 time_data_
.pop_front();
40 double megabits_per_second() {
41 double megabits
= (byte_data_
.back() - byte_data_
.front()) * 8 / 1E6
;
42 return megabits
/ time_range().InSecondsF();
45 double packets_per_second() {
46 double packets
= packet_data_
.back()- packet_data_
.front();
47 return packets
/ time_range().InSecondsF();
50 void Increment(uint64 x
) {
58 std::deque
<uint64
> byte_data_
;
59 std::deque
<uint64
> packet_data_
;
60 std::deque
<base::TimeTicks
> time_data_
;
63 ByteCounter in_pipe_input_counter
;
64 ByteCounter in_pipe_output_counter
;
65 ByteCounter out_pipe_input_counter
;
66 ByteCounter out_pipe_output_counter
;
68 class ByteCounterPipe
: public media::cast::test::PacketPipe
{
70 ByteCounterPipe(ByteCounter
* counter
) : counter_(counter
) {}
71 virtual void Send(scoped_ptr
<media::cast::transport::Packet
> packet
)
73 counter_
->Increment(packet
->size());
74 pipe_
->Send(packet
.Pass());
77 ByteCounter
* counter_
;
80 void SetupByteCounters(scoped_ptr
<media::cast::test::PacketPipe
>* pipe
,
81 ByteCounter
* pipe_input_counter
,
82 ByteCounter
* pipe_output_counter
) {
83 media::cast::test::PacketPipe
* new_pipe
=
84 new ByteCounterPipe(pipe_input_counter
);
85 new_pipe
->AppendToPipe(pipe
->Pass());
86 new_pipe
->AppendToPipe(
87 scoped_ptr
<media::cast::test::PacketPipe
>(
88 new ByteCounterPipe(pipe_output_counter
)).Pass());
89 pipe
->reset(new_pipe
);
92 void CheckByteCounters() {
93 base::TimeTicks now
= base::TimeTicks::Now();
94 in_pipe_input_counter
.push(now
);
95 in_pipe_output_counter
.push(now
);
96 out_pipe_input_counter
.push(now
);
97 out_pipe_output_counter
.push(now
);
98 if ((now
- last_printout
).InSeconds() >= 5) {
99 fprintf(stderr
, "Sending : %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
100 in_pipe_output_counter
.megabits_per_second(),
101 in_pipe_input_counter
.megabits_per_second(),
102 in_pipe_output_counter
.packets_per_second(),
103 in_pipe_input_counter
.packets_per_second());
104 fprintf(stderr
, "Receiving: %5.2f / %5.2f mbps %6.2f / %6.2f packets / s\n",
105 out_pipe_output_counter
.megabits_per_second(),
106 out_pipe_input_counter
.megabits_per_second(),
107 out_pipe_output_counter
.packets_per_second(),
108 out_pipe_input_counter
.packets_per_second());
112 base::MessageLoopProxy::current()->PostDelayedTask(
114 base::Bind(&CheckByteCounters
),
115 base::TimeDelta::FromMilliseconds(100));
118 int main(int argc
, char** argv
) {
121 "Usage: udp_proxy <localport> <remotehost> <remoteport> <type>\n"
122 "Where type is one of: perfect, wifi, bad, evil\n");
126 base::AtExitManager exit_manager
;
127 CommandLine::Init(argc
, argv
);
128 InitLogging(logging::LoggingSettings());
130 int local_port
= atoi(argv
[1]);
131 int remote_port
= atoi(argv
[3]);
132 net::IPAddressNumber remote_ip_number
;
133 net::IPAddressNumber local_ip_number
;
135 CHECK(net::ParseIPLiteralToNumber(argv
[2], &remote_ip_number
));
136 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &local_ip_number
));
137 net::IPEndPoint
remote_endpoint(remote_ip_number
, remote_port
);
138 net::IPEndPoint
local_endpoint(local_ip_number
, local_port
);
140 scoped_ptr
<media::cast::test::PacketPipe
> in_pipe
, out_pipe
;
141 std::string network_type
= argv
[4];
142 if (network_type
== "perfect") {
144 } else if (network_type
== "wifi") {
145 in_pipe
= media::cast::test::WifiNetwork().Pass();
146 out_pipe
= media::cast::test::WifiNetwork().Pass();
147 } else if (network_type
== "bad") {
148 in_pipe
= media::cast::test::BadNetwork().Pass();
149 out_pipe
= media::cast::test::BadNetwork().Pass();
150 } else if (network_type
== "evil") {
151 in_pipe
= media::cast::test::EvilNetwork().Pass();
152 out_pipe
= media::cast::test::EvilNetwork().Pass();
154 fprintf(stderr
, "Unknown network type.\n");
158 SetupByteCounters(&in_pipe
, &in_pipe_input_counter
, &in_pipe_output_counter
);
160 &out_pipe
, &out_pipe_input_counter
, &out_pipe_output_counter
);
162 printf("Press Ctrl-C when done.\n");
163 scoped_ptr
<media::cast::test::UDPProxy
> proxy(
164 media::cast::test::UDPProxy::Create(local_endpoint
,
169 base::MessageLoop message_loop
;
170 last_printout
= base::TimeTicks::Now();