3 * Copyright 2013, Google Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
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.
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.
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"
36 static unsigned char kStunMessageWithZeroLength[] = {
37 0x00, 0x01, 0x00, 0x00, // length of 0 (last 2 bytes)
38 0x21, 0x12, 0xA4, 0x42,
45 static unsigned char kTurnChannelDataMessageWithZeroLength[] = {
46 0x40, 0x00, 0x00, 0x00, // length of 0 (last 2 bytes)
49 static unsigned char kTurnChannelDataMessage[] = {
50 0x40, 0x00, 0x00, 0x10,
51 0x21, 0x12, 0xA4, 0x42,
57 static unsigned char kStunMessageWithInvalidLength[] = {
58 0x00, 0x01, 0x00, 0x10,
59 0x21, 0x12, 0xA4, 0x42,
65 static unsigned char kTurnChannelDataMessageWithInvalidLength[] = {
66 0x80, 0x00, 0x00, 0x20,
67 0x21, 0x12, 0xA4, 0x42,
73 static unsigned char kTurnChannelDataMessageWithOddLength[] = {
74 0x40, 0x00, 0x00, 0x05,
75 0x21, 0x12, 0xA4, 0x42,
80 static const talk_base::SocketAddress kClientAddr("11.11.11.11", 0);
81 static const talk_base::SocketAddress kServerAddr("22.22.22.22", 0);
83 class AsyncStunTCPSocketTest : public testing::Test,
84 public sigslot::has_slots<> {
86 AsyncStunTCPSocketTest()
87 : vss_(new talk_base::VirtualSocketServer(NULL)),
88 ss_scope_(vss_.get()) {
91 virtual void SetUp() {
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);
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();
111 void OnReadPacket(talk_base::AsyncPacketSocket* socket, const char* data,
112 size_t len, const talk_base::SocketAddress& remote_addr,
113 const talk_base::PacketTime& packet_time) {
114 recv_packets_.push_back(std::string(data, len));
117 void OnNewConnection(talk_base::AsyncPacketSocket* server,
118 talk_base::AsyncPacketSocket* new_socket) {
119 listen_socket_.reset(new_socket);
120 new_socket->SignalReadPacket.connect(
121 this, &AsyncStunTCPSocketTest::OnReadPacket);
124 bool Send(const void* data, size_t len) {
125 size_t ret = send_socket_->Send(
126 reinterpret_cast<const char*>(data), len, talk_base::DSCP_NO_CHANGE);
127 vss_->ProcessMessagesUntilIdle();
131 bool CheckData(const void* data, int len) {
133 if (recv_packets_.size()) {
134 std::string packet = recv_packets_.front();
135 recv_packets_.pop_front();
136 ret = (memcmp(data, packet.c_str(), len) == 0);
141 talk_base::scoped_ptr<talk_base::VirtualSocketServer> vss_;
142 talk_base::SocketServerScope ss_scope_;
143 talk_base::scoped_ptr<AsyncStunTCPSocket> send_socket_;
144 talk_base::scoped_ptr<AsyncStunTCPSocket> recv_socket_;
145 talk_base::scoped_ptr<talk_base::AsyncPacketSocket> listen_socket_;
146 std::list<std::string> recv_packets_;
149 // Testing a stun packet sent/recv properly.
150 TEST_F(AsyncStunTCPSocketTest, TestSingleStunPacket) {
151 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
152 sizeof(kStunMessageWithZeroLength)));
153 EXPECT_EQ(1u, recv_packets_.size());
154 EXPECT_TRUE(CheckData(kStunMessageWithZeroLength,
155 sizeof(kStunMessageWithZeroLength)));
158 // Verify sending multiple packets.
159 TEST_F(AsyncStunTCPSocketTest, TestMultipleStunPackets) {
160 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
161 sizeof(kStunMessageWithZeroLength)));
162 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
163 sizeof(kStunMessageWithZeroLength)));
164 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
165 sizeof(kStunMessageWithZeroLength)));
166 EXPECT_TRUE(Send(kStunMessageWithZeroLength,
167 sizeof(kStunMessageWithZeroLength)));
168 EXPECT_EQ(4u, recv_packets_.size());
171 // Verifying TURN channel data message with zero length.
172 TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataWithZeroLength) {
173 EXPECT_TRUE(Send(kTurnChannelDataMessageWithZeroLength,
174 sizeof(kTurnChannelDataMessageWithZeroLength)));
175 EXPECT_EQ(1u, recv_packets_.size());
176 EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithZeroLength,
177 sizeof(kTurnChannelDataMessageWithZeroLength)));
180 // Verifying TURN channel data message.
181 TEST_F(AsyncStunTCPSocketTest, TestTurnChannelData) {
182 EXPECT_TRUE(Send(kTurnChannelDataMessage,
183 sizeof(kTurnChannelDataMessage)));
184 EXPECT_EQ(1u, recv_packets_.size());
185 EXPECT_TRUE(CheckData(kTurnChannelDataMessage,
186 sizeof(kTurnChannelDataMessage)));
189 // Verifying TURN channel messages which needs padding handled properly.
190 TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataPadding) {
191 EXPECT_TRUE(Send(kTurnChannelDataMessageWithOddLength,
192 sizeof(kTurnChannelDataMessageWithOddLength)));
193 EXPECT_EQ(1u, recv_packets_.size());
194 EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithOddLength,
195 sizeof(kTurnChannelDataMessageWithOddLength)));
198 // Verifying stun message with invalid length.
199 TEST_F(AsyncStunTCPSocketTest, TestStunInvalidLength) {
200 EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
201 sizeof(kStunMessageWithInvalidLength)));
202 EXPECT_EQ(0u, recv_packets_.size());
204 // Modify the message length to larger value.
205 kStunMessageWithInvalidLength[2] = 0xFF;
206 kStunMessageWithInvalidLength[3] = 0xFF;
207 EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
208 sizeof(kStunMessageWithInvalidLength)));
210 // Modify the message length to smaller value.
211 kStunMessageWithInvalidLength[2] = 0x00;
212 kStunMessageWithInvalidLength[3] = 0x01;
213 EXPECT_FALSE(Send(kStunMessageWithInvalidLength,
214 sizeof(kStunMessageWithInvalidLength)));
217 // Verifying TURN channel data message with invalid length.
218 TEST_F(AsyncStunTCPSocketTest, TestTurnChannelDataWithInvalidLength) {
219 EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
220 sizeof(kTurnChannelDataMessageWithInvalidLength)));
221 // Modify the length to larger value.
222 kTurnChannelDataMessageWithInvalidLength[2] = 0xFF;
223 kTurnChannelDataMessageWithInvalidLength[3] = 0xF0;
224 EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
225 sizeof(kTurnChannelDataMessageWithInvalidLength)));
227 // Modify the length to smaller value.
228 kTurnChannelDataMessageWithInvalidLength[2] = 0x00;
229 kTurnChannelDataMessageWithInvalidLength[3] = 0x00;
230 EXPECT_FALSE(Send(kTurnChannelDataMessageWithInvalidLength,
231 sizeof(kTurnChannelDataMessageWithInvalidLength)));
234 // Verifying a small buffer handled (dropped) properly. This will be
235 // a common one for both stun and turn.
236 TEST_F(AsyncStunTCPSocketTest, TestTooSmallMessageBuffer) {
238 EXPECT_FALSE(Send(data, sizeof(data)));
241 // Verifying a legal large turn message.
242 TEST_F(AsyncStunTCPSocketTest, TestMaximumSizeTurnPacket) {
243 // We have problem in getting the SignalWriteEvent from the virtual socket
244 // server. So increasing the send buffer to 64k.
245 // TODO(mallinath) - Remove this setting after we fix vss issue.
246 vss_->set_send_buffer_capacity(64 * 1024);
247 unsigned char packet[65539];
252 EXPECT_TRUE(Send(packet, sizeof(packet)));
255 // Verifying a legal large stun message.
256 TEST_F(AsyncStunTCPSocketTest, TestMaximumSizeStunPacket) {
257 // We have problem in getting the SignalWriteEvent from the virtual socket
258 // server. So increasing the send buffer to 64k.
259 // TODO(mallinath) - Remove this setting after we fix vss issue.
260 vss_->set_send_buffer_capacity(64 * 1024);
261 unsigned char packet[65552];
266 EXPECT_TRUE(Send(packet, sizeof(packet)));
269 // Investigate why WriteEvent is not signaled from VSS.
270 TEST_F(AsyncStunTCPSocketTest, DISABLED_TestWithSmallSendBuffer) {
271 vss_->set_send_buffer_capacity(1);
272 Send(kTurnChannelDataMessageWithOddLength,
273 sizeof(kTurnChannelDataMessageWithOddLength));
274 EXPECT_EQ(1u, recv_packets_.size());
275 EXPECT_TRUE(CheckData(kTurnChannelDataMessageWithOddLength,
276 sizeof(kTurnChannelDataMessageWithOddLength)));
279 } // namespace cricket