 d4e598d57a
			
		
	
	d4e598d57a
	
	
	
		
			
			git-svn-id: http://webrtc.googlecode.com/svn/trunk@6799 4adac7df-926f-26a2-2b94-8c16560cd09d
		
			
				
	
	
		
			519 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			519 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * libjingle
 | |
|  * Copyright 2012, Google Inc.
 | |
|  *
 | |
|  * Redistribution and use in source and binary forms, with or without
 | |
|  * modification, are permitted provided that the following conditions are met:
 | |
|  *
 | |
|  *  1. Redistributions of source code must retain the above copyright notice,
 | |
|  *     this list of conditions and the following disclaimer.
 | |
|  *  2. Redistributions in binary form must reproduce the above copyright notice,
 | |
|  *     this list of conditions and the following disclaimer in the documentation
 | |
|  *     and/or other materials provided with the distribution.
 | |
|  *  3. The name of the author may not be used to endorse or promote products
 | |
|  *     derived from this software without specific prior written permission.
 | |
|  *
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 | |
|  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 | |
|  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 | |
|  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 | |
|  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 | |
|  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 | |
|  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 | |
|  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 | |
|  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 | |
|  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 | |
|  */
 | |
| #if defined(POSIX)
 | |
| #include <dirent.h>
 | |
| #endif
 | |
| 
 | |
| #include "webrtc/base/asynctcpsocket.h"
 | |
| #include "webrtc/base/buffer.h"
 | |
| #include "webrtc/base/dscp.h"
 | |
| #include "webrtc/base/firewallsocketserver.h"
 | |
| #include "webrtc/base/logging.h"
 | |
| #include "webrtc/base/gunit.h"
 | |
| #include "webrtc/base/helpers.h"
 | |
| #include "webrtc/base/physicalsocketserver.h"
 | |
| #include "webrtc/base/scoped_ptr.h"
 | |
| #include "webrtc/base/socketaddress.h"
 | |
| #include "webrtc/base/ssladapter.h"
 | |
| #include "webrtc/base/thread.h"
 | |
| #include "webrtc/base/virtualsocketserver.h"
 | |
| #include "talk/p2p/base/basicpacketsocketfactory.h"
 | |
| #include "talk/p2p/base/constants.h"
 | |
| #include "talk/p2p/base/tcpport.h"
 | |
| #include "talk/p2p/base/testturnserver.h"
 | |
| #include "talk/p2p/base/turnport.h"
 | |
| #include "talk/p2p/base/udpport.h"
 | |
| 
 | |
| using rtc::SocketAddress;
 | |
| using cricket::Connection;
 | |
| using cricket::Port;
 | |
| using cricket::PortInterface;
 | |
| using cricket::TurnPort;
 | |
| using cricket::UDPPort;
 | |
| 
 | |
| static const SocketAddress kLocalAddr1("11.11.11.11", 0);
 | |
| static const SocketAddress kLocalAddr2("22.22.22.22", 0);
 | |
| static const SocketAddress kLocalIPv6Addr(
 | |
|     "2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
 | |
| static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
 | |
|                                            cricket::TURN_SERVER_PORT);
 | |
| static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
 | |
|                                            cricket::TURN_SERVER_PORT);
 | |
| static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
 | |
