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