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 ~FakeUdpSocket() override
;
44 void ReceivePacket(const rtc::SocketAddress
& from
,
45 const rtc::SocketAddress
& to
,
46 const scoped_refptr
<net::IOBuffer
>& data
,
49 // rtc::AsyncPacketSocket interface.
50 rtc::SocketAddress
GetLocalAddress() const override
;
51 rtc::SocketAddress
GetRemoteAddress() const override
;
52 int Send(const void* data
,
54 const rtc::PacketOptions
& options
) override
;
55 int SendTo(const void* data
,
57 const rtc::SocketAddress
& address
,
58 const rtc::PacketOptions
& options
) override
;
60 State
GetState() const override
;
61 int GetOption(rtc::Socket::Option option
, int* value
) override
;
62 int SetOption(rtc::Socket::Option option
, int value
) override
;
63 int GetError() const override
;
64 void SetError(int error
) override
;
67 FakePacketSocketFactory
* factory_
;
68 scoped_refptr
<FakeNetworkDispatcher
> dispatcher_
;
69 rtc::SocketAddress local_address_
;
72 DISALLOW_COPY_AND_ASSIGN(FakeUdpSocket
);
75 FakeUdpSocket::FakeUdpSocket(FakePacketSocketFactory
* factory
,
76 scoped_refptr
<FakeNetworkDispatcher
> dispatcher
,
77 const rtc::SocketAddress
& local_address
)
79 dispatcher_(dispatcher
),
80 local_address_(local_address
),
84 FakeUdpSocket::~FakeUdpSocket() {
85 factory_
->OnSocketDestroyed(local_address_
.port());
88 void FakeUdpSocket::ReceivePacket(const rtc::SocketAddress
& from
,
89 const rtc::SocketAddress
& to
,
90 const scoped_refptr
<net::IOBuffer
>& data
,
93 this, data
->data(), data_size
, from
, rtc::CreatePacketTime(0));
96 rtc::SocketAddress
FakeUdpSocket::GetLocalAddress() const {
97 return local_address_
;
100 rtc::SocketAddress
FakeUdpSocket::GetRemoteAddress() const {
102 return rtc::SocketAddress();
105 int FakeUdpSocket::Send(const void* data
, size_t data_size
,
106 const rtc::PacketOptions
& options
) {
111 int FakeUdpSocket::SendTo(const void* data
, size_t data_size
,
112 const rtc::SocketAddress
& address
,
113 const rtc::PacketOptions
& options
) {
114 scoped_refptr
<net::IOBuffer
> buffer
= new net::IOBuffer(data_size
);
115 memcpy(buffer
->data(), data
, data_size
);
116 dispatcher_
->DeliverPacket(local_address_
, address
, buffer
, data_size
);
120 int FakeUdpSocket::Close() {
121 state_
= STATE_CLOSED
;
125 rtc::AsyncPacketSocket::State
FakeUdpSocket::GetState() const {
129 int FakeUdpSocket::GetOption(rtc::Socket::Option option
, int* value
) {
134 int FakeUdpSocket::SetOption(rtc::Socket::Option option
, int value
) {
139 int FakeUdpSocket::GetError() const {
143 void FakeUdpSocket::SetError(int error
) {
149 FakePacketSocketFactory::PendingPacket::PendingPacket()
153 FakePacketSocketFactory::PendingPacket::PendingPacket(
154 const rtc::SocketAddress
& from
,
155 const rtc::SocketAddress
& to
,
156 const scoped_refptr
<net::IOBuffer
>& data
,
158 : from(from
), to(to
), data(data
), data_size(data_size
) {
161 FakePacketSocketFactory::PendingPacket::~PendingPacket() {
164 FakePacketSocketFactory::FakePacketSocketFactory(
165 FakeNetworkDispatcher
* dispatcher
)
166 : task_runner_(base::ThreadTaskRunnerHandle::Get()),
167 dispatcher_(dispatcher
),
168 address_(dispatcher_
->AllocateAddress()),
169 out_of_order_rate_(0.0),
170 next_port_(kPortRangeStart
),
171 weak_factory_(this) {
172 dispatcher_
->AddNode(this);
175 FakePacketSocketFactory::~FakePacketSocketFactory() {
176 CHECK(udp_sockets_
.empty());
177 dispatcher_
->RemoveNode(this);
180 void FakePacketSocketFactory::OnSocketDestroyed(int port
) {
181 DCHECK(task_runner_
->BelongsToCurrentThread());
182 udp_sockets_
.erase(port
);
185 void FakePacketSocketFactory::SetBandwidth(int bandwidth
, int max_buffer
) {
186 DCHECK(task_runner_
->BelongsToCurrentThread());
187 if (bandwidth
<= 0) {
188 leaky_bucket_
.reset();
190 leaky_bucket_
.reset(new LeakyBucket(max_buffer
, bandwidth
));
194 void FakePacketSocketFactory::SetLatency(base::TimeDelta average
,
195 base::TimeDelta stddev
) {
196 DCHECK(task_runner_
->BelongsToCurrentThread());
197 latency_average_
= average
;
198 latency_stddev_
= stddev
;
201 rtc::AsyncPacketSocket
* FakePacketSocketFactory::CreateUdpSocket(
202 const rtc::SocketAddress
& local_address
,
203 int min_port
, int max_port
) {
204 DCHECK(task_runner_
->BelongsToCurrentThread());
207 if (min_port
> 0 && max_port
> 0) {
208 for (int i
= min_port
; i
<= max_port
; ++i
) {
209 if (udp_sockets_
.find(i
) == udp_sockets_
.end()) {
220 (next_port_
>= kPortRangeEnd
) ? kPortRangeStart
: (next_port_
+ 1);
221 } while (udp_sockets_
.find(port
) != udp_sockets_
.end());
224 CHECK(local_address
.ipaddr() == address_
);
226 FakeUdpSocket
* result
=
227 new FakeUdpSocket(this, dispatcher_
,
228 rtc::SocketAddress(local_address
.ipaddr(), port
));
231 base::Bind(&FakeUdpSocket::ReceivePacket
, base::Unretained(result
));
236 rtc::AsyncPacketSocket
* FakePacketSocketFactory::CreateServerTcpSocket(
237 const rtc::SocketAddress
& local_address
,
238 int min_port
, int max_port
,
243 rtc::AsyncPacketSocket
* FakePacketSocketFactory::CreateClientTcpSocket(
244 const rtc::SocketAddress
& local_address
,
245 const rtc::SocketAddress
& remote_address
,
246 const rtc::ProxyInfo
& proxy_info
,
247 const std::string
& user_agent
,
252 rtc::AsyncResolverInterface
*
253 FakePacketSocketFactory::CreateAsyncResolver() {
257 const scoped_refptr
<base::SingleThreadTaskRunner
>&
258 FakePacketSocketFactory::GetThread() const {
262 const rtc::IPAddress
& FakePacketSocketFactory::GetAddress() const {
266 void FakePacketSocketFactory::ReceivePacket(
267 const rtc::SocketAddress
& from
,
268 const rtc::SocketAddress
& to
,
269 const scoped_refptr
<net::IOBuffer
>& data
,
271 DCHECK(task_runner_
->BelongsToCurrentThread());
272 DCHECK(to
.ipaddr() == address_
);
274 base::TimeDelta delay
;
277 delay
= leaky_bucket_
->AddPacket(data_size
);
278 if (delay
.is_max()) {
284 if (latency_average_
> base::TimeDelta()) {
285 delay
+= base::TimeDelta::FromMillisecondsD(
286 GetNormalRandom(latency_average_
.InMillisecondsF(),
287 latency_stddev_
.InMillisecondsF()));
289 if (delay
< base::TimeDelta())
290 delay
= base::TimeDelta();
292 // Put the packet to the |pending_packets_| and post a task for
293 // DoReceivePackets(). Note that the DoReceivePackets() task posted here may
294 // deliver a different packet, not the one added to the queue here. This
295 // would happen if another task gets posted with a shorted delay or when
296 // |out_of_order_rate_| is greater than 0. It's implemented this way to
297 // decouple latency variability from out-of-order delivery.
298 PendingPacket
packet(from
, to
, data
, data_size
);
299 pending_packets_
.push_back(packet
);
300 task_runner_
->PostDelayedTask(
302 base::Bind(&FakePacketSocketFactory::DoReceivePacket
,
303 weak_factory_
.GetWeakPtr()),
307 void FakePacketSocketFactory::DoReceivePacket() {
308 DCHECK(task_runner_
->BelongsToCurrentThread());
310 PendingPacket packet
;
311 if (pending_packets_
.size() > 1 && base::RandDouble() < out_of_order_rate_
) {
312 std::list
<PendingPacket
>::iterator it
= pending_packets_
.begin();
315 pending_packets_
.erase(it
);
317 packet
= pending_packets_
.front();
318 pending_packets_
.pop_front();
321 UdpSocketsMap::iterator iter
= udp_sockets_
.find(packet
.to
.port());
322 if (iter
== udp_sockets_
.end()) {
323 // Invalid port number.
327 iter
->second
.Run(packet
.from
, packet
.to
, packet
.data
, packet
.data_size
);
330 } // namespace remoting