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