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 #pragma once 18 19 #include <folly/SocketAddress.h> 20 #include <folly/futures/Future.h> 21 #include <folly/io/SocketOptionMap.h> 22 #include <folly/io/async/AsyncSSLSocket.h> 23 #include <folly/io/async/AsyncSocket.h> 24 #include <folly/ssl/SSLSession.h> 25 #include <wangle/channel/Pipeline.h> 26 #include <memory> 27 28 namespace wangle { 29 30 class SSLSessionEstablishedCallback { 31 public: 32 virtual ~SSLSessionEstablishedCallback() = default; 33 // notified when a non-reused SSLSession is established. 34 virtual void onEstablished( 35 std::shared_ptr<folly::ssl::SSLSession> session) = 0; 36 }; 37 38 class ClientBootstrapSocketOptions { 39 public: setV4OptionMap(const folly::SocketOptionMap & options)40 ClientBootstrapSocketOptions& setV4OptionMap( 41 const folly::SocketOptionMap& options) { 42 v4_ = options; 43 return *this; 44 } getV4OptionMap()45 folly::SocketOptionMap const& getV4OptionMap() const { 46 return v4_; 47 } setV6OptionMap(const folly::SocketOptionMap & options)48 ClientBootstrapSocketOptions& setV6OptionMap( 49 const folly::SocketOptionMap& options) { 50 v6_ = options; 51 return *this; 52 } getV6OptionMap()53 folly::SocketOptionMap const& getV6OptionMap() const { 54 return v6_; 55 } 56 57 private: 58 folly::SocketOptionMap v4_; 59 folly::SocketOptionMap v6_; 60 }; 61 62 using SSLSessionEstablishedCallbackUniquePtr = 63 std::unique_ptr<SSLSessionEstablishedCallback>; 64 65 /* 66 * A wrapper template around Pipeline and AsyncSocket or SPDY/HTTP/2 session to 67 * match ServerBootstrap so BroadcastPool can work with either option 68 */ 69 template <typename P = DefaultPipeline> 70 class BaseClientBootstrap { 71 public: 72 using Ptr = std::unique_ptr<BaseClientBootstrap>; BaseClientBootstrap()73 BaseClientBootstrap() {} 74 75 virtual ~BaseClientBootstrap() = default; 76 pipelineFactory(std::shared_ptr<PipelineFactory<P>> factory)77 BaseClientBootstrap<P>* pipelineFactory( 78 std::shared_ptr<PipelineFactory<P>> factory) noexcept { 79 pipelineFactory_ = factory; 80 return this; 81 } 82 getPipeline()83 P* getPipeline() { 84 return pipeline_.get(); 85 } 86 87 virtual folly::Future<P*> connect( 88 const folly::SocketAddress& address, 89 std::chrono::milliseconds timeout = std::chrono::milliseconds(0)) = 0; 90 sslContext(folly::SSLContextPtr sslContext)91 BaseClientBootstrap* sslContext(folly::SSLContextPtr sslContext) { 92 sslContext_ = sslContext; 93 return this; 94 } 95 sslSession(std::shared_ptr<folly::ssl::SSLSession> sslSession)96 BaseClientBootstrap* sslSession( 97 std::shared_ptr<folly::ssl::SSLSession> sslSession) { 98 sslSession_ = sslSession; 99 return this; 100 } 101 serverName(const std::string & sni)102 BaseClientBootstrap* serverName(const std::string& sni) { 103 sni_ = sni; 104 return this; 105 } 106 sslSessionEstablishedCallback(SSLSessionEstablishedCallbackUniquePtr sslSessionEstablishedCallback)107 BaseClientBootstrap* sslSessionEstablishedCallback( 108 SSLSessionEstablishedCallbackUniquePtr sslSessionEstablishedCallback) { 109 sslSessionEstablishedCallback_ = std::move(sslSessionEstablishedCallback); 110 return this; 111 } 112 deferSecurityNegotiation(bool deferSecurityNegotiation)113 BaseClientBootstrap* deferSecurityNegotiation(bool deferSecurityNegotiation) { 114 deferSecurityNegotiation_ = deferSecurityNegotiation; 115 return this; 116 } 117 setPipeline(const typename P::Ptr & pipeline)118 void setPipeline(const typename P::Ptr& pipeline) { 119 pipeline_ = pipeline; 120 } 121 makePipeline(std::shared_ptr<folly::AsyncTransport> socket)122 virtual void makePipeline(std::shared_ptr<folly::AsyncTransport> socket) { 123 pipeline_ = pipelineFactory_->newPipeline(socket); 124 } 125 setSocketOptions(const ClientBootstrapSocketOptions & sockOpts)126 void setSocketOptions(const ClientBootstrapSocketOptions& sockOpts) { 127 socketOptions_ = sockOpts; 128 } 129 130 protected: getSocketOptions(sa_family_t ipFamily)131 const folly::SocketOptionMap& getSocketOptions(sa_family_t ipFamily) { 132 if (ipFamily == AF_INET) { 133 return socketOptions_.getV4OptionMap(); 134 } else if (ipFamily == AF_INET6) { 135 return socketOptions_.getV6OptionMap(); 136 } 137 return folly::emptySocketOptionMap; 138 } 139 140 std::shared_ptr<PipelineFactory<P>> pipelineFactory_; 141 typename P::Ptr pipeline_; 142 folly::SSLContextPtr sslContext_; 143 std::shared_ptr<folly::ssl::SSLSession> sslSession_{nullptr}; 144 std::string sni_; 145 bool deferSecurityNegotiation_{false}; 146 SSLSessionEstablishedCallbackUniquePtr sslSessionEstablishedCallback_; 147 ClientBootstrapSocketOptions socketOptions_; 148 }; 149 150 template <typename ClientBootstrap = BaseClientBootstrap<>> 151 class BaseClientBootstrapFactory { 152 public: 153 virtual typename ClientBootstrap::Ptr newClient() = 0; 154 virtual ~BaseClientBootstrapFactory() = default; 155 }; 156 157 } // namespace wangle 158