xref: /aosp_15_r20/external/grpc-grpc/src/objective-c/GRPCClient/GRPCInterceptor.mm (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1*cc02d7e2SAndroid Build Coastguard Worker/*
2*cc02d7e2SAndroid Build Coastguard Worker *
3*cc02d7e2SAndroid Build Coastguard Worker * Copyright 2019 gRPC authors.
4*cc02d7e2SAndroid Build Coastguard Worker *
5*cc02d7e2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*cc02d7e2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*cc02d7e2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
8*cc02d7e2SAndroid Build Coastguard Worker *
9*cc02d7e2SAndroid Build Coastguard Worker *     http://www.apache.org/licenses/LICENSE-2.0
10*cc02d7e2SAndroid Build Coastguard Worker *
11*cc02d7e2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*cc02d7e2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*cc02d7e2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*cc02d7e2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*cc02d7e2SAndroid Build Coastguard Worker * limitations under the License.
16*cc02d7e2SAndroid Build Coastguard Worker *
17*cc02d7e2SAndroid Build Coastguard Worker */
18*cc02d7e2SAndroid Build Coastguard Worker
19*cc02d7e2SAndroid Build Coastguard Worker#import <Foundation/Foundation.h>
20*cc02d7e2SAndroid Build Coastguard Worker
21*cc02d7e2SAndroid Build Coastguard Worker#import "GRPCInterceptor.h"
22*cc02d7e2SAndroid Build Coastguard Worker#import "private/GRPCTransport+Private.h"
23*cc02d7e2SAndroid Build Coastguard Worker
24*cc02d7e2SAndroid Build Coastguard Worker@interface GRPCInterceptorManager () <GRPCInterceptorInterface, GRPCResponseHandler>
25*cc02d7e2SAndroid Build Coastguard Worker
26*cc02d7e2SAndroid Build Coastguard Worker@end
27*cc02d7e2SAndroid Build Coastguard Worker
28*cc02d7e2SAndroid Build Coastguard Worker@implementation GRPCInterceptorManager {
29*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCInterceptorInterface> _nextInterceptor;
30*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCResponseHandler> _previousInterceptor;
31*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptor *_thisInterceptor;
32*cc02d7e2SAndroid Build Coastguard Worker  dispatch_queue_t _dispatchQueue;
33*cc02d7e2SAndroid Build Coastguard Worker  NSArray<id<GRPCInterceptorFactory>> *_factories;
34*cc02d7e2SAndroid Build Coastguard Worker  GRPCTransportID _transportID;
35*cc02d7e2SAndroid Build Coastguard Worker  BOOL _shutDown;
36*cc02d7e2SAndroid Build Coastguard Worker}
37*cc02d7e2SAndroid Build Coastguard Worker
38*cc02d7e2SAndroid Build Coastguard Worker- (instancetype)initWithFactories:(NSArray<id<GRPCInterceptorFactory>> *)factories
39*cc02d7e2SAndroid Build Coastguard Worker              previousInterceptor:(id<GRPCResponseHandler>)previousInterceptor
40*cc02d7e2SAndroid Build Coastguard Worker                      transportID:(nonnull GRPCTransportID)transportID {
41*cc02d7e2SAndroid Build Coastguard Worker  if ((self = [super init])) {
42*cc02d7e2SAndroid Build Coastguard Worker    if (factories.count == 0) {
43*cc02d7e2SAndroid Build Coastguard Worker      [NSException raise:NSInternalInconsistencyException
44*cc02d7e2SAndroid Build Coastguard Worker                  format:@"Interceptor manager must have factories"];
45*cc02d7e2SAndroid Build Coastguard Worker    }
46*cc02d7e2SAndroid Build Coastguard Worker    _thisInterceptor = [factories[0] createInterceptorWithManager:self];
47*cc02d7e2SAndroid Build Coastguard Worker    if (_thisInterceptor == nil) {
48*cc02d7e2SAndroid Build Coastguard Worker      return nil;
49*cc02d7e2SAndroid Build Coastguard Worker    }
50*cc02d7e2SAndroid Build Coastguard Worker    _previousInterceptor = previousInterceptor;
51*cc02d7e2SAndroid Build Coastguard Worker    _factories = factories;
52*cc02d7e2SAndroid Build Coastguard Worker    // Generate interceptor
53*cc02d7e2SAndroid Build Coastguard Worker#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
54*cc02d7e2SAndroid Build Coastguard Worker    if (@available(iOS 8.0, macOS 10.10, *)) {
55*cc02d7e2SAndroid Build Coastguard Worker      _dispatchQueue = dispatch_queue_create(
56*cc02d7e2SAndroid Build Coastguard Worker          NULL,
57*cc02d7e2SAndroid Build Coastguard Worker          dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0));
58*cc02d7e2SAndroid Build Coastguard Worker    } else {
59*cc02d7e2SAndroid Build Coastguard Worker#else
60*cc02d7e2SAndroid Build Coastguard Worker    {
61*cc02d7e2SAndroid Build Coastguard Worker#endif
62*cc02d7e2SAndroid Build Coastguard Worker      _dispatchQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
63*cc02d7e2SAndroid Build Coastguard Worker    }
64*cc02d7e2SAndroid Build Coastguard Worker    dispatch_set_target_queue(_dispatchQueue, _thisInterceptor.dispatchQueue);
65*cc02d7e2SAndroid Build Coastguard Worker    _transportID = transportID;
66*cc02d7e2SAndroid Build Coastguard Worker  }
67*cc02d7e2SAndroid Build Coastguard Worker  return self;
68*cc02d7e2SAndroid Build Coastguard Worker}
69*cc02d7e2SAndroid Build Coastguard Worker
70*cc02d7e2SAndroid Build Coastguard Worker- (void)shutDown {
71*cc02d7e2SAndroid Build Coastguard Worker  // immediately releases reference; should not queue to dispatch queue.
72*cc02d7e2SAndroid Build Coastguard Worker  _nextInterceptor = nil;
73*cc02d7e2SAndroid Build Coastguard Worker  _previousInterceptor = nil;
74*cc02d7e2SAndroid Build Coastguard Worker  _thisInterceptor = nil;
75*cc02d7e2SAndroid Build Coastguard Worker  _shutDown = YES;
76*cc02d7e2SAndroid Build Coastguard Worker}
77*cc02d7e2SAndroid Build Coastguard Worker
78*cc02d7e2SAndroid Build Coastguard Worker- (void)createNextInterceptor {
79*cc02d7e2SAndroid Build Coastguard Worker  NSAssert(_nextInterceptor == nil, @"Starting the next interceptor more than once");
80*cc02d7e2SAndroid Build Coastguard Worker  NSAssert(_factories.count > 0, @"Interceptor manager of transport cannot start next interceptor");
81*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor != nil) {
82*cc02d7e2SAndroid Build Coastguard Worker    NSLog(@"Starting the next interceptor more than once");
83*cc02d7e2SAndroid Build Coastguard Worker    return;
84*cc02d7e2SAndroid Build Coastguard Worker  }
85*cc02d7e2SAndroid Build Coastguard Worker  NSMutableArray<id<GRPCInterceptorFactory>> *interceptorFactories = [NSMutableArray
86*cc02d7e2SAndroid Build Coastguard Worker      arrayWithArray:[_factories subarrayWithRange:NSMakeRange(1, _factories.count - 1)]];
87*cc02d7e2SAndroid Build Coastguard Worker  while (_nextInterceptor == nil) {
88*cc02d7e2SAndroid Build Coastguard Worker    if (interceptorFactories.count == 0) {
89*cc02d7e2SAndroid Build Coastguard Worker      _nextInterceptor = [[GRPCTransportManager alloc] initWithTransportID:_transportID
90*cc02d7e2SAndroid Build Coastguard Worker                                                       previousInterceptor:self];
91*cc02d7e2SAndroid Build Coastguard Worker      break;
92*cc02d7e2SAndroid Build Coastguard Worker    } else {
93*cc02d7e2SAndroid Build Coastguard Worker      _nextInterceptor = [[GRPCInterceptorManager alloc] initWithFactories:interceptorFactories
94*cc02d7e2SAndroid Build Coastguard Worker                                                       previousInterceptor:self
95*cc02d7e2SAndroid Build Coastguard Worker                                                               transportID:_transportID];
96*cc02d7e2SAndroid Build Coastguard Worker      if (_nextInterceptor == nil) {
97*cc02d7e2SAndroid Build Coastguard Worker        [interceptorFactories removeObjectAtIndex:0];
98*cc02d7e2SAndroid Build Coastguard Worker      }
99*cc02d7e2SAndroid Build Coastguard Worker    }
100*cc02d7e2SAndroid Build Coastguard Worker  }
101*cc02d7e2SAndroid Build Coastguard Worker  NSAssert(_nextInterceptor != nil, @"Failed to create interceptor or transport.");
102*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil) {
103*cc02d7e2SAndroid Build Coastguard Worker    NSLog(@"Failed to create interceptor or transport.");
104*cc02d7e2SAndroid Build Coastguard Worker  }
105*cc02d7e2SAndroid Build Coastguard Worker}
106*cc02d7e2SAndroid Build Coastguard Worker
107*cc02d7e2SAndroid Build Coastguard Worker- (void)startNextInterceptorWithRequest:(GRPCRequestOptions *)requestOptions
108*cc02d7e2SAndroid Build Coastguard Worker                            callOptions:(GRPCCallOptions *)callOptions {
109*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil && !_shutDown) {
110*cc02d7e2SAndroid Build Coastguard Worker    [self createNextInterceptor];
111*cc02d7e2SAndroid Build Coastguard Worker  }
112*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil) {
113*cc02d7e2SAndroid Build Coastguard Worker    return;
114*cc02d7e2SAndroid Build Coastguard Worker  }
115*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
116*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
117*cc02d7e2SAndroid Build Coastguard Worker    [copiedNextInterceptor startWithRequestOptions:requestOptions callOptions:callOptions];
118*cc02d7e2SAndroid Build Coastguard Worker  });
119*cc02d7e2SAndroid Build Coastguard Worker}
120*cc02d7e2SAndroid Build Coastguard Worker
121*cc02d7e2SAndroid Build Coastguard Worker- (void)writeNextInterceptorWithData:(id)data {
122*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil && !_shutDown) {
123*cc02d7e2SAndroid Build Coastguard Worker    [self createNextInterceptor];
124*cc02d7e2SAndroid Build Coastguard Worker  }
125*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil) {
126*cc02d7e2SAndroid Build Coastguard Worker    return;
127*cc02d7e2SAndroid Build Coastguard Worker  }
128*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
129*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
130*cc02d7e2SAndroid Build Coastguard Worker    [copiedNextInterceptor writeData:data];
131*cc02d7e2SAndroid Build Coastguard Worker  });
132*cc02d7e2SAndroid Build Coastguard Worker}
133*cc02d7e2SAndroid Build Coastguard Worker
134*cc02d7e2SAndroid Build Coastguard Worker- (void)finishNextInterceptor {
135*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil && !_shutDown) {
136*cc02d7e2SAndroid Build Coastguard Worker    [self createNextInterceptor];
137*cc02d7e2SAndroid Build Coastguard Worker  }
138*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil) {
139*cc02d7e2SAndroid Build Coastguard Worker    return;
140*cc02d7e2SAndroid Build Coastguard Worker  }
141*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
142*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
143*cc02d7e2SAndroid Build Coastguard Worker    [copiedNextInterceptor finish];
144*cc02d7e2SAndroid Build Coastguard Worker  });
145*cc02d7e2SAndroid Build Coastguard Worker}
146*cc02d7e2SAndroid Build Coastguard Worker
147*cc02d7e2SAndroid Build Coastguard Worker- (void)cancelNextInterceptor {
148*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil && !_shutDown) {
149*cc02d7e2SAndroid Build Coastguard Worker    [self createNextInterceptor];
150*cc02d7e2SAndroid Build Coastguard Worker  }
151*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil) {
152*cc02d7e2SAndroid Build Coastguard Worker    return;
153*cc02d7e2SAndroid Build Coastguard Worker  }
154*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
155*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
156*cc02d7e2SAndroid Build Coastguard Worker    [copiedNextInterceptor cancel];
157*cc02d7e2SAndroid Build Coastguard Worker  });
158*cc02d7e2SAndroid Build Coastguard Worker}
159*cc02d7e2SAndroid Build Coastguard Worker
160*cc02d7e2SAndroid Build Coastguard Worker/** Notify the next interceptor in the chain to receive more messages */
161*cc02d7e2SAndroid Build Coastguard Worker- (void)receiveNextInterceptorMessages:(NSUInteger)numberOfMessages {
162*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil && !_shutDown) {
163*cc02d7e2SAndroid Build Coastguard Worker    [self createNextInterceptor];
164*cc02d7e2SAndroid Build Coastguard Worker  }
165*cc02d7e2SAndroid Build Coastguard Worker  if (_nextInterceptor == nil) {
166*cc02d7e2SAndroid Build Coastguard Worker    return;
167*cc02d7e2SAndroid Build Coastguard Worker  }
168*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCInterceptorInterface> copiedNextInterceptor = _nextInterceptor;
169*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedNextInterceptor.dispatchQueue, ^{
170*cc02d7e2SAndroid Build Coastguard Worker    [copiedNextInterceptor receiveNextMessages:numberOfMessages];
171*cc02d7e2SAndroid Build Coastguard Worker  });
172*cc02d7e2SAndroid Build Coastguard Worker}
173*cc02d7e2SAndroid Build Coastguard Worker
174*cc02d7e2SAndroid Build Coastguard Worker// Methods to forward GRPCResponseHandler callbacks to the previous object
175*cc02d7e2SAndroid Build Coastguard Worker
176*cc02d7e2SAndroid Build Coastguard Worker/** Forward initial metadata to the previous interceptor in the chain */
177*cc02d7e2SAndroid Build Coastguard Worker- (void)forwardPreviousInterceptorWithInitialMetadata:(NSDictionary *)initialMetadata {
178*cc02d7e2SAndroid Build Coastguard Worker  if (_previousInterceptor == nil) {
179*cc02d7e2SAndroid Build Coastguard Worker    return;
180*cc02d7e2SAndroid Build Coastguard Worker  }
181*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
182*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
183*cc02d7e2SAndroid Build Coastguard Worker    [copiedPreviousInterceptor didReceiveInitialMetadata:initialMetadata];
184*cc02d7e2SAndroid Build Coastguard Worker  });
185*cc02d7e2SAndroid Build Coastguard Worker}
186*cc02d7e2SAndroid Build Coastguard Worker
187*cc02d7e2SAndroid Build Coastguard Worker/** Forward a received message to the previous interceptor in the chain */
188*cc02d7e2SAndroid Build Coastguard Worker- (void)forwardPreviousInterceptorWithData:(id)data {
189*cc02d7e2SAndroid Build Coastguard Worker  if (_previousInterceptor == nil) {
190*cc02d7e2SAndroid Build Coastguard Worker    return;
191*cc02d7e2SAndroid Build Coastguard Worker  }
192*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
193*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
194*cc02d7e2SAndroid Build Coastguard Worker    [copiedPreviousInterceptor didReceiveData:data];
195*cc02d7e2SAndroid Build Coastguard Worker  });
196*cc02d7e2SAndroid Build Coastguard Worker}
197*cc02d7e2SAndroid Build Coastguard Worker
198*cc02d7e2SAndroid Build Coastguard Worker/** Forward call close and trailing metadata to the previous interceptor in the chain */
199*cc02d7e2SAndroid Build Coastguard Worker- (void)forwardPreviousInterceptorCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata
200*cc02d7e2SAndroid Build Coastguard Worker                                                      error:(NSError *)error {
201*cc02d7e2SAndroid Build Coastguard Worker  if (_previousInterceptor == nil) {
202*cc02d7e2SAndroid Build Coastguard Worker    return;
203*cc02d7e2SAndroid Build Coastguard Worker  }
204*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
205*cc02d7e2SAndroid Build Coastguard Worker  // no more callbacks should be issued to the previous interceptor
206*cc02d7e2SAndroid Build Coastguard Worker  _previousInterceptor = nil;
207*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
208*cc02d7e2SAndroid Build Coastguard Worker    [copiedPreviousInterceptor didCloseWithTrailingMetadata:trailingMetadata error:error];
209*cc02d7e2SAndroid Build Coastguard Worker  });
210*cc02d7e2SAndroid Build Coastguard Worker}
211*cc02d7e2SAndroid Build Coastguard Worker
212*cc02d7e2SAndroid Build Coastguard Worker/** Forward write completion to the previous interceptor in the chain */
213*cc02d7e2SAndroid Build Coastguard Worker- (void)forwardPreviousInterceptorDidWriteData {
214*cc02d7e2SAndroid Build Coastguard Worker  if (_previousInterceptor == nil) {
215*cc02d7e2SAndroid Build Coastguard Worker    return;
216*cc02d7e2SAndroid Build Coastguard Worker  }
217*cc02d7e2SAndroid Build Coastguard Worker  id<GRPCResponseHandler> copiedPreviousInterceptor = _previousInterceptor;
218*cc02d7e2SAndroid Build Coastguard Worker  dispatch_async(copiedPreviousInterceptor.dispatchQueue, ^{
219*cc02d7e2SAndroid Build Coastguard Worker    [copiedPreviousInterceptor didWriteData];
220*cc02d7e2SAndroid Build Coastguard Worker  });
221*cc02d7e2SAndroid Build Coastguard Worker}
222*cc02d7e2SAndroid Build Coastguard Worker
223*cc02d7e2SAndroid Build Coastguard Worker- (dispatch_queue_t)dispatchQueue {
224*cc02d7e2SAndroid Build Coastguard Worker  return _dispatchQueue;
225*cc02d7e2SAndroid Build Coastguard Worker}
226*cc02d7e2SAndroid Build Coastguard Worker
227*cc02d7e2SAndroid Build Coastguard Worker- (void)startWithRequestOptions:(GRPCRequestOptions *)requestOptions
228*cc02d7e2SAndroid Build Coastguard Worker                    callOptions:(GRPCCallOptions *)callOptions {
229*cc02d7e2SAndroid Build Coastguard Worker  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
230*cc02d7e2SAndroid Build Coastguard Worker  // the interceptor's method
231*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptor *thisInterceptor = _thisInterceptor;
232*cc02d7e2SAndroid Build Coastguard Worker  [thisInterceptor startWithRequestOptions:requestOptions callOptions:callOptions];
233*cc02d7e2SAndroid Build Coastguard Worker}
234*cc02d7e2SAndroid Build Coastguard Worker
235*cc02d7e2SAndroid Build Coastguard Worker- (void)writeData:(id)data {
236*cc02d7e2SAndroid Build Coastguard Worker  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
237*cc02d7e2SAndroid Build Coastguard Worker  // the interceptor's method
238*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptor *thisInterceptor = _thisInterceptor;
239*cc02d7e2SAndroid Build Coastguard Worker  [thisInterceptor writeData:data];
240*cc02d7e2SAndroid Build Coastguard Worker}
241*cc02d7e2SAndroid Build Coastguard Worker
242*cc02d7e2SAndroid Build Coastguard Worker- (void)finish {
243*cc02d7e2SAndroid Build Coastguard Worker  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
244*cc02d7e2SAndroid Build Coastguard Worker  // the interceptor's method
245*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptor *thisInterceptor = _thisInterceptor;
246*cc02d7e2SAndroid Build Coastguard Worker  [thisInterceptor finish];
247*cc02d7e2SAndroid Build Coastguard Worker}
248*cc02d7e2SAndroid Build Coastguard Worker
249*cc02d7e2SAndroid Build Coastguard Worker- (void)cancel {
250*cc02d7e2SAndroid Build Coastguard Worker  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
251*cc02d7e2SAndroid Build Coastguard Worker  // the interceptor's method
252*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptor *thisInterceptor = _thisInterceptor;
253*cc02d7e2SAndroid Build Coastguard Worker  [thisInterceptor cancel];
254*cc02d7e2SAndroid Build Coastguard Worker}
255*cc02d7e2SAndroid Build Coastguard Worker
256*cc02d7e2SAndroid Build Coastguard Worker- (void)receiveNextMessages:(NSUInteger)numberOfMessages {
257*cc02d7e2SAndroid Build Coastguard Worker  // retain this interceptor until the method exit to prevent deallocation of the interceptor within
258*cc02d7e2SAndroid Build Coastguard Worker  // the interceptor's method
259*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptor *thisInterceptor = _thisInterceptor;
260*cc02d7e2SAndroid Build Coastguard Worker  [thisInterceptor receiveNextMessages:numberOfMessages];
261*cc02d7e2SAndroid Build Coastguard Worker}
262*cc02d7e2SAndroid Build Coastguard Worker
263*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveInitialMetadata:(nullable NSDictionary *)initialMetadata {
264*cc02d7e2SAndroid Build Coastguard Worker  if ([_thisInterceptor respondsToSelector:@selector(didReceiveInitialMetadata:)]) {
265*cc02d7e2SAndroid Build Coastguard Worker    // retain this interceptor until the method exit to prevent deallocation of the interceptor
266*cc02d7e2SAndroid Build Coastguard Worker    // within the interceptor's method
267*cc02d7e2SAndroid Build Coastguard Worker    GRPCInterceptor *thisInterceptor = _thisInterceptor;
268*cc02d7e2SAndroid Build Coastguard Worker    [thisInterceptor didReceiveInitialMetadata:initialMetadata];
269*cc02d7e2SAndroid Build Coastguard Worker  }
270*cc02d7e2SAndroid Build Coastguard Worker}
271*cc02d7e2SAndroid Build Coastguard Worker
272*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveData:(id)data {
273*cc02d7e2SAndroid Build Coastguard Worker  if ([_thisInterceptor respondsToSelector:@selector(didReceiveData:)]) {
274*cc02d7e2SAndroid Build Coastguard Worker    // retain this interceptor until the method exit to prevent deallocation of the interceptor
275*cc02d7e2SAndroid Build Coastguard Worker    // within the interceptor's method
276*cc02d7e2SAndroid Build Coastguard Worker    GRPCInterceptor *thisInterceptor = _thisInterceptor;
277*cc02d7e2SAndroid Build Coastguard Worker    [thisInterceptor didReceiveData:data];
278*cc02d7e2SAndroid Build Coastguard Worker  }
279*cc02d7e2SAndroid Build Coastguard Worker}
280*cc02d7e2SAndroid Build Coastguard Worker
281*cc02d7e2SAndroid Build Coastguard Worker- (void)didCloseWithTrailingMetadata:(nullable NSDictionary *)trailingMetadata
282*cc02d7e2SAndroid Build Coastguard Worker                               error:(nullable NSError *)error {
283*cc02d7e2SAndroid Build Coastguard Worker  if ([_thisInterceptor respondsToSelector:@selector(didCloseWithTrailingMetadata:error:)]) {
284*cc02d7e2SAndroid Build Coastguard Worker    // retain this interceptor until the method exit to prevent deallocation of the interceptor
285*cc02d7e2SAndroid Build Coastguard Worker    // within the interceptor's method
286*cc02d7e2SAndroid Build Coastguard Worker    GRPCInterceptor *thisInterceptor = _thisInterceptor;
287*cc02d7e2SAndroid Build Coastguard Worker    [thisInterceptor didCloseWithTrailingMetadata:trailingMetadata error:error];
288*cc02d7e2SAndroid Build Coastguard Worker  }
289*cc02d7e2SAndroid Build Coastguard Worker}
290*cc02d7e2SAndroid Build Coastguard Worker
291*cc02d7e2SAndroid Build Coastguard Worker- (void)didWriteData {
292*cc02d7e2SAndroid Build Coastguard Worker  if ([_thisInterceptor respondsToSelector:@selector(didWriteData)]) {
293*cc02d7e2SAndroid Build Coastguard Worker    // retain this interceptor until the method exit to prevent deallocation of the interceptor
294*cc02d7e2SAndroid Build Coastguard Worker    // within the interceptor's method
295*cc02d7e2SAndroid Build Coastguard Worker    GRPCInterceptor *thisInterceptor = _thisInterceptor;
296*cc02d7e2SAndroid Build Coastguard Worker    [thisInterceptor didWriteData];
297*cc02d7e2SAndroid Build Coastguard Worker  }
298*cc02d7e2SAndroid Build Coastguard Worker}
299*cc02d7e2SAndroid Build Coastguard Worker
300*cc02d7e2SAndroid Build Coastguard Worker@end
301*cc02d7e2SAndroid Build Coastguard Worker
302*cc02d7e2SAndroid Build Coastguard Worker@implementation GRPCInterceptor {
303*cc02d7e2SAndroid Build Coastguard Worker  GRPCInterceptorManager *_manager;
304*cc02d7e2SAndroid Build Coastguard Worker  dispatch_queue_t _dispatchQueue;
305*cc02d7e2SAndroid Build Coastguard Worker}
306*cc02d7e2SAndroid Build Coastguard Worker
307*cc02d7e2SAndroid Build Coastguard Worker- (instancetype)initWithInterceptorManager:(GRPCInterceptorManager *)interceptorManager
308*cc02d7e2SAndroid Build Coastguard Worker                             dispatchQueue:(dispatch_queue_t)dispatchQueue {
309*cc02d7e2SAndroid Build Coastguard Worker  if ((self = [super init])) {
310*cc02d7e2SAndroid Build Coastguard Worker    _manager = interceptorManager;
311*cc02d7e2SAndroid Build Coastguard Worker    _dispatchQueue = dispatchQueue;
312*cc02d7e2SAndroid Build Coastguard Worker  }
313*cc02d7e2SAndroid Build Coastguard Worker
314*cc02d7e2SAndroid Build Coastguard Worker  return self;
315*cc02d7e2SAndroid Build Coastguard Worker}
316*cc02d7e2SAndroid Build Coastguard Worker
317*cc02d7e2SAndroid Build Coastguard Worker- (dispatch_queue_t)dispatchQueue {
318*cc02d7e2SAndroid Build Coastguard Worker  return _dispatchQueue;
319*cc02d7e2SAndroid Build Coastguard Worker}
320*cc02d7e2SAndroid Build Coastguard Worker
321*cc02d7e2SAndroid Build Coastguard Worker- (void)startWithRequestOptions:(GRPCRequestOptions *)requestOptions
322*cc02d7e2SAndroid Build Coastguard Worker                    callOptions:(GRPCCallOptions *)callOptions {
323*cc02d7e2SAndroid Build Coastguard Worker  [_manager startNextInterceptorWithRequest:requestOptions callOptions:callOptions];
324*cc02d7e2SAndroid Build Coastguard Worker}
325*cc02d7e2SAndroid Build Coastguard Worker
326*cc02d7e2SAndroid Build Coastguard Worker- (void)writeData:(id)data {
327*cc02d7e2SAndroid Build Coastguard Worker  [_manager writeNextInterceptorWithData:data];
328*cc02d7e2SAndroid Build Coastguard Worker}
329*cc02d7e2SAndroid Build Coastguard Worker
330*cc02d7e2SAndroid Build Coastguard Worker- (void)finish {
331*cc02d7e2SAndroid Build Coastguard Worker  [_manager finishNextInterceptor];
332*cc02d7e2SAndroid Build Coastguard Worker}
333*cc02d7e2SAndroid Build Coastguard Worker
334*cc02d7e2SAndroid Build Coastguard Worker- (void)cancel {
335*cc02d7e2SAndroid Build Coastguard Worker  [_manager cancelNextInterceptor];
336*cc02d7e2SAndroid Build Coastguard Worker  [_manager
337*cc02d7e2SAndroid Build Coastguard Worker      forwardPreviousInterceptorCloseWithTrailingMetadata:nil
338*cc02d7e2SAndroid Build Coastguard Worker                                                    error:[NSError
339*cc02d7e2SAndroid Build Coastguard Worker                                                              errorWithDomain:kGRPCErrorDomain
340*cc02d7e2SAndroid Build Coastguard Worker                                                                         code:GRPCErrorCodeCancelled
341*cc02d7e2SAndroid Build Coastguard Worker                                                                     userInfo:@{
342*cc02d7e2SAndroid Build Coastguard Worker                                                                       NSLocalizedDescriptionKey :
343*cc02d7e2SAndroid Build Coastguard Worker                                                                           @"Canceled"
344*cc02d7e2SAndroid Build Coastguard Worker                                                                     }]];
345*cc02d7e2SAndroid Build Coastguard Worker  [_manager shutDown];
346*cc02d7e2SAndroid Build Coastguard Worker}
347*cc02d7e2SAndroid Build Coastguard Worker
348*cc02d7e2SAndroid Build Coastguard Worker- (void)receiveNextMessages:(NSUInteger)numberOfMessages {
349*cc02d7e2SAndroid Build Coastguard Worker  [_manager receiveNextInterceptorMessages:numberOfMessages];
350*cc02d7e2SAndroid Build Coastguard Worker}
351*cc02d7e2SAndroid Build Coastguard Worker
352*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveInitialMetadata:(NSDictionary *)initialMetadata {
353*cc02d7e2SAndroid Build Coastguard Worker  [_manager forwardPreviousInterceptorWithInitialMetadata:initialMetadata];
354*cc02d7e2SAndroid Build Coastguard Worker}
355*cc02d7e2SAndroid Build Coastguard Worker
356*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveRawMessage:(id)message {
357*cc02d7e2SAndroid Build Coastguard Worker  NSAssert(NO,
358*cc02d7e2SAndroid Build Coastguard Worker           @"The method didReceiveRawMessage is deprecated and cannot be used with interceptor");
359*cc02d7e2SAndroid Build Coastguard Worker  NSLog(@"The method didReceiveRawMessage is deprecated and cannot be used with interceptor");
360*cc02d7e2SAndroid Build Coastguard Worker  abort();
361*cc02d7e2SAndroid Build Coastguard Worker}
362*cc02d7e2SAndroid Build Coastguard Worker
363*cc02d7e2SAndroid Build Coastguard Worker- (void)didReceiveData:(id)data {
364*cc02d7e2SAndroid Build Coastguard Worker  [_manager forwardPreviousInterceptorWithData:data];
365*cc02d7e2SAndroid Build Coastguard Worker}
366*cc02d7e2SAndroid Build Coastguard Worker
367*cc02d7e2SAndroid Build Coastguard Worker- (void)didCloseWithTrailingMetadata:(NSDictionary *)trailingMetadata error:(NSError *)error {
368*cc02d7e2SAndroid Build Coastguard Worker  [_manager forwardPreviousInterceptorCloseWithTrailingMetadata:trailingMetadata error:error];
369*cc02d7e2SAndroid Build Coastguard Worker  [_manager shutDown];
370*cc02d7e2SAndroid Build Coastguard Worker}
371*cc02d7e2SAndroid Build Coastguard Worker
372*cc02d7e2SAndroid Build Coastguard Worker- (void)didWriteData {
373*cc02d7e2SAndroid Build Coastguard Worker  [_manager forwardPreviousInterceptorDidWriteData];
374*cc02d7e2SAndroid Build Coastguard Worker}
375*cc02d7e2SAndroid Build Coastguard Worker
376*cc02d7e2SAndroid Build Coastguard Worker@end
377