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
177 * Drains all open connections of their outstanding transactions. When
178 * a connection's transaction count reaches zero, the connection closes.
180 void drainAllConnections();
183 friend class AcceptorHandshakeHelper;
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()).
192 EventBase* base_{nullptr};
194 virtual uint64_t getConnectionCountForLoadShedding(void) const { return 0; }
197 * Hook for subclasses to drop newly accepted connections prior
200 virtual bool canAccept(const folly::SocketAddress&);
203 * Invoked when a new connection is created. This is where application starts
204 * processing a new downstream connection.
206 * NOTE: Application should add the new connection to
207 * downstreamConnectionManager so that it can be garbage collected after
208 * certain period of idleness.
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
217 virtual void onNewConnection(
218 AsyncSocket::UniquePtr sock,
219 const folly::SocketAddress* address,
220 const std::string& nextProtocolName,
221 const TransportInfo& tinfo) = 0;
223 virtual AsyncSocket::UniquePtr makeNewAsyncSocket(EventBase* base, int fd) {
224 return AsyncSocket::UniquePtr(new AsyncSocket(base, fd));
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));
233 * Hook for subclasses to record stats about SSL connection establishment.
235 virtual void updateSSLStats(
236 const AsyncSSLSocket* sock,
237 std::chrono::milliseconds acceptLatency,
238 SSLErrorEnum error) noexcept {}
241 * Drop all connections.
243 * forceStop() schedules dropAllConnections() to be called in the acceptor's
246 void dropAllConnections();
251 * onConnectionsDrained() will be called once all connections have been
252 * drained while the acceptor is stopping.
254 * Subclasses can override this method to perform any subclass-specific
257 virtual void onConnectionsDrained() {}
259 // AsyncServerSocket::AcceptCallback methods
260 void connectionAccepted(int fd,
261 const folly::SocketAddress& clientAddr)
263 void acceptError(const std::exception& ex) noexcept;
264 void acceptStopped() noexcept;
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) {}
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.
277 void connectionReady(
278 AsyncSocket::UniquePtr sock,
279 const folly::SocketAddress& clientAddr,
280 const std::string& nextProtocolName,
281 TransportInfo& tinfo);
283 const LoadShedConfiguration& getLoadShedConfiguration() const {
284 return loadShedConfig_;
288 const ServerSocketConfig accConfig_;
289 void setLoadShedConfig(const LoadShedConfiguration& from,
290 IConnectionCounter* counter);
293 * Socket options to apply to the client socket
295 AsyncSocket::OptionMap socketOptions_;
297 std::unique_ptr<SSLContextManager> sslCtxManager_;
300 * Whether we want to enable client hello parsing in the handshake helper
301 * to get list of supported client ciphers.
303 bool parseClientHello_{false};
305 folly::wangle::ConnectionManager::UniquePtr downstreamConnectionManager_;
309 // Forbidden copy constructor and assignment opererator
310 Acceptor(Acceptor const &) = delete;
311 Acceptor& operator=(Acceptor const &) = delete;
314 * Wrapper for connectionReady() that decrements the count of
315 * pending SSL connections.
317 void sslConnectionReady(AsyncSocket::UniquePtr sock,
318 const folly::SocketAddress& clientAddr,
319 const std::string& nextProtocol,
320 TransportInfo& tinfo);
323 * Notification callback for SSL handshake failures.
325 void sslConnectionError();
329 State state_{State::kInit};
330 uint64_t numPendingSSLConns_{0};
332 static std::atomic<uint64_t> totalNumPendingSSLConns_;
334 bool forceShutdownInProgress_{false};
335 LoadShedConfiguration loadShedConfig_;
336 IConnectionCounter* connectionCounter_{nullptr};
337 std::shared_ptr<SSLCacheProvider> cacheProvider_;
340 class AcceptorFactory {
342 virtual std::shared_ptr<Acceptor> newAcceptor() = 0;
343 virtual ~AcceptorFactory() = default;