aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/grpcpp/impl/codegen/interceptor.h
blob: 5dea796a3b7d69b035ba6221db0364205a30c074 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*
 *
 * Copyright 2018 gRPC authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#ifndef GRPCPP_IMPL_CODEGEN_INTERCEPTOR_H
#define GRPCPP_IMPL_CODEGEN_INTERCEPTOR_H

#include <grpc/impl/codegen/grpc_types.h>
#include <grpcpp/impl/codegen/byte_buffer.h>
#include <grpcpp/impl/codegen/config.h>
#include <grpcpp/impl/codegen/core_codegen_interface.h>
#include <grpcpp/impl/codegen/metadata_map.h>

namespace grpc {

class ChannelInterface;
class Status;

namespace experimental {

/// An enumeration of different possible points at which the \a Intercept
/// method of the \a Interceptor interface may be called. Any given call
/// to \a Intercept will include one or more of these hook points, and
/// each hook point makes certain types of information available to the
/// interceptor.
/// In these enumeration names, PRE_SEND means that an interception has taken
/// place between the time the application provided a certain type of data
/// (e.g., initial metadata, status) and the time that that data goes to the
/// other side. POST_SEND means that the data has been committed for going to
/// the other side (even if it has not yet been received at the other side).
/// PRE_RECV means an interception between the time that a certain
/// operation has been requested and it is available. POST_RECV means that a
/// result is available but has not yet been passed back to the application.
enum class InterceptionHookPoints {
  /// The first three in this list are for clients and servers
  PRE_SEND_INITIAL_METADATA,
  PRE_SEND_MESSAGE,
  POST_SEND_MESSAGE,
  PRE_SEND_STATUS,  // server only
  PRE_SEND_CLOSE,   // client only: WritesDone for stream; after write in unary
  /// The following three are for hijacked clients only and can only be
  /// registered by the global interceptor
  PRE_RECV_INITIAL_METADATA,
  PRE_RECV_MESSAGE,
  PRE_RECV_STATUS,
  /// The following two are for all clients and servers
  POST_RECV_INITIAL_METADATA,
  POST_RECV_MESSAGE,
  POST_RECV_STATUS,  // client only
  POST_RECV_CLOSE,   // server only
  /// This is a special hook point available to both clients and servers when
  /// TryCancel() is performed.
  ///  - No other hook points will be present along with this.
  ///  - It is illegal for an interceptor to block/delay this operation.
  ///  - ALL interceptors see this hook point irrespective of whether the
  ///    RPC was hijacked or not.
  PRE_SEND_CANCEL,
  NUM_INTERCEPTION_HOOKS
};

/// Class that is passed as an argument to the \a Intercept method
/// of the application's \a Interceptor interface implementation. It has five
/// purposes:
///   1. Indicate which hook points are present at a specific interception
///   2. Allow an interceptor to inform the library that an RPC should
///      continue to the next stage of its processing (which may be another
///      interceptor or the main path of the library)
///   3. Allow an interceptor to hijack the processing of the RPC (only for
///      client-side RPCs with PRE_SEND_INITIAL_METADATA) so that it does not
///      proceed with normal processing beyond that stage
///   4. Access the relevant fields of an RPC at each interception point
///   5. Set some fields of an RPC at each interception point, when possible
class InterceptorBatchMethods {
 public:
  virtual ~InterceptorBatchMethods(){};
  /// Determine whether the current batch has an interception hook point
  /// of type \a type
  virtual bool QueryInterceptionHookPoint(InterceptionHookPoints type) = 0;
  /// Signal that the interceptor is done intercepting the current batch of the
  /// RPC. Every interceptor must either call Proceed or Hijack on each
  /// interception. In most cases, only Proceed will be used. Explicit use of
  /// Proceed is what enables interceptors to delay the processing of RPCs
  /// while they perform other work.
  /// Proceed is a no-op if the batch contains PRE_SEND_CANCEL. Simply returning
  /// from the Intercept method does the job of continuing the RPC in this case.
  /// This is because PRE_SEND_CANCEL is always in a separate batch and is not
  /// allowed to be delayed.
  virtual void Proceed() = 0;
  /// Indicate that the interceptor has hijacked the RPC (only valid if the
  /// batch contains send_initial_metadata on the client side). Later
  /// interceptors in the interceptor list will not be called. Later batches
  /// on the same RPC will go through interception, but only up to the point
  /// of the hijacking interceptor.
  virtual void Hijack() = 0;

