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