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