| static const SocketAddress kTurnUdpIPv6IntAddr(
 | |
|     "2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT);
 | |
| static const SocketAddress kTurnUdpIPv6ExtAddr(
 | |
|   "2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0);
 | |
| 
 | |
| static const char kIceUfrag1[] = "TESTICEUFRAG0001";
 | |
| static const char kIceUfrag2[] = "TESTICEUFRAG0002";
 | |
| static const char kIcePwd1[] = "TESTICEPWD00000000000001";
 | |
| static const char kIcePwd2[] = "TESTICEPWD00000000000002";
 | |
| static const char kTurnUsername[] = "test";
 | |
| static const char kTurnPassword[] = "test";
 | |
| static const unsigned int kTimeout = 1000;
 | |
| 
 | |
| static const cricket::ProtocolAddress kTurnUdpProtoAddr(
 | |
|     kTurnUdpIntAddr, cricket::PROTO_UDP);
 | |
| static const cricket::ProtocolAddress kTurnTcpProtoAddr(
 | |
|     kTurnTcpIntAddr, cricket::PROTO_TCP);
 | |
| static const cricket::ProtocolAddress kTurnUdpIPv6ProtoAddr(
 | |
|     kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
 | |
| 
 | |
| static const unsigned int MSG_TESTFINISH = 0;
 | |
| 
 | |
| #if defined(LINUX)
 | |
| static int GetFDCount() {
 | |
|   struct dirent *dp;
 | |
|   int fd_count = 0;
 | |
|   DIR *dir = opendir("/proc/self/fd/");
 | |
|   while ((dp = readdir(dir)) != NULL) {
 | |
|     if (dp->d_name[0] == '.')
 | |
|       continue;
 | |
|     ++fd_count;
 | |
|   }
 | |
|   closedir(dir);
 | |
|   return fd_count;
 | |
| }
 | |
| #endif
 | |
| 
 | |
| class TurnPortTest : public testing::Test,
 | |
|                      public sigslot::has_slots<>,
 | |
|                      public rtc::MessageHandler {
 | |
|  public:
 | |
|   TurnPortTest()
 | |
|       : main_(rtc::Thread::Current()),
 | |
|         pss_(new rtc::PhysicalSocketServer),
 | |
|         ss_(new rtc::VirtualSocketServer(pss_.get())),
 | |
|         ss_scope_(ss_.get()),
 | |
|         network_("unittest", "unittest", rtc::IPAddress(INADDR_ANY), 32),
 | |
|         socket_factory_(rtc::Thread::Current()),
 | |
|         turn_server_(main_, kTurnUdpIntAddr, kTurnUdpExtAddr),
 | |
|         turn_ready_(false),
 | |
|         turn_error_(false),
 | |
|         turn_unknown_address_(false),
 | |
|         turn_create_permission_success_(false),
 | |
|         udp_ready_(false),
 | |
|         test_finish_(false) {
 | |
|     network_.AddIP(rtc::IPAddress(INADDR_ANY));
 | |
|   }
 | |
| 
 | |
|   static void SetUpTestCase() {
 | |
|     rtc::InitializeSSL();
 | |
|   }
 | |
| 
 | |
|   static void TearDownTestCase() {
 | |
|     rtc::CleanupSSL();
 | |
|   }
 | |
| 
 | |
|   virtual void OnMessage(rtc::Message* msg) {
 | |
|     ASSERT(msg->message_id == MSG_TESTFINISH);
 | |
|     if (msg->message_id == MSG_TESTFINISH)
 | |
|       test_finish_ = true;
 | |
|   }
 | |
| 
 | |
|   void OnTurnPortComplete(Port* port) {
 | |
|     turn_ready_ = true;
 | |
|   }
 | |
|   void OnTurnPortError(Port* port) {
 | |
|     turn_error_ = true;
 | |
|   }
 | |
|   void OnTurnUnknownAddress(PortInterface* port, const SocketAddress& addr,
 | |
|                             cricket::ProtocolType proto,
 | |
|                             cricket::IceMessage* msg, const std::string& rf,
 | |
|                             bool /*port_muxed*/) {
 | |
|     turn_unknown_address_ = true;
 | |
|   }
 | |
|   void OnTurnCreatePermissionResult(TurnPort* port, const SocketAddress& addr,
 | |
|                                      int code) {
 | |
|     // Ignoring the address.
 | |
|     if (code == 0) {
 | |
|       turn_create_permission_success_ = true;
 | |
|     }
 | |
|   }
 | |
|   void OnTurnReadPacket(Connection* conn, const char* data, size_t size,
 | |
|                         const rtc::PacketTime& packet_time) {
 | |
|     turn_packets_.push_back(rtc::Buffer(data, size));
 | |
|   }
 | |
|   void OnUdpPortComplete(Port* port) {
 | |
|     udp_ready_ = true;
 | |
|   }
 | |
|   void OnUdpReadPacket(Connection* conn, const char* data, size_t size,
 | |
|                        const rtc::PacketTime& packet_time) {
 | |
|     udp_packets_.push_back(rtc::Buffer(data, size));
 | |
|   }
 | |
|   void OnSocketReadPacket(rtc::AsyncPacketSocket* socket,
 | |
|                           const char* data, size_t size,
 | |
|                           const rtc::SocketAddress& remote_addr,
 | |
|                           const rtc::PacketTime& packet_time) {
 | |
|     turn_port_->HandleIncomingPacket(socket, data, size, remote_addr,
 | |
|                                      packet_time);
 | |
|   }
 | |
|   rtc::AsyncSocket* CreateServerSocket(const SocketAddress addr) {
 | |
|     rtc::AsyncSocket* socket = ss_->CreateAsyncSocket(SOCK_STREAM);
 | |
|     EXPECT_GE(socket->Bind(addr), 0);
 | |
|     EXPECT_GE(socket->Listen(5), 0);
 | |
|     return socket;
 | |
|   }
 | |
| 
 | |
|   void CreateTurnPort(const std::string& username,
 | |
|                       const std::string& password,
 | |
|                       const cricket::ProtocolAddress& server_address) {
 | |
|     CreateTurnPort(kLocalAddr1, username, password, server_address);
 | |
|   }
 | |
|   void CreateTurnPort(const rtc::SocketAddress& local_address,
 | |
|                       const std::string& username,
 | |
|                       const std::string& password,
 | |
|                       const cricket::ProtocolAddress& server_address) {
 | |
|     cricket::RelayCredentials credentials(username, password);
 | |
|     turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
 | |
|                                  local_address.ipaddr(), 0, 0,
 | |
|                                  kIceUfrag1, kIcePwd1,
 | |
|                                  server_address, credentials, 0));
 | |
|     // Set ICE protocol type to ICEPROTO_RFC5245, as port by default will be
 | |
|     // in Hybrid mode. Protocol type is necessary to send correct type STUN ping
 | |
|     // messages.
 | |
|     // This TURN port will be the controlling.
 | |
|     turn_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
 | |
|     turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING);
 | |
|     ConnectSignals();
 | |
|   }
 | |
| 
 | |
|   void CreateSharedTurnPort(const std::string& username,
 | |
|                             const std::string& password,
 | |
|                             const cricket::ProtocolAddress& server_address) {
 | |
|     ASSERT(server_address.proto == cricket::PROTO_UDP);
 | |
| 
 | |
|     socket_.reset(socket_factory_.CreateUdpSocket(
 | |
|         rtc::SocketAddress(kLocalAddr1.ipaddr(), 0), 0, 0));
 | |
|     ASSERT_TRUE(socket_ != NULL);
 | |
|     socket_->SignalReadPacket.connect(this, &TurnPortTest::OnSocketReadPacket);
 | |
| 
 | |
|     cricket::RelayCredentials credentials(username, password);
 | |
|     turn_port_.reset(cricket::TurnPort::Create(
 | |
|         main_, &socket_factory_, &network_, socket_.get(),
 | |
|         kIceUfrag1, kIcePwd1, server_address, credentials, 0));
 | |
|     // Set ICE protocol type to ICEPROTO_RFC5245, as port by default will be
 | |
|     // in Hybrid mode. Protocol type is necessary to send correct type STUN ping
 | |
|     // messages.
 | |
|     // This TURN port will be the controlling.
 | |
|     turn_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
 | |
|     turn_port_->SetIceRole(cricket::ICEROLE_CONTROLLING);
 | |
|     ConnectSignals();
 | |
|   }
 | |
| 
 | |
|   void ConnectSignals() {
 | |
|     turn_port_->SignalPortComplete.connect(this,
 | |
|         &TurnPortTest::OnTurnPortComplete);
 | |
|     turn_port_->SignalPortError.connect(this,
 | |
|         &TurnPortTest::OnTurnPortError);
 | |
|     turn_port_->SignalUnknownAddress.connect(this,
 | |
|         &TurnPortTest::OnTurnUnknownAddress);
 | |
|     turn_port_->SignalCreatePermissionResult.connect(this,
 | |
|         &TurnPortTest::OnTurnCreatePermissionResult);
 | |
|   }
 | |
|   void CreateUdpPort() {
 | |
|     udp_port_.reset(UDPPort::Create(main_, &socket_factory_, &network_,
 | |
|                                     kLocalAddr2.ipaddr(), 0, 0,
 | |
|                                     kIceUfrag2, kIcePwd2));
 | |
|     // Set protocol type to RFC5245, as turn port is also in same mode.
 | |
|     // UDP port will be controlled.
 | |
|     udp_port_->SetIceProtocolType(cricket::ICEPROTO_RFC5245);
 | |
|     udp_port_->SetIceRole(cricket::ICEROLE_CONTROLLED);
 | |
|     udp_port_->SignalPortComplete.connect(
 | |
|         this, &TurnPortTest::OnUdpPortComplete);
 | |
|   }
 | |
| 
 | |
|   void TestTurnConnection() {
 | |
|     // Create ports and prepare addresses.
 | |
|     ASSERT_TRUE(turn_port_ != NULL);
 | |
|     turn_port_->PrepareAddress();
 | |
|     ASSERT_TRUE_WAIT(turn_ready_, kTimeout);
 | |
|     CreateUdpPort();
 | |
|     udp_port_->PrepareAddress();
 | |
|     ASSERT_TRUE_WAIT(udp_ready_, kTimeout);
 | |
| 
 | |
|     // Send ping from UDP to TURN.
 | |
|     Connection* conn1 = udp_port_->CreateConnection(
 | |
|                     turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
 | |
|     ASSERT_TRUE(conn1 != NULL);
 | |
|     conn1->Ping(0);
 | |
|     WAIT(!turn_unknown_address_, kTimeout);
 | |
|     EXPECT_FALSE(turn_unknown_address_);
 | |
|     EXPECT_EQ(Connection::STATE_READ_INIT, conn1->read_state());
 | |
|     EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state());
 | |
| 
 | |
|     // Send ping from TURN to UDP.
 | |
|     Connection* conn2 = turn_port_->CreateConnection(
 | |
|                     udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
 | |
|     ASSERT_TRUE(conn2 != NULL);
 | |
|     ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout);
 | |
|     conn2->Ping(0);
 | |
| 
 | |
|     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout);
 | |
|     EXPECT_EQ(Connection::STATE_READABLE, conn1->read_state());
 | |
|     EXPECT_EQ(Connection::STATE_READ_INIT, conn2->read_state());
 | |
|     EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state());
 | |
