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