| 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/flip_server/acceptor_thread.h" | |
| 6 | |
| 7 #include <errno.h> | |
| 8 #include <netinet/in.h> | |
| 9 #include <string.h> // For strerror | |
| 10 #include <sys/socket.h> | |
| 11 #include <sys/types.h> | |
| 12 | |
| 13 #include <string> | |
| 14 | |
| 15 #include "net/socket/tcp_socket.h" | |
| 16 #include "net/tools/flip_server/constants.h" | |
| 17 #include "net/tools/flip_server/flip_config.h" | |
| 18 #include "net/tools/flip_server/sm_connection.h" | |
| 19 #include "net/tools/flip_server/spdy_ssl.h" | |
| 20 #include "openssl/err.h" | |
| 21 #include "openssl/ssl.h" | |
| 22 | |
| 23 namespace net { | |
| 24 | |
| 25 SMAcceptorThread::SMAcceptorThread(FlipAcceptor* acceptor, | |
| 26 MemoryCache* memory_cache) | |
| 27 : SimpleThread("SMAcceptorThread"), | |
| 28 acceptor_(acceptor), | |
| 29 ssl_state_(NULL), | |
| 30 use_ssl_(false), | |
| 31 idle_socket_timeout_s_(acceptor->idle_socket_timeout_s_), | |
| 32 quitting_(false), | |
| 33 memory_cache_(memory_cache) { | |
| 34 if (!acceptor->ssl_cert_filename_.empty() && | |
| 35 !acceptor->ssl_key_filename_.empty()) { | |
| 36 ssl_state_ = new SSLState; | |
| 37 bool use_npn = true; | |
| 38 if (acceptor_->flip_handler_type_ == FLIP_HANDLER_HTTP_SERVER) { | |
| 39 use_npn = false; | |
| 40 } | |
| 41 InitSSL(ssl_state_, | |
| 42 acceptor_->ssl_cert_filename_, | |
| 43 acceptor_->ssl_key_filename_, | |
| 44 use_npn, | |
| 45 acceptor_->ssl_session_expiry_, | |
| 46 acceptor_->ssl_disable_compression_); | |
| 47 use_ssl_ = true; | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 SMAcceptorThread::~SMAcceptorThread() { | |
| 52 for (std::vector<SMConnection*>::iterator i = | |
| 53 allocated_server_connections_.begin(); | |
| 54 i != allocated_server_connections_.end(); | |
| 55 ++i) { | |
| 56 delete *i; | |
| 57 } | |
| 58 delete ssl_state_; | |
| 59 } | |
| 60 | |
| 61 SMConnection* SMAcceptorThread::NewConnection() { | |
| 62 SMConnection* server = SMConnection::NewSMConnection( | |
| 63 &epoll_server_, ssl_state_, memory_cache_, acceptor_, "client_conn: "); | |
| 64 allocated_server_connections_.push_back(server); | |
| 65 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Making new server."; | |
| 66 return server; | |
| 67 } | |
| 68 | |
| 69 SMConnection* SMAcceptorThread::FindOrMakeNewSMConnection() { | |
| 70 if (unused_server_connections_.empty()) { | |
| 71 return NewConnection(); | |
| 72 } | |
| 73 SMConnection* server = unused_server_connections_.back(); | |
| 74 unused_server_connections_.pop_back(); | |
| 75 VLOG(2) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Reusing server."; | |
| 76 return server; | |
| 77 } | |
| 78 | |
| 79 void SMAcceptorThread::InitWorker() { | |
| 80 epoll_server_.RegisterFD(acceptor_->listen_fd_, this, EPOLLIN | EPOLLET); | |
| 81 } | |
| 82 | |
| 83 void SMAcceptorThread::HandleConnection(int server_fd, | |
| 84 struct sockaddr_in* remote_addr) { | |
| 85 if (acceptor_->disable_nagle_) { | |
| 86 if (!SetTCPNoDelay(server_fd, /*no_delay=*/true)) { | |
| 87 close(server_fd); | |
| 88 LOG(FATAL) << "SetTCPNoDelay() failed on fd: " << server_fd; | |
| 89 return; | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 SMConnection* server_connection = FindOrMakeNewSMConnection(); | |
| 94 if (server_connection == NULL) { | |
| 95 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Acceptor: Closing fd " << server_fd; | |
| 96 close(server_fd); | |
| 97 return; | |
| 98 } | |
| 99 std::string remote_ip = inet_ntoa(remote_addr->sin_addr); | |
| 100 server_connection->InitSMConnection(this, | |
| 101 NULL, | |
| 102 &epoll_server_, | |
| 103 server_fd, | |
| 104 std::string(), | |
| 105 std::string(), | |
| 106 remote_ip, | |
| 107 use_ssl_); | |
| 108 if (server_connection->initialized()) | |
| 109 active_server_connections_.push_back(server_connection); | |
| 110 } | |
| 111 | |
| 112 void SMAcceptorThread::AcceptFromListenFD() { | |
| 113 if (acceptor_->accepts_per_wake_ > 0) { | |
| 114 for (int i = 0; i < acceptor_->accepts_per_wake_; ++i) { | |
| 115 struct sockaddr address; | |
| 116 socklen_t socklen = sizeof(address); | |
| 117 int fd = accept(acceptor_->listen_fd_, &address, &socklen); | |
| 118 if (fd == -1) { | |
| 119 if (errno != 11) { | |
| 120 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Acceptor: accept fail(" | |
| 121 << acceptor_->listen_fd_ << "): " << errno << ": " | |
| 122 << strerror(errno); | |
| 123 } | |
| 124 break; | |
| 125 } | |
| 126 VLOG(1) << ACCEPTOR_CLIENT_IDENT << " Accepted connection"; | |
| 127 HandleConnection(fd, (struct sockaddr_in*)&address); | |
| 128 } | |
| 129 } else { | |
| 130 while (true) { | |
| 131 struct sockaddr address; | |
| 132 socklen_t socklen = sizeof(address); | |
| 133 int fd = accept(acceptor_->listen_fd_, &address, &socklen); | |
| 134 if (fd == -1) { | |
| 135 if (errno != 11) { | |
| 136 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Acceptor: accept fail(" | |
| 137 << acceptor_->listen_fd_ << "): " << errno << ": " | |
| 138 << strerror(errno); | |
| 139 } | |
| 140 break; | |
| 141 } | |
| 142 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Accepted connection"; | |
| 143 HandleConnection(fd, (struct sockaddr_in*)&address); | |
| 144 } | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 void SMAcceptorThread::HandleConnectionIdleTimeout() { | |
| 149 static time_t oldest_time = time(NULL); | |
| 150 | |
| 151 int cur_time = time(NULL); | |
| 152 // Only iterate the list if we speculate that a connection is ready to be | |
| 153 // expired | |
| 154 if ((cur_time - oldest_time) < idle_socket_timeout_s_) | |
| 155 return; | |
| 156 | |
| 157 // TODO(mbelshe): This code could be optimized, active_server_connections_ | |
| 158 // is already in-order. | |
| 159 std::list<SMConnection*>::iterator iter = active_server_connections_.begin(); | |
| 160 while (iter != active_server_connections_.end()) { | |
| 161 SMConnection* conn = *iter; | |
| 162 int elapsed_time = (cur_time - conn->last_read_time_); | |
| 163 if (elapsed_time > idle_socket_timeout_s_) { | |
| 164 conn->Cleanup("Connection idle timeout reached."); | |
| 165 iter = active_server_connections_.erase(iter); | |
| 166 continue; | |
| 167 } | |
| 168 if (conn->last_read_time_ < oldest_time) | |
| 169 oldest_time = conn->last_read_time_; | |
| 170 iter++; | |
| 171 } | |
| 172 if ((cur_time - oldest_time) >= idle_socket_timeout_s_) | |
| 173 oldest_time = cur_time; | |
| 174 } | |
| 175 | |
| 176 void SMAcceptorThread::Run() { | |
| 177 while (!quitting_.HasBeenNotified()) { | |
| 178 epoll_server_.set_timeout_in_us(10 * 1000); // 10 ms | |
| 179 epoll_server_.WaitForEventsAndExecuteCallbacks(); | |
| 180 if (tmp_unused_server_connections_.size()) { | |
| 181 VLOG(2) << "have " << tmp_unused_server_connections_.size() | |
| 182 << " additional unused connections. Total = " | |
| 183 << unused_server_connections_.size(); | |
| 184 unused_server_connections_.insert(unused_server_connections_.end(), | |
| 185 tmp_unused_server_connections_.begin(), | |
| 186 tmp_unused_server_connections_.end()); | |
| 187 tmp_unused_server_connections_.clear(); | |
| 188 } | |
| 189 HandleConnectionIdleTimeout(); | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 void SMAcceptorThread::OnEvent(int fd, EpollEvent* event) { | |
| 194 if (event->in_events | EPOLLIN) { | |
| 195 VLOG(2) << ACCEPTOR_CLIENT_IDENT | |
| 196 << "Acceptor: Accepting based upon epoll events"; | |
| 197 AcceptFromListenFD(); | |
| 198 } | |
| 199 } | |
| 200 | |
| 201 void SMAcceptorThread::SMConnectionDone(SMConnection* sc) { | |
| 202 VLOG(1) << ACCEPTOR_CLIENT_IDENT << "Done with connection."; | |
| 203 tmp_unused_server_connections_.push_back(sc); | |
| 204 } | |
| 205 | |
| 206 } // namespace net | |
| OLD | NEW |