OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "build/build_config.h" |
| 6 |
| 7 #if defined(OS_WIN) |
| 8 #include <winsock2.h> // for htonl |
| 9 #else |
| 10 #include <arpa/inet.h> |
| 11 #endif |
| 12 |
| 13 #include <deque> |
| 14 #include <vector> |
| 15 |
| 16 #include "content/browser/renderer_host/p2p_socket_host_udp.h" |
| 17 #include "content/common/p2p_messages.h" |
| 18 #include "net/base/io_buffer.h" |
| 19 #include "net/base/ip_endpoint.h" |
| 20 #include "net/base/net_errors.h" |
| 21 #include "net/udp/datagram_server_socket.h" |
| 22 #include "testing/gmock/include/gmock/gmock.h" |
| 23 #include "testing/gtest/include/gtest/gtest.h" |
| 24 |
| 25 using ::testing::_; |
| 26 using ::testing::DeleteArg; |
| 27 using ::testing::DoAll; |
| 28 using ::testing::Return; |
| 29 |
| 30 namespace { |
| 31 |
| 32 const char kTestLocalIpAddress[] = "123.44.22.4"; |
| 33 const char kTestIpAddress1[] = "123.44.22.31"; |
| 34 const int kTestPort1 = 234; |
| 35 const char kTestIpAddress2[] = "133.11.22.33"; |
| 36 const int kTestPort2 = 543; |
| 37 |
| 38 const int kStunHeaderSize = 20; |
| 39 const uint16 kStunBindingRequest = 0x0001; |
| 40 const uint16 kStunBindingResponse = 0x0102; |
| 41 const uint16 kStunBindingError = 0x0111; |
| 42 const uint32 kStunMagicCookie = 0x2112A442; |
| 43 |
| 44 class FakeDatagramServerSocket : public net::DatagramServerSocket { |
| 45 public: |
| 46 typedef std::pair<net::IPEndPoint, std::vector<char> > UDPPacket; |
| 47 |
| 48 // P2PSocketHostUdp destroyes a socket on errors so sent packets |
| 49 // need to be stored outside of this object. |
| 50 explicit FakeDatagramServerSocket(std::deque<UDPPacket>* sent_packets) |
| 51 : sent_packets_(sent_packets), recv_callback_(NULL) { |
| 52 } |
| 53 |
| 54 virtual void Close() OVERRIDE { |
| 55 } |
| 56 |
| 57 virtual int GetPeerAddress(net::IPEndPoint* address) const OVERRIDE { |
| 58 NOTREACHED(); |
| 59 return net::ERR_SOCKET_NOT_CONNECTED; |
| 60 } |
| 61 |
| 62 virtual int GetLocalAddress(net::IPEndPoint* address) const OVERRIDE { |
| 63 *address = address_; |
| 64 return 0; |
| 65 } |
| 66 |
| 67 virtual int Listen(const net::IPEndPoint& address) OVERRIDE { |
| 68 address_ = address; |
| 69 return 0; |
| 70 } |
| 71 |
| 72 virtual int RecvFrom(net::IOBuffer* buf, int buf_len, |
| 73 net::IPEndPoint* address, |
| 74 net::CompletionCallback* callback) OVERRIDE { |
| 75 CHECK(!recv_callback_); |
| 76 if (incoming_packets_.size() > 0) { |
| 77 scoped_refptr<net::IOBuffer> buffer(buf); |
| 78 int size = std::min( |
| 79 static_cast<int>(incoming_packets_.front().second.size()), buf_len); |
| 80 memcpy(buffer->data(), &*incoming_packets_.front().second.begin(), size); |
| 81 *address = incoming_packets_.front().first; |
| 82 incoming_packets_.pop_front(); |
| 83 return size; |
| 84 } else { |
| 85 recv_callback_ = callback; |
| 86 recv_buffer_ = buf; |
| 87 recv_size_ = buf_len; |
| 88 recv_address_ = address; |
| 89 return net::ERR_IO_PENDING; |
| 90 } |
| 91 } |
| 92 |
| 93 virtual int SendTo(net::IOBuffer* buf, int buf_len, |
| 94 const net::IPEndPoint& address, |
| 95 net::CompletionCallback* callback) OVERRIDE { |
| 96 scoped_refptr<net::IOBuffer> buffer(buf); |
| 97 std::vector<char> data_vector(buffer->data(), buffer->data() + buf_len); |
| 98 sent_packets_->push_back(UDPPacket(address, data_vector)); |
| 99 return buf_len; |
| 100 } |
| 101 |
| 102 void ReceivePacket(const net::IPEndPoint& address, std::vector<char> data) { |
| 103 if (recv_callback_) { |
| 104 int size = std::min(recv_size_, static_cast<int>(data.size())); |
| 105 memcpy(recv_buffer_->data(), &*data.begin(), size); |
| 106 *recv_address_ = address; |
| 107 net::CompletionCallback* cb = recv_callback_; |
| 108 recv_callback_ = NULL; |
| 109 recv_buffer_ = NULL; |
| 110 cb->Run(size); |
| 111 } else { |
| 112 incoming_packets_.push_back(UDPPacket(address, data)); |
| 113 } |
| 114 } |
| 115 |
| 116 private: |
| 117 net::IPEndPoint address_; |
| 118 std::deque<UDPPacket>* sent_packets_; |
| 119 std::deque<UDPPacket> incoming_packets_; |
| 120 |
| 121 scoped_refptr<net::IOBuffer> recv_buffer_; |
| 122 net::IPEndPoint* recv_address_; |
| 123 int recv_size_; |
| 124 net::CompletionCallback* recv_callback_; |
| 125 }; |
| 126 |
| 127 class MockIPCSender : public IPC::Message::Sender { |
| 128 public: |
| 129 MOCK_METHOD1(Send, bool(IPC::Message* msg)); |
| 130 }; |
| 131 |
| 132 MATCHER_P(MatchMessage, type, "") { |
| 133 return arg->type() == type; |
| 134 } |
| 135 |
| 136 } // namespace |
| 137 |
| 138 class P2PSocketHostUdpTest : public testing::Test { |
| 139 protected: |
| 140 void SetUp() OVERRIDE { |
| 141 EXPECT_CALL(sender_, Send( |
| 142 MatchMessage(static_cast<uint32>(P2PMsg_OnSocketCreated::ID)))) |
| 143 .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| 144 |
| 145 socket_host_.reset(new P2PSocketHostUdp(&sender_, 0, 0)); |
| 146 socket_ = new FakeDatagramServerSocket(&sent_packets_); |
| 147 socket_host_->socket_.reset(socket_); |
| 148 |
| 149 net::IPAddressNumber local_ip; |
| 150 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestLocalIpAddress, &local_ip)); |
| 151 local_address_ = net::IPEndPoint(local_ip, kTestPort1); |
| 152 socket_host_->Init(local_address_); |
| 153 |
| 154 net::IPAddressNumber ip1; |
| 155 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestIpAddress1, &ip1)); |
| 156 dest1_ = net::IPEndPoint(ip1, kTestPort1); |
| 157 net::IPAddressNumber ip2; |
| 158 ASSERT_TRUE(net::ParseIPLiteralToNumber(kTestIpAddress2, &ip2)); |
| 159 dest2_ = net::IPEndPoint(ip2, kTestPort2); |
| 160 } |
| 161 |
| 162 void CreateRandomPacket(std::vector<char>* packet) { |
| 163 size_t size = kStunHeaderSize + rand() % 1000; |
| 164 packet->resize(size); |
| 165 for (size_t i = 0; i < size; i++) { |
| 166 (*packet)[i] = rand() % 256; |
| 167 } |
| 168 // Always set the first bit to ensure that generated packet is not |
| 169 // valid STUN packet. |
| 170 (*packet)[0] = (*packet)[0] | 0x80; |
| 171 } |
| 172 |
| 173 void CreateStunPacket(std::vector<char>* packet, uint16 type) { |
| 174 CreateRandomPacket(packet); |
| 175 *reinterpret_cast<uint16*>(&*packet->begin()) = htons(type); |
| 176 *reinterpret_cast<uint16*>(&*packet->begin() + 2) = |
| 177 htons(packet->size() - kStunHeaderSize); |
| 178 *reinterpret_cast<uint32*>(&*packet->begin() + 4) = htonl(kStunMagicCookie); |
| 179 } |
| 180 |
| 181 void CreateStunRequest(std::vector<char>* packet) { |
| 182 CreateStunPacket(packet, kStunBindingRequest); |
| 183 } |
| 184 |
| 185 void CreateStunResponse(std::vector<char>* packet) { |
| 186 CreateStunPacket(packet, kStunBindingResponse); |
| 187 } |
| 188 |
| 189 void CreateStunError(std::vector<char>* packet) { |
| 190 CreateStunPacket(packet, kStunBindingError); |
| 191 } |
| 192 |
| 193 std::deque<FakeDatagramServerSocket::UDPPacket> sent_packets_; |
| 194 FakeDatagramServerSocket* socket_; // Owned by |socket_host_|. |
| 195 scoped_ptr<P2PSocketHostUdp> socket_host_; |
| 196 MockIPCSender sender_; |
| 197 |
| 198 net::IPEndPoint local_address_; |
| 199 |
| 200 net::IPEndPoint dest1_; |
| 201 net::IPEndPoint dest2_; |
| 202 }; |
| 203 |
| 204 // Verify that we can send STUN messages before we receive anything |
| 205 // from the other side. |
| 206 TEST_F(P2PSocketHostUdpTest, SendStunNoAuth) { |
| 207 std::vector<char> packet1; |
| 208 CreateStunRequest(&packet1); |
| 209 socket_host_->Send(dest1_, packet1); |
| 210 |
| 211 std::vector<char> packet2; |
| 212 CreateStunResponse(&packet2); |
| 213 socket_host_->Send(dest1_, packet2); |
| 214 |
| 215 std::vector<char> packet3; |
| 216 CreateStunError(&packet3); |
| 217 socket_host_->Send(dest1_, packet3); |
| 218 |
| 219 ASSERT_EQ(sent_packets_.size(), 3U); |
| 220 ASSERT_EQ(sent_packets_[0].second, packet1); |
| 221 ASSERT_EQ(sent_packets_[1].second, packet2); |
| 222 ASSERT_EQ(sent_packets_[2].second, packet3); |
| 223 } |
| 224 |
| 225 // Verify that no data packets can be sent before STUN binding has |
| 226 // finished. |
| 227 TEST_F(P2PSocketHostUdpTest, SendDataNoAuth) { |
| 228 EXPECT_CALL(sender_, Send( |
| 229 MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID)))) |
| 230 .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| 231 |
| 232 std::vector<char> packet; |
| 233 CreateRandomPacket(&packet); |
| 234 socket_host_->Send(dest1_, packet); |
| 235 |
| 236 ASSERT_EQ(sent_packets_.size(), 0U); |
| 237 } |
| 238 |
| 239 // Verify that we can send data after we've received STUN request |
| 240 // from the other side. |
| 241 TEST_F(P2PSocketHostUdpTest, SendAfterStunRequest) { |
| 242 EXPECT_CALL(sender_, Send( |
| 243 MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID)))) |
| 244 .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| 245 |
| 246 // Receive packet from |dest1_|. |
| 247 std::vector<char> request_packet; |
| 248 CreateStunRequest(&request_packet); |
| 249 socket_->ReceivePacket(dest1_, request_packet); |
| 250 |
| 251 // Now we should be able to send any data to |dest1_|. |
| 252 std::vector<char> packet; |
| 253 CreateRandomPacket(&packet); |
| 254 socket_host_->Send(dest1_, packet); |
| 255 |
| 256 ASSERT_EQ(1U, sent_packets_.size()); |
| 257 ASSERT_EQ(dest1_, sent_packets_[0].first); |
| 258 } |
| 259 |
| 260 // Verify that we can send data after we've received STUN response |
| 261 // from the other side. |
| 262 TEST_F(P2PSocketHostUdpTest, SendAfterStunResponse) { |
| 263 EXPECT_CALL(sender_, Send( |
| 264 MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID)))) |
| 265 .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| 266 |
| 267 // Receive packet from |dest1_|. |
| 268 std::vector<char> request_packet; |
| 269 CreateStunRequest(&request_packet); |
| 270 socket_->ReceivePacket(dest1_, request_packet); |
| 271 |
| 272 // Now we should be able to send any data to |dest1_|. |
| 273 std::vector<char> packet; |
| 274 CreateRandomPacket(&packet); |
| 275 socket_host_->Send(dest1_, packet); |
| 276 |
| 277 ASSERT_EQ(1U, sent_packets_.size()); |
| 278 ASSERT_EQ(dest1_, sent_packets_[0].first); |
| 279 } |
| 280 |
| 281 // Verify messages still cannot be sent to an unathorized host after |
| 282 // successful binding with different host. |
| 283 TEST_F(P2PSocketHostUdpTest, SendAfterStunResponseDifferentHost) { |
| 284 EXPECT_CALL(sender_, Send( |
| 285 MatchMessage(static_cast<uint32>(P2PMsg_OnDataReceived::ID)))) |
| 286 .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| 287 |
| 288 // Receive packet from |dest1_|. |
| 289 std::vector<char> request_packet; |
| 290 CreateStunRequest(&request_packet); |
| 291 socket_->ReceivePacket(dest1_, request_packet); |
| 292 |
| 293 // Should fail when trying to send the same packet to |dest2_|. |
| 294 std::vector<char> packet; |
| 295 CreateRandomPacket(&packet); |
| 296 EXPECT_CALL(sender_, Send( |
| 297 MatchMessage(static_cast<uint32>(P2PMsg_OnError::ID)))) |
| 298 .WillOnce(DoAll(DeleteArg<0>(), Return(true))); |
| 299 socket_host_->Send(dest2_, packet); |
| 300 } |
OLD | NEW |