Home | History | Annotate | Download | only in quic
      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