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.
4
5#include "remoting/protocol/chromium_socket_factory.h"
6
7#include "base/message_loop/message_loop.h"
8#include "base/run_loop.h"
9#include "testing/gmock/include/gmock/gmock.h"
10#include "testing/gtest/include/gtest/gtest.h"
11#include "third_party/webrtc/base/asyncpacketsocket.h"
12#include "third_party/webrtc/base/socketaddress.h"
13
14namespace remoting {
15namespace protocol {
16
17class ChromiumSocketFactoryTest : public testing::Test,
18                                  public sigslot::has_slots<> {
19 public:
20  virtual void SetUp() OVERRIDE {
21    socket_factory_.reset(new ChromiumPacketSocketFactory());
22
23    socket_.reset(socket_factory_->CreateUdpSocket(
24        rtc::SocketAddress("127.0.0.1", 0), 0, 0));
25    ASSERT_TRUE(socket_.get() != NULL);
26    EXPECT_EQ(socket_->GetState(), rtc::AsyncPacketSocket::STATE_BOUND);
27    socket_->SignalReadPacket.connect(
28        this, &ChromiumSocketFactoryTest::OnPacket);
29  }
30
31  void OnPacket(rtc::AsyncPacketSocket* socket,
32                const char* data, size_t size,
33                const rtc::SocketAddress& address,
34                const rtc::PacketTime& packet_time) {
35    EXPECT_EQ(socket, socket_.get());
36    last_packet_.assign(data, data + size);
37    last_address_ = address;
38    run_loop_.Quit();
39  }
40
41  void VerifyCanSendAndReceive(rtc::AsyncPacketSocket* sender) {
42    // UDP packets may be lost, so we have to retry sending it more than once.
43    const int kMaxAttempts = 3;
44    const base::TimeDelta kAttemptPeriod = base::TimeDelta::FromSeconds(1);
45    std::string test_packet("TEST PACKET");
46    int attempts = 0;
47    rtc::PacketOptions options;
48    while (last_packet_.empty() && attempts++ < kMaxAttempts) {
49      sender->SendTo(test_packet.data(), test_packet.size(),
50                     socket_->GetLocalAddress(), options);
51      message_loop_.PostDelayedTask(FROM_HERE, run_loop_.QuitClosure(),
52                                    kAttemptPeriod);
53      run_loop_.Run();
54    }
55    EXPECT_EQ(test_packet, last_packet_);
56    EXPECT_EQ(sender->GetLocalAddress(), last_address_);
57  }
58
59 protected:
60  base::MessageLoopForIO message_loop_;
61  base::RunLoop run_loop_;
62
63  scoped_ptr<rtc::PacketSocketFactory> socket_factory_;
64  scoped_ptr<rtc::AsyncPacketSocket> socket_;
65
66  std::string last_packet_;
67  rtc::SocketAddress last_address_;
68};
69
70TEST_F(ChromiumSocketFactoryTest, SendAndReceive) {
71  scoped_ptr<rtc::AsyncPacketSocket> sending_socket(
72      socket_factory_->CreateUdpSocket(
73          rtc::SocketAddress("127.0.0.1", 0), 0, 0));
74  ASSERT_TRUE(sending_socket.get() != NULL);
75  EXPECT_EQ(sending_socket->GetState(),
76            rtc::AsyncPacketSocket::STATE_BOUND);
77
78  VerifyCanSendAndReceive(sending_socket.get());
79}
80
81TEST_F(ChromiumSocketFactoryTest, SetOptions) {
82  EXPECT_EQ(0, socket_->SetOption(rtc::Socket::OPT_SNDBUF, 4096));
83  EXPECT_EQ(0, socket_->SetOption(rtc::Socket::OPT_RCVBUF, 4096));
84}
85
86TEST_F(ChromiumSocketFactoryTest, PortRange) {
87  const int kMinPort = 12400;
88  const int kMaxPort = 12410;
89  socket_.reset(socket_factory_->CreateUdpSocket(
90      rtc::SocketAddress("127.0.0.1", 0), kMaxPort, kMaxPort));
91  ASSERT_TRUE(socket_.get() != NULL);
92  EXPECT_EQ(socket_->GetState(), rtc::AsyncPacketSocket::STATE_BOUND);
93  EXPECT_GE(socket_->GetLocalAddress().port(), kMinPort);
94  EXPECT_LE(socket_->GetLocalAddress().port(), kMaxPort);
95}
96
97TEST_F(ChromiumSocketFactoryTest, TransientError) {
98  scoped_ptr<rtc::AsyncPacketSocket> sending_socket(
99      socket_factory_->CreateUdpSocket(
100          rtc::SocketAddress("127.0.0.1", 0), 0, 0));
101  std::string test_packet("TEST");
102
103  // Try sending a packet to an IPv6 address from a socket that's bound to an
104  // IPv4 address. This send is expected to fail, but the socket should still be
105  // functional.
106  sending_socket->SendTo(test_packet.data(), test_packet.size(),
107                         rtc::SocketAddress("::1", 0),
108                         rtc::PacketOptions());
109
110  // Verify that socket is still usable.
111  VerifyCanSendAndReceive(sending_socket.get());
112}
113
114}  // namespace protocol
115}  // namespace remoting
116