1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_client.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <errno.h>
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <netinet/in.h>
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string.h>
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/epoll.h>
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <sys/socket.h>
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <unistd.h>
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
15c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "net/quic/congestion_control/tcp_receiver.h"
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/crypto/quic_random.h"
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_connection.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_data_reader.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/quic/quic_protocol.h"
20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "net/quic/quic_server_id.h"
214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/tools/balsa/balsa_headers.h"
226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "net/tools/epoll_server/epoll_server.h"
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_epoll_connection_helper.h"
24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/tools/quic/quic_socket_utils.h"
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/tools/quic/quic_spdy_client_stream.h"
26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#ifndef SO_RXQ_OVFL
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#define SO_RXQ_OVFL 40
29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif
30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace net {
32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace tools {
33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicClient::QuicClient(IPEndPoint server_address,
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       const QuicServerId& server_id,
381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                       const QuicVersionVector& supported_versions,
396d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                       bool print_response,
406d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                       EpollServer* epoll_server)
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    : server_address_(server_address),
42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      server_id_(server_id),
43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      local_port_(0),
446d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      epoll_server_(epoll_server),
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      fd_(-1),
461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      helper_(CreateQuicConnectionHelper()),
47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      initialized_(false),
48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      packets_dropped_(0),
49558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      overflow_supported_(false),
501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      supported_versions_(supported_versions),
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      print_response_(print_response) {
52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  config_.SetDefaults();
53b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
54b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
55b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)QuicClient::QuicClient(IPEndPoint server_address,
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       const QuicServerId& server_id,
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                       const QuicVersionVector& supported_versions,
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                       bool print_response,
596d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                       const QuicConfig& config,
606d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                       EpollServer* epoll_server)
61b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    : server_address_(server_address),
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      server_id_(server_id),
63b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      config_(config),
64b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      local_port_(0),
656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      epoll_server_(epoll_server),
66b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      fd_(-1),
671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      helper_(CreateQuicConnectionHelper()),
68b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      initialized_(false),
69b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      packets_dropped_(0),
70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      overflow_supported_(false),
711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      supported_versions_(supported_versions),
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      print_response_(print_response) {
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)QuicClient::~QuicClient() {
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (connected()) {
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    session()->connection()->SendConnectionClosePacket(
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        QUIC_PEER_GOING_AWAY, "");
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  if (fd_ > 0) {
816d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    epoll_server_->UnregisterFD(fd_);
826d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::Initialize() {
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(!initialized_);
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
886d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  epoll_server_->set_timeout_in_us(50 * 1000);
89b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  crypto_config_.SetDefaults();
90b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!CreateUDPSocket()) {
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
956d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  epoll_server_->RegisterFD(fd_, this, kEpollFlags);
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  initialized_ = true;
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicClient::DummyPacketWriterFactory::DummyPacketWriterFactory(
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    QuicPacketWriter* writer)
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    : writer_(writer) {}
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicClient::DummyPacketWriterFactory::~DummyPacketWriterFactory() {}
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)QuicPacketWriter* QuicClient::DummyPacketWriterFactory::Create(
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    QuicConnection* /*connection*/) const {
10803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  return writer_;
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)}
11003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
11103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicClient::CreateUDPSocket() {
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  int address_family = server_address_.GetSockAddrFamily();
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (fd_ < 0) {
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int get_overflow = 1;
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int rc = setsockopt(fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow,
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                      sizeof(get_overflow));
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (rc < 0) {
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DLOG(WARNING) << "Socket overflow detection not supported";
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    overflow_supported_ = true;
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
1300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                             TcpReceiver::kReceiveWindowTCP)) {
131c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
132c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
133c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
1340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!QuicSocketUtils::SetSendBufferSize(fd_,
1350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                          TcpReceiver::kReceiveWindowTCP)) {
136c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return false;
137c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  }
138c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
139116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (rc < 0) {
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "IP detection not supported" << strerror(errno);
142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (bind_to_address_.size() != 0) {
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_address_ = IPEndPoint(bind_to_address_, local_port_);
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else if (address_family == AF_INET) {
148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPAddressNumber any4;
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK(net::ParseIPLiteralToNumber("0.0.0.0", &any4));
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_address_ = IPEndPoint(any4, local_port_);
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    IPAddressNumber any6;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CHECK(net::ParseIPLiteralToNumber("::", &any6));
154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    client_address_ = IPEndPoint(any6, local_port_);
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
156c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  sockaddr_storage raw_addr;
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  socklen_t raw_addr_len = sizeof(raw_addr);
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CHECK(client_address_.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                           &raw_addr_len));
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  rc = bind(fd_,
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            reinterpret_cast<const sockaddr*>(&raw_addr),
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            sizeof(raw_addr));
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (rc < 0) {
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Bind failed: " << strerror(errno);
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  SockaddrStorage storage;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      !client_address_.FromSockAddr(storage.addr, storage.addr_len)) {
172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(ERROR) << "Unable to get self address.  Error: " << strerror(errno);
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::Connect() {
179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!StartConnect()) {
180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  while (EncryptionBeingEstablished()) {
183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    WaitForEvents();
184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return session_->connection()->connected();
186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::StartConnect() {
1895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(initialized_);
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!connected());
191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  QuicPacketWriter* writer = CreateQuicPacketWriter();
1931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
19403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  DummyPacketWriterFactory factory(writer);
19503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_.reset(new QuicClientSession(
197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      config_,
1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      new QuicConnection(GenerateConnectionId(),
1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         server_address_,
2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         helper_.get(),
20103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         factory,
20203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         /* owns_writer= */ false,
20303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)                         /* is_server= */ false,
2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                         supported_versions_)));
20503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Reset |writer_| after |session_| so that the old writer outlives the old
2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // session.
2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (writer_.get() != writer) {
2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    writer_.reset(writer);
2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  }
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  session_->InitializeSession(server_id_, &crypto_config_);
212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return session_->CryptoConnect();
213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::EncryptionBeingEstablished() {
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return !session_->IsEncryptionEstablished() &&
217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session_->connection()->connected();
218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicClient::Disconnect() {
221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(initialized_);
222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (connected()) {
224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    session()->connection()->SendConnectionClose(QUIC_PEER_GOING_AWAY);
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
2266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  epoll_server_->UnregisterFD(fd_);
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  close(fd_);
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  fd_ = -1;
22990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  initialized_ = false;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void QuicClient::SendRequestsAndWaitForResponse(
23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const base::CommandLine::StringVector& args) {
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < args.size(); ++i) {
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    BalsaHeaders headers;
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    headers.SetRequestFirstlineFromStringPieces("GET", args[i], "HTTP/1.1");
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    QuicSpdyClientStream* stream = CreateReliableClientStream();
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    DCHECK(stream != NULL);
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    stream->SendRequest(headers, "", true);
2404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    stream->set_visitor(this);
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (WaitForEvents()) {}
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)QuicSpdyClientStream* QuicClient::CreateReliableClientStream() {
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!connected()) {
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return NULL;
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return session_->CreateOutgoingDataStream();
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicClient::WaitForStreamToClose(QuicStreamId id) {
255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(connected());
256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (connected() && !session_->IsClosedStream(id)) {
2586d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    epoll_server_->WaitForEventsAndExecuteCallbacks();
259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void QuicClient::WaitForCryptoHandshakeConfirmed() {
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(connected());
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (connected() && !session_->IsCryptoHandshakeConfirmed()) {
2666d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    epoll_server_->WaitForEventsAndExecuteCallbacks();
2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::WaitForEvents() {
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(connected());
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  epoll_server_->WaitForEventsAndExecuteCallbacks();
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return session_->num_active_requests() != 0;
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void QuicClient::OnEvent(int fd, EpollEvent* event) {
278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(fd, fd_);
279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (event->in_events & EPOLLIN) {
281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (connected() && ReadAndProcessPacket()) {
282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (connected() && (event->in_events & EPOLLOUT)) {
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    writer_->SetWritable();
286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    session_->connection()->OnCanWrite();
287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (event->in_events & EPOLLERR) {
2895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DVLOG(1) << "Epollerr";
290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void QuicClient::OnClose(QuicDataStream* stream) {
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  QuicSpdyClientStream* client_stream =
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<QuicSpdyClientStream*>(stream);
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (response_listener_.get() != NULL) {
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    response_listener_->OnCompleteResponse(
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        stream->id(), client_stream->headers(), client_stream->data());
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!print_response_) {
3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
3034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  const BalsaHeaders& headers = client_stream->headers();
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  printf("%s\n", headers.first_line().as_string().c_str());
3074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (BalsaHeaders::const_header_lines_iterator i =
3084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           headers.header_lines_begin();
3094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)       i != headers.header_lines_end(); ++i) {
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    printf("%s: %s\n", i->first.as_string().c_str(),
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)           i->second.as_string().c_str());
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
3134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  printf("%s\n", client_stream->data().c_str());
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::connected() const {
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return session_.get() && session_->connection() &&
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      session_->connection()->connected();
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicConnectionId QuicClient::GenerateConnectionId() {
3221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return QuicRandom::GetInstance()->RandUint64();
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3252385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen MurdochQuicEpollConnectionHelper* QuicClient::CreateQuicConnectionHelper() {
3266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return new QuicEpollConnectionHelper(epoll_server_);
3271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
3281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)QuicPacketWriter* QuicClient::CreateQuicPacketWriter() {
3301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return new QuicDefaultPacketWriter(fd_);
3312385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch}
3322385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch
333e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochint QuicClient::ReadPacket(char* buffer,
334e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           int buffer_len,
335e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           IPEndPoint* server_address,
336e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                           IPAddressNumber* client_ip) {
337e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return QuicSocketUtils::ReadPacket(
338e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      fd_, buffer, buffer_len, overflow_supported_ ? &packets_dropped_ : NULL,
339e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      client_ip, server_address);
340e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
341e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool QuicClient::ReadAndProcessPacket() {
343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Allocate some extra space so we can send an error if the server goes over
344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // the limit.
345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  char buf[2 * kMaxPacketSize];
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint server_address;
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPAddressNumber client_ip;
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
350e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  int bytes_read = ReadPacket(buf, arraysize(buf), &server_address, &client_ip);
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (bytes_read < 0) {
353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return false;
354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  QuicEncryptedPacket packet(buf, bytes_read, false);
357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  IPEndPoint client_address(client_ip, client_address_.port());
359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  session_->connection()->ProcessUdpPacket(
360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      client_address, server_address, packet);
361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return true;
362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace tools
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace net
366