|  | @@ -1,6 +1,6 @@
 | 
	
		
			
				|  |  |  /*
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  | - * Copyright 2015 gRPC authors.
 | 
	
		
			
				|  |  | + * 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.
 | 
	
	
		
			
				|  | @@ -30,16 +30,15 @@
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/byte_buffer.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/call.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/call_hook.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/impl/codegen/call_op_set_interface.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/client_context.h>
 | 
	
		
			
				|  |  | -#include <grpcpp/impl/codegen/client_interceptor.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/completion_queue_tag.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/config.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/core_codegen_interface.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/intercepted_channel.h>
 | 
	
		
			
				|  |  | +#include <grpcpp/impl/codegen/interceptor_common.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/serialization_traits.h>
 | 
	
		
			
				|  |  | -#include <grpcpp/impl/codegen/server_interceptor.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/slice.h>
 | 
	
		
			
				|  |  | -#include <grpcpp/impl/codegen/status.h>
 | 
	
		
			
				|  |  |  #include <grpcpp/impl/codegen/string_ref.h>
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include <grpc/impl/codegen/atm.h>
 | 
	
	
		
			
				|  | @@ -207,38 +206,6 @@ class WriteOptions {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace internal {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/// Internal methods for setting the state
 | 
	
		
			
				|  |  | -class InternalInterceptorBatchMethods
 | 
	
		
			
				|  |  | -    : public experimental::InterceptorBatchMethods {
 | 
	
		
			
				|  |  | - public:
 | 
	
		
			
				|  |  | -  virtual ~InternalInterceptorBatchMethods() {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void AddInterceptionHookPoint(
 | 
	
		
			
				|  |  | -      experimental::InterceptionHookPoints type) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendMessage(ByteBuffer* buf) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendInitialMetadata(
 | 
	
		
			
				|  |  | -      std::multimap<grpc::string, grpc::string>* metadata) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendStatus(grpc_status_code* code,
 | 
	
		
			
				|  |  | -                             grpc::string* error_details,
 | 
	
		
			
				|  |  | -                             grpc::string* error_message) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendTrailingMetadata(
 | 
	
		
			
				|  |  | -      std::multimap<grpc::string, grpc::string>* metadata) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvMessage(void* message) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvInitialMetadata(internal::MetadataMap* map) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvStatus(Status* status) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvTrailingMetadata(internal::MetadataMap* map) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual std::unique_ptr<ChannelInterface> GetInterceptedChannel() = 0;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /// Default argument for CallOpSet. I is unused by the class, but can be
 | 
	
		
			
				|  |  |  /// used for generating multiple names for the same thing.
 | 
	
		
			
				|  |  |  template <int I>
 | 
	
	
		
			
				|  | @@ -783,364 +750,11 @@ class CallOpClientRecvStatus {
 | 
	
		
			
				|  |  |    grpc_slice error_message_;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -/// An abstract collection of call ops, used to generate the
 | 
	
		
			
				|  |  | -/// grpc_call_op structure to pass down to the lower layers,
 | 
	
		
			
				|  |  | -/// and as it is-a CompletionQueueTag, also massages the final
 | 
	
		
			
				|  |  | -/// completion into the correct form for consumption in the C++
 | 
	
		
			
				|  |  | -/// API.
 | 
	
		
			
				|  |  | -class CallOpSetInterface : public CompletionQueueTag {
 | 
	
		
			
				|  |  | - public:
 | 
	
		
			
				|  |  | -  /// Fills in grpc_op, starting from ops[*nops] and moving
 | 
	
		
			
				|  |  | -  /// upwards.
 | 
	
		
			
				|  |  | -  virtual void FillOps(internal::Call* call) = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  /// Get the tag to be used at the core completion queue. Generally, the
 | 
	
		
			
				|  |  | -  /// value of cq_tag will be "this". However, it can be overridden if we
 | 
	
		
			
				|  |  | -  /// want core to process the tag differently (e.g., as a core callback)
 | 
	
		
			
				|  |  | -  virtual void* cq_tag() = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // This will be called while interceptors are run if the RPC is a hijacked
 | 
	
		
			
				|  |  | -  // RPC. This should set hijacking state for each of the ops.
 | 
	
		
			
				|  |  | -  virtual void SetHijackingState() = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Should be called after interceptors are done running
 | 
	
		
			
				|  |  | -  virtual void ContinueFillOpsAfterInterception() = 0;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Should be called after interceptors are done running on the finalize result
 | 
	
		
			
				|  |  | -  // path
 | 
	
		
			
				|  |  | -  virtual void ContinueFinalizeResultAfterInterception() = 0;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  template <class Op1 = CallNoOp<1>, class Op2 = CallNoOp<2>,
 | 
	
		
			
				|  |  |            class Op3 = CallNoOp<3>, class Op4 = CallNoOp<4>,
 | 
	
		
			
				|  |  |            class Op5 = CallNoOp<5>, class Op6 = CallNoOp<6>>
 | 
	
		
			
				|  |  |  class CallOpSet;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -class InterceptorBatchMethodsImpl : public InternalInterceptorBatchMethods {
 | 
	
		
			
				|  |  | - public:
 | 
	
		
			
				|  |  | -  InterceptorBatchMethodsImpl() {
 | 
	
		
			
				|  |  | -    for (auto i = 0;
 | 
	
		
			
				|  |  | -         i < static_cast<int>(
 | 
	
		
			
				|  |  | -                 experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS);
 | 
	
		
			
				|  |  | -         i++) {
 | 
	
		
			
				|  |  | -      hooks_[i] = false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual ~InterceptorBatchMethodsImpl() {}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual bool QueryInterceptionHookPoint(
 | 
	
		
			
				|  |  | -      experimental::InterceptionHookPoints type) override {
 | 
	
		
			
				|  |  | -    return hooks_[static_cast<int>(type)];
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void Proceed() override { /* fill this */
 | 
	
		
			
				|  |  | -    if (call_->client_rpc_info() != nullptr) {
 | 
	
		
			
				|  |  | -      return ProceedClient();
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(call_->server_rpc_info() != nullptr);
 | 
	
		
			
				|  |  | -    ProceedServer();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void Hijack() override {
 | 
	
		
			
				|  |  | -    // Only the client can hijack when sending down initial metadata
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(!reverse_ && ops_ != nullptr &&
 | 
	
		
			
				|  |  | -                       call_->client_rpc_info() != nullptr);
 | 
	
		
			
				|  |  | -    // It is illegal to call Hijack twice
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(!ran_hijacking_interceptor_);
 | 
	
		
			
				|  |  | -    auto* rpc_info = call_->client_rpc_info();
 | 
	
		
			
				|  |  | -    rpc_info->hijacked_ = true;
 | 
	
		
			
				|  |  | -    rpc_info->hijacked_interceptor_ = curr_iteration_;
 | 
	
		
			
				|  |  | -    ClearHookPoints();
 | 
	
		
			
				|  |  | -    ops_->SetHijackingState();
 | 
	
		
			
				|  |  | -    ran_hijacking_interceptor_ = true;
 | 
	
		
			
				|  |  | -    rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void AddInterceptionHookPoint(
 | 
	
		
			
				|  |  | -      experimental::InterceptionHookPoints type) override {
 | 
	
		
			
				|  |  | -    hooks_[static_cast<int>(type)] = true;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual ByteBuffer* GetSendMessage() override { return send_message_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata()
 | 
	
		
			
				|  |  | -      override {
 | 
	
		
			
				|  |  | -    return send_initial_metadata_;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual Status GetSendStatus() override {
 | 
	
		
			
				|  |  | -    return Status(static_cast<StatusCode>(*code_), *error_message_,
 | 
	
		
			
				|  |  | -                  *error_details_);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void ModifySendStatus(const Status& status) override {
 | 
	
		
			
				|  |  | -    *code_ = static_cast<grpc_status_code>(status.error_code());
 | 
	
		
			
				|  |  | -    *error_details_ = status.error_details();
 | 
	
		
			
				|  |  | -    *error_message_ = status.error_message();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual std::multimap<grpc::string, grpc::string>* GetSendTrailingMetadata()
 | 
	
		
			
				|  |  | -      override {
 | 
	
		
			
				|  |  | -    return send_trailing_metadata_;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void* GetRecvMessage() override { return recv_message_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual std::multimap<grpc::string_ref, grpc::string_ref>*
 | 
	
		
			
				|  |  | -  GetRecvInitialMetadata() override {
 | 
	
		
			
				|  |  | -    return recv_initial_metadata_->map();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual Status* GetRecvStatus() override { return recv_status_; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual std::multimap<grpc::string_ref, grpc::string_ref>*
 | 
	
		
			
				|  |  | -  GetRecvTrailingMetadata() override {
 | 
	
		
			
				|  |  | -    return recv_trailing_metadata_->map();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendMessage(ByteBuffer* buf) override { send_message_ = buf; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendInitialMetadata(
 | 
	
		
			
				|  |  | -      std::multimap<grpc::string, grpc::string>* metadata) override {
 | 
	
		
			
				|  |  | -    send_initial_metadata_ = metadata;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendStatus(grpc_status_code* code,
 | 
	
		
			
				|  |  | -                             grpc::string* error_details,
 | 
	
		
			
				|  |  | -                             grpc::string* error_message) override {
 | 
	
		
			
				|  |  | -    code_ = code;
 | 
	
		
			
				|  |  | -    error_details_ = error_details;
 | 
	
		
			
				|  |  | -    error_message_ = error_message;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetSendTrailingMetadata(
 | 
	
		
			
				|  |  | -      std::multimap<grpc::string, grpc::string>* metadata) override {
 | 
	
		
			
				|  |  | -    send_trailing_metadata_ = metadata;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvMessage(void* message) override {
 | 
	
		
			
				|  |  | -    recv_message_ = message;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvInitialMetadata(internal::MetadataMap* map) override {
 | 
	
		
			
				|  |  | -    recv_initial_metadata_ = map;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvStatus(Status* status) override { recv_status_ = status; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual void SetRecvTrailingMetadata(internal::MetadataMap* map) override {
 | 
	
		
			
				|  |  | -    recv_trailing_metadata_ = map;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  virtual std::unique_ptr<ChannelInterface> GetInterceptedChannel() override {
 | 
	
		
			
				|  |  | -    auto* info = call_->client_rpc_info();
 | 
	
		
			
				|  |  | -    if (info == nullptr) {
 | 
	
		
			
				|  |  | -      return std::unique_ptr<ChannelInterface>(nullptr);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // The intercepted channel starts from the interceptor just after the
 | 
	
		
			
				|  |  | -    // current interceptor
 | 
	
		
			
				|  |  | -    return std::unique_ptr<ChannelInterface>(new internal::InterceptedChannel(
 | 
	
		
			
				|  |  | -        reinterpret_cast<grpc::ChannelInterface*>(info->channel()),
 | 
	
		
			
				|  |  | -        curr_iteration_ + 1));
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Clears all state
 | 
	
		
			
				|  |  | -  void ClearState() {
 | 
	
		
			
				|  |  | -    reverse_ = false;
 | 
	
		
			
				|  |  | -    ran_hijacking_interceptor_ = false;
 | 
	
		
			
				|  |  | -    ClearHookPoints();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Prepares for Post_recv operations
 | 
	
		
			
				|  |  | -  void SetReverse() {
 | 
	
		
			
				|  |  | -    reverse_ = true;
 | 
	
		
			
				|  |  | -    ran_hijacking_interceptor_ = false;
 | 
	
		
			
				|  |  | -    ClearHookPoints();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // This needs to be set before interceptors are run
 | 
	
		
			
				|  |  | -  void SetCall(Call* call) { call_ = call; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // This needs to be set before interceptors are run using RunInterceptors().
 | 
	
		
			
				|  |  | -  // Alternatively, RunInterceptors(std::function<void(void)> f) can be used.
 | 
	
		
			
				|  |  | -  void SetCallOpSetInterface(CallOpSetInterface* ops) { ops_ = ops; }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Returns true if no interceptors are run. This should be used only by
 | 
	
		
			
				|  |  | -  // subclasses of CallOpSetInterface. SetCall and SetCallOpSetInterface should
 | 
	
		
			
				|  |  | -  // have been called before this. After all the interceptors are done running,
 | 
	
		
			
				|  |  | -  // either ContinueFillOpsAfterInterception or
 | 
	
		
			
				|  |  | -  // ContinueFinalizeOpsAfterInterception will be called. Note that neither of
 | 
	
		
			
				|  |  | -  // them is invoked if there were no interceptors registered.
 | 
	
		
			
				|  |  | -  bool RunInterceptors() {
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(ops_);
 | 
	
		
			
				|  |  | -    auto* client_rpc_info = call_->client_rpc_info();
 | 
	
		
			
				|  |  | -    if (client_rpc_info != nullptr) {
 | 
	
		
			
				|  |  | -      if (client_rpc_info->interceptors_.size() == 0) {
 | 
	
		
			
				|  |  | -        return true;
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        RunClientInterceptors();
 | 
	
		
			
				|  |  | -        return false;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -    auto* server_rpc_info = call_->server_rpc_info();
 | 
	
		
			
				|  |  | -    if (server_rpc_info == nullptr ||
 | 
	
		
			
				|  |  | -        server_rpc_info->interceptors_.size() == 0) {
 | 
	
		
			
				|  |  | -      return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    RunServerInterceptors();
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  // Returns true if no interceptors are run. Returns false otherwise if there
 | 
	
		
			
				|  |  | -  // are interceptors registered. After the interceptors are done running \a f
 | 
	
		
			
				|  |  | -  // will be invoked. This is to be used only by BaseAsyncRequest and
 | 
	
		
			
				|  |  | -  // SyncRequest.
 | 
	
		
			
				|  |  | -  bool RunInterceptors(std::function<void(void)> f) {
 | 
	
		
			
				|  |  | -    // This is used only by the server for initial call request
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(reverse_ == true);
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(call_->client_rpc_info() == nullptr);
 | 
	
		
			
				|  |  | -    auto* server_rpc_info = call_->server_rpc_info();
 | 
	
		
			
				|  |  | -    if (server_rpc_info == nullptr ||
 | 
	
		
			
				|  |  | -        server_rpc_info->interceptors_.size() == 0) {
 | 
	
		
			
				|  |  | -      return true;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    callback_ = std::move(f);
 | 
	
		
			
				|  |  | -    RunServerInterceptors();
 | 
	
		
			
				|  |  | -    return false;
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | - private:
 | 
	
		
			
				|  |  | -  void RunClientInterceptors() {
 | 
	
		
			
				|  |  | -    auto* rpc_info = call_->client_rpc_info();
 | 
	
		
			
				|  |  | -    if (!reverse_) {
 | 
	
		
			
				|  |  | -      curr_iteration_ = 0;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      if (rpc_info->hijacked_) {
 | 
	
		
			
				|  |  | -        curr_iteration_ = rpc_info->hijacked_interceptor_;
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        curr_iteration_ = rpc_info->interceptors_.size() - 1;
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  void RunServerInterceptors() {
 | 
	
		
			
				|  |  | -    auto* rpc_info = call_->server_rpc_info();
 | 
	
		
			
				|  |  | -    if (!reverse_) {
 | 
	
		
			
				|  |  | -      curr_iteration_ = 0;
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      curr_iteration_ = rpc_info->interceptors_.size() - 1;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  void ProceedClient() {
 | 
	
		
			
				|  |  | -    auto* rpc_info = call_->client_rpc_info();
 | 
	
		
			
				|  |  | -    if (rpc_info->hijacked_ && !reverse_ &&
 | 
	
		
			
				|  |  | -        curr_iteration_ == rpc_info->hijacked_interceptor_ &&
 | 
	
		
			
				|  |  | -        !ran_hijacking_interceptor_) {
 | 
	
		
			
				|  |  | -      // We now need to provide hijacked recv ops to this interceptor
 | 
	
		
			
				|  |  | -      ClearHookPoints();
 | 
	
		
			
				|  |  | -      ops_->SetHijackingState();
 | 
	
		
			
				|  |  | -      ran_hijacking_interceptor_ = true;
 | 
	
		
			
				|  |  | -      rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -      return;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (!reverse_) {
 | 
	
		
			
				|  |  | -      curr_iteration_++;
 | 
	
		
			
				|  |  | -      // We are going down the stack of interceptors
 | 
	
		
			
				|  |  | -      if (curr_iteration_ < static_cast<long>(rpc_info->interceptors_.size())) {
 | 
	
		
			
				|  |  | -        if (rpc_info->hijacked_ &&
 | 
	
		
			
				|  |  | -            curr_iteration_ > rpc_info->hijacked_interceptor_) {
 | 
	
		
			
				|  |  | -          // This is a hijacked RPC and we are done with hijacking
 | 
	
		
			
				|  |  | -          ops_->ContinueFillOpsAfterInterception();
 | 
	
		
			
				|  |  | -        } else {
 | 
	
		
			
				|  |  | -          rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        // we are done running all the interceptors without any hijacking
 | 
	
		
			
				|  |  | -        ops_->ContinueFillOpsAfterInterception();
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      curr_iteration_--;
 | 
	
		
			
				|  |  | -      // We are going up the stack of interceptors
 | 
	
		
			
				|  |  | -      if (curr_iteration_ >= 0) {
 | 
	
		
			
				|  |  | -        // Continue running interceptors
 | 
	
		
			
				|  |  | -        rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        // we are done running all the interceptors without any hijacking
 | 
	
		
			
				|  |  | -        ops_->ContinueFinalizeResultAfterInterception();
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  void ProceedServer() {
 | 
	
		
			
				|  |  | -    auto* rpc_info = call_->server_rpc_info();
 | 
	
		
			
				|  |  | -    if (!reverse_) {
 | 
	
		
			
				|  |  | -      curr_iteration_++;
 | 
	
		
			
				|  |  | -      if (curr_iteration_ < static_cast<long>(rpc_info->interceptors_.size())) {
 | 
	
		
			
				|  |  | -        return rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -      } else if (ops_) {
 | 
	
		
			
				|  |  | -        return ops_->ContinueFillOpsAfterInterception();
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      curr_iteration_--;
 | 
	
		
			
				|  |  | -      // We are going up the stack of interceptors
 | 
	
		
			
				|  |  | -      if (curr_iteration_ >= 0) {
 | 
	
		
			
				|  |  | -        // Continue running interceptors
 | 
	
		
			
				|  |  | -        return rpc_info->RunInterceptor(this, curr_iteration_);
 | 
	
		
			
				|  |  | -      } else if (ops_) {
 | 
	
		
			
				|  |  | -        return ops_->ContinueFinalizeResultAfterInterception();
 | 
	
		
			
				|  |  | -      }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    GPR_CODEGEN_ASSERT(callback_);
 | 
	
		
			
				|  |  | -    callback_();
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  void ClearHookPoints() {
 | 
	
		
			
				|  |  | -    for (auto i = 0;
 | 
	
		
			
				|  |  | -         i < static_cast<int>(
 | 
	
		
			
				|  |  | -                 experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS);
 | 
	
		
			
				|  |  | -         i++) {
 | 
	
		
			
				|  |  | -      hooks_[i] = false;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -  }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  std::array<bool,
 | 
	
		
			
				|  |  | -             static_cast<int>(
 | 
	
		
			
				|  |  | -                 experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS)>
 | 
	
		
			
				|  |  | -      hooks_;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  int curr_iteration_ = 0;  // Current iterator
 | 
	
		
			
				|  |  | -  bool reverse_ = false;
 | 
	
		
			
				|  |  | -  bool ran_hijacking_interceptor_ = false;
 | 
	
		
			
				|  |  | -  Call* call_ =
 | 
	
		
			
				|  |  | -      nullptr;  // The Call object is present along with CallOpSet object
 | 
	
		
			
				|  |  | -  CallOpSetInterface* ops_ = nullptr;
 | 
	
		
			
				|  |  | -  std::function<void(void)> callback_;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  ByteBuffer* send_message_ = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  std::multimap<grpc::string, grpc::string>* send_initial_metadata_;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  grpc_status_code* code_ = nullptr;
 | 
	
		
			
				|  |  | -  grpc::string* error_details_ = nullptr;
 | 
	
		
			
				|  |  | -  grpc::string* error_message_ = nullptr;
 | 
	
		
			
				|  |  | -  Status send_status_;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  std::multimap<grpc::string, grpc::string>* send_trailing_metadata_ = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  void* recv_message_ = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  internal::MetadataMap* recv_initial_metadata_ = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  Status* recv_status_ = nullptr;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  internal::MetadataMap* recv_trailing_metadata_ = nullptr;
 | 
	
		
			
				|  |  | -};
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  /// Primary implementation of CallOpSetInterface.
 | 
	
		
			
				|  |  |  /// Since we cannot use variadic templates, we declare slots up to
 | 
	
		
			
				|  |  |  /// the maximum count of ops we'll need in a set. We leverage the
 |