1 /* 2 * Copyright (c) Facebook, Inc. and its affiliates. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef THRIFT_SERVER_H_ 18 #define THRIFT_SERVER_H_ 1 19 20 #include <array> 21 #include <atomic> 22 #include <chrono> 23 #include <cstdlib> 24 #include <map> 25 #include <mutex> 26 #include <optional> 27 #include <unordered_map> 28 #include <utility> 29 #include <vector> 30 31 #include <folly/Memory.h> 32 #include <folly/Singleton.h> 33 #include <folly/SocketAddress.h> 34 #include <folly/executors/IOThreadPoolExecutor.h> 35 #include <folly/experimental/PrimaryPtr.h> 36 #include <folly/experimental/coro/AsyncScope.h> 37 #include <folly/experimental/observer/Observer.h> 38 #include <folly/io/ShutdownSocketSet.h> 39 #include <folly/io/async/AsyncServerSocket.h> 40 #include <folly/io/async/EventBase.h> 41 #include <folly/io/async/EventBaseManager.h> 42 #include <folly/lang/Badge.h> 43 #include <folly/synchronization/CallOnce.h> 44 #include <thrift/lib/cpp/concurrency/PosixThreadFactory.h> 45 #include <thrift/lib/cpp/concurrency/ThreadManager.h> 46 #include <thrift/lib/cpp/server/TServerObserver.h> 47 #include <thrift/lib/cpp/transport/THeader.h> 48 #include <thrift/lib/cpp2/PluggableFunction.h> 49 #include <thrift/lib/cpp2/Thrift.h> 50 #include <thrift/lib/cpp2/async/AsyncProcessor.h> 51 #include <thrift/lib/cpp2/async/HeaderServerChannel.h> 52 #include <thrift/lib/cpp2/server/BaseThriftServer.h> 53 #include <thrift/lib/cpp2/server/PolledServiceHealth.h> 54 #include <thrift/lib/cpp2/server/PreprocessParams.h> 55 #include <thrift/lib/cpp2/server/RequestDebugLog.h> 56 #include <thrift/lib/cpp2/server/RequestsRegistry.h> 57 #include <thrift/lib/cpp2/server/ServerInstrumentation.h> 58 #include <thrift/lib/cpp2/server/ServiceHealthPoller.h> 59 #include <thrift/lib/cpp2/server/TransportRoutingHandler.h> 60 #include <thrift/lib/cpp2/transport/rocket/PayloadUtils.h> 61 #include <thrift/lib/cpp2/transport/rocket/Types.h> 62 #include <thrift/lib/thrift/gen-cpp2/RpcMetadata_constants.h> 63 #include <wangle/acceptor/ServerSocketConfig.h> 64 #include <wangle/acceptor/SharedSSLContextManager.h> 65 #include <wangle/bootstrap/ServerBootstrap.h> 66 #include <wangle/ssl/SSLContextConfig.h> 67 #include <wangle/ssl/TLSCredProcessor.h> 68 69 DECLARE_bool(thrift_abort_if_exceeds_shutdown_deadline); 70 DECLARE_string(service_identity); 71 72 THRIFT_FLAG_DECLARE_bool(dump_snapshot_on_long_shutdown); 73 THRIFT_FLAG_DECLARE_bool(alpn_allow_mismatch); 74 THRIFT_FLAG_DECLARE_bool(server_check_unimplemented_extra_interfaces); 75 76 namespace apache { 77 namespace thrift { 78 79 // Forward declaration of classes 80 class Cpp2Connection; 81 class Cpp2Worker; 82 class ThriftServer; 83 class ThriftProcessor; 84 namespace rocket { 85 class ThriftRocketServerHandler; 86 } 87 88 enum class SSLPolicy { DISABLED, PERMITTED, REQUIRED }; 89 90 typedef wangle::Pipeline<folly::IOBufQueue&, std::unique_ptr<folly::IOBuf>> 91 Pipeline; 92 93 class ThriftTlsConfig : public wangle::CustomConfig { 94 public: 95 bool enableThriftParamsNegotiation{true}; 96 bool enableStopTLS{false}; 97 }; 98 99 class TLSCredentialWatcher { 100 public: 101 explicit TLSCredentialWatcher(ThriftServer* server); 102 setCertPathsToWatch(std::set<std::string> paths)103 void setCertPathsToWatch(std::set<std::string> paths) { 104 credProcessor_.setCertPathsToWatch(std::move(paths)); 105 } 106 setTicketPathToWatch(const std::string & path)107 void setTicketPathToWatch(const std::string& path) { 108 credProcessor_.setTicketPathToWatch(path); 109 } 110 111 private: 112 wangle::TLSCredProcessor credProcessor_; 113 }; 114 115 /** 116 * State pertaining to stopping a running Thrift server. It is safe to call 117 * stop() on this even after the relevant ThriftServer has been destroyed as 118 * long as the server's event base is not re-used for something else. This is 119 * useful to prevent racing between requests to stop (such as from signal 120 * handlers) and ThriftServer's destructor. 121 * 122 * This class cannot be directly constructed by user code. Instead every 123 * ThriftServer owns a stop controller (using folly::PrimaryPtr) and hands out 124 * non-owning references to use (folly::PrimaryPtrRef). ThriftServer's 125 * destructor will block until all locked references have been released. 126 * 127 * The user-facing API that makes use of this is ServiceHandler::shutdownServer. 128 */ 129 class ThriftServerStopController final { 130 public: ThriftServerStopController(folly::badge<ThriftServer>,folly::EventBase & eventBase)131 explicit ThriftServerStopController( 132 folly::badge<ThriftServer>, folly::EventBase& eventBase) 133 : serveEventBase_(eventBase) {} 134 135 void stop(); 136 137 private: 138 folly::EventBase& serveEventBase_; 139 folly::once_flag stopped_; 140 }; 141 142 /** 143 * This is yet another thrift server. 144 * Uses cpp2 style generated code. 145 */ 146 147 class ThriftServer : public apache::thrift::BaseThriftServer, 148 public wangle::ServerBootstrap<Pipeline> { 149 private: 150 //! SSL context 151 std::optional<folly::observer::Observer<wangle::SSLContextConfig>> 152 sslContextObserver_; 153 std::optional<wangle::TLSTicketKeySeeds> ticketSeeds_; 154 folly::observer::CallbackHandle getSSLCallbackHandle(); 155 156 std::optional<bool> reusePort_; 157 std::optional<bool> enableTFO_; 158 uint32_t fastOpenQueueSize_{10000}; 159 160 std::optional<wangle::SSLCacheOptions> sslCacheOptions_; 161 wangle::FizzConfig fizzConfig_; 162 ThriftTlsConfig thriftConfig_; 163 164 // Security negotiation settings 165 std::optional<SSLPolicy> sslPolicy_; 166 bool strictSSL_ = false; 167 // whether we allow plaintext connections from loopback in REQUIRED mode 168 bool allowPlaintextOnLoopback_ = false; 169 170 // If true, then falls back to the corresponding THRIFT_FLAG. 171 // If false, then the check is bypassed even if the THRIFT_FLAG is set. 172 // This allows a hard-coded opt-out of the check for services where it would 173 // not be useful, e.g. non-C++ languages. 174 bool allowCheckUnimplementedExtraInterfaces_ = true; 175 176 std::weak_ptr<folly::ShutdownSocketSet> wShutdownSocketSet_; 177 178 //! Listen socket 179 folly::AsyncServerSocket::UniquePtr socket_; 180 181 struct IdleServerAction : public folly::HHWheelTimer::Callback { 182 IdleServerAction( 183 ThriftServer& server, 184 folly::HHWheelTimer& timer, 185 std::chrono::milliseconds timeout); 186 187 void timeoutExpired() noexcept override; 188 189 ThriftServer& server_; 190 folly::HHWheelTimer& timer_; 191 std::chrono::milliseconds timeout_; 192 }; 193 194 //! The folly::EventBase currently driving serve(). NULL when not serving. 195 std::atomic<folly::EventBase*> serveEventBase_{nullptr}; 196 std::optional<IdleServerAction> idleServer_; 197 std::chrono::milliseconds idleServerTimeout_ = std::chrono::milliseconds(0); 198 std::optional<std::chrono::milliseconds> sslHandshakeTimeout_; 199 std::atomic<std::chrono::steady_clock::duration::rep> lastRequestTime_; 200 201 // Includes non-request events in Rocket. Only bumped if idleTimeout set. 202 std::chrono::steady_clock::time_point lastRequestTime() const noexcept; 203 void touchRequestTimestamp() noexcept; 204 205 //! Manager of per-thread EventBase objects. 206 folly::EventBaseManager* eventBaseManager_ = folly::EventBaseManager::get(); 207 208 //! IO thread pool. Drives Cpp2Workers. 209 std::shared_ptr<folly::IOThreadPoolExecutor> ioThreadPool_ = 210 std::make_shared<folly::IOThreadPoolExecutor>( 211 0, std::make_shared<folly::NamedThreadFactory>("ThriftIO")); 212 213 /** 214 * The speed for adjusting connection accept rate. 215 * 0 for disabling auto adjusting connection accept rate. 216 */ 217 double acceptRateAdjustSpeed_ = 0.0; 218 219 /** 220 * Acceptors accept and process incoming connections. The acceptor factory 221 * helps create acceptors. 222 */ 223 std::shared_ptr<wangle::AcceptorFactory> acceptorFactory_; 224 std::shared_ptr<wangle::SharedSSLContextManager> sharedSSLContextManager_; 225 226 void handleSetupFailure(void); 227 228 void updateCertsToWatch(); 229 230 bool stopWorkersOnStopListening_ = true; 231 bool joinRequestsWhenServerStops_{true}; 232 233 folly::AsyncWriter::ZeroCopyEnableFunc zeroCopyEnableFunc_; 234 235 std::shared_ptr<folly::IOThreadPoolExecutor> acceptPool_; 236 int nAcceptors_ = 1; 237 uint16_t socketMaxReadsPerEvent_{16}; 238 239 // HeaderServerChannel and Cpp2Worker to use for a duplex server 240 // (used by client). Both are nullptr for a regular server. 241 std::shared_ptr<HeaderServerChannel> serverChannel_; 242 std::shared_ptr<Cpp2Worker> duplexWorker_; 243 244 bool isDuplex_ = false; // is server in duplex mode? (used by server) 245 246 mutable std::mutex ioGroupMutex_; 247 getIOGroupSafe()248 std::shared_ptr<folly::IOThreadPoolExecutor> getIOGroupSafe() const { 249 std::lock_guard<std::mutex> lock(ioGroupMutex_); 250 return getIOGroup(); 251 } 252 253 void stopWorkers(); 254 void stopCPUWorkers(); 255 void stopAcceptingAndJoinOutstandingRequests(); 256 257 void callOnStartServing(); 258 void callOnStopServing(); 259 260 void ensureDecoratedProcessorFactoryInitialized(); 261 262 #if FOLLY_HAS_COROUTINES 263 std::unique_ptr<folly::coro::CancellableAsyncScope> asyncScope_; 264 #endif 265 266 folly::Synchronized<std::optional<TLSCredentialWatcher>> tlsCredWatcher_{}; 267 268 std::unique_ptr<ThriftProcessor> thriftProcessor_; 269 std::vector<std::unique_ptr<TransportRoutingHandler>> routingHandlers_; 270 271 friend class Cpp2Connection; 272 friend class Cpp2Worker; 273 friend class rocket::ThriftRocketServerHandler; 274 275 bool tosReflect_{false}; 276 uint32_t listenerTos_{0}; 277 278 std::optional<instrumentation::ServerTracker> tracker_; 279 280 bool quickExitOnShutdownTimeout_ = false; 281 282 public: 283 /** 284 * The goal of this enum is to capture every state the server goes through in 285 * its lifecycle. Notice how the lifecycle is actually a cycle - after the 286 * server stops, it returns to its initial state of NOT_RUNNING. 287 * 288 * NOTE: For the restrictions regarding only allowing internal methods - these 289 * do not apply if getRejectRequestsUntilStarted() is false. 290 */ 291 enum class ServerStatus { 292 /** 293 * The server is not running. Either: 294 * 1. The server was never started. Or, 295 * 2. The server was stopped and there are outstanding requests 296 * were drained. 297 */ 298 NOT_RUNNING = 0, 299 /** 300 * The server is about to start and is executing 301 * TServerEventHandler::preStart hooks. If getRejectRequestsUntilStarted() 302 * is true, the server only responds to internal methods. See 303 * ServerConfigs::getInternalMethods. 304 */ 305 PRE_STARTING, 306 /** 307 * The preStart hooks are done executing and 308 * ServiceHandler::semifuture_onStartServing hooks are executing. If 309 * getRejectRequestsUntilStarted() is true, the server only responds to 310 * internal methods. 311 */ 312 STARTING, 313 /** 314 * The service is healthy and ready to handle traffic. 315 */ 316 RUNNING, 317 /** 318 * The server is preparing to stop. No new connections are accepted. 319 * Existing connections are unaffected. 320 */ 321 PRE_STOPPING, 322 /** 323 * The server is about to stop and ServiceHandler::semifuture_onStopServing 324 * hooks are still executing. 325 */ 326 STOPPING, 327 /** 328 * ServiceHandler::semifuture_onStopServing hooks have finished executing. 329 * Outstanding requests are being joined. New requests are rejected. 330 */ 331 DRAINING_UNTIL_STOPPED, 332 }; 333 getServerStatus()334 ServerStatus getServerStatus() const { 335 auto status = internalStatus_.load(std::memory_order_acquire); 336 if (status == ServerStatus::RUNNING && !getEnabled()) { 337 // Even if the server is capable of serving, the user might have 338 // explicitly disabled the service at startup, in which case the server 339 // only responds to internal methods. 340 return ServerStatus::STARTING; 341 } 342 return status; 343 } 344 345 #if FOLLY_HAS_COROUTINES 346 using ServiceHealth = PolledServiceHealth::ServiceHealth; 347 getServiceHealth()348 std::optional<ServiceHealth> getServiceHealth() const { 349 auto health = cachedServiceHealth_.load(std::memory_order_relaxed); 350 return health == ServiceHealth{} ? std::nullopt 351 : std::make_optional(health); 352 } 353 #endif 354 shouldHandleRequests()355 RequestHandlingCapability shouldHandleRequests() const override { 356 auto status = getServerStatus(); 357 switch (status) { 358 case ServerStatus::RUNNING: 359 return RequestHandlingCapability::ALL; 360 case ServerStatus::NOT_RUNNING: 361 // The server can be in the NOT_RUNNING state and still have open 362 // connections, for example, if useExistingSocket is called with a 363 // socket that is already listening. 364 [[fallthrough]]; 365 case ServerStatus::PRE_STARTING: 366 case ServerStatus::STARTING: 367 return getRejectRequestsUntilStarted() 368 ? RequestHandlingCapability::INTERNAL_METHODS_ONLY 369 : RequestHandlingCapability::ALL; 370 case ServerStatus::PRE_STOPPING: 371 case ServerStatus::STOPPING: 372 // When the server is stopping, we close the sockets for new 373 // connections. However, existing connections should be unaffected. 374 return RequestHandlingCapability::ALL; 375 case ServerStatus::DRAINING_UNTIL_STOPPED: 376 default: 377 return RequestHandlingCapability::NONE; 378 } 379 } 380 381 private: 382 /** 383 * Thrift server's view of the currently running service. This status 384 * represents the source of truth for the status reported by the server. 385 */ 386 std::atomic<ServerStatus> internalStatus_{ServerStatus::NOT_RUNNING}; 387 #if FOLLY_HAS_COROUTINES 388 /** 389 * Thrift server's latest view of the running service's reported health. 390 */ 391 std::atomic<ServiceHealth> cachedServiceHealth_{}; 392 #endif 393 394 std::unique_ptr<AsyncProcessorFactory> decoratedProcessorFactory_; 395 396 /** 397 * Collects service handlers of the current service of a specific type. 398 */ 399 template < 400 typename TServiceHandler = ServiceHandler, 401 typename = 402 std::enable_if_t<std::is_base_of_v<ServiceHandler, TServiceHandler>>> collectServiceHandlers()403 std::vector<TServiceHandler*> collectServiceHandlers() const { 404 if constexpr (std::is_same_v<TServiceHandler, ServiceHandler>) { 405 return getDecoratedProcessorFactory().getServiceHandlers(); 406 } 407 std::vector<TServiceHandler*> matchedServiceHandlers; 408 for (auto* serviceHandler : 409 getDecoratedProcessorFactory().getServiceHandlers()) { 410 if (auto matched = dynamic_cast<TServiceHandler*>(serviceHandler)) { 411 matchedServiceHandlers.push_back(matched); 412 } 413 } 414 return matchedServiceHandlers; 415 } 416 417 public: 418 ThriftServer(); 419 420 // NOTE: Don't use this constructor to create a regular Thrift server. This 421 // constructor is used by the client to create a duplex server on an existing 422 // connection. 423 // Don't create a listening server. Instead use the channel to run incoming 424 // requests. 425 explicit ThriftServer( 426 const std::shared_ptr<HeaderServerChannel>& serverChannel); 427 428 ~ThriftServer() override; 429 430 /** 431 * Set the thread pool used to drive the server's IO threads. Note that the 432 * pool's thread factory will be overridden - if you'd like to use your own, 433 * set it afterwards via ThriftServer::setIOThreadFactory(). If the given 434 * thread pool has one or more allocated threads, the number of workers will 435 * be set to this number. Use ThreadServer::setNumIOWorkerThreads() to set 436 * it afterwards if you want to change the number of works. 437 * 438 * @param the new thread pool 439 */ setIOThreadPool(std::shared_ptr<folly::IOThreadPoolExecutor> ioThreadPool)440 void setIOThreadPool( 441 std::shared_ptr<folly::IOThreadPoolExecutor> ioThreadPool) { 442 CHECK(configMutable()); 443 ioThreadPool_ = ioThreadPool; 444 445 if (ioThreadPool_->numThreads() > 0) { 446 setNumIOWorkerThreads(ioThreadPool_->numThreads()); 447 } 448 } 449 450 /** 451 * Doing any blocking work on this executor will cause the server to 452 * stall servicing requests. Be careful about using this executor for anything 453 * other than its main purpose. 454 */ getIOThreadPool()455 std::shared_ptr<folly::IOThreadPoolExecutor> getIOThreadPool() { 456 return ioThreadPool_; 457 } 458 459 /** 460 * Set the thread factory that will be used to create the server's IO 461 * threads. 462 * 463 * @param the new thread factory 464 */ setIOThreadFactory(std::shared_ptr<folly::NamedThreadFactory> threadFactory)465 void setIOThreadFactory( 466 std::shared_ptr<folly::NamedThreadFactory> threadFactory) { 467 CHECK(configMutable()); 468 ioThreadPool_->setThreadFactory(threadFactory); 469 } 470 471 /** 472 * Set the prefix for naming the worker threads. "Cpp2Worker" by default. 473 * must be called before serve() for it to take effect 474 * 475 * @param cpp2WorkerThreadName net thread name prefix 476 */ setCpp2WorkerThreadName(const std::string & cpp2WorkerThreadName)477 void setCpp2WorkerThreadName(const std::string& cpp2WorkerThreadName) { 478 CHECK(configMutable()); 479 auto factory = ioThreadPool_->getThreadFactory(); 480 CHECK(factory); 481 auto namedFactory = 482 std::dynamic_pointer_cast<folly::NamedThreadFactory>(factory); 483 CHECK(namedFactory); 484 namedFactory->setNamePrefix(cpp2WorkerThreadName); 485 } 486 487 // if overloaded, returns applicable overloaded exception code. 488 folly::Optional<std::string> checkOverload( 489 const transport::THeader::StringToStringMap* readHeaders = nullptr, 490 const std::string* = nullptr) const final; 491 492 // returns descriptive error if application is unable to process request 493 PreprocessResult preprocess( 494 const server::PreprocessParams& params) const final; 495 496 std::string getLoadInfo(int64_t load) const override; 497 498 /* 499 * Use a ZeroCopyEnableFunc to decide when to use zerocopy mode 500 * Ex: use zerocopy when the IOBuf chain exceeds a certain thresold 501 * setZeroCopyEnableFunc([threshold](const std::unique_ptr<folly::IOBuf>& buf) 502 * { return (buf->computeChainDataLength() > threshold);}); 503 */ setZeroCopyEnableFunc(folly::AsyncWriter::ZeroCopyEnableFunc func)504 void setZeroCopyEnableFunc(folly::AsyncWriter::ZeroCopyEnableFunc func) { 505 zeroCopyEnableFunc_ = std::move(func); 506 } 507 getZeroCopyEnableFunc()508 const folly::AsyncWriter::ZeroCopyEnableFunc& getZeroCopyEnableFunc() const { 509 return zeroCopyEnableFunc_; 510 } 511 setAcceptExecutor(std::shared_ptr<folly::IOThreadPoolExecutor> pool)512 void setAcceptExecutor(std::shared_ptr<folly::IOThreadPoolExecutor> pool) { 513 acceptPool_ = pool; 514 } 515 516 /** 517 * Generally the acceptor should not do any work other than 518 * accepting connections, so use this with care. 519 */ getAcceptExecutor()520 std::shared_ptr<folly::IOThreadPoolExecutor> getAcceptExecutor() { 521 return acceptPool_; 522 } 523 setNumAcceptThreads(int numAcceptThreads)524 void setNumAcceptThreads(int numAcceptThreads) { 525 CHECK(!acceptPool_); 526 nAcceptors_ = numAcceptThreads; 527 } 528 529 /** 530 * Set the SSLContextConfig on the thrift server. 531 */ setSSLConfig(std::shared_ptr<wangle::SSLContextConfig> context)532 void setSSLConfig(std::shared_ptr<wangle::SSLContextConfig> context) { 533 CHECK(configMutable()); 534 if (context) { 535 setSSLConfig(folly::observer::makeObserver( 536 [context = std::move(context)]() { return *context; })); 537 } 538 updateCertsToWatch(); 539 } 540 541 /** 542 * Set the SSLContextConfig on the thrift server. Note that the thrift server 543 * keeps an observer on the SSLContextConfig. Whenever the SSLContextConfig 544 * has an update, the observer callback would reset SSLContextConfig on all 545 * acceptors. 546 */ setSSLConfig(folly::observer::Observer<wangle::SSLContextConfig> contextObserver)547 void setSSLConfig( 548 folly::observer::Observer<wangle::SSLContextConfig> contextObserver) { 549 sslContextObserver_ = folly::observer::makeObserver( 550 [observer = std::move(contextObserver), 551 alpnObserver = ThriftServer::alpnAllowMismatch()]() { 552 auto context = **observer; 553 context.isDefault = true; 554 context.alpnAllowMismatch = **alpnObserver; 555 return context; 556 }); 557 } 558 setFizzConfig(wangle::FizzConfig config)559 void setFizzConfig(wangle::FizzConfig config) { fizzConfig_ = config; } 560 setThriftConfig(ThriftTlsConfig thriftConfig)561 void setThriftConfig(ThriftTlsConfig thriftConfig) { 562 thriftConfig_ = thriftConfig; 563 } 564 setSSLCacheOptions(wangle::SSLCacheOptions options)565 void setSSLCacheOptions(wangle::SSLCacheOptions options) { 566 sslCacheOptions_ = std::move(options); 567 } 568 setTicketSeeds(wangle::TLSTicketKeySeeds seeds)569 void setTicketSeeds(wangle::TLSTicketKeySeeds seeds) { ticketSeeds_ = seeds; } 570 571 /** 572 * Set the ssl handshake timeout. 573 */ setSSLHandshakeTimeout(std::optional<std::chrono::milliseconds> timeout)574 void setSSLHandshakeTimeout( 575 std::optional<std::chrono::milliseconds> timeout) { 576 sslHandshakeTimeout_ = timeout; 577 } 578 getSSLHandshakeTimeout()579 const std::optional<std::chrono::milliseconds>& getSSLHandshakeTimeout() 580 const { 581 return sslHandshakeTimeout_; 582 } 583 584 /** 585 * Stops the Thrift server if it's idle for the given time. 586 */ setIdleServerTimeout(std::chrono::milliseconds timeout)587 void setIdleServerTimeout(std::chrono::milliseconds timeout) { 588 idleServerTimeout_ = timeout; 589 } 590 591 /** 592 * Configures maxReadsPerEvent for accepted connections, see 593 * `folly::AsyncSocket::setMaxReadsPerEvent` for more details. 594 */ setSocketMaxReadsPerEvent(uint16_t socketMaxReadsPerEvent)595 void setSocketMaxReadsPerEvent(uint16_t socketMaxReadsPerEvent) { 596 socketMaxReadsPerEvent_ = socketMaxReadsPerEvent; 597 } 598 599 void updateTicketSeeds(wangle::TLSTicketKeySeeds seeds); 600 601 void updateTLSCert(); 602 603 /** 604 * Tells the thrift server to update ticket seeds with the contents of the 605 * file ticketPath when modified and initialized the seeds with the contents 606 * of the file ticketPath. The seed file previously being watched will no 607 * longer be watched. This is not thread safe. 608 */ 609 void watchTicketPathForChanges(const std::string& ticketPath); 610 setFastOpenOptions(bool enableTFO,uint32_t fastOpenQueueSize)611 void setFastOpenOptions(bool enableTFO, uint32_t fastOpenQueueSize) { 612 enableTFO_ = enableTFO; 613 fastOpenQueueSize_ = fastOpenQueueSize; 614 } 615 getTFOEnabled()616 std::optional<bool> getTFOEnabled() { return enableTFO_; } 617 setReusePort(bool reusePort)618 void setReusePort(bool reusePort) { reusePort_ = reusePort; } 619 getReusePort()620 std::optional<bool> getReusePort() { return reusePort_; } 621 622 const std::optional<folly::observer::Observer<wangle::SSLContextConfig>>& getSSLConfig()623 getSSLConfig() const { 624 return sslContextObserver_; 625 } 626 getTicketSeeds()627 const std::optional<wangle::TLSTicketKeySeeds>& getTicketSeeds() const { 628 return ticketSeeds_; 629 } 630 getSSLCacheOptions()631 const std::optional<wangle::SSLCacheOptions>& getSSLCacheOptions() const { 632 return sslCacheOptions_; 633 } 634 getServerSocketConfig()635 wangle::ServerSocketConfig getServerSocketConfig() { 636 wangle::ServerSocketConfig config; 637 if (sslContextObserver_.has_value()) { 638 config.sslContextConfigs.push_back(*sslContextObserver_->getSnapshot()); 639 } 640 if (sslCacheOptions_) { 641 config.sslCacheOptions = *sslCacheOptions_; 642 } 643 config.connectionIdleTimeout = getIdleTimeout(); 644 config.acceptBacklog = getListenBacklog(); 645 if (ticketSeeds_) { 646 config.initialTicketSeeds = *ticketSeeds_; 647 } 648 if (enableTFO_) { 649 config.enableTCPFastOpen = *enableTFO_; 650 config.fastOpenQueueSize = fastOpenQueueSize_; 651 } 652 if (sslHandshakeTimeout_) { 653 config.sslHandshakeTimeout = *sslHandshakeTimeout_; 654 } else if (getIdleTimeout() == std::chrono::milliseconds::zero()) { 655 // make sure a handshake that takes too long doesn't kill the connection 656 config.sslHandshakeTimeout = std::chrono::milliseconds::zero(); 657 } 658 // By default, we set strictSSL to false. This means the server will start 659 // even if cert/key is missing as it may become available later 660 config.strictSSL = getStrictSSL() || getSSLPolicy() == SSLPolicy::REQUIRED; 661 config.fizzConfig = fizzConfig_; 662 config.customConfigMap["thrift_tls_config"] = 663 std::make_shared<ThriftTlsConfig>(thriftConfig_); 664 config.socketMaxReadsPerEvent = socketMaxReadsPerEvent_; 665 666 config.useZeroCopy = !!zeroCopyEnableFunc_; 667 return config; 668 } 669 670 /** 671 * Use the provided socket rather than binding to address_. The caller must 672 * call ::bind on this socket, but should not call ::listen. 673 * 674 * NOTE: ThriftServer takes ownership of this 'socket' so if binding fails 675 * we destroy this socket, while cleaning itself up. So, 'accept' better 676 * work the first time :) 677 */ 678 void useExistingSocket(int socket); 679 void useExistingSockets(const std::vector<int>& sockets); 680 void useExistingSocket(folly::AsyncServerSocket::UniquePtr socket); 681 682 /** 683 * Return the file descriptor(s) associated with the listening socket 684 */ 685 int getListenSocket() const; 686 std::vector<int> getListenSockets() const; 687 688 /** 689 * Get the ThriftServer's main event base. 690 * 691 * @return a pointer to the EventBase. 692 */ getServeEventBase()693 folly::EventBase* getServeEventBase() const { return serveEventBase_; } 694 695 /** 696 * Get the EventBaseManager used by this server. This can be used to find 697 * or create the EventBase associated with any given thread, including any 698 * new threads created by clients. This may be called from any thread. 699 * 700 * @return a pointer to the EventBaseManager. 701 */ 702 folly::EventBaseManager* getEventBaseManager(); getEventBaseManager()703 const folly::EventBaseManager* getEventBaseManager() const { 704 return const_cast<ThriftServer*>(this)->getEventBaseManager(); 705 } 706 707 SSLPolicy getSSLPolicy() const; 708 709 // Convenience method to check if SSLPolicy is explicitly set isSSLPolicySet()710 bool isSSLPolicySet() const { return sslPolicy_.has_value(); } 711 setSSLPolicy(SSLPolicy policy)712 void setSSLPolicy(SSLPolicy policy) { sslPolicy_ = policy; } 713 setStrictSSL(bool strictSSL)714 void setStrictSSL(bool strictSSL) { strictSSL_ = strictSSL; } 715 getStrictSSL()716 bool getStrictSSL() { return strictSSL_; } 717 setAllowPlaintextOnLoopback(bool allow)718 void setAllowPlaintextOnLoopback(bool allow) { 719 allowPlaintextOnLoopback_ = allow; 720 } 721 isPlaintextAllowedOnLoopback()722 bool isPlaintextAllowedOnLoopback() const { 723 return allowPlaintextOnLoopback_; 724 } 725 setAllowCheckUnimplementedExtraInterfaces(bool allow)726 void setAllowCheckUnimplementedExtraInterfaces(bool allow) { 727 allowCheckUnimplementedExtraInterfaces_ = allow; 728 } 729 isCheckUnimplementedExtraInterfacesAllowed()730 bool isCheckUnimplementedExtraInterfacesAllowed() const { 731 return allowCheckUnimplementedExtraInterfaces_; 732 } 733 734 static folly::observer::Observer<bool> enableStopTLS(); 735 736 #if FOLLY_HAS_COROUTINES 737 /** 738 * Get CancellableAsyncScope that will be maintained by the Thrift Server. 739 * Cancellation is requested when the server is stopping. 740 * Returns nullptr, before server setup and after server stops. 741 */ getAsyncScope()742 folly::coro::CancellableAsyncScope* getAsyncScope() { 743 return asyncScope_.get(); 744 } 745 746 /** 747 * Get the global CancellableAsyncScope, it is usally the AsyncScope 748 * associated with the global server Cancellation is requested when the 749 * global server is stopping. 750 */ 751 static folly::coro::CancellableAsyncScope& getGlobalAsyncScope(); 752 #endif 753 754 static void setGlobalServer(ThriftServer* server); 755 setAcceptorFactory(const std::shared_ptr<wangle::AcceptorFactory> & acceptorFactory)756 void setAcceptorFactory( 757 const std::shared_ptr<wangle::AcceptorFactory>& acceptorFactory) { 758 acceptorFactory_ = acceptorFactory; 759 } 760 761 /** 762 * Get the speed of adjusting connection accept rate. 763 */ getAcceptRateAdjustSpeed()764 double getAcceptRateAdjustSpeed() const { return acceptRateAdjustSpeed_; } 765 766 /** 767 * Set the speed of adjusting connection accept rate. 768 */ setAcceptRateAdjustSpeed(double speed)769 void setAcceptRateAdjustSpeed(double speed) { 770 CHECK(configMutable()); 771 acceptRateAdjustSpeed_ = speed; 772 } 773 774 /** 775 * Enable/Disable TOS reflection on the server socket 776 */ setTosReflect(bool enable)777 void setTosReflect(bool enable) { tosReflect_ = enable; } 778 779 /** 780 * Get TOS reflection setting for the server socket 781 */ getTosReflect()782 bool getTosReflect() const override { return tosReflect_; } 783 784 /** 785 * Set default TOS for listener/accepted connections 786 */ setListenerTos(uint32_t tos)787 void setListenerTos(uint32_t tos) { listenerTos_ = tos; } 788 789 /** 790 * Get default TOS for listener socket 791 */ getListenerTos()792 uint32_t getListenerTos() const override { return listenerTos_; } 793 794 /** 795 * Get the number of connections dropped by the AsyncServerSocket 796 */ 797 uint64_t getNumDroppedConnections() const override; 798 799 /** 800 * Clear all the workers. 801 */ clearWorkers()802 void clearWorkers() { ioThreadPool_->join(); } 803 804 /** 805 * Set whether to stop io workers when stopListening() is called (we do stop 806 * them by default). 807 */ setStopWorkersOnStopListening(bool stopWorkers)808 void setStopWorkersOnStopListening(bool stopWorkers) { 809 CHECK(configMutable()); 810 stopWorkersOnStopListening_ = stopWorkers; 811 } 812 813 /** 814 * Get whether to stop io workers when stopListening() is called. 815 */ getStopWorkersOnStopListening()816 bool getStopWorkersOnStopListening() const { 817 return stopWorkersOnStopListening_; 818 } 819 820 /** 821 * If stopWorkersOnStopListening is disabled, then enabling 822 * leakOutstandingRequestsWhenServerStops permits thriftServer->serve() to 823 * return before all outstanding requests are joined. 824 */ leakOutstandingRequestsWhenServerStops(bool leak)825 void leakOutstandingRequestsWhenServerStops(bool leak) { 826 CHECK(configMutable()); 827 joinRequestsWhenServerStops_ = !leak; 828 } 829 830 /** 831 * Call this to complete initialization 832 */ 833 void setup(); 834 835 /** 836 * Create and start the default thread manager unless it already exists. 837 */ 838 void setupThreadManager(); 839 840 /** 841 * Kill the workers and wait for listeners to quit 842 */ 843 void cleanUp(); 844 845 /** 846 * Preferably use this method in order to start ThriftServer created for 847 * DuplexChannel instead of the serve() method. 848 */ 849 void startDuplex(); 850 851 /** 852 * This method should be used to cleanly stop a ThriftServer created for 853 * DuplexChannel before disposing the ThriftServer. The caller should pass in 854 * a shared_ptr to this ThriftServer since the ThriftServer does not have a 855 * way of getting that (does not inherit from enable_shared_from_this) 856 */ 857 void stopDuplex(std::shared_ptr<ThriftServer> thisServer); 858 859 /** 860 * One stop solution: 861 * 862 * starts worker threads, enters accept loop; when 863 * the accept loop exits, shuts down and joins workers. 864 */ 865 void serve() override; 866 867 /** 868 * Call this to stop the server, if started by serve() 869 * 870 * This (asynchronously) causes the main serve() function to stop listening 871 * for new connections, close existing connections, shut down the worker 872 * threads, and then return. 873 * 874 * NOTE: that this function may not be safe to call multiple times (such as 875 * from a signal handler) because a previous call may initiate a sequence of 876 * events leading to the destruction of this object. 877 * Instead you should use StopController (see getStopController()) which lets 878 * you guard against destruction (by way of folly::PrimaryPtr). 879 */ 880 void stop() override; 881 882 using StopController = ThriftServerStopController; 883 884 private: 885 folly::PrimaryPtr<StopController> stopController_{ 886 std::unique_ptr<StopController>{}}; 887 888 public: getStopController()889 folly::PrimaryPtrRef<StopController> getStopController() { 890 return stopController_.ref(); 891 } 892 893 /** 894 * Call this to stop listening on the server port. 895 * 896 * This causes the main serve() function to stop listening for new 897 * connections while still allows the worker threads to process 898 * existing connections. stop() still needs to be called to clear 899 * up the worker threads. 900 */ 901 void stopListening() override; 902 903 // client side duplex getDuplexServerChannel()904 std::shared_ptr<HeaderServerChannel> getDuplexServerChannel() { 905 return serverChannel_; 906 } 907 908 // server side duplex isDuplex()909 bool isDuplex() { return isDuplex_; } 910 911 std::vector<std::unique_ptr<TransportRoutingHandler>> const* getRoutingHandlers()912 getRoutingHandlers() const { 913 return &routingHandlers_; 914 } 915 addRoutingHandler(std::unique_ptr<TransportRoutingHandler> routingHandler)916 void addRoutingHandler( 917 std::unique_ptr<TransportRoutingHandler> routingHandler) { 918 routingHandlers_.push_back(std::move(routingHandler)); 919 } 920 clearRoutingHandlers()921 void clearRoutingHandlers() { routingHandlers_.clear(); } 922 setDuplex(bool duplex)923 void setDuplex(bool duplex) { 924 // setDuplex may only be called on the server side. 925 // serverChannel_ must be nullptr in this case 926 CHECK(serverChannel_ == nullptr); 927 CHECK(configMutable()); 928 isDuplex_ = duplex; 929 } 930 931 /** 932 * Returns a reference to the processor that is used by custom transports 933 */ getThriftProcessor()934 apache::thrift::ThriftProcessor* getThriftProcessor() { 935 return thriftProcessor_.get(); 936 } 937 getSockets()938 const std::vector<std::shared_ptr<folly::AsyncServerSocket>> getSockets() 939 const { 940 std::vector<std::shared_ptr<folly::AsyncServerSocket>> serverSockets; 941 for (auto& socket : ServerBootstrap::getSockets()) { 942 serverSockets.push_back( 943 std::dynamic_pointer_cast<folly::AsyncServerSocket>(socket)); 944 } 945 return serverSockets; 946 } 947 948 /** 949 * Sets an explicit AsyncProcessorFactory and sets the ThriftProcessor 950 * to use for custom transports 951 */ 952 virtual void setProcessorFactory( 953 std::shared_ptr<AsyncProcessorFactory> pFac) override; 954 955 /** 956 * Returns an AsyncProcessorFactory that wraps the user-provided service and 957 * additionally handles Thrift-internal methods as well (such as the 958 * monitoring interface). 959 * 960 * This is the factory that all transports should use to handle requests. 961 * 962 * Logically, this is an apache::thrift::MultiplexAsyncProcessorFactory with 963 * the following composition: 964 * 965 * ┌────────────────────────┐ 966 * │ User Service │ 967 * │ (setProcessorFactory) │ │ 968 * └────────────────────────┘ │ 969 * │ 970 * ┌────────────────────────┐ │ 971 * │ Status Interface │ │ 972 * │ (setStatusInterface) │ │ 973 * └────────────────────────┘ │ 974 * │ Method 975 * ┌────────────────────────┐ │ precedence 976 * │ Monitoring Interface │ │ 977 * │(setMonitoringInterface)│ │ 978 * └────────────────────────┘ │ 979 * │ 980 * ┌────────────────────────┐ │ 981 * │ Control Interface │ ▼ 982 * │ (setControlInterface) │ 983 * └────────────────────────┘ 984 */ getDecoratedProcessorFactory()985 AsyncProcessorFactory& getDecoratedProcessorFactory() const { 986 CHECK(decoratedProcessorFactory_) 987 << "Server must be set up before calling this method"; 988 return *decoratedProcessorFactory_; 989 } 990 991 /** 992 * Returns an AsyncProcessor from getDecoratedProcessorFactory() without any 993 * application-specific event handlers installed on the underlying processors. 994 * This is useful, for example, in InterfaceKind::MONITORING where 995 * application-specific checks (such as ACL checks) should be bypassed. 996 */ 997 std::unique_ptr<AsyncProcessor> getDecoratedProcessorWithoutEventHandlers() 998 const; 999 1000 /** 1001 * A struct containing all "extra" internal interfaces that the service 1002 * multiplexes behind the main user-defined interface. 1003 * 1004 * See ThriftServer::getDecoratedProcessorFactory. 1005 */ 1006 struct ExtraInterfaces { 1007 // See ThriftServer::setMonitoringInterface. 1008 std::shared_ptr<MonitoringServerInterface> monitoring; 1009 // See ThriftServer::setStatusInterface. 1010 std::shared_ptr<StatusServerInterface> status; 1011 // See ThriftServer::setControlInterface 1012 std::shared_ptr<ControlServerInterface> control; 1013 }; 1014 1015 // ThriftServer by defaults uses a global ShutdownSocketSet, so all socket's 1016 // FDs are registered there. But in some tests you might want to simulate 2 1017 // ThriftServer running in different processes, so their ShutdownSocketSet are 1018 // different. In that case server should have their own SSS each so shutting 1019 // down FD from one doesn't interfere with shutting down sockets for the 1020 // other. 1021 void replaceShutdownSocketSet( 1022 const std::shared_ptr<folly::ShutdownSocketSet>& newSSS); 1023 1024 static folly::observer::Observer<std::list<std::string>> 1025 defaultNextProtocols(); 1026 getQuickExitOnShutdownTimeout()1027 bool getQuickExitOnShutdownTimeout() const { 1028 return quickExitOnShutdownTimeout_; 1029 } 1030 setQuickExitOnShutdownTimeout(bool quickExitOnShutdownTimeout)1031 void setQuickExitOnShutdownTimeout(bool quickExitOnShutdownTimeout) { 1032 quickExitOnShutdownTimeout_ = quickExitOnShutdownTimeout; 1033 } 1034 1035 static folly::observer::Observer<bool> alpnAllowMismatch(); 1036 1037 /** 1038 * For each request debug stub, a snapshot information can be constructed to 1039 * persist some transitent states about the corresponding request. 1040 */ 1041 class RequestSnapshot { 1042 public: RequestSnapshot(const RequestsRegistry::DebugStub & stub)1043 explicit RequestSnapshot(const RequestsRegistry::DebugStub& stub) 1044 : methodName_(stub.getMethodName()), 1045 creationTimestamp_(stub.getTimestamp()), 1046 finishedTimestamp_(stub.getFinished()), 1047 protoId_(stub.getProtoId()), 1048 peerAddress_(*stub.getPeerAddress()), 1049 localAddress_(*stub.getLocalAddress()), 1050 rootRequestContextId_(stub.getRootRequestContextId()), 1051 reqId_(RequestsRegistry::getRequestId(rootRequestContextId_)), 1052 reqDebugLog_(collectRequestDebugLog(stub)) { 1053 auto requestPayload = rocket::unpack<RequestPayload>(stub.clonePayload()); 1054 payload_ = std::move(*requestPayload->payload); 1055 auto& metadata = requestPayload->metadata; 1056 if (metadata.otherMetadata_ref()) { 1057 headers_ = std::move(*requestPayload->metadata.otherMetadata_ref()); 1058 } 1059 clientId_ = metadata.clientId_ref().to_optional(); 1060 serviceTraceMeta_ = metadata.serviceTraceMeta_ref().to_optional(); 1061 auto req = stub.getRequest(); 1062 DCHECK( 1063 req != nullptr || finishedTimestamp_.time_since_epoch().count() != 0); 1064 startedProcessing_ = req == nullptr ? true : stub.getStartedProcessing(); 1065 } 1066 getMethodName()1067 const std::string& getMethodName() const { return methodName_; } 1068 getCreationTimestamp()1069 std::chrono::steady_clock::time_point getCreationTimestamp() const { 1070 return creationTimestamp_; 1071 } 1072 getFinishedTimestamp()1073 std::chrono::steady_clock::time_point getFinishedTimestamp() const { 1074 return finishedTimestamp_; 1075 } 1076 getRootRequestContextId()1077 intptr_t getRootRequestContextId() const { return rootRequestContextId_; } 1078 getRequestId()1079 const std::string& getRequestId() const { return reqId_; } 1080 getStartedProcessing()1081 bool getStartedProcessing() const { return startedProcessing_; } 1082 1083 /** 1084 * Returns empty IOBuff if payload is not present. 1085 */ getPayload()1086 const folly::IOBuf& getPayload() const { return payload_; } 1087 getHeaders()1088 const transport::THeader::StringToStringMap& getHeaders() const { 1089 return headers_; 1090 } 1091 getProtoId()1092 protocol::PROTOCOL_TYPES getProtoId() const { return protoId_; } 1093 getLocalAddress()1094 const folly::SocketAddress& getLocalAddress() const { 1095 return localAddress_; 1096 } getPeerAddress()1097 const folly::SocketAddress& getPeerAddress() const { return peerAddress_; } 1098 getDebugLog()1099 const std::vector<std::string>& getDebugLog() const { return reqDebugLog_; } 1100 clientId()1101 const auto& clientId() const { return clientId_; } clientId()1102 auto& clientId() { return clientId_; } 1103 serviceTraceMeta()1104 const auto& serviceTraceMeta() const { return serviceTraceMeta_; } serviceTraceMeta()1105 auto& serviceTraceMeta() { return serviceTraceMeta_; } 1106 1107 private: 1108 const std::string methodName_; 1109 const std::chrono::steady_clock::time_point creationTimestamp_; 1110 const std::chrono::steady_clock::time_point finishedTimestamp_; 1111 const protocol::PROTOCOL_TYPES protoId_; 1112 folly::IOBuf payload_; 1113 transport::THeader::StringToStringMap headers_; 1114 std::optional<std::string> clientId_; 1115 std::optional<std::string> serviceTraceMeta_; 1116 folly::SocketAddress peerAddress_; 1117 folly::SocketAddress localAddress_; 1118 intptr_t rootRequestContextId_; 1119 const std::string reqId_; 1120 const std::vector<std::string> reqDebugLog_; 1121 bool startedProcessing_; 1122 }; 1123 1124 struct ConnectionSnapshot { 1125 size_t numActiveRequests{0}; 1126 size_t numPendingWrites{0}; 1127 std::chrono::steady_clock::time_point creationTime; 1128 }; 1129 using RequestSnapshots = std::vector<RequestSnapshot>; 1130 using ConnectionSnapshots = 1131 std::unordered_map<folly::SocketAddress, ConnectionSnapshot>; 1132 struct ServerSnapshot { 1133 RecentRequestCounter::Values recentCounters; 1134 RequestSnapshots requests; 1135 ConnectionSnapshots connections; 1136 }; 1137 struct SnapshotOptions { 1138 std::chrono::microseconds connectionsAgeMax; 1139 }; getServerSnapshot()1140 folly::SemiFuture<ServerSnapshot> getServerSnapshot() { 1141 return getServerSnapshot(SnapshotOptions{}); 1142 } 1143 folly::SemiFuture<ServerSnapshot> getServerSnapshot( 1144 const SnapshotOptions& options); 1145 1146 /** 1147 * If shutdown does not complete within the configured worker join timeout, 1148 * then we schedule a task to dump the server's state to disk for 1149 * investigation. 1150 * 1151 * The implementor of the dumping logic should provide the the task as well 1152 * as an appropriate timeout -- we do not want to indefinitely block shutdown 1153 * in case the task deadlocks. 1154 */ 1155 struct DumpSnapshotOnLongShutdownResult { 1156 folly::SemiFuture<folly::Unit> task; 1157 std::chrono::milliseconds timeout; 1158 }; 1159 1160 enum class UnimplementedExtraInterfacesResult { 1161 /** 1162 * The method is completely unrecognized by the service. 1163 */ 1164 UNRECOGNIZED, 1165 /** 1166 * Extra interfaces are implemented directly by the service. 1167 */ 1168 IMPLEMENTED, 1169 /** 1170 * Extra interfaces are left unimplemented but recognized by the service. 1171 */ 1172 UNIMPLEMENTED, 1173 }; 1174 }; 1175 1176 template <typename AcceptorClass, typename SharedSSLContextManagerClass> 1177 class ThriftAcceptorFactory : public wangle::AcceptorFactorySharedSSLContext { 1178 public: ThriftAcceptorFactory(ThriftServer * server)1179 ThriftAcceptorFactory(ThriftServer* server) : server_(server) {} 1180 1181 std::shared_ptr<wangle::SharedSSLContextManager> initSharedSSLContextManager()1182 initSharedSSLContextManager() { 1183 if constexpr (!std::is_same<SharedSSLContextManagerClass, void>::value) { 1184 sharedSSLContextManager_ = std::make_shared<SharedSSLContextManagerClass>( 1185 server_->getServerSocketConfig()); 1186 } 1187 return sharedSSLContextManager_; 1188 } 1189 newAcceptor(folly::EventBase * eventBase)1190 std::shared_ptr<wangle::Acceptor> newAcceptor(folly::EventBase* eventBase) { 1191 if (!sharedSSLContextManager_) { 1192 return AcceptorClass::create(server_, nullptr, eventBase); 1193 } 1194 auto acceptor = AcceptorClass::create( 1195 server_, 1196 nullptr, 1197 eventBase, 1198 sharedSSLContextManager_->getCertManager(), 1199 sharedSSLContextManager_->getContextManager(), 1200 sharedSSLContextManager_->getFizzContext()); 1201 sharedSSLContextManager_->addAcceptor(acceptor); 1202 return acceptor; 1203 } 1204 1205 protected: 1206 ThriftServer* server_; 1207 }; 1208 using DefaultThriftAcceptorFactory = ThriftAcceptorFactory<Cpp2Worker, void>; 1209 1210 using DefaultThriftAcceptorFactorySharedSSLContext = ThriftAcceptorFactory< 1211 Cpp2Worker, 1212 wangle::SharedSSLContextManagerImpl<wangle::FizzConfigUtil>>; 1213 1214 namespace detail { 1215 1216 THRIFT_PLUGGABLE_FUNC_DECLARE( 1217 apache::thrift::ThriftServer::DumpSnapshotOnLongShutdownResult, 1218 dumpSnapshotOnLongShutdown); 1219 1220 THRIFT_PLUGGABLE_FUNC_DECLARE( 1221 apache::thrift::ThriftServer::ExtraInterfaces, 1222 createDefaultExtraInterfaces); 1223 1224 THRIFT_PLUGGABLE_FUNC_DECLARE( 1225 ThriftServer::UnimplementedExtraInterfacesResult, 1226 serviceHasUnimplementedExtraInterfaces, 1227 AsyncProcessorFactory& service); 1228 1229 } // namespace detail 1230 1231 } // namespace thrift 1232 } // namespace apache 1233 1234 #endif // #ifndef THRIFT_SERVER_H_ 1235