| 
 | |
|     // Send another ping from UDP to TURN.
 | |
|     conn1->Ping(0);
 | |
|     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout);
 | |
|     EXPECT_EQ(Connection::STATE_READABLE, conn2->read_state());
 | |
|   }
 | |
| 
 | |
|   void TestTurnSendData() {
 | |
|     turn_port_->PrepareAddress();
 | |
|     EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
 | |
|     CreateUdpPort();
 | |
|     udp_port_->PrepareAddress();
 | |
|     EXPECT_TRUE_WAIT(udp_ready_, kTimeout);
 | |
|     // Create connections and send pings.
 | |
|     Connection* conn1 = turn_port_->CreateConnection(
 | |
|         udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
 | |
|     Connection* conn2 = udp_port_->CreateConnection(
 | |
|         turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
 | |
|     ASSERT_TRUE(conn1 != NULL);
 | |
|     ASSERT_TRUE(conn2 != NULL);
 | |
|     conn1->SignalReadPacket.connect(static_cast<TurnPortTest*>(this),
 | |
|                                     &TurnPortTest::OnTurnReadPacket);
 | |
|     conn2->SignalReadPacket.connect(static_cast<TurnPortTest*>(this),
 | |
|                                     &TurnPortTest::OnUdpReadPacket);
 | |
|     conn1->Ping(0);
 | |
|     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout);
 | |
|     conn2->Ping(0);
 | |
|     EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout);
 | |
| 
 | |
|     // Send some data.
 | |
|     size_t num_packets = 256;
 | |
|     for (size_t i = 0; i < num_packets; ++i) {
 | |
|       unsigned char buf[256] = { 0 };
 | |
|       for (size_t j = 0; j < i + 1; ++j) {
 | |
|         buf[j] = 0xFF - static_cast<unsigned char>(j);
 | |
|       }
 | |
|       conn1->Send(buf, i + 1, options);
 | |
|       conn2->Send(buf, i + 1, options);
 | |
|       main_->ProcessMessages(0);
 | |
|     }
 | |
| 
 | |
|     // Check the data.
 | |
|     ASSERT_EQ_WAIT(num_packets, turn_packets_.size(), kTimeout);
 | |
|     ASSERT_EQ_WAIT(num_packets, udp_packets_.size(), kTimeout);
 | |
|     for (size_t i = 0; i < num_packets; ++i) {
 | |
|       EXPECT_EQ(i + 1, turn_packets_[i].length());
 | |
|       EXPECT_EQ(i + 1, udp_packets_[i].length());
 | |
|       EXPECT_EQ(turn_packets_[i], udp_packets_[i]);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|  protected:
 | |
|   rtc::Thread* main_;
 | |
|   rtc::scoped_ptr<rtc::PhysicalSocketServer> pss_;
 | |
|   rtc::scoped_ptr<rtc::VirtualSocketServer> ss_;
 | |
|   rtc::SocketServerScope ss_scope_;
 | |
|   rtc::Network network_;
 | |
|   rtc::BasicPacketSocketFactory socket_factory_;
 | |
|   rtc::scoped_ptr<rtc::AsyncPacketSocket> socket_;
 | |
|   cricket::TestTurnServer turn_server_;
 | |
|   rtc::scoped_ptr<TurnPort> turn_port_;
 | |
|   rtc::scoped_ptr<UDPPort> udp_port_;
 | |
|   bool turn_ready_;
 | |
|   bool turn_error_;
 | |
|   bool turn_unknown_address_;
 | |
|   bool turn_create_permission_success_;
 | |
|   bool udp_ready_;
 | |
|   bool test_finish_;
 | |
|   std::vector<rtc::Buffer> turn_packets_;
 | |
|   std::vector<rtc::Buffer> udp_packets_;
 | |
|   rtc::PacketOptions options;
 | |
| };
 | |
| 
 | |
| // Do a normal TURN allocation.
 | |
| TEST_F(TurnPortTest, TestTurnAllocate) {
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
 | |
|   EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10*1024));
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
 | |
