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_HANDSHAKER_HANDSHAKER_H 20 #define GRPC_SRC_CORE_HANDSHAKER_HANDSHAKER_H 21 22 #include <grpc/event_engine/event_engine.h> 23 #include <grpc/slice.h> 24 #include <grpc/support/port_platform.h> 25 #include <stddef.h> 26 27 #include <memory> 28 29 #include "absl/base/thread_annotations.h" 30 #include "absl/container/inlined_vector.h" 31 #include "src/core/lib/channel/channel_args.h" 32 #include "src/core/lib/iomgr/closure.h" 33 #include "src/core/lib/iomgr/endpoint.h" 34 #include "src/core/lib/iomgr/error.h" 35 #include "src/core/lib/iomgr/tcp_server.h" 36 #include "src/core/lib/slice/slice_buffer.h" 37 #include "src/core/util/orphanable.h" 38 #include "src/core/util/ref_counted.h" 39 #include "src/core/util/ref_counted_ptr.h" 40 #include "src/core/util/sync.h" 41 #include "src/core/util/time.h" 42 43 namespace grpc_core { 44 45 /// Handshakers are used to perform initial handshakes on a connection 46 /// before the client sends the initial request. Some examples of what 47 /// a handshaker can be used for includes support for HTTP CONNECT on 48 /// the client side and various types of security initialization. 49 /// 50 /// In general, handshakers should be used via a handshake manager. 51 52 /// Arguments passed through handshakers and back to the caller. 53 /// 54 /// For handshakers, all members are input/output parameters; for 55 /// example, a handshaker may read from or write to \a endpoint and 56 /// then later replace it with a wrapped endpoint. Similarly, a 57 /// handshaker may modify \a args. 58 /// 59 /// A handshaker takes ownership of the members when this struct is 60 /// passed to DoHandshake(). It passes ownership back to the caller 61 /// when it invokes on_handshake_done. 62 struct HandshakerArgs { 63 OrphanablePtr<grpc_endpoint> endpoint; 64 ChannelArgs args; 65 // Any bytes read from the endpoint that are not consumed by the 66 // handshaker must be passed back via this buffer. 67 SliceBuffer read_buffer; 68 // A handshaker may set this to true before invoking on_handshake_done 69 // to indicate that subsequent handshakers should be skipped. 70 bool exit_early = false; 71 // EventEngine to use for async work. 72 // (This is just a convenience to avoid digging it out of args.) 73 grpc_event_engine::experimental::EventEngine* event_engine = nullptr; 74 // Deadline associated with the handshake. 75 // TODO(anramach): Move this out of handshake args after EventEngine 76 // is the default. 77 Timestamp deadline; 78 // TODO(roth): Make this go away somehow as part of the EventEngine 79 // migration? 80 grpc_tcp_server_acceptor* acceptor = nullptr; 81 }; 82 83 /// 84 /// Handshaker 85 /// 86 87 class Handshaker : public RefCounted<Handshaker> { 88 public: 89 ~Handshaker() override = default; 90 virtual absl::string_view name() const = 0; 91 virtual void DoHandshake( 92 HandshakerArgs* args, 93 absl::AnyInvocable<void(absl::Status)> on_handshake_done) = 0; 94 virtual void Shutdown(absl::Status error) = 0; 95 96 protected: 97 // Helper function to safely invoke on_handshake_done asynchronously. 98 // 99 // Note that on_handshake_done may complete in another thread as soon 100 // as this method returns, so the handshaker object may be destroyed 101 // by the callback unless the caller of this method is holding its own 102 // ref to the handshaker. 103 static void InvokeOnHandshakeDone( 104 HandshakerArgs* args, 105 absl::AnyInvocable<void(absl::Status)> on_handshake_done, 106 absl::Status status); 107 }; 108 109 // 110 // HandshakeManager 111 // 112 113 class HandshakeManager : public RefCounted<HandshakeManager> { 114 public: 115 HandshakeManager(); 116 117 /// Adds a handshaker to the handshake manager. 118 /// Takes ownership of \a handshaker. 119 void Add(RefCountedPtr<Handshaker> handshaker) ABSL_LOCKS_EXCLUDED(mu_); 120 121 /// Invokes handshakers in the order they were added. 122 /// Takes ownership of \a endpoint, and then passes that ownership to 123 /// the \a on_handshake_done callback. 124 /// Does NOT take ownership of \a channel_args. Instead, makes a copy before 125 /// invoking the first handshaker. 126 /// \a acceptor will be nullptr for client-side handshakers. 127 /// 128 /// When done, invokes \a on_handshake_done with a HandshakerArgs 129 /// object as its argument. If the callback is invoked with error != 130 /// absl::OkStatus(), then handshaking failed and the handshaker has done 131 /// the necessary clean-up. Otherwise, the callback takes ownership of 132 /// the arguments. 133 void DoHandshake(OrphanablePtr<grpc_endpoint> endpoint, 134 const ChannelArgs& channel_args, Timestamp deadline, 135 grpc_tcp_server_acceptor* acceptor, 136 absl::AnyInvocable<void(absl::StatusOr<HandshakerArgs*>)> 137 on_handshake_done) ABSL_LOCKS_EXCLUDED(mu_); 138 139 /// Shuts down the handshake manager (e.g., to clean up when the operation is 140 /// aborted in the middle). 141 void Shutdown(absl::Status error) ABSL_LOCKS_EXCLUDED(mu_); 142 143 private: 144 // A function used as the handshaker-done callback when chaining 145 // handshakers together. 146 void CallNextHandshakerLocked(absl::Status error) 147 ABSL_EXCLUSIVE_LOCKS_REQUIRED(mu_); 148 149 static const size_t kHandshakerListInlineSize = 2; 150 151 Mutex mu_; 152 bool is_shutdown_ ABSL_GUARDED_BY(mu_) = false; 153 // The index of the handshaker to invoke next and closure to invoke it. 154 size_t index_ ABSL_GUARDED_BY(mu_) = 0; 155 // An array of handshakers added via Add(). 156 absl::InlinedVector<RefCountedPtr<Handshaker>, kHandshakerListInlineSize> 157 handshakers_ ABSL_GUARDED_BY(mu_); 158 // Handshaker args. 159 HandshakerArgs args_ ABSL_GUARDED_BY(mu_); 160 // The final callback to invoke after the last handshaker. 161 absl::AnyInvocable<void(absl::StatusOr<HandshakerArgs*>)> on_handshake_done_ 162 ABSL_GUARDED_BY(mu_); 163 // Deadline timer across all handshakers. 164 grpc_event_engine::experimental::EventEngine::TaskHandle 165 deadline_timer_handle_ ABSL_GUARDED_BY(mu_); 166 }; 167 168 } // namespace grpc_core 169 170 #endif // GRPC_SRC_CORE_HANDSHAKER_HANDSHAKER_H 171