blob: d559894ac565124d1c736b46c7251d7959e0325f [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
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"
mallinath@webrtc.org1112c302013-09-23 20:34:45 +000030#include "talk/base/dscp.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000031#include "talk/base/firewallsocketserver.h"
32#include "talk/base/logging.h"
33#include "talk/base/gunit.h"
34#include "talk/base/helpers.h"
35#include "talk/base/physicalsocketserver.h"
36#include "talk/base/scoped_ptr.h"
37#include "talk/base/socketaddress.h"
38#include "talk/base/thread.h"
39#include "talk/base/virtualsocketserver.h"
40#include "talk/p2p/base/basicpacketsocketfactory.h"
41#include "talk/p2p/base/constants.h"
42#include "talk/p2p/base/tcpport.h"
43#include "talk/p2p/base/testturnserver.h"
44#include "talk/p2p/base/turnport.h"
45#include "talk/p2p/base/udpport.h"
46
47using talk_base::SocketAddress;
48using cricket::Connection;
49using cricket::Port;
50using cricket::PortInterface;
51using cricket::TurnPort;
52using cricket::UDPPort;
53
54static const SocketAddress kLocalAddr1("11.11.11.11", 0);
55static const SocketAddress kLocalAddr2("22.22.22.22", 0);
wu@webrtc.org97077a32013-10-25 21:18:33 +000056static const SocketAddress kLocalIPv6Addr(
57 "2401:fa00:4:1000:be30:5bff:fee5:c3", 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000058static const SocketAddress kTurnUdpIntAddr("99.99.99.3",
59 cricket::TURN_SERVER_PORT);
60static const SocketAddress kTurnTcpIntAddr("99.99.99.4",
61 cricket::TURN_SERVER_PORT);
62static const SocketAddress kTurnUdpExtAddr("99.99.99.5", 0);
wu@webrtc.org97077a32013-10-25 21:18:33 +000063static const SocketAddress kTurnUdpIPv6IntAddr(
64 "2400:4030:1:2c00:be30:abcd:efab:cdef", cricket::TURN_SERVER_PORT);
65static const SocketAddress kTurnUdpIPv6ExtAddr(
66 "2620:0:1000:1b03:2e41:38ff:fea6:f2a4", 0);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000067
68static const char kIceUfrag1[] = "TESTICEUFRAG0001";
69static const char kIceUfrag2[] = "TESTICEUFRAG0002";
70static const char kIcePwd1[] = "TESTICEPWD00000000000001";
71static const char kIcePwd2[] = "TESTICEPWD00000000000002";
72static const char kTurnUsername[] = "test";
73static const char kTurnPassword[] = "test";
74static const int kTimeout = 1000;
75
wu@webrtc.org91053e72013-08-10 07:18:04 +000076static const cricket::ProtocolAddress kTurnUdpProtoAddr(
77 kTurnUdpIntAddr, cricket::PROTO_UDP);
78static const cricket::ProtocolAddress kTurnTcpProtoAddr(
79 kTurnTcpIntAddr, cricket::PROTO_TCP);
wu@webrtc.org97077a32013-10-25 21:18:33 +000080static const cricket::ProtocolAddress kTurnUdpIPv6ProtoAddr(
81 kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
henrike@webrtc.org28e20752013-07-10 00:45:36 +000082
83class TurnPortTest : public testing::Test,
84 public sigslot::has_slots<> {
85 public:
86 TurnPortTest()
87 : main_(talk_base::Thread::Current()),
88 pss_(new talk_base::PhysicalSocketServer),
89 ss_(new talk_base::VirtualSocketServer(pss_.get())),
90 ss_scope_(ss_.get()),
91 network_("unittest", "unittest", talk_base::IPAddress(INADDR_ANY), 32),
92 socket_factory_(talk_base::Thread::Current()),
93 turn_server_(main_, kTurnUdpIntAddr, kTurnUdpExtAddr),
94 turn_ready_(false),
95 turn_error_(false),
96 turn_unknown_address_(false),
97 turn_create_permission_success_(false),
98 udp_ready_(false) {
99 network_.AddIP(talk_base::IPAddress(INADDR_ANY));
100 }
101
102 void OnTurnPortComplete(Port* port) {
103 turn_ready_ = true;
104 }
105 void OnTurnPortError(Port* port) {
106 turn_error_ = true;
107 }
108 void OnTurnUnknownAddress(PortInterface* port, const SocketAddress& addr,
109 cricket::ProtocolType proto,
110 cricket::IceMessage* msg, const std::string& rf,
111 bool /*port_muxed*/) {
112 turn_unknown_address_ = true;
113 }
114 void OnTurnCreatePermissionResult(TurnPort* port, const SocketAddress& addr,
115 int code) {
116 // Ignoring the address.
117 if (code == 0) {
118 turn_create_permission_success_ = true;
119 }
120 }
wu@webrtc.orga9890802013-12-13 00:21:03 +0000121 void OnTurnReadPacket(Connection* conn, const char* data, size_t size,
122 const talk_base::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000123 turn_packets_.push_back(talk_base::Buffer(data, size));
124 }
125 void OnUdpPortComplete(Port* port) {
126 udp_ready_ = true;
127 }
wu@webrtc.orga9890802013-12-13 00:21:03 +0000128 void OnUdpReadPacket(Connection* conn, const char* data, size_t size,
129 const talk_base::PacketTime& packet_time) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000130 udp_packets_.push_back(talk_base::Buffer(data, size));
131 }
132
133 talk_base::AsyncSocket* CreateServerSocket(const SocketAddress addr) {
134 talk_base::AsyncSocket* socket = ss_->CreateAsyncSocket(SOCK_STREAM);
135 EXPECT_GE(socket->Bind(addr), 0);
136 EXPECT_GE(socket->Listen(5), 0);
137 return socket;
138 }
139
140 void CreateTurnPort(const std::string& username,
141 const std::string& password,
142 const cricket::ProtocolAddress& server_address) {
wu@webrtc.org97077a32013-10-25 21:18:33 +0000143 CreateTurnPort(kLocalAddr1, username, password, server_address);
144 }
145 void CreateTurnPort(const talk_base::SocketAddress& local_address,
146 const std::string& username,
147 const std::string& password,
148 const cricket::ProtocolAddress& server_address) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000149 cricket::RelayCredentials credentials(username, password);
150 turn_port_.reset(TurnPort::Create(main_, &socket_factory_, &network_,
wu@webrtc.org97077a32013-10-25 21:18:33 +0000151 local_address.ipaddr(), 0, 0,
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000152 kIceUfrag1, kIcePwd1,
153 server_address, credentials));
154 turn_port_->SignalPortComplete.connect(this,
155 &TurnPortTest::OnTurnPortComplete);
156 turn_port_->SignalPortError.connect(this,
157 &TurnPortTest::OnTurnPortError);
158 turn_port_->SignalUnknownAddress.connect(this,
159 &TurnPortTest::OnTurnUnknownAddress);
160 turn_port_->SignalCreatePermissionResult.connect(this,
161 &TurnPortTest::OnTurnCreatePermissionResult);
162 }
163 void CreateUdpPort() {
164 udp_port_.reset(UDPPort::Create(main_, &socket_factory_, &network_,
165 kLocalAddr2.ipaddr(), 0, 0,
166 kIceUfrag2, kIcePwd2));
167 udp_port_->SignalPortComplete.connect(
168 this, &TurnPortTest::OnUdpPortComplete);
169 }
170
171 void TestTurnConnection() {
172 // Create ports and prepare addresses.
173 ASSERT_TRUE(turn_port_ != NULL);
174 turn_port_->PrepareAddress();
175 ASSERT_TRUE_WAIT(turn_ready_, kTimeout);
176 CreateUdpPort();
177 udp_port_->PrepareAddress();
178 ASSERT_TRUE_WAIT(udp_ready_, kTimeout);
179
180 // Send ping from UDP to TURN.
181 Connection* conn1 = udp_port_->CreateConnection(
182 turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
183 ASSERT_TRUE(conn1 != NULL);
184 conn1->Ping(0);
185 WAIT(!turn_unknown_address_, kTimeout);
186 EXPECT_FALSE(turn_unknown_address_);
187 EXPECT_EQ(Connection::STATE_READ_INIT, conn1->read_state());
188 EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state());
189
190 // Send ping from TURN to UDP.
191 Connection* conn2 = turn_port_->CreateConnection(
192 udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
193 ASSERT_TRUE(conn2 != NULL);
194 ASSERT_TRUE_WAIT(turn_create_permission_success_, kTimeout);
195 conn2->Ping(0);
196
197 EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout);
198 EXPECT_EQ(Connection::STATE_READABLE, conn1->read_state());
199 EXPECT_EQ(Connection::STATE_READ_INIT, conn2->read_state());
200 EXPECT_EQ(Connection::STATE_WRITE_INIT, conn1->write_state());
201
202 // Send another ping from UDP to TURN.
203 conn1->Ping(0);
204 EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout);
205 EXPECT_EQ(Connection::STATE_READABLE, conn2->read_state());
206 }
207
208 void TestTurnSendData() {
209 turn_port_->PrepareAddress();
210 EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
211 CreateUdpPort();
212 udp_port_->PrepareAddress();
213 EXPECT_TRUE_WAIT(udp_ready_, kTimeout);
214 // Create connections and send pings.
215 Connection* conn1 = turn_port_->CreateConnection(
216 udp_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
217 Connection* conn2 = udp_port_->CreateConnection(
218 turn_port_->Candidates()[0], Port::ORIGIN_MESSAGE);
219 ASSERT_TRUE(conn1 != NULL);
220 ASSERT_TRUE(conn2 != NULL);
221 conn1->SignalReadPacket.connect(static_cast<TurnPortTest*>(this),
222 &TurnPortTest::OnTurnReadPacket);
223 conn2->SignalReadPacket.connect(static_cast<TurnPortTest*>(this),
224 &TurnPortTest::OnUdpReadPacket);
225 conn1->Ping(0);
226 EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn1->write_state(), kTimeout);
227 conn2->Ping(0);
228 EXPECT_EQ_WAIT(Connection::STATE_WRITABLE, conn2->write_state(), kTimeout);
229
230 // Send some data.
231 size_t num_packets = 256;
232 for (size_t i = 0; i < num_packets; ++i) {
233 char buf[256];
234 for (size_t j = 0; j < i + 1; ++j) {
235 buf[j] = 0xFF - j;
236 }
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000237 conn1->Send(buf, i + 1, talk_base::DSCP_NO_CHANGE);
238 conn2->Send(buf, i + 1, talk_base::DSCP_NO_CHANGE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000239 main_->ProcessMessages(0);
240 }
241
242 // Check the data.
243 ASSERT_EQ_WAIT(num_packets, turn_packets_.size(), kTimeout);
244 ASSERT_EQ_WAIT(num_packets, udp_packets_.size(), kTimeout);
245 for (size_t i = 0; i < num_packets; ++i) {
246 EXPECT_EQ(i + 1, turn_packets_[i].length());
247 EXPECT_EQ(i + 1, udp_packets_[i].length());
248 EXPECT_EQ(turn_packets_[i], udp_packets_[i]);
249 }
250 }
251
252 protected:
253 talk_base::Thread* main_;
254 talk_base::scoped_ptr<talk_base::PhysicalSocketServer> pss_;
255 talk_base::scoped_ptr<talk_base::VirtualSocketServer> ss_;
256 talk_base::SocketServerScope ss_scope_;
257 talk_base::Network network_;
258 talk_base::BasicPacketSocketFactory socket_factory_;
259 cricket::TestTurnServer turn_server_;
260 talk_base::scoped_ptr<TurnPort> turn_port_;
261 talk_base::scoped_ptr<UDPPort> udp_port_;
262 bool turn_ready_;
263 bool turn_error_;
264 bool turn_unknown_address_;
265 bool turn_create_permission_success_;
266 bool udp_ready_;
267 std::vector<talk_base::Buffer> turn_packets_;
268 std::vector<talk_base::Buffer> udp_packets_;
269};
270
271// Do a normal TURN allocation.
272TEST_F(TurnPortTest, TestTurnAllocate) {
273 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
274 EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
275 turn_port_->PrepareAddress();
276 EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
277 ASSERT_EQ(1U, turn_port_->Candidates().size());
278 EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
279 turn_port_->Candidates()[0].address().ipaddr());
280 EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
281}
282
283TEST_F(TurnPortTest, TestTurnTcpAllocate) {
wu@webrtc.org97077a32013-10-25 21:18:33 +0000284 turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000285 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
286 EXPECT_EQ(0, turn_port_->SetOption(talk_base::Socket::OPT_SNDBUF, 10*1024));
287 turn_port_->PrepareAddress();
288 EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
289 ASSERT_EQ(1U, turn_port_->Candidates().size());
290 EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
291 turn_port_->Candidates()[0].address().ipaddr());
292 EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
293}
294
295// Try to do a TURN allocation with an invalid password.
296TEST_F(TurnPortTest, TestTurnAllocateBadPassword) {
297 CreateTurnPort(kTurnUsername, "bad", kTurnUdpProtoAddr);
298 turn_port_->PrepareAddress();
299 EXPECT_TRUE_WAIT(turn_error_, kTimeout);
300 ASSERT_EQ(0U, turn_port_->Candidates().size());
301}
302
303// Do a TURN allocation and try to send a packet to it from the outside.
304// The packet should be dropped. Then, try to send a packet from TURN to the
305// outside. It should reach its destination. Finally, try again from the
306// outside. It should now work as well.
307TEST_F(TurnPortTest, TestTurnConnection) {
308 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
309 TestTurnConnection();
310}
311
wu@webrtc.org91053e72013-08-10 07:18:04 +0000312// Test that we can establish a TCP connection with TURN server.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000313TEST_F(TurnPortTest, TestTurnTcpConnection) {
wu@webrtc.org97077a32013-10-25 21:18:33 +0000314 turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000315 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
316 TestTurnConnection();
317}
318
wu@webrtc.org91053e72013-08-10 07:18:04 +0000319// Test that we fail to create a connection when we want to use TLS over TCP.
320// This test should be removed once we have TLS support.
321TEST_F(TurnPortTest, TestTurnTlsTcpConnectionFails) {
322 cricket::ProtocolAddress secure_addr(kTurnTcpProtoAddr.address,
323 kTurnTcpProtoAddr.proto,
324 true);
325 CreateTurnPort(kTurnUsername, kTurnPassword, secure_addr);
326 turn_port_->PrepareAddress();
327 EXPECT_TRUE_WAIT(turn_error_, kTimeout);
328 ASSERT_EQ(0U, turn_port_->Candidates().size());
329}
330
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000331// Run TurnConnectionTest with one-time-use nonce feature.
332// Here server will send a 438 STALE_NONCE error message for
333// every TURN transaction.
334TEST_F(TurnPortTest, TestTurnConnectionUsingOTUNonce) {
335 turn_server_.set_enable_otu_nonce(true);
336 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
337 TestTurnConnection();
338}
339
wu@webrtc.org97077a32013-10-25 21:18:33 +0000340// Do a TURN allocation, establish a UDP connection, and send some data.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000341TEST_F(TurnPortTest, TestTurnSendDataTurnUdpToUdp) {
342 // Create ports and prepare addresses.
343 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnUdpProtoAddr);
344 TestTurnSendData();
345}
346
wu@webrtc.org97077a32013-10-25 21:18:33 +0000347// Do a TURN allocation, establish a TCP connection, and send some data.
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000348TEST_F(TurnPortTest, TestTurnSendDataTurnTcpToUdp) {
wu@webrtc.org97077a32013-10-25 21:18:33 +0000349 turn_server_.AddInternalSocket(kTurnTcpIntAddr, cricket::PROTO_TCP);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000350 // Create ports and prepare addresses.
351 CreateTurnPort(kTurnUsername, kTurnPassword, kTurnTcpProtoAddr);
352 TestTurnSendData();
353}
wu@webrtc.org97077a32013-10-25 21:18:33 +0000354
355// Test TURN fails to make a connection from IPv6 address to a server which has
356// IPv4 address.
357TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv4) {
358 turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
359 CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
360 kTurnUdpProtoAddr);
361 turn_port_->PrepareAddress();
362 ASSERT_TRUE_WAIT(turn_error_, kTimeout);
363 EXPECT_TRUE(turn_port_->Candidates().empty());
364}
365
366// Test TURN make a connection from IPv6 address to a server which has
367// IPv6 intenal address. But in this test external address is a IPv4 address,
368// hence allocated address will be a IPv4 address.
369TEST_F(TurnPortTest, TestTurnLocalIPv6AddressServerIPv6ExtenalIPv4) {
370 turn_server_.AddInternalSocket(kTurnUdpIPv6IntAddr, cricket::PROTO_UDP);
371 CreateTurnPort(kLocalIPv6Addr, kTurnUsername, kTurnPassword,
372 kTurnUdpIPv6ProtoAddr);
373 turn_port_->PrepareAddress();
374 EXPECT_TRUE_WAIT(turn_ready_, kTimeout);
375 ASSERT_EQ(1U, turn_port_->Candidates().size());
376 EXPECT_EQ(kTurnUdpExtAddr.ipaddr(),
377 turn_port_->Candidates()[0].address().ipaddr());
378 EXPECT_NE(0, turn_port_->Candidates()[0].address().port());
379}
380