Home | History | Annotate | Download | only in base
      1 /*
      2  * libjingle
      3  * Copyright 2012, Google Inc.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *
      8  *  1. Redistributions of source code must retain the above copyright notice,
      9  *     this list of conditions and the following disclaimer.
     10  *  2. Redistributions in binary form must reproduce the above copyright notice,
     11  *     this list of conditions and the following disclaimer in the documentation
     12  *     and/or other materials provided with the distribution.
     13  *  3. The name of the author may not be used to endorse or promote products
     14  *     derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
     17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
     18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
     19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
     25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 #include "talk/base/asynctcpsocket.h"
     29 #include "talk/base/buffer.h"
     30 #include "talk/base/firewallsocketserver.h"
     31 #include "talk/base/logging.h"
     32 #include "talk/base/gunit.h"
     33 #include "talk/base/helpers.h"
     34 #include "talk/base/physicalsocketserver.h"
     35 #include "talk/base/scoped_ptr.h"
     36 #include "talk/base/socketaddress.h"
     37 #include "talk/base/thread.h"
     38 #include "talk/base/virtualsocketserver.h"
     39 #include "talk/p2p/base/basicpacketsocketfactory.h"
     40 #include "talk/p2p/base/constants.h"
     41 #include "talk/p2p/base/tcpport.h"
     42 #include "talk/p2p/base/testturnserver.h"
     43 #include "talk/p2p/base/turnport.h"
     44 #include "talk/p2p/base/udpport.h"
     45 
     46 using talk_base::SocketAddress;
     47 using cricket::Connection;
     48 using cricket::Port;
     49 using cricket::PortInterface;
     50 using cricket::TurnPort;
     51 using cricket::UDPPort;
     52 
     53 static const SocketAddress kLocalAddr1("11.11.11.11", 0);
     54 static const SocketAddress kLocalAddr2("22.22.22.22", 0);
     55 static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
     56                                            cricket::TURN_SERVER_PORT);
     57 static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
     58                                            cricket::TURN_SERVER_PORT);
     59 static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
     60 
     61 static const char kIceUfrag1[] = "TESTICEUFRAG0001";
     62 static const char kIceUfrag2[] = "TESTICEUFRAG0002";
     63 static const char kIcePwd1[] = "TESTICEPWD00000000000001";
     64 static const char kIcePwd2[] = "TESTICEPWD00000000000002";
     65 static const char kTurnUsername[] = "test";
     66 static const char kTurnPassword[] = "test";
     67 static const int kTimeout = 1000;
     68 
     69 static const cricket::ProtocolAddress kTurnUdpProtoAddr(
     70     kTurnUdpIntAddr, cricket::PROTO_UDP);
     71 static const cricket::ProtocolAddress kTurnTcpProtoAddr(
     72     kTurnTcpIntAddr, cricket::PROTO_TCP);
     73 
     74 class TurnPortTest : public testing::Test,
     75                      public sigslot::has_slots<> {
     76  public:
     77   TurnPortTest()
     78       : main_(talk_base::Thread::Current()),
     79         pss_(new talk_base::PhysicalSocketServer),
     80         ss_(new talk_base::VirtualSocketServer(pss_.get())),
     81         ss_scope_(ss_.get()),
     82         network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
     83         socket_factory_(talk_base::Thread::Current()),
     84         turn_server_(main_, kTurnUdpIntAddr, kTurnUdpExtAddr),
     85         turn_ready_(false),
     86         turn_error_(false),
     87         turn_unknown_address_(false),
     88         turn_create_permission_success_(false),
     89         udp_ready_(false) {
     90     network_.AddIP(talk_base::IPAddress(INADDR_ANY));
     91   }
     92 
     93   void OnTurnPortComplete(Port* port) {
     94     turn_ready_ = true;
     95   }
     96   void OnTurnPortError(Port* port) {
     97     turn_error_ = true;
     98   }
     99   void OnTurnUnknownAddress(PortInterface* port, const SocketAddress& addr,
    100                             cricket::ProtocolType proto,
    101                             cricket::IceMessage* msg, const std::string& rf,
    102                             bool /*port_muxed*/) {
    103     turn_unknown_address_ = true;
    104   }
    105   void OnTurnCreatePermissionResult(TurnPort* port, const SocketAddress& addr,
    106                                      int code) {
    107     // Ignoring the address.
    108     if (code == 0) {
    109       turn_create_permission_success_ = true;
    110     }
    111   }
    112   void OnTurnReadPacket(Connection* conn, const char* data, size_t size) {
    113     turn_packets_.push_back(talk_base::Buffer(data, size));
    114   }
    115   void OnUdpPortComplete(Port* port) {
    116     udp_ready_ = true;
    117   }
    118   void OnUdpReadPacket(Connection* conn, const char* data, size_t size) {
    119     udp_packets_.push_back(talk_base::Buffer(data, size));
    120   }
    121 
    122   talk_base::AsyncSocket* CreateServerSocket(const SocketAddress addr) {
    123     talk_base::AsyncSocket* socket = ss_->CreateAsyncSocket(SOCK_STREAM);
    124     EXPECT_GE(socket->Bind(addr), 0);
    125     EXPECT_GE(socket->Listen(5), 0);
    126     return socket;
    127   }
    128 
    129   void CreateTurnPort(const std::string& username,
    130                       const std::string& password,
    131                       const cricket::ProtocolAddress& server_address) {
    132     cricket::RelayCredentials credentials(username, password);
    133     turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
    134                                  kLocalAddr1.ipaddr(), 0, 0,
    135                                  kIceUfrag1, kIcePwd1,
    136                                  server_address, credentials));
    137     turn_port_->SignalPortComplete.connect(this,
    138         &TurnPortTest::OnTurnPortComplete);
    139     turn_port_->SignalPortError.connect(this,
    140         &TurnPortTest::OnTurnPortError);
    141     turn_port_->SignalUnknownAddress.connect(this,
    142         &TurnPortTest::OnTurnUnknownAddress);
    143     turn_port_->SignalCreatePermissionResult.connect(this,
    144         &TurnPortTest::OnTurnCreatePermissionResult);
    145   }
    146   void CreateUdpPort() {
    147     udp_port_.reset(UDPPort::Create(main_, &socket_factory_, &network_,
    148                                     kLocalAddr2.ipaddr(), 0, 0,
    149                                     kIceUfrag2, kIcePwd2));
    150     udp_port_->SignalPortComplete.connect(
    151         this, &TurnPortTest::OnUdpPortComplete);
    152   }
    153 
    154   void TestTurnConnection() {
    155     // Create ports and prepare addresses.
    156     ASSERT_TRUE(turn_port_ != NULL);
    157     turn_port_->PrepareAddress();
    158     ASSERT_TRUE_WAIT(turn_ready_, kTimeout);
    159     CreateUdpPort();
    160     udp_port_->PrepareAddress();
    161     ASSERT_TRUE_WAIT(udp_ready_, kTimeout);
    162 
    163     // Send ping from UDP to TURN.
    164     Connection* conn1 = udp_port_->CreateConnection(
    165                     turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
    166     ASSERT_TRUE(conn1 != NULL);
    167     conn1->Ping(0);
    168     WAIT(!turn_unknown_address_, kTimeout);
    169     EXPECT_FALSE(turn_unknown_address_);
    170     EXPECT_EQ(Connection::STATE_READ_INIT, conn1->read_state());
    171     EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state());
    172 
    173     // Send ping from TURN to UDP.
    174     Connection* conn2 = turn_port_->CreateConnection(
    175                     udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
    176     ASSERT_TRUE(conn2 != NULL);
    177     ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout);
    178     conn2->Ping(0);
    179 
    180     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout);
    181     EXPECT_EQ(Connection::STATE_READABLE, conn1->read_state());
    182     EXPECT_EQ(Connection::STATE_READ_INIT, conn2->read_state());
    183     EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state());
    184 
    185     // Send another ping from UDP to TURN.
    186     conn1->Ping(0);
    187     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout);
    188     EXPECT_EQ(Connection::STATE_READABLE, conn2->read_state());
    189   }
    190 
    191   void TestTurnSendData() {
    192     turn_port_->PrepareAddress();
    193     EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
    194     CreateUdpPort();
    195     udp_port_->PrepareAddress();
    196     EXPECT_TRUE_WAIT(udp_ready_, kTimeout);
    197     // Create connections and send pings.
    198     Connection* conn1 = turn_port_->CreateConnection(
    199         udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
    200     Connection* conn2 = udp_port_->CreateConnection(
    201         turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
    202     ASSERT_TRUE(conn1 != NULL);
    203     ASSERT_TRUE(conn2 != NULL);
    204     conn1->SignalReadPacket.connect(static_cast<TurnPortTest*>(this),
    205                                     &TurnPortTest::OnTurnReadPacket);
    206     conn2->SignalReadPacket.connect(static_cast<TurnPortTest*>(this),
    207                                     &TurnPortTest::OnUdpReadPacket);
    208     conn1->Ping(0);
    209     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout);
    210     conn2->Ping(0);
    211     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout);
    212 
    213     // Send some data.
    214     size_t num_packets = 256;
    215     for (size_t i = 0; i < num_packets; ++i) {
    216       char buf[256];
    217       for (size_t j = 0; j < i + 1; ++j) {
    218         buf[j] = 0xFF - j;
    219       }
    220       conn1->Send(buf, i + 1);
    221       conn2->Send(buf, i + 1);
    222       main_->ProcessMessages(0);
    223     }
    224 
    225     // Check the data.
    226     ASSERT_EQ_WAIT(num_packets, turn_packets_.size(), kTimeout);
    227     ASSERT_EQ_WAIT(num_packets, udp_packets_.size(), kTimeout);
    228     for (size_t i = 0; i < num_packets; ++i) {
    229       EXPECT_EQ(i + 1, turn_packets_[i].length());
    230       EXPECT_EQ(i + 1, udp_packets_[i].length());
    231       EXPECT_EQ(turn_packets_[i], udp_packets_[i]);
    232     }
    233   }
    234 
    235  protected:
    236   talk_base::Thread* main_;
    237   talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
    238   talk_base::scoped_ptr<talk_base::VirtualSocketServer> ss_;
    239   talk_base::SocketServerScope ss_scope_;
    240   talk_base::Network network_;
    241   talk_base::BasicPacketSocketFactory socket_factory_;
    242   cricket::TestTurnServer turn_server_;
    243   talk_base::scoped_ptr<TurnPort> turn_port_;
    244   talk_base::scoped_ptr<UDPPort> udp_port_;
    245   bool turn_ready_;
    246   bool turn_error_;
    247   bool turn_unknown_address_;
    248   bool turn_create_permission_success_;
    249   bool udp_ready_;
    250   std::vector<talk_base::Buffer> turn_packets_;
    251   std::vector<talk_base::Buffer> udp_packets_;
    252 };
    253 
    254 // Do a normal TURN allocation.
    255 TEST_F(TurnPortTest, TestTurnAllocate) {
    256   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
    257   EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
    258   turn_port_->PrepareAddress();
    259   EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
    260   ASSERT_EQ(1U, turn_port_->Candidates().size());
    261   EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
    262             turn_port_->Candidates()[0].address().ipaddr());
    263   EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
    264 }
    265 
    266 TEST_F(TurnPortTest, TestTurnTcpAllocate) {
    267   talk_base::AsyncSocket* tcp_server_socket =
    268       CreateServerSocket(kTurnTcpIntAddr);
    269   turn_server_.server()->AddInternalServerSocket(
    270       tcp_server_socket, cricket::PROTO_TCP);
    271   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
    272   EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
    273   turn_port_->PrepareAddress();
    274   EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
    275   ASSERT_EQ(1U, turn_port_->Candidates().size());
    276   EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
    277             turn_port_->Candidates()[0].address().ipaddr());
    278   EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
    279 }
    280 
    281 // Try to do a TURN allocation with an invalid password.
    282 TEST_F(TurnPortTest, TestTurnAllocateBadPassword) {
    283   CreateTurnPort(kTurnUsername, "bad", kTurnUdpProtoAddr);
    284   turn_port_->PrepareAddress();
    285   EXPECT_TRUE_WAIT(turn_error_, kTimeout);
    286   ASSERT_EQ(0U, turn_port_->Candidates().size());
    287 }
    288 
    289 // Do a TURN allocation and try to send a packet to it from the outside.
    290 // The packet should be dropped. Then, try to send a packet from TURN to the
    291 // outside. It should reach its destination. Finally, try again from the
    292 // outside. It should now work as well.
    293 TEST_F(TurnPortTest, TestTurnConnection) {
    294   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
    295   TestTurnConnection();
    296 }
    297 
    298 // Test that we can establish a TCP connection with TURN server.
    299 TEST_F(TurnPortTest, TestTurnTcpConnection) {
    300   talk_base::AsyncSocket* tcp_server_socket =
    301       CreateServerSocket(kTurnTcpIntAddr);
    302   turn_server_.server()->AddInternalServerSocket(
    303       tcp_server_socket, cricket::PROTO_TCP);
    304   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
    305   TestTurnConnection();
    306 }
    307 
    308 // Test that we fail to create a connection when we want to use TLS over TCP.
    309 // This test should be removed once we have TLS support.
    310 TEST_F(TurnPortTest, TestTurnTlsTcpConnectionFails) {
    311   cricket::ProtocolAddress secure_addr(kTurnTcpProtoAddr.address,
    312                                        kTurnTcpProtoAddr.proto,
    313                                        true);
    314   CreateTurnPort(kTurnUsername, kTurnPassword, secure_addr);
    315   turn_port_->PrepareAddress();
    316   EXPECT_TRUE_WAIT(turn_error_, kTimeout);
    317   ASSERT_EQ(0U, turn_port_->Candidates().size());
    318 }
    319 
    320 // Run TurnConnectionTest with one-time-use nonce feature.
    321 // Here server will send a 438 STALE_NONCE error message for
    322 // every TURN transaction.
    323 TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
    324   turn_server_.set_enable_otu_nonce(true);
    325   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
    326   TestTurnConnection();
    327 }
    328 
    329 // Do a TURN allocation, establish a connection, and send some data.
    330 TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
    331   // Create ports and prepare addresses.
    332   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
    333   TestTurnSendData();
    334 }
    335 
    336 TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
    337   talk_base::AsyncSocket* tcp_server_socket =
    338       CreateServerSocket(kTurnTcpIntAddr);
    339   turn_server_.server()->AddInternalServerSocket(
    340       tcp_server_socket, cricket::PROTO_TCP);
    341   // Create ports and prepare addresses.
    342   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
    343   TestTurnSendData();
    344 }
    345