2 * Copyright (c) 2014, Facebook, Inc.
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.
12 #include "folly/experimental/wangle/acceptor/ServerSocketConfig.h"
13 #include "folly/experimental/wangle/acceptor/ConnectionCounter.h"
14 #include <folly/experimental/wangle/ConnectionManager.h>
15 #include "folly/experimental/wangle/acceptor/LoadShedConfiguration.h"
16 #include "folly/experimental/wangle/ssl/SSLCacheProvider.h"
17 #include "folly/experimental/wangle/acceptor/TransportInfo.h"
21 #include <folly/io/async/AsyncSSLSocket.h>
22 #include <folly/io/async/AsyncServerSocket.h>
24 namespace folly { namespace wangle {
25 class ManagedConnection;
33 class SSLContextManager;
36 * An abstract acceptor for TCP-based network services.
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.
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.
48 public folly::AsyncServerSocket::AcceptCallback,
49 public folly::wangle::ConnectionManager::Callback {
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
59 explicit Acceptor(const ServerSocketConfig& accConfig);
63 * Supply an SSL cache provider
64 * @note Call this before init()
66 virtual void setSSLCacheProvider(
67 const std::shared_ptr<SSLCacheProvider>& cacheProvider) {
68 cacheProvider_ = cacheProvider;
72 * Initialize the Acceptor to run in the specified EventBase
73 * thread, receiving connections from the specified AsyncServerSocket.
75 * This method will be called from the AsyncServerSocket's primary thread,
76 * not the specified EventBase thread.
78 virtual void init(AsyncServerSocket* serverSocket,
79 EventBase* eventBase);
82 * Dynamically add a new SSLContextConfig
84 void addSSLContextConfig(const SSLContextConfig& sslCtxConfig);
86 SSLContextManager* getSSLContextManager() const {
87 return sslCtxManager_.get();
91 * Return the number of outstanding connections in this service instance.
93 uint32_t getNumConnections() const {
94 return downstreamConnectionManager_ ?
95 downstreamConnectionManager_->getNumConnections() : 0;
99 * Access the Acceptor's event base.
101 EventBase* getEventBase() { return base_; }
104 * Access the Acceptor's downstream (client-side) ConnectionManager
106 virtual folly::wangle::ConnectionManager* getConnectionManager() {
107 return downstreamConnectionManager_.get();
111 * Invoked when a new ManagedConnection is created.
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.
117 void addConnection(folly::wangle::ManagedConnection* connection);
120 * Get this acceptor's current state.
122 State getState() const {
127 * Get the current connection timeout.
129 std::chrono::milliseconds getConnTimeout() const;
132 * Returns the name of this VIP.
134 * Will return an empty string if no name has been configured.
136 const std::string& getName() const {
137 return accConfig_.name;
141 * Force the acceptor to drop all connections and stop processing.
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.
147 virtual void forceStop();
149 bool isSSL() const { return accConfig_.isSSL(); }
151 const ServerSocketConfig& getConfig() const { return accConfig_; }
153 static uint64_t getTotalNumPendingSSLConns() {
154 return totalNumPendingSSLConns_.load();
158 * Called right when the TCP connection has been accepted, before processing
159 * the first HTTP bytes (HTTP) or the SSL handshake (HTTPS)
161 virtual void onDoneAcceptingConnection(
163 const SocketAddress& clientAddr,
164 std::chrono::steady_clock::time_point acceptTime
168 * Begins either processing HTTP bytes (HTTP) or the SSL handshake (HTTPS)
170 void processEstablishedConnection(
172 const SocketAddress& clientAddr,
173 std::chrono::steady_clock::time_point acceptTime
177 friend class AcceptorHandshakeHelper;
182 * Probably needs to be used to pass to a ManagedConnection
183 * implementation. Also visible in case a subclass wishes to do additional
184 * things w/ the event loop (e.g. in attach()).
186 EventBase* base_{nullptr};
188 virtual uint64_t getConnectionCountForLoadShedding(void) const { return 0; }
191 * Hook for subclasses to drop newly accepted connections prior
194 virtual bool canAccept(const folly::SocketAddress&);
197 * Invoked when a new connection is created. This is where application starts
198 * processing a new downstream connection.
200 * NOTE: Application should add the new connection to
201 * downstreamConnectionManager so that it can be garbage collected after
202 * certain period of idleness.
204 * @param sock the socket connected to the client
205 * @param address the address of the client
206 * @param nextProtocolName the name of the L6 or L7 protocol to be
207 * spoken on the connection, if known (e.g.,
208 * from TLS NPN during secure connection setup),
209 * or an empty string if unknown
211 virtual void onNewConnection(
212 AsyncSocket::UniquePtr sock,
213 const folly::SocketAddress* address,
214 const std::string& nextProtocolName,
215 const TransportInfo& tinfo) = 0;
217 virtual AsyncSocket::UniquePtr makeNewAsyncSocket(EventBase* base, int fd) {
218 return AsyncSocket::UniquePtr(new AsyncSocket(base, fd));
221 virtual AsyncSSLSocket::UniquePtr makeNewAsyncSSLSocket(
222 const std::shared_ptr<SSLContext>& ctx, EventBase* base, int fd) {
223 return AsyncSSLSocket::UniquePtr(new AsyncSSLSocket(ctx, base, fd));
227 * Hook for subclasses to record stats about SSL connection establishment.
229 virtual void updateSSLStats(
230 const AsyncSSLSocket* sock,
231 std::chrono::milliseconds acceptLatency,
232 SSLErrorEnum error) noexcept {}
235 * Drop all connections.
237 * forceStop() schedules dropAllConnections() to be called in the acceptor's
240 void dropAllConnections();
243 * Drains all open connections of their outstanding transactions. When
244 * a connection's transaction count reaches zero, the connection closes.
246 void drainAllConnections();
249 * onConnectionsDrained() will be called once all connections have been
250 * drained while the acceptor is stopping.
252 * Subclasses can override this method to perform any subclass-specific
255 virtual void onConnectionsDrained() {}
257 // AsyncServerSocket::AcceptCallback methods
258 void connectionAccepted(int fd,
259 const folly::SocketAddress& clientAddr)
261 void acceptError(const std::exception& ex) noexcept;
262 void acceptStopped() noexcept;
264 // ConnectionManager::Callback methods
265 void onEmpty(const folly::wangle::ConnectionManager& cm);
266 void onConnectionAdded(const folly::wangle::ConnectionManager& cm) {}
267 void onConnectionRemoved(const folly::wangle::ConnectionManager& cm) {}
270 * Process a connection that is to ready to receive L7 traffic.
271 * This method is called immediately upon accept for plaintext
272 * connections and upon completion of SSL handshaking or resumption
273 * for SSL connections.
275 void connectionReady(
276 AsyncSocket::UniquePtr sock,
277 const folly::SocketAddress& clientAddr,
278 const std::string& nextProtocolName,
279 TransportInfo& tinfo);
281 const LoadShedConfiguration& getLoadShedConfiguration() const {
282 return loadShedConfig_;
286 const ServerSocketConfig accConfig_;
287 void setLoadShedConfig(const LoadShedConfiguration& from,
288 IConnectionCounter* counter);
291 * Socket options to apply to the client socket
293 AsyncSocket::OptionMap socketOptions_;
295 std::unique_ptr<SSLContextManager> sslCtxManager_;
298 * Whether we want to enable client hello parsing in the handshake helper
299 * to get list of supported client ciphers.
301 bool parseClientHello_{false};
303 folly::wangle::ConnectionManager::UniquePtr downstreamConnectionManager_;
307 // Forbidden copy constructor and assignment opererator
308 Acceptor(Acceptor const &) = delete;
309 Acceptor& operator=(Acceptor const &) = delete;
312 * Wrapper for connectionReady() that decrements the count of
313 * pending SSL connections.
315 void sslConnectionReady(AsyncSocket::UniquePtr sock,
316 const folly::SocketAddress& clientAddr,
317 const std::string& nextProtocol,
318 TransportInfo& tinfo);
321 * Notification callback for SSL handshake failures.
323 void sslConnectionError();
327 State state_{State::kInit};
328 uint64_t numPendingSSLConns_{0};
330 static std::atomic<uint64_t> totalNumPendingSSLConns_;
332 bool forceShutdownInProgress_{false};
333 LoadShedConfiguration loadShedConfig_;
334 IConnectionCounter* connectionCounter_{nullptr};
335 std::shared_ptr<SSLCacheProvider> cacheProvider_;