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.
5 // MSVC++ requires this to be set before any other includes to get M_PI.
6 #define _USE_MATH_DEFINES
8 #include "remoting/test/fake_socket_factory.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/location.h"
15 #include "base/rand_util.h"
16 #include "base/single_thread_task_runner.h"
17 #include "base/thread_task_runner_handle.h"
18 #include "net/base/io_buffer.h"
19 #include "remoting/test/leaky_bucket.h"
20 #include "third_party/webrtc/base/asyncpacketsocket.h"
26 const int kPortRangeStart
= 1024;
27 const int kPortRangeEnd
= 65535;
29 double GetNormalRandom(double average
, double stddev
) {
30 // Based on Box-Muller transform, see
31 // http://en.wikipedia.org/wiki/Box_Muller_transform .
33 stddev
* sqrt(-2.0 * log(1.0 - base::RandDouble())) *
34 cos(base::RandDouble() * 2.0 * M_PI
);
37 class FakeUdpSocket
: public rtc::AsyncPacketSocket
{
39 FakeUdpSocket(FakePacketSocketFactory
* factory
,
40 scoped_refptr
<FakeNetworkDispatcher
> dispatcher
,
41 const rtc::SocketAddress
& local_address
);
42 virtual ~FakeUdpSocket();
44 void ReceivePacket(const rtc::SocketAddress
& from
,
45 const rtc::SocketAddress
& to
,
46 const scoped_refptr
<net::IOBuffer
>& data
,
49 // rtc::AsyncPacketSocket interface.
50 virtual rtc::SocketAddress
GetLocalAddress() const OVERRIDE
;
51 virtual rtc::SocketAddress
GetRemoteAddress() const OVERRIDE
;
52 virtual int Send(const void* data
, size_t data_size
,
53 const rtc::PacketOptions
& options
) OVERRIDE
;
54 virtual int SendTo(const void* data
, size_t data_size
,
55 const rtc::SocketAddress
& address
,
56 const rtc::PacketOptions
& options
) OVERRIDE
;
57 virtual int Close() OVERRIDE
;
58 virtual State
GetState() const OVERRIDE
;
59 virtual int GetOption(rtc::Socket::Option option
, int* value
) OVERRIDE
;
60 virtual int SetOption(rtc::Socket::Option option
, int value
) OVERRIDE
;
61 virtual int GetError() const OVERRIDE
;
62 virtual void SetError(int error
) OVERRIDE
;
65 FakePacketSocketFactory
* factory_
;
66 scoped_refptr
<FakeNetworkDispatcher
> dispatcher_
;
67 rtc::SocketAddress local_address_
;
70 DISALLOW_COPY_AND_ASSIGN(FakeUdpSocket
);
73 FakeUdpSocket::FakeUdpSocket(FakePacketSocketFactory
* factory
,
74 scoped_refptr
<FakeNetworkDispatcher
> dispatcher
,
75 const rtc::SocketAddress
& local_address
)
77 dispatcher_(dispatcher
),
78 local_address_(local_address
),
82 FakeUdpSocket::~FakeUdpSocket() {
83 factory_
->OnSocketDestroyed(local_address_
.port());
86 void FakeUdpSocket::ReceivePacket(const rtc::SocketAddress
& from
,
87 const rtc::SocketAddress
& to
,
88 const scoped_refptr
<net::IOBuffer
>& data
,
91 this, data
->data(), data_size
, from
, rtc::CreatePacketTime(0));
94 rtc::SocketAddress
FakeUdpSocket::GetLocalAddress() const {
95 return local_address_
;
98 rtc::SocketAddress
FakeUdpSocket::GetRemoteAddress() const {
100 return rtc::SocketAddress();
103 int FakeUdpSocket::Send(const void* data
, size_t data_size
,
104 const rtc::PacketOptions
& options
) {
109 int FakeUdpSocket::SendTo(const void* data
, size_t data_size
,
110 const rtc::SocketAddress
& address
,
111 const rtc::PacketOptions
& options
) {
112 scoped_refptr
<net::IOBuffer
> buffer
= new net::IOBuffer(data_size
);
113 memcpy(buffer
->data(), data
, data_size
);
114 dispatcher_
->DeliverPacket(local_address_
, address
, buffer
, data_size
);
118 int FakeUdpSocket::Close() {
119 state_
= STATE_CLOSED
;
123 rtc::AsyncPacketSocket::State
FakeUdpSocket::GetState() const {
127 int FakeUdpSocket::GetOption(rtc::Socket::Option option
, int* value
) {
132 int FakeUdpSocket::SetOption(rtc::Socket::Option option
, int value
) {
137 int FakeUdpSocket::GetError() const {
141 void FakeUdpSocket::SetError(int error
) {
147 FakePacketSocketFactory::PendingPacket::PendingPacket()
151 FakePacketSocketFactory::PendingPacket::PendingPacket(
152 const rtc::SocketAddress
& from
,
153 const rtc::SocketAddress
& to
,
154 const scoped_refptr
<net::IOBuffer
>& data
,
156 : from(from
), to(to
), data(data
), data_size(data_size
) {
159 FakePacketSocketFactory::PendingPacket::~PendingPacket() {
162 FakePacketSocketFactory::FakePacketSocketFactory(
163 FakeNetworkDispatcher
* dispatcher
)
164 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
165 dispatcher_(dispatcher
),
166 address_(dispatcher_
->AllocateAddress()),
167 out_of_order_rate_(0.0),
168 next_port_(kPortRangeStart
),
169 weak_factory_(this) {
170 dispatcher_
->AddNode(this);
173 FakePacketSocketFactory::~FakePacketSocketFactory() {
174 CHECK(udp_sockets_
.empty());
175 dispatcher_
->RemoveNode(this);
178 void FakePacketSocketFactory::OnSocketDestroyed(int port
) {
179 DCHECK(task_runner_
->BelongsToCurrentThread());
180 udp_sockets_
.erase(port
);
183 void FakePacketSocketFactory::SetBandwidth(int bandwidth
, int max_buffer
) {
184 DCHECK(task_runner_
->BelongsToCurrentThread());
185 if (bandwidth
<= 0) {
186 leaky_bucket_
.reset();
188 leaky_bucket_
.reset(new LeakyBucket(max_buffer
, bandwidth
));
192 void FakePacketSocketFactory::SetLatency(base::TimeDelta average
,
193 base::TimeDelta stddev
) {
194 DCHECK(task_runner_
->BelongsToCurrentThread());
195 latency_average_
= average
;
196 latency_stddev_
= stddev
;
199 rtc::AsyncPacketSocket
* FakePacketSocketFactory::CreateUdpSocket(
200 const rtc::SocketAddress
& local_address
,
201 int min_port
, int max_port
) {
202 DCHECK(task_runner_
->BelongsToCurrentThread());
205 if (min_port
> 0 && max_port
> 0) {
206 for (int i
= min_port
; i
<= max_port
; ++i
) {
207 if (udp_sockets_
.find(i
) == udp_sockets_
.end()) {
218 (next_port_
>= kPortRangeEnd
) ? kPortRangeStart
: (next_port_
+ 1);
219 } while (udp_sockets_
.find(port
) != udp_sockets_
.end());
222 CHECK(local_address
.ipaddr() == address_
);
224 FakeUdpSocket
* result
=
225 new FakeUdpSocket(this, dispatcher_
,
226 rtc::SocketAddress(local_address
.ipaddr(), port
));
229 base::Bind(&FakeUdpSocket::ReceivePacket
, base::Unretained(result
));
234 rtc::AsyncPacketSocket
* FakePacketSocketFactory::CreateServerTcpSocket(
235 const rtc::SocketAddress
& local_address
,
236 int min_port
, int max_port
,
241 rtc::AsyncPacketSocket
* FakePacketSocketFactory::CreateClientTcpSocket(
242 const rtc::SocketAddress
& local_address
,
243 const rtc::SocketAddress
& remote_address
,
244 const rtc::ProxyInfo
& proxy_info
,
245 const std::string
& user_agent
,
250 rtc::AsyncResolverInterface
*
251 FakePacketSocketFactory::CreateAsyncResolver() {
255 const scoped_refptr
<base::SingleThreadTaskRunner
>&
256 FakePacketSocketFactory::GetThread() const {
260 const rtc::IPAddress
& FakePacketSocketFactory::GetAddress() const {
264 void FakePacketSocketFactory::ReceivePacket(
265 const rtc::SocketAddress
& from
,
266 const rtc::SocketAddress
& to
,
267 const scoped_refptr
<net::IOBuffer
>& data
,
269 DCHECK(task_runner_
->BelongsToCurrentThread());
270 DCHECK(to
.ipaddr() == address_
);
272 base::TimeDelta delay
;
275 delay
= leaky_bucket_
->AddPacket(data_size
);
276 if (delay
.is_max()) {
282 if (latency_average_
> base::TimeDelta()) {
283 delay
+= base::TimeDelta::FromMillisecondsD(
284 GetNormalRandom(latency_average_
.InMillisecondsF(),
285 latency_stddev_
.InMillisecondsF()));
287 if (delay
< base::TimeDelta())
288 delay
= base::TimeDelta();
290 // Put the packet to the |pending_packets_| and post a task for
291 // DoReceivePackets(). Note that the DoReceivePackets() task posted here may
292 // deliver a different packet, not the one added to the queue here. This
293 // would happen if another task gets posted with a shorted delay or when
294 // |out_of_order_rate_| is greater than 0. It's implemented this way to
295 // decouple latency variability from out-of-order delivery.
296 PendingPacket
packet(from
, to
, data
, data_size
);
297 pending_packets_
.push_back(packet
);
298 task_runner_
->PostDelayedTask(
300 base::Bind(&FakePacketSocketFactory::DoReceivePacket
,
301 weak_factory_
.GetWeakPtr()),
305 void FakePacketSocketFactory::DoReceivePacket() {
306 DCHECK(task_runner_
->BelongsToCurrentThread());
308 PendingPacket packet
;
309 if (pending_packets_
.size() > 1 && base::RandDouble() < out_of_order_rate_
) {
310 std::list
<PendingPacket
>::iterator it
= pending_packets_
.begin();
313 pending_packets_
.erase(it
);
315 packet
= pending_packets_
.front();
316 pending_packets_
.pop_front();
319 UdpSocketsMap::iterator iter
= udp_sockets_
.find(packet
.to
.port());
320 if (iter
== udp_sockets_
.end()) {
321 // Invalid port number.
325 iter
->second
.Run(packet
.from
, packet
.to
, packet
.data
, packet
.data_size
);
328 } // namespace remoting