|   ASSERT_EQ(1U, turn_port_->Candidates().size());
 | |
|   EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
 | |
|             turn_port_->Candidates()[0].address().ipaddr());
 | |
|   EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
 | |
| }
 | |
| 
 | |
| // Testing a normal UDP allocation using TCP connection.
 | |
| TEST_F(TurnPortTest, TestTurnTcpAllocate) {
 | |
|   turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
 | |
|   EXPECT_EQ(0, turn_port_->SetOption(rtc::Socket::OPT_SNDBUF, 10*1024));
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
 | |
|   ASSERT_EQ(1U, turn_port_->Candidates().size());
 | |
|   EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
 | |
|             turn_port_->Candidates()[0].address().ipaddr());
 | |
|   EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
 | |
| }
 | |
| 
 | |
| // Testing turn port will attempt to create TCP socket on address resolution
 | |
| // failure.
 | |
| TEST_F(TurnPortTest, TestTurnTcpOnAddressResolveFailure) {
 | |
|   turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, cricket::ProtocolAddress(
 | |
|       rtc::SocketAddress("www.webrtc-blah-blah.com", 3478),
 | |
|       cricket::PROTO_TCP));
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_error_, kTimeout);
 | |
|   // As VSS doesn't provide a DNS resolution, name resolve will fail. TurnPort
 | |