  /// Returns a modifable ByteBuffer holding the serialized form of the message
  /// that is going to be sent. Valid for PRE_SEND_MESSAGE interceptions.
  /// A return value of nullptr indicates that this ByteBuffer is not valid.
  virtual ByteBuffer* GetSerializedSendMessage() = 0;

  /// Returns a non-modifiable pointer to the non-serialized form of the message
  /// to be sent. Valid for PRE_SEND_MESSAGE interceptions. A return value of
  /// nullptr indicates that this field is not valid. Also note that this is
  /// only supported for sync and callback APIs at the present moment.
  virtual const void* GetSendMessage() = 0;

  /// Overwrites the message to be sent with \a message. \a message should be in
  /// the non-serialized form expected by the method. Valid for PRE_SEND_MESSAGE
  /// interceptions. Note that the interceptor is responsible for maintaining
  /// the life of the message for the duration on the send operation, i.e., till
  /// POST_SEND_MESSAGE.
  virtual void ModifySendMessage(const void* message) = 0;

  /// Checks whether the SEND MESSAGE op succeeded. Valid for POST_SEND_MESSAGE
  /// interceptions.
  virtual bool GetSendMessageStatus() = 0;

  /// Returns a modifiable multimap of the initial metadata to be sent. Valid
  /// for PRE_SEND_INITIAL_METADATA interceptions. A value of nullptr indicates
  /// that this field is not valid.
  virtual std::multimap<grpc::string, grpc::string>*
  GetSendInitialMetadata() = 0;

  /// Returns the status to be sent. Valid for PRE_SEND_STATUS interceptions.
  virtual Status GetSendStatus() = 0;

  /// Overwrites the status with \a status. Valid for PRE_SEND_STATUS
  /// interceptions.
  virtual void ModifySendStatus(const Status& status) = 0;

  /// Returns a modifiable multimap of the trailing metadata to be sent. Valid
  /// for PRE_SEND_STATUS interceptions. A value of nullptr indicates
  /// that this field is not valid.
  virtual std::multimap<grpc::string, grpc::string>*
  GetSendTrailingMetadata() = 0;

  /// Returns a pointer to the modifiable received message. Note that the
  /// message is already deserialized but the type is not set; the interceptor
  /// should static_cast to the appropriate type before using it. This is valid
  /// for POST_RECV_MESSAGE interceptions; nullptr for not valid
  virtual void* GetRecvMessage() = 0;

  /// Returns a modifiable multimap of the received initial metadata.
  /// Valid for POST_RECV_INITIAL_METADATA interceptions; nullptr if not valid
  virtual std::multimap<grpc::string_ref, grpc::string_ref>*
  GetRecvInitialMetadata() = 0;

  /// Returns a modifiable view of the received status on POST_RECV_STATUS
  /// interceptions; nullptr if not valid.
  virtual Status* GetRecvStatus() = 0;

  /// Returns a modifiable multimap of the received trailing metadata on
  /// POST_RECV_STATUS interceptions; nullptr if not valid
  virtual std::multimap<grpc::string_ref, grpc::string_ref>*
  GetRecvTrailingMetadata() = 0;

  /// Gets an intercepted channel. When a call is started on this interceptor,
  /// only interceptors after the current interceptor are created from the
  /// factory objects registered with the channel. This allows calls to be
  /// started from interceptors without infinite regress through the interceptor
  /// list.
  virtual std::unique_ptr<ChannelInterface> GetInterceptedChannel() = 0;

  /// On a hijacked RPC, an interceptor can decide to fail a PRE_RECV_MESSAGE
  /// op. This would be a signal to the reader that there will be no more
  /// messages, or the stream has failed or been cancelled.
  virtual void FailHijackedRecvMessage() = 0;

  /// On a hijacked RPC/ to-be hijacked RPC, this can be called to fail a SEND
  /// MESSAGE op
  virtual void FailHijackedSendMessage() = 0;
};

/// Interface for an interceptor. Interceptor authors must create a class
/// that derives from this parent class.
class Interceptor {
 public:
  virtual ~Interceptor() {}

  /// The one public method of an Interceptor interface. Override this to
  /// trigger the desired actions at the hook points described above.
  virtual void Intercept(InterceptorBatchMethods* methods) = 0;
};

}  // namespace experimental
}  // namespace grpc

#endif  // GRPCPP_IMPL_CODEGEN_INTERCEPTOR_H