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/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>
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 virtual EventBase* getEventBase() const { 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,
178 * Drains all open connections of their outstanding transactions. When
179 * a connection's transaction count reaches zero, the connection closes.
181 void drainAllConnections();
184 * Drop all connections.
186 * forceStop() schedules dropAllConnections() to be called in the acceptor's
189 void dropAllConnections();
192 friend class AcceptorHandshakeHelper;
197 * Probably needs to be used to pass to a ManagedConnection
198 * implementation. Also visible in case a subclass wishes to do additional
199 * things w/ the event loop (e.g. in attach()).
201 EventBase* base_{nullptr};
203 virtual uint64_t getConnectionCountForLoadShedding(void) const { return 0; }
206 * Hook for subclasses to drop newly accepted connections prior
209 virtual bool canAccept(const folly::SocketAddress&);
212 * Invoked when a new connection is created. This is where application starts
213 * processing a new downstream connection.
215 * NOTE: Application should add the new connection to
216 * downstreamConnectionManager so that it can be garbage collected after
217 * certain period of idleness.
219 * @param sock the socket connected to the client
220 * @param address the address of the client
221 * @param nextProtocolName the name of the L6 or L7 protocol to be
222 * spoken on the connection, if known (e.g.,
223 * from TLS NPN during secure connection setup),
224 * or an empty string if unknown
226 virtual void onNewConnection(
227 AsyncSocket::UniquePtr sock,
228 const folly::SocketAddress* address,
229 const std::string& nextProtocolName,
230 const TransportInfo& tinfo) = 0;
232 virtual AsyncSocket::UniquePtr makeNewAsyncSocket(EventBase* base, int fd) {
233 return AsyncSocket::UniquePtr(new AsyncSocket(base, fd));
236 virtual AsyncSSLSocket::UniquePtr makeNewAsyncSSLSocket(
237 const std::shared_ptr<SSLContext>& ctx, EventBase* base, int fd) {
238 return AsyncSSLSocket::UniquePtr(new AsyncSSLSocket(ctx, base, fd));
242 * Hook for subclasses to record stats about SSL connection establishment.
244 virtual void updateSSLStats(
245 const AsyncSSLSocket* sock,
246 std::chrono::milliseconds acceptLatency,
247 SSLErrorEnum error) noexcept {}
252 * onConnectionsDrained() will be called once all connections have been
253 * drained while the acceptor is stopping.
255 * Subclasses can override this method to perform any subclass-specific
258 virtual void onConnectionsDrained() {}
260 // AsyncServerSocket::AcceptCallback methods
261 void connectionAccepted(int fd,
262 const folly::SocketAddress& clientAddr)
264 void acceptError(const std::exception& ex) noexcept;
265 void acceptStopped() noexcept;
267 // ConnectionManager::Callback methods
268 void onEmpty(const folly::wangle::ConnectionManager& cm);
269 void onConnectionAdded(const folly::wangle::ConnectionManager& cm) {}
270 void onConnectionRemoved(const folly::wangle::ConnectionManager& cm) {}
273 * Process a connection that is to ready to receive L7 traffic.
274 * This method is called immediately upon accept for plaintext
275 * connections and upon completion of SSL handshaking or resumption
276 * for SSL connections.
278 void connectionReady(
279 AsyncSocket::UniquePtr sock,
280 const folly::SocketAddress& clientAddr,
281 const std::string& nextProtocolName,
282 TransportInfo& tinfo);
284 const LoadShedConfiguration& getLoadShedConfiguration() const {
285 return loadShedConfig_;
289 const ServerSocketConfig accConfig_;
290 void setLoadShedConfig(const LoadShedConfiguration& from,
291 IConnectionCounter* counter);
294 * Socket options to apply to the client socket
296 AsyncSocket::OptionMap socketOptions_;
298 std::unique_ptr<SSLContextManager> sslCtxManager_;
301 * Whether we want to enable client hello parsing in the handshake helper
302 * to get list of supported client ciphers.
304 bool parseClientHello_{false};
306 folly::wangle::ConnectionManager::UniquePtr downstreamConnectionManager_;
310 // Forbidden copy constructor and assignment opererator
311 Acceptor(Acceptor const &) = delete;
312 Acceptor& operator=(Acceptor const &) = delete;
315 * Wrapper for connectionReady() that decrements the count of
316 * pending SSL connections.
318 void sslConnectionReady(AsyncSocket::UniquePtr sock,
319 const folly::SocketAddress& clientAddr,
320 const std::string& nextProtocol,
321 TransportInfo& tinfo);
324 * Notification callback for SSL handshake failures.
326 void sslConnectionError();
330 State state_{State::kInit};
331 uint64_t numPendingSSLConns_{0};
333 static std::atomic<uint64_t> totalNumPendingSSLConns_;
335 bool forceShutdownInProgress_{false};
336 LoadShedConfiguration loadShedConfig_;
337 IConnectionCounter* connectionCounter_{nullptr};
338 std::shared_ptr<SSLCacheProvider> cacheProvider_;
341 class AcceptorFactory {
343 virtual std::shared_ptr<Acceptor> newAcceptor(folly::EventBase*) = 0;
344 virtual ~AcceptorFactory() = default;