/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once #include #include #include #include #include #include #include #include #include #include namespace apache { namespace thrift { /** * HTTP/2 implementation of ClientConnectionIf. * * Static methods are provided to create HTTP1 or HTTP2 connections. * These methods optionally take a host and url parameter. Some * servers will only work with specific values for these. If these * parameters are not set, the implementation will use the most * efficient possible setting for these values. * * Host and url values can only be specified at connection creation * time - i.e., you cannot use different values (for url) for * different RPCs. * * This class maintains a nested Proxygen connection * (HTTPUpstreamSession). If the Proxygen connection dies, we do not * attempt to recreate it, instead we pass this error to the callers. * In the future, we may change this (for now callers have to create a * new H2ClientConnection object and discard the old one). */ class H2ClientConnection : public ClientConnectionIf, public proxygen::HTTPSession::InfoCallback { public: struct FlowControlSettings { private: // Stream and initial receive control window are 10MB static constexpr size_t kStreamWindow = 10U * (1U << 20); // Session (i.e connection) window is larger at 15MB static constexpr size_t kSessionWindow = 15U * (1U << 20); public: FlowControlSettings() : initialReceiveWindow(kStreamWindow), receiveStreamWindowSize(kStreamWindow), receiveSessionWindowSize(kSessionWindow) {} size_t initialReceiveWindow; size_t receiveStreamWindowSize; size_t receiveSessionWindowSize; }; static std::unique_ptr newHTTP2Connection( folly::AsyncTransport::UniquePtr transport, FlowControlSettings flowControlSettings = FlowControlSettings()); virtual ~H2ClientConnection() override; H2ClientConnection(const H2ClientConnection&) = delete; H2ClientConnection& operator=(const H2ClientConnection&) = delete; std::shared_ptr getChannel() override; void setMaxPendingRequests(uint32_t num) override; void setCloseCallback(ThriftClient* client, CloseCallback* cb) override; folly::EventBase* getEventBase() const override; // Returns a new transaction that is bound to the channel parameter. // Throws TTransportException if unable to create a new transaction. proxygen::HTTPTransaction* newTransaction(H2Channel* channel); bool isStable(); void setIsStable(); folly::AsyncTransport* getTransport() override; bool good() override; ClientChannel::SaturationStatus getSaturationStatus() override; void attachEventBase(folly::EventBase* evb) override; void detachEventBase() override; bool isDetachable() override; uint32_t getTimeout() override; void setTimeout(uint32_t ms) override; void closeNow() override; CLIENT_TYPE getClientType() override; // HTTPSession::InfoCallback method void onDestroy(const proxygen::HTTPSessionBase&) override; private: H2ClientConnection( folly::AsyncTransport::UniquePtr transport, std::unique_ptr codec, FlowControlSettings flowControlSettings); proxygen::HTTPUpstreamSession* httpSession_; folly::EventBase* evb_{nullptr}; std::chrono::milliseconds timeout_{ apache::thrift::ThriftClientCallback::kDefaultTimeout}; // A map of all registered CloseCallback objects keyed by the // ThriftClient objects that registered the callback. std::unordered_map closeCallbacks_; }; } // namespace thrift } // namespace apache