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