1/*
2 *
3 * Copyright 2015 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 GRPCPP_SUPPORT_INTERCEPTOR_H
20#define GRPCPP_SUPPORT_INTERCEPTOR_H
21
22#include <map>
23#include <memory>
24#include <string>
25
26#include <grpc/impl/codegen/grpc_types.h>
27#include <grpcpp/impl/codegen/core_codegen_interface.h>
28#include <grpcpp/impl/codegen/metadata_map.h>
29#include <grpcpp/support/byte_buffer.h>
30#include <grpcpp/support/config.h>
31#include <grpcpp/support/string_ref.h>
32
33namespace grpc {
34
35class ChannelInterface;
36class Status;
37
38namespace experimental {
39
40/// An enumeration of different possible points at which the \a Intercept
41/// method of the \a Interceptor interface may be called. Any given call
42/// to \a Intercept will include one or more of these hook points, and
43/// each hook point makes certain types of information available to the
44/// interceptor.
45/// In these enumeration names, PRE_SEND means that an interception has taken
46/// place between the time the application provided a certain type of data
47/// (e.g., initial metadata, status) and the time that that data goes to the
48/// other side. POST_SEND means that the data has been committed for going to
49/// the other side (even if it has not yet been received at the other side).
50/// PRE_RECV means an interception between the time that a certain
51/// operation has been requested and it is available. POST_RECV means that a
52/// result is available but has not yet been passed back to the application.
53/// A batch of interception points will only contain either PRE or POST hooks
54/// but not both types. For example, a batch with PRE_SEND hook points will not
55/// contain POST_RECV or POST_SEND ops. Likewise, a batch with POST_* ops can
56/// not contain PRE_* ops.
57enum class InterceptionHookPoints {
58 /// The first three in this list are for clients and servers
59 PRE_SEND_INITIAL_METADATA,
60 PRE_SEND_MESSAGE,
61 POST_SEND_MESSAGE,
62 PRE_SEND_STATUS, // server only
63 PRE_SEND_CLOSE, // client only: WritesDone for stream; after write in unary
64 /// The following three are for hijacked clients only. A batch with PRE_RECV_*
65 /// hook points will never contain hook points of other types.
66 PRE_RECV_INITIAL_METADATA,
67 PRE_RECV_MESSAGE,
68 PRE_RECV_STATUS,
69 /// The following two are for all clients and servers
70 POST_RECV_INITIAL_METADATA,
71 POST_RECV_MESSAGE,
72 POST_RECV_STATUS, // client only
73 POST_RECV_CLOSE, // server only
74 /// This is a special hook point available to both clients and servers when
75 /// TryCancel() is performed.
76 /// - No other hook points will be present along with this.
77 /// - It is illegal for an interceptor to block/delay this operation.
78 /// - ALL interceptors see this hook point irrespective of whether the
79 /// RPC was hijacked or not.
80 PRE_SEND_CANCEL,
81 NUM_INTERCEPTION_HOOKS
82};
83
84/// Class that is passed as an argument to the \a Intercept method
85/// of the application's \a Interceptor interface implementation. It has five
86/// purposes:
87/// 1. Indicate which hook points are present at a specific interception
88/// 2. Allow an interceptor to inform the library that an RPC should
89/// continue to the next stage of its processing (which may be another
90/// interceptor or the main path of the library)
91/// 3. Allow an interceptor to hijack the processing of the RPC (only for
92/// client-side RPCs with PRE_SEND_INITIAL_METADATA) so that it does not
93/// proceed with normal processing beyond that stage
94/// 4. Access the relevant fields of an RPC at each interception point
95/// 5. Set some fields of an RPC at each interception point, when possible
96class InterceptorBatchMethods {
97 public:
98 virtual ~InterceptorBatchMethods() {}
99 /// Determine whether the current batch has an interception hook point
100 /// of type \a type
101 virtual bool QueryInterceptionHookPoint(InterceptionHookPoints type) = 0;
102 /// Signal that the interceptor is done intercepting the current batch of the
103 /// RPC. Every interceptor must either call Proceed or Hijack on each
104 /// interception. In most cases, only Proceed will be used. Explicit use of
105 /// Proceed is what enables interceptors to delay the processing of RPCs
106 /// while they perform other work.
107 /// Proceed is a no-op if the batch contains PRE_SEND_CANCEL. Simply returning
108 /// from the Intercept method does the job of continuing the RPC in this case.
109 /// This is because PRE_SEND_CANCEL is always in a separate batch and is not
110 /// allowed to be delayed.
111 virtual void Proceed() = 0;
112 /// Indicate that the interceptor has hijacked the RPC (only valid if the
113 /// batch contains send_initial_metadata on the client side). Later
114 /// interceptors in the interceptor list will not be called. Later batches
115 /// on the same RPC will go through interception, but only up to the point
116 /// of the hijacking interceptor.
117 virtual void Hijack() = 0;
118
119 /// Send Message Methods
120 /// GetSerializedSendMessage and GetSendMessage/ModifySendMessage are the
121 /// available methods to view and modify the request payload. An interceptor
122 /// can access the payload in either serialized form or non-serialized form
123 /// but not both at the same time.
124 /// gRPC performs serialization in a lazy manner, which means
125 /// that a call to GetSerializedSendMessage will result in a serialization
126 /// operation if the payload stored is not in the serialized form already; the
127 /// non-serialized form will be lost and GetSendMessage will no longer return
128 /// a valid pointer, and this will remain true for later interceptors too.
129 /// This can change however if ModifySendMessage is used to replace the
130 /// current payload. Note that ModifySendMessage requires a new payload
131 /// message in the non-serialized form. This will overwrite the existing
132 /// payload irrespective of whether it had been serialized earlier. Also note
133 /// that gRPC Async API requires early serialization of the payload which
134 /// means that the payload would be available in the serialized form only
135 /// unless an interceptor replaces the payload with ModifySendMessage.
136
137 /// Returns a modifable ByteBuffer holding the serialized form of the message
138 /// that is going to be sent. Valid for PRE_SEND_MESSAGE interceptions.
139 /// A return value of nullptr indicates that this ByteBuffer is not valid.
140 virtual ByteBuffer* GetSerializedSendMessage() = 0;
141
142 /// Returns a non-modifiable pointer to the non-serialized form of the message
143 /// to be sent. Valid for PRE_SEND_MESSAGE interceptions. A return value of
144 /// nullptr indicates that this field is not valid.
145 virtual const void* GetSendMessage() = 0;
146
147 /// Overwrites the message to be sent with \a message. \a message should be in
148 /// the non-serialized form expected by the method. Valid for PRE_SEND_MESSAGE
149 /// interceptions. Note that the interceptor is responsible for maintaining
150 /// the life of the message till it is serialized or it receives the
151 /// POST_SEND_MESSAGE interception point, whichever happens earlier. The
152 /// modifying interceptor may itself force early serialization by calling
153 /// GetSerializedSendMessage.
154 virtual void ModifySendMessage(const void* message) = 0;
155
156 /// Checks whether the SEND MESSAGE op succeeded. Valid for POST_SEND_MESSAGE
157 /// interceptions.
158 virtual bool GetSendMessageStatus() = 0;
159
160 /// Returns a modifiable multimap of the initial metadata to be sent. Valid
161 /// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates
162 /// that this field is not valid.
163 virtual std::multimap<std::string, std::string>* GetSendInitialMetadata() = 0;
164
165 /// Returns the status to be sent. Valid for PRE_SEND_STATUS interceptions.
166 virtual Status GetSendStatus() = 0;
167
168 /// Overwrites the status with \a status. Valid for PRE_SEND_STATUS
169 /// interceptions.
170 virtual void ModifySendStatus(const Status& status) = 0;
171
172 /// Returns a modifiable multimap of the trailing metadata to be sent. Valid
173 /// for PRE_SEND_STATUS interceptions. A value of nullptr indicates
174 /// that this field is not valid.
175 virtual std::multimap<std::string, std::string>*
176 GetSendTrailingMetadata() = 0;
177
178 /// Returns a pointer to the modifiable received message. Note that the
179 /// message is already deserialized but the type is not set; the interceptor
180 /// should static_cast to the appropriate type before using it. This is valid
181 /// for PRE_RECV_MESSAGE and POST_RECV_MESSAGE interceptions; nullptr for not
182 /// valid
183 virtual void* GetRecvMessage() = 0;
184
185 /// Returns a modifiable multimap of the received initial metadata.
186 /// Valid for PRE_RECV_INITIAL_METADATA and POST_RECV_INITIAL_METADATA
187 /// interceptions; nullptr if not valid
188 virtual std::multimap<grpc::string_ref, grpc::string_ref>*
189 GetRecvInitialMetadata() = 0;
190
191 /// Returns a modifiable view of the received status on PRE_RECV_STATUS and
192 /// POST_RECV_STATUS interceptions; nullptr if not valid.
193 virtual Status* GetRecvStatus() = 0;
194
195 /// Returns a modifiable multimap of the received trailing metadata on
196 /// PRE_RECV_STATUS and POST_RECV_STATUS interceptions; nullptr if not valid
197 virtual std::multimap<grpc::string_ref, grpc::string_ref>*
198 GetRecvTrailingMetadata() = 0;
199
200 /// Gets an intercepted channel. When a call is started on this interceptor,
201 /// only interceptors after the current interceptor are created from the
202 /// factory objects registered with the channel. This allows calls to be
203 /// started from interceptors without infinite regress through the interceptor
204 /// list.
205 virtual std::unique_ptr<ChannelInterface> GetInterceptedChannel() = 0;
206
207 /// On a hijacked RPC, an interceptor can decide to fail a PRE_RECV_MESSAGE
208 /// op. This would be a signal to the reader that there will be no more
209 /// messages, or the stream has failed or been cancelled.
210 virtual void FailHijackedRecvMessage() = 0;
211
212 /// On a hijacked RPC/ to-be hijacked RPC, this can be called to fail a SEND
213 /// MESSAGE op
214 virtual void FailHijackedSendMessage() = 0;
215};
216
217/// Interface for an interceptor. Interceptor authors must create a class
218/// that derives from this parent class.
219class Interceptor {
220 public:
221 virtual ~Interceptor() {}
222
223 /// The one public method of an Interceptor interface. Override this to
224 /// trigger the desired actions at the hook points described above.
225 virtual void Intercept(InterceptorBatchMethods* methods) = 0;
226};
227
228} // namespace experimental
229} // namespace grpc
230
231#endif // GRPCPP_SUPPORT_INTERCEPTOR_H
232

source code of include/grpcpp/support/interceptor.h