| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/tools/quic/quic_server.h" | 5 #include "net/tools/quic/quic_server.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <features.h> | 8 #include <features.h> |
| 9 #include <netinet/in.h> | 9 #include <netinet/in.h> |
| 10 #include <string.h> | 10 #include <string.h> |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 #if MMSG_MORE | 70 #if MMSG_MORE |
| 71 use_recvmmsg_ = true; | 71 use_recvmmsg_ = true; |
| 72 #endif | 72 #endif |
| 73 epoll_server_.set_timeout_in_us(50 * 1000); | 73 epoll_server_.set_timeout_in_us(50 * 1000); |
| 74 // Initialize the in memory cache now. | 74 // Initialize the in memory cache now. |
| 75 QuicInMemoryCache::GetInstance(); | 75 QuicInMemoryCache::GetInstance(); |
| 76 | 76 |
| 77 QuicEpollClock clock(&epoll_server_); | 77 QuicEpollClock clock(&epoll_server_); |
| 78 | 78 |
| 79 scoped_ptr<CryptoHandshakeMessage> scfg( | 79 scoped_ptr<CryptoHandshakeMessage> scfg( |
| 80 crypto_config_.AddDefaultConfig( | 80 crypto_config_.AddDefaultConfig(QuicRandom::GetInstance(), |
| 81 QuicRandom::GetInstance(), &clock, | 81 &clock, |
| 82 QuicCryptoServerConfig::ConfigOptions())); | 82 QuicCryptoServerConfig::ConfigOptions())); |
| 83 } | 83 } |
| 84 | 84 |
| 85 QuicServer::~QuicServer() { | 85 QuicServer::~QuicServer() { |
| 86 } | 86 } |
| 87 | 87 |
| 88 bool QuicServer::Listen(const IPEndPoint& address) { | 88 bool QuicServer::Listen(const IPEndPoint& address) { |
| 89 port_ = address.port(); | 89 port_ = address.port(); |
| 90 int address_family = address.GetSockAddrFamily(); | 90 int address_family = address.GetSockAddrFamily(); |
| 91 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); | 91 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); |
| 92 if (fd_ < 0) { | 92 if (fd_ < 0) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 120 } | 120 } |
| 121 | 121 |
| 122 if (!QuicSocketUtils::SetSendBufferSize(fd_, | 122 if (!QuicSocketUtils::SetSendBufferSize(fd_, |
| 123 TcpReceiver::kReceiveWindowTCP)) { | 123 TcpReceiver::kReceiveWindowTCP)) { |
| 124 return false; | 124 return false; |
| 125 } | 125 } |
| 126 | 126 |
| 127 // Enable the socket option that allows the local address to be | 127 // Enable the socket option that allows the local address to be |
| 128 // returned if the socket is bound to more than on address. | 128 // returned if the socket is bound to more than on address. |
| 129 int get_local_ip = 1; | 129 int get_local_ip = 1; |
| 130 rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO, | 130 rc = setsockopt( |
| 131 &get_local_ip, sizeof(get_local_ip)); | 131 fd_, IPPROTO_IP, IP_PKTINFO, &get_local_ip, sizeof(get_local_ip)); |
| 132 if (rc == 0 && address_family == AF_INET6) { | 132 if (rc == 0 && address_family == AF_INET6) { |
| 133 rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO, | 133 rc = setsockopt(fd_, |
| 134 &get_local_ip, sizeof(get_local_ip)); | 134 IPPROTO_IPV6, |
| 135 IPV6_RECVPKTINFO, |
| 136 &get_local_ip, |
| 137 sizeof(get_local_ip)); |
| 135 } | 138 } |
| 136 if (rc != 0) { | 139 if (rc != 0) { |
| 137 LOG(ERROR) << "Failed to set required socket options"; | 140 LOG(ERROR) << "Failed to set required socket options"; |
| 138 return false; | 141 return false; |
| 139 } | 142 } |
| 140 | 143 |
| 141 sockaddr_storage raw_addr; | 144 sockaddr_storage raw_addr; |
| 142 socklen_t raw_addr_len = sizeof(raw_addr); | 145 socklen_t raw_addr_len = sizeof(raw_addr); |
| 143 CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), | 146 CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), |
| 144 &raw_addr_len)); | 147 &raw_addr_len)); |
| 145 rc = bind(fd_, | 148 rc = |
| 146 reinterpret_cast<const sockaddr*>(&raw_addr), | 149 bind(fd_, reinterpret_cast<const sockaddr*>(&raw_addr), sizeof(raw_addr)); |
| 147 sizeof(raw_addr)); | |
| 148 if (rc < 0) { | 150 if (rc < 0) { |
| 149 LOG(ERROR) << "Bind failed: " << strerror(errno); | 151 LOG(ERROR) << "Bind failed: " << strerror(errno); |
| 150 return false; | 152 return false; |
| 151 } | 153 } |
| 152 | 154 |
| 153 DVLOG(1) << "Listening on " << address.ToString(); | 155 DVLOG(1) << "Listening on " << address.ToString(); |
| 154 if (port_ == 0) { | 156 if (port_ == 0) { |
| 155 SockaddrStorage storage; | 157 SockaddrStorage storage; |
| 156 IPEndPoint server_address; | 158 IPEndPoint server_address; |
| 157 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || | 159 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || |
| 158 !server_address.FromSockAddr(storage.addr, storage.addr_len)) { | 160 !server_address.FromSockAddr(storage.addr, storage.addr_len)) { |
| 159 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); | 161 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); |
| 160 return false; | 162 return false; |
| 161 } | 163 } |
| 162 port_ = server_address.port(); | 164 port_ = server_address.port(); |
| 163 DVLOG(1) << "Kernel assigned port is " << port_; | 165 DVLOG(1) << "Kernel assigned port is " << port_; |
| 164 } | 166 } |
| 165 | 167 |
| 166 epoll_server_.RegisterFD(fd_, this, kEpollFlags); | 168 epoll_server_.RegisterFD(fd_, this, kEpollFlags); |
| 167 dispatcher_.reset(new QuicDispatcher( | 169 dispatcher_.reset( |
| 168 config_, | 170 new QuicDispatcher(config_, |
| 169 crypto_config_, | 171 crypto_config_, |
| 170 supported_versions_, | 172 supported_versions_, |
| 171 &epoll_server_, | 173 &epoll_server_, |
| 172 server_initial_flow_control_receive_window_)); | 174 server_initial_flow_control_receive_window_)); |
| 173 dispatcher_->Initialize(fd_); | 175 dispatcher_->Initialize(fd_); |
| 174 | 176 |
| 175 return true; | 177 return true; |
| 176 } | 178 } |
| 177 | 179 |
| 178 void QuicServer::WaitForEvents() { | 180 void QuicServer::WaitForEvents() { |
| 179 epoll_server_.WaitForEventsAndExecuteCallbacks(); | 181 epoll_server_.WaitForEventsAndExecuteCallbacks(); |
| 180 } | 182 } |
| 181 | 183 |
| 182 void QuicServer::Shutdown() { | 184 void QuicServer::Shutdown() { |
| 183 // Before we shut down the epoll server, give all active sessions a chance to | 185 // Before we shut down the epoll server, give all active sessions a chance to |
| 184 // notify clients that they're closing. | 186 // notify clients that they're closing. |
| 185 dispatcher_->Shutdown(); | 187 dispatcher_->Shutdown(); |
| 186 | 188 |
| 187 close(fd_); | 189 close(fd_); |
| 188 fd_ = -1; | 190 fd_ = -1; |
| 189 } | 191 } |
| 190 | 192 |
| 191 void QuicServer::OnEvent(int fd, EpollEvent* event) { | 193 void QuicServer::OnEvent(int fd, EpollEvent* event) { |
| 192 DCHECK_EQ(fd, fd_); | 194 DCHECK_EQ(fd, fd_); |
| 193 event->out_ready_mask = 0; | 195 event->out_ready_mask = 0; |
| 194 | 196 |
| 195 if (event->in_events & EPOLLIN) { | 197 if (event->in_events & EPOLLIN) { |
| 196 DVLOG(1) << "EPOLLIN"; | 198 DVLOG(1) << "EPOLLIN"; |
| 197 bool read = true; | 199 bool read = true; |
| 198 while (read) { | 200 while (read) { |
| 199 read = ReadAndDispatchSinglePacket( | 201 read = ReadAndDispatchSinglePacket( |
| 200 fd_, port_, dispatcher_.get(), | 202 fd_, |
| 201 overflow_supported_ ? &packets_dropped_ : NULL); | 203 port_, |
| 204 dispatcher_.get(), |
| 205 overflow_supported_ ? &packets_dropped_ : NULL); |
| 202 } | 206 } |
| 203 } | 207 } |
| 204 if (event->in_events & EPOLLOUT) { | 208 if (event->in_events & EPOLLOUT) { |
| 205 dispatcher_->OnCanWrite(); | 209 dispatcher_->OnCanWrite(); |
| 206 if (dispatcher_->HasPendingWrites()) { | 210 if (dispatcher_->HasPendingWrites()) { |
| 207 event->out_ready_mask |= EPOLLOUT; | 211 event->out_ready_mask |= EPOLLOUT; |
| 208 } | 212 } |
| 209 } | 213 } |
| 210 if (event->in_events & EPOLLERR) { | 214 if (event->in_events & EPOLLERR) { |
| 211 } | 215 } |
| 212 } | 216 } |
| 213 | 217 |
| 214 /* static */ | 218 /* static */ |
| 215 bool QuicServer::ReadAndDispatchSinglePacket(int fd, | 219 bool QuicServer::ReadAndDispatchSinglePacket(int fd, |
| 216 int port, | 220 int port, |
| 217 QuicDispatcher* dispatcher, | 221 QuicDispatcher* dispatcher, |
| 218 uint32* packets_dropped) { | 222 uint32* packets_dropped) { |
| 219 // Allocate some extra space so we can send an error if the client goes over | 223 // Allocate some extra space so we can send an error if the client goes over |
| 220 // the limit. | 224 // the limit. |
| 221 char buf[2 * kMaxPacketSize]; | 225 char buf[2 * kMaxPacketSize]; |
| 222 | 226 |
| 223 IPEndPoint client_address; | 227 IPEndPoint client_address; |
| 224 IPAddressNumber server_ip; | 228 IPAddressNumber server_ip; |
| 225 int bytes_read = | 229 int bytes_read = QuicSocketUtils::ReadPacket( |
| 226 QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), | 230 fd, buf, arraysize(buf), packets_dropped, &server_ip, &client_address); |
| 227 packets_dropped, | |
| 228 &server_ip, &client_address); | |
| 229 | 231 |
| 230 if (bytes_read < 0) { | 232 if (bytes_read < 0) { |
| 231 return false; // We failed to read. | 233 return false; // We failed to read. |
| 232 } | 234 } |
| 233 | 235 |
| 234 QuicEncryptedPacket packet(buf, bytes_read, false); | 236 QuicEncryptedPacket packet(buf, bytes_read, false); |
| 235 | 237 |
| 236 IPEndPoint server_address(server_ip, port); | 238 IPEndPoint server_address(server_ip, port); |
| 237 dispatcher->ProcessPacket(server_address, client_address, packet); | 239 dispatcher->ProcessPacket(server_address, client_address, packet); |
| 238 | 240 |
| 239 return true; | 241 return true; |
| 240 } | 242 } |
| 241 | 243 |
| 242 } // namespace tools | 244 } // namespace tools |
| 243 } // namespace net | 245 } // namespace net |
| OLD | NEW |