blob: 7cb380b0aa483fdb992fb3d73769ca3833434ae5 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2013, 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/asyncsocket.h"
29#include "talk/base/gunit.h"
30#include "talk/base/physicalsocketserver.h"
31#include "talk/base/virtualsocketserver.h"
32#include "talk/p2p/base/asyncstuntcpsocket.h"
33
34namespace cricket {
35
36static unsigned char kStunMessageWithZeroLength[] = {
37 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
38 0x21, 0x12, 0xA4, 0x42,
39 '0', '1', '2', '3',
40 '4', '5', '6', '7',
41 '8', '9', 'a', 'b',
42};
43
44
45static unsigned char kTurnChannelDataMessageWithZeroLength[] = {
46 0x40, 0x00, 0x00, 0x00, // length of 0 (last 2 bytes)
47};
48
49static unsigned char kTurnChannelDataMessage[] = {
50 0x40, 0x00, 0x00, 0x10,
51 0x21, 0x12, 0xA4, 0x42,
52 '0', '1', '2', '3',
53 '4', '5', '6', '7',
54 '8', '9', 'a', 'b',
55};
56
57static unsigned char kStunMessageWithInvalidLength[] = {
58 0x00, 0x01, 0x00, 0x10,
59 0x21, 0x12, 0xA4, 0x42,
60 '0', '1', '2', '3',
61 '4', '5', '6', '7',
62 '8', '9', 'a', 'b',
63};
64
65static unsigned char kTurnChannelDataMessageWithInvalidLength[] = {
66 0x80, 0x00, 0x00, 0x20,
67 0x21, 0x12, 0xA4, 0x42,
68 '0', '1', '2', '3',
69 '4', '5', '6', '7',
70 '8', '9', 'a', 'b',
71};
72
73static unsigned char kTurnChannelDataMessageWithOddLength[] = {
74 0x40, 0x00, 0x00, 0x05,
75 0x21, 0x12, 0xA4, 0x42,
76 '0',
77};
78
79
80static const talk_base::SocketAddress kClientAddr("11.11.11.11", 0);
81static const talk_base::SocketAddress kServerAddr("22.22.22.22", 0);
82
83class AsyncStunTCPSocketTest : public testing::Test,
84 public sigslot::has_slots<> {
85 protected:
86 AsyncStunTCPSocketTest()
87 : vss_(new talk_base::VirtualSocketServer(NULL)),
88 ss_scope_(vss_.get()) {
89 }
90
91 virtual void SetUp() {
92 CreateSockets();
93 }
94
95 void CreateSockets() {
96 talk_base::AsyncSocket* server = vss_->CreateAsyncSocket(
97 kServerAddr.family(), SOCK_STREAM);
98 server->Bind(kServerAddr);
99 recv_socket_.reset(new AsyncStunTCPSocket(server, true));
100 recv_socket_->SignalNewConnection.connect(
101 this, &AsyncStunTCPSocketTest::OnNewConnection);
102
103 talk_base::AsyncSocket* client = vss_->CreateAsyncSocket(
104 kClientAddr.family(), SOCK_STREAM);
105 send_socket_.reset(AsyncStunTCPSocket::Create(
106 client, kClientAddr, recv_socket_->GetLocalAddress()));
107 ASSERT_TRUE(send_socket_.get() != NULL);
108 vss_->ProcessMessagesUntilIdle();
109 }
110
111 void OnReadPacket(talk_base::AsyncPacketSocket* socket, const char* data,
wu@webrtc.org20182692013-12-12 22:54:25 +0000112 size_t len, const talk_base::SocketAddress& remote_addr) {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000113 recv_packets_.push_back(std::string(data, len));
114 }
115
116 void OnNewConnection(talk_base::AsyncPacketSocket* server,
117 talk_base::AsyncPacketSocket* new_socket) {
118 listen_socket_.reset(new_socket);
119 new_socket->SignalReadPacket.connect(
120 this, &AsyncStunTCPSocketTest::OnReadPacket);
121 }
122
123 bool Send(const void* data, size_t len) {
mallinath@webrtc.org1112c302013-09-23 20:34:45 +0000124 size_t ret = send_socket_->Send(
125 reinterpret_cast<const char*>(data), len, talk_base::DSCP_NO_CHANGE);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000126 vss_->ProcessMessagesUntilIdle();
127 return (ret == len);
128 }
129
130 bool CheckData(const void* data, int len) {
131 bool ret = false;
132 if (recv_packets_.size()) {
133 std::string packet = recv_packets_.front();
134 recv_packets_.pop_front();
135 ret = (memcmp(data, packet.c_str(), len) == 0);
136 }
137 return ret;
138 }
139
140 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
141 talk_base::SocketServerScope ss_scope_;
142 talk_base::scoped_ptr<AsyncStunTCPSocket> send_socket_;
143 talk_base::scoped_ptr<AsyncStunTCPSocket> recv_socket_;
144 talk_base::scoped_ptr<talk_base::AsyncPacketSocket> listen_socket_;
145 std::list<std::string> recv_packets_;
146};
147
148// Testing a stun packet sent/recv properly.
149TEST_F(AsyncStunTCPSocketTest, TestSingleStunPacket) {
150 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
151 sizeof(kStunMessageWithZeroLength)));
152 EXPECT_EQ(1u, recv_packets_.size());
153 EXPECT_TRUE(CheckData(kStunMessageWithZeroLength,
154 sizeof(kStunMessageWithZeroLength)));
155}
156
157// Verify sending multiple packets.
158TEST_F(AsyncStunTCPSocketTest, TestMultipleStunPackets) {
159 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
160 sizeof(kStunMessageWithZeroLength)));
161 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
162 sizeof(kStunMessageWithZeroLength)));
163 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
164 sizeof(kStunMessageWithZeroLength)));
165 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
166 sizeof(kStunMessageWithZeroLength)));
167 EXPECT_EQ(4u, recv_packets_.size());
168}
169
170// Verifying TURN channel data message with zero length.
171TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataWithZeroLength) {
172 EXPECT_TRUE(Send(kTurnChannelDataMessageWithZeroLength,
173 sizeof(kTurnChannelDataMessageWithZeroLength)));
174 EXPECT_EQ(1u, recv_packets_.size());
175 EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithZeroLength,
176 sizeof(kTurnChannelDataMessageWithZeroLength)));
177}
178
179// Verifying TURN channel data message.
180TEST_F(AsyncStunTCPSocketTest, TestTurnChannelData) {
181 EXPECT_TRUE(Send(kTurnChannelDataMessage,
182 sizeof(kTurnChannelDataMessage)));
183 EXPECT_EQ(1u, recv_packets_.size());
184 EXPECT_TRUE(CheckData(kTurnChannelDataMessage,
185 sizeof(kTurnChannelDataMessage)));
186}
187
188// Verifying TURN channel messages which needs padding handled properly.
189TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataPadding) {
190 EXPECT_TRUE(Send(kTurnChannelDataMessageWithOddLength,
191 sizeof(kTurnChannelDataMessageWithOddLength)));
192 EXPECT_EQ(1u, recv_packets_.size());
193 EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithOddLength,
194 sizeof(kTurnChannelDataMessageWithOddLength)));
195}
196
197// Verifying stun message with invalid length.
198TEST_F(AsyncStunTCPSocketTest, TestStunInvalidLength) {
199 EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
200 sizeof(kStunMessageWithInvalidLength)));
201 EXPECT_EQ(0u, recv_packets_.size());
202
203 // Modify the message length to larger value.
204 kStunMessageWithInvalidLength[2] = 0xFF;
205 kStunMessageWithInvalidLength[3] = 0xFF;
206 EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
207 sizeof(kStunMessageWithInvalidLength)));
208
209 // Modify the message length to smaller value.
210 kStunMessageWithInvalidLength[2] = 0x00;
211 kStunMessageWithInvalidLength[3] = 0x01;
212 EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
213 sizeof(kStunMessageWithInvalidLength)));
214}
215
216// Verifying TURN channel data message with invalid length.
217TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataWithInvalidLength) {
218 EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
219 sizeof(kTurnChannelDataMessageWithInvalidLength)));
220 // Modify the length to larger value.
221 kTurnChannelDataMessageWithInvalidLength[2] = 0xFF;
222 kTurnChannelDataMessageWithInvalidLength[3] = 0xF0;
223 EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
224 sizeof(kTurnChannelDataMessageWithInvalidLength)));
225
226 // Modify the length to smaller value.
227 kTurnChannelDataMessageWithInvalidLength[2] = 0x00;
228 kTurnChannelDataMessageWithInvalidLength[3] = 0x00;
229 EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
230 sizeof(kTurnChannelDataMessageWithInvalidLength)));
231}
232
233// Verifying a small buffer handled (dropped) properly. This will be
234// a common one for both stun and turn.
235TEST_F(AsyncStunTCPSocketTest, TestTooSmallMessageBuffer) {
236 char data[1];
237 EXPECT_FALSE(Send(data, sizeof(data)));
238}
239
240// Verifying a legal large turn message.
241TEST_F(AsyncStunTCPSocketTest, TestMaximumSizeTurnPacket) {
242 // We have problem in getting the SignalWriteEvent from the virtual socket
243 // server. So increasing the send buffer to 64k.
244 // TODO(mallinath) - Remove this setting after we fix vss issue.
245 vss_->set_send_buffer_capacity(64 * 1024);
246 unsigned char packet[65539];
247 packet[0] = 0x40;
248 packet[1] = 0x00;
249 packet[2] = 0xFF;
250 packet[3] = 0xFF;
251 EXPECT_TRUE(Send(packet, sizeof(packet)));
252}
253
254// Verifying a legal large stun message.
255TEST_F(AsyncStunTCPSocketTest, TestMaximumSizeStunPacket) {
256 // We have problem in getting the SignalWriteEvent from the virtual socket
257 // server. So increasing the send buffer to 64k.
258 // TODO(mallinath) - Remove this setting after we fix vss issue.
259 vss_->set_send_buffer_capacity(64 * 1024);
260 unsigned char packet[65552];
261 packet[0] = 0x00;
262 packet[1] = 0x01;
263 packet[2] = 0xFF;
264 packet[3] = 0xFC;
265 EXPECT_TRUE(Send(packet, sizeof(packet)));
266}
267
268// Investigate why WriteEvent is not signaled from VSS.
269TEST_F(AsyncStunTCPSocketTest, DISABLED_TestWithSmallSendBuffer) {
270 vss_->set_send_buffer_capacity(1);
271 Send(kTurnChannelDataMessageWithOddLength,
272 sizeof(kTurnChannelDataMessageWithOddLength));
273 EXPECT_EQ(1u, recv_packets_.size());
274 EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithOddLength,
275 sizeof(kTurnChannelDataMessageWithOddLength)));
276}
277
278} // namespace cricket