Revert grpc upgrade

Due to a grpc bug breaking Bazel inside docer in Bazel 3.4.0, we have to revert the upgrade of grpc 1.26.0

Revert third_party/grpc/BUILD

This partially reverts commit 2ed3980.

Revert "Upgrade gRPC to 1.26.0"

This reverts commit dfbf87c9196a15d491e9cbb81ee2d3da416cc0c2.

Closes https://github.com/bazelbuild/bazel/pull/11758
diff --git a/third_party/grpc/include/grpcpp/impl/README.md b/third_party/grpc/include/grpcpp/impl/README.md
new file mode 100644
index 0000000..612150c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/README.md
@@ -0,0 +1,4 @@
+**The APIs in this directory are not stable!**
+
+This directory contains header files that need to be installed but are not part
+of the public API. Users should not use these headers directly.
diff --git a/third_party/grpc/include/grpcpp/impl/call.h b/third_party/grpc/include/grpcpp/impl/call.h
new file mode 100644
index 0000000..a6b1312
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/call.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_CALL_H
+#define GRPCPP_IMPL_CALL_H
+
+#include <grpcpp/impl/codegen/call.h>
+
+#endif  // GRPCPP_IMPL_CALL_H
diff --git a/third_party/grpc/include/grpcpp/impl/channel_argument_option.h b/third_party/grpc/include/grpcpp/impl/channel_argument_option.h
new file mode 100644
index 0000000..0c48824
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/channel_argument_option.h
@@ -0,0 +1,37 @@
+/*
+ *
+ * Copyright 2017 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_CHANNEL_ARGUMENT_OPTION_H
+#define GRPCPP_IMPL_CHANNEL_ARGUMENT_OPTION_H
+
+#include <map>
+#include <memory>
+
+#include <grpcpp/impl/server_builder_option.h>
+#include <grpcpp/support/channel_arguments.h>
+
+namespace grpc {
+
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+    const grpc::string& name, const grpc::string& value);
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+    const grpc::string& name, int value);
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CHANNEL_ARGUMENT_OPTION_H
diff --git a/third_party/grpc/include/grpcpp/impl/client_unary_call.h b/third_party/grpc/include/grpcpp/impl/client_unary_call.h
new file mode 100644
index 0000000..378482c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/client_unary_call.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_CLIENT_UNARY_CALL_H
+#define GRPCPP_IMPL_CLIENT_UNARY_CALL_H
+
+#include <grpcpp/impl/codegen/client_unary_call.h>
+
+#endif  // GRPCPP_IMPL_CLIENT_UNARY_CALL_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/async_generic_service.h b/third_party/grpc/include/grpcpp/impl/codegen/async_generic_service.h
new file mode 100644
index 0000000..2a0e1b4
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/async_generic_service.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * Copyright 2015 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_ASYNC_GENERIC_SERVICE_H
+#define GRPCPP_IMPL_CODEGEN_ASYNC_GENERIC_SERVICE_H
+
+#include <grpcpp/impl/codegen/async_stream.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+
+struct grpc_server;
+
+namespace grpc {
+
+typedef ServerAsyncReaderWriter<ByteBuffer, ByteBuffer>
+    GenericServerAsyncReaderWriter;
+typedef ServerAsyncResponseWriter<ByteBuffer> GenericServerAsyncResponseWriter;
+typedef ServerAsyncReader<ByteBuffer, ByteBuffer> GenericServerAsyncReader;
+typedef ServerAsyncWriter<ByteBuffer> GenericServerAsyncWriter;
+
+class GenericServerContext final : public ServerContext {
+ public:
+  const grpc::string& method() const { return method_; }
+  const grpc::string& host() const { return host_; }
+
+ private:
+  friend class Server;
+  friend class ServerInterface;
+
+  grpc::string method_;
+  grpc::string host_;
+};
+
+// A generic service at the server side accepts all RPC methods and hosts. It is
+// typically used in proxies. The generic service can be registered to a server
+// which also has other services.
+// Sample usage:
+//   ServerBuilder builder;
+//   auto cq = builder.AddCompletionQueue();
+//   AsyncGenericService generic_service;
+//   builder.RegisterAsyncGenericService(&generic_service);
+//   auto server = builder.BuildAndStart();
+//
+//   // request a new call
+//   GenericServerContext context;
+//   GenericServerAsyncReaderWriter stream;
+//   generic_service.RequestCall(&context, &stream, cq.get(), cq.get(), tag);
+//
+// When tag is retrieved from cq->Next(), context.method() can be used to look
+// at the method and the RPC can be handled accordingly.
+class AsyncGenericService final {
+ public:
+  AsyncGenericService() : server_(nullptr) {}
+
+  void RequestCall(GenericServerContext* ctx,
+                   GenericServerAsyncReaderWriter* reader_writer,
+                   CompletionQueue* call_cq,
+                   ServerCompletionQueue* notification_cq, void* tag);
+
+ private:
+  friend class Server;
+  Server* server_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_ASYNC_GENERIC_SERVICE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/async_stream.h b/third_party/grpc/include/grpcpp/impl/codegen/async_stream.h
new file mode 100644
index 0000000..bfb2df4
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/async_stream.h
@@ -0,0 +1,1134 @@
+/*
+ *
+ * Copyright 2015 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_ASYNC_STREAM_H
+#define GRPCPP_IMPL_CODEGEN_ASYNC_STREAM_H
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class CompletionQueue;
+
+namespace internal {
+/// Common interface for all client side asynchronous streaming.
+class ClientAsyncStreamingInterface {
+ public:
+  virtual ~ClientAsyncStreamingInterface() {}
+
+  /// Start the call that was set up by the constructor, but only if the
+  /// constructor was invoked through the "Prepare" API which doesn't actually
+  /// start the call
+  virtual void StartCall(void* tag) = 0;
+
+  /// Request notification of the reading of the initial metadata. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a AsyncReaderInterface::Read method.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  virtual void ReadInitialMetadata(void* tag) = 0;
+
+  /// Indicate that the stream is to be finished and request notification for
+  /// when the call has been ended.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when both:
+  ///   * the client side has no more message to send
+  ///     (this can be declared implicitly by calling this method, or
+  ///     explicitly through an earlier call to the <i>WritesDone</i> method
+  ///     of the class in use, e.g. \a ClientAsyncWriterInterface::WritesDone or
+  ///     \a ClientAsyncReaderWriterInterface::WritesDone).
+  ///   * there are no more messages to be received from the server (this can
+  ///     be known implicitly by the calling code, or explicitly from an
+  ///     earlier call to \a AsyncReaderInterface::Read that yielded a failed
+  ///     result, e.g. cq->Next(&read_tag, &ok) filled in 'ok' with 'false').
+  ///
+  /// The tag will be returned when either:
+  /// - all incoming messages have been read and the server has returned
+  ///   a status.
+  /// - the server has returned a non-OK status.
+  /// - the call failed for some reason and the library generated a
+  ///   status.
+  ///
+  /// Note that implementations of this method attempt to receive initial
+  /// metadata from the server if initial metadata hasn't yet been received.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[out] status To be updated with the operation status.
+  virtual void Finish(Status* status, void* tag) = 0;
+};
+
+/// An interface that yields a sequence of messages of type \a R.
+template <class R>
+class AsyncReaderInterface {
+ public:
+  virtual ~AsyncReaderInterface() {}
+
+  /// Read a message of type \a R into \a msg. Completion will be notified by \a
+  /// tag on the associated completion queue.
+  /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+  /// should not be called concurrently with other streaming APIs
+  /// on the same stream. It is not meaningful to call it concurrently
+  /// with another \a AsyncReaderInterface::Read on the same stream since reads
+  /// on the same stream are delivered in order.
+  ///
+  /// \param[out] msg Where to eventually store the read message.
+  /// \param[in] tag The tag identifying the operation.
+  ///
+  /// Side effect: note that this method attempt to receive initial metadata for
+  /// a stream if it hasn't yet been received.
+  virtual void Read(R* msg, void* tag) = 0;
+};
+
+/// An interface that can be fed a sequence of messages of type \a W.
+template <class W>
+class AsyncWriterInterface {
+ public:
+  virtual ~AsyncWriterInterface() {}
+
+  /// Request the writing of \a msg with identifying tag \a tag.
+  ///
+  /// Only one write may be outstanding at any given time. This means that
+  /// after calling Write, one must wait to receive \a tag from the completion
+  /// queue BEFORE calling Write again.
+  /// This is thread-safe with respect to \a AsyncReaderInterface::Read
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg, so it is safe to
+  /// to deallocate once Write returns.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] tag The tag identifying the operation.
+  virtual void Write(const W& msg, void* tag) = 0;
+
+  /// Request the writing of \a msg using WriteOptions \a options with
+  /// identifying tag \a tag.
+  ///
+  /// Only one write may be outstanding at any given time. This means that
+  /// after calling Write, one must wait to receive \a tag from the completion
+  /// queue BEFORE calling Write again.
+  /// WriteOptions \a options is used to set the write options of this message.
+  /// This is thread-safe with respect to \a AsyncReaderInterface::Read
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg, so it is safe to
+  /// to deallocate once Write returns.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  /// \param[in] tag The tag identifying the operation.
+  virtual void Write(const W& msg, WriteOptions options, void* tag) = 0;
+
+  /// Request the writing of \a msg and coalesce it with the writing
+  /// of trailing metadata, using WriteOptions \a options with
+  /// identifying tag \a tag.
+  ///
+  /// For client, WriteLast is equivalent of performing Write and
+  /// WritesDone in a single step.
+  /// For server, WriteLast buffers the \a msg. The writing of \a msg is held
+  /// until Finish is called, where \a msg and trailing metadata are coalesced
+  /// and write is initiated. Note that WriteLast can only buffer \a msg up to
+  /// the flow control window size. If \a msg size is larger than the window
+  /// size, it will be sent on wire without buffering.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg, so it is safe to
+  /// to deallocate once Write returns.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  /// \param[in] tag The tag identifying the operation.
+  void WriteLast(const W& msg, WriteOptions options, void* tag) {
+    Write(msg, options.set_last_message(), tag);
+  }
+};
+
+}  // namespace internal
+
+template <class R>
+class ClientAsyncReaderInterface
+    : public internal::ClientAsyncStreamingInterface,
+      public internal::AsyncReaderInterface<R> {};
+
+namespace internal {
+template <class R>
+class ClientAsyncReaderFactory {
+ public:
+  /// Create a stream object.
+  /// Write the first request out if \a start is set.
+  /// \a tag will be notified on \a cq when the call has been started and
+  /// \a request has been written out. If \a start is not set, \a tag must be
+  /// nullptr and the actual call must be initiated by StartCall
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  template <class W>
+  static ClientAsyncReader<R>* Create(ChannelInterface* channel,
+                                      CompletionQueue* cq,
+                                      const ::grpc::internal::RpcMethod& method,
+                                      ClientContext* context, const W& request,
+                                      bool start, void* tag) {
+    ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncReader<R>)))
+        ClientAsyncReader<R>(call, context, request, start, tag);
+  }
+};
+}  // namespace internal
+
+/// Async client-side API for doing server-streaming RPCs,
+/// where the incoming message stream coming from the server has
+/// messages of type \a R.
+template <class R>
+class ClientAsyncReader final : public ClientAsyncReaderInterface<R> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientAsyncReader));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void StartCall(void* tag) override {
+    assert(!started_);
+    started_ = true;
+    StartCallInternal(tag);
+  }
+
+  /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata
+  /// method for semantics.
+  ///
+  /// Side effect:
+  ///   - upon receiving initial metadata from the server,
+  ///     the \a ClientContext associated with this call is updated, and the
+  ///     calling code can access the received metadata through the
+  ///     \a ClientContext.
+  void ReadInitialMetadata(void* tag) override {
+    assert(started_);
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    meta_ops_.set_output_tag(tag);
+    meta_ops_.RecvInitialMetadata(context_);
+    call_.PerformOps(&meta_ops_);
+  }
+
+  void Read(R* msg, void* tag) override {
+    assert(started_);
+    read_ops_.set_output_tag(tag);
+    if (!context_->initial_metadata_received_) {
+      read_ops_.RecvInitialMetadata(context_);
+    }
+    read_ops_.RecvMessage(msg);
+    call_.PerformOps(&read_ops_);
+  }
+
+  /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata received from the server.
+  void Finish(Status* status, void* tag) override {
+    assert(started_);
+    finish_ops_.set_output_tag(tag);
+    if (!context_->initial_metadata_received_) {
+      finish_ops_.RecvInitialMetadata(context_);
+    }
+    finish_ops_.ClientRecvStatus(context_, status);
+    call_.PerformOps(&finish_ops_);
+  }
+
+ private:
+  friend class internal::ClientAsyncReaderFactory<R>;
+  template <class W>
+  ClientAsyncReader(::grpc::internal::Call call, ClientContext* context,
+                    const W& request, bool start, void* tag)
+      : context_(context), call_(call), started_(start) {
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
+    init_ops_.ClientSendClose();
+    if (start) {
+      StartCallInternal(tag);
+    } else {
+      assert(tag == nullptr);
+    }
+  }
+
+  void StartCallInternal(void* tag) {
+    init_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                  context_->initial_metadata_flags());
+    init_ops_.set_output_tag(tag);
+    call_.PerformOps(&init_ops_);
+  }
+
+  ClientContext* context_;
+  ::grpc::internal::Call call_;
+  bool started_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpClientSendClose>
+      init_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+      meta_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpRecvMessage<R>>
+      read_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpClientRecvStatus>
+      finish_ops_;
+};
+
+/// Common interface for client side asynchronous writing.
+template <class W>
+class ClientAsyncWriterInterface
+    : public internal::ClientAsyncStreamingInterface,
+      public internal::AsyncWriterInterface<W> {
+ public:
+  /// Signal the client is done with the writes (half-close the client stream).
+  /// Thread-safe with respect to \a AsyncReaderInterface::Read
+  ///
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WritesDone(void* tag) = 0;
+};
+
+namespace internal {
+template <class W>
+class ClientAsyncWriterFactory {
+ public:
+  /// Create a stream object.
+  /// Start the RPC if \a start is set
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent) and \a request has been written out.
+  /// If \a start is not set, \a tag must be nullptr and the actual call
+  /// must be initiated by StartCall
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  /// \a response will be filled in with the single expected response
+  /// message from the server upon a successful call to the \a Finish
+  /// method of this instance.
+  template <class R>
+  static ClientAsyncWriter<W>* Create(ChannelInterface* channel,
+                                      CompletionQueue* cq,
+                                      const ::grpc::internal::RpcMethod& method,
+                                      ClientContext* context, R* response,
+                                      bool start, void* tag) {
+    ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncWriter<W>)))
+        ClientAsyncWriter<W>(call, context, response, start, tag);
+  }
+};
+}  // namespace internal
+
+/// Async API on the client side for doing client-streaming RPCs,
+/// where the outgoing message stream going to the server contains
+/// messages of type \a W.
+template <class W>
+class ClientAsyncWriter final : public ClientAsyncWriterInterface<W> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientAsyncWriter));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void StartCall(void* tag) override {
+    assert(!started_);
+    started_ = true;
+    StartCallInternal(tag);
+  }
+
+  /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method for
+  /// semantics.
+  ///
+  /// Side effect:
+  ///   - upon receiving initial metadata from the server, the \a ClientContext
+  ///     associated with this call is updated, and the calling code can access
+  ///     the received metadata through the \a ClientContext.
+  void ReadInitialMetadata(void* tag) override {
+    assert(started_);
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    meta_ops_.set_output_tag(tag);
+    meta_ops_.RecvInitialMetadata(context_);
+    call_.PerformOps(&meta_ops_);
+  }
+
+  void Write(const W& msg, void* tag) override {
+    assert(started_);
+    write_ops_.set_output_tag(tag);
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  void Write(const W& msg, WriteOptions options, void* tag) override {
+    assert(started_);
+    write_ops_.set_output_tag(tag);
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+      write_ops_.ClientSendClose();
+    }
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  void WritesDone(void* tag) override {
+    assert(started_);
+    write_ops_.set_output_tag(tag);
+    write_ops_.ClientSendClose();
+    call_.PerformOps(&write_ops_);
+  }
+
+  /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata received from the server.
+  ///   - attempts to fill in the \a response parameter passed to this class's
+  ///     constructor with the server's response message.
+  void Finish(Status* status, void* tag) override {
+    assert(started_);
+    finish_ops_.set_output_tag(tag);
+    if (!context_->initial_metadata_received_) {
+      finish_ops_.RecvInitialMetadata(context_);
+    }
+    finish_ops_.ClientRecvStatus(context_, status);
+    call_.PerformOps(&finish_ops_);
+  }
+
+ private:
+  friend class internal::ClientAsyncWriterFactory<W>;
+  template <class R>
+  ClientAsyncWriter(::grpc::internal::Call call, ClientContext* context,
+                    R* response, bool start, void* tag)
+      : context_(context), call_(call), started_(start) {
+    finish_ops_.RecvMessage(response);
+    finish_ops_.AllowNoMessage();
+    if (start) {
+      StartCallInternal(tag);
+    } else {
+      assert(tag == nullptr);
+    }
+  }
+
+  void StartCallInternal(void* tag) {
+    write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                   context_->initial_metadata_flags());
+    // if corked bit is set in context, we just keep the initial metadata
+    // buffered up to coalesce with later message send. No op is performed.
+    if (!context_->initial_metadata_corked_) {
+      write_ops_.set_output_tag(tag);
+      call_.PerformOps(&write_ops_);
+    }
+  }
+
+  ClientContext* context_;
+  ::grpc::internal::Call call_;
+  bool started_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+      meta_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpClientSendClose>
+      write_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpGenericRecvMessage,
+                              ::grpc::internal::CallOpClientRecvStatus>
+      finish_ops_;
+};
+
+/// Async client-side interface for bi-directional streaming,
+/// where the client-to-server message stream has messages of type \a W,
+/// and the server-to-client message stream has messages of type \a R.
+template <class W, class R>
+class ClientAsyncReaderWriterInterface
+    : public internal::ClientAsyncStreamingInterface,
+      public internal::AsyncWriterInterface<W>,
+      public internal::AsyncReaderInterface<R> {
+ public:
+  /// Signal the client is done with the writes (half-close the client stream).
+  /// Thread-safe with respect to \a AsyncReaderInterface::Read
+  ///
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WritesDone(void* tag) = 0;
+};
+
+namespace internal {
+template <class W, class R>
+class ClientAsyncReaderWriterFactory {
+ public:
+  /// Create a stream object.
+  /// Start the RPC request if \a start is set.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent). If \a start is not set, \a tag must be
+  /// nullptr and the actual call must be initiated by StartCall
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  static ClientAsyncReaderWriter<W, R>* Create(
+      ChannelInterface* channel, CompletionQueue* cq,
+      const ::grpc::internal::RpcMethod& method, ClientContext* context,
+      bool start, void* tag) {
+    ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncReaderWriter<W, R>)))
+        ClientAsyncReaderWriter<W, R>(call, context, start, tag);
+  }
+};
+}  // namespace internal
+
+/// Async client-side interface for bi-directional streaming,
+/// where the outgoing message stream going to the server
+/// has messages of type \a W,  and the incoming message stream coming
+/// from the server has messages of type \a R.
+template <class W, class R>
+class ClientAsyncReaderWriter final
+    : public ClientAsyncReaderWriterInterface<W, R> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientAsyncReaderWriter));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void StartCall(void* tag) override {
+    assert(!started_);
+    started_ = true;
+    StartCallInternal(tag);
+  }
+
+  /// See the \a ClientAsyncStreamingInterface.ReadInitialMetadata method
+  /// for semantics of this method.
+  ///
+  /// Side effect:
+  ///   - upon receiving initial metadata from the server, the \a ClientContext
+  ///     is updated with it, and then the receiving initial metadata can
+  ///     be accessed through this \a ClientContext.
+  void ReadInitialMetadata(void* tag) override {
+    assert(started_);
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    meta_ops_.set_output_tag(tag);
+    meta_ops_.RecvInitialMetadata(context_);
+    call_.PerformOps(&meta_ops_);
+  }
+
+  void Read(R* msg, void* tag) override {
+    assert(started_);
+    read_ops_.set_output_tag(tag);
+    if (!context_->initial_metadata_received_) {
+      read_ops_.RecvInitialMetadata(context_);
+    }
+    read_ops_.RecvMessage(msg);
+    call_.PerformOps(&read_ops_);
+  }
+
+  void Write(const W& msg, void* tag) override {
+    assert(started_);
+    write_ops_.set_output_tag(tag);
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  void Write(const W& msg, WriteOptions options, void* tag) override {
+    assert(started_);
+    write_ops_.set_output_tag(tag);
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+      write_ops_.ClientSendClose();
+    }
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  void WritesDone(void* tag) override {
+    assert(started_);
+    write_ops_.set_output_tag(tag);
+    write_ops_.ClientSendClose();
+    call_.PerformOps(&write_ops_);
+  }
+
+  /// See the \a ClientAsyncStreamingInterface.Finish method for semantics.
+  /// Side effect
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata sent from the server.
+  void Finish(Status* status, void* tag) override {
+    assert(started_);
+    finish_ops_.set_output_tag(tag);
+    if (!context_->initial_metadata_received_) {
+      finish_ops_.RecvInitialMetadata(context_);
+    }
+    finish_ops_.ClientRecvStatus(context_, status);
+    call_.PerformOps(&finish_ops_);
+  }
+
+ private:
+  friend class internal::ClientAsyncReaderWriterFactory<W, R>;
+  ClientAsyncReaderWriter(::grpc::internal::Call call, ClientContext* context,
+                          bool start, void* tag)
+      : context_(context), call_(call), started_(start) {
+    if (start) {
+      StartCallInternal(tag);
+    } else {
+      assert(tag == nullptr);
+    }
+  }
+
+  void StartCallInternal(void* tag) {
+    write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                   context_->initial_metadata_flags());
+    // if corked bit is set in context, we just keep the initial metadata
+    // buffered up to coalesce with later message send. No op is performed.
+    if (!context_->initial_metadata_corked_) {
+      write_ops_.set_output_tag(tag);
+      call_.PerformOps(&write_ops_);
+    }
+  }
+
+  ClientContext* context_;
+  ::grpc::internal::Call call_;
+  bool started_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+      meta_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpRecvMessage<R>>
+      read_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpClientSendClose>
+      write_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpClientRecvStatus>
+      finish_ops_;
+};
+
+template <class W, class R>
+class ServerAsyncReaderInterface
+    : public internal::ServerAsyncStreamingInterface,
+      public internal::AsyncReaderInterface<R> {
+ public:
+  /// Indicate that the stream is to be finished with a certain status code
+  /// and also send out \a msg response to the client.
+  /// Request notification for when the server has sent the response and the
+  /// appropriate signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous
+  ///     \a AsyncReaderInterface::Read operation with a non-ok result,
+  ///     e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false').
+  ///
+  /// This operation will end when the server has finished sending out initial
+  /// metadata (if not sent already), response message, and status, or if
+  /// some failure occurred when trying to do so.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg or \a status, so it
+  /// is safe to to deallocate once Finish returns.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  /// \param[in] msg To be sent to the client as the response for this call.
+  virtual void Finish(const W& msg, const Status& status, void* tag) = 0;
+
+  /// Indicate that the stream is to be finished with a certain
+  /// non-OK status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// This call is meant to end the call with some error, and can be called at
+  /// any point that the server would like to "fail" the call (though note
+  /// this shouldn't be called concurrently with any other "sending" call, like
+  /// \a AsyncWriterInterface::Write).
+  ///
+  /// This operation will end when the server has finished sending out initial
+  /// metadata (if not sent already), and status, or if some failure occurred
+  /// when trying to do so.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a status, so it is safe to
+  /// to deallocate once FinishWithError returns.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  ///     - Note: \a status must have a non-OK code.
+  virtual void FinishWithError(const Status& status, void* tag) = 0;
+};
+
+/// Async server-side API for doing client-streaming RPCs,
+/// where the incoming message stream from the client has messages of type \a R,
+/// and the single response message sent from the server is type \a W.
+template <class W, class R>
+class ServerAsyncReader final : public ServerAsyncReaderInterface<W, R> {
+ public:
+  explicit ServerAsyncReader(ServerContext* ctx)
+      : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+  /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - The initial metadata that will be sent to the client from this op will
+  ///     be taken from the \a ServerContext associated with the call.
+  void SendInitialMetadata(void* tag) override {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    meta_ops_.set_output_tag(tag);
+    meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      meta_ops_.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_.PerformOps(&meta_ops_);
+  }
+
+  void Read(R* msg, void* tag) override {
+    read_ops_.set_output_tag(tag);
+    read_ops_.RecvMessage(msg);
+    call_.PerformOps(&read_ops_);
+  }
+
+  /// See the \a ServerAsyncReaderInterface.Read method for semantics
+  ///
+  /// Side effect:
+  ///   - also sends initial metadata if not alreay sent.
+  ///   - uses the \a ServerContext associated with this call to send possible
+  ///     initial and trailing metadata.
+  ///
+  /// Note: \a msg is not sent if \a status has a non-OK code.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg and \a status, so it
+  /// is safe to to deallocate once Finish returns.
+  void Finish(const W& msg, const Status& status, void* tag) override {
+    finish_ops_.set_output_tag(tag);
+    if (!ctx_->sent_initial_metadata_) {
+      finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        finish_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+    // The response is dropped if the status is not OK.
+    if (status.ok()) {
+      finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
+                                   finish_ops_.SendMessage(msg));
+    } else {
+      finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    }
+    call_.PerformOps(&finish_ops_);
+  }
+
+  /// See the \a ServerAsyncReaderInterface.Read method for semantics
+  ///
+  /// Side effect:
+  ///   - also sends initial metadata if not alreay sent.
+  ///   - uses the \a ServerContext associated with this call to send possible
+  ///     initial and trailing metadata.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a status, so it is safe to
+  /// to deallocate once FinishWithError returns.
+  void FinishWithError(const Status& status, void* tag) override {
+    GPR_CODEGEN_ASSERT(!status.ok());
+    finish_ops_.set_output_tag(tag);
+    if (!ctx_->sent_initial_metadata_) {
+      finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        finish_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+    finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    call_.PerformOps(&finish_ops_);
+  }
+
+ private:
+  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+  ::grpc::internal::Call call_;
+  ServerContext* ctx_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+      meta_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpServerSendStatus>
+      finish_ops_;
+};
+
+template <class W>
+class ServerAsyncWriterInterface
+    : public internal::ServerAsyncStreamingInterface,
+      public internal::AsyncWriterInterface<W> {
+ public:
+  /// Indicate that the stream is to be finished with a certain status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when either:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a
+  ///     AsyncReaderInterface::Read operation with a non-ok
+  ///     result (e.g., cq->Next(&read_tag, &ok) filled in 'ok' with 'false'.
+  ///   * it is desired to end the call early with some non-OK status code.
+  ///
+  /// This operation will end when the server has finished sending out initial
+  /// metadata (if not sent already), response message, and status, or if
+  /// some failure occurred when trying to do so.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a status, so it is safe to
+  /// to deallocate once Finish returns.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  virtual void Finish(const Status& status, void* tag) = 0;
+
+  /// Request the writing of \a msg and coalesce it with trailing metadata which
+  /// contains \a status, using WriteOptions options with
+  /// identifying tag \a tag.
+  ///
+  /// WriteAndFinish is equivalent of performing WriteLast and Finish
+  /// in a single step.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg and \a status, so it
+  /// is safe to to deallocate once WriteAndFinish returns.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  /// \param[in] status The Status that server returns to client.
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WriteAndFinish(const W& msg, WriteOptions options,
+                              const Status& status, void* tag) = 0;
+};
+
+/// Async server-side API for doing server streaming RPCs,
+/// where the outgoing message stream from the server has messages of type \a W.
+template <class W>
+class ServerAsyncWriter final : public ServerAsyncWriterInterface<W> {
+ public:
+  explicit ServerAsyncWriter(ServerContext* ctx)
+      : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+  /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - The initial metadata that will be sent to the client from this op will
+  ///     be taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  void SendInitialMetadata(void* tag) override {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    meta_ops_.set_output_tag(tag);
+    meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      meta_ops_.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_.PerformOps(&meta_ops_);
+  }
+
+  void Write(const W& msg, void* tag) override {
+    write_ops_.set_output_tag(tag);
+    EnsureInitialMetadataSent(&write_ops_);
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  void Write(const W& msg, WriteOptions options, void* tag) override {
+    write_ops_.set_output_tag(tag);
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+    }
+
+    EnsureInitialMetadataSent(&write_ops_);
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  /// See the \a ServerAsyncWriterInterface.WriteAndFinish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used
+  ///     for sending trailing (and initial) metadata to the client.
+  ///
+  /// Note: \a status must have an OK code.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg and \a status, so it
+  /// is safe to to deallocate once WriteAndFinish returns.
+  void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
+                      void* tag) override {
+    write_ops_.set_output_tag(tag);
+    EnsureInitialMetadataSent(&write_ops_);
+    options.set_buffer_hint();
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+    write_ops_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    call_.PerformOps(&write_ops_);
+  }
+
+  /// See the \a ServerAsyncWriterInterface.Finish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used for sending
+  ///     trailing (and initial if not already sent) metadata to the client.
+  ///
+  /// Note: there are no restrictions are the code of
+  /// \a status,it may be non-OK
+  ///
+  /// gRPC doesn't take ownership or a reference to \a status, so it is safe to
+  /// to deallocate once Finish returns.
+  void Finish(const Status& status, void* tag) override {
+    finish_ops_.set_output_tag(tag);
+    EnsureInitialMetadataSent(&finish_ops_);
+    finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    call_.PerformOps(&finish_ops_);
+  }
+
+ private:
+  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+  template <class T>
+  void EnsureInitialMetadataSent(T* ops) {
+    if (!ctx_->sent_initial_metadata_) {
+      ops->SendInitialMetadata(&ctx_->initial_metadata_,
+                               ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        ops->set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+  }
+
+  ::grpc::internal::Call call_;
+  ServerContext* ctx_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+      meta_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpServerSendStatus>
+      write_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpServerSendStatus>
+      finish_ops_;
+};
+
+/// Server-side interface for asynchronous bi-directional streaming.
+template <class W, class R>
+class ServerAsyncReaderWriterInterface
+    : public internal::ServerAsyncStreamingInterface,
+      public internal::AsyncWriterInterface<W>,
+      public internal::AsyncReaderInterface<R> {
+ public:
+  /// Indicate that the stream is to be finished with a certain status code.
+  /// Request notification for when the server has sent the appropriate
+  /// signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// It is appropriate to call this method when either:
+  ///   * all messages from the client have been received (either known
+  ///     implictly, or explicitly because a previous \a
+  ///     AsyncReaderInterface::Read operation
+  ///     with a non-ok result (e.g., cq->Next(&read_tag, &ok) filled in 'ok'
+  ///     with 'false'.
+  ///   * it is desired to end the call early with some non-OK status code.
+  ///
+  /// This operation will end when the server has finished sending out initial
+  /// metadata (if not sent already), response message, and status, or if some
+  /// failure occurred when trying to do so.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a status, so it is safe to
+  /// to deallocate once Finish returns.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of this call.
+  virtual void Finish(const Status& status, void* tag) = 0;
+
+  /// Request the writing of \a msg and coalesce it with trailing metadata which
+  /// contains \a status, using WriteOptions options with
+  /// identifying tag \a tag.
+  ///
+  /// WriteAndFinish is equivalent of performing WriteLast and Finish in a
+  /// single step.
+  ///
+  /// gRPC doesn't take ownership or a reference to \a msg and \a status, so it
+  /// is safe to to deallocate once WriteAndFinish returns.
+  ///
+  /// \param[in] msg The message to be written.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  /// \param[in] status The Status that server returns to client.
+  /// \param[in] tag The tag identifying the operation.
+  virtual void WriteAndFinish(const W& msg, WriteOptions options,
+                              const Status& status, void* tag) = 0;
+};
+
+/// Async server-side API for doing bidirectional streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R, and the outgoing message stream coming from the server has
+/// messages of type \a W.
+template <class W, class R>
+class ServerAsyncReaderWriter final
+    : public ServerAsyncReaderWriterInterface<W, R> {
+ public:
+  explicit ServerAsyncReaderWriter(ServerContext* ctx)
+      : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+  /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - The initial metadata that will be sent to the client from this op will
+  ///     be taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  void SendInitialMetadata(void* tag) override {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    meta_ops_.set_output_tag(tag);
+    meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      meta_ops_.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_.PerformOps(&meta_ops_);
+  }
+
+  void Read(R* msg, void* tag) override {
+    read_ops_.set_output_tag(tag);
+    read_ops_.RecvMessage(msg);
+    call_.PerformOps(&read_ops_);
+  }
+
+  void Write(const W& msg, void* tag) override {
+    write_ops_.set_output_tag(tag);
+    EnsureInitialMetadataSent(&write_ops_);
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  void Write(const W& msg, WriteOptions options, void* tag) override {
+    write_ops_.set_output_tag(tag);
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+    }
+    EnsureInitialMetadataSent(&write_ops_);
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+    call_.PerformOps(&write_ops_);
+  }
+
+  /// See the \a ServerAsyncReaderWriterInterface.WriteAndFinish
+  /// method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used
+  ///     for sending trailing (and initial) metadata to the client.
+  ///
+  /// Note: \a status must have an OK code.
+  //
+  /// gRPC doesn't take ownership or a reference to \a msg and \a status, so it
+  /// is safe to to deallocate once WriteAndFinish returns.
+  void WriteAndFinish(const W& msg, WriteOptions options, const Status& status,
+                      void* tag) override {
+    write_ops_.set_output_tag(tag);
+    EnsureInitialMetadataSent(&write_ops_);
+    options.set_buffer_hint();
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg, options).ok());
+    write_ops_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    call_.PerformOps(&write_ops_);
+  }
+
+  /// See the \a ServerAsyncReaderWriterInterface.Finish method for semantics.
+  ///
+  /// Implicit input parameter:
+  ///   - the \a ServerContext associated with this call is used for sending
+  ///     trailing (and initial if not already sent) metadata to the client.
+  ///
+  /// Note: there are no restrictions are the code of \a status,
+  /// it may be non-OK
+  //
+  /// gRPC doesn't take ownership or a reference to \a status, so it is safe to
+  /// to deallocate once Finish returns.
+  void Finish(const Status& status, void* tag) override {
+    finish_ops_.set_output_tag(tag);
+    EnsureInitialMetadataSent(&finish_ops_);
+
+    finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    call_.PerformOps(&finish_ops_);
+  }
+
+ private:
+  friend class ::grpc::Server;
+
+  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+  template <class T>
+  void EnsureInitialMetadataSent(T* ops) {
+    if (!ctx_->sent_initial_metadata_) {
+      ops->SendInitialMetadata(&ctx_->initial_metadata_,
+                               ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        ops->set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+  }
+
+  ::grpc::internal::Call call_;
+  ServerContext* ctx_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+      meta_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>> read_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpServerSendStatus>
+      write_ops_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpServerSendStatus>
+      finish_ops_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_ASYNC_STREAM_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/async_unary_call.h b/third_party/grpc/include/grpcpp/impl/codegen/async_unary_call.h
new file mode 100644
index 0000000..89dcb12
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/async_unary_call.h
@@ -0,0 +1,317 @@
+/*
+ *
+ * Copyright 2015 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_ASYNC_UNARY_CALL_H
+#define GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
+
+#include <assert.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class CompletionQueue;
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// An interface relevant for async client side unary RPCs (which send
+/// one request message to a server and receive one response message).
+template <class R>
+class ClientAsyncResponseReaderInterface {
+ public:
+  virtual ~ClientAsyncResponseReaderInterface() {}
+
+  /// Start the call that was set up by the constructor, but only if the
+  /// constructor was invoked through the "Prepare" API which doesn't actually
+  /// start the call
+  virtual void StartCall() = 0;
+
+  /// Request notification of the reading of initial metadata. Completion
+  /// will be notified by \a tag on the associated completion queue.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  virtual void ReadInitialMetadata(void* tag) = 0;
+
+  /// Request to receive the server's response \a msg and final \a status for
+  /// the call, and to notify \a tag on this call's completion queue when
+  /// finished.
+  ///
+  /// This function will return when either:
+  /// - when the server's response message and status have been received.
+  /// - when the server has returned a non-OK status (no message expected in
+  ///   this case).
+  /// - when the call failed for some reason and the library generated a
+  ///   non-OK status.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[out] status To be updated with the operation status.
+  /// \param[out] msg To be filled in with the server's response message.
+  virtual void Finish(R* msg, Status* status, void* tag) = 0;
+};
+
+namespace internal {
+template <class R>
+class ClientAsyncResponseReaderFactory {
+ public:
+  /// Start a call and write the request out if \a start is set.
+  /// \a tag will be notified on \a cq when the call has been started (i.e.
+  /// intitial metadata sent) and \a request has been written out.
+  /// If \a start is not set, the actual call must be initiated by StartCall
+  /// Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  template <class W>
+  static ClientAsyncResponseReader<R>* Create(
+      ChannelInterface* channel, CompletionQueue* cq,
+      const ::grpc::internal::RpcMethod& method, ClientContext* context,
+      const W& request, bool start) {
+    ::grpc::internal::Call call = channel->CreateCall(method, context, cq);
+    return new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientAsyncResponseReader<R>)))
+        ClientAsyncResponseReader<R>(call, context, request, start);
+  }
+};
+}  // namespace internal
+
+/// Async API for client-side unary RPCs, where the message response
+/// received from the server is of type \a R.
+template <class R>
+class ClientAsyncResponseReader final
+    : public ClientAsyncResponseReaderInterface<R> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientAsyncResponseReader));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void StartCall() override {
+    assert(!started_);
+    started_ = true;
+    StartCallInternal();
+  }
+
+  /// See \a ClientAsyncResponseReaderInterface::ReadInitialMetadata for
+  /// semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata sent from the server.
+  void ReadInitialMetadata(void* tag) override {
+    assert(started_);
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    single_buf.set_output_tag(tag);
+    single_buf.RecvInitialMetadata(context_);
+    call_.PerformOps(&single_buf);
+    initial_metadata_read_ = true;
+  }
+
+  /// See \a ClientAysncResponseReaderInterface::Finish for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible initial and trailing metadata sent from the server.
+  void Finish(R* msg, Status* status, void* tag) override {
+    assert(started_);
+    if (initial_metadata_read_) {
+      finish_buf.set_output_tag(tag);
+      finish_buf.RecvMessage(msg);
+      finish_buf.AllowNoMessage();
+      finish_buf.ClientRecvStatus(context_, status);
+      call_.PerformOps(&finish_buf);
+    } else {
+      single_buf.set_output_tag(tag);
+      single_buf.RecvInitialMetadata(context_);
+      single_buf.RecvMessage(msg);
+      single_buf.AllowNoMessage();
+      single_buf.ClientRecvStatus(context_, status);
+      call_.PerformOps(&single_buf);
+    }
+  }
+
+ private:
+  friend class internal::ClientAsyncResponseReaderFactory<R>;
+  ClientContext* const context_;
+  ::grpc::internal::Call call_;
+  bool started_;
+  bool initial_metadata_read_ = false;
+
+  template <class W>
+  ClientAsyncResponseReader(::grpc::internal::Call call, ClientContext* context,
+                            const W& request, bool start)
+      : context_(context), call_(call), started_(start) {
+    // Bind the metadata at time of StartCallInternal but set up the rest here
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(single_buf.SendMessage(request).ok());
+    single_buf.ClientSendClose();
+    if (start) StartCallInternal();
+  }
+
+  void StartCallInternal() {
+    single_buf.SendInitialMetadata(&context_->send_initial_metadata_,
+                                   context_->initial_metadata_flags());
+  }
+
+  // disable operator new
+  static void* operator new(std::size_t size);
+  static void* operator new(std::size_t size, void* p) { return p; }
+
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpClientSendClose,
+                              ::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpRecvMessage<R>,
+                              ::grpc::internal::CallOpClientRecvStatus>
+      single_buf;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvMessage<R>,
+                              ::grpc::internal::CallOpClientRecvStatus>
+      finish_buf;
+};
+
+/// Async server-side API for handling unary calls, where the single
+/// response message sent to the client is of type \a W.
+template <class W>
+class ServerAsyncResponseWriter final
+    : public internal::ServerAsyncStreamingInterface {
+ public:
+  explicit ServerAsyncResponseWriter(ServerContext* ctx)
+      : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
+
+  /// See \a ServerAsyncStreamingInterface::SendInitialMetadata for semantics.
+  ///
+  /// Side effect:
+  ///   The initial metadata that will be sent to the client from this op will
+  ///   be taken from the \a ServerContext associated with the call.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  void SendInitialMetadata(void* tag) override {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    meta_buf_.set_output_tag(tag);
+    meta_buf_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                  ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      meta_buf_.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_.PerformOps(&meta_buf_);
+  }
+
+  /// Indicate that the stream is to be finished and request notification
+  /// when the server has sent the appropriate signals to the client to
+  /// end the call. Should not be used concurrently with other operations.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of the call.
+  /// \param[in] msg Message to be sent to the client.
+  ///
+  /// Side effect:
+  ///   - also sends initial metadata if not already sent (using the
+  ///     \a ServerContext associated with this call).
+  ///
+  /// Note: if \a status has a non-OK code, then \a msg will not be sent,
+  /// and the client will receive only the status with possible trailing
+  /// metadata.
+  void Finish(const W& msg, const Status& status, void* tag) {
+    finish_buf_.set_output_tag(tag);
+    finish_buf_.set_core_cq_tag(&finish_buf_);
+    if (!ctx_->sent_initial_metadata_) {
+      finish_buf_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        finish_buf_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+    // The response is dropped if the status is not OK.
+    if (status.ok()) {
+      finish_buf_.ServerSendStatus(&ctx_->trailing_metadata_,
+                                   finish_buf_.SendMessage(msg));
+    } else {
+      finish_buf_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    }
+    call_.PerformOps(&finish_buf_);
+  }
+
+  /// Indicate that the stream is to be finished with a non-OK status,
+  /// and request notification for when the server has finished sending the
+  /// appropriate signals to the client to end the call.
+  /// Should not be used concurrently with other operations.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  /// \param[in] status To be sent to the client as the result of the call.
+  ///   - Note: \a status must have a non-OK code.
+  ///
+  /// Side effect:
+  ///   - also sends initial metadata if not already sent (using the
+  ///     \a ServerContext associated with this call).
+  void FinishWithError(const Status& status, void* tag) {
+    GPR_CODEGEN_ASSERT(!status.ok());
+    finish_buf_.set_output_tag(tag);
+    if (!ctx_->sent_initial_metadata_) {
+      finish_buf_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                      ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        finish_buf_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+    finish_buf_.ServerSendStatus(&ctx_->trailing_metadata_, status);
+    call_.PerformOps(&finish_buf_);
+  }
+
+ private:
+  void BindCall(::grpc::internal::Call* call) override { call_ = *call; }
+
+  ::grpc::internal::Call call_;
+  ServerContext* ctx_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+      meta_buf_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                              ::grpc::internal::CallOpSendMessage,
+                              ::grpc::internal::CallOpServerSendStatus>
+      finish_buf_;
+};
+
+}  // namespace grpc
+
+namespace std {
+template <class R>
+class default_delete<grpc::ClientAsyncResponseReader<R>> {
+ public:
+  void operator()(void* p) {}
+};
+template <class R>
+class default_delete<grpc::ClientAsyncResponseReaderInterface<R>> {
+ public:
+  void operator()(void* p) {}
+};
+}  // namespace std
+
+#endif  // GRPCPP_IMPL_CODEGEN_ASYNC_UNARY_CALL_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/byte_buffer.h b/third_party/grpc/include/grpcpp/impl/codegen/byte_buffer.h
new file mode 100644
index 0000000..a77e36d
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/byte_buffer.h
@@ -0,0 +1,224 @@
+/*
+ *
+ * Copyright 2017 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_BYTE_BUFFER_H
+#define GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
+
+#include <grpc/impl/codegen/byte_buffer.h>
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+
+#include <vector>
+
+namespace grpc {
+
+class ServerInterface;
+class ByteBuffer;
+class ServerInterface;
+
+namespace internal {
+class CallOpSendMessage;
+template <class R>
+class CallOpRecvMessage;
+class CallOpGenericRecvMessage;
+class MethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class RequestType, class ResponseType>
+class CallbackUnaryHandler;
+template <class RequestType, class ResponseType>
+class CallbackServerStreamingHandler;
+template <StatusCode code>
+class ErrorMethodHandler;
+template <class R>
+class DeserializeFuncType;
+class GrpcByteBufferPeer;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+
+}  // namespace internal
+/// A sequence of bytes.
+class ByteBuffer final {
+ public:
+  /// Constuct an empty buffer.
+  ByteBuffer() : buffer_(nullptr) {}
+
+  /// Construct buffer from \a slices, of which there are \a nslices.
+  ByteBuffer(const Slice* slices, size_t nslices) {
+    // The following assertions check that the representation of a grpc::Slice
+    // is identical to that of a grpc_slice:  it has a grpc_slice field, and
+    // nothing else.
+    static_assert(std::is_same<decltype(slices[0].slice_), grpc_slice>::value,
+                  "Slice must have same representation as grpc_slice");
+    static_assert(sizeof(Slice) == sizeof(grpc_slice),
+                  "Slice must have same representation as grpc_slice");
+    // The following assertions check that the representation of a ByteBuffer is
+    // identical to grpc_byte_buffer*:  it has a grpc_byte_buffer* field,
+    // and nothing else.
+    static_assert(std::is_same<decltype(buffer_), grpc_byte_buffer*>::value,
+                  "ByteBuffer must have same representation as "
+                  "grpc_byte_buffer*");
+    static_assert(sizeof(ByteBuffer) == sizeof(grpc_byte_buffer*),
+                  "ByteBuffer must have same representation as "
+                  "grpc_byte_buffer*");
+    // The const_cast is legal if grpc_raw_byte_buffer_create() does no more
+    // than its advertised side effect of increasing the reference count of the
+    // slices it processes, and such an increase does not affect the semantics
+    // seen by the caller of this constructor.
+    buffer_ = g_core_codegen_interface->grpc_raw_byte_buffer_create(
+        reinterpret_cast<grpc_slice*>(const_cast<Slice*>(slices)), nslices);
+  }
+
+  /// Constuct a byte buffer by referencing elements of existing buffer
+  /// \a buf. Wrapper of core function grpc_byte_buffer_copy . This is not
+  /// a deep copy; it is just a referencing. As a result, its performance is
+  /// size-independent.
+  ByteBuffer(const ByteBuffer& buf);
+
+  ~ByteBuffer() {
+    if (buffer_) {
+      g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
+    }
+  }
+
+  /// Wrapper of core function grpc_byte_buffer_copy . This is not
+  /// a deep copy; it is just a referencing. As a result, its performance is
+  /// size-independent.
+  ByteBuffer& operator=(const ByteBuffer&);
+
+  /// Dump (read) the buffer contents into \a slices.
+  Status Dump(std::vector<Slice>* slices) const;
+
+  /// Remove all data.
+  void Clear() {
+    if (buffer_) {
+      g_core_codegen_interface->grpc_byte_buffer_destroy(buffer_);
+      buffer_ = nullptr;
+    }
+  }
+
+  /// Make a duplicate copy of the internals of this byte
+  /// buffer so that we have our own owned version of it.
+  /// bbuf.Duplicate(); is equivalent to bbuf=bbuf; but is actually readable.
+  /// This is not a deep copy; it is a referencing and its performance
+  /// is size-independent.
+  void Duplicate() {
+    buffer_ = g_core_codegen_interface->grpc_byte_buffer_copy(buffer_);
+  }
+
+  /// Forget underlying byte buffer without destroying
+  /// Use this only for un-owned byte buffers
+  void Release() { buffer_ = nullptr; }
+
+  /// Buffer size in bytes.
+  size_t Length() const {
+    return buffer_ == nullptr
+               ? 0
+               : g_core_codegen_interface->grpc_byte_buffer_length(buffer_);
+  }
+
+  /// Swap the state of *this and *other.
+  void Swap(ByteBuffer* other) {
+    grpc_byte_buffer* tmp = other->buffer_;
+    other->buffer_ = buffer_;
+    buffer_ = tmp;
+  }
+
+  /// Is this ByteBuffer valid?
+  bool Valid() const { return (buffer_ != nullptr); }
+
+ private:
+  friend class SerializationTraits<ByteBuffer, void>;
+  friend class ServerInterface;
+  friend class internal::CallOpSendMessage;
+  template <class R>
+  friend class internal::CallOpRecvMessage;
+  friend class internal::CallOpGenericRecvMessage;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class RpcMethodHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ServerStreamingHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class internal::RpcMethodHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class internal::ServerStreamingHandler;
+  template <class RequestType, class ResponseType>
+  friend class internal::CallbackUnaryHandler;
+  template <class RequestType, class ResponseType>
+  friend class ::grpc::internal::CallbackServerStreamingHandler;
+  template <StatusCode code>
+  friend class internal::ErrorMethodHandler;
+  template <class R>
+  friend class internal::DeserializeFuncType;
+  friend class ProtoBufferReader;
+  friend class ProtoBufferWriter;
+  friend class internal::GrpcByteBufferPeer;
+
+  grpc_byte_buffer* buffer_;
+
+  // takes ownership
+  void set_buffer(grpc_byte_buffer* buf) {
+    if (buffer_) {
+      Clear();
+    }
+    buffer_ = buf;
+  }
+
+  grpc_byte_buffer* c_buffer() { return buffer_; }
+  grpc_byte_buffer** c_buffer_ptr() { return &buffer_; }
+
+  class ByteBufferPointer {
+   public:
+    ByteBufferPointer(const ByteBuffer* b)
+        : bbuf_(const_cast<ByteBuffer*>(b)) {}
+    operator ByteBuffer*() { return bbuf_; }
+    operator grpc_byte_buffer*() { return bbuf_->buffer_; }
+    operator grpc_byte_buffer**() { return &bbuf_->buffer_; }
+
+   private:
+    ByteBuffer* bbuf_;
+  };
+  ByteBufferPointer bbuf_ptr() const { return ByteBufferPointer(this); }
+};
+
+template <>
+class SerializationTraits<ByteBuffer, void> {
+ public:
+  static Status Deserialize(ByteBuffer* byte_buffer, ByteBuffer* dest) {
+    dest->set_buffer(byte_buffer->buffer_);
+    return Status::OK;
+  }
+  static Status Serialize(const ByteBuffer& source, ByteBuffer* buffer,
+                          bool* own_buffer) {
+    *buffer = source;
+    *own_buffer = true;
+    return Status::OK;
+  }
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_BYTE_BUFFER_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/call.h b/third_party/grpc/include/grpcpp/impl/codegen/call.h
new file mode 100644
index 0000000..c040c30
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/call.h
@@ -0,0 +1,94 @@
+/*
+ *
+ * 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_CALL_H
+#define GRPCPP_IMPL_CODEGEN_CALL_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/call_hook.h>
+
+namespace grpc {
+class CompletionQueue;
+
+namespace experimental {
+class ClientRpcInfo;
+class ServerRpcInfo;
+}  // namespace experimental
+namespace internal {
+class CallHook;
+class CallOpSetInterface;
+
+/// Straightforward wrapping of the C call object
+class Call final {
+ public:
+  Call()
+      : call_hook_(nullptr),
+        cq_(nullptr),
+        call_(nullptr),
+        max_receive_message_size_(-1) {}
+  /** call is owned by the caller */
+  Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
+      : call_hook_(call_hook),
+        cq_(cq),
+        call_(call),
+        max_receive_message_size_(-1) {}
+
+  Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
+       experimental::ClientRpcInfo* rpc_info)
+      : call_hook_(call_hook),
+        cq_(cq),
+        call_(call),
+        max_receive_message_size_(-1),
+        client_rpc_info_(rpc_info) {}
+
+  Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
+       int max_receive_message_size, experimental::ServerRpcInfo* rpc_info)
+      : call_hook_(call_hook),
+        cq_(cq),
+        call_(call),
+        max_receive_message_size_(max_receive_message_size),
+        server_rpc_info_(rpc_info) {}
+
+  void PerformOps(CallOpSetInterface* ops) {
+    call_hook_->PerformOpsOnCall(ops, this);
+  }
+
+  grpc_call* call() const { return call_; }
+  CompletionQueue* cq() const { return cq_; }
+
+  int max_receive_message_size() const { return max_receive_message_size_; }
+
+  experimental::ClientRpcInfo* client_rpc_info() const {
+    return client_rpc_info_;
+  }
+
+  experimental::ServerRpcInfo* server_rpc_info() const {
+    return server_rpc_info_;
+  }
+
+ private:
+  CallHook* call_hook_;
+  CompletionQueue* cq_;
+  grpc_call* call_;
+  int max_receive_message_size_;
+  experimental::ClientRpcInfo* client_rpc_info_ = nullptr;
+  experimental::ServerRpcInfo* server_rpc_info_ = nullptr;
+};
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CALL_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/call_hook.h b/third_party/grpc/include/grpcpp/impl/codegen/call_hook.h
new file mode 100644
index 0000000..4f7d370
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/call_hook.h
@@ -0,0 +1,39 @@
+/*
+ *
+ * Copyright 2015 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_CALL_HOOK_H
+#define GRPCPP_IMPL_CODEGEN_CALL_HOOK_H
+
+namespace grpc {
+
+namespace internal {
+class CallOpSetInterface;
+class Call;
+
+/// This is an interface that Channel and Server implement to allow them to hook
+/// performing ops.
+class CallHook {
+ public:
+  virtual ~CallHook() {}
+  virtual void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) = 0;
+};
+}  // namespace internal
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CALL_HOOK_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/call_op_set.h b/third_party/grpc/include/grpcpp/impl/codegen/call_op_set.h
new file mode 100644
index 0000000..b2100c6
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/call_op_set.h
@@ -0,0 +1,923 @@
+/*
+ *
+ * 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_CALL_OP_SET_H
+#define GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
+
+#include <assert.h>
+#include <array>
+#include <cstring>
+#include <functional>
+#include <map>
+#include <memory>
+#include <vector>
+
+#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/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/slice.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+#include <grpc/impl/codegen/atm.h>
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/grpc_types.h>
+
+namespace grpc {
+
+class CompletionQueue;
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+namespace internal {
+class Call;
+class CallHook;
+
+// TODO(yangg) if the map is changed before we send, the pointers will be a
+// mess. Make sure it does not happen.
+inline grpc_metadata* FillMetadataArray(
+    const std::multimap<grpc::string, grpc::string>& metadata,
+    size_t* metadata_count, const grpc::string& optional_error_details) {
+  *metadata_count = metadata.size() + (optional_error_details.empty() ? 0 : 1);
+  if (*metadata_count == 0) {
+    return nullptr;
+  }
+  grpc_metadata* metadata_array =
+      (grpc_metadata*)(g_core_codegen_interface->gpr_malloc(
+          (*metadata_count) * sizeof(grpc_metadata)));
+  size_t i = 0;
+  for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
+    metadata_array[i].key = SliceReferencingString(iter->first);
+    metadata_array[i].value = SliceReferencingString(iter->second);
+  }
+  if (!optional_error_details.empty()) {
+    metadata_array[i].key =
+        g_core_codegen_interface->grpc_slice_from_static_buffer(
+            kBinaryErrorDetailsKey, sizeof(kBinaryErrorDetailsKey) - 1);
+    metadata_array[i].value = SliceReferencingString(optional_error_details);
+  }
+  return metadata_array;
+}
+}  // namespace internal
+
+/// Per-message write options.
+class WriteOptions {
+ public:
+  WriteOptions() : flags_(0), last_message_(false) {}
+  WriteOptions(const WriteOptions& other)
+      : flags_(other.flags_), last_message_(other.last_message_) {}
+
+  /// Clear all flags.
+  inline void Clear() { flags_ = 0; }
+
+  /// Returns raw flags bitset.
+  inline uint32_t flags() const { return flags_; }
+
+  /// Sets flag for the disabling of compression for the next message write.
+  ///
+  /// \sa GRPC_WRITE_NO_COMPRESS
+  inline WriteOptions& set_no_compression() {
+    SetBit(GRPC_WRITE_NO_COMPRESS);
+    return *this;
+  }
+
+  /// Clears flag for the disabling of compression for the next message write.
+  ///
+  /// \sa GRPC_WRITE_NO_COMPRESS
+  inline WriteOptions& clear_no_compression() {
+    ClearBit(GRPC_WRITE_NO_COMPRESS);
+    return *this;
+  }
+
+  /// Get value for the flag indicating whether compression for the next
+  /// message write is forcefully disabled.
+  ///
+  /// \sa GRPC_WRITE_NO_COMPRESS
+  inline bool get_no_compression() const {
+    return GetBit(GRPC_WRITE_NO_COMPRESS);
+  }
+
+  /// Sets flag indicating that the write may be buffered and need not go out on
+  /// the wire immediately.
+  ///
+  /// \sa GRPC_WRITE_BUFFER_HINT
+  inline WriteOptions& set_buffer_hint() {
+    SetBit(GRPC_WRITE_BUFFER_HINT);
+    return *this;
+  }
+
+  /// Clears flag indicating that the write may be buffered and need not go out
+  /// on the wire immediately.
+  ///
+  /// \sa GRPC_WRITE_BUFFER_HINT
+  inline WriteOptions& clear_buffer_hint() {
+    ClearBit(GRPC_WRITE_BUFFER_HINT);
+    return *this;
+  }
+
+  /// Get value for the flag indicating that the write may be buffered and need
+  /// not go out on the wire immediately.
+  ///
+  /// \sa GRPC_WRITE_BUFFER_HINT
+  inline bool get_buffer_hint() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
+
+  /// corked bit: aliases set_buffer_hint currently, with the intent that
+  /// set_buffer_hint will be removed in the future
+  inline WriteOptions& set_corked() {
+    SetBit(GRPC_WRITE_BUFFER_HINT);
+    return *this;
+  }
+
+  inline WriteOptions& clear_corked() {
+    ClearBit(GRPC_WRITE_BUFFER_HINT);
+    return *this;
+  }
+
+  inline bool is_corked() const { return GetBit(GRPC_WRITE_BUFFER_HINT); }
+
+  /// last-message bit: indicates this is the last message in a stream
+  /// client-side:  makes Write the equivalent of performing Write, WritesDone
+  /// in a single step
+  /// server-side:  hold the Write until the service handler returns (sync api)
+  /// or until Finish is called (async api)
+  inline WriteOptions& set_last_message() {
+    last_message_ = true;
+    return *this;
+  }
+
+  /// Clears flag indicating that this is the last message in a stream,
+  /// disabling coalescing.
+  inline WriteOptions& clear_last_message() {
+    last_message_ = false;
+    return *this;
+  }
+
+  /// Guarantee that all bytes have been written to the socket before completing
+  /// this write (usually writes are completed when they pass flow control).
+  inline WriteOptions& set_write_through() {
+    SetBit(GRPC_WRITE_THROUGH);
+    return *this;
+  }
+
+  inline bool is_write_through() const { return GetBit(GRPC_WRITE_THROUGH); }
+
+  /// Get value for the flag indicating that this is the last message, and
+  /// should be coalesced with trailing metadata.
+  ///
+  /// \sa GRPC_WRITE_LAST_MESSAGE
+  bool is_last_message() const { return last_message_; }
+
+  WriteOptions& operator=(const WriteOptions& rhs) {
+    flags_ = rhs.flags_;
+    return *this;
+  }
+
+ private:
+  void SetBit(const uint32_t mask) { flags_ |= mask; }
+
+  void ClearBit(const uint32_t mask) { flags_ &= ~mask; }
+
+  bool GetBit(const uint32_t mask) const { return (flags_ & mask) != 0; }
+
+  uint32_t flags_;
+  bool last_message_;
+};
+
+namespace internal {
+
+/// 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>
+class CallNoOp {
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {}
+  void FinishOp(bool* status) {}
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {}
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {}
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {}
+};
+
+class CallOpSendInitialMetadata {
+ public:
+  CallOpSendInitialMetadata() : send_(false) {
+    maybe_compression_level_.is_set = false;
+  }
+
+  void SendInitialMetadata(std::multimap<grpc::string, grpc::string>* metadata,
+                           uint32_t flags) {
+    maybe_compression_level_.is_set = false;
+    send_ = true;
+    flags_ = flags;
+    metadata_map_ = metadata;
+  }
+
+  void set_compression_level(grpc_compression_level level) {
+    maybe_compression_level_.is_set = true;
+    maybe_compression_level_.level = level;
+  }
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (!send_ || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_SEND_INITIAL_METADATA;
+    op->flags = flags_;
+    op->reserved = NULL;
+    initial_metadata_ =
+        FillMetadataArray(*metadata_map_, &initial_metadata_count_, "");
+    op->data.send_initial_metadata.count = initial_metadata_count_;
+    op->data.send_initial_metadata.metadata = initial_metadata_;
+    op->data.send_initial_metadata.maybe_compression_level.is_set =
+        maybe_compression_level_.is_set;
+    if (maybe_compression_level_.is_set) {
+      op->data.send_initial_metadata.maybe_compression_level.level =
+          maybe_compression_level_.level;
+    }
+  }
+  void FinishOp(bool* status) {
+    if (!send_ || hijacked_) return;
+    g_core_codegen_interface->gpr_free(initial_metadata_);
+    send_ = false;
+  }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (!send_) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_SEND_INITIAL_METADATA);
+    interceptor_methods->SetSendInitialMetadata(metadata_map_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {}
+
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+  }
+
+  bool hijacked_ = false;
+  bool send_;
+  uint32_t flags_;
+  size_t initial_metadata_count_;
+  std::multimap<grpc::string, grpc::string>* metadata_map_;
+  grpc_metadata* initial_metadata_;
+  struct {
+    bool is_set;
+    grpc_compression_level level;
+  } maybe_compression_level_;
+};
+
+class CallOpSendMessage {
+ public:
+  CallOpSendMessage() : send_buf_() {}
+
+  /// Send \a message using \a options for the write. The \a options are cleared
+  /// after use.
+  template <class M>
+  Status SendMessage(const M& message,
+                     WriteOptions options) GRPC_MUST_USE_RESULT;
+
+  template <class M>
+  Status SendMessage(const M& message) GRPC_MUST_USE_RESULT;
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (!send_buf_.Valid() || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_SEND_MESSAGE;
+    op->flags = write_options_.flags();
+    op->reserved = NULL;
+    op->data.send_message.send_message = send_buf_.c_buffer();
+    // Flags are per-message: clear them after use.
+    write_options_.Clear();
+  }
+  void FinishOp(bool* status) { send_buf_.Clear(); }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (!send_buf_.Valid()) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_SEND_MESSAGE);
+    interceptor_methods->SetSendMessage(&send_buf_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    // The contents of the SendMessage value that was previously set
+    // has had its references stolen by core's operations
+    interceptor_methods->SetSendMessage(nullptr);
+  }
+
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+  }
+
+ private:
+  bool hijacked_ = false;
+  ByteBuffer send_buf_;
+  WriteOptions write_options_;
+};
+
+template <class M>
+Status CallOpSendMessage::SendMessage(const M& message, WriteOptions options) {
+  write_options_ = options;
+  bool own_buf;
+  // TODO(vjpai): Remove the void below when possible
+  // The void in the template parameter below should not be needed
+  // (since it should be implicit) but is needed due to an observed
+  // difference in behavior between clang and gcc for certain internal users
+  Status result = SerializationTraits<M, void>::Serialize(
+      message, send_buf_.bbuf_ptr(), &own_buf);
+  if (!own_buf) {
+    send_buf_.Duplicate();
+  }
+  return result;
+}
+
+template <class M>
+Status CallOpSendMessage::SendMessage(const M& message) {
+  return SendMessage(message, WriteOptions());
+}
+
+template <class R>
+class CallOpRecvMessage {
+ public:
+  CallOpRecvMessage()
+      : got_message(false),
+        message_(nullptr),
+        allow_not_getting_message_(false) {}
+
+  void RecvMessage(R* message) { message_ = message; }
+
+  // Do not change status if no message is received.
+  void AllowNoMessage() { allow_not_getting_message_ = true; }
+
+  bool got_message;
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (message_ == nullptr || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_RECV_MESSAGE;
+    op->flags = 0;
+    op->reserved = NULL;
+    op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
+  }
+
+  void FinishOp(bool* status) {
+    if (message_ == nullptr || hijacked_) return;
+    if (recv_buf_.Valid()) {
+      if (*status) {
+        got_message = *status =
+            SerializationTraits<R>::Deserialize(recv_buf_.bbuf_ptr(), message_)
+                .ok();
+        recv_buf_.Release();
+      } else {
+        got_message = false;
+        recv_buf_.Clear();
+      }
+    } else {
+      got_message = false;
+      if (!allow_not_getting_message_) {
+        *status = false;
+      }
+    }
+    message_ = nullptr;
+  }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    interceptor_methods->SetRecvMessage(message_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (!got_message) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+  }
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+    if (message_ == nullptr) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_RECV_MESSAGE);
+    got_message = true;
+  }
+
+ private:
+  R* message_;
+  ByteBuffer recv_buf_;
+  bool allow_not_getting_message_;
+  bool hijacked_ = false;
+};
+
+class DeserializeFunc {
+ public:
+  virtual Status Deserialize(ByteBuffer* buf) = 0;
+  virtual ~DeserializeFunc() {}
+};
+
+template <class R>
+class DeserializeFuncType final : public DeserializeFunc {
+ public:
+  DeserializeFuncType(R* message) : message_(message) {}
+  Status Deserialize(ByteBuffer* buf) override {
+    return SerializationTraits<R>::Deserialize(buf->bbuf_ptr(), message_);
+  }
+
+  ~DeserializeFuncType() override {}
+
+ private:
+  R* message_;  // Not a managed pointer because management is external to this
+};
+
+class CallOpGenericRecvMessage {
+ public:
+  CallOpGenericRecvMessage()
+      : got_message(false), allow_not_getting_message_(false) {}
+
+  template <class R>
+  void RecvMessage(R* message) {
+    // Use an explicit base class pointer to avoid resolution error in the
+    // following unique_ptr::reset for some old implementations.
+    DeserializeFunc* func = new DeserializeFuncType<R>(message);
+    deserialize_.reset(func);
+    message_ = message;
+  }
+
+  // Do not change status if no message is received.
+  void AllowNoMessage() { allow_not_getting_message_ = true; }
+
+  bool got_message;
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (!deserialize_ || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_RECV_MESSAGE;
+    op->flags = 0;
+    op->reserved = NULL;
+    op->data.recv_message.recv_message = recv_buf_.c_buffer_ptr();
+  }
+
+  void FinishOp(bool* status) {
+    if (!deserialize_ || hijacked_) return;
+    if (recv_buf_.Valid()) {
+      if (*status) {
+        got_message = true;
+        *status = deserialize_->Deserialize(&recv_buf_).ok();
+        recv_buf_.Release();
+      } else {
+        got_message = false;
+        recv_buf_.Clear();
+      }
+    } else {
+      got_message = false;
+      if (!allow_not_getting_message_) {
+        *status = false;
+      }
+    }
+    deserialize_.reset();
+  }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    interceptor_methods->SetRecvMessage(message_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (!got_message) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+  }
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+    if (!deserialize_) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_RECV_MESSAGE);
+  }
+
+ private:
+  void* message_;
+  bool hijacked_ = false;
+  std::unique_ptr<DeserializeFunc> deserialize_;
+  ByteBuffer recv_buf_;
+  bool allow_not_getting_message_;
+};
+
+class CallOpClientSendClose {
+ public:
+  CallOpClientSendClose() : send_(false) {}
+
+  void ClientSendClose() { send_ = true; }
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (!send_ || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_SEND_CLOSE_FROM_CLIENT;
+    op->flags = 0;
+    op->reserved = NULL;
+  }
+  void FinishOp(bool* status) { send_ = false; }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (!send_) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_SEND_CLOSE);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {}
+
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+  }
+
+ private:
+  bool hijacked_ = false;
+  bool send_;
+};
+
+class CallOpServerSendStatus {
+ public:
+  CallOpServerSendStatus() : send_status_available_(false) {}
+
+  void ServerSendStatus(
+      std::multimap<grpc::string, grpc::string>* trailing_metadata,
+      const Status& status) {
+    send_error_details_ = status.error_details();
+    metadata_map_ = trailing_metadata;
+    send_status_available_ = true;
+    send_status_code_ = static_cast<grpc_status_code>(status.error_code());
+    send_error_message_ = status.error_message();
+  }
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (!send_status_available_ || hijacked_) return;
+    trailing_metadata_ = FillMetadataArray(
+        *metadata_map_, &trailing_metadata_count_, send_error_details_);
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_SEND_STATUS_FROM_SERVER;
+    op->data.send_status_from_server.trailing_metadata_count =
+        trailing_metadata_count_;
+    op->data.send_status_from_server.trailing_metadata = trailing_metadata_;
+    op->data.send_status_from_server.status = send_status_code_;
+    error_message_slice_ = SliceReferencingString(send_error_message_);
+    op->data.send_status_from_server.status_details =
+        send_error_message_.empty() ? nullptr : &error_message_slice_;
+    op->flags = 0;
+    op->reserved = NULL;
+  }
+
+  void FinishOp(bool* status) {
+    if (!send_status_available_ || hijacked_) return;
+    g_core_codegen_interface->gpr_free(trailing_metadata_);
+    send_status_available_ = false;
+  }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (!send_status_available_) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_SEND_STATUS);
+    interceptor_methods->SetSendTrailingMetadata(metadata_map_);
+    interceptor_methods->SetSendStatus(&send_status_code_, &send_error_details_,
+                                       &send_error_message_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {}
+
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+  }
+
+ private:
+  bool hijacked_ = false;
+  bool send_status_available_;
+  grpc_status_code send_status_code_;
+  grpc::string send_error_details_;
+  grpc::string send_error_message_;
+  size_t trailing_metadata_count_;
+  std::multimap<grpc::string, grpc::string>* metadata_map_;
+  grpc_metadata* trailing_metadata_;
+  grpc_slice error_message_slice_;
+};
+
+class CallOpRecvInitialMetadata {
+ public:
+  CallOpRecvInitialMetadata() : metadata_map_(nullptr) {}
+
+  void RecvInitialMetadata(ClientContext* context) {
+    context->initial_metadata_received_ = true;
+    metadata_map_ = &context->recv_initial_metadata_;
+  }
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (metadata_map_ == nullptr || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_RECV_INITIAL_METADATA;
+    op->data.recv_initial_metadata.recv_initial_metadata = metadata_map_->arr();
+    op->flags = 0;
+    op->reserved = NULL;
+  }
+
+  void FinishOp(bool* status) {
+    if (metadata_map_ == nullptr || hijacked_) return;
+  }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    interceptor_methods->SetRecvInitialMetadata(metadata_map_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (metadata_map_ == nullptr) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
+    metadata_map_ = nullptr;
+  }
+
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+    if (metadata_map_ == nullptr) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_RECV_INITIAL_METADATA);
+  }
+
+ private:
+  bool hijacked_ = false;
+  MetadataMap* metadata_map_;
+};
+
+class CallOpClientRecvStatus {
+ public:
+  CallOpClientRecvStatus()
+      : recv_status_(nullptr), debug_error_string_(nullptr) {}
+
+  void ClientRecvStatus(ClientContext* context, Status* status) {
+    client_context_ = context;
+    metadata_map_ = &client_context_->trailing_metadata_;
+    recv_status_ = status;
+    error_message_ = g_core_codegen_interface->grpc_empty_slice();
+  }
+
+ protected:
+  void AddOp(grpc_op* ops, size_t* nops) {
+    if (recv_status_ == nullptr || hijacked_) return;
+    grpc_op* op = &ops[(*nops)++];
+    op->op = GRPC_OP_RECV_STATUS_ON_CLIENT;
+    op->data.recv_status_on_client.trailing_metadata = metadata_map_->arr();
+    op->data.recv_status_on_client.status = &status_code_;
+    op->data.recv_status_on_client.status_details = &error_message_;
+    op->data.recv_status_on_client.error_string = &debug_error_string_;
+    op->flags = 0;
+    op->reserved = NULL;
+  }
+
+  void FinishOp(bool* status) {
+    if (recv_status_ == nullptr || hijacked_) return;
+    grpc::string binary_error_details = metadata_map_->GetBinaryErrorDetails();
+    *recv_status_ =
+        Status(static_cast<StatusCode>(status_code_),
+               GRPC_SLICE_IS_EMPTY(error_message_)
+                   ? grpc::string()
+                   : grpc::string(GRPC_SLICE_START_PTR(error_message_),
+                                  GRPC_SLICE_END_PTR(error_message_)),
+               binary_error_details);
+    client_context_->set_debug_error_string(
+        debug_error_string_ != nullptr ? debug_error_string_ : "");
+    g_core_codegen_interface->grpc_slice_unref(error_message_);
+    if (debug_error_string_ != nullptr) {
+      g_core_codegen_interface->gpr_free((void*)debug_error_string_);
+    }
+  }
+
+  void SetInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    interceptor_methods->SetRecvStatus(recv_status_);
+    interceptor_methods->SetRecvTrailingMetadata(metadata_map_);
+  }
+
+  void SetFinishInterceptionHookPoint(
+      InterceptorBatchMethodsImpl* interceptor_methods) {
+    if (recv_status_ == nullptr) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::POST_RECV_STATUS);
+    recv_status_ = nullptr;
+  }
+
+  void SetHijackingState(InterceptorBatchMethodsImpl* interceptor_methods) {
+    hijacked_ = true;
+    if (recv_status_ == nullptr) return;
+    interceptor_methods->AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::PRE_RECV_STATUS);
+  }
+
+ private:
+  bool hijacked_ = false;
+  ClientContext* client_context_;
+  MetadataMap* metadata_map_;
+  Status* recv_status_;
+  const char* debug_error_string_;
+  grpc_status_code status_code_;
+  grpc_slice error_message_;
+};
+
+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;
+
+/// 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
+/// empty base class optimization to slim this class (especially
+/// when there are many unused slots used). To avoid duplicate base classes,
+/// the template parmeter for CallNoOp is varied by argument position.
+template <class Op1, class Op2, class Op3, class Op4, class Op5, class Op6>
+class CallOpSet : public CallOpSetInterface,
+                  public Op1,
+                  public Op2,
+                  public Op3,
+                  public Op4,
+                  public Op5,
+                  public Op6 {
+ public:
+  CallOpSet() : core_cq_tag_(this), return_tag_(this) {}
+  // The copy constructor and assignment operator reset the value of
+  // core_cq_tag_, return_tag_, done_intercepting_ and interceptor_methods_
+  // since those are only meaningful on a specific object, not across objects.
+  CallOpSet(const CallOpSet& other)
+      : core_cq_tag_(this),
+        return_tag_(this),
+        call_(other.call_),
+        done_intercepting_(false),
+        interceptor_methods_(InterceptorBatchMethodsImpl()) {}
+
+  CallOpSet& operator=(const CallOpSet& other) {
+    core_cq_tag_ = this;
+    return_tag_ = this;
+    call_ = other.call_;
+    done_intercepting_ = false;
+    interceptor_methods_ = InterceptorBatchMethodsImpl();
+    return *this;
+  }
+
+  void FillOps(Call* call) override {
+    done_intercepting_ = false;
+    g_core_codegen_interface->grpc_call_ref(call->call());
+    call_ =
+        *call;  // It's fine to create a copy of call since it's just pointers
+
+    if (RunInterceptors()) {
+      ContinueFillOpsAfterInterception();
+    } else {
+      // After the interceptors are run, ContinueFillOpsAfterInterception will
+      // be run
+    }
+  }
+
+  bool FinalizeResult(void** tag, bool* status) override {
+    if (done_intercepting_) {
+      // We have already finished intercepting and filling in the results. This
+      // round trip from the core needed to be made because interceptors were
+      // run
+      *tag = return_tag_;
+      *status = saved_status_;
+      g_core_codegen_interface->grpc_call_unref(call_.call());
+      return true;
+    }
+
+    this->Op1::FinishOp(status);
+    this->Op2::FinishOp(status);
+    this->Op3::FinishOp(status);
+    this->Op4::FinishOp(status);
+    this->Op5::FinishOp(status);
+    this->Op6::FinishOp(status);
+    saved_status_ = *status;
+    if (RunInterceptorsPostRecv()) {
+      *tag = return_tag_;
+      g_core_codegen_interface->grpc_call_unref(call_.call());
+      return true;
+    }
+    // Interceptors are going to be run, so we can't return the tag just yet.
+    // After the interceptors are run, ContinueFinalizeResultAfterInterception
+    return false;
+  }
+
+  void set_output_tag(void* return_tag) { return_tag_ = return_tag; }
+
+  void* core_cq_tag() override { return core_cq_tag_; }
+
+  /// set_core_cq_tag is used to provide a different core CQ tag than "this".
+  /// This is used for callback-based tags, where the core tag is the core
+  /// callback function. It does not change the use or behavior of any other
+  /// function (such as FinalizeResult)
+  void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
+
+  // 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.
+  void SetHijackingState() override {
+    this->Op1::SetHijackingState(&interceptor_methods_);
+    this->Op2::SetHijackingState(&interceptor_methods_);
+    this->Op3::SetHijackingState(&interceptor_methods_);
+    this->Op4::SetHijackingState(&interceptor_methods_);
+    this->Op5::SetHijackingState(&interceptor_methods_);
+    this->Op6::SetHijackingState(&interceptor_methods_);
+  }
+
+  // Should be called after interceptors are done running
+  void ContinueFillOpsAfterInterception() override {
+    static const size_t MAX_OPS = 6;
+    grpc_op ops[MAX_OPS];
+    size_t nops = 0;
+    this->Op1::AddOp(ops, &nops);
+    this->Op2::AddOp(ops, &nops);
+    this->Op3::AddOp(ops, &nops);
+    this->Op4::AddOp(ops, &nops);
+    this->Op5::AddOp(ops, &nops);
+    this->Op6::AddOp(ops, &nops);
+    GPR_CODEGEN_ASSERT(GRPC_CALL_OK ==
+                       g_core_codegen_interface->grpc_call_start_batch(
+                           call_.call(), ops, nops, core_cq_tag(), nullptr));
+  }
+
+  // Should be called after interceptors are done running on the finalize result
+  // path
+  void ContinueFinalizeResultAfterInterception() override {
+    done_intercepting_ = true;
+    GPR_CODEGEN_ASSERT(GRPC_CALL_OK ==
+                       g_core_codegen_interface->grpc_call_start_batch(
+                           call_.call(), nullptr, 0, core_cq_tag(), nullptr));
+  }
+
+ private:
+  // Returns true if no interceptors need to be run
+  bool RunInterceptors() {
+    interceptor_methods_.ClearState();
+    interceptor_methods_.SetCallOpSetInterface(this);
+    interceptor_methods_.SetCall(&call_);
+    this->Op1::SetInterceptionHookPoint(&interceptor_methods_);
+    this->Op2::SetInterceptionHookPoint(&interceptor_methods_);
+    this->Op3::SetInterceptionHookPoint(&interceptor_methods_);
+    this->Op4::SetInterceptionHookPoint(&interceptor_methods_);
+    this->Op5::SetInterceptionHookPoint(&interceptor_methods_);
+    this->Op6::SetInterceptionHookPoint(&interceptor_methods_);
+    return interceptor_methods_.RunInterceptors();
+  }
+  // Returns true if no interceptors need to be run
+  bool RunInterceptorsPostRecv() {
+    // Call and OpSet had already been set on the set state.
+    // SetReverse also clears previously set hook points
+    interceptor_methods_.SetReverse();
+    this->Op1::SetFinishInterceptionHookPoint(&interceptor_methods_);
+    this->Op2::SetFinishInterceptionHookPoint(&interceptor_methods_);
+    this->Op3::SetFinishInterceptionHookPoint(&interceptor_methods_);
+    this->Op4::SetFinishInterceptionHookPoint(&interceptor_methods_);
+    this->Op5::SetFinishInterceptionHookPoint(&interceptor_methods_);
+    this->Op6::SetFinishInterceptionHookPoint(&interceptor_methods_);
+    return interceptor_methods_.RunInterceptors();
+  }
+
+  void* core_cq_tag_;
+  void* return_tag_;
+  Call call_;
+  bool done_intercepting_ = false;
+  InterceptorBatchMethodsImpl interceptor_methods_;
+  bool saved_status_;
+};
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CALL_OP_SET_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/call_op_set_interface.h b/third_party/grpc/include/grpcpp/impl/codegen/call_op_set_interface.h
new file mode 100644
index 0000000..3b74566
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/call_op_set_interface.h
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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_CALL_OP_SET_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_CALL_OP_SET_INTERFACE_H
+
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+
+namespace grpc {
+namespace internal {
+
+class Call;
+
+/// 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 core_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* core_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;
+};
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CALL_OP_SET_INTERFACE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/callback_common.h b/third_party/grpc/include/grpcpp/impl/codegen/callback_common.h
new file mode 100644
index 0000000..a3c8c41
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/callback_common.h
@@ -0,0 +1,217 @@
+/*
+ *
+ * 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_CALLBACK_COMMON_H
+#define GRPCPP_IMPL_CODEGEN_CALLBACK_COMMON_H
+
+#include <functional>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+namespace internal {
+
+/// An exception-safe way of invoking a user-specified callback function
+// TODO(vjpai): decide whether it is better for this to take a const lvalue
+//              parameter or an rvalue parameter, or if it even matters
+template <class Func, class... Args>
+void CatchingCallback(Func&& func, Args&&... args) {
+#if GRPC_ALLOW_EXCEPTIONS
+  try {
+    func(std::forward<Args>(args)...);
+  } catch (...) {
+    // nothing to return or change here, just don't crash the library
+  }
+#else   // GRPC_ALLOW_EXCEPTIONS
+  func(std::forward<Args>(args)...);
+#endif  // GRPC_ALLOW_EXCEPTIONS
+}
+
+template <class ReturnType, class Func, class... Args>
+ReturnType* CatchingReactorCreator(Func&& func, Args&&... args) {
+#if GRPC_ALLOW_EXCEPTIONS
+  try {
+    return func(std::forward<Args>(args)...);
+  } catch (...) {
+    // fail the RPC, don't crash the library
+    return nullptr;
+  }
+#else   // GRPC_ALLOW_EXCEPTIONS
+  return func(std::forward<Args>(args)...);
+#endif  // GRPC_ALLOW_EXCEPTIONS
+}
+
+// The contract on these tags is that they are single-shot. They must be
+// constructed and then fired at exactly one point. There is no expectation
+// that they can be reused without reconstruction.
+
+class CallbackWithStatusTag
+    : public grpc_experimental_completion_queue_functor {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(CallbackWithStatusTag));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  CallbackWithStatusTag(grpc_call* call, std::function<void(Status)> f,
+                        CompletionQueueTag* ops)
+      : call_(call), func_(std::move(f)), ops_(ops) {
+    g_core_codegen_interface->grpc_call_ref(call);
+    functor_run = &CallbackWithStatusTag::StaticRun;
+  }
+  ~CallbackWithStatusTag() {}
+  Status* status_ptr() { return &status_; }
+
+  // force_run can not be performed on a tag if operations using this tag
+  // have been sent to PerformOpsOnCall. It is intended for error conditions
+  // that are detected before the operations are internally processed.
+  void force_run(Status s) {
+    status_ = std::move(s);
+    Run(true);
+  }
+
+ private:
+  grpc_call* call_;
+  std::function<void(Status)> func_;
+  CompletionQueueTag* ops_;
+  Status status_;
+
+  static void StaticRun(grpc_experimental_completion_queue_functor* cb,
+                        int ok) {
+    static_cast<CallbackWithStatusTag*>(cb)->Run(static_cast<bool>(ok));
+  }
+  void Run(bool ok) {
+    void* ignored = ops_;
+
+    if (!ops_->FinalizeResult(&ignored, &ok)) {
+      // The tag was swallowed
+      return;
+    }
+    GPR_CODEGEN_ASSERT(ignored == ops_);
+
+    // Last use of func_ or status_, so ok to move them out
+    auto func = std::move(func_);
+    auto status = std::move(status_);
+    func_ = nullptr;     // reset to clear this out for sure
+    status_ = Status();  // reset to clear this out for sure
+    CatchingCallback(std::move(func), std::move(status));
+    g_core_codegen_interface->grpc_call_unref(call_);
+  }
+};
+
+/// CallbackWithSuccessTag can be reused multiple times, and will be used in
+/// this fashion for streaming operations. As a result, it shouldn't clear
+/// anything up until its destructor
+class CallbackWithSuccessTag
+    : public grpc_experimental_completion_queue_functor {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(CallbackWithSuccessTag));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  CallbackWithSuccessTag() : call_(nullptr) {}
+
+  CallbackWithSuccessTag(grpc_call* call, std::function<void(bool)> f,
+                         CompletionQueueTag* ops) {
+    Set(call, f, ops);
+  }
+
+  CallbackWithSuccessTag(const CallbackWithSuccessTag&) = delete;
+  CallbackWithSuccessTag& operator=(const CallbackWithSuccessTag&) = delete;
+
+  ~CallbackWithSuccessTag() { Clear(); }
+
+  // Set can only be called on a default-constructed or Clear'ed tag.
+  // It should never be called on a tag that was constructed with arguments
+  // or on a tag that has been Set before unless the tag has been cleared.
+  void Set(grpc_call* call, std::function<void(bool)> f,
+           CompletionQueueTag* ops) {
+    GPR_CODEGEN_ASSERT(call_ == nullptr);
+    g_core_codegen_interface->grpc_call_ref(call);
+    call_ = call;
+    func_ = std::move(f);
+    ops_ = ops;
+    functor_run = &CallbackWithSuccessTag::StaticRun;
+  }
+
+  void Clear() {
+    if (call_ != nullptr) {
+      grpc_call* call = call_;
+      call_ = nullptr;
+      func_ = nullptr;
+      g_core_codegen_interface->grpc_call_unref(call);
+    }
+  }
+
+  CompletionQueueTag* ops() { return ops_; }
+
+  // force_run can not be performed on a tag if operations using this tag
+  // have been sent to PerformOpsOnCall. It is intended for error conditions
+  // that are detected before the operations are internally processed.
+  void force_run(bool ok) { Run(ok); }
+
+  /// check if this tag is currently set
+  operator bool() const { return call_ != nullptr; }
+
+ private:
+  grpc_call* call_;
+  std::function<void(bool)> func_;
+  CompletionQueueTag* ops_;
+
+  static void StaticRun(grpc_experimental_completion_queue_functor* cb,
+                        int ok) {
+    static_cast<CallbackWithSuccessTag*>(cb)->Run(static_cast<bool>(ok));
+  }
+  void Run(bool ok) {
+    void* ignored = ops_;
+    // Allow a "false" return value from FinalizeResult to silence the
+    // callback, just as it silences a CQ tag in the async cases
+    auto* ops = ops_;
+    bool do_callback = ops_->FinalizeResult(&ignored, &ok);
+    GPR_CODEGEN_ASSERT(ignored == ops);
+
+    if (do_callback) {
+      CatchingCallback(func_, ok);
+    }
+  }
+};
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CALLBACK_COMMON_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/channel_interface.h b/third_party/grpc/include/grpcpp/impl/codegen/channel_interface.h
new file mode 100644
index 0000000..5353f5f
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/channel_interface.h
@@ -0,0 +1,164 @@
+/*
+ *
+ * Copyright 2016 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_CHANNEL_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
+
+#include <grpc/impl/codegen/connectivity_state.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/time.h>
+
+namespace grpc {
+class ChannelInterface;
+class ClientContext;
+class CompletionQueue;
+
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+
+namespace internal {
+class Call;
+class CallOpSetInterface;
+class RpcMethod;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+template <class InputMessage, class OutputMessage>
+class CallbackUnaryCallImpl;
+template <class R>
+class ClientAsyncReaderFactory;
+template <class W>
+class ClientAsyncWriterFactory;
+template <class W, class R>
+class ClientAsyncReaderWriterFactory;
+template <class R>
+class ClientAsyncResponseReaderFactory;
+template <class W, class R>
+class ClientCallbackReaderWriterFactory;
+template <class R>
+class ClientCallbackReaderFactory;
+template <class W>
+class ClientCallbackWriterFactory;
+class InterceptedChannel;
+}  // namespace internal
+
+/// Codegen interface for \a grpc::Channel.
+class ChannelInterface {
+ public:
+  virtual ~ChannelInterface() {}
+  /// Get the current channel state. If the channel is in IDLE and
+  /// \a try_to_connect is set to true, try to connect.
+  virtual grpc_connectivity_state GetState(bool try_to_connect) = 0;
+
+  /// Return the \a tag on \a cq when the channel state is changed or \a
+  /// deadline expires. \a GetState needs to called to get the current state.
+  template <typename T>
+  void NotifyOnStateChange(grpc_connectivity_state last_observed, T deadline,
+                           CompletionQueue* cq, void* tag) {
+    TimePoint<T> deadline_tp(deadline);
+    NotifyOnStateChangeImpl(last_observed, deadline_tp.raw_time(), cq, tag);
+  }
+
+  /// Blocking wait for channel state change or \a deadline expiration.
+  /// \a GetState needs to called to get the current state.
+  template <typename T>
+  bool WaitForStateChange(grpc_connectivity_state last_observed, T deadline) {
+    TimePoint<T> deadline_tp(deadline);
+    return WaitForStateChangeImpl(last_observed, deadline_tp.raw_time());
+  }
+
+  /// Wait for this channel to be connected
+  template <typename T>
+  bool WaitForConnected(T deadline) {
+    grpc_connectivity_state state;
+    while ((state = GetState(true)) != GRPC_CHANNEL_READY) {
+      if (!WaitForStateChange(state, deadline)) return false;
+    }
+    return true;
+  }
+
+ private:
+  template <class R>
+  friend class ::grpc::ClientReader;
+  template <class W>
+  friend class ::grpc::ClientWriter;
+  template <class W, class R>
+  friend class ::grpc::ClientReaderWriter;
+  template <class R>
+  friend class ::grpc::internal::ClientAsyncReaderFactory;
+  template <class W>
+  friend class ::grpc::internal::ClientAsyncWriterFactory;
+  template <class W, class R>
+  friend class ::grpc::internal::ClientAsyncReaderWriterFactory;
+  template <class R>
+  friend class ::grpc::internal::ClientAsyncResponseReaderFactory;
+  template <class W, class R>
+  friend class ::grpc::internal::ClientCallbackReaderWriterFactory;
+  template <class R>
+  friend class ::grpc::internal::ClientCallbackReaderFactory;
+  template <class W>
+  friend class ::grpc::internal::ClientCallbackWriterFactory;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::BlockingUnaryCallImpl;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::CallbackUnaryCallImpl;
+  friend class ::grpc::internal::RpcMethod;
+  friend class ::grpc::internal::InterceptedChannel;
+  virtual internal::Call CreateCall(const internal::RpcMethod& method,
+                                    ClientContext* context,
+                                    CompletionQueue* cq) = 0;
+  virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
+                                internal::Call* call) = 0;
+  virtual void* RegisterMethod(const char* method) = 0;
+  virtual void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
+                                       gpr_timespec deadline,
+                                       CompletionQueue* cq, void* tag) = 0;
+  virtual bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
+                                      gpr_timespec deadline) = 0;
+
+  // EXPERIMENTAL
+  // This is needed to keep codegen_test_minimal happy. InterceptedChannel needs
+  // to make use of this but can't directly call Channel's implementation
+  // because of the test.
+  // Returns an empty Call object (rather than being pure) since this is a new
+  // method and adding a new pure method to an interface would be a breaking
+  // change (even though this is private and non-API)
+  virtual internal::Call CreateCallInternal(const internal::RpcMethod& method,
+                                            ClientContext* context,
+                                            CompletionQueue* cq,
+                                            size_t interceptor_pos) {
+    return internal::Call();
+  }
+
+  // EXPERIMENTAL
+  // A method to get the callbackable completion queue associated with this
+  // channel. If the return value is nullptr, this channel doesn't support
+  // callback operations.
+  // TODO(vjpai): Consider a better default like using a global CQ
+  // Returns nullptr (rather than being pure) since this is a post-1.0 method
+  // and adding a new pure method to an interface would be a breaking change
+  // (even though this is private and non-API)
+  virtual CompletionQueue* CallbackCQ() { return nullptr; }
+};
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CHANNEL_INTERFACE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/client_callback.h b/third_party/grpc/include/grpcpp/impl/codegen/client_callback.h
new file mode 100644
index 0000000..66cf9b7
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/client_callback.h
@@ -0,0 +1,750 @@
+/*
+ *
+ * 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_CLIENT_CALLBACK_H
+#define GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H
+
+#include <functional>
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/call_op_set.h>
+#include <grpcpp/impl/codegen/callback_common.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class Channel;
+class ClientContext;
+class CompletionQueue;
+
+namespace internal {
+class RpcMethod;
+
+/// Perform a callback-based unary call
+/// TODO(vjpai): Combine as much as possible with the blocking unary call code
+template <class InputMessage, class OutputMessage>
+void CallbackUnaryCall(ChannelInterface* channel, const RpcMethod& method,
+                       ClientContext* context, const InputMessage* request,
+                       OutputMessage* result,
+                       std::function<void(Status)> on_completion) {
+  CallbackUnaryCallImpl<InputMessage, OutputMessage> x(
+      channel, method, context, request, result, on_completion);
+}
+
+template <class InputMessage, class OutputMessage>
+class CallbackUnaryCallImpl {
+ public:
+  CallbackUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
+                        ClientContext* context, const InputMessage* request,
+                        OutputMessage* result,
+                        std::function<void(Status)> on_completion) {
+    CompletionQueue* cq = channel->CallbackCQ();
+    GPR_CODEGEN_ASSERT(cq != nullptr);
+    Call call(channel->CreateCall(method, context, cq));
+
+    using FullCallOpSet =
+        CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+                  CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
+                  CallOpClientSendClose, CallOpClientRecvStatus>;
+
+    auto* ops = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(FullCallOpSet))) FullCallOpSet;
+
+    auto* tag = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(CallbackWithStatusTag)))
+        CallbackWithStatusTag(call.call(), on_completion, ops);
+
+    // TODO(vjpai): Unify code with sync API as much as possible
+    Status s = ops->SendMessage(*request);
+    if (!s.ok()) {
+      tag->force_run(s);
+      return;
+    }
+    ops->SendInitialMetadata(&context->send_initial_metadata_,
+                             context->initial_metadata_flags());
+    ops->RecvInitialMetadata(context);
+    ops->RecvMessage(result);
+    ops->AllowNoMessage();
+    ops->ClientSendClose();
+    ops->ClientRecvStatus(context, tag->status_ptr());
+    ops->set_core_cq_tag(tag);
+    call.PerformOps(ops);
+  }
+};
+}  // namespace internal
+
+namespace experimental {
+
+// Forward declarations
+template <class Request, class Response>
+class ClientBidiReactor;
+template <class Response>
+class ClientReadReactor;
+template <class Request>
+class ClientWriteReactor;
+
+// NOTE: The streaming objects are not actually implemented in the public API.
+//       These interfaces are provided for mocking only. Typical applications
+//       will interact exclusively with the reactors that they define.
+template <class Request, class Response>
+class ClientCallbackReaderWriter {
+ public:
+  virtual ~ClientCallbackReaderWriter() {}
+  virtual void StartCall() = 0;
+  virtual void Write(const Request* req, WriteOptions options) = 0;
+  virtual void WritesDone() = 0;
+  virtual void Read(Response* resp) = 0;
+
+ protected:
+  void BindReactor(ClientBidiReactor<Request, Response>* reactor) {
+    reactor->BindStream(this);
+  }
+};
+
+template <class Response>
+class ClientCallbackReader {
+ public:
+  virtual ~ClientCallbackReader() {}
+  virtual void StartCall() = 0;
+  virtual void Read(Response* resp) = 0;
+
+ protected:
+  void BindReactor(ClientReadReactor<Response>* reactor) {
+    reactor->BindReader(this);
+  }
+};
+
+template <class Request>
+class ClientCallbackWriter {
+ public:
+  virtual ~ClientCallbackWriter() {}
+  virtual void StartCall() = 0;
+  void Write(const Request* req) { Write(req, WriteOptions()); }
+  virtual void Write(const Request* req, WriteOptions options) = 0;
+  void WriteLast(const Request* req, WriteOptions options) {
+    Write(req, options.set_last_message());
+  }
+  virtual void WritesDone() = 0;
+
+ protected:
+  void BindReactor(ClientWriteReactor<Request>* reactor) {
+    reactor->BindWriter(this);
+  }
+};
+
+// The user must implement this reactor interface with reactions to each event
+// type that gets called by the library. An empty reaction is provided by
+// default
+template <class Request, class Response>
+class ClientBidiReactor {
+ public:
+  virtual ~ClientBidiReactor() {}
+  virtual void OnDone(const Status& s) {}
+  virtual void OnReadInitialMetadataDone(bool ok) {}
+  virtual void OnReadDone(bool ok) {}
+  virtual void OnWriteDone(bool ok) {}
+  virtual void OnWritesDoneDone(bool ok) {}
+
+  void StartCall() { stream_->StartCall(); }
+  void StartRead(Response* resp) { stream_->Read(resp); }
+  void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); }
+  void StartWrite(const Request* req, WriteOptions options) {
+    stream_->Write(req, std::move(options));
+  }
+  void StartWriteLast(const Request* req, WriteOptions options) {
+    StartWrite(req, std::move(options.set_last_message()));
+  }
+  void StartWritesDone() { stream_->WritesDone(); }
+
+ private:
+  friend class ClientCallbackReaderWriter<Request, Response>;
+  void BindStream(ClientCallbackReaderWriter<Request, Response>* stream) {
+    stream_ = stream;
+  }
+  ClientCallbackReaderWriter<Request, Response>* stream_;
+};
+
+template <class Response>
+class ClientReadReactor {
+ public:
+  virtual ~ClientReadReactor() {}
+  virtual void OnDone(const Status& s) {}
+  virtual void OnReadInitialMetadataDone(bool ok) {}
+  virtual void OnReadDone(bool ok) {}
+
+  void StartCall() { reader_->StartCall(); }
+  void StartRead(Response* resp) { reader_->Read(resp); }
+
+ private:
+  friend class ClientCallbackReader<Response>;
+  void BindReader(ClientCallbackReader<Response>* reader) { reader_ = reader; }
+  ClientCallbackReader<Response>* reader_;
+};
+
+template <class Request>
+class ClientWriteReactor {
+ public:
+  virtual ~ClientWriteReactor() {}
+  virtual void OnDone(const Status& s) {}
+  virtual void OnReadInitialMetadataDone(bool ok) {}
+  virtual void OnWriteDone(bool ok) {}
+  virtual void OnWritesDoneDone(bool ok) {}
+
+  void StartCall() { writer_->StartCall(); }
+  void StartWrite(const Request* req) { StartWrite(req, WriteOptions()); }
+  void StartWrite(const Request* req, WriteOptions options) {
+    writer_->Write(req, std::move(options));
+  }
+  void StartWriteLast(const Request* req, WriteOptions options) {
+    StartWrite(req, std::move(options.set_last_message()));
+  }
+  void StartWritesDone() { writer_->WritesDone(); }
+
+ private:
+  friend class ClientCallbackWriter<Request>;
+  void BindWriter(ClientCallbackWriter<Request>* writer) { writer_ = writer; }
+  ClientCallbackWriter<Request>* writer_;
+};
+
+}  // namespace experimental
+
+namespace internal {
+
+// Forward declare factory classes for friendship
+template <class Request, class Response>
+class ClientCallbackReaderWriterFactory;
+template <class Response>
+class ClientCallbackReaderFactory;
+template <class Request>
+class ClientCallbackWriterFactory;
+
+template <class Request, class Response>
+class ClientCallbackReaderWriterImpl
+    : public ::grpc::experimental::ClientCallbackReaderWriter<Request,
+                                                              Response> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientCallbackReaderWriterImpl));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void MaybeFinish() {
+    if (--callbacks_outstanding_ == 0) {
+      Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackReaderWriterImpl();
+      g_core_codegen_interface->grpc_call_unref(call);
+      reactor->OnDone(s);
+    }
+  }
+
+  void StartCall() override {
+    // This call initiates two batches, plus any backlog, each with a callback
+    // 1. Send initial metadata (unless corked) + recv initial metadata
+    // 2. Any read backlog
+    // 3. Recv trailing metadata, on_completion callback
+    // 4. Any write backlog
+    // 5. See if the call can finish (if other callbacks were triggered already)
+    started_ = true;
+
+    start_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnReadInitialMetadataDone(ok);
+                     MaybeFinish();
+                   },
+                   &start_ops_);
+    if (!start_corked_) {
+      start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                     context_->initial_metadata_flags());
+    }
+    start_ops_.RecvInitialMetadata(context_);
+    start_ops_.set_core_cq_tag(&start_tag_);
+    call_.PerformOps(&start_ops_);
+
+    // Also set up the read and write tags so that they don't have to be set up
+    // each time
+    write_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnWriteDone(ok);
+                     MaybeFinish();
+                   },
+                   &write_ops_);
+    write_ops_.set_core_cq_tag(&write_tag_);
+
+    read_tag_.Set(call_.call(),
+                  [this](bool ok) {
+                    reactor_->OnReadDone(ok);
+                    MaybeFinish();
+                  },
+                  &read_ops_);
+    read_ops_.set_core_cq_tag(&read_tag_);
+    if (read_ops_at_start_) {
+      call_.PerformOps(&read_ops_);
+    }
+
+    finish_tag_.Set(call_.call(), [this](bool ok) { MaybeFinish(); },
+                    &finish_ops_);
+    finish_ops_.ClientRecvStatus(context_, &finish_status_);
+    finish_ops_.set_core_cq_tag(&finish_tag_);
+    call_.PerformOps(&finish_ops_);
+
+    if (write_ops_at_start_) {
+      call_.PerformOps(&write_ops_);
+    }
+
+    if (writes_done_ops_at_start_) {
+      call_.PerformOps(&writes_done_ops_);
+    }
+    MaybeFinish();
+  }
+
+  void Read(Response* msg) override {
+    read_ops_.RecvMessage(msg);
+    callbacks_outstanding_++;
+    if (started_) {
+      call_.PerformOps(&read_ops_);
+    } else {
+      read_ops_at_start_ = true;
+    }
+  }
+
+  void Write(const Request* msg, WriteOptions options) override {
+    if (start_corked_) {
+      write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                     context_->initial_metadata_flags());
+      start_corked_ = false;
+    }
+    // TODO(vjpai): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok());
+
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+      write_ops_.ClientSendClose();
+    }
+    callbacks_outstanding_++;
+    if (started_) {
+      call_.PerformOps(&write_ops_);
+    } else {
+      write_ops_at_start_ = true;
+    }
+  }
+  void WritesDone() override {
+    if (start_corked_) {
+      writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                           context_->initial_metadata_flags());
+      start_corked_ = false;
+    }
+    writes_done_ops_.ClientSendClose();
+    writes_done_tag_.Set(call_.call(),
+                         [this](bool ok) {
+                           reactor_->OnWritesDoneDone(ok);
+                           MaybeFinish();
+                         },
+                         &writes_done_ops_);
+    writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
+    callbacks_outstanding_++;
+    if (started_) {
+      call_.PerformOps(&writes_done_ops_);
+    } else {
+      writes_done_ops_at_start_ = true;
+    }
+  }
+
+ private:
+  friend class ClientCallbackReaderWriterFactory<Request, Response>;
+
+  ClientCallbackReaderWriterImpl(
+      Call call, ClientContext* context,
+      ::grpc::experimental::ClientBidiReactor<Request, Response>* reactor)
+      : context_(context),
+        call_(call),
+        reactor_(reactor),
+        start_corked_(context_->initial_metadata_corked_) {
+    this->BindReactor(reactor);
+  }
+
+  ClientContext* context_;
+  Call call_;
+  ::grpc::experimental::ClientBidiReactor<Request, Response>* reactor_;
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpRecvInitialMetadata> start_ops_;
+  CallbackWithSuccessTag start_tag_;
+  bool start_corked_;
+
+  CallOpSet<CallOpClientRecvStatus> finish_ops_;
+  CallbackWithSuccessTag finish_tag_;
+  Status finish_status_;
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
+      write_ops_;
+  CallbackWithSuccessTag write_tag_;
+  bool write_ops_at_start_{false};
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpClientSendClose> writes_done_ops_;
+  CallbackWithSuccessTag writes_done_tag_;
+  bool writes_done_ops_at_start_{false};
+
+  CallOpSet<CallOpRecvMessage<Response>> read_ops_;
+  CallbackWithSuccessTag read_tag_;
+  bool read_ops_at_start_{false};
+
+  // Minimum of 3 callbacks to pre-register for StartCall, start, and finish
+  std::atomic_int callbacks_outstanding_{3};
+  bool started_{false};
+};
+
+template <class Request, class Response>
+class ClientCallbackReaderWriterFactory {
+ public:
+  static void Create(
+      ChannelInterface* channel, const ::grpc::internal::RpcMethod& method,
+      ClientContext* context,
+      ::grpc::experimental::ClientBidiReactor<Request, Response>* reactor) {
+    Call call = channel->CreateCall(method, context, channel->CallbackCQ());
+
+    g_core_codegen_interface->grpc_call_ref(call.call());
+    new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientCallbackReaderWriterImpl<Request, Response>)))
+        ClientCallbackReaderWriterImpl<Request, Response>(call, context,
+                                                          reactor);
+  }
+};
+
+template <class Response>
+class ClientCallbackReaderImpl
+    : public ::grpc::experimental::ClientCallbackReader<Response> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientCallbackReaderImpl));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void MaybeFinish() {
+    if (--callbacks_outstanding_ == 0) {
+      Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackReaderImpl();
+      g_core_codegen_interface->grpc_call_unref(call);
+      reactor->OnDone(s);
+    }
+  }
+
+  void StartCall() override {
+    // This call initiates two batches, plus any backlog, each with a callback
+    // 1. Send initial metadata (unless corked) + recv initial metadata
+    // 2. Any backlog
+    // 3. Recv trailing metadata, on_completion callback
+    // 4. See if the call can finish (if other callbacks were triggered already)
+    started_ = true;
+
+    start_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnReadInitialMetadataDone(ok);
+                     MaybeFinish();
+                   },
+                   &start_ops_);
+    start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                   context_->initial_metadata_flags());
+    start_ops_.RecvInitialMetadata(context_);
+    start_ops_.set_core_cq_tag(&start_tag_);
+    call_.PerformOps(&start_ops_);
+
+    // Also set up the read tag so it doesn't have to be set up each time
+    read_tag_.Set(call_.call(),
+                  [this](bool ok) {
+                    reactor_->OnReadDone(ok);
+                    MaybeFinish();
+                  },
+                  &read_ops_);
+    read_ops_.set_core_cq_tag(&read_tag_);
+    if (read_ops_at_start_) {
+      call_.PerformOps(&read_ops_);
+    }
+
+    finish_tag_.Set(call_.call(), [this](bool ok) { MaybeFinish(); },
+                    &finish_ops_);
+    finish_ops_.ClientRecvStatus(context_, &finish_status_);
+    finish_ops_.set_core_cq_tag(&finish_tag_);
+    call_.PerformOps(&finish_ops_);
+
+    MaybeFinish();
+  }
+
+  void Read(Response* msg) override {
+    read_ops_.RecvMessage(msg);
+    callbacks_outstanding_++;
+    if (started_) {
+      call_.PerformOps(&read_ops_);
+    } else {
+      read_ops_at_start_ = true;
+    }
+  }
+
+ private:
+  friend class ClientCallbackReaderFactory<Response>;
+
+  template <class Request>
+  ClientCallbackReaderImpl(
+      Call call, ClientContext* context, Request* request,
+      ::grpc::experimental::ClientReadReactor<Response>* reactor)
+      : context_(context), call_(call), reactor_(reactor) {
+    this->BindReactor(reactor);
+    // TODO(vjpai): don't assert
+    GPR_CODEGEN_ASSERT(start_ops_.SendMessage(*request).ok());
+    start_ops_.ClientSendClose();
+  }
+
+  ClientContext* context_;
+  Call call_;
+  ::grpc::experimental::ClientReadReactor<Response>* reactor_;
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose,
+            CallOpRecvInitialMetadata>
+      start_ops_;
+  CallbackWithSuccessTag start_tag_;
+
+  CallOpSet<CallOpClientRecvStatus> finish_ops_;
+  CallbackWithSuccessTag finish_tag_;
+  Status finish_status_;
+
+  CallOpSet<CallOpRecvMessage<Response>> read_ops_;
+  CallbackWithSuccessTag read_tag_;
+  bool read_ops_at_start_{false};
+
+  // Minimum of 3 callbacks to pre-register for StartCall, start, and finish
+  std::atomic_int callbacks_outstanding_{3};
+  bool started_{false};
+};
+
+template <class Response>
+class ClientCallbackReaderFactory {
+ public:
+  template <class Request>
+  static void Create(
+      ChannelInterface* channel, const ::grpc::internal::RpcMethod& method,
+      ClientContext* context, const Request* request,
+      ::grpc::experimental::ClientReadReactor<Response>* reactor) {
+    Call call = channel->CreateCall(method, context, channel->CallbackCQ());
+
+    g_core_codegen_interface->grpc_call_ref(call.call());
+    new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientCallbackReaderImpl<Response>)))
+        ClientCallbackReaderImpl<Response>(call, context, request, reactor);
+  }
+};
+
+template <class Request>
+class ClientCallbackWriterImpl
+    : public ::grpc::experimental::ClientCallbackWriter<Request> {
+ public:
+  // always allocated against a call arena, no memory free required
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(ClientCallbackWriterImpl));
+  }
+
+  // This operator should never be called as the memory should be freed as part
+  // of the arena destruction. It only exists to provide a matching operator
+  // delete to the operator new so that some compilers will not complain (see
+  // https://github.com/grpc/grpc/issues/11301) Note at the time of adding this
+  // there are no tests catching the compiler warning.
+  static void operator delete(void*, void*) { assert(0); }
+
+  void MaybeFinish() {
+    if (--callbacks_outstanding_ == 0) {
+      Status s = std::move(finish_status_);
+      auto* reactor = reactor_;
+      auto* call = call_.call();
+      this->~ClientCallbackWriterImpl();
+      g_core_codegen_interface->grpc_call_unref(call);
+      reactor->OnDone(s);
+    }
+  }
+
+  void StartCall() override {
+    // This call initiates two batches, plus any backlog, each with a callback
+    // 1. Send initial metadata (unless corked) + recv initial metadata
+    // 2. Recv trailing metadata, on_completion callback
+    // 3. Any backlog
+    // 4. See if the call can finish (if other callbacks were triggered already)
+    started_ = true;
+
+    start_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnReadInitialMetadataDone(ok);
+                     MaybeFinish();
+                   },
+                   &start_ops_);
+    if (!start_corked_) {
+      start_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                     context_->initial_metadata_flags());
+    }
+    start_ops_.RecvInitialMetadata(context_);
+    start_ops_.set_core_cq_tag(&start_tag_);
+    call_.PerformOps(&start_ops_);
+
+    // Also set up the read and write tags so that they don't have to be set up
+    // each time
+    write_tag_.Set(call_.call(),
+                   [this](bool ok) {
+                     reactor_->OnWriteDone(ok);
+                     MaybeFinish();
+                   },
+                   &write_ops_);
+    write_ops_.set_core_cq_tag(&write_tag_);
+
+    finish_tag_.Set(call_.call(), [this](bool ok) { MaybeFinish(); },
+                    &finish_ops_);
+    finish_ops_.ClientRecvStatus(context_, &finish_status_);
+    finish_ops_.set_core_cq_tag(&finish_tag_);
+    call_.PerformOps(&finish_ops_);
+
+    if (write_ops_at_start_) {
+      call_.PerformOps(&write_ops_);
+    }
+
+    if (writes_done_ops_at_start_) {
+      call_.PerformOps(&writes_done_ops_);
+    }
+
+    MaybeFinish();
+  }
+
+  void Write(const Request* msg, WriteOptions options) override {
+    if (start_corked_) {
+      write_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                     context_->initial_metadata_flags());
+      start_corked_ = false;
+    }
+    // TODO(vjpai): don't assert
+    GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*msg).ok());
+
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+      write_ops_.ClientSendClose();
+    }
+    callbacks_outstanding_++;
+    if (started_) {
+      call_.PerformOps(&write_ops_);
+    } else {
+      write_ops_at_start_ = true;
+    }
+  }
+  void WritesDone() override {
+    if (start_corked_) {
+      writes_done_ops_.SendInitialMetadata(&context_->send_initial_metadata_,
+                                           context_->initial_metadata_flags());
+      start_corked_ = false;
+    }
+    writes_done_ops_.ClientSendClose();
+    writes_done_tag_.Set(call_.call(),
+                         [this](bool ok) {
+                           reactor_->OnWritesDoneDone(ok);
+                           MaybeFinish();
+                         },
+                         &writes_done_ops_);
+    writes_done_ops_.set_core_cq_tag(&writes_done_tag_);
+    callbacks_outstanding_++;
+    if (started_) {
+      call_.PerformOps(&writes_done_ops_);
+    } else {
+      writes_done_ops_at_start_ = true;
+    }
+  }
+
+ private:
+  friend class ClientCallbackWriterFactory<Request>;
+
+  template <class Response>
+  ClientCallbackWriterImpl(
+      Call call, ClientContext* context, Response* response,
+      ::grpc::experimental::ClientWriteReactor<Request>* reactor)
+      : context_(context),
+        call_(call),
+        reactor_(reactor),
+        start_corked_(context_->initial_metadata_corked_) {
+    this->BindReactor(reactor);
+    finish_ops_.RecvMessage(response);
+    finish_ops_.AllowNoMessage();
+  }
+
+  ClientContext* context_;
+  Call call_;
+  ::grpc::experimental::ClientWriteReactor<Request>* reactor_;
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpRecvInitialMetadata> start_ops_;
+  CallbackWithSuccessTag start_tag_;
+  bool start_corked_;
+
+  CallOpSet<CallOpGenericRecvMessage, CallOpClientRecvStatus> finish_ops_;
+  CallbackWithSuccessTag finish_tag_;
+  Status finish_status_;
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
+      write_ops_;
+  CallbackWithSuccessTag write_tag_;
+  bool write_ops_at_start_{false};
+
+  CallOpSet<CallOpSendInitialMetadata, CallOpClientSendClose> writes_done_ops_;
+  CallbackWithSuccessTag writes_done_tag_;
+  bool writes_done_ops_at_start_{false};
+
+  // Minimum of 3 callbacks to pre-register for StartCall, start, and finish
+  std::atomic_int callbacks_outstanding_{3};
+  bool started_{false};
+};
+
+template <class Request>
+class ClientCallbackWriterFactory {
+ public:
+  template <class Response>
+  static void Create(
+      ChannelInterface* channel, const ::grpc::internal::RpcMethod& method,
+      ClientContext* context, Response* response,
+      ::grpc::experimental::ClientWriteReactor<Request>* reactor) {
+    Call call = channel->CreateCall(method, context, channel->CallbackCQ());
+
+    g_core_codegen_interface->grpc_call_ref(call.call());
+    new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call.call(), sizeof(ClientCallbackWriterImpl<Request>)))
+        ClientCallbackWriterImpl<Request>(call, context, response, reactor);
+  }
+};
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CLIENT_CALLBACK_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/client_context.h b/third_party/grpc/include/grpcpp/impl/codegen/client_context.h
new file mode 100644
index 0000000..5946488
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/client_context.h
@@ -0,0 +1,485 @@
+/*
+ *
+ * Copyright 2015 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.
+ *
+ */
+
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+/// side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistent at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+
+#ifndef GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
+
+#include <map>
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include <grpc/impl/codegen/compression_types.h>
+#include <grpc/impl/codegen/propagation_bits.h>
+#include <grpcpp/impl/codegen/client_interceptor.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/create_auth_context.h>
+#include <grpcpp/impl/codegen/metadata_map.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct census_context;
+struct grpc_call;
+
+namespace grpc {
+
+class Channel;
+class ChannelInterface;
+class CompletionQueue;
+class CallCredentials;
+class ClientContext;
+
+namespace internal {
+class RpcMethod;
+class CallOpClientRecvStatus;
+class CallOpRecvInitialMetadata;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+template <class InputMessage, class OutputMessage>
+class CallbackUnaryCallImpl;
+template <class Request, class Response>
+class ClientCallbackReaderWriterImpl;
+template <class Response>
+class ClientCallbackReaderImpl;
+template <class Request>
+class ClientCallbackWriterImpl;
+}  // namespace internal
+
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+template <class R>
+class ClientAsyncReader;
+template <class W>
+class ClientAsyncWriter;
+template <class W, class R>
+class ClientAsyncReaderWriter;
+template <class R>
+class ClientAsyncResponseReader;
+class ServerContext;
+
+/// Options for \a ClientContext::FromServerContext specifying which traits from
+/// the \a ServerContext to propagate (copy) from it into a new \a
+/// ClientContext.
+///
+/// \see ClientContext::FromServerContext
+class PropagationOptions {
+ public:
+  PropagationOptions() : propagate_(GRPC_PROPAGATE_DEFAULTS) {}
+
+  PropagationOptions& enable_deadline_propagation() {
+    propagate_ |= GRPC_PROPAGATE_DEADLINE;
+    return *this;
+  }
+
+  PropagationOptions& disable_deadline_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_DEADLINE;
+    return *this;
+  }
+
+  PropagationOptions& enable_census_stats_propagation() {
+    propagate_ |= GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& disable_census_stats_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_CENSUS_STATS_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& enable_census_tracing_propagation() {
+    propagate_ |= GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& disable_census_tracing_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_CENSUS_TRACING_CONTEXT;
+    return *this;
+  }
+
+  PropagationOptions& enable_cancellation_propagation() {
+    propagate_ |= GRPC_PROPAGATE_CANCELLATION;
+    return *this;
+  }
+
+  PropagationOptions& disable_cancellation_propagation() {
+    propagate_ &= ~GRPC_PROPAGATE_CANCELLATION;
+    return *this;
+  }
+
+  uint32_t c_bitmask() const { return propagate_; }
+
+ private:
+  uint32_t propagate_;
+};
+
+namespace testing {
+class InteropClientContextInspector;
+}  // namespace testing
+
+/// A ClientContext allows the person implementing a service client to:
+///
+/// - Add custom metadata key-value pairs that will propagated to the server
+///   side.
+/// - Control call settings such as compression and authentication.
+/// - Initial and trailing metadata coming from the server.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call they are invoked with, that
+/// is to say, they aren't sticky. Some of these settings, such as the
+/// compression options, can be made persistent at channel construction time
+/// (see \a grpc::CreateCustomChannel).
+///
+/// \warning ClientContext instances should \em not be reused across rpcs.
+/// \warning The ClientContext instance used for creating an rpc must remain
+///          alive and valid for the lifetime of the rpc.
+class ClientContext {
+ public:
+  ClientContext();
+  ~ClientContext();
+
+  /// Create a new \a ClientContext as a child of an incoming server call,
+  /// according to \a options (\see PropagationOptions).
+  ///
+  /// \param server_context The source server context to use as the basis for
+  /// constructing the client context.
+  /// \param options The options controlling what to copy from the \a
+  /// server_context.
+  ///
+  /// \return A newly constructed \a ClientContext instance based on \a
+  /// server_context, with traits propagated (copied) according to \a options.
+  static std::unique_ptr<ClientContext> FromServerContext(
+      const ServerContext& server_context,
+      PropagationOptions options = PropagationOptions());
+
+  /// Add the (\a meta_key, \a meta_value) pair to the metadata associated with
+  /// a client call. These are made available at the server side by the \a
+  /// grpc::ServerContext::client_metadata() method.
+  ///
+  /// \warning This method should only be called before invoking the rpc.
+  ///
+  /// \param meta_key The metadata key. If \a meta_value is binary data, it must
+  /// end in "-bin".
+  /// \param meta_value The metadata value. If its value is binary, the key name
+  /// must end in "-bin".
+  ///
+  /// Metadata must conform to the following format:
+  /// Custom-Metadata -> Binary-Header / ASCII-Header
+  /// Binary-Header -> {Header-Name "-bin" } {binary value}
+  /// ASCII-Header -> Header-Name ASCII-Value
+  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
+  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
+  void AddMetadata(const grpc::string& meta_key,
+                   const grpc::string& meta_value);
+
+  /// Return a collection of initial metadata key-value pairs. Note that keys
+  /// may happen more than once (ie, a \a std::multimap is returned).
+  ///
+  /// \warning This method should only be called after initial metadata has been
+  /// received. For streaming calls, see \a
+  /// ClientReaderInterface::WaitForInitialMetadata().
+  ///
+  /// \return A multimap of initial metadata key-value pairs from the server.
+  const std::multimap<grpc::string_ref, grpc::string_ref>&
+  GetServerInitialMetadata() const {
+    GPR_CODEGEN_ASSERT(initial_metadata_received_);
+    return *recv_initial_metadata_.map();
+  }
+
+  /// Return a collection of trailing metadata key-value pairs. Note that keys
+  /// may happen more than once (ie, a \a std::multimap is returned).
+  ///
+  /// \warning This method is only callable once the stream has finished.
+  ///
+  /// \return A multimap of metadata trailing key-value pairs from the server.
+  const std::multimap<grpc::string_ref, grpc::string_ref>&
+  GetServerTrailingMetadata() const {
+    // TODO(yangg) check finished
+    return *trailing_metadata_.map();
+  }
+
+  /// Set the deadline for the client call.
+  ///
+  /// \warning This method should only be called before invoking the rpc.
+  ///
+  /// \param deadline the deadline for the client call. Units are determined by
+  /// the type used. The deadline is an absolute (not relative) time.
+  template <typename T>
+  void set_deadline(const T& deadline) {
+    TimePoint<T> deadline_tp(deadline);
+    deadline_ = deadline_tp.raw_time();
+  }
+
+  /// EXPERIMENTAL: Indicate that this request is idempotent.
+  /// By default, RPCs are assumed to <i>not</i> be idempotent.
+  ///
+  /// If true, the gRPC library assumes that it's safe to initiate
+  /// this RPC multiple times.
+  void set_idempotent(bool idempotent) { idempotent_ = idempotent; }
+
+  /// EXPERIMENTAL: Set this request to be cacheable.
+  /// If set, grpc is free to use the HTTP GET verb for sending the request,
+  /// with the possibility of receiving a cached response.
+  void set_cacheable(bool cacheable) { cacheable_ = cacheable; }
+
+  /// EXPERIMENTAL: Trigger wait-for-ready or not on this request.
+  /// See https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md.
+  /// If set, if an RPC is made when a channel's connectivity state is
+  /// TRANSIENT_FAILURE or CONNECTING, the call will not "fail fast",
+  /// and the channel will wait until the channel is READY before making the
+  /// call.
+  void set_wait_for_ready(bool wait_for_ready) {
+    wait_for_ready_ = wait_for_ready;
+    wait_for_ready_explicitly_set_ = true;
+  }
+
+  /// DEPRECATED: Use set_wait_for_ready() instead.
+  void set_fail_fast(bool fail_fast) { set_wait_for_ready(!fail_fast); }
+
+  /// Return the deadline for the client call.
+  std::chrono::system_clock::time_point deadline() const {
+    return Timespec2Timepoint(deadline_);
+  }
+
+  /// Return a \a gpr_timespec representation of the client call's deadline.
+  gpr_timespec raw_deadline() const { return deadline_; }
+
+  /// Set the per call authority header (see
+  /// https://tools.ietf.org/html/rfc7540#section-8.1.2.3).
+  void set_authority(const grpc::string& authority) { authority_ = authority; }
+
+  /// Return the authentication context for this client call.
+  ///
+  /// \see grpc::AuthContext.
+  std::shared_ptr<const AuthContext> auth_context() const {
+    if (auth_context_.get() == nullptr) {
+      auth_context_ = CreateAuthContext(call_);
+    }
+    return auth_context_;
+  }
+
+  /// Set credentials for the client call.
+  ///
+  /// A credentials object encapsulates all the state needed by a client to
+  /// authenticate with a server and make various assertions, e.g., about the
+  /// client’s identity, role, or whether it is authorized to make a particular
+  /// call.
+  ///
+  /// \see  https://grpc.io/docs/guides/auth.html
+  void set_credentials(const std::shared_ptr<CallCredentials>& creds) {
+    creds_ = creds;
+  }
+
+  /// Return the compression algorithm the client call will request be used.
+  /// Note that the gRPC runtime may decide to ignore this request, for example,
+  /// due to resource constraints.
+  grpc_compression_algorithm compression_algorithm() const {
+    return compression_algorithm_;
+  }
+
+  /// Set \a algorithm to be the compression algorithm used for the client call.
+  ///
+  /// \param algorithm The compression algorithm used for the client call.
+  void set_compression_algorithm(grpc_compression_algorithm algorithm);
+
+  /// Flag whether the initial metadata should be \a corked
+  ///
+  /// If \a corked is true, then the initial metadata will be coalesced with the
+  /// write of first message in the stream. As a result, any tag set for the
+  /// initial metadata operation (starting a client-streaming or bidi-streaming
+  /// RPC) will not actually be sent to the completion queue or delivered
+  /// via Next.
+  ///
+  /// \param corked The flag indicating whether the initial metadata is to be
+  /// corked or not.
+  void set_initial_metadata_corked(bool corked) {
+    initial_metadata_corked_ = corked;
+  }
+
+  /// Return the peer uri in a string.
+  ///
+  /// \warning This value is never authenticated or subject to any security
+  /// related code. It must not be used for any authentication related
+  /// functionality. Instead, use auth_context.
+  ///
+  /// \return The call's peer URI.
+  grpc::string peer() const;
+
+  /// Get and set census context.
+  void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
+  struct census_context* census_context() const {
+    return census_context_;
+  }
+
+  /// Send a best-effort out-of-band cancel on the call associated with
+  /// this client context.  The call could be in any stage; e.g., if it is
+  /// already finished, it may still return success.
+  ///
+  /// There is no guarantee the call will be cancelled.
+  ///
+  /// Note that TryCancel() does not change any of the tags that are pending
+  /// on the completion queue. All pending tags will still be delivered
+  /// (though their ok result may reflect the effect of cancellation).
+  void TryCancel();
+
+  /// Global Callbacks
+  ///
+  /// Can be set exactly once per application to install hooks whenever
+  /// a client context is constructed and destructed.
+  class GlobalCallbacks {
+   public:
+    virtual ~GlobalCallbacks() {}
+    virtual void DefaultConstructor(ClientContext* context) = 0;
+    virtual void Destructor(ClientContext* context) = 0;
+  };
+  static void SetGlobalCallbacks(GlobalCallbacks* callbacks);
+
+  /// Should be used for framework-level extensions only.
+  /// Applications never need to call this method.
+  grpc_call* c_call() { return call_; }
+
+  /// EXPERIMENTAL debugging API
+  ///
+  /// if status is not ok() for an RPC, this will return a detailed string
+  /// of the gRPC Core error that led to the failure. It should not be relied
+  /// upon for anything other than gaining more debug data in failure cases.
+  grpc::string debug_error_string() const { return debug_error_string_; }
+
+ private:
+  // Disallow copy and assign.
+  ClientContext(const ClientContext&);
+  ClientContext& operator=(const ClientContext&);
+
+  friend class ::grpc::testing::InteropClientContextInspector;
+  friend class ::grpc::internal::CallOpClientRecvStatus;
+  friend class ::grpc::internal::CallOpRecvInitialMetadata;
+  friend class Channel;
+  template <class R>
+  friend class ::grpc::ClientReader;
+  template <class W>
+  friend class ::grpc::ClientWriter;
+  template <class W, class R>
+  friend class ::grpc::ClientReaderWriter;
+  template <class R>
+  friend class ::grpc::ClientAsyncReader;
+  template <class W>
+  friend class ::grpc::ClientAsyncWriter;
+  template <class W, class R>
+  friend class ::grpc::ClientAsyncReaderWriter;
+  template <class R>
+  friend class ::grpc::ClientAsyncResponseReader;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::BlockingUnaryCallImpl;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::CallbackUnaryCallImpl;
+  template <class Request, class Response>
+  friend class ::grpc::internal::ClientCallbackReaderWriterImpl;
+  template <class Response>
+  friend class ::grpc::internal::ClientCallbackReaderImpl;
+  template <class Request>
+  friend class ::grpc::internal::ClientCallbackWriterImpl;
+
+  // Used by friend class CallOpClientRecvStatus
+  void set_debug_error_string(const grpc::string& debug_error_string) {
+    debug_error_string_ = debug_error_string;
+  }
+
+  grpc_call* call() const { return call_; }
+  void set_call(grpc_call* call, const std::shared_ptr<Channel>& channel);
+
+  experimental::ClientRpcInfo* set_client_rpc_info(
+      const char* method, internal::RpcMethod::RpcType type,
+      grpc::ChannelInterface* channel,
+      const std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>&
+          creators,
+      size_t interceptor_pos) {
+    rpc_info_ = experimental::ClientRpcInfo(this, type, method, channel);
+    rpc_info_.RegisterInterceptors(creators, interceptor_pos);
+    return &rpc_info_;
+  }
+
+  uint32_t initial_metadata_flags() const {
+    return (idempotent_ ? GRPC_INITIAL_METADATA_IDEMPOTENT_REQUEST : 0) |
+           (wait_for_ready_ ? GRPC_INITIAL_METADATA_WAIT_FOR_READY : 0) |
+           (cacheable_ ? GRPC_INITIAL_METADATA_CACHEABLE_REQUEST : 0) |
+           (wait_for_ready_explicitly_set_
+                ? GRPC_INITIAL_METADATA_WAIT_FOR_READY_EXPLICITLY_SET
+                : 0) |
+           (initial_metadata_corked_ ? GRPC_INITIAL_METADATA_CORKED : 0);
+  }
+
+  grpc::string authority() { return authority_; }
+
+  void SendCancelToInterceptors();
+
+  bool initial_metadata_received_;
+  bool wait_for_ready_;
+  bool wait_for_ready_explicitly_set_;
+  bool idempotent_;
+  bool cacheable_;
+  std::shared_ptr<Channel> channel_;
+  std::mutex mu_;
+  grpc_call* call_;
+  bool call_canceled_;
+  gpr_timespec deadline_;
+  grpc::string authority_;
+  std::shared_ptr<CallCredentials> creds_;
+  mutable std::shared_ptr<const AuthContext> auth_context_;
+  struct census_context* census_context_;
+  std::multimap<grpc::string, grpc::string> send_initial_metadata_;
+  mutable internal::MetadataMap recv_initial_metadata_;
+  mutable internal::MetadataMap trailing_metadata_;
+
+  grpc_call* propagate_from_call_;
+  PropagationOptions propagation_options_;
+
+  grpc_compression_algorithm compression_algorithm_;
+  bool initial_metadata_corked_;
+
+  grpc::string debug_error_string_;
+
+  experimental::ClientRpcInfo rpc_info_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CLIENT_CONTEXT_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/client_interceptor.h b/third_party/grpc/include/grpcpp/impl/codegen/client_interceptor.h
new file mode 100644
index 0000000..7dfe229
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/client_interceptor.h
@@ -0,0 +1,189 @@
+/*
+ *
+ * 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_CLIENT_INTERCEPTOR_H
+#define GRPCPP_IMPL_CODEGEN_CLIENT_INTERCEPTOR_H
+
+#include <memory>
+#include <vector>
+
+#include <grpcpp/impl/codegen/interceptor.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+namespace grpc {
+
+class ClientContext;
+class Channel;
+
+namespace internal {
+class InterceptorBatchMethodsImpl;
+}
+
+namespace experimental {
+class ClientRpcInfo;
+
+// A factory interface for creation of client interceptors. A vector of
+// factories can be provided at channel creation which will be used to create a
+// new vector of client interceptors per RPC. Client interceptor authors should
+// create a subclass of ClientInterceptorFactorInterface which creates objects
+// of their interceptors.
+class ClientInterceptorFactoryInterface {
+ public:
+  virtual ~ClientInterceptorFactoryInterface() {}
+  // Returns a pointer to an Interceptor object on successful creation, nullptr
+  // otherwise. If nullptr is returned, this server interceptor factory is
+  // ignored for the purposes of that RPC.
+  virtual Interceptor* CreateClientInterceptor(ClientRpcInfo* info) = 0;
+};
+}  // namespace experimental
+
+namespace internal {
+extern experimental::ClientInterceptorFactoryInterface*
+    g_global_client_interceptor_factory;
+}
+
+/// ClientRpcInfo represents the state of a particular RPC as it
+/// appears to an interceptor. It is created and owned by the library and
+/// passed to the CreateClientInterceptor method of the application's
+/// ClientInterceptorFactoryInterface implementation
+namespace experimental {
+class ClientRpcInfo {
+ public:
+  // TODO(yashykt): Stop default-constructing ClientRpcInfo and remove UNKNOWN
+  //                from the list of possible Types.
+  /// Type categorizes RPCs by unary or streaming type
+  enum class Type {
+    UNARY,
+    CLIENT_STREAMING,
+    SERVER_STREAMING,
+    BIDI_STREAMING,
+    UNKNOWN  // UNKNOWN is not API and will be removed later
+  };
+
+  ~ClientRpcInfo(){};
+
+  // Delete copy constructor but allow default move constructor
+  ClientRpcInfo(const ClientRpcInfo&) = delete;
+  ClientRpcInfo(ClientRpcInfo&&) = default;
+
+  // Getter methods
+
+  /// Return the fully-specified method name
+  const char* method() const { return method_; }
+
+  /// Return a pointer to the channel on which the RPC is being sent
+  ChannelInterface* channel() { return channel_; }
+
+  /// Return a pointer to the underlying ClientContext structure associated
+  /// with the RPC to support features that apply to it
+  grpc::ClientContext* client_context() { return ctx_; }
+
+  /// Return the type of the RPC (unary or a streaming flavor)
+  Type type() const { return type_; }
+
+ private:
+  static_assert(Type::UNARY ==
+                    static_cast<Type>(internal::RpcMethod::NORMAL_RPC),
+                "violated expectation about Type enum");
+  static_assert(Type::CLIENT_STREAMING ==
+                    static_cast<Type>(internal::RpcMethod::CLIENT_STREAMING),
+                "violated expectation about Type enum");
+  static_assert(Type::SERVER_STREAMING ==
+                    static_cast<Type>(internal::RpcMethod::SERVER_STREAMING),
+                "violated expectation about Type enum");
+  static_assert(Type::BIDI_STREAMING ==
+                    static_cast<Type>(internal::RpcMethod::BIDI_STREAMING),
+                "violated expectation about Type enum");
+
+  // Default constructor should only be used by ClientContext
+  ClientRpcInfo() = default;
+
+  // Constructor will only be called from ClientContext
+  ClientRpcInfo(grpc::ClientContext* ctx, internal::RpcMethod::RpcType type,
+                const char* method, grpc::ChannelInterface* channel)
+      : ctx_(ctx),
+        type_(static_cast<Type>(type)),
+        method_(method),
+        channel_(channel) {}
+
+  // Move assignment should only be used by ClientContext
+  // TODO(yashykt): Delete move assignment
+  ClientRpcInfo& operator=(ClientRpcInfo&&) = default;
+
+  // Runs interceptor at pos \a pos.
+  void RunInterceptor(
+      experimental::InterceptorBatchMethods* interceptor_methods, size_t pos) {
+    GPR_CODEGEN_ASSERT(pos < interceptors_.size());
+    interceptors_[pos]->Intercept(interceptor_methods);
+  }
+
+  void RegisterInterceptors(
+      const std::vector<std::unique_ptr<
+          experimental::ClientInterceptorFactoryInterface>>& creators,
+      size_t interceptor_pos) {
+    if (interceptor_pos > creators.size()) {
+      // No interceptors to register
+      return;
+    }
+    for (auto it = creators.begin() + interceptor_pos; it != creators.end();
+         ++it) {
+      auto* interceptor = (*it)->CreateClientInterceptor(this);
+      if (interceptor != nullptr) {
+        interceptors_.push_back(
+            std::unique_ptr<experimental::Interceptor>(interceptor));
+      }
+    }
+    if (internal::g_global_client_interceptor_factory != nullptr) {
+      interceptors_.push_back(std::unique_ptr<experimental::Interceptor>(
+          internal::g_global_client_interceptor_factory
+              ->CreateClientInterceptor(this)));
+    }
+  }
+
+  grpc::ClientContext* ctx_ = nullptr;
+  // TODO(yashykt): make type_ const once move-assignment is deleted
+  Type type_{Type::UNKNOWN};
+  const char* method_ = nullptr;
+  grpc::ChannelInterface* channel_ = nullptr;
+  std::vector<std::unique_ptr<experimental::Interceptor>> interceptors_;
+  bool hijacked_ = false;
+  size_t hijacked_interceptor_ = 0;
+
+  friend class internal::InterceptorBatchMethodsImpl;
+  friend class grpc::ClientContext;
+};
+
+// PLEASE DO NOT USE THIS. ALWAYS PREFER PER CHANNEL INTERCEPTORS OVER A GLOBAL
+// INTERCEPTOR. IF USAGE IS ABSOLUTELY NECESSARY, PLEASE READ THE SAFETY NOTES.
+// Registers a global client interceptor factory object, which is used for all
+// RPCs made in this process.  If the argument is nullptr, the global
+// interceptor factory is deregistered. The application is responsible for
+// maintaining the life of the object while gRPC operations are in progress. It
+// is unsafe to try to register/deregister if any gRPC operation is in progress.
+// For safety, it is in the best interests of the developer to register the
+// global interceptor factory once at the start of the process before any gRPC
+// operations have begun. Deregistration is optional since gRPC does not
+// maintain any references to the object.
+void RegisterGlobalClientInterceptorFactory(
+    ClientInterceptorFactoryInterface* factory);
+
+}  // namespace experimental
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CLIENT_INTERCEPTOR_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/client_unary_call.h b/third_party/grpc/include/grpcpp/impl/codegen/client_unary_call.h
new file mode 100644
index 0000000..5151839
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/client_unary_call.h
@@ -0,0 +1,94 @@
+/*
+ *
+ * Copyright 2015 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_CLIENT_UNARY_CALL_H
+#define GRPCPP_IMPL_CODEGEN_CLIENT_UNARY_CALL_H
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class Channel;
+class ClientContext;
+class CompletionQueue;
+
+namespace internal {
+class RpcMethod;
+/// Wrapper that performs a blocking unary call
+template <class InputMessage, class OutputMessage>
+Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
+                         ClientContext* context, const InputMessage& request,
+                         OutputMessage* result) {
+  return BlockingUnaryCallImpl<InputMessage, OutputMessage>(
+             channel, method, context, request, result)
+      .status();
+}
+
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl {
+ public:
+  BlockingUnaryCallImpl(ChannelInterface* channel, const RpcMethod& method,
+                        ClientContext* context, const InputMessage& request,
+                        OutputMessage* result) {
+    CompletionQueue cq(grpc_completion_queue_attributes{
+        GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
+        nullptr});  // Pluckable completion queue
+    Call call(channel->CreateCall(method, context, &cq));
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpRecvInitialMetadata, CallOpRecvMessage<OutputMessage>,
+              CallOpClientSendClose, CallOpClientRecvStatus>
+        ops;
+    status_ = ops.SendMessage(request);
+    if (!status_.ok()) {
+      return;
+    }
+    ops.SendInitialMetadata(&context->send_initial_metadata_,
+                            context->initial_metadata_flags());
+    ops.RecvInitialMetadata(context);
+    ops.RecvMessage(result);
+    ops.AllowNoMessage();
+    ops.ClientSendClose();
+    ops.ClientRecvStatus(context, &status_);
+    call.PerformOps(&ops);
+    cq.Pluck(&ops);
+    // Some of the ops might fail. If the ops fail in the core layer, status
+    // would reflect the error. But, if the ops fail in the C++ layer, the
+    // status would still be the same as the one returned by gRPC Core. This can
+    // happen if deserialization of the message fails.
+    // TODO(yashykt): If deserialization fails, but the status received is OK,
+    // then it might be a good idea to change the status to something better
+    // than StatusCode::UNIMPLEMENTED to reflect this.
+    if (!ops.got_message && status_.ok()) {
+      status_ = Status(StatusCode::UNIMPLEMENTED,
+                       "No message returned for unary request");
+    }
+  }
+  Status status() { return status_; }
+
+ private:
+  Status status_;
+};
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CLIENT_UNARY_CALL_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/completion_queue.h b/third_party/grpc/include/grpcpp/impl/codegen/completion_queue.h
new file mode 100644
index 0000000..fb38788
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/completion_queue.h
@@ -0,0 +1,403 @@
+/*
+ *
+ * Copyright 2015-2016 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.
+ *
+ */
+
+/// A completion queue implements a concurrent producer-consumer queue, with
+/// two main API-exposed methods: \a Next and \a AsyncNext. These
+/// methods are the essential component of the gRPC C++ asynchronous API.
+/// There is also a \a Shutdown method to indicate that a given completion queue
+/// will no longer have regular events. This must be called before the
+/// completion queue is destroyed.
+/// All completion queue APIs are thread-safe and may be used concurrently with
+/// any other completion queue API invocation; it is acceptable to have
+/// multiple threads calling \a Next or \a AsyncNext on the same or different
+/// completion queues, or to call these methods concurrently with a \a Shutdown
+/// elsewhere.
+/// \remark{All other API calls on completion queue should be completed before
+/// a completion queue destructor is called.}
+#ifndef GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
+#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
+
+#include <grpc/impl/codegen/atm.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+#include <grpcpp/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct grpc_completion_queue;
+
+namespace grpc {
+
+template <class R>
+class ClientReader;
+template <class W>
+class ClientWriter;
+template <class W, class R>
+class ClientReaderWriter;
+template <class R>
+class ServerReader;
+template <class W>
+class ServerWriter;
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody;
+}  // namespace internal
+
+class Channel;
+class ChannelInterface;
+class ClientContext;
+class CompletionQueue;
+class Server;
+class ServerBuilder;
+class ServerContext;
+class ServerInterface;
+
+namespace internal {
+class CompletionQueueTag;
+class RpcMethod;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class BidiStreamingHandler;
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler;
+template <StatusCode code>
+class ErrorMethodHandler;
+template <class InputMessage, class OutputMessage>
+class BlockingUnaryCallImpl;
+}  // namespace internal
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// A thin wrapper around \ref grpc_completion_queue (see \ref
+/// src/core/lib/surface/completion_queue.h).
+/// See \ref doc/cpp/perf_notes.md for notes on best practices for high
+/// performance servers.
+class CompletionQueue : private GrpcLibraryCodegen {
+ public:
+  /// Default constructor. Implicitly creates a \a grpc_completion_queue
+  /// instance.
+  CompletionQueue()
+      : CompletionQueue(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_NEXT, GRPC_CQ_DEFAULT_POLLING,
+            nullptr}) {}
+
+  /// Wrap \a take, taking ownership of the instance.
+  ///
+  /// \param take The completion queue instance to wrap. Ownership is taken.
+  explicit CompletionQueue(grpc_completion_queue* take);
+
+  /// Destructor. Destroys the owned wrapped completion queue / instance.
+  ~CompletionQueue() {
+    g_core_codegen_interface->grpc_completion_queue_destroy(cq_);
+  }
+
+  /// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
+  enum NextStatus {
+    SHUTDOWN,   ///< The completion queue has been shutdown and fully-drained
+    GOT_EVENT,  ///< Got a new event; \a tag will be filled in with its
+                ///< associated value; \a ok indicating its success.
+    TIMEOUT     ///< deadline was reached.
+  };
+
+  /// Read from the queue, blocking until an event is available or the queue is
+  /// shutting down.
+  ///
+  /// \param tag [out] Updated to point to the read event's tag.
+  /// \param ok [out] true if read a successful event, false otherwise.
+  ///
+  /// Note that each tag sent to the completion queue (through RPC operations
+  /// or alarms) will be delivered out of the completion queue by a call to
+  /// Next (or a related method), regardless of whether the operation succeeded
+  /// or not. Success here means that this operation completed in the normal
+  /// valid manner.
+  ///
+  /// Server-side RPC request: \a ok indicates that the RPC has indeed
+  /// been started. If it is false, the server has been Shutdown
+  /// before this particular call got matched to an incoming RPC.
+  ///
+  /// Client-side StartCall/RPC invocation: \a ok indicates that the RPC is
+  /// going to go to the wire. If it is false, it not going to the wire. This
+  /// would happen if the channel is either permanently broken or
+  /// transiently broken but with the fail-fast option. (Note that async unary
+  /// RPCs don't post a CQ tag at this point, nor do client-streaming
+  /// or bidi-streaming RPCs that have the initial metadata corked option set.)
+  ///
+  /// Client-side Write, Client-side WritesDone, Server-side Write,
+  /// Server-side Finish, Server-side SendInitialMetadata (which is
+  /// typically included in Write or Finish when not done explicitly):
+  /// \a ok means that the data/metadata/status/etc is going to go to the
+  /// wire. If it is false, it not going to the wire because the call
+  /// is already dead (i.e., canceled, deadline expired, other side
+  /// dropped the channel, etc).
+  ///
+  /// Client-side Read, Server-side Read, Client-side
+  /// RecvInitialMetadata (which is typically included in Read if not
+  /// done explicitly): \a ok indicates whether there is a valid message
+  /// that got read. If not, you know that there are certainly no more
+  /// messages that can ever be read from this stream. For the client-side
+  /// operations, this only happens because the call is dead. For the
+  /// server-sider operation, though, this could happen because the client
+  /// has done a WritesDone already.
+  ///
+  /// Client-side Finish: \a ok should always be true
+  ///
+  /// Server-side AsyncNotifyWhenDone: \a ok should always be true
+  ///
+  /// Alarm: \a ok is true if it expired, false if it was canceled
+  ///
+  /// \return true if got an event, false if the queue is fully drained and
+  ///         shut down.
+  bool Next(void** tag, bool* ok) {
+    return (AsyncNextInternal(tag, ok,
+                              g_core_codegen_interface->gpr_inf_future(
+                                  GPR_CLOCK_REALTIME)) != SHUTDOWN);
+  }
+
+  /// Read from the queue, blocking up to \a deadline (or the queue's shutdown).
+  /// Both \a tag and \a ok are updated upon success (if an event is available
+  /// within the \a deadline).  A \a tag points to an arbitrary location usually
+  /// employed to uniquely identify an event.
+  ///
+  /// \param tag [out] Upon sucess, updated to point to the event's tag.
+  /// \param ok [out] Upon sucess, true if a successful event, false otherwise
+  ///        See documentation for CompletionQueue::Next for explanation of ok
+  /// \param deadline [in] How long to block in wait for an event.
+  ///
+  /// \return The type of event read.
+  template <typename T>
+  NextStatus AsyncNext(void** tag, bool* ok, const T& deadline) {
+    TimePoint<T> deadline_tp(deadline);
+    return AsyncNextInternal(tag, ok, deadline_tp.raw_time());
+  }
+
+  /// EXPERIMENTAL
+  /// First executes \a F, then reads from the queue, blocking up to
+  /// \a deadline (or the queue's shutdown).
+  /// Both \a tag and \a ok are updated upon success (if an event is available
+  /// within the \a deadline).  A \a tag points to an arbitrary location usually
+  /// employed to uniquely identify an event.
+  ///
+  /// \param f [in] Function to execute before calling AsyncNext on this queue.
+  /// \param tag [out] Upon sucess, updated to point to the event's tag.
+  /// \param ok [out] Upon sucess, true if read a regular event, false
+  /// otherwise.
+  /// \param deadline [in] How long to block in wait for an event.
+  ///
+  /// \return The type of event read.
+  template <typename T, typename F>
+  NextStatus DoThenAsyncNext(F&& f, void** tag, bool* ok, const T& deadline) {
+    CompletionQueueTLSCache cache = CompletionQueueTLSCache(this);
+    f();
+    if (cache.Flush(tag, ok)) {
+      return GOT_EVENT;
+    } else {
+      return AsyncNext(tag, ok, deadline);
+    }
+  }
+
+  /// Request the shutdown of the queue.
+  ///
+  /// \warning This method must be called at some point if this completion queue
+  /// is accessed with Next or AsyncNext. \a Next will not return false
+  /// until this method has been called and all pending tags have been drained.
+  /// (Likewise for \a AsyncNext returning \a NextStatus::SHUTDOWN .)
+  /// Only once either one of these methods does that (that is, once the queue
+  /// has been \em drained) can an instance of this class be destroyed.
+  /// Also note that applications must ensure that no work is enqueued on this
+  /// completion queue after this method is called.
+  void Shutdown();
+
+  /// Returns a \em raw pointer to the underlying \a grpc_completion_queue
+  /// instance.
+  ///
+  /// \warning Remember that the returned instance is owned. No transfer of
+  /// owership is performed.
+  grpc_completion_queue* cq() { return cq_; }
+
+ protected:
+  /// Private constructor of CompletionQueue only visible to friend classes
+  CompletionQueue(const grpc_completion_queue_attributes& attributes) {
+    cq_ = g_core_codegen_interface->grpc_completion_queue_create(
+        g_core_codegen_interface->grpc_completion_queue_factory_lookup(
+            &attributes),
+        &attributes, NULL);
+    InitialAvalanching();  // reserve this for the future shutdown
+  }
+
+ private:
+  // Friend synchronous wrappers so that they can access Pluck(), which is
+  // a semi-private API geared towards the synchronous implementation.
+  template <class R>
+  friend class ::grpc::ClientReader;
+  template <class W>
+  friend class ::grpc::ClientWriter;
+  template <class W, class R>
+  friend class ::grpc::ClientReaderWriter;
+  template <class R>
+  friend class ::grpc::ServerReader;
+  template <class W>
+  friend class ::grpc::ServerWriter;
+  template <class W, class R>
+  friend class ::grpc::internal::ServerReaderWriterBody;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc::internal::RpcMethodHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc::internal::ClientStreamingHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc::internal::ServerStreamingHandler;
+  template <class Streamer, bool WriteNeeded>
+  friend class ::grpc::internal::TemplatedBidiStreamingHandler;
+  template <StatusCode code>
+  friend class ::grpc::internal::ErrorMethodHandler;
+  friend class ::grpc::Server;
+  friend class ::grpc::ServerContext;
+  friend class ::grpc::ServerInterface;
+  template <class InputMessage, class OutputMessage>
+  friend class ::grpc::internal::BlockingUnaryCallImpl;
+
+  // Friends that need access to constructor for callback CQ
+  friend class ::grpc::Channel;
+
+  /// EXPERIMENTAL
+  /// Creates a Thread Local cache to store the first event
+  /// On this completion queue queued from this thread.  Once
+  /// initialized, it must be flushed on the same thread.
+  class CompletionQueueTLSCache {
+   public:
+    CompletionQueueTLSCache(CompletionQueue* cq);
+    ~CompletionQueueTLSCache();
+    bool Flush(void** tag, bool* ok);
+
+   private:
+    CompletionQueue* cq_;
+    bool flushed_;
+  };
+
+  NextStatus AsyncNextInternal(void** tag, bool* ok, gpr_timespec deadline);
+
+  /// Wraps \a grpc_completion_queue_pluck.
+  /// \warning Must not be mixed with calls to \a Next.
+  bool Pluck(internal::CompletionQueueTag* tag) {
+    auto deadline =
+        g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
+    while (true) {
+      auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
+          cq_, tag, deadline, nullptr);
+      bool ok = ev.success != 0;
+      void* ignored = tag;
+      if (tag->FinalizeResult(&ignored, &ok)) {
+        GPR_CODEGEN_ASSERT(ignored == tag);
+        return ok;
+      }
+    }
+  }
+
+  /// Performs a single polling pluck on \a tag.
+  /// \warning Must not be mixed with calls to \a Next.
+  ///
+  /// TODO: sreek - This calls tag->FinalizeResult() even if the cq_ is already
+  /// shutdown. This is most likely a bug and if it is a bug, then change this
+  /// implementation to simple call the other TryPluck function with a zero
+  /// timeout. i.e:
+  ///      TryPluck(tag, gpr_time_0(GPR_CLOCK_REALTIME))
+  void TryPluck(internal::CompletionQueueTag* tag) {
+    auto deadline = g_core_codegen_interface->gpr_time_0(GPR_CLOCK_REALTIME);
+    auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
+        cq_, tag, deadline, nullptr);
+    if (ev.type == GRPC_QUEUE_TIMEOUT) return;
+    bool ok = ev.success != 0;
+    void* ignored = tag;
+    // the tag must be swallowed if using TryPluck
+    GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
+  }
+
+  /// Performs a single polling pluck on \a tag. Calls tag->FinalizeResult if
+  /// the pluck() was successful and returned the tag.
+  ///
+  /// This exects tag->FinalizeResult (if called) to return 'false' i.e expects
+  /// that the tag is internal not something that is returned to the user.
+  void TryPluck(internal::CompletionQueueTag* tag, gpr_timespec deadline) {
+    auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
+        cq_, tag, deadline, nullptr);
+    if (ev.type == GRPC_QUEUE_TIMEOUT || ev.type == GRPC_QUEUE_SHUTDOWN) {
+      return;
+    }
+
+    bool ok = ev.success != 0;
+    void* ignored = tag;
+    GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
+  }
+
+  /// Manage state of avalanching operations : completion queue tags that
+  /// trigger other completion queue operations. The underlying core completion
+  /// queue should not really shutdown until all avalanching operations have
+  /// been finalized. Note that we maintain the requirement that an avalanche
+  /// registration must take place before CQ shutdown (which must be maintained
+  /// elsehwere)
+  void InitialAvalanching() {
+    gpr_atm_rel_store(&avalanches_in_flight_, static_cast<gpr_atm>(1));
+  }
+  void RegisterAvalanching() {
+    gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
+                                 static_cast<gpr_atm>(1));
+  }
+  void CompleteAvalanching();
+
+  grpc_completion_queue* cq_;  // owned
+
+  gpr_atm avalanches_in_flight_;
+};
+
+/// A specific type of completion queue used by the processing of notifications
+/// by servers. Instantiated by \a ServerBuilder.
+class ServerCompletionQueue : public CompletionQueue {
+ public:
+  bool IsFrequentlyPolled() { return polling_type_ != GRPC_CQ_NON_LISTENING; }
+
+ protected:
+  /// Default constructor
+  ServerCompletionQueue() : polling_type_(GRPC_CQ_DEFAULT_POLLING) {}
+
+ private:
+  /// \param completion_type indicates whether this is a NEXT or CALLBACK
+  /// completion queue.
+  /// \param polling_type Informs the GRPC library about the type of polling
+  /// allowed on this completion queue. See grpc_cq_polling_type's description
+  /// in grpc_types.h for more details.
+  /// \param shutdown_cb is the shutdown callback used for CALLBACK api queues
+  ServerCompletionQueue(grpc_cq_completion_type completion_type,
+                        grpc_cq_polling_type polling_type,
+                        grpc_experimental_completion_queue_functor* shutdown_cb)
+      : CompletionQueue(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, completion_type, polling_type,
+            shutdown_cb}),
+        polling_type_(polling_type) {}
+
+  grpc_cq_polling_type polling_type_;
+  friend class ServerBuilder;
+  friend class Server;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/completion_queue_tag.h b/third_party/grpc/include/grpcpp/impl/codegen/completion_queue_tag.h
new file mode 100644
index 0000000..304386a
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/completion_queue_tag.h
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright 2015 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_COMPLETION_QUEUE_TAG_H
+#define GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H
+
+namespace grpc {
+
+namespace internal {
+/// An interface allowing implementors to process and filter event tags.
+class CompletionQueueTag {
+ public:
+  virtual ~CompletionQueueTag() {}
+
+  /// FinalizeResult must be called before informing user code that the
+  /// operation bound to the underlying core completion queue tag has
+  /// completed. In practice, this means:
+  ///
+  ///   1. For the sync API - before returning from Pluck
+  ///   2. For the CQ-based async API - before returning from Next
+  ///   3. For the callback-based API - before invoking the user callback
+  ///
+  /// This is the method that translates from core-side tag/status to
+  /// C++ API-observable tag/status.
+  ///
+  /// The return value is the status of the operation (returning status is the
+  /// general behavior of this function). If this function returns false, the
+  /// tag is dropped and not returned from the completion queue: this concept is
+  /// for events that are observed at core but not requested by the user
+  /// application (e.g., server shutdown, for server unimplemented method
+  /// responses, or for cases where a server-side RPC doesn't have a completion
+  /// notification registered using AsyncNotifyWhenDone)
+  virtual bool FinalizeResult(void** tag, bool* status) = 0;
+};
+}  // namespace internal
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_COMPLETION_QUEUE_TAG_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/config.h b/third_party/grpc/include/grpcpp/impl/codegen/config.h
new file mode 100644
index 0000000..37f0fd1f
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/config.h
@@ -0,0 +1,41 @@
+/*
+ *
+ * Copyright 2016 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_CONFIG_H
+#define GRPCPP_IMPL_CODEGEN_CONFIG_H
+
+#ifndef GRPC_CUSTOM_STRING
+#include <string>
+#define GRPC_CUSTOM_STRING std::string
+#endif
+
+/// The following macros are deprecated and appear only for users
+/// with PB files generated using gRPC 1.0.x plugins. They should
+/// not be used in new code
+#define GRPC_OVERRIDE override  // deprecated
+#define GRPC_FINAL final        // deprecated
+
+namespace grpc {
+
+typedef GRPC_CUSTOM_STRING string;
+
+using std::to_string;
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CONFIG_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/config_protobuf.h b/third_party/grpc/include/grpcpp/impl/codegen/config_protobuf.h
new file mode 100644
index 0000000..8c2e9e6
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/config_protobuf.h
@@ -0,0 +1,107 @@
+/*
+ *
+ * Copyright 2015 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_CONFIG_PROTOBUF_H
+#define GRPCPP_IMPL_CODEGEN_CONFIG_PROTOBUF_H
+
+#define GRPC_OPEN_SOURCE_PROTO
+
+#ifndef GRPC_CUSTOM_PROTOBUF_INT64
+#include <google/protobuf/stubs/common.h>
+#define GRPC_CUSTOM_PROTOBUF_INT64 ::google::protobuf::int64
+#endif
+
+#ifndef GRPC_CUSTOM_MESSAGE
+#ifdef GRPC_USE_PROTO_LITE
+#include <google/protobuf/message_lite.h>
+#define GRPC_CUSTOM_MESSAGE ::google::protobuf::MessageLite
+#else
+#include <google/protobuf/message.h>
+#define GRPC_CUSTOM_MESSAGE ::google::protobuf::Message
+#endif
+#endif
+
+#ifndef GRPC_CUSTOM_DESCRIPTOR
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+#define GRPC_CUSTOM_DESCRIPTOR ::google::protobuf::Descriptor
+#define GRPC_CUSTOM_DESCRIPTORPOOL ::google::protobuf::DescriptorPool
+#define GRPC_CUSTOM_FIELDDESCRIPTOR ::google::protobuf::FieldDescriptor
+#define GRPC_CUSTOM_FILEDESCRIPTOR ::google::protobuf::FileDescriptor
+#define GRPC_CUSTOM_FILEDESCRIPTORPROTO ::google::protobuf::FileDescriptorProto
+#define GRPC_CUSTOM_METHODDESCRIPTOR ::google::protobuf::MethodDescriptor
+#define GRPC_CUSTOM_SERVICEDESCRIPTOR ::google::protobuf::ServiceDescriptor
+#define GRPC_CUSTOM_SOURCELOCATION ::google::protobuf::SourceLocation
+#endif
+
+#ifndef GRPC_CUSTOM_DESCRIPTORDATABASE
+#include <google/protobuf/descriptor_database.h>
+#define GRPC_CUSTOM_DESCRIPTORDATABASE ::google::protobuf::DescriptorDatabase
+#define GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE \
+  ::google::protobuf::SimpleDescriptorDatabase
+#endif
+
+#ifndef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#define GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM \
+  ::google::protobuf::io::ZeroCopyOutputStream
+#define GRPC_CUSTOM_ZEROCOPYINPUTSTREAM \
+  ::google::protobuf::io::ZeroCopyInputStream
+#define GRPC_CUSTOM_CODEDINPUTSTREAM ::google::protobuf::io::CodedInputStream
+#endif
+
+#ifndef GRPC_CUSTOM_JSONUTIL
+#include <google/protobuf/util/json_util.h>
+#define GRPC_CUSTOM_JSONUTIL ::google::protobuf::util
+#define GRPC_CUSTOM_UTIL_STATUS ::google::protobuf::util::Status
+#endif
+
+namespace grpc {
+namespace protobuf {
+
+typedef GRPC_CUSTOM_MESSAGE Message;
+typedef GRPC_CUSTOM_PROTOBUF_INT64 int64;
+
+typedef GRPC_CUSTOM_DESCRIPTOR Descriptor;
+typedef GRPC_CUSTOM_DESCRIPTORPOOL DescriptorPool;
+typedef GRPC_CUSTOM_DESCRIPTORDATABASE DescriptorDatabase;
+typedef GRPC_CUSTOM_FIELDDESCRIPTOR FieldDescriptor;
+typedef GRPC_CUSTOM_FILEDESCRIPTOR FileDescriptor;
+typedef GRPC_CUSTOM_FILEDESCRIPTORPROTO FileDescriptorProto;
+typedef GRPC_CUSTOM_METHODDESCRIPTOR MethodDescriptor;
+typedef GRPC_CUSTOM_SERVICEDESCRIPTOR ServiceDescriptor;
+typedef GRPC_CUSTOM_SIMPLEDESCRIPTORDATABASE SimpleDescriptorDatabase;
+typedef GRPC_CUSTOM_SOURCELOCATION SourceLocation;
+
+namespace util {
+typedef GRPC_CUSTOM_UTIL_STATUS Status;
+}  // namespace util
+
+namespace json = GRPC_CUSTOM_JSONUTIL;
+
+namespace io {
+typedef GRPC_CUSTOM_ZEROCOPYOUTPUTSTREAM ZeroCopyOutputStream;
+typedef GRPC_CUSTOM_ZEROCOPYINPUTSTREAM ZeroCopyInputStream;
+typedef GRPC_CUSTOM_CODEDINPUTSTREAM CodedInputStream;
+}  // namespace io
+
+}  // namespace protobuf
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CONFIG_PROTOBUF_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/core_codegen.h b/third_party/grpc/include/grpcpp/impl/codegen/core_codegen.h
new file mode 100644
index 0000000..6ef184d
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/core_codegen.h
@@ -0,0 +1,123 @@
+/*
+ *
+ * Copyright 2016 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_CORE_CODEGEN_H
+#define GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_H
+
+// This file should be compiled as part of grpcpp.
+
+#include <grpc/byte_buffer.h>
+#include <grpc/grpc.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+
+namespace grpc {
+
+/// Implementation of the core codegen interface.
+class CoreCodegen final : public CoreCodegenInterface {
+ private:
+  virtual const grpc_completion_queue_factory*
+  grpc_completion_queue_factory_lookup(
+      const grpc_completion_queue_attributes* attributes) override;
+  virtual grpc_completion_queue* grpc_completion_queue_create(
+      const grpc_completion_queue_factory* factory,
+      const grpc_completion_queue_attributes* attributes,
+      void* reserved) override;
+  grpc_completion_queue* grpc_completion_queue_create_for_next(
+      void* reserved) override;
+  grpc_completion_queue* grpc_completion_queue_create_for_pluck(
+      void* reserved) override;
+  void grpc_completion_queue_destroy(grpc_completion_queue* cq) override;
+  grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag,
+                                         gpr_timespec deadline,
+                                         void* reserved) override;
+
+  void* gpr_malloc(size_t size) override;
+  void gpr_free(void* p) override;
+
+  void grpc_init() override;
+  void grpc_shutdown() override;
+
+  void gpr_mu_init(gpr_mu* mu) override;
+  void gpr_mu_destroy(gpr_mu* mu) override;
+  void gpr_mu_lock(gpr_mu* mu) override;
+  void gpr_mu_unlock(gpr_mu* mu) override;
+  void gpr_cv_init(gpr_cv* cv) override;
+  void gpr_cv_destroy(gpr_cv* cv) override;
+  int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu, gpr_timespec abs_deadline) override;
+  void gpr_cv_signal(gpr_cv* cv) override;
+  void gpr_cv_broadcast(gpr_cv* cv) override;
+
+  grpc_call_error grpc_call_start_batch(grpc_call* call, const grpc_op* ops,
+                                        size_t nops, void* tag,
+                                        void* reserved) override;
+  grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
+                                               grpc_status_code status,
+                                               const char* description,
+                                               void* reserved) override;
+  void grpc_call_ref(grpc_call* call) override;
+  void grpc_call_unref(grpc_call* call) override;
+  virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) override;
+
+  grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) override;
+  void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;
+  size_t grpc_byte_buffer_length(grpc_byte_buffer* bb) override;
+
+  int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
+                                   grpc_byte_buffer* buffer) override;
+  void grpc_byte_buffer_reader_destroy(
+      grpc_byte_buffer_reader* reader) override;
+  int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader,
+                                   grpc_slice* slice) override;
+
+  grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice,
+                                                size_t nslices) override;
+  grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
+                                           void (*destroy)(void*),
+                                           void* user_data) override;
+  grpc_slice grpc_slice_new_with_len(void* p, size_t len,
+                                     void (*destroy)(void*, size_t)) override;
+  grpc_slice grpc_empty_slice() override;
+  grpc_slice grpc_slice_malloc(size_t length) override;
+  void grpc_slice_unref(grpc_slice slice) override;
+  grpc_slice grpc_slice_ref(grpc_slice slice) override;
+  grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) override;
+  grpc_slice grpc_slice_split_head(grpc_slice* s, size_t split) override;
+  grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end) override;
+  void grpc_slice_buffer_add(grpc_slice_buffer* sb, grpc_slice slice) override;
+  void grpc_slice_buffer_pop(grpc_slice_buffer* sb) override;
+  grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+                                           size_t length) override;
+  grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+                                           size_t length) override;
+  void grpc_metadata_array_init(grpc_metadata_array* array) override;
+  void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
+
+  gpr_timespec gpr_inf_future(gpr_clock_type type) override;
+  gpr_timespec gpr_time_0(gpr_clock_type type) override;
+
+  virtual const Status& ok() override;
+  virtual const Status& cancelled() override;
+
+  void assert_fail(const char* failed_assertion, const char* file,
+                   int line) override;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/core_codegen_interface.h b/third_party/grpc/include/grpcpp/impl/codegen/core_codegen_interface.h
new file mode 100644
index 0000000..20a5b33
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/core_codegen_interface.h
@@ -0,0 +1,159 @@
+/*
+ *
+ * Copyright 2015 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_CORE_CODEGEN_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
+
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/sync.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+/// Interface between the codegen library and the minimal subset of core
+/// features required by the generated code.
+///
+/// All undocumented methods are simply forwarding the call to their namesakes.
+/// Please refer to their corresponding documentation for details.
+///
+/// \warning This interface should be considered internal and private.
+class CoreCodegenInterface {
+ public:
+  virtual ~CoreCodegenInterface() = default;
+
+  /// Upon a failed assertion, log the error.
+  virtual void assert_fail(const char* failed_assertion, const char* file,
+                           int line) = 0;
+
+  virtual const grpc_completion_queue_factory*
+  grpc_completion_queue_factory_lookup(
+      const grpc_completion_queue_attributes* attributes) = 0;
+  virtual grpc_completion_queue* grpc_completion_queue_create(
+      const grpc_completion_queue_factory* factory,
+      const grpc_completion_queue_attributes* attributes, void* reserved) = 0;
+  virtual grpc_completion_queue* grpc_completion_queue_create_for_next(
+      void* reserved) = 0;
+  virtual grpc_completion_queue* grpc_completion_queue_create_for_pluck(
+      void* reserved) = 0;
+  virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0;
+  virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq,
+                                                 void* tag,
+                                                 gpr_timespec deadline,
+                                                 void* reserved) = 0;
+
+  virtual void* gpr_malloc(size_t size) = 0;
+  virtual void gpr_free(void* p) = 0;
+
+  // These are only to be used to fix edge cases involving grpc_init and
+  // grpc_shutdown. Calling grpc_init from the codegen interface before
+  // the real grpc_init is called will cause a crash, so if you use this
+  // function, ensure that it is not the first call to grpc_init.
+  virtual void grpc_init() = 0;
+  virtual void grpc_shutdown() = 0;
+
+  virtual void gpr_mu_init(gpr_mu* mu) = 0;
+  virtual void gpr_mu_destroy(gpr_mu* mu) = 0;
+  virtual void gpr_mu_lock(gpr_mu* mu) = 0;
+  virtual void gpr_mu_unlock(gpr_mu* mu) = 0;
+  virtual void gpr_cv_init(gpr_cv* cv) = 0;
+  virtual void gpr_cv_destroy(gpr_cv* cv) = 0;
+  virtual int gpr_cv_wait(gpr_cv* cv, gpr_mu* mu,
+                          gpr_timespec abs_deadline) = 0;
+  virtual void gpr_cv_signal(gpr_cv* cv) = 0;
+  virtual void gpr_cv_broadcast(gpr_cv* cv) = 0;
+
+  virtual grpc_byte_buffer* grpc_byte_buffer_copy(grpc_byte_buffer* bb) = 0;
+  virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0;
+  virtual size_t grpc_byte_buffer_length(grpc_byte_buffer* bb)
+      GRPC_MUST_USE_RESULT = 0;
+
+  virtual int grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
+                                           grpc_byte_buffer* buffer)
+      GRPC_MUST_USE_RESULT = 0;
+  virtual void grpc_byte_buffer_reader_destroy(
+      grpc_byte_buffer_reader* reader) = 0;
+  virtual int grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader,
+                                           grpc_slice* slice) = 0;
+
+  virtual grpc_byte_buffer* grpc_raw_byte_buffer_create(grpc_slice* slice,
+                                                        size_t nslices) = 0;
+  virtual grpc_slice grpc_slice_new_with_user_data(void* p, size_t len,
+                                                   void (*destroy)(void*),
+                                                   void* user_data) = 0;
+  virtual grpc_slice grpc_slice_new_with_len(void* p, size_t len,
+                                             void (*destroy)(void*,
+                                                             size_t)) = 0;
+  virtual grpc_call_error grpc_call_start_batch(grpc_call* call,
+                                                const grpc_op* ops, size_t nops,
+                                                void* tag, void* reserved) = 0;
+  virtual grpc_call_error grpc_call_cancel_with_status(grpc_call* call,
+                                                       grpc_status_code status,
+                                                       const char* description,
+                                                       void* reserved) = 0;
+  virtual void grpc_call_ref(grpc_call* call) = 0;
+  virtual void grpc_call_unref(grpc_call* call) = 0;
+  virtual void* grpc_call_arena_alloc(grpc_call* call, size_t length) = 0;
+  virtual grpc_slice grpc_empty_slice() = 0;
+  virtual grpc_slice grpc_slice_malloc(size_t length) = 0;
+  virtual void grpc_slice_unref(grpc_slice slice) = 0;
+  virtual grpc_slice grpc_slice_ref(grpc_slice slice) = 0;
+  virtual grpc_slice grpc_slice_split_tail(grpc_slice* s, size_t split) = 0;
+  virtual grpc_slice grpc_slice_split_head(grpc_slice* s, size_t split) = 0;
+  virtual grpc_slice grpc_slice_sub(grpc_slice s, size_t begin, size_t end) = 0;
+  virtual void grpc_slice_buffer_add(grpc_slice_buffer* sb,
+                                     grpc_slice slice) = 0;
+  virtual void grpc_slice_buffer_pop(grpc_slice_buffer* sb) = 0;
+  virtual grpc_slice grpc_slice_from_static_buffer(const void* buffer,
+                                                   size_t length) = 0;
+  virtual grpc_slice grpc_slice_from_copied_buffer(const void* buffer,
+                                                   size_t length) = 0;
+
+  virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
+  virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
+
+  virtual const Status& ok() = 0;
+  virtual const Status& cancelled() = 0;
+
+  virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0;
+  virtual gpr_timespec gpr_time_0(gpr_clock_type type) = 0;
+};
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// Codegen specific version of \a GPR_ASSERT.
+#define GPR_CODEGEN_ASSERT(x)                                              \
+  do {                                                                     \
+    if (!(x)) {                                                            \
+      grpc::g_core_codegen_interface->assert_fail(#x, __FILE__, __LINE__); \
+    }                                                                      \
+  } while (0)
+
+/// Codegen specific version of \a GPR_DEBUG_ASSERT.
+#ifndef NDEBUG
+#define GPR_CODEGEN_DEBUG_ASSERT(x) GPR_CODEGEN_ASSERT(x)
+#else
+#define GPR_CODEGEN_DEBUG_ASSERT(x) \
+  do {                              \
+  } while (0)
+#endif
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/create_auth_context.h b/third_party/grpc/include/grpcpp/impl/codegen/create_auth_context.h
new file mode 100644
index 0000000..cb6095c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/create_auth_context.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * Copyright 2015 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_CREATE_AUTH_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
+
+#include <memory>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+
+namespace grpc {
+
+std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_CREATE_AUTH_CONTEXT_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/grpc_library.h b/third_party/grpc/include/grpcpp/impl/codegen/grpc_library.h
new file mode 100644
index 0000000..17c904d
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/grpc_library.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * Copyright 2016 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_GRPC_LIBRARY_H
+#define GRPCPP_IMPL_CODEGEN_GRPC_LIBRARY_H
+
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+
+namespace grpc {
+
+class GrpcLibraryInterface {
+ public:
+  virtual ~GrpcLibraryInterface() = default;
+  virtual void init() = 0;
+  virtual void shutdown() = 0;
+};
+
+/// Initialized by \a grpc::GrpcLibraryInitializer from
+/// <grpcpp/impl/grpc_library.h>
+extern GrpcLibraryInterface* g_glip;
+
+/// Classes that require gRPC to be initialized should inherit from this class.
+class GrpcLibraryCodegen {
+ public:
+  GrpcLibraryCodegen(bool call_grpc_init = true) : grpc_init_called_(false) {
+    if (call_grpc_init) {
+      GPR_CODEGEN_ASSERT(g_glip &&
+                         "gRPC library not initialized. See "
+                         "grpc::internal::GrpcLibraryInitializer.");
+      g_glip->init();
+      grpc_init_called_ = true;
+    }
+  }
+  virtual ~GrpcLibraryCodegen() {
+    if (grpc_init_called_) {
+      GPR_CODEGEN_ASSERT(g_glip &&
+                         "gRPC library not initialized. See "
+                         "grpc::internal::GrpcLibraryInitializer.");
+      g_glip->shutdown();
+    }
+  }
+
+ private:
+  bool grpc_init_called_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_GRPC_LIBRARY_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/intercepted_channel.h b/third_party/grpc/include/grpcpp/impl/codegen/intercepted_channel.h
new file mode 100644
index 0000000..5255a6d
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/intercepted_channel.h
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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_INTERCEPTED_CHANNEL_H
+#define GRPCPP_IMPL_CODEGEN_INTERCEPTED_CHANNEL_H
+
+#include <grpcpp/impl/codegen/channel_interface.h>
+
+namespace grpc {
+
+namespace internal {
+
+class InterceptorBatchMethodsImpl;
+
+/// An InterceptedChannel is available to client Interceptors. An
+/// InterceptedChannel is unique to an interceptor, and when an RPC is started
+/// on this channel, only those interceptors that come after this interceptor
+/// see the RPC.
+class InterceptedChannel : public ChannelInterface {
+ public:
+  virtual ~InterceptedChannel() { channel_ = nullptr; }
+
+  /// Get the current channel state. If the channel is in IDLE and
+  /// \a try_to_connect is set to true, try to connect.
+  grpc_connectivity_state GetState(bool try_to_connect) override {
+    return channel_->GetState(try_to_connect);
+  }
+
+ private:
+  InterceptedChannel(ChannelInterface* channel, size_t pos)
+      : channel_(channel), interceptor_pos_(pos) {}
+
+  Call CreateCall(const RpcMethod& method, ClientContext* context,
+                  CompletionQueue* cq) override {
+    return channel_->CreateCallInternal(method, context, cq, interceptor_pos_);
+  }
+
+  void PerformOpsOnCall(CallOpSetInterface* ops, Call* call) override {
+    return channel_->PerformOpsOnCall(ops, call);
+  }
+  void* RegisterMethod(const char* method) override {
+    return channel_->RegisterMethod(method);
+  }
+
+  void NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
+                               gpr_timespec deadline, CompletionQueue* cq,
+                               void* tag) override {
+    return channel_->NotifyOnStateChangeImpl(last_observed, deadline, cq, tag);
+  }
+  bool WaitForStateChangeImpl(grpc_connectivity_state last_observed,
+                              gpr_timespec deadline) override {
+    return channel_->WaitForStateChangeImpl(last_observed, deadline);
+  }
+
+  CompletionQueue* CallbackCQ() override { return channel_->CallbackCQ(); }
+
+  ChannelInterface* channel_;
+  size_t interceptor_pos_;
+
+  friend class InterceptorBatchMethodsImpl;
+};
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_INTERCEPTED_CHANNEL_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/interceptor.h b/third_party/grpc/include/grpcpp/impl/codegen/interceptor.h
new file mode 100644
index 0000000..46175cd
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/interceptor.h
@@ -0,0 +1,175 @@
+/*
+ *
+ * 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 two in this list are for clients and servers
+  PRE_SEND_INITIAL_METADATA,
+  PRE_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* GetSendMessage() = 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;
+};
+
+/// 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
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/interceptor_common.h b/third_party/grpc/include/grpcpp/impl/codegen/interceptor_common.h
new file mode 100644
index 0000000..d0aa23c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/interceptor_common.h
@@ -0,0 +1,458 @@
+/*
+ *
+ * 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_COMMON_H
+#define GRPCPP_IMPL_CODEGEN_INTERCEPTOR_COMMON_H
+
+#include <array>
+#include <functional>
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/call_op_set_interface.h>
+#include <grpcpp/impl/codegen/client_interceptor.h>
+#include <grpcpp/impl/codegen/intercepted_channel.h>
+#include <grpcpp/impl/codegen/server_interceptor.h>
+
+#include <grpc/impl/codegen/grpc_types.h>
+
+namespace grpc {
+namespace internal {
+
+class InterceptorBatchMethodsImpl
+    : public experimental::InterceptorBatchMethods {
+ public:
+  InterceptorBatchMethodsImpl() {
+    for (auto i = static_cast<experimental::InterceptionHookPoints>(0);
+         i < experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS;
+         i = static_cast<experimental::InterceptionHookPoints>(
+             static_cast<size_t>(i) + 1)) {
+      hooks_[static_cast<size_t>(i)] = false;
+    }
+  }
+
+  ~InterceptorBatchMethodsImpl() {}
+
+  bool QueryInterceptionHookPoint(
+      experimental::InterceptionHookPoints type) override {
+    return hooks_[static_cast<size_t>(type)];
+  }
+
+  void Proceed() override {
+    if (call_->client_rpc_info() != nullptr) {
+      return ProceedClient();
+    }
+    GPR_CODEGEN_ASSERT(call_->server_rpc_info() != nullptr);
+    ProceedServer();
+  }
+
+  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_ = current_interceptor_index_;
+    ClearHookPoints();
+    ops_->SetHijackingState();
+    ran_hijacking_interceptor_ = true;
+    rpc_info->RunInterceptor(this, current_interceptor_index_);
+  }
+
+  void AddInterceptionHookPoint(experimental::InterceptionHookPoints type) {
+    hooks_[static_cast<size_t>(type)] = true;
+  }
+
+  ByteBuffer* GetSendMessage() override { return send_message_; }
+
+  std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
+    return send_initial_metadata_;
+  }
+
+  Status GetSendStatus() override {
+    return Status(static_cast<StatusCode>(*code_), *error_message_,
+                  *error_details_);
+  }
+
+  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();
+  }
+
+  std::multimap<grpc::string, grpc::string>* GetSendTrailingMetadata()
+      override {
+    return send_trailing_metadata_;
+  }
+
+  void* GetRecvMessage() override { return recv_message_; }
+
+  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvInitialMetadata()
+      override {
+    return recv_initial_metadata_->map();
+  }
+
+  Status* GetRecvStatus() override { return recv_status_; }
+
+  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvTrailingMetadata()
+      override {
+    return recv_trailing_metadata_->map();
+  }
+
+  void SetSendMessage(ByteBuffer* buf) { send_message_ = buf; }
+
+  void SetSendInitialMetadata(
+      std::multimap<grpc::string, grpc::string>* metadata) {
+    send_initial_metadata_ = metadata;
+  }
+
+  void SetSendStatus(grpc_status_code* code, grpc::string* error_details,
+                     grpc::string* error_message) {
+    code_ = code;
+    error_details_ = error_details;
+    error_message_ = error_message;
+  }
+
+  void SetSendTrailingMetadata(
+      std::multimap<grpc::string, grpc::string>* metadata) {
+    send_trailing_metadata_ = metadata;
+  }
+
+  void SetRecvMessage(void* message) { recv_message_ = message; }
+
+  void SetRecvInitialMetadata(MetadataMap* map) {
+    recv_initial_metadata_ = map;
+  }
+
+  void SetRecvStatus(Status* status) { recv_status_ = status; }
+
+  void SetRecvTrailingMetadata(MetadataMap* map) {
+    recv_trailing_metadata_ = map;
+  }
+
+  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 InterceptedChannel(
+        info->channel(), current_interceptor_index_ + 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_) {
+      current_interceptor_index_ = 0;
+    } else {
+      if (rpc_info->hijacked_) {
+        current_interceptor_index_ = rpc_info->hijacked_interceptor_;
+      } else {
+        current_interceptor_index_ = rpc_info->interceptors_.size() - 1;
+      }
+    }
+    rpc_info->RunInterceptor(this, current_interceptor_index_);
+  }
+
+  void RunServerInterceptors() {
+    auto* rpc_info = call_->server_rpc_info();
+    if (!reverse_) {
+      current_interceptor_index_ = 0;
+    } else {
+      current_interceptor_index_ = rpc_info->interceptors_.size() - 1;
+    }
+    rpc_info->RunInterceptor(this, current_interceptor_index_);
+  }
+
+  void ProceedClient() {
+    auto* rpc_info = call_->client_rpc_info();
+    if (rpc_info->hijacked_ && !reverse_ &&
+        current_interceptor_index_ == 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, current_interceptor_index_);
+      return;
+    }
+    if (!reverse_) {
+      current_interceptor_index_++;
+      // We are going down the stack of interceptors
+      if (current_interceptor_index_ < rpc_info->interceptors_.size()) {
+        if (rpc_info->hijacked_ &&
+            current_interceptor_index_ > rpc_info->hijacked_interceptor_) {
+          // This is a hijacked RPC and we are done with hijacking
+          ops_->ContinueFillOpsAfterInterception();
+        } else {
+          rpc_info->RunInterceptor(this, current_interceptor_index_);
+        }
+      } else {
+        // we are done running all the interceptors without any hijacking
+        ops_->ContinueFillOpsAfterInterception();
+      }
+    } else {
+      // We are going up the stack of interceptors
+      if (current_interceptor_index_ > 0) {
+        // Continue running interceptors
+        current_interceptor_index_--;
+        rpc_info->RunInterceptor(this, current_interceptor_index_);
+      } else {
+        // we are done running all the interceptors without any hijacking
+        ops_->ContinueFinalizeResultAfterInterception();
+      }
+    }
+  }
+
+  void ProceedServer() {
+    auto* rpc_info = call_->server_rpc_info();
+    if (!reverse_) {
+      current_interceptor_index_++;
+      if (current_interceptor_index_ < rpc_info->interceptors_.size()) {
+        return rpc_info->RunInterceptor(this, current_interceptor_index_);
+      } else if (ops_) {
+        return ops_->ContinueFillOpsAfterInterception();
+      }
+    } else {
+      // We are going up the stack of interceptors
+      if (current_interceptor_index_ > 0) {
+        // Continue running interceptors
+        current_interceptor_index_--;
+        return rpc_info->RunInterceptor(this, current_interceptor_index_);
+      } else if (ops_) {
+        return ops_->ContinueFinalizeResultAfterInterception();
+      }
+    }
+    GPR_CODEGEN_ASSERT(callback_);
+    callback_();
+  }
+
+  void ClearHookPoints() {
+    for (auto i = static_cast<experimental::InterceptionHookPoints>(0);
+         i < experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS;
+         i = static_cast<experimental::InterceptionHookPoints>(
+             static_cast<size_t>(i) + 1)) {
+      hooks_[static_cast<size_t>(i)] = false;
+    }
+  }
+
+  std::array<bool,
+             static_cast<size_t>(
+                 experimental::InterceptionHookPoints::NUM_INTERCEPTION_HOOKS)>
+      hooks_;
+
+  size_t current_interceptor_index_ = 0;  // Current iterator
+  bool reverse_ = false;
+  bool ran_hijacking_interceptor_ = false;
+  Call* call_ = nullptr;  // The Call object is present along with CallOpSet
+                          // object/callback
+  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;
+
+  MetadataMap* recv_initial_metadata_ = nullptr;
+
+  Status* recv_status_ = nullptr;
+
+  MetadataMap* recv_trailing_metadata_ = nullptr;
+};
+
+// A special implementation of InterceptorBatchMethods to send a Cancel
+// notification down the interceptor stack
+class CancelInterceptorBatchMethods
+    : public experimental::InterceptorBatchMethods {
+ public:
+  bool QueryInterceptionHookPoint(
+      experimental::InterceptionHookPoints type) override {
+    if (type == experimental::InterceptionHookPoints::PRE_SEND_CANCEL) {
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  void Proceed() override {
+    // This is a no-op. For actual continuation of the RPC simply needs to
+    // return from the Intercept method
+  }
+
+  void Hijack() override {
+    // Only the client can hijack when sending down initial metadata
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call Hijack on a method which has a "
+                       "Cancel notification");
+  }
+
+  ByteBuffer* GetSendMessage() override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetSendMessage on a method which "
+                       "has a Cancel notification");
+    return nullptr;
+  }
+
+  std::multimap<grpc::string, grpc::string>* GetSendInitialMetadata() override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetSendInitialMetadata on a "
+                       "method which has a Cancel notification");
+    return nullptr;
+  }
+
+  Status GetSendStatus() override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetSendStatus on a method which "
+                       "has a Cancel notification");
+    return Status();
+  }
+
+  void ModifySendStatus(const Status& status) override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call ModifySendStatus on a method "
+                       "which has a Cancel notification");
+    return;
+  }
+
+  std::multimap<grpc::string, grpc::string>* GetSendTrailingMetadata()
+      override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetSendTrailingMetadata on a "
+                       "method which has a Cancel notification");
+    return nullptr;
+  }
+
+  void* GetRecvMessage() override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetRecvMessage on a method which "
+                       "has a Cancel notification");
+    return nullptr;
+  }
+
+  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvInitialMetadata()
+      override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetRecvInitialMetadata on a "
+                       "method which has a Cancel notification");
+    return nullptr;
+  }
+
+  Status* GetRecvStatus() override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetRecvStatus on a method which "
+                       "has a Cancel notification");
+    return nullptr;
+  }
+
+  std::multimap<grpc::string_ref, grpc::string_ref>* GetRecvTrailingMetadata()
+      override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetRecvTrailingMetadata on a "
+                       "method which has a Cancel notification");
+    return nullptr;
+  }
+
+  std::unique_ptr<ChannelInterface> GetInterceptedChannel() override {
+    GPR_CODEGEN_ASSERT(false &&
+                       "It is illegal to call GetInterceptedChannel on a "
+                       "method which has a Cancel notification");
+    return std::unique_ptr<ChannelInterface>(nullptr);
+  }
+};
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_INTERCEPTOR_COMMON_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/metadata_map.h b/third_party/grpc/include/grpcpp/impl/codegen/metadata_map.h
new file mode 100644
index 0000000..9cec54d
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/metadata_map.h
@@ -0,0 +1,105 @@
+/*
+ *
+ * Copyright 2015 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_METADATA_MAP_H
+#define GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
+
+#include <map>
+
+#include <grpc/impl/codegen/log.h>
+#include <grpcpp/impl/codegen/slice.h>
+
+namespace grpc {
+
+namespace internal {
+
+const char kBinaryErrorDetailsKey[] = "grpc-status-details-bin";
+
+class MetadataMap {
+ public:
+  MetadataMap() { Setup(); }
+
+  ~MetadataMap() { Destroy(); }
+
+  grpc::string GetBinaryErrorDetails() {
+    // if filled_, extract from the multimap for O(log(n))
+    if (filled_) {
+      auto iter = map_.find(kBinaryErrorDetailsKey);
+      if (iter != map_.end()) {
+        return grpc::string(iter->second.begin(), iter->second.length());
+      }
+    }
+    // if not yet filled, take the O(n) lookup to avoid allocating the
+    // multimap until it is requested.
+    // TODO(ncteisen): plumb this through core as a first class object, just
+    // like code and message.
+    else {
+      for (size_t i = 0; i < arr_.count; i++) {
+        if (strncmp(reinterpret_cast<const char*>(
+                        GRPC_SLICE_START_PTR(arr_.metadata[i].key)),
+                    kBinaryErrorDetailsKey,
+                    GRPC_SLICE_LENGTH(arr_.metadata[i].key)) == 0) {
+          return grpc::string(reinterpret_cast<const char*>(
+                                  GRPC_SLICE_START_PTR(arr_.metadata[i].value)),
+                              GRPC_SLICE_LENGTH(arr_.metadata[i].value));
+        }
+      }
+    }
+    return grpc::string();
+  }
+
+  std::multimap<grpc::string_ref, grpc::string_ref>* map() {
+    FillMap();
+    return &map_;
+  }
+  grpc_metadata_array* arr() { return &arr_; }
+
+  void Reset() {
+    filled_ = false;
+    map_.clear();
+    Destroy();
+    Setup();
+  }
+
+ private:
+  bool filled_ = false;
+  grpc_metadata_array arr_;
+  std::multimap<grpc::string_ref, grpc::string_ref> map_;
+
+  void Destroy() {
+    g_core_codegen_interface->grpc_metadata_array_destroy(&arr_);
+  }
+
+  void Setup() { memset(&arr_, 0, sizeof(arr_)); }
+
+  void FillMap() {
+    if (filled_) return;
+    filled_ = true;
+    for (size_t i = 0; i < arr_.count; i++) {
+      // TODO(yangg) handle duplicates?
+      map_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
+          StringRefFromSlice(&arr_.metadata[i].key),
+          StringRefFromSlice(&arr_.metadata[i].value)));
+    }
+  }
+};
+}  // namespace internal
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_METADATA_MAP_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/method_handler_impl.h b/third_party/grpc/include/grpcpp/impl/codegen/method_handler_impl.h
new file mode 100644
index 0000000..dd53f97
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/method_handler_impl.h
@@ -0,0 +1,347 @@
+/*
+ *
+ * Copyright 2015 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_METHOD_HANDLER_IMPL_H
+#define GRPCPP_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
+
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+#include <grpcpp/impl/codegen/sync_stream.h>
+
+namespace grpc {
+
+namespace internal {
+
+// Invoke the method handler, fill in the status, and
+// return whether or not we finished safely (without an exception).
+// Note that exception handling is 0-cost in most compiler/library
+// implementations (except when an exception is actually thrown),
+// so this process doesn't require additional overhead in the common case.
+// Additionally, we don't need to return if we caught an exception or not;
+// the handling is the same in either case.
+template <class Callable>
+Status CatchingFunctionHandler(Callable&& handler) {
+#if GRPC_ALLOW_EXCEPTIONS
+  try {
+    return handler();
+  } catch (...) {
+    return Status(StatusCode::UNKNOWN, "Unexpected error in RPC handling");
+  }
+#else   // GRPC_ALLOW_EXCEPTIONS
+  return handler();
+#endif  // GRPC_ALLOW_EXCEPTIONS
+}
+
+/// A wrapper class of an application provided rpc method handler.
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler : public MethodHandler {
+ public:
+  RpcMethodHandler(std::function<Status(ServiceType*, ServerContext*,
+                                        const RequestType*, ResponseType*)>
+                       func,
+                   ServiceType* service)
+      : func_(func), service_(service) {}
+
+  void RunHandler(const HandlerParameter& param) final {
+    ResponseType rsp;
+    Status status = param.status;
+    if (status.ok()) {
+      status = CatchingFunctionHandler([this, &param, &rsp] {
+        return func_(service_, param.server_context,
+                     static_cast<RequestType*>(param.request), &rsp);
+      });
+      static_cast<RequestType*>(param.request)->~RequestType();
+    }
+
+    GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpServerSendStatus>
+        ops;
+    ops.SendInitialMetadata(&param.server_context->initial_metadata_,
+                            param.server_context->initial_metadata_flags());
+    if (param.server_context->compression_level_set()) {
+      ops.set_compression_level(param.server_context->compression_level());
+    }
+    if (status.ok()) {
+      status = ops.SendMessage(rsp);
+    }
+    ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
+    param.call->PerformOps(&ops);
+    param.call->cq()->Pluck(&ops);
+  }
+
+  void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
+                    Status* status) final {
+    ByteBuffer buf;
+    buf.set_buffer(req);
+    auto* request = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call, sizeof(RequestType))) RequestType();
+    *status = SerializationTraits<RequestType>::Deserialize(&buf, request);
+    buf.Release();
+    if (status->ok()) {
+      return request;
+    }
+    request->~RequestType();
+    return nullptr;
+  }
+
+ private:
+  /// Application provided rpc handler function.
+  std::function<Status(ServiceType*, ServerContext*, const RequestType*,
+                       ResponseType*)>
+      func_;
+  // The class the above handler function lives in.
+  ServiceType* service_;
+};
+
+/// A wrapper class of an application provided client streaming handler.
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler : public MethodHandler {
+ public:
+  ClientStreamingHandler(
+      std::function<Status(ServiceType*, ServerContext*,
+                           ServerReader<RequestType>*, ResponseType*)>
+          func,
+      ServiceType* service)
+      : func_(func), service_(service) {}
+
+  void RunHandler(const HandlerParameter& param) final {
+    ServerReader<RequestType> reader(param.call, param.server_context);
+    ResponseType rsp;
+    Status status = CatchingFunctionHandler([this, &param, &reader, &rsp] {
+      return func_(service_, param.server_context, &reader, &rsp);
+    });
+
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpServerSendStatus>
+        ops;
+    if (!param.server_context->sent_initial_metadata_) {
+      ops.SendInitialMetadata(&param.server_context->initial_metadata_,
+                              param.server_context->initial_metadata_flags());
+      if (param.server_context->compression_level_set()) {
+        ops.set_compression_level(param.server_context->compression_level());
+      }
+    }
+    if (status.ok()) {
+      status = ops.SendMessage(rsp);
+    }
+    ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
+    param.call->PerformOps(&ops);
+    param.call->cq()->Pluck(&ops);
+  }
+
+ private:
+  std::function<Status(ServiceType*, ServerContext*, ServerReader<RequestType>*,
+                       ResponseType*)>
+      func_;
+  ServiceType* service_;
+};
+
+/// A wrapper class of an application provided server streaming handler.
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler : public MethodHandler {
+ public:
+  ServerStreamingHandler(
+      std::function<Status(ServiceType*, ServerContext*, const RequestType*,
+                           ServerWriter<ResponseType>*)>
+          func,
+      ServiceType* service)
+      : func_(func), service_(service) {}
+
+  void RunHandler(const HandlerParameter& param) final {
+    Status status = param.status;
+    if (status.ok()) {
+      ServerWriter<ResponseType> writer(param.call, param.server_context);
+      status = CatchingFunctionHandler([this, &param, &writer] {
+        return func_(service_, param.server_context,
+                     static_cast<RequestType*>(param.request), &writer);
+      });
+      static_cast<RequestType*>(param.request)->~RequestType();
+    }
+
+    CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
+    if (!param.server_context->sent_initial_metadata_) {
+      ops.SendInitialMetadata(&param.server_context->initial_metadata_,
+                              param.server_context->initial_metadata_flags());
+      if (param.server_context->compression_level_set()) {
+        ops.set_compression_level(param.server_context->compression_level());
+      }
+    }
+    ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
+    param.call->PerformOps(&ops);
+    if (param.server_context->has_pending_ops_) {
+      param.call->cq()->Pluck(&param.server_context->pending_ops_);
+    }
+    param.call->cq()->Pluck(&ops);
+  }
+
+  void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
+                    Status* status) final {
+    ByteBuffer buf;
+    buf.set_buffer(req);
+    auto* request = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call, sizeof(RequestType))) RequestType();
+    *status = SerializationTraits<RequestType>::Deserialize(&buf, request);
+    buf.Release();
+    if (status->ok()) {
+      return request;
+    }
+    request->~RequestType();
+    return nullptr;
+  }
+
+ private:
+  std::function<Status(ServiceType*, ServerContext*, const RequestType*,
+                       ServerWriter<ResponseType>*)>
+      func_;
+  ServiceType* service_;
+};
+
+/// A wrapper class of an application provided bidi-streaming handler.
+/// This also applies to server-streamed implementation of a unary method
+/// with the additional requirement that such methods must have done a
+/// write for status to be ok
+/// Since this is used by more than 1 class, the service is not passed in.
+/// Instead, it is expected to be an implicitly-captured argument of func
+/// (through bind or something along those lines)
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler : public MethodHandler {
+ public:
+  TemplatedBidiStreamingHandler(
+      std::function<Status(ServerContext*, Streamer*)> func)
+      : func_(func), write_needed_(WriteNeeded) {}
+
+  void RunHandler(const HandlerParameter& param) final {
+    Streamer stream(param.call, param.server_context);
+    Status status = CatchingFunctionHandler([this, &param, &stream] {
+      return func_(param.server_context, &stream);
+    });
+
+    CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
+    if (!param.server_context->sent_initial_metadata_) {
+      ops.SendInitialMetadata(&param.server_context->initial_metadata_,
+                              param.server_context->initial_metadata_flags());
+      if (param.server_context->compression_level_set()) {
+        ops.set_compression_level(param.server_context->compression_level());
+      }
+      if (write_needed_ && status.ok()) {
+        // If we needed a write but never did one, we need to mark the
+        // status as a fail
+        status = Status(StatusCode::INTERNAL,
+                        "Service did not provide response message");
+      }
+    }
+    ops.ServerSendStatus(&param.server_context->trailing_metadata_, status);
+    param.call->PerformOps(&ops);
+    if (param.server_context->has_pending_ops_) {
+      param.call->cq()->Pluck(&param.server_context->pending_ops_);
+    }
+    param.call->cq()->Pluck(&ops);
+  }
+
+ private:
+  std::function<Status(ServerContext*, Streamer*)> func_;
+  const bool write_needed_;
+};
+
+template <class ServiceType, class RequestType, class ResponseType>
+class BidiStreamingHandler
+    : public TemplatedBidiStreamingHandler<
+          ServerReaderWriter<ResponseType, RequestType>, false> {
+ public:
+  BidiStreamingHandler(
+      std::function<Status(ServiceType*, ServerContext*,
+                           ServerReaderWriter<ResponseType, RequestType>*)>
+          func,
+      ServiceType* service)
+      : TemplatedBidiStreamingHandler<
+            ServerReaderWriter<ResponseType, RequestType>, false>(std::bind(
+            func, service, std::placeholders::_1, std::placeholders::_2)) {}
+};
+
+template <class RequestType, class ResponseType>
+class StreamedUnaryHandler
+    : public TemplatedBidiStreamingHandler<
+          ServerUnaryStreamer<RequestType, ResponseType>, true> {
+ public:
+  explicit StreamedUnaryHandler(
+      std::function<Status(ServerContext*,
+                           ServerUnaryStreamer<RequestType, ResponseType>*)>
+          func)
+      : TemplatedBidiStreamingHandler<
+            ServerUnaryStreamer<RequestType, ResponseType>, true>(func) {}
+};
+
+template <class RequestType, class ResponseType>
+class SplitServerStreamingHandler
+    : public TemplatedBidiStreamingHandler<
+          ServerSplitStreamer<RequestType, ResponseType>, false> {
+ public:
+  explicit SplitServerStreamingHandler(
+      std::function<Status(ServerContext*,
+                           ServerSplitStreamer<RequestType, ResponseType>*)>
+          func)
+      : TemplatedBidiStreamingHandler<
+            ServerSplitStreamer<RequestType, ResponseType>, false>(func) {}
+};
+
+/// General method handler class for errors that prevent real method use
+/// e.g., handle unknown method by returning UNIMPLEMENTED error.
+template <StatusCode code>
+class ErrorMethodHandler : public MethodHandler {
+ public:
+  template <class T>
+  static void FillOps(ServerContext* context, T* ops) {
+    Status status(code, "");
+    if (!context->sent_initial_metadata_) {
+      ops->SendInitialMetadata(&context->initial_metadata_,
+                               context->initial_metadata_flags());
+      if (context->compression_level_set()) {
+        ops->set_compression_level(context->compression_level());
+      }
+      context->sent_initial_metadata_ = true;
+    }
+    ops->ServerSendStatus(&context->trailing_metadata_, status);
+  }
+
+  void RunHandler(const HandlerParameter& param) final {
+    CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> ops;
+    FillOps(param.server_context, &ops);
+    param.call->PerformOps(&ops);
+    param.call->cq()->Pluck(&ops);
+  }
+
+  void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
+                    Status* status) final {
+    // We have to destroy any request payload
+    if (req != nullptr) {
+      g_core_codegen_interface->grpc_byte_buffer_destroy(req);
+    }
+    return nullptr;
+  }
+};
+
+typedef ErrorMethodHandler<StatusCode::UNIMPLEMENTED> UnknownMethodHandler;
+typedef ErrorMethodHandler<StatusCode::RESOURCE_EXHAUSTED>
+    ResourceExhaustedHandler;
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/proto_buffer_reader.h b/third_party/grpc/include/grpcpp/impl/codegen/proto_buffer_reader.h
new file mode 100644
index 0000000..9acae47
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/proto_buffer_reader.h
@@ -0,0 +1,151 @@
+/*
+ *
+ * Copyright 2015 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_PROTO_BUFFER_READER_H
+#define GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H
+
+#include <type_traits>
+
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config_protobuf.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/status.h>
+
+/// This header provides an object that reads bytes directly from a
+/// grpc::ByteBuffer, via the ZeroCopyInputStream interface
+
+namespace grpc {
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// This is a specialization of the protobuf class ZeroCopyInputStream
+/// The principle is to get one chunk of data at a time from the proto layer,
+/// with options to backup (re-see some bytes) or skip (forward past some bytes)
+///
+/// Read more about ZeroCopyInputStream interface here:
+/// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream#ZeroCopyInputStream
+class ProtoBufferReader : public ::grpc::protobuf::io::ZeroCopyInputStream {
+ public:
+  /// Constructs buffer reader from \a buffer. Will set \a status() to non ok
+  /// if \a buffer is invalid (the internal buffer has not been initialized).
+  explicit ProtoBufferReader(ByteBuffer* buffer)
+      : byte_count_(0), backup_count_(0), status_() {
+    /// Implemented through a grpc_byte_buffer_reader which iterates
+    /// over the slices that make up a byte buffer
+    if (!buffer->Valid() ||
+        !g_core_codegen_interface->grpc_byte_buffer_reader_init(
+            &reader_, buffer->c_buffer())) {
+      status_ = Status(StatusCode::INTERNAL,
+                       "Couldn't initialize byte buffer reader");
+    }
+  }
+
+  ~ProtoBufferReader() {
+    if (status_.ok()) {
+      g_core_codegen_interface->grpc_byte_buffer_reader_destroy(&reader_);
+    }
+  }
+
+  /// Give the proto library a chunk of data from the stream. The caller
+  /// may safely read from data[0, size - 1].
+  bool Next(const void** data, int* size) override {
+    if (!status_.ok()) {
+      return false;
+    }
+    /// If we have backed up previously, we need to return the backed-up slice
+    if (backup_count_ > 0) {
+      *data = GRPC_SLICE_START_PTR(slice_) + GRPC_SLICE_LENGTH(slice_) -
+              backup_count_;
+      GPR_CODEGEN_ASSERT(backup_count_ <= INT_MAX);
+      *size = (int)backup_count_;
+      backup_count_ = 0;
+      return true;
+    }
+    /// Otherwise get the next slice from the byte buffer reader
+    if (!g_core_codegen_interface->grpc_byte_buffer_reader_next(&reader_,
+                                                                &slice_)) {
+      return false;
+    }
+    g_core_codegen_interface->grpc_slice_unref(slice_);
+    *data = GRPC_SLICE_START_PTR(slice_);
+    // On win x64, int is only 32bit
+    GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
+    byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
+    return true;
+  }
+
+  /// Returns the status of the buffer reader.
+  Status status() const { return status_; }
+
+  /// The proto library calls this to indicate that we should back up \a count
+  /// bytes that have already been returned by the last call of Next.
+  /// So do the backup and have that ready for a later Next.
+  void BackUp(int count) override {
+    GPR_CODEGEN_ASSERT(count <= static_cast<int>(GRPC_SLICE_LENGTH(slice_)));
+    backup_count_ = count;
+  }
+
+  /// The proto library calls this to skip over \a count bytes. Implement this
+  /// using Next and BackUp combined.
+  bool Skip(int count) override {
+    const void* data;
+    int size;
+    while (Next(&data, &size)) {
+      if (size >= count) {
+        BackUp(size - count);
+        return true;
+      }
+      // size < count;
+      count -= size;
+    }
+    // error or we have too large count;
+    return false;
+  }
+
+  /// Returns the total number of bytes read since this object was created.
+  grpc::protobuf::int64 ByteCount() const override {
+    return byte_count_ - backup_count_;
+  }
+
+  // These protected members are needed to support internal optimizations.
+  // they expose internal bits of grpc core that are NOT stable. If you have
+  // a use case needs to use one of these functions, please send an email to
+  // https://groups.google.com/forum/#!forum/grpc-io.
+ protected:
+  void set_byte_count(int64_t byte_count) { byte_count_ = byte_count; }
+  int64_t backup_count() { return backup_count_; }
+  void set_backup_count(int64_t backup_count) { backup_count_ = backup_count; }
+  grpc_byte_buffer_reader* reader() { return &reader_; }
+  grpc_slice* slice() { return &slice_; }
+
+ private:
+  int64_t byte_count_;              ///< total bytes read since object creation
+  int64_t backup_count_;            ///< how far backed up in the stream we are
+  grpc_byte_buffer_reader reader_;  ///< internal object to read \a grpc_slice
+                                    ///< from the \a grpc_byte_buffer
+  grpc_slice slice_;                ///< current slice passed back to the caller
+  Status status_;                   ///< status of the entire object
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_READER_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/proto_buffer_writer.h b/third_party/grpc/include/grpcpp/impl/codegen/proto_buffer_writer.h
new file mode 100644
index 0000000..fdff467
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/proto_buffer_writer.h
@@ -0,0 +1,167 @@
+/*
+ *
+ * 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_PROTO_BUFFER_WRITER_H
+#define GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H
+
+#include <type_traits>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config_protobuf.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/status.h>
+
+/// This header provides an object that writes bytes directly into a
+/// grpc::ByteBuffer, via the ZeroCopyOutputStream interface
+
+namespace grpc {
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+// Forward declaration for testing use only
+namespace internal {
+class ProtoBufferWriterPeer;
+}  // namespace internal
+
+const int kProtoBufferWriterMaxBufferLength = 1024 * 1024;
+
+/// This is a specialization of the protobuf class ZeroCopyOutputStream.
+/// The principle is to give the proto layer one buffer of bytes at a time
+/// that it can use to serialize the next portion of the message, with the
+/// option to "backup" if more buffer is given than required at the last buffer.
+///
+/// Read more about ZeroCopyOutputStream interface here:
+/// https://developers.google.com/protocol-buffers/docs/reference/cpp/google.protobuf.io.zero_copy_stream#ZeroCopyOutputStream
+class ProtoBufferWriter : public ::grpc::protobuf::io::ZeroCopyOutputStream {
+ public:
+  /// Constructor for this derived class
+  ///
+  /// \param[out] byte_buffer A pointer to the grpc::ByteBuffer created
+  /// \param block_size How big are the chunks to allocate at a time
+  /// \param total_size How many total bytes are required for this proto
+  ProtoBufferWriter(ByteBuffer* byte_buffer, int block_size, int total_size)
+      : block_size_(block_size),
+        total_size_(total_size),
+        byte_count_(0),
+        have_backup_(false) {
+    GPR_CODEGEN_ASSERT(!byte_buffer->Valid());
+    /// Create an empty raw byte buffer and look at its underlying slice buffer
+    grpc_byte_buffer* bp =
+        g_core_codegen_interface->grpc_raw_byte_buffer_create(NULL, 0);
+    byte_buffer->set_buffer(bp);
+    slice_buffer_ = &bp->data.raw.slice_buffer;
+  }
+
+  ~ProtoBufferWriter() {
+    if (have_backup_) {
+      g_core_codegen_interface->grpc_slice_unref(backup_slice_);
+    }
+  }
+
+  /// Give the proto library the next buffer of bytes and its size. It is
+  /// safe for the caller to write from data[0, size - 1].
+  bool Next(void** data, int* size) override {
+    // Protobuf should not ask for more memory than total_size_.
+    GPR_CODEGEN_ASSERT(byte_count_ < total_size_);
+    // 1. Use the remaining backup slice if we have one
+    // 2. Otherwise allocate a slice, up to the remaining length needed
+    //    or our maximum allocation size
+    // 3. Provide the slice start and size available
+    // 4. Add the slice being returned to the slice buffer
+    size_t remain = total_size_ - byte_count_;
+    if (have_backup_) {
+      /// If we have a backup slice, we should use it first
+      slice_ = backup_slice_;
+      have_backup_ = false;
+      if (GRPC_SLICE_LENGTH(slice_) > remain) {
+        GRPC_SLICE_SET_LENGTH(slice_, remain);
+      }
+    } else {
+      // When less than a whole block is needed, only allocate that much.
+      // But make sure the allocated slice is not inlined.
+      size_t allocate_length =
+          remain > static_cast<size_t>(block_size_) ? block_size_ : remain;
+      slice_ = g_core_codegen_interface->grpc_slice_malloc(
+          allocate_length > GRPC_SLICE_INLINED_SIZE
+              ? allocate_length
+              : GRPC_SLICE_INLINED_SIZE + 1);
+    }
+    *data = GRPC_SLICE_START_PTR(slice_);
+    // On win x64, int is only 32bit
+    GPR_CODEGEN_ASSERT(GRPC_SLICE_LENGTH(slice_) <= INT_MAX);
+    byte_count_ += * size = (int)GRPC_SLICE_LENGTH(slice_);
+    g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
+    return true;
+  }
+
+  /// Backup by \a count bytes because Next returned more bytes than needed
+  /// (only used in the last buffer). \a count must be less than or equal too
+  /// the last buffer returned from next.
+  void BackUp(int count) override {
+    /// 1. Remove the partially-used last slice from the slice buffer
+    /// 2. Split it into the needed (if any) and unneeded part
+    /// 3. Add the needed part back to the slice buffer
+    /// 4. Mark that we still have the remaining part (for later use/unref)
+    GPR_CODEGEN_ASSERT(count <= static_cast<int>(GRPC_SLICE_LENGTH(slice_)));
+    g_core_codegen_interface->grpc_slice_buffer_pop(slice_buffer_);
+    if ((size_t)count == GRPC_SLICE_LENGTH(slice_)) {
+      backup_slice_ = slice_;
+    } else {
+      backup_slice_ = g_core_codegen_interface->grpc_slice_split_tail(
+          &slice_, GRPC_SLICE_LENGTH(slice_) - count);
+      g_core_codegen_interface->grpc_slice_buffer_add(slice_buffer_, slice_);
+    }
+    // It's dangerous to keep an inlined grpc_slice as the backup slice, since
+    // on a following Next() call, a reference will be returned to this slice
+    // via GRPC_SLICE_START_PTR, which will not be an address held by
+    // slice_buffer_.
+    have_backup_ = backup_slice_.refcount != NULL;
+    byte_count_ -= count;
+  }
+
+  /// Returns the total number of bytes written since this object was created.
+  grpc::protobuf::int64 ByteCount() const override { return byte_count_; }
+
+  // These protected members are needed to support internal optimizations.
+  // they expose internal bits of grpc core that are NOT stable. If you have
+  // a use case needs to use one of these functions, please send an email to
+  // https://groups.google.com/forum/#!forum/grpc-io.
+ protected:
+  grpc_slice_buffer* slice_buffer() { return slice_buffer_; }
+  void set_byte_count(int64_t byte_count) { byte_count_ = byte_count; }
+
+ private:
+  // friend for testing purposes only
+  friend class internal::ProtoBufferWriterPeer;
+  const int block_size_;  ///< size to alloc for each new \a grpc_slice needed
+  const int total_size_;  ///< byte size of proto being serialized
+  int64_t byte_count_;    ///< bytes written since this object was created
+  grpc_slice_buffer*
+      slice_buffer_;  ///< internal buffer of slices holding the serialized data
+  bool have_backup_;  ///< if we are holding a backup slice or not
+  grpc_slice backup_slice_;  ///< holds space we can still write to, if the
+                             ///< caller has called BackUp
+  grpc_slice slice_;         ///< current slice passed back to the caller
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_PROTO_BUFFER_WRITER_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/proto_utils.h b/third_party/grpc/include/grpcpp/impl/codegen/proto_utils.h
new file mode 100644
index 0000000..d9db6de
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/proto_utils.h
@@ -0,0 +1,121 @@
+/*
+ *
+ * Copyright 2015 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_PROTO_UTILS_H
+#define GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
+
+#include <type_traits>
+
+#include <grpc/impl/codegen/byte_buffer_reader.h>
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpc/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config_protobuf.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/proto_buffer_reader.h>
+#include <grpcpp/impl/codegen/proto_buffer_writer.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/impl/codegen/status.h>
+
+/// This header provides serialization and deserialization between gRPC
+/// messages serialized using protobuf and the C++ objects they represent.
+
+namespace grpc {
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+// ProtoBufferWriter must be a subclass of ::protobuf::io::ZeroCopyOutputStream.
+template <class ProtoBufferWriter, class T>
+Status GenericSerialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
+                        bool* own_buffer) {
+  static_assert(std::is_base_of<protobuf::io::ZeroCopyOutputStream,
+                                ProtoBufferWriter>::value,
+                "ProtoBufferWriter must be a subclass of "
+                "::protobuf::io::ZeroCopyOutputStream");
+  *own_buffer = true;
+  int byte_size = msg.ByteSize();
+  if ((size_t)byte_size <= GRPC_SLICE_INLINED_SIZE) {
+    Slice slice(byte_size);
+    // We serialize directly into the allocated slices memory
+    GPR_CODEGEN_ASSERT(slice.end() == msg.SerializeWithCachedSizesToArray(
+                                          const_cast<uint8_t*>(slice.begin())));
+    ByteBuffer tmp(&slice, 1);
+    bb->Swap(&tmp);
+
+    return g_core_codegen_interface->ok();
+  }
+  ProtoBufferWriter writer(bb, kProtoBufferWriterMaxBufferLength, byte_size);
+  return msg.SerializeToZeroCopyStream(&writer)
+             ? g_core_codegen_interface->ok()
+             : Status(StatusCode::INTERNAL, "Failed to serialize message");
+}
+
+// BufferReader must be a subclass of ::protobuf::io::ZeroCopyInputStream.
+template <class ProtoBufferReader, class T>
+Status GenericDeserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
+  static_assert(std::is_base_of<protobuf::io::ZeroCopyInputStream,
+                                ProtoBufferReader>::value,
+                "ProtoBufferReader must be a subclass of "
+                "::protobuf::io::ZeroCopyInputStream");
+  if (buffer == nullptr) {
+    return Status(StatusCode::INTERNAL, "No payload");
+  }
+  Status result = g_core_codegen_interface->ok();
+  {
+    ProtoBufferReader reader(buffer);
+    if (!reader.status().ok()) {
+      return reader.status();
+    }
+    ::grpc::protobuf::io::CodedInputStream decoder(&reader);
+    decoder.SetTotalBytesLimit(INT_MAX, INT_MAX);
+    if (!msg->ParseFromCodedStream(&decoder)) {
+      result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
+    }
+    if (!decoder.ConsumedEntireMessage()) {
+      result = Status(StatusCode::INTERNAL, "Did not read entire message");
+    }
+  }
+  buffer->Clear();
+  return result;
+}
+
+// this is needed so the following class does not conflict with protobuf
+// serializers that utilize internal-only tools.
+#ifdef GRPC_OPEN_SOURCE_PROTO
+// This class provides a protobuf serializer. It translates between protobuf
+// objects and grpc_byte_buffers. More information about SerializationTraits can
+// be found in include/grpcpp/impl/codegen/serialization_traits.h.
+template <class T>
+class SerializationTraits<T, typename std::enable_if<std::is_base_of<
+                                 grpc::protobuf::Message, T>::value>::type> {
+ public:
+  static Status Serialize(const grpc::protobuf::Message& msg, ByteBuffer* bb,
+                          bool* own_buffer) {
+    return GenericSerialize<ProtoBufferWriter, T>(msg, bb, own_buffer);
+  }
+
+  static Status Deserialize(ByteBuffer* buffer, grpc::protobuf::Message* msg) {
+    return GenericDeserialize<ProtoBufferReader, T>(buffer, msg);
+  }
+};
+#endif
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_PROTO_UTILS_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/rpc_method.h b/third_party/grpc/include/grpcpp/impl/codegen/rpc_method.h
new file mode 100644
index 0000000..9dcde95
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/rpc_method.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015 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_RPC_METHOD_H
+#define GRPCPP_IMPL_CODEGEN_RPC_METHOD_H
+
+#include <memory>
+
+#include <grpcpp/impl/codegen/channel_interface.h>
+
+namespace grpc {
+namespace internal {
+/// Descriptor of an RPC method
+class RpcMethod {
+ public:
+  enum RpcType {
+    NORMAL_RPC = 0,
+    CLIENT_STREAMING,  // request streaming
+    SERVER_STREAMING,  // response streaming
+    BIDI_STREAMING
+  };
+
+  RpcMethod(const char* name, RpcType type)
+      : name_(name), method_type_(type), channel_tag_(NULL) {}
+
+  RpcMethod(const char* name, RpcType type,
+            const std::shared_ptr<ChannelInterface>& channel)
+      : name_(name),
+        method_type_(type),
+        channel_tag_(channel->RegisterMethod(name)) {}
+
+  const char* name() const { return name_; }
+  RpcType method_type() const { return method_type_; }
+  void SetMethodType(RpcType type) { method_type_ = type; }
+  void* channel_tag() const { return channel_tag_; }
+
+ private:
+  const char* const name_;
+  RpcType method_type_;
+  void* const channel_tag_;
+};
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_RPC_METHOD_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/rpc_service_method.h b/third_party/grpc/include/grpcpp/impl/codegen/rpc_service_method.h
new file mode 100644
index 0000000..f465c5f
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/rpc_service_method.h
@@ -0,0 +1,150 @@
+/*
+ *
+ * Copyright 2016 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_RPC_SERVICE_METHOD_H
+#define GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H
+
+#include <climits>
+#include <functional>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <grpc/impl/codegen/log.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+class ServerContext;
+
+namespace internal {
+/// Base class for running an RPC handler.
+class MethodHandler {
+ public:
+  virtual ~MethodHandler() {}
+  struct HandlerParameter {
+    /// Constructor for HandlerParameter
+    ///
+    /// \param c : the gRPC Call structure for this server call
+    /// \param context : the ServerContext structure for this server call
+    /// \param req : the request payload, if appropriate for this RPC
+    /// \param req_status : the request status after any interceptors have run
+    /// \param rpc_requester : used only by the callback API. It is a function
+    ///        called by the RPC Controller to request another RPC (and also
+    ///        to set up the state required to make that request possible)
+    HandlerParameter(Call* c, ServerContext* context, void* req,
+                     Status req_status, std::function<void()> requester)
+        : call(c),
+          server_context(context),
+          request(req),
+          status(req_status),
+          call_requester(std::move(requester)) {}
+    ~HandlerParameter() {}
+    Call* call;
+    ServerContext* server_context;
+    void* request;
+    Status status;
+    std::function<void()> call_requester;
+  };
+  virtual void RunHandler(const HandlerParameter& param) = 0;
+
+  /* Returns a pointer to the deserialized request. \a status reflects the
+     result of deserialization. This pointer and the status should be filled in
+     a HandlerParameter and passed to RunHandler. It is illegal to access the
+     pointer after calling RunHandler. Ownership of the deserialized request is
+     retained by the handler. Returns nullptr if deserialization failed. */
+  virtual void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
+                            Status* status) {
+    GPR_CODEGEN_ASSERT(req == nullptr);
+    return nullptr;
+  }
+};
+
+/// Server side rpc method class
+class RpcServiceMethod : public RpcMethod {
+ public:
+  /// Takes ownership of the handler
+  RpcServiceMethod(const char* name, RpcMethod::RpcType type,
+                   MethodHandler* handler)
+      : RpcMethod(name, type),
+        server_tag_(nullptr),
+        api_type_(ApiType::SYNC),
+        handler_(handler) {}
+
+  enum class ApiType {
+    SYNC,
+    ASYNC,
+    RAW,
+    CALL_BACK,  // not CALLBACK because that is reserved in Windows
+    RAW_CALL_BACK,
+  };
+
+  void set_server_tag(void* tag) { server_tag_ = tag; }
+  void* server_tag() const { return server_tag_; }
+  /// if MethodHandler is nullptr, then this is an async method
+  MethodHandler* handler() const { return handler_.get(); }
+  ApiType api_type() const { return api_type_; }
+  void SetHandler(MethodHandler* handler) { handler_.reset(handler); }
+  void SetServerApiType(RpcServiceMethod::ApiType type) {
+    if ((api_type_ == ApiType::SYNC) &&
+        (type == ApiType::ASYNC || type == ApiType::RAW)) {
+      // this marks this method as async
+      handler_.reset();
+    } else if (api_type_ != ApiType::SYNC) {
+      // this is not an error condition, as it allows users to declare a server
+      // like WithRawMethod_foo<AsyncService>. However since it
+      // overwrites behavior, it should be logged.
+      gpr_log(
+          GPR_INFO,
+          "You are marking method %s as '%s', even though it was "
+          "previously marked '%s'. This behavior will overwrite the original "
+          "behavior. If you expected this then ignore this message.",
+          name(), TypeToString(api_type_), TypeToString(type));
+    }
+    api_type_ = type;
+  }
+
+ private:
+  void* server_tag_;
+  ApiType api_type_;
+  std::unique_ptr<MethodHandler> handler_;
+
+  const char* TypeToString(RpcServiceMethod::ApiType type) {
+    switch (type) {
+      case ApiType::SYNC:
+        return "sync";
+      case ApiType::ASYNC:
+        return "async";
+      case ApiType::RAW:
+        return "raw";
+      case ApiType::CALL_BACK:
+        return "callback";
+      case ApiType::RAW_CALL_BACK:
+        return "raw_callback";
+      default:
+        GPR_UNREACHABLE_CODE(return "unknown");
+    }
+  }
+};
+}  // namespace internal
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_RPC_SERVICE_METHOD_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/security/auth_context.h b/third_party/grpc/include/grpcpp/impl/codegen/security/auth_context.h
new file mode 100644
index 0000000..0e30f7c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/security/auth_context.h
@@ -0,0 +1,95 @@
+/*
+ *
+ * Copyright 2015 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_SECURITY_AUTH_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H
+
+#include <iterator>
+#include <vector>
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+struct grpc_auth_context;
+struct grpc_auth_property;
+struct grpc_auth_property_iterator;
+
+namespace grpc {
+class SecureAuthContext;
+
+typedef std::pair<grpc::string_ref, grpc::string_ref> AuthProperty;
+
+class AuthPropertyIterator
+    : public std::iterator<std::input_iterator_tag, const AuthProperty> {
+ public:
+  ~AuthPropertyIterator();
+  AuthPropertyIterator& operator++();
+  AuthPropertyIterator operator++(int);
+  bool operator==(const AuthPropertyIterator& rhs) const;
+  bool operator!=(const AuthPropertyIterator& rhs) const;
+  const AuthProperty operator*();
+
+ protected:
+  AuthPropertyIterator();
+  AuthPropertyIterator(const grpc_auth_property* property,
+                       const grpc_auth_property_iterator* iter);
+
+ private:
+  friend class SecureAuthContext;
+  const grpc_auth_property* property_;
+  // The following items form a grpc_auth_property_iterator.
+  const grpc_auth_context* ctx_;
+  size_t index_;
+  const char* name_;
+};
+
+/// Class encapsulating the Authentication Information.
+///
+/// It includes the secure identity of the peer, the type of secure transport
+/// used as well as any other properties required by the authorization layer.
+class AuthContext {
+ public:
+  virtual ~AuthContext() {}
+
+  /// Returns true if the peer is authenticated.
+  virtual bool IsPeerAuthenticated() const = 0;
+
+  /// A peer identity.
+  ///
+  /// It is, in general, comprised of one or more properties (in which case they
+  /// have the same name).
+  virtual std::vector<grpc::string_ref> GetPeerIdentity() const = 0;
+  virtual grpc::string GetPeerIdentityPropertyName() const = 0;
+
+  /// Returns all the property values with the given name.
+  virtual std::vector<grpc::string_ref> FindPropertyValues(
+      const grpc::string& name) const = 0;
+
+  /// Iteration over all the properties.
+  virtual AuthPropertyIterator begin() const = 0;
+  virtual AuthPropertyIterator end() const = 0;
+
+  /// Mutation functions: should only be used by an AuthMetadataProcessor.
+  virtual void AddProperty(const grpc::string& key,
+                           const grpc::string_ref& value) = 0;
+  virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SECURITY_AUTH_CONTEXT_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/serialization_traits.h b/third_party/grpc/include/grpcpp/impl/codegen/serialization_traits.h
new file mode 100644
index 0000000..8f792232
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/serialization_traits.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * Copyright 2015 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_SERIALIZATION_TRAITS_H
+#define GRPCPP_IMPL_CODEGEN_SERIALIZATION_TRAITS_H
+
+namespace grpc {
+
+/// Defines how to serialize and deserialize some type.
+///
+/// Used for hooking different message serialization API's into GRPC.
+/// Each SerializationTraits<Message> implementation must provide the
+/// following functions:
+/// 1.  static Status Serialize(const Message& msg,
+///                             ByteBuffer* buffer,
+///                             bool* own_buffer);
+///     OR
+///     static Status Serialize(const Message& msg,
+///                             grpc_byte_buffer** buffer,
+///                             bool* own_buffer);
+///     The former is preferred; the latter is deprecated
+///
+/// 2.  static Status Deserialize(ByteBuffer* buffer,
+///                               Message* msg);
+///     OR
+///     static Status Deserialize(grpc_byte_buffer* buffer,
+///                               Message* msg);
+///     The former is preferred; the latter is deprecated
+///
+/// Serialize is required to convert message to a ByteBuffer, and
+/// return that byte buffer through *buffer. *own_buffer should
+/// be set to true if the caller owns said byte buffer, or false if
+/// ownership is retained elsewhere.
+///
+/// Deserialize is required to convert buffer into the message stored at
+/// msg. max_receive_message_size is passed in as a bound on the maximum
+/// number of message bytes Deserialize should accept.
+///
+/// Both functions return a Status, allowing them to explain what went
+/// wrong if required.
+template <class Message,
+          class UnusedButHereForPartialTemplateSpecialization = void>
+class SerializationTraits;
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SERIALIZATION_TRAITS_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/server_callback.h b/third_party/grpc/include/grpcpp/impl/codegen/server_callback.h
new file mode 100644
index 0000000..1854f6e
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/server_callback.h
@@ -0,0 +1,890 @@
+/*
+ *
+ * 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_SERVER_CALLBACK_H
+#define GRPCPP_IMPL_CODEGEN_SERVER_CALLBACK_H
+
+#include <atomic>
+#include <functional>
+#include <type_traits>
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/call_op_set.h>
+#include <grpcpp/impl/codegen/callback_common.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/server_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+// Declare base class of all reactors as internal
+namespace internal {
+
+class ServerReactor {
+ public:
+  virtual ~ServerReactor() = default;
+  virtual void OnDone() {}
+  virtual void OnCancel() {}
+};
+
+}  // namespace internal
+
+namespace experimental {
+
+// Forward declarations
+template <class Request, class Response>
+class ServerReadReactor;
+template <class Request, class Response>
+class ServerWriteReactor;
+template <class Request, class Response>
+class ServerBidiReactor;
+
+// For unary RPCs, the exposed controller class is only an interface
+// and the actual implementation is an internal class.
+class ServerCallbackRpcController {
+ public:
+  virtual ~ServerCallbackRpcController() = default;
+
+  // The method handler must call this function when it is done so that
+  // the library knows to free its resources
+  virtual void Finish(Status s) = 0;
+
+  // Allow the method handler to push out the initial metadata before
+  // the response and status are ready
+  virtual void SendInitialMetadata(std::function<void(bool)>) = 0;
+};
+
+// NOTE: The actual streaming object classes are provided
+// as API only to support mocking. There are no implementations of
+// these class interfaces in the API.
+template <class Request>
+class ServerCallbackReader {
+ public:
+  virtual ~ServerCallbackReader() {}
+  virtual void Finish(Status s) = 0;
+  virtual void SendInitialMetadata() = 0;
+  virtual void Read(Request* msg) = 0;
+
+ protected:
+  template <class Response>
+  void BindReactor(ServerReadReactor<Request, Response>* reactor) {
+    reactor->BindReader(this);
+  }
+};
+
+template <class Response>
+class ServerCallbackWriter {
+ public:
+  virtual ~ServerCallbackWriter() {}
+
+  virtual void Finish(Status s) = 0;
+  virtual void SendInitialMetadata() = 0;
+  virtual void Write(const Response* msg, WriteOptions options) = 0;
+  virtual void WriteAndFinish(const Response* msg, WriteOptions options,
+                              Status s) {
+    // Default implementation that can/should be overridden
+    Write(msg, std::move(options));
+    Finish(std::move(s));
+  };
+
+ protected:
+  template <class Request>
+  void BindReactor(ServerWriteReactor<Request, Response>* reactor) {
+    reactor->BindWriter(this);
+  }
+};
+
+template <class Request, class Response>
+class ServerCallbackReaderWriter {
+ public:
+  virtual ~ServerCallbackReaderWriter() {}
+
+  virtual void Finish(Status s) = 0;
+  virtual void SendInitialMetadata() = 0;
+  virtual void Read(Request* msg) = 0;
+  virtual void Write(const Response* msg, WriteOptions options) = 0;
+  virtual void WriteAndFinish(const Response* msg, WriteOptions options,
+                              Status s) {
+    // Default implementation that can/should be overridden
+    Write(msg, std::move(options));
+    Finish(std::move(s));
+  };
+
+ protected:
+  void BindReactor(ServerBidiReactor<Request, Response>* reactor) {
+    reactor->BindStream(this);
+  }
+};
+
+// The following classes are reactors that are to be implemented
+// by the user, returned as the result of the method handler for
+// a callback method, and activated by the call to OnStarted
+template <class Request, class Response>
+class ServerBidiReactor : public internal::ServerReactor {
+ public:
+  ~ServerBidiReactor() = default;
+  virtual void OnStarted(ServerContext*) {}
+  virtual void OnSendInitialMetadataDone(bool ok) {}
+  virtual void OnReadDone(bool ok) {}
+  virtual void OnWriteDone(bool ok) {}
+
+  void StartSendInitialMetadata() { stream_->SendInitialMetadata(); }
+  void StartRead(Request* msg) { stream_->Read(msg); }
+  void StartWrite(const Response* msg) { StartWrite(msg, WriteOptions()); }
+  void StartWrite(const Response* msg, WriteOptions options) {
+    stream_->Write(msg, std::move(options));
+  }
+  void StartWriteAndFinish(const Response* msg, WriteOptions options,
+                           Status s) {
+    stream_->WriteAndFinish(msg, std::move(options), std::move(s));
+  }
+  void StartWriteLast(const Response* msg, WriteOptions options) {
+    StartWrite(msg, std::move(options.set_last_message()));
+  }
+  void Finish(Status s) { stream_->Finish(std::move(s)); }
+
+ private:
+  friend class ServerCallbackReaderWriter<Request, Response>;
+  void BindStream(ServerCallbackReaderWriter<Request, Response>* stream) {
+    stream_ = stream;
+  }
+
+  ServerCallbackReaderWriter<Request, Response>* stream_;
+};
+
+template <class Request, class Response>
+class ServerReadReactor : public internal::ServerReactor {
+ public:
+  ~ServerReadReactor() = default;
+  virtual void OnStarted(ServerContext*, Response* resp) {}
+  virtual void OnSendInitialMetadataDone(bool ok) {}
+  virtual void OnReadDone(bool ok) {}
+
+  void StartSendInitialMetadata() { reader_->SendInitialMetadata(); }
+  void StartRead(Request* msg) { reader_->Read(msg); }
+  void Finish(Status s) { reader_->Finish(std::move(s)); }
+
+ private:
+  friend class ServerCallbackReader<Request>;
+  void BindReader(ServerCallbackReader<Request>* reader) { reader_ = reader; }
+
+  ServerCallbackReader<Request>* reader_;
+};
+
+template <class Request, class Response>
+class ServerWriteReactor : public internal::ServerReactor {
+ public:
+  ~ServerWriteReactor() = default;
+  virtual void OnStarted(ServerContext*, const Request* req) {}
+  virtual void OnSendInitialMetadataDone(bool ok) {}
+  virtual void OnWriteDone(bool ok) {}
+
+  void StartSendInitialMetadata() { writer_->SendInitialMetadata(); }
+  void StartWrite(const Response* msg) { StartWrite(msg, WriteOptions()); }
+  void StartWrite(const Response* msg, WriteOptions options) {
+    writer_->Write(msg, std::move(options));
+  }
+  void StartWriteAndFinish(const Response* msg, WriteOptions options,
+                           Status s) {
+    writer_->WriteAndFinish(msg, std::move(options), std::move(s));
+  }
+  void StartWriteLast(const Response* msg, WriteOptions options) {
+    StartWrite(msg, std::move(options.set_last_message()));
+  }
+  void Finish(Status s) { writer_->Finish(std::move(s)); }
+
+ private:
+  friend class ServerCallbackWriter<Response>;
+  void BindWriter(ServerCallbackWriter<Response>* writer) { writer_ = writer; }
+
+  ServerCallbackWriter<Response>* writer_;
+};
+
+}  // namespace experimental
+
+namespace internal {
+
+template <class Request, class Response>
+class UnimplementedReadReactor
+    : public experimental::ServerReadReactor<Request, Response> {
+ public:
+  void OnDone() override { delete this; }
+  void OnStarted(ServerContext*, Response*) override {
+    this->Finish(Status(StatusCode::UNIMPLEMENTED, ""));
+  }
+};
+
+template <class Request, class Response>
+class UnimplementedWriteReactor
+    : public experimental::ServerWriteReactor<Request, Response> {
+ public:
+  void OnDone() override { delete this; }
+  void OnStarted(ServerContext*, const Request*) override {
+    this->Finish(Status(StatusCode::UNIMPLEMENTED, ""));
+  }
+};
+
+template <class Request, class Response>
+class UnimplementedBidiReactor
+    : public experimental::ServerBidiReactor<Request, Response> {
+ public:
+  void OnDone() override { delete this; }
+  void OnStarted(ServerContext*) override {
+    this->Finish(Status(StatusCode::UNIMPLEMENTED, ""));
+  }
+};
+
+template <class RequestType, class ResponseType>
+class CallbackUnaryHandler : public MethodHandler {
+ public:
+  CallbackUnaryHandler(
+      std::function<void(ServerContext*, const RequestType*, ResponseType*,
+                         experimental::ServerCallbackRpcController*)>
+          func)
+      : func_(func) {}
+  void RunHandler(const HandlerParameter& param) final {
+    // Arena allocate a controller structure (that includes request/response)
+    g_core_codegen_interface->grpc_call_ref(param.call->call());
+    auto* controller = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        param.call->call(), sizeof(ServerCallbackRpcControllerImpl)))
+        ServerCallbackRpcControllerImpl(
+            param.server_context, param.call,
+            static_cast<RequestType*>(param.request),
+            std::move(param.call_requester));
+    Status status = param.status;
+
+    if (status.ok()) {
+      // Call the actual function handler and expect the user to call finish
+      CatchingCallback(func_, param.server_context, controller->request(),
+                       controller->response(), controller);
+    } else {
+      // if deserialization failed, we need to fail the call
+      controller->Finish(status);
+    }
+  }
+
+  void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
+                    Status* status) final {
+    ByteBuffer buf;
+    buf.set_buffer(req);
+    auto* request = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call, sizeof(RequestType))) RequestType();
+    *status = SerializationTraits<RequestType>::Deserialize(&buf, request);
+    buf.Release();
+    if (status->ok()) {
+      return request;
+    }
+    request->~RequestType();
+    return nullptr;
+  }
+
+ private:
+  std::function<void(ServerContext*, const RequestType*, ResponseType*,
+                     experimental::ServerCallbackRpcController*)>
+      func_;
+
+  // The implementation class of ServerCallbackRpcController is a private member
+  // of CallbackUnaryHandler since it is never exposed anywhere, and this allows
+  // it to take advantage of CallbackUnaryHandler's friendships.
+  class ServerCallbackRpcControllerImpl
+      : public experimental::ServerCallbackRpcController {
+   public:
+    void Finish(Status s) override {
+      finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); },
+                      &finish_ops_);
+      if (!ctx_->sent_initial_metadata_) {
+        finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                        ctx_->initial_metadata_flags());
+        if (ctx_->compression_level_set()) {
+          finish_ops_.set_compression_level(ctx_->compression_level());
+        }
+        ctx_->sent_initial_metadata_ = true;
+      }
+      // The response is dropped if the status is not OK.
+      if (s.ok()) {
+        finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
+                                     finish_ops_.SendMessage(resp_));
+      } else {
+        finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
+      }
+      finish_ops_.set_core_cq_tag(&finish_tag_);
+      call_.PerformOps(&finish_ops_);
+    }
+
+    void SendInitialMetadata(std::function<void(bool)> f) override {
+      GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+      callbacks_outstanding_++;
+      // TODO(vjpai): Consider taking f as a move-capture if we adopt C++14
+      //              and if performance of this operation matters
+      meta_tag_.Set(call_.call(),
+                    [this, f](bool ok) {
+                      f(ok);
+                      MaybeDone();
+                    },
+                    &meta_ops_);
+      meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                    ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        meta_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+      meta_ops_.set_core_cq_tag(&meta_tag_);
+      call_.PerformOps(&meta_ops_);
+    }
+
+   private:
+    friend class CallbackUnaryHandler<RequestType, ResponseType>;
+
+    ServerCallbackRpcControllerImpl(ServerContext* ctx, Call* call,
+                                    const RequestType* req,
+                                    std::function<void()> call_requester)
+        : ctx_(ctx),
+          call_(*call),
+          req_(req),
+          call_requester_(std::move(call_requester)) {
+      ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, nullptr);
+    }
+
+    ~ServerCallbackRpcControllerImpl() { req_->~RequestType(); }
+
+    const RequestType* request() { return req_; }
+    ResponseType* response() { return &resp_; }
+
+    void MaybeDone() {
+      if (--callbacks_outstanding_ == 0) {
+        grpc_call* call = call_.call();
+        auto call_requester = std::move(call_requester_);
+        this->~ServerCallbackRpcControllerImpl();  // explicitly call destructor
+        g_core_codegen_interface->grpc_call_unref(call);
+        call_requester();
+      }
+    }
+
+    CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+    CallbackWithSuccessTag meta_tag_;
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpServerSendStatus>
+        finish_ops_;
+    CallbackWithSuccessTag finish_tag_;
+
+    ServerContext* ctx_;
+    Call call_;
+    const RequestType* req_;
+    ResponseType resp_;
+    std::function<void()> call_requester_;
+    std::atomic_int callbacks_outstanding_{
+        2};  // reserve for Finish and CompletionOp
+  };
+};
+
+template <class RequestType, class ResponseType>
+class CallbackClientStreamingHandler : public MethodHandler {
+ public:
+  CallbackClientStreamingHandler(
+      std::function<
+          experimental::ServerReadReactor<RequestType, ResponseType>*()>
+          func)
+      : func_(std::move(func)) {}
+  void RunHandler(const HandlerParameter& param) final {
+    // Arena allocate a reader structure (that includes response)
+    g_core_codegen_interface->grpc_call_ref(param.call->call());
+
+    experimental::ServerReadReactor<RequestType, ResponseType>* reactor =
+        param.status.ok()
+            ? CatchingReactorCreator<
+                  experimental::ServerReadReactor<RequestType, ResponseType>>(
+                  func_)
+            : nullptr;
+
+    if (reactor == nullptr) {
+      // if deserialization or reactor creator failed, we need to fail the call
+      reactor = new UnimplementedReadReactor<RequestType, ResponseType>;
+    }
+
+    auto* reader = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        param.call->call(), sizeof(ServerCallbackReaderImpl)))
+        ServerCallbackReaderImpl(param.server_context, param.call,
+                                 std::move(param.call_requester), reactor);
+
+    reader->BindReactor(reactor);
+    reactor->OnStarted(param.server_context, reader->response());
+    reader->MaybeDone();
+  }
+
+ private:
+  std::function<experimental::ServerReadReactor<RequestType, ResponseType>*()>
+      func_;
+
+  class ServerCallbackReaderImpl
+      : public experimental::ServerCallbackReader<RequestType> {
+   public:
+    void Finish(Status s) override {
+      finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); },
+                      &finish_ops_);
+      if (!ctx_->sent_initial_metadata_) {
+        finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                        ctx_->initial_metadata_flags());
+        if (ctx_->compression_level_set()) {
+          finish_ops_.set_compression_level(ctx_->compression_level());
+        }
+        ctx_->sent_initial_metadata_ = true;
+      }
+      // The response is dropped if the status is not OK.
+      if (s.ok()) {
+        finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_,
+                                     finish_ops_.SendMessage(resp_));
+      } else {
+        finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
+      }
+      finish_ops_.set_core_cq_tag(&finish_tag_);
+      call_.PerformOps(&finish_ops_);
+    }
+
+    void SendInitialMetadata() override {
+      GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+      callbacks_outstanding_++;
+      meta_tag_.Set(call_.call(),
+                    [this](bool ok) {
+                      reactor_->OnSendInitialMetadataDone(ok);
+                      MaybeDone();
+                    },
+                    &meta_ops_);
+      meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                    ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        meta_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+      meta_ops_.set_core_cq_tag(&meta_tag_);
+      call_.PerformOps(&meta_ops_);
+    }
+
+    void Read(RequestType* req) override {
+      callbacks_outstanding_++;
+      read_ops_.RecvMessage(req);
+      call_.PerformOps(&read_ops_);
+    }
+
+   private:
+    friend class CallbackClientStreamingHandler<RequestType, ResponseType>;
+
+    ServerCallbackReaderImpl(
+        ServerContext* ctx, Call* call, std::function<void()> call_requester,
+        experimental::ServerReadReactor<RequestType, ResponseType>* reactor)
+        : ctx_(ctx),
+          call_(*call),
+          call_requester_(std::move(call_requester)),
+          reactor_(reactor) {
+      ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, reactor);
+      read_tag_.Set(call_.call(),
+                    [this](bool ok) {
+                      reactor_->OnReadDone(ok);
+                      MaybeDone();
+                    },
+                    &read_ops_);
+      read_ops_.set_core_cq_tag(&read_tag_);
+    }
+
+    ~ServerCallbackReaderImpl() {}
+
+    ResponseType* response() { return &resp_; }
+
+    void MaybeDone() {
+      if (--callbacks_outstanding_ == 0) {
+        reactor_->OnDone();
+        grpc_call* call = call_.call();
+        auto call_requester = std::move(call_requester_);
+        this->~ServerCallbackReaderImpl();  // explicitly call destructor
+        g_core_codegen_interface->grpc_call_unref(call);
+        call_requester();
+      }
+    }
+
+    CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+    CallbackWithSuccessTag meta_tag_;
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpServerSendStatus>
+        finish_ops_;
+    CallbackWithSuccessTag finish_tag_;
+    CallOpSet<CallOpRecvMessage<RequestType>> read_ops_;
+    CallbackWithSuccessTag read_tag_;
+
+    ServerContext* ctx_;
+    Call call_;
+    ResponseType resp_;
+    std::function<void()> call_requester_;
+    experimental::ServerReadReactor<RequestType, ResponseType>* reactor_;
+    std::atomic_int callbacks_outstanding_{
+        3};  // reserve for OnStarted, Finish, and CompletionOp
+  };
+};
+
+template <class RequestType, class ResponseType>
+class CallbackServerStreamingHandler : public MethodHandler {
+ public:
+  CallbackServerStreamingHandler(
+      std::function<
+          experimental::ServerWriteReactor<RequestType, ResponseType>*()>
+          func)
+      : func_(std::move(func)) {}
+  void RunHandler(const HandlerParameter& param) final {
+    // Arena allocate a writer structure
+    g_core_codegen_interface->grpc_call_ref(param.call->call());
+
+    experimental::ServerWriteReactor<RequestType, ResponseType>* reactor =
+        param.status.ok()
+            ? CatchingReactorCreator<
+                  experimental::ServerWriteReactor<RequestType, ResponseType>>(
+                  func_)
+            : nullptr;
+
+    if (reactor == nullptr) {
+      // if deserialization or reactor creator failed, we need to fail the call
+      reactor = new UnimplementedWriteReactor<RequestType, ResponseType>;
+    }
+
+    auto* writer = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        param.call->call(), sizeof(ServerCallbackWriterImpl)))
+        ServerCallbackWriterImpl(param.server_context, param.call,
+                                 static_cast<RequestType*>(param.request),
+                                 std::move(param.call_requester), reactor);
+    writer->BindReactor(reactor);
+    reactor->OnStarted(param.server_context, writer->request());
+    writer->MaybeDone();
+  }
+
+  void* Deserialize(grpc_call* call, grpc_byte_buffer* req,
+                    Status* status) final {
+    ByteBuffer buf;
+    buf.set_buffer(req);
+    auto* request = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        call, sizeof(RequestType))) RequestType();
+    *status = SerializationTraits<RequestType>::Deserialize(&buf, request);
+    buf.Release();
+    if (status->ok()) {
+      return request;
+    }
+    request->~RequestType();
+    return nullptr;
+  }
+
+ private:
+  std::function<experimental::ServerWriteReactor<RequestType, ResponseType>*()>
+      func_;
+
+  class ServerCallbackWriterImpl
+      : public experimental::ServerCallbackWriter<ResponseType> {
+   public:
+    void Finish(Status s) override {
+      finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); },
+                      &finish_ops_);
+      finish_ops_.set_core_cq_tag(&finish_tag_);
+
+      if (!ctx_->sent_initial_metadata_) {
+        finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                        ctx_->initial_metadata_flags());
+        if (ctx_->compression_level_set()) {
+          finish_ops_.set_compression_level(ctx_->compression_level());
+        }
+        ctx_->sent_initial_metadata_ = true;
+      }
+      finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
+      call_.PerformOps(&finish_ops_);
+    }
+
+    void SendInitialMetadata() override {
+      GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+      callbacks_outstanding_++;
+      meta_tag_.Set(call_.call(),
+                    [this](bool ok) {
+                      reactor_->OnSendInitialMetadataDone(ok);
+                      MaybeDone();
+                    },
+                    &meta_ops_);
+      meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                    ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        meta_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+      meta_ops_.set_core_cq_tag(&meta_tag_);
+      call_.PerformOps(&meta_ops_);
+    }
+
+    void Write(const ResponseType* resp, WriteOptions options) override {
+      callbacks_outstanding_++;
+      if (options.is_last_message()) {
+        options.set_buffer_hint();
+      }
+      if (!ctx_->sent_initial_metadata_) {
+        write_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                       ctx_->initial_metadata_flags());
+        if (ctx_->compression_level_set()) {
+          write_ops_.set_compression_level(ctx_->compression_level());
+        }
+        ctx_->sent_initial_metadata_ = true;
+      }
+      // TODO(vjpai): don't assert
+      GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok());
+      call_.PerformOps(&write_ops_);
+    }
+
+    void WriteAndFinish(const ResponseType* resp, WriteOptions options,
+                        Status s) override {
+      // This combines the write into the finish callback
+      // Don't send any message if the status is bad
+      if (s.ok()) {
+        // TODO(vjpai): don't assert
+        GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok());
+      }
+      Finish(std::move(s));
+    }
+
+   private:
+    friend class CallbackServerStreamingHandler<RequestType, ResponseType>;
+
+    ServerCallbackWriterImpl(
+        ServerContext* ctx, Call* call, const RequestType* req,
+        std::function<void()> call_requester,
+        experimental::ServerWriteReactor<RequestType, ResponseType>* reactor)
+        : ctx_(ctx),
+          call_(*call),
+          req_(req),
+          call_requester_(std::move(call_requester)),
+          reactor_(reactor) {
+      ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, reactor);
+      write_tag_.Set(call_.call(),
+                     [this](bool ok) {
+                       reactor_->OnWriteDone(ok);
+                       MaybeDone();
+                     },
+                     &write_ops_);
+      write_ops_.set_core_cq_tag(&write_tag_);
+    }
+    ~ServerCallbackWriterImpl() { req_->~RequestType(); }
+
+    const RequestType* request() { return req_; }
+
+    void MaybeDone() {
+      if (--callbacks_outstanding_ == 0) {
+        reactor_->OnDone();
+        grpc_call* call = call_.call();
+        auto call_requester = std::move(call_requester_);
+        this->~ServerCallbackWriterImpl();  // explicitly call destructor
+        g_core_codegen_interface->grpc_call_unref(call);
+        call_requester();
+      }
+    }
+
+    CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+    CallbackWithSuccessTag meta_tag_;
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpServerSendStatus>
+        finish_ops_;
+    CallbackWithSuccessTag finish_tag_;
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
+    CallbackWithSuccessTag write_tag_;
+
+    ServerContext* ctx_;
+    Call call_;
+    const RequestType* req_;
+    std::function<void()> call_requester_;
+    experimental::ServerWriteReactor<RequestType, ResponseType>* reactor_;
+    std::atomic_int callbacks_outstanding_{
+        3};  // reserve for OnStarted, Finish, and CompletionOp
+  };
+};
+
+template <class RequestType, class ResponseType>
+class CallbackBidiHandler : public MethodHandler {
+ public:
+  CallbackBidiHandler(
+      std::function<
+          experimental::ServerBidiReactor<RequestType, ResponseType>*()>
+          func)
+      : func_(std::move(func)) {}
+  void RunHandler(const HandlerParameter& param) final {
+    g_core_codegen_interface->grpc_call_ref(param.call->call());
+
+    experimental::ServerBidiReactor<RequestType, ResponseType>* reactor =
+        param.status.ok()
+            ? CatchingReactorCreator<
+                  experimental::ServerBidiReactor<RequestType, ResponseType>>(
+                  func_)
+            : nullptr;
+
+    if (reactor == nullptr) {
+      // if deserialization or reactor creator failed, we need to fail the call
+      reactor = new UnimplementedBidiReactor<RequestType, ResponseType>;
+    }
+
+    auto* stream = new (g_core_codegen_interface->grpc_call_arena_alloc(
+        param.call->call(), sizeof(ServerCallbackReaderWriterImpl)))
+        ServerCallbackReaderWriterImpl(param.server_context, param.call,
+                                       std::move(param.call_requester),
+                                       reactor);
+
+    stream->BindReactor(reactor);
+    reactor->OnStarted(param.server_context);
+    stream->MaybeDone();
+  }
+
+ private:
+  std::function<experimental::ServerBidiReactor<RequestType, ResponseType>*()>
+      func_;
+
+  class ServerCallbackReaderWriterImpl
+      : public experimental::ServerCallbackReaderWriter<RequestType,
+                                                        ResponseType> {
+   public:
+    void Finish(Status s) override {
+      finish_tag_.Set(call_.call(), [this](bool) { MaybeDone(); },
+                      &finish_ops_);
+      finish_ops_.set_core_cq_tag(&finish_tag_);
+
+      if (!ctx_->sent_initial_metadata_) {
+        finish_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                        ctx_->initial_metadata_flags());
+        if (ctx_->compression_level_set()) {
+          finish_ops_.set_compression_level(ctx_->compression_level());
+        }
+        ctx_->sent_initial_metadata_ = true;
+      }
+      finish_ops_.ServerSendStatus(&ctx_->trailing_metadata_, s);
+      call_.PerformOps(&finish_ops_);
+    }
+
+    void SendInitialMetadata() override {
+      GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+      callbacks_outstanding_++;
+      meta_tag_.Set(call_.call(),
+                    [this](bool ok) {
+                      reactor_->OnSendInitialMetadataDone(ok);
+                      MaybeDone();
+                    },
+                    &meta_ops_);
+      meta_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                    ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        meta_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+      meta_ops_.set_core_cq_tag(&meta_tag_);
+      call_.PerformOps(&meta_ops_);
+    }
+
+    void Write(const ResponseType* resp, WriteOptions options) override {
+      callbacks_outstanding_++;
+      if (options.is_last_message()) {
+        options.set_buffer_hint();
+      }
+      if (!ctx_->sent_initial_metadata_) {
+        write_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                       ctx_->initial_metadata_flags());
+        if (ctx_->compression_level_set()) {
+          write_ops_.set_compression_level(ctx_->compression_level());
+        }
+        ctx_->sent_initial_metadata_ = true;
+      }
+      // TODO(vjpai): don't assert
+      GPR_CODEGEN_ASSERT(write_ops_.SendMessage(*resp, options).ok());
+      call_.PerformOps(&write_ops_);
+    }
+
+    void WriteAndFinish(const ResponseType* resp, WriteOptions options,
+                        Status s) override {
+      // Don't send any message if the status is bad
+      if (s.ok()) {
+        // TODO(vjpai): don't assert
+        GPR_CODEGEN_ASSERT(finish_ops_.SendMessage(*resp, options).ok());
+      }
+      Finish(std::move(s));
+    }
+
+    void Read(RequestType* req) override {
+      callbacks_outstanding_++;
+      read_ops_.RecvMessage(req);
+      call_.PerformOps(&read_ops_);
+    }
+
+   private:
+    friend class CallbackBidiHandler<RequestType, ResponseType>;
+
+    ServerCallbackReaderWriterImpl(
+        ServerContext* ctx, Call* call, std::function<void()> call_requester,
+        experimental::ServerBidiReactor<RequestType, ResponseType>* reactor)
+        : ctx_(ctx),
+          call_(*call),
+          call_requester_(std::move(call_requester)),
+          reactor_(reactor) {
+      ctx_->BeginCompletionOp(call, [this](bool) { MaybeDone(); }, reactor);
+      write_tag_.Set(call_.call(),
+                     [this](bool ok) {
+                       reactor_->OnWriteDone(ok);
+                       MaybeDone();
+                     },
+                     &write_ops_);
+      write_ops_.set_core_cq_tag(&write_tag_);
+      read_tag_.Set(call_.call(),
+                    [this](bool ok) {
+                      reactor_->OnReadDone(ok);
+                      MaybeDone();
+                    },
+                    &read_ops_);
+      read_ops_.set_core_cq_tag(&read_tag_);
+    }
+    ~ServerCallbackReaderWriterImpl() {}
+
+    void MaybeDone() {
+      if (--callbacks_outstanding_ == 0) {
+        reactor_->OnDone();
+        grpc_call* call = call_.call();
+        auto call_requester = std::move(call_requester_);
+        this->~ServerCallbackReaderWriterImpl();  // explicitly call destructor
+        g_core_codegen_interface->grpc_call_unref(call);
+        call_requester();
+      }
+    }
+
+    CallOpSet<CallOpSendInitialMetadata> meta_ops_;
+    CallbackWithSuccessTag meta_tag_;
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
+              CallOpServerSendStatus>
+        finish_ops_;
+    CallbackWithSuccessTag finish_tag_;
+    CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
+    CallbackWithSuccessTag write_tag_;
+    CallOpSet<CallOpRecvMessage<RequestType>> read_ops_;
+    CallbackWithSuccessTag read_tag_;
+
+    ServerContext* ctx_;
+    Call call_;
+    std::function<void()> call_requester_;
+    experimental::ServerBidiReactor<RequestType, ResponseType>* reactor_;
+    std::atomic_int callbacks_outstanding_{
+        3};  // reserve for OnStarted, Finish, and CompletionOp
+  };
+};
+
+}  // namespace internal
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SERVER_CALLBACK_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/server_context.h b/third_party/grpc/include/grpcpp/impl/codegen/server_context.h
new file mode 100644
index 0000000..affe61b
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/server_context.h
@@ -0,0 +1,370 @@
+/*
+ *
+ * Copyright 2015 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_SERVER_CONTEXT_H
+#define GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include <grpc/impl/codegen/compression_types.h>
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/call_op_set.h>
+#include <grpcpp/impl/codegen/callback_common.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/create_auth_context.h>
+#include <grpcpp/impl/codegen/metadata_map.h>
+#include <grpcpp/impl/codegen/security/auth_context.h>
+#include <grpcpp/impl/codegen/server_interceptor.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+#include <grpcpp/impl/codegen/time.h>
+
+struct grpc_metadata;
+struct grpc_call;
+struct census_context;
+
+namespace grpc {
+class ClientContext;
+template <class W, class R>
+class ServerAsyncReader;
+template <class W>
+class ServerAsyncWriter;
+template <class W>
+class ServerAsyncResponseWriter;
+template <class W, class R>
+class ServerAsyncReaderWriter;
+template <class R>
+class ServerReader;
+template <class W>
+class ServerWriter;
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody;
+template <class ServiceType, class RequestType, class ResponseType>
+class RpcMethodHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ClientStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class ServerStreamingHandler;
+template <class ServiceType, class RequestType, class ResponseType>
+class BidiStreamingHandler;
+template <class RequestType, class ResponseType>
+class CallbackUnaryHandler;
+template <class RequestType, class ResponseType>
+class CallbackClientStreamingHandler;
+template <class RequestType, class ResponseType>
+class CallbackServerStreamingHandler;
+template <class RequestType, class ResponseType>
+class CallbackBidiHandler;
+template <class Streamer, bool WriteNeeded>
+class TemplatedBidiStreamingHandler;
+template <StatusCode code>
+class ErrorMethodHandler;
+class Call;
+class ServerReactor;
+}  // namespace internal
+
+class CompletionQueue;
+class Server;
+class ServerInterface;
+
+namespace testing {
+class InteropServerContextInspector;
+class ServerContextTestSpouse;
+}  // namespace testing
+
+/// A ServerContext allows the person implementing a service handler to:
+///
+/// - Add custom initial and trailing metadata key-value pairs that will
+///   propagated to the client side.
+/// - Control call settings such as compression and authentication.
+/// - Access metadata coming from the client.
+/// - Get performance metrics (ie, census).
+///
+/// Context settings are only relevant to the call handler they are supplied to,
+/// that is to say, they aren't sticky across multiple calls. Some of these
+/// settings, such as the compression options, can be made persistent at server
+/// construction time by specifying the appropriate \a ChannelArguments
+/// to a \a grpc::ServerBuilder, via \a ServerBuilder::AddChannelArgument.
+///
+/// \warning ServerContext instances should \em not be reused across rpcs.
+class ServerContext {
+ public:
+  ServerContext();  // for async calls
+  ~ServerContext();
+
+  /// Return the deadline for the server call.
+  std::chrono::system_clock::time_point deadline() const {
+    return Timespec2Timepoint(deadline_);
+  }
+
+  /// Return a \a gpr_timespec representation of the server call's deadline.
+  gpr_timespec raw_deadline() const { return deadline_; }
+
+  /// Add the (\a key, \a value) pair to the initial metadata
+  /// associated with a server call. These are made available at the client side
+  /// by the \a grpc::ClientContext::GetServerInitialMetadata() method.
+  ///
+  /// \warning This method should only be called before sending initial metadata
+  /// to the client (which can happen explicitly, or implicitly when sending a
+  /// a response message or status to the client).
+  ///
+  /// \param key The metadata key. If \a value is binary data, it must
+  /// end in "-bin".
+  /// \param value The metadata value. If its value is binary, the key name
+  /// must end in "-bin".
+  ///
+  /// Metadata must conform to the following format:
+  /// Custom-Metadata -> Binary-Header / ASCII-Header
+  /// Binary-Header -> {Header-Name "-bin" } {binary value}
+  /// ASCII-Header -> Header-Name ASCII-Value
+  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
+  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
+  void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
+
+  /// Add the (\a key, \a value) pair to the initial metadata
+  /// associated with a server call. These are made available at the client
+  /// side by the \a grpc::ClientContext::GetServerTrailingMetadata() method.
+  ///
+  /// \warning This method should only be called before sending trailing
+  /// metadata to the client (which happens when the call is finished and a
+  /// status is sent to the client).
+  ///
+  /// \param key The metadata key. If \a value is binary data,
+  /// it must end in "-bin".
+  /// \param value The metadata value. If its value is binary, the key name
+  /// must end in "-bin".
+  ///
+  /// Metadata must conform to the following format:
+  /// Custom-Metadata -> Binary-Header / ASCII-Header
+  /// Binary-Header -> {Header-Name "-bin" } {binary value}
+  /// ASCII-Header -> Header-Name ASCII-Value
+  /// Header-Name -> 1*( %x30-39 / %x61-7A / "_" / "-" / ".") ; 0-9 a-z _ - .
+  /// ASCII-Value -> 1*( %x20-%x7E ) ; space and printable ASCII
+  void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
+
+  /// IsCancelled is always safe to call when using sync or callback API.
+  /// When using async API, it is only safe to call IsCancelled after
+  /// the AsyncNotifyWhenDone tag has been delivered.
+  bool IsCancelled() const;
+
+  /// Cancel the Call from the server. This is a best-effort API and
+  /// depending on when it is called, the RPC may still appear successful to
+  /// the client.
+  /// For example, if TryCancel() is called on a separate thread, it might race
+  /// with the server handler which might return success to the client before
+  /// TryCancel() was even started by the thread.
+  ///
+  /// It is the caller's responsibility to prevent such races and ensure that if
+  /// TryCancel() is called, the serverhandler must return Status::CANCELLED.
+  /// The only exception is that if the serverhandler is already returning an
+  /// error status code, it is ok to not return Status::CANCELLED even if
+  /// TryCancel() was called.
+  ///
+  /// Note that TryCancel() does not change any of the tags that are pending
+  /// on the completion queue. All pending tags will still be delivered
+  /// (though their ok result may reflect the effect of cancellation).
+  void TryCancel() const;
+
+  /// Return a collection of initial metadata key-value pairs sent from the
+  /// client. Note that keys may happen more than
+  /// once (ie, a \a std::multimap is returned).
+  ///
+  /// It is safe to use this method after initial metadata has been received,
+  /// Calls always begin with the client sending initial metadata, so this is
+  /// safe to access as soon as the call has begun on the server side.
+  ///
+  /// \return A multimap of initial metadata key-value pairs from the server.
+  const std::multimap<grpc::string_ref, grpc::string_ref>& client_metadata()
+      const {
+    return *client_metadata_.map();
+  }
+
+  /// Return the compression algorithm to be used by the server call.
+  grpc_compression_level compression_level() const {
+    return compression_level_;
+  }
+
+  /// Set \a level to be the compression level used for the server call.
+  ///
+  /// \param level The compression level used for the server call.
+  void set_compression_level(grpc_compression_level level) {
+    compression_level_set_ = true;
+    compression_level_ = level;
+  }
+
+  /// Return a bool indicating whether the compression level for this call
+  /// has been set (either implicitly or through a previous call to
+  /// \a set_compression_level.
+  bool compression_level_set() const { return compression_level_set_; }
+
+  /// Return the compression algorithm the server call will request be used.
+  /// Note that the gRPC runtime may decide to ignore this request, for example,
+  /// due to resource constraints, or if the server is aware the client doesn't
+  /// support the requested algorithm.
+  grpc_compression_algorithm compression_algorithm() const {
+    return compression_algorithm_;
+  }
+  /// Set \a algorithm to be the compression algorithm used for the server call.
+  ///
+  /// \param algorithm The compression algorithm used for the server call.
+  void set_compression_algorithm(grpc_compression_algorithm algorithm);
+
+  /// Set the serialized load reporting costs in \a cost_data for the call.
+  void SetLoadReportingCosts(const std::vector<grpc::string>& cost_data);
+
+  /// Return the authentication context for this server call.
+  ///
+  /// \see grpc::AuthContext.
+  std::shared_ptr<const AuthContext> auth_context() const {
+    if (auth_context_.get() == nullptr) {
+      auth_context_ = CreateAuthContext(call_);
+    }
+    return auth_context_;
+  }
+
+  /// Return the peer uri in a string.
+  /// WARNING: this value is never authenticated or subject to any security
+  /// related code. It must not be used for any authentication related
+  /// functionality. Instead, use auth_context.
+  grpc::string peer() const;
+
+  /// Get the census context associated with this server call.
+  const struct census_context* census_context() const;
+
+  /// Async only. Has to be called before the rpc starts.
+  /// Returns the tag in completion queue when the rpc finishes.
+  /// IsCancelled() can then be called to check whether the rpc was cancelled.
+  /// TODO(vjpai): Fix this so that the tag is returned even if the call never
+  /// starts (https://github.com/grpc/grpc/issues/10136).
+  void AsyncNotifyWhenDone(void* tag) {
+    has_notify_when_done_tag_ = true;
+    async_notify_when_done_tag_ = tag;
+  }
+
+  /// Should be used for framework-level extensions only.
+  /// Applications never need to call this method.
+  grpc_call* c_call() { return call_; }
+
+ private:
+  friend class ::grpc::testing::InteropServerContextInspector;
+  friend class ::grpc::testing::ServerContextTestSpouse;
+  friend class ::grpc::ServerInterface;
+  friend class ::grpc::Server;
+  template <class W, class R>
+  friend class ::grpc::ServerAsyncReader;
+  template <class W>
+  friend class ::grpc::ServerAsyncWriter;
+  template <class W>
+  friend class ::grpc::ServerAsyncResponseWriter;
+  template <class W, class R>
+  friend class ::grpc::ServerAsyncReaderWriter;
+  template <class R>
+  friend class ::grpc::ServerReader;
+  template <class W>
+  friend class ::grpc::ServerWriter;
+  template <class W, class R>
+  friend class ::grpc::internal::ServerReaderWriterBody;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc::internal::RpcMethodHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc::internal::ClientStreamingHandler;
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class ::grpc::internal::ServerStreamingHandler;
+  template <class Streamer, bool WriteNeeded>
+  friend class ::grpc::internal::TemplatedBidiStreamingHandler;
+  template <class RequestType, class ResponseType>
+  friend class ::grpc::internal::CallbackUnaryHandler;
+  template <class RequestType, class ResponseType>
+  friend class ::grpc::internal::CallbackClientStreamingHandler;
+  template <class RequestType, class ResponseType>
+  friend class ::grpc::internal::CallbackServerStreamingHandler;
+  template <class RequestType, class ResponseType>
+  friend class ::grpc::internal::CallbackBidiHandler;
+  template <StatusCode code>
+  friend class internal::ErrorMethodHandler;
+  friend class ::grpc::ClientContext;
+
+  /// Prevent copying.
+  ServerContext(const ServerContext&);
+  ServerContext& operator=(const ServerContext&);
+
+  class CompletionOp;
+
+  void BeginCompletionOp(internal::Call* call,
+                         std::function<void(bool)> callback,
+                         internal::ServerReactor* reactor);
+  /// Return the tag queued by BeginCompletionOp()
+  internal::CompletionQueueTag* GetCompletionOpTag();
+
+  ServerContext(gpr_timespec deadline, grpc_metadata_array* arr);
+
+  void set_call(grpc_call* call) { call_ = call; }
+
+  void BindDeadlineAndMetadata(gpr_timespec deadline, grpc_metadata_array* arr);
+
+  void Clear();
+
+  void Setup(gpr_timespec deadline);
+
+  uint32_t initial_metadata_flags() const { return 0; }
+
+  experimental::ServerRpcInfo* set_server_rpc_info(
+      const char* method, internal::RpcMethod::RpcType type,
+      const std::vector<
+          std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>&
+          creators) {
+    if (creators.size() != 0) {
+      rpc_info_ = new experimental::ServerRpcInfo(this, method, type);
+      rpc_info_->RegisterInterceptors(creators);
+    }
+    return rpc_info_;
+  }
+
+  CompletionOp* completion_op_;
+  bool has_notify_when_done_tag_;
+  void* async_notify_when_done_tag_;
+  internal::CallbackWithSuccessTag completion_tag_;
+
+  gpr_timespec deadline_;
+  grpc_call* call_;
+  CompletionQueue* cq_;
+  bool sent_initial_metadata_;
+  mutable std::shared_ptr<const AuthContext> auth_context_;
+  mutable internal::MetadataMap client_metadata_;
+  std::multimap<grpc::string, grpc::string> initial_metadata_;
+  std::multimap<grpc::string, grpc::string> trailing_metadata_;
+
+  bool compression_level_set_;
+  grpc_compression_level compression_level_;
+  grpc_compression_algorithm compression_algorithm_;
+
+  internal::CallOpSet<internal::CallOpSendInitialMetadata,
+                      internal::CallOpSendMessage>
+      pending_ops_;
+  bool has_pending_ops_;
+
+  experimental::ServerRpcInfo* rpc_info_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SERVER_CONTEXT_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/server_interceptor.h b/third_party/grpc/include/grpcpp/impl/codegen/server_interceptor.h
new file mode 100644
index 0000000..3e71b3f
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/server_interceptor.h
@@ -0,0 +1,143 @@
+/*
+ *
+ * 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_SERVER_INTERCEPTOR_H
+#define GRPCPP_IMPL_CODEGEN_SERVER_INTERCEPTOR_H
+
+#include <atomic>
+#include <vector>
+
+#include <grpcpp/impl/codegen/interceptor.h>
+#include <grpcpp/impl/codegen/rpc_method.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+namespace grpc {
+
+class ServerContext;
+
+namespace internal {
+class InterceptorBatchMethodsImpl;
+}
+
+namespace experimental {
+class ServerRpcInfo;
+
+// A factory interface for creation of server interceptors. A vector of
+// factories can be provided to ServerBuilder which will be used to create a new
+// vector of server interceptors per RPC. Server interceptor authors should
+// create a subclass of ServerInterceptorFactorInterface which creates objects
+// of their interceptors.
+class ServerInterceptorFactoryInterface {
+ public:
+  virtual ~ServerInterceptorFactoryInterface() {}
+  // Returns a pointer to an Interceptor object on successful creation, nullptr
+  // otherwise. If nullptr is returned, this server interceptor factory is
+  // ignored for the purposes of that RPC.
+  virtual Interceptor* CreateServerInterceptor(ServerRpcInfo* info) = 0;
+};
+
+/// ServerRpcInfo represents the state of a particular RPC as it
+/// appears to an interceptor. It is created and owned by the library and
+/// passed to the CreateServerInterceptor method of the application's
+/// ServerInterceptorFactoryInterface implementation
+class ServerRpcInfo {
+ public:
+  /// Type categorizes RPCs by unary or streaming type
+  enum class Type { UNARY, CLIENT_STREAMING, SERVER_STREAMING, BIDI_STREAMING };
+
+  ~ServerRpcInfo(){};
+
+  // Delete all copy and move constructors and assignments
+  ServerRpcInfo(const ServerRpcInfo&) = delete;
+  ServerRpcInfo& operator=(const ServerRpcInfo&) = delete;
+  ServerRpcInfo(ServerRpcInfo&&) = delete;
+  ServerRpcInfo& operator=(ServerRpcInfo&&) = delete;
+
+  // Getter methods
+
+  /// Return the fully-specified method name
+  const char* method() const { return method_; }
+
+  /// Return the type of the RPC (unary or a streaming flavor)
+  Type type() const { return type_; }
+
+  /// Return a pointer to the underlying ServerContext structure associated
+  /// with the RPC to support features that apply to it
+  grpc::ServerContext* server_context() { return ctx_; }
+
+ private:
+  static_assert(Type::UNARY ==
+                    static_cast<Type>(internal::RpcMethod::NORMAL_RPC),
+                "violated expectation about Type enum");
+  static_assert(Type::CLIENT_STREAMING ==
+                    static_cast<Type>(internal::RpcMethod::CLIENT_STREAMING),
+                "violated expectation about Type enum");
+  static_assert(Type::SERVER_STREAMING ==
+                    static_cast<Type>(internal::RpcMethod::SERVER_STREAMING),
+                "violated expectation about Type enum");
+  static_assert(Type::BIDI_STREAMING ==
+                    static_cast<Type>(internal::RpcMethod::BIDI_STREAMING),
+                "violated expectation about Type enum");
+
+  ServerRpcInfo(grpc::ServerContext* ctx, const char* method,
+                internal::RpcMethod::RpcType type)
+      : ctx_(ctx), method_(method), type_(static_cast<Type>(type)) {
+    ref_.store(1);
+  }
+
+  // Runs interceptor at pos \a pos.
+  void RunInterceptor(
+      experimental::InterceptorBatchMethods* interceptor_methods, size_t pos) {
+    GPR_CODEGEN_ASSERT(pos < interceptors_.size());
+    interceptors_[pos]->Intercept(interceptor_methods);
+  }
+
+  void RegisterInterceptors(
+      const std::vector<
+          std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>&
+          creators) {
+    for (const auto& creator : creators) {
+      auto* interceptor = creator->CreateServerInterceptor(this);
+      if (interceptor != nullptr) {
+        interceptors_.push_back(
+            std::unique_ptr<experimental::Interceptor>(interceptor));
+      }
+    }
+  }
+
+  void Ref() { ref_++; }
+  void Unref() {
+    if (--ref_ == 0) {
+      delete this;
+    }
+  }
+
+  grpc::ServerContext* ctx_ = nullptr;
+  const char* method_ = nullptr;
+  const Type type_;
+  std::atomic_int ref_;
+  std::vector<std::unique_ptr<experimental::Interceptor>> interceptors_;
+
+  friend class internal::InterceptorBatchMethodsImpl;
+  friend class grpc::ServerContext;
+};
+
+}  // namespace experimental
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SERVER_INTERCEPTOR_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/server_interface.h b/third_party/grpc/include/grpcpp/impl/codegen/server_interface.h
new file mode 100644
index 0000000..e0e2629
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/server_interface.h
@@ -0,0 +1,362 @@
+/*
+ *
+ * Copyright 2015 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_SERVER_INTERFACE_H
+#define GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/byte_buffer.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/call_hook.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+#include <grpcpp/impl/codegen/server_context.h>
+
+namespace grpc {
+
+class AsyncGenericService;
+class Channel;
+class GenericServerContext;
+class ServerCompletionQueue;
+class ServerContext;
+class ServerCredentials;
+class Service;
+
+extern CoreCodegenInterface* g_core_codegen_interface;
+
+/// Models a gRPC server.
+///
+/// Servers are configured and started via \a grpc::ServerBuilder.
+namespace internal {
+class ServerAsyncStreamingInterface;
+}  // namespace internal
+
+class ServerInterface : public internal::CallHook {
+ public:
+  virtual ~ServerInterface() {}
+
+  /// \a Shutdown does the following things:
+  ///
+  /// 1. Shutdown the server: deactivate all listening ports, mark it in
+  ///    "shutdown mode" so that further call Request's or incoming RPC matches
+  ///    are no longer allowed. Also return all Request'ed-but-not-yet-active
+  ///    calls as failed (!ok). This refers to calls that have been requested
+  ///    at the server by the server-side library or application code but that
+  ///    have not yet been matched to incoming RPCs from the client. Note that
+  ///    this would even include default calls added automatically by the gRPC
+  ///    C++ API without the user's input (e.g., "Unimplemented RPC method")
+  ///
+  /// 2. Block until all rpc method handlers invoked automatically by the sync
+  ///    API finish.
+  ///
+  /// 3. If all pending calls complete (and all their operations are
+  ///    retrieved by Next) before \a deadline expires, this finishes
+  ///    gracefully. Otherwise, forcefully cancel all pending calls associated
+  ///    with the server after \a deadline expires. In the case of the sync API,
+  ///    if the RPC function for a streaming call has already been started and
+  ///    takes a week to complete, the RPC function won't be forcefully
+  ///    terminated (since that would leave state corrupt and incomplete) and
+  ///    the method handler will just keep running (which will prevent the
+  ///    server from completing the "join" operation that it needs to do at
+  ///    shutdown time).
+  ///
+  /// All completion queue associated with the server (for example, for async
+  /// serving) must be shutdown *after* this method has returned:
+  /// See \a ServerBuilder::AddCompletionQueue for details.
+  /// They must also be drained (by repeated Next) after being shutdown.
+  ///
+  /// \param deadline How long to wait until pending rpcs are forcefully
+  /// terminated.
+  template <class T>
+  void Shutdown(const T& deadline) {
+    ShutdownInternal(TimePoint<T>(deadline).raw_time());
+  }
+
+  /// Shutdown the server without a deadline and forced cancellation.
+  ///
+  /// All completion queue associated with the server (for example, for async
+  /// serving) must be shutdown *after* this method has returned:
+  /// See \a ServerBuilder::AddCompletionQueue for details.
+  void Shutdown() {
+    ShutdownInternal(
+        g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_MONOTONIC));
+  }
+
+  /// Block waiting for all work to complete.
+  ///
+  /// \warning The server must be either shutting down or some other thread must
+  /// call \a Shutdown for this function to ever return.
+  virtual void Wait() = 0;
+
+ protected:
+  friend class ::grpc::Service;
+
+  /// Register a service. This call does not take ownership of the service.
+  /// The service must exist for the lifetime of the Server instance.
+  virtual bool RegisterService(const grpc::string* host, Service* service) = 0;
+
+  /// Register a generic service. This call does not take ownership of the
+  /// service. The service must exist for the lifetime of the Server instance.
+  virtual void RegisterAsyncGenericService(AsyncGenericService* service) = 0;
+
+  /// Tries to bind \a server to the given \a addr.
+  ///
+  /// It can be invoked multiple times.
+  ///
+  /// \param addr The address to try to bind to the server (eg, localhost:1234,
+  /// 192.168.1.1:31416, [::1]:27182, etc.).
+  /// \params creds The credentials associated with the server.
+  ///
+  /// \return bound port number on sucess, 0 on failure.
+  ///
+  /// \warning It's an error to call this method on an already started server.
+  virtual int AddListeningPort(const grpc::string& addr,
+                               ServerCredentials* creds) = 0;
+
+  /// Start the server.
+  ///
+  /// \param cqs Completion queues for handling asynchronous services. The
+  /// caller is required to keep all completion queues live until the server is
+  /// destroyed.
+  /// \param num_cqs How many completion queues does \a cqs hold.
+  virtual void Start(ServerCompletionQueue** cqs, size_t num_cqs) = 0;
+
+  virtual void ShutdownInternal(gpr_timespec deadline) = 0;
+
+  virtual int max_receive_message_size() const = 0;
+
+  virtual grpc_server* server() = 0;
+
+  virtual void PerformOpsOnCall(internal::CallOpSetInterface* ops,
+                                internal::Call* call) = 0;
+
+  class BaseAsyncRequest : public internal::CompletionQueueTag {
+   public:
+    BaseAsyncRequest(ServerInterface* server, ServerContext* context,
+                     internal::ServerAsyncStreamingInterface* stream,
+                     CompletionQueue* call_cq,
+                     ServerCompletionQueue* notification_cq, void* tag,
+                     bool delete_on_finalize);
+    virtual ~BaseAsyncRequest();
+
+    bool FinalizeResult(void** tag, bool* status) override;
+
+   private:
+    void ContinueFinalizeResultAfterInterception();
+
+   protected:
+    ServerInterface* const server_;
+    ServerContext* const context_;
+    internal::ServerAsyncStreamingInterface* const stream_;
+    CompletionQueue* const call_cq_;
+    ServerCompletionQueue* const notification_cq_;
+    void* const tag_;
+    const bool delete_on_finalize_;
+    grpc_call* call_;
+    internal::Call call_wrapper_;
+    internal::InterceptorBatchMethodsImpl interceptor_methods_;
+    bool done_intercepting_;
+  };
+
+  /// RegisteredAsyncRequest is not part of the C++ API
+  class RegisteredAsyncRequest : public BaseAsyncRequest {
+   public:
+    RegisteredAsyncRequest(ServerInterface* server, ServerContext* context,
+                           internal::ServerAsyncStreamingInterface* stream,
+                           CompletionQueue* call_cq,
+                           ServerCompletionQueue* notification_cq, void* tag,
+                           const char* name, internal::RpcMethod::RpcType type);
+
+    virtual bool FinalizeResult(void** tag, bool* status) override {
+      /* If we are done intercepting, then there is nothing more for us to do */
+      if (done_intercepting_) {
+        return BaseAsyncRequest::FinalizeResult(tag, status);
+      }
+      call_wrapper_ = internal::Call(
+          call_, server_, call_cq_, server_->max_receive_message_size(),
+          context_->set_server_rpc_info(name_, type_,
+                                        *server_->interceptor_creators()));
+      return BaseAsyncRequest::FinalizeResult(tag, status);
+    }
+
+   protected:
+    void IssueRequest(void* registered_method, grpc_byte_buffer** payload,
+                      ServerCompletionQueue* notification_cq);
+    const char* name_;
+    const internal::RpcMethod::RpcType type_;
+  };
+
+  class NoPayloadAsyncRequest final : public RegisteredAsyncRequest {
+   public:
+    NoPayloadAsyncRequest(internal::RpcServiceMethod* registered_method,
+                          ServerInterface* server, ServerContext* context,
+                          internal::ServerAsyncStreamingInterface* stream,
+                          CompletionQueue* call_cq,
+                          ServerCompletionQueue* notification_cq, void* tag)
+        : RegisteredAsyncRequest(
+              server, context, stream, call_cq, notification_cq, tag,
+              registered_method->name(), registered_method->method_type()) {
+      IssueRequest(registered_method->server_tag(), nullptr, notification_cq);
+    }
+
+    // uses RegisteredAsyncRequest::FinalizeResult
+  };
+
+  template <class Message>
+  class PayloadAsyncRequest final : public RegisteredAsyncRequest {
+   public:
+    PayloadAsyncRequest(internal::RpcServiceMethod* registered_method,
+                        ServerInterface* server, ServerContext* context,
+                        internal::ServerAsyncStreamingInterface* stream,
+                        CompletionQueue* call_cq,
+                        ServerCompletionQueue* notification_cq, void* tag,
+                        Message* request)
+        : RegisteredAsyncRequest(
+              server, context, stream, call_cq, notification_cq, tag,
+              registered_method->name(), registered_method->method_type()),
+          registered_method_(registered_method),
+          server_(server),
+          context_(context),
+          stream_(stream),
+          call_cq_(call_cq),
+          notification_cq_(notification_cq),
+          tag_(tag),
+          request_(request) {
+      IssueRequest(registered_method->server_tag(), payload_.bbuf_ptr(),
+                   notification_cq);
+    }
+
+    ~PayloadAsyncRequest() {
+      payload_.Release();  // We do not own the payload_
+    }
+
+    bool FinalizeResult(void** tag, bool* status) override {
+      /* If we are done intercepting, then there is nothing more for us to do */
+      if (done_intercepting_) {
+        return RegisteredAsyncRequest::FinalizeResult(tag, status);
+      }
+      if (*status) {
+        if (!payload_.Valid() || !SerializationTraits<Message>::Deserialize(
+                                      payload_.bbuf_ptr(), request_)
+                                      .ok()) {
+          // If deserialization fails, we cancel the call and instantiate
+          // a new instance of ourselves to request another call.  We then
+          // return false, which prevents the call from being returned to
+          // the application.
+          g_core_codegen_interface->grpc_call_cancel_with_status(
+              call_, GRPC_STATUS_INTERNAL, "Unable to parse request", nullptr);
+          g_core_codegen_interface->grpc_call_unref(call_);
+          new PayloadAsyncRequest(registered_method_, server_, context_,
+                                  stream_, call_cq_, notification_cq_, tag_,
+                                  request_);
+          delete this;
+          return false;
+        }
+      }
+      /* Set interception point for recv message */
+      interceptor_methods_.AddInterceptionHookPoint(
+          experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+      interceptor_methods_.SetRecvMessage(request_);
+      return RegisteredAsyncRequest::FinalizeResult(tag, status);
+    }
+
+   private:
+    internal::RpcServiceMethod* const registered_method_;
+    ServerInterface* const server_;
+    ServerContext* const context_;
+    internal::ServerAsyncStreamingInterface* const stream_;
+    CompletionQueue* const call_cq_;
+
+    ServerCompletionQueue* const notification_cq_;
+    void* const tag_;
+    Message* const request_;
+    ByteBuffer payload_;
+  };
+
+  class GenericAsyncRequest : public BaseAsyncRequest {
+   public:
+    GenericAsyncRequest(ServerInterface* server, GenericServerContext* context,
+                        internal::ServerAsyncStreamingInterface* stream,
+                        CompletionQueue* call_cq,
+                        ServerCompletionQueue* notification_cq, void* tag,
+                        bool delete_on_finalize);
+
+    bool FinalizeResult(void** tag, bool* status) override;
+
+   private:
+    grpc_call_details call_details_;
+  };
+
+  template <class Message>
+  void RequestAsyncCall(internal::RpcServiceMethod* method,
+                        ServerContext* context,
+                        internal::ServerAsyncStreamingInterface* stream,
+                        CompletionQueue* call_cq,
+                        ServerCompletionQueue* notification_cq, void* tag,
+                        Message* message) {
+    GPR_CODEGEN_ASSERT(method);
+    new PayloadAsyncRequest<Message>(method, this, context, stream, call_cq,
+                                     notification_cq, tag, message);
+  }
+
+  void RequestAsyncCall(internal::RpcServiceMethod* method,
+                        ServerContext* context,
+                        internal::ServerAsyncStreamingInterface* stream,
+                        CompletionQueue* call_cq,
+                        ServerCompletionQueue* notification_cq, void* tag) {
+    GPR_CODEGEN_ASSERT(method);
+    new NoPayloadAsyncRequest(method, this, context, stream, call_cq,
+                              notification_cq, tag);
+  }
+
+  void RequestAsyncGenericCall(GenericServerContext* context,
+                               internal::ServerAsyncStreamingInterface* stream,
+                               CompletionQueue* call_cq,
+                               ServerCompletionQueue* notification_cq,
+                               void* tag) {
+    new GenericAsyncRequest(this, context, stream, call_cq, notification_cq,
+                            tag, true);
+  }
+
+ private:
+  // EXPERIMENTAL
+  // Getter method for the vector of interceptor factory objects.
+  // Returns a nullptr (rather than being pure) since this is a post-1.0 method
+  // and adding a new pure method to an interface would be a breaking change
+  // (even though this is private and non-API)
+  virtual std::vector<
+      std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>*
+  interceptor_creators() {
+    return nullptr;
+  }
+
+  // EXPERIMENTAL
+  // A method to get the callbackable completion queue associated with this
+  // server. If the return value is nullptr, this server doesn't support
+  // callback operations.
+  // TODO(vjpai): Consider a better default like using a global CQ
+  // Returns nullptr (rather than being pure) since this is a post-1.0 method
+  // and adding a new pure method to an interface would be a breaking change
+  // (even though this is private and non-API)
+  virtual CompletionQueue* CallbackCQ() { return nullptr; }
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SERVER_INTERFACE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/service_type.h b/third_party/grpc/include/grpcpp/impl/codegen/service_type.h
new file mode 100644
index 0000000..332a04c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/service_type.h
@@ -0,0 +1,239 @@
+/*
+ *
+ * Copyright 2015 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_SERVICE_TYPE_H
+#define GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+#include <grpcpp/impl/codegen/serialization_traits.h>
+#include <grpcpp/impl/codegen/server_interface.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+class CompletionQueue;
+class Server;
+class ServerInterface;
+class ServerCompletionQueue;
+class ServerContext;
+
+namespace internal {
+class Call;
+class ServerAsyncStreamingInterface {
+ public:
+  virtual ~ServerAsyncStreamingInterface() {}
+
+  /// Request notification of the sending of initial metadata to the client.
+  /// Completion will be notified by \a tag on the associated completion
+  /// queue. This call is optional, but if it is used, it cannot be used
+  /// concurrently with or after the \a Finish method.
+  ///
+  /// \param[in] tag Tag identifying this request.
+  virtual void SendInitialMetadata(void* tag) = 0;
+
+ private:
+  friend class ::grpc::ServerInterface;
+  virtual void BindCall(Call* call) = 0;
+};
+}  // namespace internal
+
+/// Desriptor of an RPC service and its various RPC methods
+class Service {
+ public:
+  Service() : server_(nullptr) {}
+  virtual ~Service() {}
+
+  bool has_async_methods() const {
+    for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+      if (*it && (*it)->handler() == nullptr) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool has_synchronous_methods() const {
+    for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+      if (*it &&
+          (*it)->api_type() == internal::RpcServiceMethod::ApiType::SYNC) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool has_callback_methods() const {
+    for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+      if (*it && ((*it)->api_type() ==
+                      internal::RpcServiceMethod::ApiType::CALL_BACK ||
+                  (*it)->api_type() ==
+                      internal::RpcServiceMethod::ApiType::RAW_CALL_BACK)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool has_generic_methods() const {
+    for (auto it = methods_.begin(); it != methods_.end(); ++it) {
+      if (it->get() == nullptr) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+ protected:
+  // TODO(vjpai): Promote experimental contents once callback API is accepted
+  class experimental_type {
+   public:
+    explicit experimental_type(Service* service) : service_(service) {}
+
+    void MarkMethodCallback(int index, internal::MethodHandler* handler) {
+      // This does not have to be a hard error, however no one has approached us
+      // with a use case yet. Please file an issue if you believe you have one.
+      size_t idx = static_cast<size_t>(index);
+      GPR_CODEGEN_ASSERT(
+          service_->methods_[idx].get() != nullptr &&
+          "Cannot mark the method as 'callback' because it has already been "
+          "marked as 'generic'.");
+      service_->methods_[idx]->SetHandler(handler);
+      service_->methods_[idx]->SetServerApiType(
+          internal::RpcServiceMethod::ApiType::CALL_BACK);
+    }
+
+    void MarkMethodRawCallback(int index, internal::MethodHandler* handler) {
+      // This does not have to be a hard error, however no one has approached us
+      // with a use case yet. Please file an issue if you believe you have one.
+      size_t idx = static_cast<size_t>(index);
+      GPR_CODEGEN_ASSERT(
+          service_->methods_[idx].get() != nullptr &&
+          "Cannot mark the method as 'raw callback' because it has already "
+          "been marked as 'generic'.");
+      service_->methods_[idx]->SetHandler(handler);
+      service_->methods_[idx]->SetServerApiType(
+          internal::RpcServiceMethod::ApiType::RAW_CALL_BACK);
+    }
+
+   private:
+    Service* service_;
+  };
+
+  experimental_type experimental() { return experimental_type(this); }
+
+  template <class Message>
+  void RequestAsyncUnary(int index, ServerContext* context, Message* request,
+                         internal::ServerAsyncStreamingInterface* stream,
+                         CompletionQueue* call_cq,
+                         ServerCompletionQueue* notification_cq, void* tag) {
+    // Typecast the index to size_t for indexing into a vector
+    // while preserving the API that existed before a compiler
+    // warning was first seen (grpc/grpc#11664)
+    size_t idx = static_cast<size_t>(index);
+    server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
+                              notification_cq, tag, request);
+  }
+  void RequestAsyncClientStreaming(
+      int index, ServerContext* context,
+      internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+      ServerCompletionQueue* notification_cq, void* tag) {
+    size_t idx = static_cast<size_t>(index);
+    server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
+                              notification_cq, tag);
+  }
+  template <class Message>
+  void RequestAsyncServerStreaming(
+      int index, ServerContext* context, Message* request,
+      internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+      ServerCompletionQueue* notification_cq, void* tag) {
+    size_t idx = static_cast<size_t>(index);
+    server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
+                              notification_cq, tag, request);
+  }
+  void RequestAsyncBidiStreaming(
+      int index, ServerContext* context,
+      internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+      ServerCompletionQueue* notification_cq, void* tag) {
+    size_t idx = static_cast<size_t>(index);
+    server_->RequestAsyncCall(methods_[idx].get(), context, stream, call_cq,
+                              notification_cq, tag);
+  }
+
+  void AddMethod(internal::RpcServiceMethod* method) {
+    methods_.emplace_back(method);
+  }
+
+  void MarkMethodAsync(int index) {
+    // This does not have to be a hard error, however no one has approached us
+    // with a use case yet. Please file an issue if you believe you have one.
+    size_t idx = static_cast<size_t>(index);
+    GPR_CODEGEN_ASSERT(
+        methods_[idx].get() != nullptr &&
+        "Cannot mark the method as 'async' because it has already been "
+        "marked as 'generic'.");
+    methods_[idx]->SetServerApiType(internal::RpcServiceMethod::ApiType::ASYNC);
+  }
+
+  void MarkMethodRaw(int index) {
+    // This does not have to be a hard error, however no one has approached us
+    // with a use case yet. Please file an issue if you believe you have one.
+    size_t idx = static_cast<size_t>(index);
+    GPR_CODEGEN_ASSERT(methods_[idx].get() != nullptr &&
+                       "Cannot mark the method as 'raw' because it has already "
+                       "been marked as 'generic'.");
+    methods_[idx]->SetServerApiType(internal::RpcServiceMethod::ApiType::RAW);
+  }
+
+  void MarkMethodGeneric(int index) {
+    // This does not have to be a hard error, however no one has approached us
+    // with a use case yet. Please file an issue if you believe you have one.
+    size_t idx = static_cast<size_t>(index);
+    GPR_CODEGEN_ASSERT(
+        methods_[idx]->handler() != nullptr &&
+        "Cannot mark the method as 'generic' because it has already been "
+        "marked as 'async' or 'raw'.");
+    methods_[idx].reset();
+  }
+
+  void MarkMethodStreamed(int index, internal::MethodHandler* streamed_method) {
+    // This does not have to be a hard error, however no one has approached us
+    // with a use case yet. Please file an issue if you believe you have one.
+    size_t idx = static_cast<size_t>(index);
+    GPR_CODEGEN_ASSERT(methods_[idx] && methods_[idx]->handler() &&
+                       "Cannot mark an async or generic method Streamed");
+    methods_[idx]->SetHandler(streamed_method);
+
+    // From the server's point of view, streamed unary is a special
+    // case of BIDI_STREAMING that has 1 read and 1 write, in that order,
+    // and split server-side streaming is BIDI_STREAMING with 1 read and
+    // any number of writes, in that order.
+    methods_[idx]->SetMethodType(internal::RpcMethod::BIDI_STREAMING);
+  }
+
+ private:
+  friend class Server;
+  friend class ServerInterface;
+  ServerInterface* server_;
+  std::vector<std::unique_ptr<internal::RpcServiceMethod>> methods_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SERVICE_TYPE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/slice.h b/third_party/grpc/include/grpcpp/impl/codegen/slice.h
new file mode 100644
index 0000000..8966559
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/slice.h
@@ -0,0 +1,143 @@
+/*
+ *
+ * Copyright 2015 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_SLICE_H
+#define GRPCPP_IMPL_CODEGEN_SLICE_H
+
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/string_ref.h>
+
+#include <grpc/impl/codegen/slice.h>
+
+namespace grpc {
+
+/// A wrapper around \a grpc_slice.
+///
+/// A slice represents a contiguous reference counted array of bytes.
+/// It is cheap to take references to a slice, and it is cheap to create a
+/// slice pointing to a subset of another slice.
+class Slice final {
+ public:
+  /// Construct an empty slice.
+  Slice() : slice_(g_core_codegen_interface->grpc_empty_slice()) {}
+  /// Destructor - drops one reference.
+  ~Slice() { g_core_codegen_interface->grpc_slice_unref(slice_); }
+
+  enum AddRef { ADD_REF };
+  /// Construct a slice from \a slice, adding a reference.
+  Slice(grpc_slice slice, AddRef)
+      : slice_(g_core_codegen_interface->grpc_slice_ref(slice)) {}
+
+  enum StealRef { STEAL_REF };
+  /// Construct a slice from \a slice, stealing a reference.
+  Slice(grpc_slice slice, StealRef) : slice_(slice) {}
+
+  /// Allocate a slice of specified size
+  Slice(size_t len)
+      : slice_(g_core_codegen_interface->grpc_slice_malloc(len)) {}
+
+  /// Construct a slice from a copied buffer
+  Slice(const void* buf, size_t len)
+      : slice_(g_core_codegen_interface->grpc_slice_from_copied_buffer(
+            reinterpret_cast<const char*>(buf), len)) {}
+
+  /// Construct a slice from a copied string
+  Slice(const grpc::string& str)
+      : slice_(g_core_codegen_interface->grpc_slice_from_copied_buffer(
+            str.c_str(), str.length())) {}
+
+  enum StaticSlice { STATIC_SLICE };
+
+  /// Construct a slice from a static buffer
+  Slice(const void* buf, size_t len, StaticSlice)
+      : slice_(g_core_codegen_interface->grpc_slice_from_static_buffer(
+            reinterpret_cast<const char*>(buf), len)) {}
+
+  /// Copy constructor, adds a reference.
+  Slice(const Slice& other)
+      : slice_(g_core_codegen_interface->grpc_slice_ref(other.slice_)) {}
+
+  /// Assignment, reference count is unchanged.
+  Slice& operator=(Slice other) {
+    std::swap(slice_, other.slice_);
+    return *this;
+  }
+
+  /// Create a slice pointing at some data. Calls malloc to allocate a refcount
+  /// for the object, and arranges that destroy will be called with the
+  /// user data pointer passed in at destruction. Can be the same as buf or
+  /// different (e.g., if data is part of a larger structure that must be
+  /// destroyed when the data is no longer needed)
+  Slice(void* buf, size_t len, void (*destroy)(void*), void* user_data)
+      : slice_(g_core_codegen_interface->grpc_slice_new_with_user_data(
+            buf, len, destroy, user_data)) {}
+
+  /// Specialization of above for common case where buf == user_data
+  Slice(void* buf, size_t len, void (*destroy)(void*))
+      : Slice(buf, len, destroy, buf) {}
+
+  /// Similar to the above but has a destroy that also takes slice length
+  Slice(void* buf, size_t len, void (*destroy)(void*, size_t))
+      : slice_(g_core_codegen_interface->grpc_slice_new_with_len(buf, len,
+                                                                 destroy)) {}
+
+  /// Byte size.
+  size_t size() const { return GRPC_SLICE_LENGTH(slice_); }
+
+  /// Raw pointer to the beginning (first element) of the slice.
+  const uint8_t* begin() const { return GRPC_SLICE_START_PTR(slice_); }
+
+  /// Raw pointer to the end (one byte \em past the last element) of the slice.
+  const uint8_t* end() const { return GRPC_SLICE_END_PTR(slice_); }
+
+  /// Raw C slice. Caller needs to call grpc_slice_unref when done.
+  grpc_slice c_slice() const {
+    return g_core_codegen_interface->grpc_slice_ref(slice_);
+  }
+
+ private:
+  friend class ByteBuffer;
+
+  grpc_slice slice_;
+};
+
+inline grpc::string_ref StringRefFromSlice(const grpc_slice* slice) {
+  return grpc::string_ref(
+      reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(*slice)),
+      GRPC_SLICE_LENGTH(*slice));
+}
+
+inline grpc::string StringFromCopiedSlice(grpc_slice slice) {
+  return grpc::string(reinterpret_cast<char*>(GRPC_SLICE_START_PTR(slice)),
+                      GRPC_SLICE_LENGTH(slice));
+}
+
+inline grpc_slice SliceReferencingString(const grpc::string& str) {
+  return g_core_codegen_interface->grpc_slice_from_static_buffer(str.data(),
+                                                                 str.length());
+}
+
+inline grpc_slice SliceFromCopiedString(const grpc::string& str) {
+  return g_core_codegen_interface->grpc_slice_from_copied_buffer(str.data(),
+                                                                 str.length());
+}
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SLICE_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/status.h b/third_party/grpc/include/grpcpp/impl/codegen/status.h
new file mode 100644
index 0000000..e625a76
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/status.h
@@ -0,0 +1,133 @@
+/*
+ *
+ * Copyright 2016 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_STATUS_H
+#define GRPCPP_IMPL_CODEGEN_STATUS_H
+
+#include <grpc/impl/codegen/status.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/status_code_enum.h>
+
+namespace grpc {
+
+/// Did it work? If it didn't, why?
+///
+/// See \a grpc::StatusCode for details on the available code and their meaning.
+class Status {
+ public:
+  /// Construct an OK instance.
+  Status() : code_(StatusCode::OK) {
+    // Static assertions to make sure that the C++ API value correctly
+    // maps to the core surface API value
+    static_assert(StatusCode::OK == static_cast<StatusCode>(GRPC_STATUS_OK),
+                  "Mismatched status code");
+    static_assert(
+        StatusCode::CANCELLED == static_cast<StatusCode>(GRPC_STATUS_CANCELLED),
+        "Mismatched status code");
+    static_assert(
+        StatusCode::UNKNOWN == static_cast<StatusCode>(GRPC_STATUS_UNKNOWN),
+        "Mismatched status code");
+    static_assert(StatusCode::INVALID_ARGUMENT ==
+                      static_cast<StatusCode>(GRPC_STATUS_INVALID_ARGUMENT),
+                  "Mismatched status code");
+    static_assert(StatusCode::DEADLINE_EXCEEDED ==
+                      static_cast<StatusCode>(GRPC_STATUS_DEADLINE_EXCEEDED),
+                  "Mismatched status code");
+    static_assert(
+        StatusCode::NOT_FOUND == static_cast<StatusCode>(GRPC_STATUS_NOT_FOUND),
+        "Mismatched status code");
+    static_assert(StatusCode::ALREADY_EXISTS ==
+                      static_cast<StatusCode>(GRPC_STATUS_ALREADY_EXISTS),
+                  "Mismatched status code");
+    static_assert(StatusCode::PERMISSION_DENIED ==
+                      static_cast<StatusCode>(GRPC_STATUS_PERMISSION_DENIED),
+                  "Mismatched status code");
+    static_assert(StatusCode::UNAUTHENTICATED ==
+                      static_cast<StatusCode>(GRPC_STATUS_UNAUTHENTICATED),
+                  "Mismatched status code");
+    static_assert(StatusCode::RESOURCE_EXHAUSTED ==
+                      static_cast<StatusCode>(GRPC_STATUS_RESOURCE_EXHAUSTED),
+                  "Mismatched status code");
+    static_assert(StatusCode::FAILED_PRECONDITION ==
+                      static_cast<StatusCode>(GRPC_STATUS_FAILED_PRECONDITION),
+                  "Mismatched status code");
+    static_assert(
+        StatusCode::ABORTED == static_cast<StatusCode>(GRPC_STATUS_ABORTED),
+        "Mismatched status code");
+    static_assert(StatusCode::OUT_OF_RANGE ==
+                      static_cast<StatusCode>(GRPC_STATUS_OUT_OF_RANGE),
+                  "Mismatched status code");
+    static_assert(StatusCode::UNIMPLEMENTED ==
+                      static_cast<StatusCode>(GRPC_STATUS_UNIMPLEMENTED),
+                  "Mismatched status code");
+    static_assert(
+        StatusCode::INTERNAL == static_cast<StatusCode>(GRPC_STATUS_INTERNAL),
+        "Mismatched status code");
+    static_assert(StatusCode::UNAVAILABLE ==
+                      static_cast<StatusCode>(GRPC_STATUS_UNAVAILABLE),
+                  "Mismatched status code");
+    static_assert(
+        StatusCode::DATA_LOSS == static_cast<StatusCode>(GRPC_STATUS_DATA_LOSS),
+        "Mismatched status code");
+  }
+
+  /// Construct an instance with associated \a code and \a error_message.
+  /// It is an error to construct an OK status with non-empty \a error_message.
+  Status(StatusCode code, const grpc::string& error_message)
+      : code_(code), error_message_(error_message) {}
+
+  /// Construct an instance with \a code,  \a error_message and
+  /// \a error_details. It is an error to construct an OK status with non-empty
+  /// \a error_message and/or \a error_details.
+  Status(StatusCode code, const grpc::string& error_message,
+         const grpc::string& error_details)
+      : code_(code),
+        error_message_(error_message),
+        binary_error_details_(error_details) {}
+
+  // Pre-defined special status objects.
+  /// An OK pre-defined instance.
+  static const Status& OK;
+  /// A CANCELLED pre-defined instance.
+  static const Status& CANCELLED;
+
+  /// Return the instance's error code.
+  StatusCode error_code() const { return code_; }
+  /// Return the instance's error message.
+  grpc::string error_message() const { return error_message_; }
+  /// Return the (binary) error details.
+  // Usually it contains a serialized google.rpc.Status proto.
+  grpc::string error_details() const { return binary_error_details_; }
+
+  /// Is the status OK?
+  bool ok() const { return code_ == StatusCode::OK; }
+
+  // Ignores any errors. This method does nothing except potentially suppress
+  // complaints from any tools that are checking that errors are not dropped on
+  // the floor.
+  void IgnoreError() const {}
+
+ private:
+  StatusCode code_;
+  grpc::string error_message_;
+  grpc::string binary_error_details_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_STATUS_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/status_code_enum.h b/third_party/grpc/include/grpcpp/impl/codegen/status_code_enum.h
new file mode 100644
index 0000000..09943f1
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/status_code_enum.h
@@ -0,0 +1,142 @@
+/*
+ *
+ * Copyright 2016 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_STATUS_CODE_ENUM_H
+#define GRPCPP_IMPL_CODEGEN_STATUS_CODE_ENUM_H
+
+namespace grpc {
+
+enum StatusCode {
+  /// Not an error; returned on success.
+  OK = 0,
+
+  /// The operation was cancelled (typically by the caller).
+  CANCELLED = 1,
+
+  /// Unknown error. An example of where this error may be returned is if a
+  /// Status value received from another address space belongs to an error-space
+  /// that is not known in this address space. Also errors raised by APIs that
+  /// do not return enough error information may be converted to this error.
+  UNKNOWN = 2,
+
+  /// Client specified an invalid argument. Note that this differs from
+  /// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
+  /// problematic regardless of the state of the system (e.g., a malformed file
+  /// name).
+  INVALID_ARGUMENT = 3,
+
+  /// Deadline expired before operation could complete. For operations that
+  /// change the state of the system, this error may be returned even if the
+  /// operation has completed successfully. For example, a successful response
+  /// from a server could have been delayed long enough for the deadline to
+  /// expire.
+  DEADLINE_EXCEEDED = 4,
+
+  /// Some requested entity (e.g., file or directory) was not found.
+  NOT_FOUND = 5,
+
+  /// Some entity that we attempted to create (e.g., file or directory) already
+  /// exists.
+  ALREADY_EXISTS = 6,
+
+  /// The caller does not have permission to execute the specified operation.
+  /// PERMISSION_DENIED must not be used for rejections caused by exhausting
+  /// some resource (use RESOURCE_EXHAUSTED instead for those errors).
+  /// PERMISSION_DENIED must not be used if the caller can not be identified
+  /// (use UNAUTHENTICATED instead for those errors).
+  PERMISSION_DENIED = 7,
+
+  /// The request does not have valid authentication credentials for the
+  /// operation.
+  UNAUTHENTICATED = 16,
+
+  /// Some resource has been exhausted, perhaps a per-user quota, or perhaps the
+  /// entire file system is out of space.
+  RESOURCE_EXHAUSTED = 8,
+
+  /// Operation was rejected because the system is not in a state required for
+  /// the operation's execution. For example, directory to be deleted may be
+  /// non-empty, an rmdir operation is applied to a non-directory, etc.
+  ///
+  /// A litmus test that may help a service implementor in deciding
+  /// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
+  ///  (a) Use UNAVAILABLE if the client can retry just the failing call.
+  ///  (b) Use ABORTED if the client should retry at a higher-level
+  ///      (e.g., restarting a read-modify-write sequence).
+  ///  (c) Use FAILED_PRECONDITION if the client should not retry until
+  ///      the system state has been explicitly fixed. E.g., if an "rmdir"
+  ///      fails because the directory is non-empty, FAILED_PRECONDITION
+  ///      should be returned since the client should not retry unless
+  ///      they have first fixed up the directory by deleting files from it.
+  ///  (d) Use FAILED_PRECONDITION if the client performs conditional
+  ///      REST Get/Update/Delete on a resource and the resource on the
+  ///      server does not match the condition. E.g., conflicting
+  ///      read-modify-write on the same resource.
+  FAILED_PRECONDITION = 9,
+
+  /// The operation was aborted, typically due to a concurrency issue like
+  /// sequencer check failures, transaction aborts, etc.
+  ///
+  /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
+  /// and UNAVAILABLE.
+  ABORTED = 10,
+
+  /// Operation was attempted past the valid range. E.g., seeking or reading
+  /// past end of file.
+  ///
+  /// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
+  /// if the system state changes. For example, a 32-bit file system will
+  /// generate INVALID_ARGUMENT if asked to read at an offset that is not in the
+  /// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
+  /// an offset past the current file size.
+  ///
+  /// There is a fair bit of overlap between FAILED_PRECONDITION and
+  /// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
+  /// when it applies so that callers who are iterating through a space can
+  /// easily look for an OUT_OF_RANGE error to detect when they are done.
+  OUT_OF_RANGE = 11,
+
+  /// Operation is not implemented or not supported/enabled in this service.
+  UNIMPLEMENTED = 12,
+
+  /// Internal errors. Means some invariants expected by underlying System has
+  /// been broken. If you see one of these errors, Something is very broken.
+  INTERNAL = 13,
+
+  /// The service is currently unavailable. This is a most likely a transient
+  /// condition and may be corrected by retrying with a backoff.
+  ///
+  /// \warning Although data MIGHT not have been transmitted when this
+  /// status occurs, there is NOT A GUARANTEE that the server has not seen
+  /// anything. So in general it is unsafe to retry on this status code
+  /// if the call is non-idempotent.
+  ///
+  /// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
+  /// and UNAVAILABLE.
+  UNAVAILABLE = 14,
+
+  /// Unrecoverable data loss or corruption.
+  DATA_LOSS = 15,
+
+  /// Force users to include a default branch:
+  DO_NOT_USE = -1
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_STATUS_CODE_ENUM_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/string_ref.h b/third_party/grpc/include/grpcpp/impl/codegen/string_ref.h
new file mode 100644
index 0000000..5d55fc4
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/string_ref.h
@@ -0,0 +1,146 @@
+/*
+ *
+ * Copyright 2015 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_STRING_REF_H
+#define GRPCPP_IMPL_CODEGEN_STRING_REF_H
+
+#include <string.h>
+
+#include <algorithm>
+#include <iosfwd>
+#include <iostream>
+#include <iterator>
+
+#include <grpcpp/impl/codegen/config.h>
+
+namespace grpc {
+
+/// This class is a non owning reference to a string.
+///
+/// It should be a strict subset of the upcoming std::string_ref.
+///
+/// \see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html
+///
+/// The constexpr is dropped or replaced with const for legacy compiler
+/// compatibility.
+class string_ref {
+ public:
+  /// types
+  typedef const char* const_iterator;
+  typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+  /// constants
+  const static size_t npos;
+
+  /// construct/copy.
+  string_ref() : data_(nullptr), length_(0) {}
+  string_ref(const string_ref& other)
+      : data_(other.data_), length_(other.length_) {}
+  string_ref& operator=(const string_ref& rhs) {
+    data_ = rhs.data_;
+    length_ = rhs.length_;
+    return *this;
+  }
+
+  string_ref(const char* s) : data_(s), length_(strlen(s)) {}
+  string_ref(const char* s, size_t l) : data_(s), length_(l) {}
+  string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {}
+
+  /// iterators
+  const_iterator begin() const { return data_; }
+  const_iterator end() const { return data_ + length_; }
+  const_iterator cbegin() const { return data_; }
+  const_iterator cend() const { return data_ + length_; }
+  const_reverse_iterator rbegin() const {
+    return const_reverse_iterator(end());
+  }
+  const_reverse_iterator rend() const {
+    return const_reverse_iterator(begin());
+  }
+  const_reverse_iterator crbegin() const {
+    return const_reverse_iterator(end());
+  }
+  const_reverse_iterator crend() const {
+    return const_reverse_iterator(begin());
+  }
+
+  /// capacity
+  size_t size() const { return length_; }
+  size_t length() const { return length_; }
+  size_t max_size() const { return length_; }
+  bool empty() const { return length_ == 0; }
+
+  /// element access
+  const char* data() const { return data_; }
+
+  /// string operations
+  int compare(string_ref x) const {
+    size_t min_size = length_ < x.length_ ? length_ : x.length_;
+    int r = memcmp(data_, x.data_, min_size);
+    if (r < 0) return -1;
+    if (r > 0) return 1;
+    if (length_ < x.length_) return -1;
+    if (length_ > x.length_) return 1;
+    return 0;
+  }
+
+  bool starts_with(string_ref x) const {
+    return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0);
+  }
+
+  bool ends_with(string_ref x) const {
+    return length_ >= x.length_ &&
+           (memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0);
+  }
+
+  size_t find(string_ref s) const {
+    auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend());
+    return it == cend() ? npos : std::distance(cbegin(), it);
+  }
+
+  size_t find(char c) const {
+    auto it = std::find(cbegin(), cend(), c);
+    return it == cend() ? npos : std::distance(cbegin(), it);
+  }
+
+  string_ref substr(size_t pos, size_t n = npos) const {
+    if (pos > length_) pos = length_;
+    if (n > (length_ - pos)) n = length_ - pos;
+    return string_ref(data_ + pos, n);
+  }
+
+ private:
+  const char* data_;
+  size_t length_;
+};
+
+/// Comparison operators
+inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
+inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
+inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
+inline bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; }
+inline bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; }
+inline bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; }
+
+inline std::ostream& operator<<(std::ostream& out, const string_ref& string) {
+  return out << grpc::string(string.begin(), string.end());
+}
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_STRING_REF_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/stub_options.h b/third_party/grpc/include/grpcpp/impl/codegen/stub_options.h
new file mode 100644
index 0000000..a56695a
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/stub_options.h
@@ -0,0 +1,29 @@
+/*
+ *
+ * Copyright 2015 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_STUB_OPTIONS_H
+#define GRPCPP_IMPL_CODEGEN_STUB_OPTIONS_H
+
+namespace grpc {
+
+/// Useful interface for generated stubs
+class StubOptions {};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_STUB_OPTIONS_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/sync_stream.h b/third_party/grpc/include/grpcpp/impl/codegen/sync_stream.h
new file mode 100644
index 0000000..6981076
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/sync_stream.h
@@ -0,0 +1,934 @@
+/*
+ *
+ * Copyright 2015 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_SYNC_STREAM_H
+#define GRPCPP_IMPL_CODEGEN_SYNC_STREAM_H
+
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/channel_interface.h>
+#include <grpcpp/impl/codegen/client_context.h>
+#include <grpcpp/impl/codegen/completion_queue.h>
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/server_context.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/impl/codegen/status.h>
+
+namespace grpc {
+
+namespace internal {
+/// Common interface for all synchronous client side streaming.
+class ClientStreamingInterface {
+ public:
+  virtual ~ClientStreamingInterface() {}
+
+  /// Block waiting until the stream finishes and a final status of the call is
+  /// available.
+  ///
+  /// It is appropriate to call this method when both:
+  ///   * the calling code (client-side) has no more message to send
+  ///     (this can be declared implicitly by calling this method, or
+  ///     explicitly through an earlier call to <i>WritesDone</i> method of the
+  ///     class in use, e.g. \a ClientWriterInterface::WritesDone or
+  ///     \a ClientReaderWriterInterface::WritesDone).
+  ///   * there are no more messages to be received from the server (which can
+  ///     be known implicitly, or explicitly from an earlier call to \a
+  ///     ReaderInterface::Read that returned "false").
+  ///
+  /// This function will return either:
+  /// - when all incoming messages have been read and the server has
+  ///   returned status.
+  /// - when the server has returned a non-OK status.
+  /// - OR when the call failed for some reason and the library generated a
+  ///   status.
+  ///
+  /// Return values:
+  ///   - \a Status contains the status code, message and details for the call
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible trailing metadata sent from the server.
+  virtual Status Finish() = 0;
+};
+
+/// Common interface for all synchronous server side streaming.
+class ServerStreamingInterface {
+ public:
+  virtual ~ServerStreamingInterface() {}
+
+  /// Block to send initial metadata to client.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// The initial metadata that will be sent to the client will be
+  /// taken from the \a ServerContext associated with the call.
+  virtual void SendInitialMetadata() = 0;
+};
+
+/// An interface that yields a sequence of messages of type \a R.
+template <class R>
+class ReaderInterface {
+ public:
+  virtual ~ReaderInterface() {}
+
+  /// Get an upper bound on the next message size available for reading on this
+  /// stream.
+  virtual bool NextMessageSize(uint32_t* sz) = 0;
+
+  /// Block to read a message and parse to \a msg. Returns \a true on success.
+  /// This is thread-safe with respect to \a Write or \WritesDone methods on
+  /// the same stream. It should not be called concurrently with another \a
+  /// Read on the same stream as the order of delivery will not be defined.
+  ///
+  /// \param[out] msg The read message.
+  ///
+  /// \return \a false when there will be no more incoming messages, either
+  /// because the other side has called \a WritesDone() or the stream has failed
+  /// (or been cancelled).
+  virtual bool Read(R* msg) = 0;
+};
+
+/// An interface that can be fed a sequence of messages of type \a W.
+template <class W>
+class WriterInterface {
+ public:
+  virtual ~WriterInterface() {}
+
+  /// Block to write \a msg to the stream with WriteOptions \a options.
+  /// This is thread-safe with respect to \a ReaderInterface::Read
+  ///
+  /// \param msg The message to be written to the stream.
+  /// \param options The WriteOptions affecting the write operation.
+  ///
+  /// \return \a true on success, \a false when the stream has been closed.
+  virtual bool Write(const W& msg, WriteOptions options) = 0;
+
+  /// Block to write \a msg to the stream with default write options.
+  /// This is thread-safe with respect to \a ReaderInterface::Read
+  ///
+  /// \param msg The message to be written to the stream.
+  ///
+  /// \return \a true on success, \a false when the stream has been closed.
+  inline bool Write(const W& msg) { return Write(msg, WriteOptions()); }
+
+  /// Write \a msg and coalesce it with the writing of trailing metadata, using
+  /// WriteOptions \a options.
+  ///
+  /// For client, WriteLast is equivalent of performing Write and WritesDone in
+  /// a single step. \a msg and trailing metadata are coalesced and sent on wire
+  /// by calling this function. For server, WriteLast buffers the \a msg.
+  /// The writing of \a msg is held until the service handler returns,
+  /// where \a msg and trailing metadata are coalesced and sent on wire.
+  /// Note that WriteLast can only buffer \a msg up to the flow control window
+  /// size. If \a msg size is larger than the window size, it will be sent on
+  /// wire without buffering.
+  ///
+  /// \param[in] msg The message to be written to the stream.
+  /// \param[in] options The WriteOptions to be used to write this message.
+  void WriteLast(const W& msg, WriteOptions options) {
+    Write(msg, options.set_last_message());
+  }
+};
+
+}  // namespace internal
+
+/// Client-side interface for streaming reads of message of type \a R.
+template <class R>
+class ClientReaderInterface : public internal::ClientStreamingInterface,
+                              public internal::ReaderInterface<R> {
+ public:
+  /// Block to wait for initial metadata from server. The received metadata
+  /// can only be accessed after this call returns. Should only be called before
+  /// the first read. Calling this method is optional, and if it is not called
+  /// the metadata will be available in ClientContext after the first read.
+  virtual void WaitForInitialMetadata() = 0;
+};
+
+namespace internal {
+template <class R>
+class ClientReaderFactory {
+ public:
+  template <class W>
+  static ClientReader<R>* Create(ChannelInterface* channel,
+                                 const ::grpc::internal::RpcMethod& method,
+                                 ClientContext* context, const W& request) {
+    return new ClientReader<R>(channel, method, context, request);
+  }
+};
+}  // namespace internal
+
+/// Synchronous (blocking) client-side API for doing server-streaming RPCs,
+/// where the stream of messages coming from the server has messages
+/// of type \a R.
+template <class R>
+class ClientReader final : public ClientReaderInterface<R> {
+ public:
+  /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+  /// semantics.
+  ///
+  //  Side effect:
+  ///   Once complete, the initial metadata read from
+  ///   the server will be accessable through the \a ClientContext used to
+  ///   construct this object.
+  void WaitForInitialMetadata() override {
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+        ops;
+    ops.RecvInitialMetadata(context_);
+    call_.PerformOps(&ops);
+    cq_.Pluck(&ops);  /// status ignored
+  }
+
+  bool NextMessageSize(uint32_t* sz) override {
+    *sz = call_.max_receive_message_size();
+    return true;
+  }
+
+  /// See the \a ReaderInterface.Read method for semantics.
+  /// Side effect:
+  ///   This also receives initial metadata from the server, if not
+  ///   already received (if initial metadata is received, it can be then
+  ///   accessed through the \a ClientContext associated with this call).
+  bool Read(R* msg) override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                                ::grpc::internal::CallOpRecvMessage<R>>
+        ops;
+    if (!context_->initial_metadata_received_) {
+      ops.RecvInitialMetadata(context_);
+    }
+    ops.RecvMessage(msg);
+    call_.PerformOps(&ops);
+    return cq_.Pluck(&ops) && ops.got_message;
+  }
+
+  /// See the \a ClientStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   The \a ClientContext associated with this call is updated with
+  ///   possible metadata received from the server.
+  Status Finish() override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientRecvStatus> ops;
+    Status status;
+    ops.ClientRecvStatus(context_, &status);
+    call_.PerformOps(&ops);
+    GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
+    return status;
+  }
+
+ private:
+  friend class internal::ClientReaderFactory<R>;
+  ClientContext* context_;
+  CompletionQueue cq_;
+  ::grpc::internal::Call call_;
+
+  /// Block to create a stream and write the initial metadata and \a request
+  /// out. Note that \a context will be used to fill in custom initial
+  /// metadata used to send to the server when starting the call.
+  template <class W>
+  ClientReader(::grpc::ChannelInterface* channel,
+               const ::grpc::internal::RpcMethod& method,
+               ClientContext* context, const W& request)
+      : context_(context),
+        cq_(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
+            nullptr}),  // Pluckable cq
+        call_(channel->CreateCall(method, context, &cq_)) {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                                ::grpc::internal::CallOpSendMessage,
+                                ::grpc::internal::CallOpClientSendClose>
+        ops;
+    ops.SendInitialMetadata(&context->send_initial_metadata_,
+                            context->initial_metadata_flags());
+    // TODO(ctiller): don't assert
+    GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
+    ops.ClientSendClose();
+    call_.PerformOps(&ops);
+    cq_.Pluck(&ops);
+  }
+};
+
+/// Client-side interface for streaming writes of message type \a W.
+template <class W>
+class ClientWriterInterface : public internal::ClientStreamingInterface,
+                              public internal::WriterInterface<W> {
+ public:
+  /// Half close writing from the client. (signal that the stream of messages
+  /// coming from the client is complete).
+  /// Blocks until currently-pending writes are completed.
+  /// Thread safe with respect to \a ReaderInterface::Read operations only
+  ///
+  /// \return Whether the writes were successful.
+  virtual bool WritesDone() = 0;
+};
+
+namespace internal {
+template <class W>
+class ClientWriterFactory {
+ public:
+  template <class R>
+  static ClientWriter<W>* Create(::grpc::ChannelInterface* channel,
+                                 const ::grpc::internal::RpcMethod& method,
+                                 ClientContext* context, R* response) {
+    return new ClientWriter<W>(channel, method, context, response);
+  }
+};
+}  // namespace internal
+
+/// Synchronous (blocking) client-side API for doing client-streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of
+/// type \a W.
+template <class W>
+class ClientWriter : public ClientWriterInterface<W> {
+ public:
+  /// See the \a ClientStreamingInterface.WaitForInitialMetadata method for
+  /// semantics.
+  ///
+  //  Side effect:
+  ///   Once complete, the initial metadata read from the server will be
+  ///   accessable through the \a ClientContext used to construct this object.
+  void WaitForInitialMetadata() {
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+        ops;
+    ops.RecvInitialMetadata(context_);
+    call_.PerformOps(&ops);
+    cq_.Pluck(&ops);  // status ignored
+  }
+
+  /// See the WriterInterface.Write(const W& msg, WriteOptions options) method
+  /// for semantics.
+  ///
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the
+  ///   \a ClientContext associated with this call).
+  using ::grpc::internal::WriterInterface<W>::Write;
+  bool Write(const W& msg, WriteOptions options) override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                                ::grpc::internal::CallOpSendMessage,
+                                ::grpc::internal::CallOpClientSendClose>
+        ops;
+
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+      ops.ClientSendClose();
+    }
+    if (context_->initial_metadata_corked_) {
+      ops.SendInitialMetadata(&context_->send_initial_metadata_,
+                              context_->initial_metadata_flags());
+      context_->set_initial_metadata_corked(false);
+    }
+    if (!ops.SendMessage(msg, options).ok()) {
+      return false;
+    }
+
+    call_.PerformOps(&ops);
+    return cq_.Pluck(&ops);
+  }
+
+  bool WritesDone() override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
+    ops.ClientSendClose();
+    call_.PerformOps(&ops);
+    return cq_.Pluck(&ops);
+  }
+
+  /// See the ClientStreamingInterface.Finish method for semantics.
+  /// Side effects:
+  ///   - Also receives initial metadata if not already received.
+  ///   - Attempts to fill in the \a response parameter passed
+  ///     to the constructor of this instance with the response
+  ///     message from the server.
+  Status Finish() override {
+    Status status;
+    if (!context_->initial_metadata_received_) {
+      finish_ops_.RecvInitialMetadata(context_);
+    }
+    finish_ops_.ClientRecvStatus(context_, &status);
+    call_.PerformOps(&finish_ops_);
+    GPR_CODEGEN_ASSERT(cq_.Pluck(&finish_ops_));
+    return status;
+  }
+
+ private:
+  friend class internal::ClientWriterFactory<W>;
+
+  /// Block to create a stream (i.e. send request headers and other initial
+  /// metadata to the server). Note that \a context will be used to fill
+  /// in custom initial metadata. \a response will be filled in with the
+  /// single expected response message from the server upon a successful
+  /// call to the \a Finish method of this instance.
+  template <class R>
+  ClientWriter(ChannelInterface* channel,
+               const ::grpc::internal::RpcMethod& method,
+               ClientContext* context, R* response)
+      : context_(context),
+        cq_(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
+            nullptr}),  // Pluckable cq
+        call_(channel->CreateCall(method, context, &cq_)) {
+    finish_ops_.RecvMessage(response);
+    finish_ops_.AllowNoMessage();
+
+    if (!context_->initial_metadata_corked_) {
+      ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+          ops;
+      ops.SendInitialMetadata(&context->send_initial_metadata_,
+                              context->initial_metadata_flags());
+      call_.PerformOps(&ops);
+      cq_.Pluck(&ops);
+    }
+  }
+
+  ClientContext* context_;
+  ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                              ::grpc::internal::CallOpGenericRecvMessage,
+                              ::grpc::internal::CallOpClientRecvStatus>
+      finish_ops_;
+  CompletionQueue cq_;
+  ::grpc::internal::Call call_;
+};
+
+/// Client-side interface for bi-directional streaming with
+/// client-to-server stream messages of type \a W and
+/// server-to-client stream messages of type \a R.
+template <class W, class R>
+class ClientReaderWriterInterface : public internal::ClientStreamingInterface,
+                                    public internal::WriterInterface<W>,
+                                    public internal::ReaderInterface<R> {
+ public:
+  /// Block to wait for initial metadata from server. The received metadata
+  /// can only be accessed after this call returns. Should only be called before
+  /// the first read. Calling this method is optional, and if it is not called
+  /// the metadata will be available in ClientContext after the first read.
+  virtual void WaitForInitialMetadata() = 0;
+
+  /// Half close writing from the client. (signal that the stream of messages
+  /// coming from the clinet is complete).
+  /// Blocks until currently-pending writes are completed.
+  /// Thread-safe with respect to \a ReaderInterface::Read
+  ///
+  /// \return Whether the writes were successful.
+  virtual bool WritesDone() = 0;
+};
+
+namespace internal {
+template <class W, class R>
+class ClientReaderWriterFactory {
+ public:
+  static ClientReaderWriter<W, R>* Create(
+      ::grpc::ChannelInterface* channel,
+      const ::grpc::internal::RpcMethod& method, ClientContext* context) {
+    return new ClientReaderWriter<W, R>(channel, method, context);
+  }
+};
+}  // namespace internal
+
+/// Synchronous (blocking) client-side API for bi-directional streaming RPCs,
+/// where the outgoing message stream coming from the client has messages of
+/// type \a W, and the incoming messages stream coming from the server has
+/// messages of type \a R.
+template <class W, class R>
+class ClientReaderWriter final : public ClientReaderWriterInterface<W, R> {
+ public:
+  /// Block waiting to read initial metadata from the server.
+  /// This call is optional, but if it is used, it cannot be used concurrently
+  /// with or after the \a Finish method.
+  ///
+  /// Once complete, the initial metadata read from the server will be
+  /// accessable through the \a ClientContext used to construct this object.
+  void WaitForInitialMetadata() override {
+    GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
+
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata>
+        ops;
+    ops.RecvInitialMetadata(context_);
+    call_.PerformOps(&ops);
+    cq_.Pluck(&ops);  // status ignored
+  }
+
+  bool NextMessageSize(uint32_t* sz) override {
+    *sz = call_.max_receive_message_size();
+    return true;
+  }
+
+  /// See the \a ReaderInterface.Read method for semantics.
+  /// Side effect:
+  ///   Also receives initial metadata if not already received (updates the \a
+  ///   ClientContext associated with this call in that case).
+  bool Read(R* msg) override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                                ::grpc::internal::CallOpRecvMessage<R>>
+        ops;
+    if (!context_->initial_metadata_received_) {
+      ops.RecvInitialMetadata(context_);
+    }
+    ops.RecvMessage(msg);
+    call_.PerformOps(&ops);
+    return cq_.Pluck(&ops) && ops.got_message;
+  }
+
+  /// See the \a WriterInterface.Write method for semantics.
+  ///
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the
+  ///   \a ClientContext associated with this call to fill in values).
+  using ::grpc::internal::WriterInterface<W>::Write;
+  bool Write(const W& msg, WriteOptions options) override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata,
+                                ::grpc::internal::CallOpSendMessage,
+                                ::grpc::internal::CallOpClientSendClose>
+        ops;
+
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+      ops.ClientSendClose();
+    }
+    if (context_->initial_metadata_corked_) {
+      ops.SendInitialMetadata(&context_->send_initial_metadata_,
+                              context_->initial_metadata_flags());
+      context_->set_initial_metadata_corked(false);
+    }
+    if (!ops.SendMessage(msg, options).ok()) {
+      return false;
+    }
+
+    call_.PerformOps(&ops);
+    return cq_.Pluck(&ops);
+  }
+
+  bool WritesDone() override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpClientSendClose> ops;
+    ops.ClientSendClose();
+    call_.PerformOps(&ops);
+    return cq_.Pluck(&ops);
+  }
+
+  /// See the ClientStreamingInterface.Finish method for semantics.
+  ///
+  /// Side effect:
+  ///   - the \a ClientContext associated with this call is updated with
+  ///     possible trailing metadata sent from the server.
+  Status Finish() override {
+    ::grpc::internal::CallOpSet<::grpc::internal::CallOpRecvInitialMetadata,
+                                ::grpc::internal::CallOpClientRecvStatus>
+        ops;
+    if (!context_->initial_metadata_received_) {
+      ops.RecvInitialMetadata(context_);
+    }
+    Status status;
+    ops.ClientRecvStatus(context_, &status);
+    call_.PerformOps(&ops);
+    GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
+    return status;
+  }
+
+ private:
+  friend class internal::ClientReaderWriterFactory<W, R>;
+
+  ClientContext* context_;
+  CompletionQueue cq_;
+  ::grpc::internal::Call call_;
+
+  /// Block to create a stream and write the initial metadata and \a request
+  /// out. Note that \a context will be used to fill in custom initial metadata
+  /// used to send to the server when starting the call.
+  ClientReaderWriter(::grpc::ChannelInterface* channel,
+                     const ::grpc::internal::RpcMethod& method,
+                     ClientContext* context)
+      : context_(context),
+        cq_(grpc_completion_queue_attributes{
+            GRPC_CQ_CURRENT_VERSION, GRPC_CQ_PLUCK, GRPC_CQ_DEFAULT_POLLING,
+            nullptr}),  // Pluckable cq
+        call_(channel->CreateCall(method, context, &cq_)) {
+    if (!context_->initial_metadata_corked_) {
+      ::grpc::internal::CallOpSet<::grpc::internal::CallOpSendInitialMetadata>
+          ops;
+      ops.SendInitialMetadata(&context->send_initial_metadata_,
+                              context->initial_metadata_flags());
+      call_.PerformOps(&ops);
+      cq_.Pluck(&ops);
+    }
+  }
+};
+
+/// Server-side interface for streaming reads of message of type \a R.
+template <class R>
+class ServerReaderInterface : public internal::ServerStreamingInterface,
+                              public internal::ReaderInterface<R> {};
+
+/// Synchronous (blocking) server-side API for doing client-streaming RPCs,
+/// where the incoming message stream coming from the client has messages of
+/// type \a R.
+template <class R>
+class ServerReader final : public ServerReaderInterface<R> {
+ public:
+  /// See the \a ServerStreamingInterface.SendInitialMetadata method
+  /// for semantics. Note that initial metadata will be affected by the
+  /// \a ServerContext associated with this call.
+  void SendInitialMetadata() override {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
+    ops.SendInitialMetadata(&ctx_->initial_metadata_,
+                            ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      ops.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_->PerformOps(&ops);
+    call_->cq()->Pluck(&ops);
+  }
+
+  bool NextMessageSize(uint32_t* sz) override {
+    *sz = call_->max_receive_message_size();
+    return true;
+  }
+
+  bool Read(R* msg) override {
+    internal::CallOpSet<internal::CallOpRecvMessage<R>> ops;
+    ops.RecvMessage(msg);
+    call_->PerformOps(&ops);
+    return call_->cq()->Pluck(&ops) && ops.got_message;
+  }
+
+ private:
+  internal::Call* const call_;
+  ServerContext* const ctx_;
+
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class internal::ClientStreamingHandler;
+
+  ServerReader(internal::Call* call, ServerContext* ctx)
+      : call_(call), ctx_(ctx) {}
+};
+
+/// Server-side interface for streaming writes of message of type \a W.
+template <class W>
+class ServerWriterInterface : public internal::ServerStreamingInterface,
+                              public internal::WriterInterface<W> {};
+
+/// Synchronous (blocking) server-side API for doing for doing a
+/// server-streaming RPCs, where the outgoing message stream coming from the
+/// server has messages of type \a W.
+template <class W>
+class ServerWriter final : public ServerWriterInterface<W> {
+ public:
+  /// See the \a ServerStreamingInterface.SendInitialMetadata method
+  /// for semantics.
+  /// Note that initial metadata will be affected by the
+  /// \a ServerContext associated with this call.
+  void SendInitialMetadata() override {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    internal::CallOpSet<internal::CallOpSendInitialMetadata> ops;
+    ops.SendInitialMetadata(&ctx_->initial_metadata_,
+                            ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      ops.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_->PerformOps(&ops);
+    call_->cq()->Pluck(&ops);
+  }
+
+  /// See the \a WriterInterface.Write method for semantics.
+  ///
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the
+  ///   \a ClientContext associated with this call to fill in values).
+  using internal::WriterInterface<W>::Write;
+  bool Write(const W& msg, WriteOptions options) override {
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+    }
+
+    if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
+      return false;
+    }
+    if (!ctx_->sent_initial_metadata_) {
+      ctx_->pending_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                             ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        ctx_->pending_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+    call_->PerformOps(&ctx_->pending_ops_);
+    // if this is the last message we defer the pluck until AFTER we start
+    // the trailing md op. This prevents hangs. See
+    // https://github.com/grpc/grpc/issues/11546
+    if (options.is_last_message()) {
+      ctx_->has_pending_ops_ = true;
+      return true;
+    }
+    ctx_->has_pending_ops_ = false;
+    return call_->cq()->Pluck(&ctx_->pending_ops_);
+  }
+
+ private:
+  internal::Call* const call_;
+  ServerContext* const ctx_;
+
+  template <class ServiceType, class RequestType, class ResponseType>
+  friend class internal::ServerStreamingHandler;
+
+  ServerWriter(internal::Call* call, ServerContext* ctx)
+      : call_(call), ctx_(ctx) {}
+};
+
+/// Server-side interface for bi-directional streaming.
+template <class W, class R>
+class ServerReaderWriterInterface : public internal::ServerStreamingInterface,
+                                    public internal::WriterInterface<W>,
+                                    public internal::ReaderInterface<R> {};
+
+/// Actual implementation of bi-directional streaming
+namespace internal {
+template <class W, class R>
+class ServerReaderWriterBody final {
+ public:
+  ServerReaderWriterBody(Call* call, ServerContext* ctx)
+      : call_(call), ctx_(ctx) {}
+
+  void SendInitialMetadata() {
+    GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
+
+    CallOpSet<CallOpSendInitialMetadata> ops;
+    ops.SendInitialMetadata(&ctx_->initial_metadata_,
+                            ctx_->initial_metadata_flags());
+    if (ctx_->compression_level_set()) {
+      ops.set_compression_level(ctx_->compression_level());
+    }
+    ctx_->sent_initial_metadata_ = true;
+    call_->PerformOps(&ops);
+    call_->cq()->Pluck(&ops);
+  }
+
+  bool NextMessageSize(uint32_t* sz) {
+    *sz = call_->max_receive_message_size();
+    return true;
+  }
+
+  bool Read(R* msg) {
+    CallOpSet<CallOpRecvMessage<R>> ops;
+    ops.RecvMessage(msg);
+    call_->PerformOps(&ops);
+    return call_->cq()->Pluck(&ops) && ops.got_message;
+  }
+
+  bool Write(const W& msg, WriteOptions options) {
+    if (options.is_last_message()) {
+      options.set_buffer_hint();
+    }
+    if (!ctx_->pending_ops_.SendMessage(msg, options).ok()) {
+      return false;
+    }
+    if (!ctx_->sent_initial_metadata_) {
+      ctx_->pending_ops_.SendInitialMetadata(&ctx_->initial_metadata_,
+                                             ctx_->initial_metadata_flags());
+      if (ctx_->compression_level_set()) {
+        ctx_->pending_ops_.set_compression_level(ctx_->compression_level());
+      }
+      ctx_->sent_initial_metadata_ = true;
+    }
+    call_->PerformOps(&ctx_->pending_ops_);
+    // if this is the last message we defer the pluck until AFTER we start
+    // the trailing md op. This prevents hangs. See
+    // https://github.com/grpc/grpc/issues/11546
+    if (options.is_last_message()) {
+      ctx_->has_pending_ops_ = true;
+      return true;
+    }
+    ctx_->has_pending_ops_ = false;
+    return call_->cq()->Pluck(&ctx_->pending_ops_);
+  }
+
+ private:
+  Call* const call_;
+  ServerContext* const ctx_;
+};
+
+}  // namespace internal
+
+/// Synchronous (blocking) server-side API for a bidirectional
+/// streaming call, where the incoming message stream coming from the client has
+/// messages of type \a R, and the outgoing message streaming coming from
+/// the server has messages of type \a W.
+template <class W, class R>
+class ServerReaderWriter final : public ServerReaderWriterInterface<W, R> {
+ public:
+  /// See the \a ServerStreamingInterface.SendInitialMetadata method
+  /// for semantics. Note that initial metadata will be affected by the
+  /// \a ServerContext associated with this call.
+  void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+
+  bool NextMessageSize(uint32_t* sz) override {
+    return body_.NextMessageSize(sz);
+  }
+
+  bool Read(R* msg) override { return body_.Read(msg); }
+
+  /// See the \a WriterInterface.Write(const W& msg, WriteOptions options)
+  /// method for semantics.
+  /// Side effect:
+  ///   Also sends initial metadata if not already sent (using the \a
+  ///   ServerContext associated with this call).
+  using internal::WriterInterface<W>::Write;
+  bool Write(const W& msg, WriteOptions options) override {
+    return body_.Write(msg, options);
+  }
+
+ private:
+  internal::ServerReaderWriterBody<W, R> body_;
+
+  friend class internal::TemplatedBidiStreamingHandler<ServerReaderWriter<W, R>,
+                                                       false>;
+  ServerReaderWriter(internal::Call* call, ServerContext* ctx)
+      : body_(call, ctx) {}
+};
+
+/// A class to represent a flow-controlled unary call. This is something
+/// of a hybrid between conventional unary and streaming. This is invoked
+/// through a unary call on the client side, but the server responds to it
+/// as though it were a single-ping-pong streaming call. The server can use
+/// the \a NextMessageSize method to determine an upper-bound on the size of
+/// the message. A key difference relative to streaming: ServerUnaryStreamer
+/// must have exactly 1 Read and exactly 1 Write, in that order, to function
+/// correctly. Otherwise, the RPC is in error.
+template <class RequestType, class ResponseType>
+class ServerUnaryStreamer final
+    : public ServerReaderWriterInterface<ResponseType, RequestType> {
+ public:
+  /// Block to send initial metadata to client.
+  /// Implicit input parameter:
+  ///    - the \a ServerContext associated with this call will be used for
+  ///      sending initial metadata.
+  void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+
+  /// Get an upper bound on the request message size from the client.
+  bool NextMessageSize(uint32_t* sz) override {
+    return body_.NextMessageSize(sz);
+  }
+
+  /// Read a message of type \a R into \a msg. Completion will be notified by \a
+  /// tag on the associated completion queue.
+  /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+  /// should not be called concurrently with other streaming APIs
+  /// on the same stream. It is not meaningful to call it concurrently
+  /// with another \a ReaderInterface::Read on the same stream since reads on
+  /// the same stream are delivered in order.
+  ///
+  /// \param[out] msg Where to eventually store the read message.
+  /// \param[in] tag The tag identifying the operation.
+  bool Read(RequestType* request) override {
+    if (read_done_) {
+      return false;
+    }
+    read_done_ = true;
+    return body_.Read(request);
+  }
+
+  /// Block to write \a msg to the stream with WriteOptions \a options.
+  /// This is thread-safe with respect to \a ReaderInterface::Read
+  ///
+  /// \param msg The message to be written to the stream.
+  /// \param options The WriteOptions affecting the write operation.
+  ///
+  /// \return \a true on success, \a false when the stream has been closed.
+  using internal::WriterInterface<ResponseType>::Write;
+  bool Write(const ResponseType& response, WriteOptions options) override {
+    if (write_done_ || !read_done_) {
+      return false;
+    }
+    write_done_ = true;
+    return body_.Write(response, options);
+  }
+
+ private:
+  internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
+  bool read_done_;
+  bool write_done_;
+
+  friend class internal::TemplatedBidiStreamingHandler<
+      ServerUnaryStreamer<RequestType, ResponseType>, true>;
+  ServerUnaryStreamer(internal::Call* call, ServerContext* ctx)
+      : body_(call, ctx), read_done_(false), write_done_(false) {}
+};
+
+/// A class to represent a flow-controlled server-side streaming call.
+/// This is something of a hybrid between server-side and bidi streaming.
+/// This is invoked through a server-side streaming call on the client side,
+/// but the server responds to it as though it were a bidi streaming call that
+/// must first have exactly 1 Read and then any number of Writes.
+template <class RequestType, class ResponseType>
+class ServerSplitStreamer final
+    : public ServerReaderWriterInterface<ResponseType, RequestType> {
+ public:
+  /// Block to send initial metadata to client.
+  /// Implicit input parameter:
+  ///    - the \a ServerContext associated with this call will be used for
+  ///      sending initial metadata.
+  void SendInitialMetadata() override { body_.SendInitialMetadata(); }
+
+  /// Get an upper bound on the request message size from the client.
+  bool NextMessageSize(uint32_t* sz) override {
+    return body_.NextMessageSize(sz);
+  }
+
+  /// Read a message of type \a R into \a msg. Completion will be notified by \a
+  /// tag on the associated completion queue.
+  /// This is thread-safe with respect to \a Write or \a WritesDone methods. It
+  /// should not be called concurrently with other streaming APIs
+  /// on the same stream. It is not meaningful to call it concurrently
+  /// with another \a ReaderInterface::Read on the same stream since reads on
+  /// the same stream are delivered in order.
+  ///
+  /// \param[out] msg Where to eventually store the read message.
+  /// \param[in] tag The tag identifying the operation.
+  bool Read(RequestType* request) override {
+    if (read_done_) {
+      return false;
+    }
+    read_done_ = true;
+    return body_.Read(request);
+  }
+
+  /// Block to write \a msg to the stream with WriteOptions \a options.
+  /// This is thread-safe with respect to \a ReaderInterface::Read
+  ///
+  /// \param msg The message to be written to the stream.
+  /// \param options The WriteOptions affecting the write operation.
+  ///
+  /// \return \a true on success, \a false when the stream has been closed.
+  using internal::WriterInterface<ResponseType>::Write;
+  bool Write(const ResponseType& response, WriteOptions options) override {
+    return read_done_ && body_.Write(response, options);
+  }
+
+ private:
+  internal::ServerReaderWriterBody<ResponseType, RequestType> body_;
+  bool read_done_;
+
+  friend class internal::TemplatedBidiStreamingHandler<
+      ServerSplitStreamer<RequestType, ResponseType>, false>;
+  ServerSplitStreamer(internal::Call* call, ServerContext* ctx)
+      : body_(call, ctx), read_done_(false) {}
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_SYNC_STREAM_H
diff --git a/third_party/grpc/include/grpcpp/impl/codegen/time.h b/third_party/grpc/include/grpcpp/impl/codegen/time.h
new file mode 100644
index 0000000..c32f254
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/codegen/time.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright 2015 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_TIME_H
+#define GRPCPP_IMPL_CODEGEN_TIME_H
+
+#include <chrono>
+
+#include <grpc/impl/codegen/grpc_types.h>
+#include <grpcpp/impl/codegen/config.h>
+
+namespace grpc {
+
+/** If you are trying to use CompletionQueue::AsyncNext with a time class that
+    isn't either gpr_timespec or std::chrono::system_clock::time_point, you
+    will most likely be looking at this comment as your compiler will have
+    fired an error below. In order to fix this issue, you have two potential
+    solutions:
+
+      1. Use gpr_timespec or std::chrono::system_clock::time_point instead
+      2. Specialize the TimePoint class with whichever time class that you
+         want to use here. See below for two examples of how to do this.
+ */
+template <typename T>
+class TimePoint {
+ public:
+  TimePoint(const T& time) { you_need_a_specialization_of_TimePoint(); }
+  gpr_timespec raw_time() {
+    gpr_timespec t;
+    return t;
+  }
+
+ private:
+  void you_need_a_specialization_of_TimePoint();
+};
+
+template <>
+class TimePoint<gpr_timespec> {
+ public:
+  TimePoint(const gpr_timespec& time) : time_(time) {}
+  gpr_timespec raw_time() { return time_; }
+
+ private:
+  gpr_timespec time_;
+};
+
+}  // namespace grpc
+
+namespace grpc {
+
+// from and to should be absolute time.
+void Timepoint2Timespec(const std::chrono::system_clock::time_point& from,
+                        gpr_timespec* to);
+void TimepointHR2Timespec(
+    const std::chrono::high_resolution_clock::time_point& from,
+    gpr_timespec* to);
+
+std::chrono::system_clock::time_point Timespec2Timepoint(gpr_timespec t);
+
+template <>
+class TimePoint<std::chrono::system_clock::time_point> {
+ public:
+  TimePoint(const std::chrono::system_clock::time_point& time) {
+    Timepoint2Timespec(time, &time_);
+  }
+  gpr_timespec raw_time() const { return time_; }
+
+ private:
+  gpr_timespec time_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_CODEGEN_TIME_H
diff --git a/third_party/grpc/include/grpcpp/impl/grpc_library.h b/third_party/grpc/include/grpcpp/impl/grpc_library.h
new file mode 100644
index 0000000..d1f3ff1
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/grpc_library.h
@@ -0,0 +1,61 @@
+/*
+ *
+ * Copyright 2015 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_GRPC_LIBRARY_H
+#define GRPCPP_IMPL_GRPC_LIBRARY_H
+
+#include <iostream>
+
+#include <grpc/grpc.h>
+#include <grpcpp/impl/codegen/config.h>
+#include <grpcpp/impl/codegen/core_codegen.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+
+namespace grpc {
+
+namespace internal {
+class GrpcLibrary final : public GrpcLibraryInterface {
+ public:
+  void init() override { grpc_init(); }
+  void shutdown() override { grpc_shutdown(); }
+};
+
+static GrpcLibrary g_gli;
+static CoreCodegen g_core_codegen;
+
+/// Instantiating this class ensures the proper initialization of gRPC.
+class GrpcLibraryInitializer final {
+ public:
+  GrpcLibraryInitializer() {
+    if (grpc::g_glip == nullptr) {
+      grpc::g_glip = &g_gli;
+    }
+    if (grpc::g_core_codegen_interface == nullptr) {
+      grpc::g_core_codegen_interface = &g_core_codegen;
+    }
+  }
+
+  /// A no-op method to force the linker to reference this class, which will
+  /// take care of initializing and shutting down the gRPC runtime.
+  int summon() { return 0; }
+};
+
+}  // namespace internal
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_GRPC_LIBRARY_H
diff --git a/third_party/grpc/include/grpcpp/impl/method_handler_impl.h b/third_party/grpc/include/grpcpp/impl/method_handler_impl.h
new file mode 100644
index 0000000..7f3be64
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/method_handler_impl.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_METHOD_HANDLER_IMPL_H
+#define GRPCPP_IMPL_METHOD_HANDLER_IMPL_H
+
+#include <grpcpp/impl/codegen/method_handler_impl.h>
+
+#endif  // GRPCPP_IMPL_METHOD_HANDLER_IMPL_H
diff --git a/third_party/grpc/include/grpcpp/impl/rpc_method.h b/third_party/grpc/include/grpcpp/impl/rpc_method.h
new file mode 100644
index 0000000..5da7041
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/rpc_method.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_RPC_METHOD_H
+#define GRPCPP_IMPL_RPC_METHOD_H
+
+#include <grpcpp/impl/codegen/rpc_method.h>
+
+#endif  // GRPCPP_IMPL_RPC_METHOD_H
diff --git a/third_party/grpc/include/grpcpp/impl/rpc_service_method.h b/third_party/grpc/include/grpcpp/impl/rpc_service_method.h
new file mode 100644
index 0000000..ef70a3a
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/rpc_service_method.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2016 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_RPC_SERVICE_METHOD_H
+#define GRPCPP_IMPL_RPC_SERVICE_METHOD_H
+
+#include <grpcpp/impl/codegen/rpc_service_method.h>
+
+#endif  // GRPCPP_IMPL_RPC_SERVICE_METHOD_H
diff --git a/third_party/grpc/include/grpcpp/impl/serialization_traits.h b/third_party/grpc/include/grpcpp/impl/serialization_traits.h
new file mode 100644
index 0000000..95194fb
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/serialization_traits.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_SERIALIZATION_TRAITS_H
+#define GRPCPP_IMPL_SERIALIZATION_TRAITS_H
+
+#include <grpcpp/impl/codegen/serialization_traits.h>
+
+#endif  // GRPCPP_IMPL_SERIALIZATION_TRAITS_H
diff --git a/third_party/grpc/include/grpcpp/impl/server_builder_option.h b/third_party/grpc/include/grpcpp/impl/server_builder_option.h
new file mode 100644
index 0000000..c7b7801
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/server_builder_option.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * Copyright 2015 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_SERVER_BUILDER_OPTION_H
+#define GRPCPP_IMPL_SERVER_BUILDER_OPTION_H
+
+#include <map>
+#include <memory>
+
+#include <grpcpp/impl/server_builder_plugin.h>
+#include <grpcpp/support/channel_arguments.h>
+
+namespace grpc {
+
+/// Interface to pass an option to a \a ServerBuilder.
+class ServerBuilderOption {
+ public:
+  virtual ~ServerBuilderOption() {}
+  /// Alter the \a ChannelArguments used to create the gRPC server.
+  virtual void UpdateArguments(ChannelArguments* args) = 0;
+  /// Alter the ServerBuilderPlugin map that will be added into ServerBuilder.
+  virtual void UpdatePlugins(
+      std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) = 0;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_SERVER_BUILDER_OPTION_H
diff --git a/third_party/grpc/include/grpcpp/impl/server_builder_plugin.h b/third_party/grpc/include/grpcpp/impl/server_builder_plugin.h
new file mode 100644
index 0000000..39450b4
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/server_builder_plugin.h
@@ -0,0 +1,66 @@
+/*
+ *
+ * Copyright 2016 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_SERVER_BUILDER_PLUGIN_H
+#define GRPCPP_IMPL_SERVER_BUILDER_PLUGIN_H
+
+#include <memory>
+
+#include <grpcpp/support/config.h>
+
+namespace grpc {
+
+class ServerBuilder;
+class ServerInitializer;
+class ChannelArguments;
+
+/// This interface is meant for internal usage only. Implementations of this
+/// interface should add themselves to a \a ServerBuilder instance through the
+/// \a InternalAddPluginFactory method.
+class ServerBuilderPlugin {
+ public:
+  virtual ~ServerBuilderPlugin() {}
+  virtual grpc::string name() = 0;
+
+  /// UpdateServerBuilder will be called at an early stage in
+  /// ServerBuilder::BuildAndStart(), right after the ServerBuilderOptions have
+  /// done their updates.
+  virtual void UpdateServerBuilder(ServerBuilder* builder) {}
+
+  /// InitServer will be called in ServerBuilder::BuildAndStart(), after the
+  /// Server instance is created.
+  virtual void InitServer(ServerInitializer* si) = 0;
+
+  /// Finish will be called at the end of ServerBuilder::BuildAndStart().
+  virtual void Finish(ServerInitializer* si) = 0;
+
+  /// ChangeArguments is an interface that can be used in
+  /// ServerBuilderOption::UpdatePlugins
+  virtual void ChangeArguments(const grpc::string& name, void* value) = 0;
+
+  /// UpdateChannelArguments will be called in ServerBuilder::BuildAndStart(),
+  /// before the Server instance is created.
+  virtual void UpdateChannelArguments(ChannelArguments* args) {}
+
+  virtual bool has_sync_methods() const { return false; }
+  virtual bool has_async_methods() const { return false; }
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_SERVER_BUILDER_PLUGIN_H
diff --git a/third_party/grpc/include/grpcpp/impl/server_initializer.h b/third_party/grpc/include/grpcpp/impl/server_initializer.h
new file mode 100644
index 0000000..f949fab
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/server_initializer.h
@@ -0,0 +1,55 @@
+/*
+ *
+ * Copyright 2016 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_SERVER_INITIALIZER_H
+#define GRPCPP_IMPL_SERVER_INITIALIZER_H
+
+#include <memory>
+#include <vector>
+
+#include <grpcpp/server.h>
+
+namespace grpc {
+
+class Server;
+class Service;
+
+class ServerInitializer {
+ public:
+  ServerInitializer(Server* server) : server_(server) {}
+
+  bool RegisterService(std::shared_ptr<Service> service) {
+    if (!server_->RegisterService(nullptr, service.get())) {
+      return false;
+    }
+    default_services_.push_back(service);
+    return true;
+  }
+
+  const std::vector<grpc::string>* GetServiceList() {
+    return &server_->services_;
+  }
+
+ private:
+  Server* server_;
+  std::vector<std::shared_ptr<Service> > default_services_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCPP_IMPL_SERVER_INITIALIZER_H
diff --git a/third_party/grpc/include/grpcpp/impl/service_type.h b/third_party/grpc/include/grpcpp/impl/service_type.h
new file mode 100644
index 0000000..250bc8c
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/service_type.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_SERVICE_TYPE_H
+#define GRPCPP_IMPL_SERVICE_TYPE_H
+
+#include <grpcpp/impl/codegen/service_type.h>
+
+#endif  // GRPCPP_IMPL_SERVICE_TYPE_H
diff --git a/third_party/grpc/include/grpcpp/impl/sync_cxx11.h b/third_party/grpc/include/grpcpp/impl/sync_cxx11.h
new file mode 100644
index 0000000..76dcfe3
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/sync_cxx11.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_SYNC_CXX11_H
+#define GRPCPP_IMPL_SYNC_CXX11_H
+
+#include <grpcpp/impl/codegen/sync_cxx11.h>
+
+#endif  // GRPCPP_IMPL_SYNC_CXX11_H
diff --git a/third_party/grpc/include/grpcpp/impl/sync_no_cxx11.h b/third_party/grpc/include/grpcpp/impl/sync_no_cxx11.h
new file mode 100644
index 0000000..cc2d4f1
--- /dev/null
+++ b/third_party/grpc/include/grpcpp/impl/sync_no_cxx11.h
@@ -0,0 +1,24 @@
+/*
+ *
+ * Copyright 2015 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_SYNC_NO_CXX11_H
+#define GRPCPP_IMPL_SYNC_NO_CXX11_H
+
+#include <grpcpp/impl/codegen/sync_no_cxx11.h>
+
+#endif  // GRPCPP_IMPL_SYNC_NO_CXX11_H