1 // 2 // 3 // Copyright 2016 gRPC authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // 17 // 18 19 #ifndef GRPC_SRC_CORE_LIB_TRANSPORT_HANDSHAKER_H 20 #define GRPC_SRC_CORE_LIB_TRANSPORT_HANDSHAKER_H 21 22 #include <grpc/support/port_platform.h> 23 24 #include <stddef.h> 25 26 #include <memory> 27 28 #include "absl/base/thread_annotations.h" 29 #include "absl/container/inlined_vector.h" 30 31 #include <grpc/event_engine/event_engine.h> 32 #include <grpc/slice.h> 33 34 #include "src/core/lib/channel/channel_args.h" 35 #include "src/core/lib/gprpp/ref_counted.h" 36 #include "src/core/lib/gprpp/ref_counted_ptr.h" 37 #include "src/core/lib/gprpp/sync.h" 38 #include "src/core/lib/gprpp/time.h" 39 #include "src/core/lib/iomgr/closure.h" 40 #include "src/core/lib/iomgr/endpoint.h" 41 #include "src/core/lib/iomgr/error.h" 42 #include "src/core/lib/iomgr/tcp_server.h" 43 44 namespace grpc_core { 45 46 /// Handshakers are used to perform initial handshakes on a connection 47 /// before the client sends the initial request. Some examples of what 48 /// a handshaker can be used for includes support for HTTP CONNECT on 49 /// the client side and various types of security initialization. 50 /// 51 /// In general, handshakers should be used via a handshake manager. 52 53 /// Arguments passed through handshakers and to the on_handshake_done callback. 54 /// 55 /// For handshakers, all members are input/output parameters; for 56 /// example, a handshaker may read from or write to \a endpoint and 57 /// then later replace it with a wrapped endpoint. Similarly, a 58 /// handshaker may modify \a args. 59 /// 60 /// A handshaker takes ownership of the members while a handshake is in 61 /// progress. Upon failure or shutdown of an in-progress handshaker, 62 /// the handshaker is responsible for destroying the members and setting 63 /// them to NULL before invoking the on_handshake_done callback. 64 /// 65 /// For the on_handshake_done callback, all members are input arguments, 66 /// which the callback takes ownership of. 67 struct HandshakerArgs { 68 grpc_endpoint* endpoint = nullptr; 69 ChannelArgs args; 70 grpc_slice_buffer* read_buffer = nullptr; 71 // A handshaker may set this to true before invoking on_handshake_done 72 // to indicate that subsequent handshakers should be skipped. 73 bool exit_early = false; 74 // User data passed through the handshake manager. Not used by 75 // individual handshakers. 76 void* user_data = nullptr; 77 // Deadline associated with the handshake. 78 // TODO(anramach): Move this out of handshake args after EventEngine 79 // is the default. 80 Timestamp deadline; 81 }; 82 83 /// 84 /// Handshaker 85 /// 86 87 class Handshaker : public RefCounted<Handshaker> { 88 public: 89 ~Handshaker() override = default; 90 virtual void Shutdown(grpc_error_handle why) = 0; 91 virtual void DoHandshake(grpc_tcp_server_acceptor* acceptor, 92 grpc_closure* on_handshake_done, 93 HandshakerArgs* args) = 0; 94 virtual const char* name() const = 0; 95 }; 96 97 // 98 // HandshakeManager 99 // 100 101 class HandshakeManager : public RefCounted<HandshakeManager> { 102 public: 103 HandshakeManager(); 104 ~HandshakeManager() override; 105 106 /// Adds a handshaker to the handshake manager. 107 /// Takes ownership of \a handshaker. 108 void Add(RefCountedPtr<Handshaker> handshaker) ABSL_LOCKS_EXCLUDED(mu_); 109 110 /// Shuts down the handshake manager (e.g., to clean up when the operation is 111 /// aborted in the middle). 112 void Shutdown(grpc_error_handle why) ABSL_LOCKS_EXCLUDED(mu_); 113 114 /// Invokes handshakers in the order they were added. 115 /// Takes ownership of \a endpoint, and then passes that ownership to 116 /// the \a on_handshake_done callback. 117 /// Does NOT take ownership of \a channel_args. Instead, makes a copy before 118 /// invoking the first handshaker. 119 /// \a acceptor will be nullptr for client-side handshakers. 120 /// 121 /// When done, invokes \a on_handshake_done with a HandshakerArgs 122 /// object as its argument. If the callback is invoked with error != 123 /// absl::OkStatus(), then handshaking failed and the handshaker has done 124 /// the necessary clean-up. Otherwise, the callback takes ownership of 125 /// the arguments. 126 void DoHandshake(grpc_endpoint* endpoint, const ChannelArgs& channel_args, 127 Timestamp deadline, grpc_tcp_server_acceptor* acceptor, 128 grpc_iomgr_cb_func on_handshake_done, void* user_data) 129 ABSL_LOCKS_EXCLUDED(mu_); 130 131 private: 132 bool CallNextHandshakerLocked(grpc_error_handle error) 133 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); 134 135 // A function used as the handshaker-done callback when chaining 136 // handshakers together. 137 static void CallNextHandshakerFn(void* arg, grpc_error_handle error) 138 ABSL_LOCKS_EXCLUDED(mu_); 139 140 static const size_t HANDSHAKERS_INIT_SIZE = 2; 141 142 Mutex mu_; 143 bool is_shutdown_ ABSL_GUARDED_BY(mu_) = false; 144 // An array of handshakers added via grpc_handshake_manager_add(). 145 absl::InlinedVector<RefCountedPtr<Handshaker>, HANDSHAKERS_INIT_SIZE> 146 handshakers_ ABSL_GUARDED_BY(mu_); 147 // The index of the handshaker to invoke next and closure to invoke it. 148 size_t index_ ABSL_GUARDED_BY(mu_) = 0; 149 grpc_closure call_next_handshaker_ ABSL_GUARDED_BY(mu_); 150 // The acceptor to call the handshakers with. 151 grpc_tcp_server_acceptor* acceptor_ ABSL_GUARDED_BY(mu_); 152 // The final callback and user_data to invoke after the last handshaker. 153 grpc_closure on_handshake_done_ ABSL_GUARDED_BY(mu_); 154 // Handshaker args. 155 HandshakerArgs args_ ABSL_GUARDED_BY(mu_); 156 // Deadline timer across all handshakers. 157 grpc_event_engine::experimental::EventEngine::TaskHandle 158 deadline_timer_handle_ ABSL_GUARDED_BY(mu_); 159 std::shared_ptr<grpc_event_engine::experimental::EventEngine> event_engine_ 160 ABSL_GUARDED_BY(mu_); 161 }; 162 163 } // namespace grpc_core 164 165 // TODO(arjunroy): These are transitional to account for the new handshaker API 166 // and will eventually be removed entirely. 167 typedef grpc_core::HandshakeManager grpc_handshake_manager; 168 typedef grpc_core::Handshaker grpc_handshaker; 169 void grpc_handshake_manager_add(grpc_handshake_manager* mgr, 170 grpc_handshaker* handshaker); 171 172 #endif // GRPC_SRC_CORE_LIB_TRANSPORT_HANDSHAKER_H 173