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