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