2 * Copyright (c) 2015, 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>
23 #include <folly/io/async/AsyncUDPServerSocket.h>
25 namespace folly { namespace wangle {
26 class ManagedConnection;
34 class SSLContextManager;
37 * An abstract acceptor for TCP-based network services.
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.
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.
49 public folly::AsyncServerSocket::AcceptCallback,
50 public folly::wangle::ConnectionManager::Callback,
51 public AsyncUDPServerSocket::Callback {
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
61 explicit Acceptor(const ServerSocketConfig& accConfig);
65 * Supply an SSL cache provider
66 * @note Call this before init()
68 virtual void setSSLCacheProvider(
69 const std::shared_ptr<SSLCacheProvider>& cacheProvider) {
70 cacheProvider_ = cacheProvider;
74 * Initialize the Acceptor to run in the specified EventBase
75 * thread, receiving connections from the specified AsyncServerSocket.
77 * This method will be called from the AsyncServerSocket's primary thread,
78 * not the specified EventBase thread.
80 virtual void init(AsyncServerSocket* serverSocket,
81 EventBase* eventBase);
84 * Dynamically add a new SSLContextConfig
86 void addSSLContextConfig(const SSLContextConfig& sslCtxConfig);
88 SSLContextManager* getSSLContextManager() const {
89 return sslCtxManager_.get();
93 * Return the number of outstanding connections in this service instance.
95 uint32_t getNumConnections() const {
96 return downstreamConnectionManager_ ?
97 (uint32_t)downstreamConnectionManager_->getNumConnections() : 0;
101 * Access the Acceptor's event base.
103 virtual EventBase* getEventBase() const { return base_; }
106 * Access the Acceptor's downstream (client-side) ConnectionManager
108 virtual folly::wangle::ConnectionManager* getConnectionManager() {
109 return downstreamConnectionManager_.get();
113 * Invoked when a new ManagedConnection is created.
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.
119 void addConnection(folly::wangle::ManagedConnection* connection);
122 * Get this acceptor's current state.
124 State getState() const {
129 * Get the current connection timeout.
131 std::chrono::milliseconds getConnTimeout() const;
134 * Returns the name of this VIP.
136 * Will return an empty string if no name has been configured.
138 const std::string& getName() const {
139 return accConfig_.name;
143 * Force the acceptor to drop all connections and stop processing.
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.
149 virtual void forceStop();
151 bool isSSL() const { return accConfig_.isSSL(); }
153 const ServerSocketConfig& getConfig() const { return accConfig_; }
155 static uint64_t getTotalNumPendingSSLConns() {
156 return totalNumPendingSSLConns_.load();
160 * Called right when the TCP connection has been accepted, before processing
161 * the first HTTP bytes (HTTP) or the SSL handshake (HTTPS)
163 virtual void onDoneAcceptingConnection(
165 const SocketAddress& clientAddr,
166 std::chrono::steady_clock::time_point acceptTime
170 * Begins either processing HTTP bytes (HTTP) or the SSL handshake (HTTPS)
172 void processEstablishedConnection(
174 const SocketAddress& clientAddr,
175 std::chrono::steady_clock::time_point acceptTime,
180 * Drains all open connections of their outstanding transactions. When
181 * a connection's transaction count reaches zero, the connection closes.
183 void drainAllConnections();
186 * Drop all connections.
188 * forceStop() schedules dropAllConnections() to be called in the acceptor's
191 void dropAllConnections();
194 friend class AcceptorHandshakeHelper;
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()).
203 EventBase* base_{nullptr};
205 virtual uint64_t getConnectionCountForLoadShedding(void) const { return 0; }
208 * Hook for subclasses to drop newly accepted connections prior
211 virtual bool canAccept(const folly::SocketAddress&);
214 * Invoked when a new connection is created. This is where application starts
215 * processing a new downstream connection.
217 * NOTE: Application should add the new connection to
218 * downstreamConnectionManager so that it can be garbage collected after
219 * certain period of idleness.
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
228 virtual void onNewConnection(
229 AsyncSocket::UniquePtr sock,
230 const folly::SocketAddress* address,
231 const std::string& nextProtocolName,
232 const TransportInfo& tinfo) {}
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 {}
241 virtual AsyncSocket::UniquePtr makeNewAsyncSocket(EventBase* base, int fd) {
242 return AsyncSocket::UniquePtr(new AsyncSocket(base, fd));
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));
251 * Hook for subclasses to record stats about SSL connection establishment.
253 virtual void updateSSLStats(
254 const AsyncSSLSocket* sock,
255 std::chrono::milliseconds acceptLatency,
256 SSLErrorEnum error) noexcept {}
261 * onConnectionsDrained() will be called once all connections have been
262 * drained while the acceptor is stopping.
264 * Subclasses can override this method to perform any subclass-specific
267 virtual void onConnectionsDrained() {}
269 // AsyncServerSocket::AcceptCallback methods
270 void connectionAccepted(int fd,
271 const folly::SocketAddress& clientAddr)
273 void acceptError(const std::exception& ex) noexcept;
274 void acceptStopped() noexcept;
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) {}
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.
287 void connectionReady(
288 AsyncSocket::UniquePtr sock,
289 const folly::SocketAddress& clientAddr,
290 const std::string& nextProtocolName,
291 TransportInfo& tinfo);
293 const LoadShedConfiguration& getLoadShedConfiguration() const {
294 return loadShedConfig_;
298 const ServerSocketConfig accConfig_;
299 void setLoadShedConfig(const LoadShedConfiguration& from,
300 IConnectionCounter* counter);
303 * Socket options to apply to the client socket
305 AsyncSocket::OptionMap socketOptions_;
307 std::unique_ptr<SSLContextManager> sslCtxManager_;
310 * Whether we want to enable client hello parsing in the handshake helper
311 * to get list of supported client ciphers.
313 bool parseClientHello_{false};
315 folly::wangle::ConnectionManager::UniquePtr downstreamConnectionManager_;
319 // Forbidden copy constructor and assignment opererator
320 Acceptor(Acceptor const &) = delete;
321 Acceptor& operator=(Acceptor const &) = delete;
324 * Wrapper for connectionReady() that decrements the count of
325 * pending SSL connections.
327 void sslConnectionReady(AsyncSocket::UniquePtr sock,
328 const folly::SocketAddress& clientAddr,
329 const std::string& nextProtocol,
330 TransportInfo& tinfo);
333 * Notification callback for SSL handshake failures.
335 void sslConnectionError();
339 State state_{State::kInit};
340 uint64_t numPendingSSLConns_{0};
342 static std::atomic<uint64_t> totalNumPendingSSLConns_;
344 bool forceShutdownInProgress_{false};
345 LoadShedConfiguration loadShedConfig_;
346 IConnectionCounter* connectionCounter_{nullptr};
347 std::shared_ptr<SSLCacheProvider> cacheProvider_;
350 class AcceptorFactory {
352 virtual std::shared_ptr<Acceptor> newAcceptor(folly::EventBase*) = 0;
353 virtual ~AcceptorFactory() = default;