1/*
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/p2p/base/asyncstuntcpsocket.h"
29#include "webrtc/base/asyncsocket.h"
30#include "webrtc/base/gunit.h"
31#include "webrtc/base/physicalsocketserver.h"
32#include "webrtc/base/virtualsocketserver.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 rtc::SocketAddress kClientAddr("11.11.11.11", 0);
81static const rtc::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 rtc::VirtualSocketServer(NULL)),
88        ss_scope_(vss_.get()) {
89  }
90
91  virtual void SetUp() {
92    CreateSockets();
93  }
94
95  void CreateSockets() {
96    rtc::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    rtc::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(rtc::AsyncPacketSocket* socket, const char* data,
112                    size_t len, const rtc::SocketAddress& remote_addr,
113                    const rtc::PacketTime& packet_time) {
114    recv_packets_.push_back(std::string(data, len));
115  }
116
117  void OnNewConnection(rtc::AsyncPacketSocket* server,
118                       rtc::AsyncPacketSocket* new_socket) {
119    listen_socket_.reset(new_socket);
120    new_socket->SignalReadPacket.connect(
121        this, &AsyncStunTCPSocketTest::OnReadPacket);
122  }
123
124  bool Send(const void* data, size_t len) {
125    rtc::PacketOptions options;
126    size_t ret = send_socket_->Send(
127        reinterpret_cast<const char*>(data), len, options);
128    vss_->ProcessMessagesUntilIdle();
129    return (ret == len);
130  }
131
132  bool CheckData(const void* data, int len) {
133    bool ret = false;
134    if (recv_packets_.size()) {
135      std::string packet =  recv_packets_.front();
136      recv_packets_.pop_front();
137      ret = (memcmp(data, packet.c_str(), len) == 0);
138    }
139    return ret;
140  }
141
142  rtc::scoped_ptr<rtc::VirtualSocketServer> vss_;
143  rtc::SocketServerScope ss_scope_;
144  rtc::scoped_ptr<AsyncStunTCPSocket> send_socket_;
145  rtc::scoped_ptr<AsyncStunTCPSocket> recv_socket_;
146  rtc::scoped_ptr<rtc::AsyncPacketSocket> listen_socket_;
147  std::list<std::string> recv_packets_;
148};
149
150// Testing a stun packet sent/recv properly.
151TEST_F(AsyncStunTCPSocketTest, TestSingleStunPacket) {
152  EXPECT_TRUE(Send(kStunMessageWithZeroLength,
153                   sizeof(kStunMessageWithZeroLength)));
154  EXPECT_EQ(1u, recv_packets_.size());
155  EXPECT_TRUE(CheckData(kStunMessageWithZeroLength,
156                        sizeof(kStunMessageWithZeroLength)));
157}
158
159// Verify sending multiple packets.
160TEST_F(AsyncStunTCPSocketTest, TestMultipleStunPackets) {
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_TRUE(Send(kStunMessageWithZeroLength,
168                   sizeof(kStunMessageWithZeroLength)));
169  EXPECT_EQ(4u, recv_packets_.size());
170}
171
172// Verifying TURN channel data message with zero length.
173TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataWithZeroLength) {
174  EXPECT_TRUE(Send(kTurnChannelDataMessageWithZeroLength,
175                   sizeof(kTurnChannelDataMessageWithZeroLength)));
176  EXPECT_EQ(1u, recv_packets_.size());
177  EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithZeroLength,
178                        sizeof(kTurnChannelDataMessageWithZeroLength)));
179}
180
181// Verifying TURN channel data message.
182TEST_F(AsyncStunTCPSocketTest, TestTurnChannelData) {
183  EXPECT_TRUE(Send(kTurnChannelDataMessage,
184                   sizeof(kTurnChannelDataMessage)));
185  EXPECT_EQ(1u, recv_packets_.size());
186  EXPECT_TRUE(CheckData(kTurnChannelDataMessage,
187                        sizeof(kTurnChannelDataMessage)));
188}
189
190// Verifying TURN channel messages which needs padding handled properly.
191TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataPadding) {
192  EXPECT_TRUE(Send(kTurnChannelDataMessageWithOddLength,
193                   sizeof(kTurnChannelDataMessageWithOddLength)));
194  EXPECT_EQ(1u, recv_packets_.size());
195  EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithOddLength,
196                        sizeof(kTurnChannelDataMessageWithOddLength)));
197}
198
199// Verifying stun message with invalid length.
200TEST_F(AsyncStunTCPSocketTest, TestStunInvalidLength) {
201  EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
202                    sizeof(kStunMessageWithInvalidLength)));
203  EXPECT_EQ(0u, recv_packets_.size());
204
205  // Modify the message length to larger value.
206  kStunMessageWithInvalidLength[2] = 0xFF;
207  kStunMessageWithInvalidLength[3] = 0xFF;
208  EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
209                    sizeof(kStunMessageWithInvalidLength)));
210
211  // Modify the message length to smaller value.
212  kStunMessageWithInvalidLength[2] = 0x00;
213  kStunMessageWithInvalidLength[3] = 0x01;
214  EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
215                    sizeof(kStunMessageWithInvalidLength)));
216}
217
218// Verifying TURN channel data message with invalid length.
219TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataWithInvalidLength) {
220  EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
221                   sizeof(kTurnChannelDataMessageWithInvalidLength)));
222  // Modify the length to larger value.
223  kTurnChannelDataMessageWithInvalidLength[2] = 0xFF;
224  kTurnChannelDataMessageWithInvalidLength[3] = 0xF0;
225  EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
226                   sizeof(kTurnChannelDataMessageWithInvalidLength)));
227
228  // Modify the length to smaller value.
229  kTurnChannelDataMessageWithInvalidLength[2] = 0x00;
230  kTurnChannelDataMessageWithInvalidLength[3] = 0x00;
231  EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
232                   sizeof(kTurnChannelDataMessageWithInvalidLength)));
233}
234
235// Verifying a small buffer handled (dropped) properly. This will be
236// a common one for both stun and turn.
237TEST_F(AsyncStunTCPSocketTest, TestTooSmallMessageBuffer) {
238  char data[1];
239  EXPECT_FALSE(Send(data, sizeof(data)));
240}
241
242// Verifying a legal large turn message.
243TEST_F(AsyncStunTCPSocketTest, TestMaximumSizeTurnPacket) {
244  // We have problem in getting the SignalWriteEvent from the virtual socket
245  // server. So increasing the send buffer to 64k.
246  // TODO(mallinath) - Remove this setting after we fix vss issue.
247  vss_->set_send_buffer_capacity(64 * 1024);
248  unsigned char packet[65539];
249  packet[0] = 0x40;
250  packet[1] = 0x00;
251  packet[2] = 0xFF;
252  packet[3] = 0xFF;
253  EXPECT_TRUE(Send(packet, sizeof(packet)));
254}
255
256// Verifying a legal large stun message.
257TEST_F(AsyncStunTCPSocketTest, TestMaximumSizeStunPacket) {
258  // We have problem in getting the SignalWriteEvent from the virtual socket
259  // server. So increasing the send buffer to 64k.
260  // TODO(mallinath) - Remove this setting after we fix vss issue.
261  vss_->set_send_buffer_capacity(64 * 1024);
262  unsigned char packet[65552];
263  packet[0] = 0x00;
264  packet[1] = 0x01;
265  packet[2] = 0xFF;
266  packet[3] = 0xFC;
267  EXPECT_TRUE(Send(packet, sizeof(packet)));
268}
269
270// Investigate why WriteEvent is not signaled from VSS.
271TEST_F(AsyncStunTCPSocketTest, DISABLED_TestWithSmallSendBuffer) {
272  vss_->set_send_buffer_capacity(1);
273  Send(kTurnChannelDataMessageWithOddLength,
274       sizeof(kTurnChannelDataMessageWithOddLength));
275  EXPECT_EQ(1u, recv_packets_.size());
276  EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithOddLength,
277                        sizeof(kTurnChannelDataMessageWithOddLength)));
278}
279
280}  // namespace cricket
281