| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/quic/quic_client.h" | 5 #include "net/tools/quic/quic_client.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <netinet/in.h> | 8 #include <netinet/in.h> |
| 9 #include <string.h> | 9 #include <string.h> |
| 10 #include <sys/epoll.h> | 10 #include <sys/epoll.h> |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 initialized_(false), | 65 initialized_(false), |
| 66 packets_dropped_(0), | 66 packets_dropped_(0), |
| 67 overflow_supported_(false), | 67 overflow_supported_(false), |
| 68 supported_versions_(supported_versions), | 68 supported_versions_(supported_versions), |
| 69 print_response_(false), | 69 print_response_(false), |
| 70 initial_flow_control_window_(initial_flow_control_window) { | 70 initial_flow_control_window_(initial_flow_control_window) { |
| 71 } | 71 } |
| 72 | 72 |
| 73 QuicClient::~QuicClient() { | 73 QuicClient::~QuicClient() { |
| 74 if (connected()) { | 74 if (connected()) { |
| 75 session()->connection()->SendConnectionClosePacket( | 75 session()->connection()->SendConnectionClosePacket(QUIC_PEER_GOING_AWAY, |
| 76 QUIC_PEER_GOING_AWAY, ""); | 76 ""); |
| 77 } | 77 } |
| 78 } | 78 } |
| 79 | 79 |
| 80 bool QuicClient::Initialize() { | 80 bool QuicClient::Initialize() { |
| 81 DCHECK(!initialized_); | 81 DCHECK(!initialized_); |
| 82 | 82 |
| 83 epoll_server_.set_timeout_in_us(50 * 1000); | 83 epoll_server_.set_timeout_in_us(50 * 1000); |
| 84 crypto_config_.SetDefaults(); | 84 crypto_config_.SetDefaults(); |
| 85 | 85 |
| 86 int address_family = server_address_.GetSockAddrFamily(); | 86 int address_family = server_address_.GetSockAddrFamily(); |
| 87 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); | 87 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); |
| 88 if (fd_ < 0) { | 88 if (fd_ < 0) { |
| 89 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno); | 89 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno); |
| 90 return false; | 90 return false; |
| 91 } | 91 } |
| 92 | 92 |
| 93 int get_overflow = 1; | 93 int get_overflow = 1; |
| 94 int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, | 94 int rc = setsockopt( |
| 95 sizeof(get_overflow)); | 95 fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, sizeof(get_overflow)); |
| 96 if (rc < 0) { | 96 if (rc < 0) { |
| 97 DLOG(WARNING) << "Socket overflow detection not supported"; | 97 DLOG(WARNING) << "Socket overflow detection not supported"; |
| 98 } else { | 98 } else { |
| 99 overflow_supported_ = true; | 99 overflow_supported_ = true; |
| 100 } | 100 } |
| 101 | 101 |
| 102 if (!QuicSocketUtils::SetReceiveBufferSize(fd_, | 102 if (!QuicSocketUtils::SetReceiveBufferSize(fd_, |
| 103 TcpReceiver::kReceiveWindowTCP)) { | 103 TcpReceiver::kReceiveWindowTCP)) { |
| 104 return false; | 104 return false; |
| 105 } | 105 } |
| 106 | 106 |
| 107 if (!QuicSocketUtils::SetSendBufferSize(fd_, | 107 if (!QuicSocketUtils::SetSendBufferSize(fd_, |
| 108 TcpReceiver::kReceiveWindowTCP)) { | 108 TcpReceiver::kReceiveWindowTCP)) { |
| 109 return false; | 109 return false; |
| 110 } | 110 } |
| 111 | 111 |
| 112 int get_local_ip = 1; | 112 int get_local_ip = 1; |
| 113 if (address_family == AF_INET) { | 113 if (address_family == AF_INET) { |
| 114 rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO, | 114 rc = setsockopt( |
| 115 &get_local_ip, sizeof(get_local_ip)); | 115 fd_, IPPROTO_IP, IP_PKTINFO, &get_local_ip, sizeof(get_local_ip)); |
| 116 } else { | 116 } else { |
| 117 rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO, | 117 rc = setsockopt(fd_, |
| 118 &get_local_ip, sizeof(get_local_ip)); | 118 IPPROTO_IPV6, |
| 119 IPV6_RECVPKTINFO, |
| 120 &get_local_ip, |
| 121 sizeof(get_local_ip)); |
| 119 } | 122 } |
| 120 | 123 |
| 121 if (rc < 0) { | 124 if (rc < 0) { |
| 122 LOG(ERROR) << "IP detection not supported" << strerror(errno); | 125 LOG(ERROR) << "IP detection not supported" << strerror(errno); |
| 123 return false; | 126 return false; |
| 124 } | 127 } |
| 125 | 128 |
| 126 if (bind_to_address_.size() != 0) { | 129 if (bind_to_address_.size() != 0) { |
| 127 client_address_ = IPEndPoint(bind_to_address_, local_port_); | 130 client_address_ = IPEndPoint(bind_to_address_, local_port_); |
| 128 } else if (address_family == AF_INET) { | 131 } else if (address_family == AF_INET) { |
| 129 IPAddressNumber any4; | 132 IPAddressNumber any4; |
| 130 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4)); | 133 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4)); |
| 131 client_address_ = IPEndPoint(any4, local_port_); | 134 client_address_ = IPEndPoint(any4, local_port_); |
| 132 } else { | 135 } else { |
| 133 IPAddressNumber any6; | 136 IPAddressNumber any6; |
| 134 CHECK(net::ParseIPLiteralToNumber("::", &any6)); | 137 CHECK(net::ParseIPLiteralToNumber("::", &any6)); |
| 135 client_address_ = IPEndPoint(any6, local_port_); | 138 client_address_ = IPEndPoint(any6, local_port_); |
| 136 } | 139 } |
| 137 | 140 |
| 138 sockaddr_storage raw_addr; | 141 sockaddr_storage raw_addr; |
| 139 socklen_t raw_addr_len = sizeof(raw_addr); | 142 socklen_t raw_addr_len = sizeof(raw_addr); |
| 140 CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), | 143 CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), |
| 141 &raw_addr_len)); | 144 &raw_addr_len)); |
| 142 rc = bind(fd_, | 145 rc = |
| 143 reinterpret_cast<const sockaddr*>(&raw_addr), | 146 bind(fd_, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr)); |
| 144 sizeof(raw_addr)); | |
| 145 if (rc < 0) { | 147 if (rc < 0) { |
| 146 LOG(ERROR) << "Bind failed: " << strerror(errno); | 148 LOG(ERROR) << "Bind failed: " << strerror(errno); |
| 147 return false; | 149 return false; |
| 148 } | 150 } |
| 149 | 151 |
| 150 SockaddrStorage storage; | 152 SockaddrStorage storage; |
| 151 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || | 153 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || |
| 152 !client_address_.FromSockAddr(storage.addr, storage.addr_len)) { | 154 !client_address_.FromSockAddr(storage.addr, storage.addr_len)) { |
| 153 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); | 155 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); |
| 154 } | 156 } |
| (...skipping 15 matching lines...) Expand all Loading... |
| 170 | 172 |
| 171 bool QuicClient::StartConnect() { | 173 bool QuicClient::StartConnect() { |
| 172 DCHECK(initialized_); | 174 DCHECK(initialized_); |
| 173 DCHECK(!connected()); | 175 DCHECK(!connected()); |
| 174 | 176 |
| 175 QuicPacketWriter* writer = CreateQuicPacketWriter(); | 177 QuicPacketWriter* writer = CreateQuicPacketWriter(); |
| 176 if (writer_.get() != writer) { | 178 if (writer_.get() != writer) { |
| 177 writer_.reset(writer); | 179 writer_.reset(writer); |
| 178 } | 180 } |
| 179 | 181 |
| 180 session_.reset(new QuicClientSession( | 182 session_.reset( |
| 181 server_id_, | 183 new QuicClientSession(server_id_, |
| 182 config_, | 184 config_, |
| 183 new QuicConnection(GenerateConnectionId(), server_address_, helper_.get(), | 185 new QuicConnection(GenerateConnectionId(), |
| 184 writer_.get(), false, supported_versions_, | 186 server_address_, |
| 185 initial_flow_control_window_), | 187 helper_.get(), |
| 186 &crypto_config_)); | 188 writer_.get(), |
| 189 false, |
| 190 supported_versions_, |
| 191 initial_flow_control_window_), |
| 192 &crypto_config_)); |
| 187 return session_->CryptoConnect(); | 193 return session_->CryptoConnect(); |
| 188 } | 194 } |
| 189 | 195 |
| 190 bool QuicClient::EncryptionBeingEstablished() { | 196 bool QuicClient::EncryptionBeingEstablished() { |
| 191 return !session_->IsEncryptionEstablished() && | 197 return !session_->IsEncryptionEstablished() && |
| 192 session_->connection()->connected(); | 198 session_->connection()->connected(); |
| 193 } | 199 } |
| 194 | 200 |
| 195 void QuicClient::Disconnect() { | 201 void QuicClient::Disconnect() { |
| 196 DCHECK(initialized_); | 202 DCHECK(initialized_); |
| 197 | 203 |
| 198 if (connected()) { | 204 if (connected()) { |
| 199 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); | 205 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY); |
| 200 } | 206 } |
| 201 epoll_server_.UnregisterFD(fd_); | 207 epoll_server_.UnregisterFD(fd_); |
| 202 close(fd_); | 208 close(fd_); |
| 203 fd_ = -1; | 209 fd_ = -1; |
| 204 initialized_ = false; | 210 initialized_ = false; |
| 205 } | 211 } |
| 206 | 212 |
| 207 void QuicClient::SendRequestsAndWaitForResponse( | 213 void QuicClient::SendRequestsAndWaitForResponse( |
| 208 const CommandLine::StringVector& args) { | 214 const CommandLine::StringVector& args) { |
| 209 for (size_t i = 0; i < args.size(); ++i) { | 215 for (size_t i = 0; i < args.size(); ++i) { |
| 210 BalsaHeaders headers; | 216 BalsaHeaders headers; |
| 211 headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1"); | 217 headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1"); |
| 212 QuicSpdyClientStream* stream = CreateReliableClientStream(); | 218 QuicSpdyClientStream* stream = CreateReliableClientStream(); |
| 213 stream->SendRequest(headers, "", true); | 219 stream->SendRequest(headers, "", true); |
| 214 stream->set_visitor(this); | 220 stream->set_visitor(this); |
| 215 } | 221 } |
| 216 | 222 |
| 217 while (WaitForEvents()) { } | 223 while (WaitForEvents()) { |
| 224 } |
| 218 } | 225 } |
| 219 | 226 |
| 220 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { | 227 QuicSpdyClientStream* QuicClient::CreateReliableClientStream() { |
| 221 if (!connected()) { | 228 if (!connected()) { |
| 222 return NULL; | 229 return NULL; |
| 223 } | 230 } |
| 224 | 231 |
| 225 return session_->CreateOutgoingDataStream(); | 232 return session_->CreateOutgoingDataStream(); |
| 226 } | 233 } |
| 227 | 234 |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 } | 280 } |
| 274 | 281 |
| 275 if (!print_response_) { | 282 if (!print_response_) { |
| 276 return; | 283 return; |
| 277 } | 284 } |
| 278 | 285 |
| 279 const BalsaHeaders& headers = client_stream->headers(); | 286 const BalsaHeaders& headers = client_stream->headers(); |
| 280 printf("%s\n", headers.first_line().as_string().c_str()); | 287 printf("%s\n", headers.first_line().as_string().c_str()); |
| 281 for (BalsaHeaders::const_header_lines_iterator i = | 288 for (BalsaHeaders::const_header_lines_iterator i = |
| 282 headers.header_lines_begin(); | 289 headers.header_lines_begin(); |
| 283 i != headers.header_lines_end(); ++i) { | 290 i != headers.header_lines_end(); |
| 284 printf("%s: %s\n", i->first.as_string().c_str(), | 291 ++i) { |
| 292 printf("%s: %s\n", |
| 293 i->first.as_string().c_str(), |
| 285 i->second.as_string().c_str()); | 294 i->second.as_string().c_str()); |
| 286 } | 295 } |
| 287 printf("%s\n", client_stream->data().c_str()); | 296 printf("%s\n", client_stream->data().c_str()); |
| 288 } | 297 } |
| 289 | 298 |
| 290 QuicPacketCreator::Options* QuicClient::options() { | 299 QuicPacketCreator::Options* QuicClient::options() { |
| 291 if (session() == NULL) { | 300 if (session() == NULL) { |
| 292 return NULL; | 301 return NULL; |
| 293 } | 302 } |
| 294 return session_->options(); | 303 return session_->options(); |
| 295 } | 304 } |
| 296 | 305 |
| 297 bool QuicClient::connected() const { | 306 bool QuicClient::connected() const { |
| 298 return session_.get() && session_->connection() && | 307 return session_.get() && session_->connection() && |
| 299 session_->connection()->connected(); | 308 session_->connection()->connected(); |
| 300 } | 309 } |
| 301 | 310 |
| 302 QuicConnectionId QuicClient::GenerateConnectionId() { | 311 QuicConnectionId QuicClient::GenerateConnectionId() { |
| 303 return QuicRandom::GetInstance()->RandUint64(); | 312 return QuicRandom::GetInstance()->RandUint64(); |
| 304 } | 313 } |
| 305 | 314 |
| 306 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() { | 315 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() { |
| 307 return new QuicEpollConnectionHelper(&epoll_server_); | 316 return new QuicEpollConnectionHelper(&epoll_server_); |
| 308 } | 317 } |
| 309 | 318 |
| 310 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { | 319 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() { |
| 311 return new QuicDefaultPacketWriter(fd_); | 320 return new QuicDefaultPacketWriter(fd_); |
| 312 } | 321 } |
| 313 | 322 |
| 314 int QuicClient::ReadPacket(char* buffer, | 323 int QuicClient::ReadPacket(char* buffer, |
| 315 int buffer_len, | 324 int buffer_len, |
| 316 IPEndPoint* server_address, | 325 IPEndPoint* server_address, |
| 317 IPAddressNumber* client_ip) { | 326 IPAddressNumber* client_ip) { |
| 318 return QuicSocketUtils::ReadPacket( | 327 return QuicSocketUtils::ReadPacket( |
| 319 fd_, buffer, buffer_len, overflow_supported_ ? &packets_dropped_ : NULL, | 328 fd_, |
| 320 client_ip, server_address); | 329 buffer, |
| 330 buffer_len, |
| 331 overflow_supported_ ? &packets_dropped_ : NULL, |
| 332 client_ip, |
| 333 server_address); |
| 321 } | 334 } |
| 322 | 335 |
| 323 bool QuicClient::ReadAndProcessPacket() { | 336 bool QuicClient::ReadAndProcessPacket() { |
| 324 // Allocate some extra space so we can send an error if the server goes over | 337 // Allocate some extra space so we can send an error if the server goes over |
| 325 // the limit. | 338 // the limit. |
| 326 char buf[2 * kMaxPacketSize]; | 339 char buf[2 * kMaxPacketSize]; |
| 327 | 340 |
| 328 IPEndPoint server_address; | 341 IPEndPoint server_address; |
| 329 IPAddressNumber client_ip; | 342 IPAddressNumber client_ip; |
| 330 | 343 |
| 331 int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip); | 344 int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip); |
| 332 | 345 |
| 333 if (bytes_read < 0) { | 346 if (bytes_read < 0) { |
| 334 return false; | 347 return false; |
| 335 } | 348 } |
| 336 | 349 |
| 337 QuicEncryptedPacket packet(buf, bytes_read, false); | 350 QuicEncryptedPacket packet(buf, bytes_read, false); |
| 338 | 351 |
| 339 IPEndPoint client_address(client_ip, client_address_.port()); | 352 IPEndPoint client_address(client_ip, client_address_.port()); |
| 340 session_->connection()->ProcessUdpPacket( | 353 session_->connection()->ProcessUdpPacket( |
| 341 client_address, server_address, packet); | 354 client_address, server_address, packet); |
| 342 return true; | 355 return true; |
| 343 } | 356 } |
| 344 | 357 |
| 345 } // namespace tools | 358 } // namespace tools |
| 346 } // namespace net | 359 } // namespace net |
| OLD | NEW |