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