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