|   // will proceed in creating a TCP socket which will fail as there is no
 | |
|   // server on the above domain and error will be set to SOCKET_ERROR.
 | |
|   EXPECT_EQ(SOCKET_ERROR, turn_port_->error());
 | |
| }
 | |
| 
 | |
| // In case of UDP on address resolve failure, TurnPort will not create socket
 | |
| // and return allocate failure.
 | |
| TEST_F(TurnPortTest, TestTurnUdpOnAdressResolveFailure) {
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, cricket::ProtocolAddress(
 | |
|       rtc::SocketAddress("www.webrtc-blah-blah.com", 3478),
 | |
|       cricket::PROTO_UDP));
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_error_, kTimeout);
 | |
|   // Error from turn port will not be socket error.
 | |
|   EXPECT_NE(SOCKET_ERROR, turn_port_->error());
 | |
| }
 | |
| 
 | |
| // Try to do a TURN allocation with an invalid password.
 | |
| TEST_F(TurnPortTest, TestTurnAllocateBadPassword) {
 | |
|   CreateTurnPort(kTurnUsername, "bad", kTurnUdpProtoAddr);
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_error_, kTimeout);
 | |
|   ASSERT_EQ(0U, turn_port_->Candidates().size());
 | |
| }
 | |
| 
 | |
| // Do a TURN allocation and try to send a packet to it from the outside.
 | |
| // The packet should be dropped. Then, try to send a packet from TURN to the
 | |
| // outside. It should reach its destination. Finally, try again from the
 | |
| // outside. It should now work as well.
 | |
| TEST_F(TurnPortTest, TestTurnConnection) {
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
 | |
|   TestTurnConnection();
 | |
| }
 | |
