23d8ee022e180aafe99b77fc1fde8567e5c5f37b
[folly.git] / folly / wangle / acceptor / Acceptor.h
1 /*
2  *  Copyright (c) 2014, Facebook, Inc.
3  *  All rights reserved.
4  *
5  *  This source code is licensed under the BSD-style license found in the
6  *  LICENSE file in the root directory of this source tree. An additional grant
7  *  of patent rights can be found in the PATENTS file in the same directory.
8  *
9  */
10 #pragma once
11
12 #include <folly/wangle/acceptor/ServerSocketConfig.h>
13 #include <folly/wangle/acceptor/ConnectionCounter.h>
14 #include <folly/wangle/acceptor/ConnectionManager.h>
15 #include <folly/wangle/acceptor/LoadShedConfiguration.h>
16 #include <folly/wangle/ssl/SSLCacheProvider.h>
17 #include <folly/wangle/acceptor/TransportInfo.h>
18
19 #include <chrono>
20 #include <event.h>
21 #include <folly/io/async/AsyncSSLSocket.h>
22 #include <folly/io/async/AsyncServerSocket.h>
23
24 namespace folly { namespace wangle {
25 class ManagedConnection;
26 }}
27
28 namespace folly {
29
30 class SocketAddress;
31 class SSLContext;
32 class AsyncTransport;
33 class SSLContextManager;
34
35 /**
36  * An abstract acceptor for TCP-based network services.
37  *
38  * There is one acceptor object per thread for each listening socket.  When a
39  * new connection arrives on the listening socket, it is accepted by one of the
40  * acceptor objects.  From that point on the connection will be processed by
41  * that acceptor's thread.
42  *
43  * The acceptor will call the abstract onNewConnection() method to create
44  * a new ManagedConnection object for each accepted socket.  The acceptor
45  * also tracks all outstanding connections that it has accepted.
46  */
47 class Acceptor :
48   public folly::AsyncServerSocket::AcceptCallback,
49   public folly::wangle::ConnectionManager::Callback {
50  public:
51
52   enum class State : uint32_t {
53     kInit,  // not yet started
54     kRunning, // processing requests normally
55     kDraining, // processing outstanding conns, but not accepting new ones
56     kDone,  // no longer accepting, and all connections finished
57   };
58
59   explicit Acceptor(const ServerSocketConfig& accConfig);
60   virtual ~Acceptor();
61
62   /**
63    * Supply an SSL cache provider
64    * @note Call this before init()
65    */
66   virtual void setSSLCacheProvider(
67       const std::shared_ptr<SSLCacheProvider>& cacheProvider) {
68     cacheProvider_ = cacheProvider;
69   }
70
71   /**
72    * Initialize the Acceptor to run in the specified EventBase
73    * thread, receiving connections from the specified AsyncServerSocket.
74    *
75    * This method will be called from the AsyncServerSocket's primary thread,
76    * not the specified EventBase thread.
77    */
78   virtual void init(AsyncServerSocket* serverSocket,
79                     EventBase* eventBase);
80
81   /**
82    * Dynamically add a new SSLContextConfig
83    */
84   void addSSLContextConfig(const SSLContextConfig& sslCtxConfig);
85
86   SSLContextManager* getSSLContextManager() const {
87     return sslCtxManager_.get();
88   }
89
90   /**
91    * Return the number of outstanding connections in this service instance.
92    */
93   uint32_t getNumConnections() const {
94     return downstreamConnectionManager_ ?
95         downstreamConnectionManager_->getNumConnections() : 0;
96   }
97
98   /**
99    * Access the Acceptor's event base.
100    */
101   virtual EventBase* getEventBase() const { return base_; }
102
103   /**
104    * Access the Acceptor's downstream (client-side) ConnectionManager
105    */
106   virtual folly::wangle::ConnectionManager* getConnectionManager() {
107     return downstreamConnectionManager_.get();
108   }
109
110   /**
111    * Invoked when a new ManagedConnection is created.
112    *
113    * This allows the Acceptor to track the outstanding connections,
114    * for tracking timeouts and for ensuring that all connections have been
115    * drained on shutdown.
116    */
117   void addConnection(folly::wangle::ManagedConnection* connection);
118
119   /**
120    * Get this acceptor's current state.
121    */
122   State getState() const {
123     return state_;
124   }
125
126   /**
127    * Get the current connection timeout.
128    */
129   std::chrono::milliseconds getConnTimeout() const;
130
131   /**
132    * Returns the name of this VIP.
133    *
134    * Will return an empty string if no name has been configured.
135    */
136   const std::string& getName() const {
137     return accConfig_.name;
138   }
139
140   /**
141    * Force the acceptor to drop all connections and stop processing.
142    *
143    * This function may be called from any thread.  The acceptor will not
144    * necessarily stop before this function returns: the stop will be scheduled
145    * to run in the acceptor's thread.
146    */
147   virtual void forceStop();
148
149   bool isSSL() const { return accConfig_.isSSL(); }
150
151   const ServerSocketConfig& getConfig() const { return accConfig_; }
152
153   static uint64_t getTotalNumPendingSSLConns() {
154     return totalNumPendingSSLConns_.load();
155   }
156
157   /**
158    * Called right when the TCP connection has been accepted, before processing
159    * the first HTTP bytes (HTTP) or the SSL handshake (HTTPS)
160    */
161   virtual void onDoneAcceptingConnection(
162     int fd,
163     const SocketAddress& clientAddr,
164     std::chrono::steady_clock::time_point acceptTime
165   ) noexcept;
166
167   /**
168    * Begins either processing HTTP bytes (HTTP) or the SSL handshake (HTTPS)
169    */
170   void processEstablishedConnection(
171     int fd,
172     const SocketAddress& clientAddr,
173     std::chrono::steady_clock::time_point acceptTime
174   ) noexcept;
175
176   /**
177    * Drains all open connections of their outstanding transactions. When
178    * a connection's transaction count reaches zero, the connection closes.
179    */
180   void drainAllConnections();
181
182  protected:
183   friend class AcceptorHandshakeHelper;
184
185   /**
186    * Our event loop.
187    *
188    * Probably needs to be used to pass to a ManagedConnection
189    * implementation. Also visible in case a subclass wishes to do additional
190    * things w/ the event loop (e.g. in attach()).
191    */
192   EventBase* base_{nullptr};
193
194   virtual uint64_t getConnectionCountForLoadShedding(void) const { return 0; }
195
196   /**
197    * Hook for subclasses to drop newly accepted connections prior
198    * to handshaking.
199    */
200   virtual bool canAccept(const folly::SocketAddress&);
201
202   /**
203    * Invoked when a new connection is created. This is where application starts
204    * processing a new downstream connection.
205    *
206    * NOTE: Application should add the new connection to
207    *       downstreamConnectionManager so that it can be garbage collected after
208    *       certain period of idleness.
209    *
210    * @param sock              the socket connected to the client
211    * @param address           the address of the client
212    * @param nextProtocolName  the name of the L6 or L7 protocol to be
213    *                            spoken on the connection, if known (e.g.,
214    *                            from TLS NPN during secure connection setup),
215    *                            or an empty string if unknown
216    */
217   virtual void onNewConnection(
218       AsyncSocket::UniquePtr sock,
219       const folly::SocketAddress* address,
220       const std::string& nextProtocolName,
221       const TransportInfo& tinfo) = 0;
222
223   virtual AsyncSocket::UniquePtr makeNewAsyncSocket(EventBase* base, int fd) {
224     return AsyncSocket::UniquePtr(new AsyncSocket(base, fd));
225   }
226
227   virtual AsyncSSLSocket::UniquePtr makeNewAsyncSSLSocket(
228     const std::shared_ptr<SSLContext>& ctx, EventBase* base, int fd) {
229     return AsyncSSLSocket::UniquePtr(new AsyncSSLSocket(ctx, base, fd));
230   }
231
232   /**
233    * Hook for subclasses to record stats about SSL connection establishment.
234    */
235   virtual void updateSSLStats(
236       const AsyncSSLSocket* sock,
237       std::chrono::milliseconds acceptLatency,
238       SSLErrorEnum error) noexcept {}
239
240   /**
241    * Drop all connections.
242    *
243    * forceStop() schedules dropAllConnections() to be called in the acceptor's
244    * thread.
245    */
246   void dropAllConnections();
247
248  protected:
249
250   /**
251    * onConnectionsDrained() will be called once all connections have been
252    * drained while the acceptor is stopping.
253    *
254    * Subclasses can override this method to perform any subclass-specific
255    * cleanup.
256    */
257   virtual void onConnectionsDrained() {}
258
259   // AsyncServerSocket::AcceptCallback methods
260   void connectionAccepted(int fd,
261       const folly::SocketAddress& clientAddr)
262       noexcept;
263   void acceptError(const std::exception& ex) noexcept;
264   void acceptStopped() noexcept;
265
266   // ConnectionManager::Callback methods
267   void onEmpty(const folly::wangle::ConnectionManager& cm);
268   void onConnectionAdded(const folly::wangle::ConnectionManager& cm) {}
269   void onConnectionRemoved(const folly::wangle::ConnectionManager& cm) {}
270
271   /**
272    * Process a connection that is to ready to receive L7 traffic.
273    * This method is called immediately upon accept for plaintext
274    * connections and upon completion of SSL handshaking or resumption
275    * for SSL connections.
276    */
277    void connectionReady(
278       AsyncSocket::UniquePtr sock,
279       const folly::SocketAddress& clientAddr,
280       const std::string& nextProtocolName,
281       TransportInfo& tinfo);
282
283   const LoadShedConfiguration& getLoadShedConfiguration() const {
284     return loadShedConfig_;
285   }
286
287  protected:
288   const ServerSocketConfig accConfig_;
289   void setLoadShedConfig(const LoadShedConfiguration& from,
290                          IConnectionCounter* counter);
291
292   /**
293    * Socket options to apply to the client socket
294    */
295   AsyncSocket::OptionMap socketOptions_;
296
297   std::unique_ptr<SSLContextManager> sslCtxManager_;
298
299   /**
300    * Whether we want to enable client hello parsing in the handshake helper
301    * to get list of supported client ciphers.
302    */
303   bool parseClientHello_{false};
304
305   folly::wangle::ConnectionManager::UniquePtr downstreamConnectionManager_;
306
307  private:
308
309   // Forbidden copy constructor and assignment opererator
310   Acceptor(Acceptor const &) = delete;
311   Acceptor& operator=(Acceptor const &) = delete;
312
313   /**
314    * Wrapper for connectionReady() that decrements the count of
315    * pending SSL connections.
316    */
317   void sslConnectionReady(AsyncSocket::UniquePtr sock,
318       const folly::SocketAddress& clientAddr,
319       const std::string& nextProtocol,
320       TransportInfo& tinfo);
321
322   /**
323    * Notification callback for SSL handshake failures.
324    */
325   void sslConnectionError();
326
327   void checkDrained();
328
329   State state_{State::kInit};
330   uint64_t numPendingSSLConns_{0};
331
332   static std::atomic<uint64_t> totalNumPendingSSLConns_;
333
334   bool forceShutdownInProgress_{false};
335   LoadShedConfiguration loadShedConfig_;
336   IConnectionCounter* connectionCounter_{nullptr};
337   std::shared_ptr<SSLCacheProvider> cacheProvider_;
338 };
339
340 class AcceptorFactory {
341  public:
342   virtual std::shared_ptr<Acceptor> newAcceptor() = 0;
343   virtual ~AcceptorFactory() = default;
344 };
345
346 } // namespace