1 // Copyright (c) 2012 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 "net/tools/quic/quic_client.h" 6 7 #include <errno.h> 8 #include <netinet/in.h> 9 #include <string.h> 10 #include <sys/epoll.h> 11 #include <sys/socket.h> 12 #include <unistd.h> 13 14 #include "base/logging.h" 15 #include "net/quic/congestion_control/tcp_receiver.h" 16 #include "net/quic/crypto/quic_random.h" 17 #include "net/quic/quic_connection.h" 18 #include "net/quic/quic_data_reader.h" 19 #include "net/quic/quic_protocol.h" 20 #include "net/quic/quic_server_id.h" 21 #include "net/tools/balsa/balsa_headers.h" 22 #include "net/tools/epoll_server/epoll_server.h" 23 #include "net/tools/quic/quic_epoll_connection_helper.h" 24 #include "net/tools/quic/quic_socket_utils.h" 25 #include "net/tools/quic/quic_spdy_client_stream.h" 26 27 #ifndef SO_RXQ_OVFL 28 #define SO_RXQ_OVFL 40 29 #endif 30 31 namespace net { 32 namespace tools { 33 34 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; 35 36 QuicClient::QuicClient(IPEndPoint server_address, 37 const QuicServerId& server_id, 38 const QuicVersionVector& supported_versions, 39 bool print_response, 40 EpollServer* epoll_server) 41 : server_address_(server_address), 42 server_id_(server_id), 43 local_port_(0), 44 epoll_server_(epoll_server), 45 fd_(-1), 46 helper_(CreateQuicConnectionHelper()), 47 initialized_(false), 48 packets_dropped_(0), 49 overflow_supported_(false), 50 supported_versions_(supported_versions), 51 print_response_(print_response) { 52 config_.SetDefaults(); 53 } 54 55 QuicClient::QuicClient(IPEndPoint server_address, 56 const QuicServerId& server_id, 57 const QuicVersionVector& supported_versions, 58 bool print_response, 59 const QuicConfig& config, 60 EpollServer* epoll_server) 61 : server_address_(server_address), 62 server_id_(server_id), 63 config_(config), 64 local_port_(0), 65 epoll_server_(epoll_server), 66 fd_(-1), 67 helper_(CreateQuicConnectionHelper()), 68 initialized_(false), 69 packets_dropped_(0), 70 overflow_supported_(false), 71 supported_versions_(supported_versions), 72 print_response_(print_response) { 73 } 74 75 QuicClient::~QuicClient() { 76 if (connected()) { 77 session()->connection()->SendConnectionClosePacket( 78 QUIC_PEER_GOING_AWAY, ""); 79 } 80 if (fd_ > 0) { 81 epoll_server_->UnregisterFD(fd_); 82 } 83 } 84 85 bool QuicClient::Initialize() { 86 DCHECK(!initialized_); 87 88 epoll_server_->set_timeout_in_us(50 * 1000); 89 crypto_config_.SetDefaults(); 90 91 if (!CreateUDPSocket()) { 92 return false; 93 } 94 95 epoll_server_->RegisterFD(fd_, this, kEpollFlags); 96 initialized_ = true; 97 return true; 98 } 99 100 QuicClient::DummyPacketWriterFactory::DummyPacketWriterFactory( 101 QuicPacketWriter* writer) 102 : writer_(writer) {} 103 104 QuicClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {} 105 106 QuicPacketWriter* QuicClient::DummyPacketWriterFactory::Create( 107 QuicConnection* /*connection*/) const { 108 return writer_; 109 } 110 111 112 bool QuicClient::CreateUDPSocket() { 113 int address_family = server_address_.GetSockAddrFamily(); 114 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); 115 if (fd_ < 0) { 116 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno); 117 return false; 118 } 119 120 int get_overflow = 1; 121 int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, 122 sizeof(get_overflow)); 123 if (rc < 0) { 124 DLOG(WARNING) << "Socket overflow detection not supported"; 125 } else { 126 overflow_supported_ = true; 127 } 128 129 if (!QuicSocketUtils::SetReceiveBufferSize(fd_, 130 TcpReceiver::kReceiveWindowTCP)) { 131 return false; 132 } 133 134 if (!QuicSocketUtils::SetSendBufferSize(fd_, 135 TcpReceiver::kReceiveWindowTCP)) { 136 return false; 137 } 138 139 rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family); 140 if (rc < 0) { 141 LOG(ERROR) << "IP detection not supported" << strerror(errno); 142 return false; 143 } 144 145 if (bind_to_address_.size() != 0) { 146 client_address_ = IPEndPoint(bind_to_address_, local_port_); 147 } else if (address_family == AF_INET) { 148 IPAddressNumber any4; 149 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4)); 150 client_address_ = IPEndPoint(any4, local_port_); 151 } else { 152 IPAddressNumber any6; 153 CHECK(net::ParseIPLiteralToNumber("::", &any6)); 154 client_address_ = IPEndPoint(any6, local_port_); 155 } 156 157 sockaddr_storage raw_addr; 158 socklen_t raw_addr_len = sizeof(raw_addr); 159 CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), 160 &raw_addr_len)); 161 rc = bind(fd_, 162 reinterpret_cast<const sockaddr*>(&raw_addr), 163 sizeof(raw_addr)); 164 if (rc < 0) { 165 LOG(ERROR) << "Bind failed: " << strerror(errno); 166 return false; 167 } 168 169 SockaddrStorage storage; 170 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || 171 !client_address_.FromSockAddr(storage.addr, storage.addr_len)) { 172 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); 173 } 174 175 return true; 176 } 177 178 bool QuicClient::Connect() { 179 if (!StartConnect()) { 180 return false; 181 } 182 while (EncryptionBeingEstablished()) { 183 WaitForEvents(); 184 } 185 return session_->connection()->connected(); 186 } 187 188 bool QuicClient::StartConnect() { 189 DCHECK(initialized_); 190 DCHECK(!connected()); 191 192 QuicPacketWriter* writer = CreateQuicPacketWriter(); 193 194 DummyPacketWriterFactory factory(writer); 195 196 session_.reset(new QuicClientSession( 197 config_, 198 new QuicConnection(GenerateConnectionId(), 199 server_address_, 200 helper_.get(), 201 factory, 202 /* owns_writer= */ false, 203 /* is_server= */ false, 204 supported_versions_))); 205 206 // Reset |writer_| after |session_| so that the old writer outlives the old 207 // session. 208 if (writer_.get() != writer) { 209 writer_.reset(writer); 210 } 211 session_->InitializeSession(server_id_, &crypto_config_); 212 return session_->CryptoConnect(); 213 } 214 215 bool QuicClient::EncryptionBeingEstablished() { 216 return !session_->IsEncryptionEstablished() && 217 session_->connection()->connected(); 218 } 219 220 void QuicClient::Disconnect() { 221 DCHECK(initialized_); 222 223 if (connected()) { 224 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); 225 } 226 epoll_server_->UnregisterFD(fd_); 227 close(fd_); 228 fd_ = -1; 229 initialized_ = false; 230 } 231 232 void QuicClient::SendRequestsAndWaitForResponse( 233 const base::CommandLine::StringVector& args) { 234 for (size_t i = 0; i < args.size(); ++i) { 235 BalsaHeaders headers; 236 headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1"); 237 QuicSpdyClientStream* stream = CreateReliableClientStream(); 238 DCHECK(stream != NULL); 239 stream->SendRequest(headers, "", true); 240 stream->set_visitor(this); 241 } 242 243 while (WaitForEvents()) {} 244 } 245 246 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { 247 if (!connected()) { 248 return NULL; 249 } 250 251 return session_->CreateOutgoingDataStream(); 252 } 253 254 void QuicClient::WaitForStreamToClose(QuicStreamId id) { 255 DCHECK(connected()); 256 257 while (connected() && !session_->IsClosedStream(id)) { 258 epoll_server_->WaitForEventsAndExecuteCallbacks(); 259 } 260 } 261 262 void QuicClient::WaitForCryptoHandshakeConfirmed() { 263 DCHECK(connected()); 264 265 while (connected() && !session_->IsCryptoHandshakeConfirmed()) { 266 epoll_server_->WaitForEventsAndExecuteCallbacks(); 267 } 268 } 269 270 bool QuicClient::WaitForEvents() { 271 DCHECK(connected()); 272 273 epoll_server_->WaitForEventsAndExecuteCallbacks(); 274 return session_->num_active_requests() != 0; 275 } 276 277 void QuicClient::OnEvent(int fd, EpollEvent* event) { 278 DCHECK_EQ(fd, fd_); 279 280 if (event->in_events & EPOLLIN) { 281 while (connected() && ReadAndProcessPacket()) { 282 } 283 } 284 if (connected() && (event->in_events & EPOLLOUT)) { 285 writer_->SetWritable(); 286 session_->connection()->OnCanWrite(); 287 } 288 if (event->in_events & EPOLLERR) { 289 DVLOG(1) << "Epollerr"; 290 } 291 } 292 293 void QuicClient::OnClose(QuicDataStream* stream) { 294 QuicSpdyClientStream* client_stream = 295 static_cast<QuicSpdyClientStream*>(stream); 296 if (response_listener_.get() != NULL) { 297 response_listener_->OnCompleteResponse( 298 stream->id(), client_stream->headers(), client_stream->data()); 299 } 300 301 if (!print_response_) { 302 return; 303 } 304 305 const BalsaHeaders& headers = client_stream->headers(); 306 printf("%s\n", headers.first_line().as_string().c_str()); 307 for (BalsaHeaders::const_header_lines_iterator i = 308 headers.header_lines_begin(); 309 i != headers.header_lines_end(); ++i) { 310 printf("%s: %s\n", i->first.as_string().c_str(), 311 i->second.as_string().c_str()); 312 } 313 printf("%s\n", client_stream->data().c_str()); 314 } 315 316 bool QuicClient::connected() const { 317 return session_.get() && session_->connection() && 318 session_->connection()->connected(); 319 } 320 321 QuicConnectionId QuicClient::GenerateConnectionId() { 322 return QuicRandom::GetInstance()->RandUint64(); 323 } 324 325 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() { 326 return new QuicEpollConnectionHelper(epoll_server_); 327 } 328 329 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { 330 return new QuicDefaultPacketWriter(fd_); 331 } 332 333 int QuicClient::ReadPacket(char* buffer, 334 int buffer_len, 335 IPEndPoint* server_address, 336 IPAddressNumber* client_ip) { 337 return QuicSocketUtils::ReadPacket( 338 fd_, buffer, buffer_len, overflow_supported_ ? &packets_dropped_ : NULL, 339 client_ip, server_address); 340 } 341 342 bool QuicClient::ReadAndProcessPacket() { 343 // Allocate some extra space so we can send an error if the server goes over 344 // the limit. 345 char buf[2 * kMaxPacketSize]; 346 347 IPEndPoint server_address; 348 IPAddressNumber client_ip; 349 350 int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip); 351 352 if (bytes_read < 0) { 353 return false; 354 } 355 356 QuicEncryptedPacket packet(buf, bytes_read, false); 357 358 IPEndPoint client_address(client_ip, client_address_.port()); 359 session_->connection()->ProcessUdpPacket( 360 client_address, server_address, packet); 361 return true; 362 } 363 364 } // namespace tools 365 } // namespace net 366