| 
 | |
| // Similar to above, except that this test will use the shared socket.
 | |
| TEST_F(TurnPortTest, TestTurnConnectionUsingSharedSocket) {
 | |
|   CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
 | |
|   TestTurnConnection();
 | |
| }
 | |
| 
 | |
| // Test that we can establish a TCP connection with TURN server.
 | |
| TEST_F(TurnPortTest, TestTurnTcpConnection) {
 | |
|   turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
 | |
|   TestTurnConnection();
 | |
| }
 | |
| 
 | |
| // Test that we fail to create a connection when we want to use TLS over TCP.
 | |
| // This test should be removed once we have TLS support.
 | |
| TEST_F(TurnPortTest, TestTurnTlsTcpConnectionFails) {
 | |
|   cricket::ProtocolAddress secure_addr(kTurnTcpProtoAddr.address,
 | |
|                                        kTurnTcpProtoAddr.proto,
 | |
|                                        true);
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, secure_addr);
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_error_, kTimeout);
 | |
|   ASSERT_EQ(0U, turn_port_->Candidates().size());
 | |
| }
 | |
| 
 | |
| // Run TurnConnectionTest with one-time-use nonce feature.
 | |
| // Here server will send a 438 STALE_NONCE error message for
 | |
| // every TURN transaction.
 | |
| TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
 | |
|   turn_server_.set_enable_otu_nonce(true);
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
 | |
|   TestTurnConnection();
 | |
| }
 | |
| 
 | |
| // Do a TURN allocation, establish a UDP connection, and send some data.
 | |
| TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
 | |
|   // Create ports and prepare addresses.
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
 | |
|   TestTurnSendData();
 | |
| }
 | |
| 
 | |
| // Do a TURN allocation, establish a TCP connection, and send some data.
 | |
| TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
 | |
|   turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
 | |
|   // Create ports and prepare addresses.
 | |
|   CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
 | |
|   TestTurnSendData();
 | |
| }
 | |
| 
 | |
| // Test TURN fails to make a connection from IPv6 address to a server which has
 | |
| // IPv4 address.
 | |
| TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv4) {
 | |
|   turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
 | |
|   CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
 | |
|                  kTurnUdpProtoAddr);
 | |
|   turn_port_->PrepareAddress();
 | |
|   ASSERT_TRUE_WAIT(turn_error_, kTimeout);
 | |
|   EXPECT_TRUE(turn_port_->Candidates().empty());
 | |
| }
 | |
| 
 | |
| // Test TURN make a connection from IPv6 address to a server which has
 | |
| // IPv6 intenal address. But in this test external address is a IPv4 address,
 | |
| // hence allocated address will be a IPv4 address.
 | |
| TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) {
 | |
|   turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
 | |
|   CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
 | |
|                  kTurnUdpIPv6ProtoAddr);
 | |
|   turn_port_->PrepareAddress();
 | |
|   EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
 | |
|   ASSERT_EQ(1U, turn_port_->Candidates().size());
 | |
|   EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
 | |
|             turn_port_->Candidates()[0].address().ipaddr());
 | |
|   EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
 | |
| }
 | |
| 
 | |
| // This test verifies any FD's are not leaked after TurnPort is destroyed.
 | |
| // https://code.google.com/p/webrtc/issues/detail?id=2651
 | |
| #if defined(LINUX)
 | |
| TEST_F(TurnPortTest, TestResolverShutdown) {
 | |
|   turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
 | |
|   int last_fd_count = GetFDCount();
 | |
|   // Need to supply unresolved address to kick off resolver.
 | |
|   CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
 | |
|                  cricket::ProtocolAddress(rtc::SocketAddress(
 | |
|                     "stun.l.google.com", 3478), cricket::PROTO_UDP));
 | |
|   turn_port_->PrepareAddress();
 | |
|   ASSERT_TRUE_WAIT(turn_error_, kTimeout);
 | |
|   EXPECT_TRUE(turn_port_->Candidates().empty());
 | |
|   turn_port_.reset();
 | |
|   rtc::Thread::Current()->Post(this, MSG_TESTFINISH);
 | |
|   // Waiting for above message to be processed.
 | |
|   ASSERT_TRUE_WAIT(test_finish_, kTimeout);
 | |
|   EXPECT_EQ(last_fd_count, GetFDCount());
 | |
| }
 | |
| #endif
 | |
| 
 |