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_CORE_LIB_CHANNEL_HANDSHAKER_H
20 #define GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include <grpc/impl/codegen/grpc_types.h>
25 
26 #include "src/core/lib/iomgr/closure.h"
27 #include "src/core/lib/iomgr/endpoint.h"
28 #include "src/core/lib/iomgr/exec_ctx.h"
29 #include "src/core/lib/iomgr/tcp_server.h"
30 
31 /// Handshakers are used to perform initial handshakes on a connection
32 /// before the client sends the initial request.  Some examples of what
33 /// a handshaker can be used for includes support for HTTP CONNECT on
34 /// the client side and various types of security initialization.
35 ///
36 /// In general, handshakers should be used via a handshake manager.
37 
38 ///
39 /// grpc_handshaker
40 ///
41 
42 typedef struct grpc_handshaker grpc_handshaker;
43 
44 /// Arguments passed through handshakers and to the on_handshake_done callback.
45 ///
46 /// For handshakers, all members are input/output parameters; for
47 /// example, a handshaker may read from or write to \a endpoint and
48 /// then later replace it with a wrapped endpoint.  Similarly, a
49 /// handshaker may modify \a args.
50 ///
51 /// A handshaker takes ownership of the members while a handshake is in
52 /// progress.  Upon failure or shutdown of an in-progress handshaker,
53 /// the handshaker is responsible for destroying the members and setting
54 /// them to NULL before invoking the on_handshake_done callback.
55 ///
56 /// For the on_handshake_done callback, all members are input arguments,
57 /// which the callback takes ownership of.
58 typedef struct {
59   grpc_pollset_set* interested_parties;
60   grpc_endpoint* endpoint;
61   grpc_channel_args* args;
62   grpc_slice_buffer* read_buffer;
63   // A handshaker may set this to true before invoking on_handshake_done
64   // to indicate that subsequent handshakers should be skipped.
65   bool exit_early;
66   // User data passed through the handshake manager.  Not used by
67   // individual handshakers.
68   void* user_data;
69 } grpc_handshaker_args;
70 
71 typedef struct {
72   /// Destroys the handshaker.
73   void (*destroy)(grpc_handshaker* handshaker);
74 
75   /// Shuts down the handshaker (e.g., to clean up when the operation is
76   /// aborted in the middle).
77   void (*shutdown)(grpc_handshaker* handshaker, grpc_error* why);
78 
79   /// Performs handshaking, modifying \a args as needed (e.g., to
80   /// replace \a endpoint with a wrapped endpoint).
81   /// When finished, invokes \a on_handshake_done.
82   /// \a acceptor will be NULL for client-side handshakers.
83   void (*do_handshake)(grpc_handshaker* handshaker,
84                        grpc_tcp_server_acceptor* acceptor,
85                        grpc_closure* on_handshake_done,
86                        grpc_handshaker_args* args);
87 
88   /// The name of the handshaker, for debugging purposes.
89   const char* name;
90 } grpc_handshaker_vtable;
91 
92 /// Base struct.  To subclass, make this the first member of the
93 /// implementation struct.
94 struct grpc_handshaker {
95   const grpc_handshaker_vtable* vtable;
96 };
97 
98 /// Called by concrete implementations to initialize the base struct.
99 void grpc_handshaker_init(const grpc_handshaker_vtable* vtable,
100                           grpc_handshaker* handshaker);
101 
102 void grpc_handshaker_destroy(grpc_handshaker* handshaker);
103 void grpc_handshaker_shutdown(grpc_handshaker* handshaker, grpc_error* why);
104 void grpc_handshaker_do_handshake(grpc_handshaker* handshaker,
105                                   grpc_tcp_server_acceptor* acceptor,
106                                   grpc_closure* on_handshake_done,
107                                   grpc_handshaker_args* args);
108 const char* grpc_handshaker_name(grpc_handshaker* handshaker);
109 
110 ///
111 /// grpc_handshake_manager
112 ///
113 
114 typedef struct grpc_handshake_manager grpc_handshake_manager;
115 
116 /// Creates a new handshake manager.  Caller takes ownership.
117 grpc_handshake_manager* grpc_handshake_manager_create();
118 
119 /// Adds a handshaker to the handshake manager.
120 /// Takes ownership of \a handshaker.
121 void grpc_handshake_manager_add(grpc_handshake_manager* mgr,
122                                 grpc_handshaker* handshaker);
123 
124 /// Destroys the handshake manager.
125 void grpc_handshake_manager_destroy(grpc_handshake_manager* mgr);
126 
127 /// Shuts down the handshake manager (e.g., to clean up when the operation is
128 /// aborted in the middle).
129 /// The caller must still call grpc_handshake_manager_destroy() after
130 /// calling this function.
131 void grpc_handshake_manager_shutdown(grpc_handshake_manager* mgr,
132                                      grpc_error* why);
133 
134 /// Invokes handshakers in the order they were added.
135 /// \a interested_parties may be non-nullptr to provide a pollset_set that
136 /// may be used during handshaking. Ownership is not taken.
137 /// Takes ownership of \a endpoint, and then passes that ownership to
138 /// the \a on_handshake_done callback.
139 /// Does NOT take ownership of \a channel_args.  Instead, makes a copy before
140 /// invoking the first handshaker.
141 /// \a acceptor will be nullptr for client-side handshakers.
142 ///
143 /// When done, invokes \a on_handshake_done with a grpc_handshaker_args
144 /// object as its argument.  If the callback is invoked with error !=
145 /// GRPC_ERROR_NONE, then handshaking failed and the handshaker has done
146 /// the necessary clean-up.  Otherwise, the callback takes ownership of
147 /// the arguments.
148 void grpc_handshake_manager_do_handshake(
149     grpc_handshake_manager* mgr, grpc_pollset_set* interested_parties,
150     grpc_endpoint* endpoint, const grpc_channel_args* channel_args,
151     grpc_millis deadline, grpc_tcp_server_acceptor* acceptor,
152     grpc_iomgr_cb_func on_handshake_done, void* user_data);
153 
154 /// Add \a mgr to the server side list of all pending handshake managers, the
155 /// list starts with \a *head.
156 // Not thread-safe. Caller needs to synchronize.
157 void grpc_handshake_manager_pending_list_add(grpc_handshake_manager** head,
158                                              grpc_handshake_manager* mgr);
159 
160 /// Remove \a mgr from the server side list of all pending handshake managers.
161 // Not thread-safe. Caller needs to synchronize.
162 void grpc_handshake_manager_pending_list_remove(grpc_handshake_manager** head,
163                                                 grpc_handshake_manager* mgr);
164 
165 /// Shutdown all pending handshake managers on the server side.
166 // Not thread-safe. Caller needs to synchronize.
167 void grpc_handshake_manager_pending_list_shutdown_all(
168     grpc_handshake_manager* head, grpc_error* why);
169 
170 #endif /* GRPC_CORE_LIB_CHANNEL_HANDSHAKER_H */
171