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