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_server.h"
      6 
      7 #include <errno.h>
      8 #include <features.h>
      9 #include <netinet/in.h>
     10 #include <string.h>
     11 #include <sys/epoll.h>
     12 #include <sys/socket.h>
     13 
     14 #include "net/base/ip_endpoint.h"
     15 #include "net/quic/congestion_control/tcp_receiver.h"
     16 #include "net/quic/crypto/crypto_handshake.h"
     17 #include "net/quic/crypto/quic_random.h"
     18 #include "net/quic/quic_clock.h"
     19 #include "net/quic/quic_crypto_stream.h"
     20 #include "net/quic/quic_data_reader.h"
     21 #include "net/quic/quic_protocol.h"
     22 #include "net/tools/quic/quic_dispatcher.h"
     23 #include "net/tools/quic/quic_in_memory_cache.h"
     24 #include "net/tools/quic/quic_socket_utils.h"
     25 
     26 #define MMSG_MORE 0
     27 
     28 #ifndef SO_RXQ_OVFL
     29 #define SO_RXQ_OVFL 40
     30 #endif
     31 
     32 namespace net {
     33 namespace tools {
     34 
     35 namespace {
     36 
     37 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
     38 const char kSourceAddressTokenSecret[] = "secret";
     39 const uint32 kServerInitialFlowControlWindow = 100 * net::kMaxPacketSize;
     40 
     41 }  // namespace
     42 
     43 QuicServer::QuicServer()
     44     : port_(0),
     45       fd_(-1),
     46       packets_dropped_(0),
     47       overflow_supported_(false),
     48       use_recvmmsg_(false),
     49       crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
     50       supported_versions_(QuicSupportedVersions()) {
     51   // Use hardcoded crypto parameters for now.
     52   config_.SetDefaults();
     53   Initialize();
     54 }
     55 
     56 QuicServer::QuicServer(const QuicConfig& config,
     57                        const QuicVersionVector& supported_versions)
     58     : port_(0),
     59       fd_(-1),
     60       packets_dropped_(0),
     61       overflow_supported_(false),
     62       use_recvmmsg_(false),
     63       config_(config),
     64       crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
     65       supported_versions_(supported_versions) {
     66   Initialize();
     67 }
     68 
     69 void QuicServer::Initialize() {
     70 #if MMSG_MORE
     71   use_recvmmsg_ = true;
     72 #endif
     73   epoll_server_.set_timeout_in_us(50 * 1000);
     74   // Initialize the in memory cache now.
     75   QuicInMemoryCache::GetInstance();
     76 
     77   QuicEpollClock clock(&epoll_server_);
     78 
     79   scoped_ptr<CryptoHandshakeMessage> scfg(
     80       crypto_config_.AddDefaultConfig(
     81           QuicRandom::GetInstance(), &clock,
     82           QuicCryptoServerConfig::ConfigOptions()));
     83 
     84   // Set flow control options in the config.
     85   config_.SetInitialCongestionWindowToSend(kServerInitialFlowControlWindow);
     86 }
     87 
     88 QuicServer::~QuicServer() {
     89 }
     90 
     91 bool QuicServer::Listen(const IPEndPoint& address) {
     92   port_ = address.port();
     93   int address_family = address.GetSockAddrFamily();
     94   fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
     95   if (fd_ < 0) {
     96     LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
     97     return false;
     98   }
     99 
    100   // Enable the socket option that allows the local address to be
    101   // returned if the socket is bound to more than one address.
    102   int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
    103 
    104   if (rc < 0) {
    105     LOG(ERROR) << "IP detection not supported" << strerror(errno);
    106     return false;
    107   }
    108 
    109   int get_overflow = 1;
    110   rc = setsockopt(
    111       fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, sizeof(get_overflow));
    112 
    113   if (rc < 0) {
    114     DLOG(WARNING) << "Socket overflow detection not supported";
    115   } else {
    116     overflow_supported_ = true;
    117   }
    118 
    119   // These send and receive buffer sizes are sized for a single connection,
    120   // because the default usage of QuicServer is as a test server with one or
    121   // two clients.  Adjust higher for use with many clients.
    122   if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
    123                                              TcpReceiver::kReceiveWindowTCP)) {
    124     return false;
    125   }
    126 
    127   if (!QuicSocketUtils::SetSendBufferSize(fd_,
    128                                           TcpReceiver::kReceiveWindowTCP)) {
    129     return false;
    130   }
    131 
    132   sockaddr_storage raw_addr;
    133   socklen_t raw_addr_len = sizeof(raw_addr);
    134   CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
    135                            &raw_addr_len));
    136   rc = bind(fd_,
    137             reinterpret_cast<const sockaddr*>(&raw_addr),
    138             sizeof(raw_addr));
    139   if (rc < 0) {
    140     LOG(ERROR) << "Bind failed: " << strerror(errno);
    141     return false;
    142   }
    143 
    144   DVLOG(1) << "Listening on " << address.ToString();
    145   if (port_ == 0) {
    146     SockaddrStorage storage;
    147     IPEndPoint server_address;
    148     if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
    149         !server_address.FromSockAddr(storage.addr, storage.addr_len)) {
    150       LOG(ERROR) << "Unable to get self address.  Error: " << strerror(errno);
    151       return false;
    152     }
    153     port_ = server_address.port();
    154     DVLOG(1) << "Kernel assigned port is " << port_;
    155   }
    156 
    157   epoll_server_.RegisterFD(fd_, this, kEpollFlags);
    158   dispatcher_.reset(CreateQuicDispatcher());
    159   dispatcher_->Initialize(fd_);
    160 
    161   return true;
    162 }
    163 
    164 QuicDispatcher* QuicServer::CreateQuicDispatcher() {
    165   return new QuicDispatcher(
    166       config_,
    167       crypto_config_,
    168       supported_versions_,
    169       new QuicDispatcher::DefaultPacketWriterFactory(),
    170       &epoll_server_);
    171 }
    172 
    173 void QuicServer::WaitForEvents() {
    174   epoll_server_.WaitForEventsAndExecuteCallbacks();
    175 }
    176 
    177 void QuicServer::Shutdown() {
    178   // Before we shut down the epoll server, give all active sessions a chance to
    179   // notify clients that they're closing.
    180   dispatcher_->Shutdown();
    181 
    182   close(fd_);
    183   fd_ = -1;
    184 }
    185 
    186 void QuicServer::OnEvent(int fd, EpollEvent* event) {
    187   DCHECK_EQ(fd, fd_);
    188   event->out_ready_mask = 0;
    189 
    190   if (event->in_events & EPOLLIN) {
    191     DVLOG(1) << "EPOLLIN";
    192     bool read = true;
    193     while (read) {
    194         read = ReadAndDispatchSinglePacket(
    195             fd_, port_, dispatcher_.get(),
    196             overflow_supported_ ? &packets_dropped_ : NULL);
    197     }
    198   }
    199   if (event->in_events & EPOLLOUT) {
    200     dispatcher_->OnCanWrite();
    201     if (dispatcher_->HasPendingWrites()) {
    202       event->out_ready_mask |= EPOLLOUT;
    203     }
    204   }
    205   if (event->in_events & EPOLLERR) {
    206   }
    207 }
    208 
    209 /* static */
    210 bool QuicServer::ReadAndDispatchSinglePacket(int fd,
    211                                              int port,
    212                                              ProcessPacketInterface* processor,
    213                                              uint32* packets_dropped) {
    214   // Allocate some extra space so we can send an error if the client goes over
    215   // the limit.
    216   char buf[2 * kMaxPacketSize];
    217 
    218   IPEndPoint client_address;
    219   IPAddressNumber server_ip;
    220   int bytes_read =
    221       QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf),
    222                                   packets_dropped,
    223                                   &server_ip, &client_address);
    224 
    225   if (bytes_read < 0) {
    226     return false;  // We failed to read.
    227   }
    228 
    229   QuicEncryptedPacket packet(buf, bytes_read, false);
    230 
    231   IPEndPoint server_address(server_ip, port);
    232   processor->ProcessPacket(server_address, client_address, packet);
    233 
    234   return true;
    235 }
    236 
    237 }  // namespace tools
    238 }  // namespace net
    239