#include <dirent.h>
#endif
-#include "talk/base/asynctcpsocket.h"
-#include "talk/base/buffer.h"
-#include "talk/base/dscp.h"
-#include "talk/base/firewallsocketserver.h"
-#include "talk/base/logging.h"
-#include "talk/base/gunit.h"
-#include "talk/base/helpers.h"
-#include "talk/base/physicalsocketserver.h"
-#include "talk/base/scoped_ptr.h"
-#include "talk/base/socketaddress.h"
-#include "talk/base/thread.h"
-#include "talk/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 talk_base::SocketAddress;
+#include "webrtc/p2p/base/basicpacketsocketfactory.h"
+#include "webrtc/p2p/base/constants.h"
+#include "webrtc/p2p/base/tcpport.h"
+#include "webrtc/p2p/base/testturnserver.h"
+#include "webrtc/p2p/base/turnport.h"
+#include "webrtc/p2p/base/udpport.h"
+#include "webrtc/base/asynctcpsocket.h"
+#include "webrtc/base/buffer.h"
+#include "webrtc/base/dscp.h"
+#include "webrtc/base/firewallsocketserver.h"
+#include "webrtc/base/gunit.h"
+#include "webrtc/base/helpers.h"
+#include "webrtc/base/logging.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"
+
+using rtc::SocketAddress;
using cricket::Connection;
using cricket::Port;
using cricket::PortInterface;
static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
+static const SocketAddress kTurnAlternateUdpIntAddr(
+ "99.99.99.6", cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpIPv6IntAddr(
"2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT);
static const SocketAddress kTurnUdpIPv6ExtAddr(
class TurnPortTest : public testing::Test,
public sigslot::has_slots<>,
- public talk_base::MessageHandler {
+ public rtc::MessageHandler {
public:
TurnPortTest()
- : main_(talk_base::Thread::Current()),
- pss_(new talk_base::PhysicalSocketServer),
- ss_(new talk_base::VirtualSocketServer(pss_.get())),
+ : main_(rtc::Thread::Current()),
+ pss_(new rtc::PhysicalSocketServer),
+ ss_(new rtc::VirtualSocketServer(pss_.get())),
ss_scope_(ss_.get()),
- network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
- socket_factory_(talk_base::Thread::Current()),
+ 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_create_permission_success_(false),
udp_ready_(false),
test_finish_(false) {
- network_.AddIP(talk_base::IPAddress(INADDR_ANY));
+ network_.AddIP(rtc::IPAddress(INADDR_ANY));
}
- virtual void OnMessage(talk_base::Message* msg) {
+ virtual void OnMessage(rtc::Message* msg) {
ASSERT(msg->message_id == MSG_TESTFINISH);
if (msg->message_id == MSG_TESTFINISH)
test_finish_ = true;
}
}
void OnTurnReadPacket(Connection* conn, const char* data, size_t size,
- const talk_base::PacketTime& packet_time) {
- turn_packets_.push_back(talk_base::Buffer(data, 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 talk_base::PacketTime& packet_time) {
- udp_packets_.push_back(talk_base::Buffer(data, size));
+ const rtc::PacketTime& packet_time) {
+ udp_packets_.push_back(rtc::Buffer(data, size));
}
- void OnSocketReadPacket(talk_base::AsyncPacketSocket* socket,
+ void OnSocketReadPacket(rtc::AsyncPacketSocket* socket,
const char* data, size_t size,
- const talk_base::SocketAddress& remote_addr,
- const talk_base::PacketTime& packet_time) {
+ const rtc::SocketAddress& remote_addr,
+ const rtc::PacketTime& packet_time) {
turn_port_->HandleIncomingPacket(socket, data, size, remote_addr,
packet_time);
}
- talk_base::AsyncSocket* CreateServerSocket(const SocketAddress addr) {
- talk_base::AsyncSocket* socket = ss_->CreateAsyncSocket(SOCK_STREAM);
+ 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;
const cricket::ProtocolAddress& server_address) {
CreateTurnPort(kLocalAddr1, username, password, server_address);
}
- void CreateTurnPort(const talk_base::SocketAddress& local_address,
+ void CreateTurnPort(const rtc::SocketAddress& local_address,
const std::string& username,
const std::string& password,
const cricket::ProtocolAddress& server_address) {
turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
local_address.ipaddr(), 0, 0,
kIceUfrag1, kIcePwd1,
- server_address, credentials));
+ 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.
const cricket::ProtocolAddress& server_address) {
ASSERT(server_address.proto == cricket::PROTO_UDP);
- socket_.reset(socket_factory_.CreateUdpSocket(
- talk_base::SocketAddress(kLocalAddr1.ipaddr(), 0), 0, 0));
- ASSERT_TRUE(socket_ != NULL);
- socket_->SignalReadPacket.connect(this, &TurnPortTest::OnSocketReadPacket);
+ if (!socket_) {
+ 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));
+ 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.
// Send some data.
size_t num_packets = 256;
for (size_t i = 0; i < num_packets; ++i) {
- char buf[256];
+ unsigned char buf[256] = { 0 };
for (size_t j = 0; j < i + 1; ++j) {
- buf[j] = 0xFF - j;
+ buf[j] = 0xFF - static_cast<unsigned char>(j);
}
conn1->Send(buf, i + 1, options);
conn2->Send(buf, i + 1, options);
}
protected:
- talk_base::Thread* main_;
- talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
- talk_base::scoped_ptr<talk_base::VirtualSocketServer> ss_;
- talk_base::SocketServerScope ss_scope_;
- talk_base::Network network_;
- talk_base::BasicPacketSocketFactory socket_factory_;
- talk_base::scoped_ptr<talk_base::AsyncPacketSocket> socket_;
+ 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_;
- talk_base::scoped_ptr<TurnPort> turn_port_;
- talk_base::scoped_ptr<UDPPort> udp_port_;
+ 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<talk_base::Buffer> turn_packets_;
- std::vector<talk_base::Buffer> udp_packets_;
- talk_base::PacketOptions options;
+ 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(talk_base::Socket::OPT_SNDBUF, 10*1024));
+ 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_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(talk_base::Socket::OPT_SNDBUF, 10*1024));
+ 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_NE(0, turn_port_->Candidates()[0].address().port());
}
+// Testing turn port will attempt to create TCP socket on address resolution
+// failure.
+TEST_F(TurnPortTest, DISABLED_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, DISABLED_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);
ASSERT_EQ(0U, turn_port_->Candidates().size());
}
+// Tests that a new local address is created after
+// STUN_ERROR_ALLOCATION_MISMATCH.
+TEST_F(TurnPortTest, TestTurnAllocateMismatch) {
+ // Do a normal allocation first.
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+
+ // Forces the socket server to assign the same port.
+ ss_->SetNextPortForTesting(first_addr.port());
+
+ turn_ready_ = false;
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+
+ // Verifies that the new port has the same address.
+ EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress());
+
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ // Verifies that the new port has a different address now.
+ EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress());
+}
+
+// Tests that a shared-socket-TurnPort creates its own socket after
+// STUN_ERROR_ALLOCATION_MISMATCH.
+TEST_F(TurnPortTest, TestSharedSocketAllocateMismatch) {
+ // Do a normal allocation first.
+ CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+
+ turn_ready_ = false;
+ CreateSharedTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ // Verifies that the new port has the same address.
+ EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress());
+ EXPECT_TRUE(turn_port_->SharedSocket());
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ // Verifies that the new port has a different address now.
+ EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress());
+ EXPECT_FALSE(turn_port_->SharedSocket());
+}
+
+TEST_F(TurnPortTest, TestTurnTcpAllocateMismatch) {
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+
+ // Do a normal allocation first.
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ rtc::SocketAddress first_addr(turn_port_->socket()->GetLocalAddress());
+
+ // Forces the socket server to assign the same port.
+ ss_->SetNextPortForTesting(first_addr.port());
+
+ turn_ready_ = false;
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+ turn_port_->PrepareAddress();
+
+ // Verifies that the new port has the same address.
+ EXPECT_EQ(first_addr, turn_port_->socket()->GetLocalAddress());
+
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+
+ // Verifies that the new port has a different address now.
+ EXPECT_NE(first_addr, turn_port_->socket()->GetLocalAddress());
+}
+
// 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
ASSERT_EQ(0U, turn_port_->Candidates().size());
}
+// Test try-alternate-server feature.
+TEST_F(TurnPortTest, TestTurnAlternateServer) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ // Retrieve the address before we run the state machine.
+ const SocketAddress old_addr = turn_port_->server_address().address;
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
+ // Retrieve the address again, the turn port's address should be
+ // changed.
+ const SocketAddress new_addr = turn_port_->server_address().address;
+ EXPECT_NE(old_addr, new_addr);
+ 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());
+}
+
+// Test that we fail when we redirect to an address different from
+// current IP family.
+TEST_F(TurnPortTest, TestTurnAlternateServerV4toV6) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnUdpIPv6IntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+}
+
+// Test that we fail to handle alternate-server response over TCP protocol.
+TEST_F(TurnPortTest, TestTurnAlternateServerTcp) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+ turn_server_.set_redirect_hook(&redirector);
+ turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
+
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr, cricket::PROTO_TCP);
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+}
+
+// Test try-alternate-server catches the case of pingpong.
+TEST_F(TurnPortTest, TestTurnAlternateServerPingPong) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+ redirect_addresses.push_back(kTurnUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ turn_port_->PrepareAddress();
+ EXPECT_TRUE_WAIT(turn_error_, kTimeout);
+ ASSERT_EQ(0U, turn_port_->Candidates().size());
+ rtc::SocketAddress address;
+ // Verify that we have exhausted all alternate servers instead of
+ // failure caused by other errors.
+ EXPECT_FALSE(redirector.ShouldRedirect(address, &address));
+}
+
+// Test try-alternate-server catch the case of repeated server.
+TEST_F(TurnPortTest, TestTurnAlternateServerDetectRepetition) {
+ std::vector<rtc::SocketAddress> redirect_addresses;
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+ redirect_addresses.push_back(kTurnAlternateUdpIntAddr);
+
+ cricket::TestTurnRedirector redirector(redirect_addresses);
+
+ turn_server_.AddInternalSocket(kTurnAlternateUdpIntAddr,
+ cricket::PROTO_UDP);
+ turn_server_.set_redirect_hook(&redirector);
+ CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
+
+ 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.
int last_fd_count = GetFDCount();
// Need to supply unresolved address to kick off resolver.
CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
- cricket::ProtocolAddress(talk_base::SocketAddress(
+ 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();
- talk_base::Thread::Current()->Post(this, MSG_TESTFINISH);
+ 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
-