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.
5 #include "net/tools/quic/quic_client.h"
8 #include <netinet/in.h>
10 #include <sys/epoll.h>
11 #include <sys/socket.h>
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_reliable_client_stream.h"
22 #include "net/tools/quic/quic_socket_utils.h"
25 #define SO_RXQ_OVFL 40
31 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
33 QuicClient::QuicClient(IPEndPoint server_address,
34 const string& server_hostname,
35 const QuicVersionVector& supported_versions,
37 : server_address_(server_address),
38 server_hostname_(server_hostname),
41 helper_(CreateQuicConnectionHelper()),
44 overflow_supported_(false),
45 supported_versions_(supported_versions),
46 print_response_(print_response) {
47 config_.SetDefaults();
48 // TODO(ianswett): Allow the client to change the server's max packet size and
49 // initial congestion window.
50 config_.set_server_max_packet_size(kDefaultMaxPacketSize,
51 kDefaultMaxPacketSize);
52 config_.set_server_initial_congestion_window(kDefaultInitialWindow,
53 kDefaultInitialWindow);
56 QuicClient::QuicClient(IPEndPoint server_address,
57 const string& server_hostname,
58 const QuicConfig& config,
59 const QuicVersionVector& supported_versions)
60 : server_address_(server_address),
61 server_hostname_(server_hostname),
65 helper_(CreateQuicConnectionHelper()),
68 overflow_supported_(false),
69 supported_versions_(supported_versions),
70 print_response_(false) {
73 QuicClient::~QuicClient() {
75 session()->connection()->SendConnectionClosePacket(
76 QUIC_PEER_GOING_AWAY, "");
80 bool QuicClient::Initialize() {
81 DCHECK(!initialized_);
83 epoll_server_.set_timeout_in_us(50 * 1000);
84 crypto_config_.SetDefaults();
86 int address_family = server_address_.GetSockAddrFamily();
87 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
89 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
94 int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
95 sizeof(get_overflow));
97 DLOG(WARNING) << "Socket overflow detection not supported";
99 overflow_supported_ = true;
102 int get_local_ip = 1;
103 if (address_family == AF_INET) {
104 rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO,
105 &get_local_ip, sizeof(get_local_ip));
107 rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO,
108 &get_local_ip, sizeof(get_local_ip));
112 LOG(ERROR) << "IP detection not supported" << strerror(errno);
116 if (bind_to_address_.size() != 0) {
117 client_address_ = IPEndPoint(bind_to_address_, local_port_);
118 } else if (address_family == AF_INET) {
119 IPAddressNumber any4;
120 CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
121 client_address_ = IPEndPoint(any4, local_port_);
123 IPAddressNumber any6;
124 CHECK(net::ParseIPLiteralToNumber("::", &any6));
125 client_address_ = IPEndPoint(any6, local_port_);
128 sockaddr_storage raw_addr;
129 socklen_t raw_addr_len = sizeof(raw_addr);
130 CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
133 reinterpret_cast<const sockaddr*>(&raw_addr),
136 LOG(ERROR) << "Bind failed: " << strerror(errno);
140 SockaddrStorage storage;
141 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
142 !client_address_.FromSockAddr(storage.addr, storage.addr_len)) {
143 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno);
146 epoll_server_.RegisterFD(fd_, this, kEpollFlags);
151 bool QuicClient::Connect() {
152 if (!StartConnect()) {
155 while (EncryptionBeingEstablished()) {
158 return session_->connection()->connected();
161 bool QuicClient::StartConnect() {
162 DCHECK(!connected() && initialized_);
164 QuicPacketWriter* writer = CreateQuicPacketWriter();
165 if (writer_.get() != writer) {
166 writer_.reset(writer);
169 session_.reset(new QuicClientSession(
172 new QuicConnection(GenerateGuid(), server_address_, helper_.get(),
173 writer_.get(), false, supported_versions_),
175 return session_->CryptoConnect();
178 bool QuicClient::EncryptionBeingEstablished() {
179 return !session_->IsEncryptionEstablished() &&
180 session_->connection()->connected();
183 void QuicClient::Disconnect() {
186 session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
187 epoll_server_.UnregisterFD(fd_);
190 initialized_ = false;
193 void QuicClient::SendRequestsAndWaitForResponse(
194 const CommandLine::StringVector& args) {
195 for (size_t i = 0; i < args.size(); i++) {
196 BalsaHeaders headers;
197 headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1");
198 QuicReliableClientStream* stream = CreateReliableClientStream();
199 stream->SendRequest(headers, "", true);
200 stream->set_visitor(this);
203 while (WaitForEvents()) { }
206 QuicReliableClientStream* QuicClient::CreateReliableClientStream() {
211 return session_->CreateOutgoingReliableStream();
214 void QuicClient::WaitForStreamToClose(QuicStreamId id) {
217 while (!session_->IsClosedStream(id)) {
218 epoll_server_.WaitForEventsAndExecuteCallbacks();
222 void QuicClient::WaitForCryptoHandshakeConfirmed() {
225 while (!session_->IsCryptoHandshakeConfirmed()) {
226 epoll_server_.WaitForEventsAndExecuteCallbacks();
230 bool QuicClient::WaitForEvents() {
233 epoll_server_.WaitForEventsAndExecuteCallbacks();
234 return session_->num_active_requests() != 0;
237 void QuicClient::OnEvent(int fd, EpollEvent* event) {
240 if (event->in_events & EPOLLIN) {
241 while (connected() && ReadAndProcessPacket()) {
244 if (connected() && (event->in_events & EPOLLOUT)) {
245 session_->connection()->OnCanWrite();
247 if (event->in_events & EPOLLERR) {
248 DLOG(INFO) << "Epollerr";
252 void QuicClient::OnClose(ReliableQuicStream* stream) {
253 if (!print_response_) {
257 QuicReliableClientStream* client_stream =
258 static_cast<QuicReliableClientStream*>(stream);
259 const BalsaHeaders& headers = client_stream->headers();
260 printf("%s\n", headers.first_line().as_string().c_str());
261 for (BalsaHeaders::const_header_lines_iterator i =
262 headers.header_lines_begin();
263 i != headers.header_lines_end(); ++i) {
264 printf("%s: %s\n", i->first.as_string().c_str(),
265 i->second.as_string().c_str());
267 printf("%s\n", client_stream->data().c_str());
270 QuicPacketCreator::Options* QuicClient::options() {
271 if (session() == NULL) {
274 return session_->options();
277 bool QuicClient::connected() const {
278 return session_.get() && session_->connection() &&
279 session_->connection()->connected();
282 QuicGuid QuicClient::GenerateGuid() {
283 return QuicRandom::GetInstance()->RandUint64();
286 QuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() {
287 return new QuicEpollConnectionHelper(&epoll_server_);
290 QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
291 return new QuicDefaultPacketWriter(fd_);
294 bool QuicClient::ReadAndProcessPacket() {
295 // Allocate some extra space so we can send an error if the server goes over
297 char buf[2 * kMaxPacketSize];
299 IPEndPoint server_address;
300 IPAddressNumber client_ip;
302 int bytes_read = QuicSocketUtils::ReadPacket(
303 fd_, buf, arraysize(buf), overflow_supported_ ? &packets_dropped_ : NULL,
304 &client_ip, &server_address);
306 if (bytes_read < 0) {
310 QuicEncryptedPacket packet(buf, bytes_read, false);
311 QuicGuid our_guid = session_->connection()->guid();
312 QuicGuid packet_guid;
314 if (!QuicFramer::ReadGuidFromPacket(packet, &packet_guid)) {
315 DLOG(INFO) << "Could not read GUID from packet";
318 if (packet_guid != our_guid) {
319 DLOG(INFO) << "Ignoring packet from unexpected GUID: "
320 << packet_guid << " instead of " << our_guid;
324 IPEndPoint client_address(client_ip, client_address_.port());
325 session_->connection()->ProcessUdpPacket(
326 client_address, server_address, packet);