Update bundled gRPC to 1.18.0 and nanopb to 0.3.6

And take the opportunity to align third_party/grpc/BUILD closer with
gRPC upstream's BUILD file (by adopting the same intermediate targets)
to make importing easier next time.

The MSYS2 patch is no longer needed judging by discussion in
https://groups.google.com/forum/#!msg/grpc-io/gd6sIuo6rjQ/eyEFarhABgAJ

Fixes #2804.
diff --git a/third_party/grpc/src/cpp/README.md b/third_party/grpc/src/cpp/README.md
index baeba08..4ec9133 100644
--- a/third_party/grpc/src/cpp/README.md
+++ b/third_party/grpc/src/cpp/README.md
@@ -1,8 +1,83 @@
 
-#Overview
+# Overview
 
-This directory contains source code for C++ implementation of gRPC.
+A C++ implementation of gRPC
 
-#Status
+# To start using gRPC C++
 
-Beta
+In the C++ world, there's no universally accepted standard for managing project dependencies.
+Therefore, gRPC supports several major build systems, which should satisfy most users.
+
+## bazel
+
+We recommend using Bazel for projects that use gRPC as it will give you the best developer experience
+(easy handling of dependencies that support bazel & fast builds).
+
+To add gRPC as a dependency in bazel:
+1. determine commit SHA for the grpc release you want to use
+2. Use the [http_archive](https://docs.bazel.build/versions/master/be/workspace.html#http_archive) bazel rule to include gRPC source
+  ```
+  http_archive(
+      name = "com_github_grpc_grpc",
+      urls = [
+          "https://github.com/grpc/grpc/archive/YOUR_GRPC_COMMIT_SHA.tar.gz",
+      ],
+      strip_prefix = "grpc-YOUR_GRPC_COMMIT_SHA",
+  )
+
+  load("@com_github_grpc_grpc//bazel:grpc_deps.bzl", "grpc_deps")
+
+  grpc_deps()
+  ```
+
+NOTE: currently bazel is only supported for building gRPC on Linux.
+
+## make
+
+Currently the default choice for building on UNIX based systems is `make`.
+
+To install gRPC for C++ on your system using `make`, follow the [Building gRPC C++](../../BUILDING.md)
+instructions to build from source and then install locally using `make install`.
+This also installs the protocol buffer compiler `protoc` (if you don't have it already),
+and the C++ gRPC plugin for `protoc`.
+
+WARNING: After installing with `make install` there is no easy way to uninstall, which can cause issues
+if you later want to remove the grpc and/or protobuf installation or upgrade to a newer version.
+
+## cmake
+
+`cmake` is the default build option on Windows, but also works on Linux, MacOS. `cmake` has good
+support for crosscompiling and can be used for targeting Android platform.
+
+If your project is using cmake, there are several ways to add gRPC dependency.
+- install gRPC via cmake first and then locate it with `find_package(gRPC CONFIG)`. [Example](../../examples/cpp/helloworld/CMakeLists.txt)
+- via cmake's `ExternalProject_Add` using a technique called "superbuild". [Example](../../examples/cpp/helloworld/cmake_externalproject/CMakeLists.txt)
+- add gRPC source tree to your project (preferrably as a git submodule) and add it to your cmake project with `add_subdirectory`. [Example](../../examples/cpp/helloworld/CMakeLists.txt)
+
+## Packaging systems
+
+There's no standard packaging system for C++. We've looked into supporting some (e.g. Conan and vcpkg) but we are not there yet.
+Contributions and community-maintained packages for popular packaging systems are welcome!
+
+
+## Examples & Additional Documentation
+
+You can find out how to build and run our simplest gRPC C++ example in our
+[C++ quick start](../../examples/cpp).
+
+For more detailed documentation on using gRPC in C++ , see our main
+documentation site at [grpc.io](https://grpc.io), specifically:
+
+* [Overview](https://grpc.io/docs/): An introduction to gRPC with a simple
+  Hello World example in all our supported languages, including C++.
+* [gRPC Basics - C++](https://grpc.io/docs/tutorials/basic/c.html):
+  A tutorial that steps you through creating a simple gRPC C++ example
+  application.
+* [Asynchronous Basics - C++](https://grpc.io/docs/tutorials/async/helloasync-cpp.html):
+  A tutorial that shows you how to use gRPC C++'s asynchronous/non-blocking
+  APIs.
+
+
+# To start developing gRPC C++
+
+For instructions on how to build gRPC C++ from source, follow the [Building gRPC C++](../../BUILDING.md) instructions.
diff --git a/third_party/grpc/src/cpp/client/channel.cc b/third_party/grpc/src/cpp/client/channel.cc
deleted file mode 100644
index ae20392..0000000
--- a/third_party/grpc/src/cpp/client/channel.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/channel.h>
-
-#include <memory>
-
-#include <grpc++/client_context.h>
-#include <grpc++/completion_queue.h>
-#include <grpc++/impl/call.h>
-#include <grpc++/impl/codegen/completion_queue_tag.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/impl/rpc_method.h>
-#include <grpc++/security/credentials.h>
-#include <grpc++/support/channel_arguments.h>
-#include <grpc++/support/config.h>
-#include <grpc++/support/status.h>
-#include <grpc++/support/time.h>
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice.h>
-#include "src/core/profiling/timers.h"
-
-namespace grpc {
-
-static internal::GrpcLibraryInitializer g_gli_initializer;
-Channel::Channel(const grpc::string& host, grpc_channel* channel)
-    : host_(host), c_channel_(channel) {
-  g_gli_initializer.summon();
-}
-
-Channel::~Channel() { grpc_channel_destroy(c_channel_); }
-
-Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
-                         CompletionQueue* cq) {
-  const bool kRegistered = method.channel_tag() && context->authority().empty();
-  grpc_call* c_call = NULL;
-  if (kRegistered) {
-    c_call = grpc_channel_create_registered_call(
-        c_channel_, context->propagate_from_call_,
-        context->propagation_options_.c_bitmask(), cq->cq(),
-        method.channel_tag(), context->raw_deadline(), nullptr);
-  } else {
-    const char* host_str = NULL;
-    if (!context->authority().empty()) {
-      host_str = context->authority_.c_str();
-    } else if (!host_.empty()) {
-      host_str = host_.c_str();
-    }
-    c_call = grpc_channel_create_call(c_channel_, context->propagate_from_call_,
-                                      context->propagation_options_.c_bitmask(),
-                                      cq->cq(), method.name(), host_str,
-                                      context->raw_deadline(), nullptr);
-  }
-  grpc_census_call_set_context(c_call, context->census_context());
-  context->set_call(c_call, shared_from_this());
-  return Call(c_call, this, cq);
-}
-
-void Channel::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) {
-  static const size_t MAX_OPS = 8;
-  size_t nops = 0;
-  grpc_op cops[MAX_OPS];
-  ops->FillOps(cops, &nops);
-  GPR_ASSERT(GRPC_CALL_OK ==
-             grpc_call_start_batch(call->call(), cops, nops, ops, nullptr));
-}
-
-void* Channel::RegisterMethod(const char* method) {
-  return grpc_channel_register_call(
-      c_channel_, method, host_.empty() ? NULL : host_.c_str(), nullptr);
-}
-
-grpc_connectivity_state Channel::GetState(bool try_to_connect) {
-  return grpc_channel_check_connectivity_state(c_channel_, try_to_connect);
-}
-
-namespace {
-class TagSaver GRPC_FINAL : public CompletionQueueTag {
- public:
-  explicit TagSaver(void* tag) : tag_(tag) {}
-  ~TagSaver() GRPC_OVERRIDE {}
-  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
-    *tag = tag_;
-    delete this;
-    return true;
-  }
-
- private:
-  void* tag_;
-};
-
-}  // namespace
-
-void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
-                                      gpr_timespec deadline,
-                                      CompletionQueue* cq, void* tag) {
-  TagSaver* tag_saver = new TagSaver(tag);
-  grpc_channel_watch_connectivity_state(c_channel_, last_observed, deadline,
-                                        cq->cq(), tag_saver);
-}
-
-bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed,
-                                     gpr_timespec deadline) {
-  CompletionQueue cq;
-  bool ok = false;
-  void* tag = NULL;
-  NotifyOnStateChangeImpl(last_observed, deadline, &cq, NULL);
-  cq.Next(&tag, &ok);
-  GPR_ASSERT(tag == NULL);
-  return ok;
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/channel_cc.cc b/third_party/grpc/src/cpp/client/channel_cc.cc
new file mode 100644
index 0000000..a31d0b3
--- /dev/null
+++ b/third_party/grpc/src/cpp/client/channel_cc.cc
@@ -0,0 +1,255 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/channel.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <cstring>
+#include <memory>
+#include <mutex>
+
+#include <grpc/grpc.h>
+#include <grpc/slice.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/sync.h>
+#include <grpc/support/time.h>
+#include <grpcpp/client_context.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/impl/call.h>
+#include <grpcpp/impl/codegen/call_op_set.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/impl/rpc_method.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/support/channel_arguments.h>
+#include <grpcpp/support/config.h>
+#include <grpcpp/support/status.h>
+#include <grpcpp/support/time.h>
+#include "src/core/lib/gpr/env.h"
+#include "src/core/lib/gpr/string.h"
+#include "src/core/lib/gprpp/memory.h"
+#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/surface/completion_queue.h"
+
+namespace grpc {
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+Channel::Channel(
+    const grpc::string& host, grpc_channel* channel,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators)
+    : host_(host), c_channel_(channel) {
+  interceptor_creators_ = std::move(interceptor_creators);
+  g_gli_initializer.summon();
+}
+
+Channel::~Channel() {
+  grpc_channel_destroy(c_channel_);
+  if (callback_cq_ != nullptr) {
+    callback_cq_->Shutdown();
+  }
+}
+
+namespace {
+
+inline grpc_slice SliceFromArray(const char* arr, size_t len) {
+  return g_core_codegen_interface->grpc_slice_from_copied_buffer(arr, len);
+}
+
+grpc::string GetChannelInfoField(grpc_channel* channel,
+                                 grpc_channel_info* channel_info,
+                                 char*** channel_info_field) {
+  char* value = nullptr;
+  memset(channel_info, 0, sizeof(*channel_info));
+  *channel_info_field = &value;
+  grpc_channel_get_info(channel, channel_info);
+  if (value == nullptr) return "";
+  grpc::string result = value;
+  gpr_free(value);
+  return result;
+}
+
+}  // namespace
+
+grpc::string Channel::GetLoadBalancingPolicyName() const {
+  grpc_channel_info channel_info;
+  return GetChannelInfoField(c_channel_, &channel_info,
+                             &channel_info.lb_policy_name);
+}
+
+grpc::string Channel::GetServiceConfigJSON() const {
+  grpc_channel_info channel_info;
+  return GetChannelInfoField(c_channel_, &channel_info,
+                             &channel_info.service_config_json);
+}
+
+namespace experimental {
+
+void ChannelResetConnectionBackoff(Channel* channel) {
+  grpc_channel_reset_connect_backoff(channel->c_channel_);
+}
+
+}  // namespace experimental
+
+internal::Call Channel::CreateCallInternal(const internal::RpcMethod& method,
+                                           ClientContext* context,
+                                           CompletionQueue* cq,
+                                           size_t interceptor_pos) {
+  const bool kRegistered = method.channel_tag() && context->authority().empty();
+  grpc_call* c_call = nullptr;
+  if (kRegistered) {
+    c_call = grpc_channel_create_registered_call(
+        c_channel_, context->propagate_from_call_,
+        context->propagation_options_.c_bitmask(), cq->cq(),
+        method.channel_tag(), context->raw_deadline(), nullptr);
+  } else {
+    const string* host_str = nullptr;
+    if (!context->authority_.empty()) {
+      host_str = &context->authority_;
+    } else if (!host_.empty()) {
+      host_str = &host_;
+    }
+    grpc_slice method_slice =
+        SliceFromArray(method.name(), strlen(method.name()));
+    grpc_slice host_slice;
+    if (host_str != nullptr) {
+      host_slice = SliceFromCopiedString(*host_str);
+    }
+    c_call = grpc_channel_create_call(
+        c_channel_, context->propagate_from_call_,
+        context->propagation_options_.c_bitmask(), cq->cq(), method_slice,
+        host_str == nullptr ? nullptr : &host_slice, context->raw_deadline(),
+        nullptr);
+    grpc_slice_unref(method_slice);
+    if (host_str != nullptr) {
+      grpc_slice_unref(host_slice);
+    }
+  }
+  grpc_census_call_set_context(c_call, context->census_context());
+
+  // ClientRpcInfo should be set before call because set_call also checks
+  // whether the call has been cancelled, and if the call was cancelled, we
+  // should notify the interceptors too/
+  auto* info =
+      context->set_client_rpc_info(method.name(), method.method_type(), this,
+                                   interceptor_creators_, interceptor_pos);
+  context->set_call(c_call, shared_from_this());
+
+  return internal::Call(c_call, this, cq, info);
+}
+
+internal::Call Channel::CreateCall(const internal::RpcMethod& method,
+                                   ClientContext* context,
+                                   CompletionQueue* cq) {
+  return CreateCallInternal(method, context, cq, 0);
+}
+
+void Channel::PerformOpsOnCall(internal::CallOpSetInterface* ops,
+                               internal::Call* call) {
+  ops->FillOps(
+      call);  // Make a copy of call. It's fine since Call just has pointers
+}
+
+void* Channel::RegisterMethod(const char* method) {
+  return grpc_channel_register_call(
+      c_channel_, method, host_.empty() ? nullptr : host_.c_str(), nullptr);
+}
+
+grpc_connectivity_state Channel::GetState(bool try_to_connect) {
+  return grpc_channel_check_connectivity_state(c_channel_, try_to_connect);
+}
+
+namespace {
+
+class TagSaver final : public internal::CompletionQueueTag {
+ public:
+  explicit TagSaver(void* tag) : tag_(tag) {}
+  ~TagSaver() override {}
+  bool FinalizeResult(void** tag, bool* status) override {
+    *tag = tag_;
+    delete this;
+    return true;
+  }
+
+ private:
+  void* tag_;
+};
+
+}  // namespace
+
+void Channel::NotifyOnStateChangeImpl(grpc_connectivity_state last_observed,
+                                      gpr_timespec deadline,
+                                      CompletionQueue* cq, void* tag) {
+  TagSaver* tag_saver = new TagSaver(tag);
+  grpc_channel_watch_connectivity_state(c_channel_, last_observed, deadline,
+                                        cq->cq(), tag_saver);
+}
+
+bool Channel::WaitForStateChangeImpl(grpc_connectivity_state last_observed,
+                                     gpr_timespec deadline) {
+  CompletionQueue cq;
+  bool ok = false;
+  void* tag = nullptr;
+  NotifyOnStateChangeImpl(last_observed, deadline, &cq, nullptr);
+  cq.Next(&tag, &ok);
+  GPR_ASSERT(tag == nullptr);
+  return ok;
+}
+
+namespace {
+class ShutdownCallback : public grpc_experimental_completion_queue_functor {
+ public:
+  ShutdownCallback() { functor_run = &ShutdownCallback::Run; }
+  // TakeCQ takes ownership of the cq into the shutdown callback
+  // so that the shutdown callback will be responsible for destroying it
+  void TakeCQ(CompletionQueue* cq) { cq_ = cq; }
+
+  // The Run function will get invoked by the completion queue library
+  // when the shutdown is actually complete
+  static void Run(grpc_experimental_completion_queue_functor* cb, int) {
+    auto* callback = static_cast<ShutdownCallback*>(cb);
+    delete callback->cq_;
+    delete callback;
+  }
+
+ private:
+  CompletionQueue* cq_ = nullptr;
+};
+}  // namespace
+
+CompletionQueue* Channel::CallbackCQ() {
+  // TODO(vjpai): Consider using a single global CQ for the default CQ
+  // if there is no explicit per-channel CQ registered
+  std::lock_guard<std::mutex> l(mu_);
+  if (callback_cq_ == nullptr) {
+    auto* shutdown_callback = new ShutdownCallback;
+    callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{
+        GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING,
+        shutdown_callback});
+
+    // Transfer ownership of the new cq to its own shutdown callback
+    shutdown_callback->TakeCQ(callback_cq_);
+  }
+  return callback_cq_;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/client_context.cc b/third_party/grpc/src/cpp/client/client_context.cc
index 73147fd..c9ea3e5 100644
--- a/third_party/grpc/src/cpp/client/client_context.cc
+++ b/third_party/grpc/src/cpp/client/client_context.cc
@@ -1,75 +1,69 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/client_context.h>
+#include <grpcpp/client_context.h>
 
 #include <grpc/compression.h>
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
-#include <grpc++/security/credentials.h>
-#include <grpc++/server_context.h>
-#include <grpc++/support/time.h>
 
-#include "src/core/channel/compress_filter.h"
-#include "src/cpp/common/create_auth_context.h"
+#include <grpcpp/impl/codegen/interceptor_common.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/server_context.h>
+#include <grpcpp/support/time.h>
 
 namespace grpc {
 
-class DefaultGlobalClientCallbacks GRPC_FINAL
+class DefaultGlobalClientCallbacks final
     : public ClientContext::GlobalCallbacks {
  public:
-  ~DefaultGlobalClientCallbacks() GRPC_OVERRIDE {}
-  void DefaultConstructor(ClientContext* context) GRPC_OVERRIDE {}
-  void Destructor(ClientContext* context) GRPC_OVERRIDE {}
+  ~DefaultGlobalClientCallbacks() override {}
+  void DefaultConstructor(ClientContext* context) override {}
+  void Destructor(ClientContext* context) override {}
 };
 
-static DefaultGlobalClientCallbacks g_default_client_callbacks;
+static internal::GrpcLibraryInitializer g_gli_initializer;
+static DefaultGlobalClientCallbacks* g_default_client_callbacks =
+    new DefaultGlobalClientCallbacks();
 static ClientContext::GlobalCallbacks* g_client_callbacks =
-    &g_default_client_callbacks;
+    g_default_client_callbacks;
 
 ClientContext::ClientContext()
     : initial_metadata_received_(false),
+      wait_for_ready_(false),
+      wait_for_ready_explicitly_set_(false),
+      idempotent_(false),
+      cacheable_(false),
       call_(nullptr),
       call_canceled_(false),
       deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
-      propagate_from_call_(nullptr) {
+      census_context_(nullptr),
+      propagate_from_call_(nullptr),
+      initial_metadata_corked_(false) {
   g_client_callbacks->DefaultConstructor(this);
 }
 
 ClientContext::~ClientContext() {
   if (call_) {
-    grpc_call_destroy(call_);
+    grpc_call_unref(call_);
   }
   g_client_callbacks->Destructor(this);
 }
@@ -89,47 +83,52 @@
 
 void ClientContext::set_call(grpc_call* call,
                              const std::shared_ptr<Channel>& channel) {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
+  std::unique_lock<std::mutex> lock(mu_);
   GPR_ASSERT(call_ == nullptr);
   call_ = call;
   channel_ = channel;
   if (creds_ && !creds_->ApplyToCall(call_)) {
+    // TODO(yashykt): should interceptors also see this status?
+    SendCancelToInterceptors();
     grpc_call_cancel_with_status(call, GRPC_STATUS_CANCELLED,
                                  "Failed to set credentials to rpc.", nullptr);
   }
   if (call_canceled_) {
+    SendCancelToInterceptors();
     grpc_call_cancel(call_, nullptr);
   }
 }
 
 void ClientContext::set_compression_algorithm(
     grpc_compression_algorithm algorithm) {
-  char* algorithm_name = nullptr;
+  compression_algorithm_ = algorithm;
+  const char* algorithm_name = nullptr;
   if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
     gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.",
             algorithm);
     abort();
   }
   GPR_ASSERT(algorithm_name != nullptr);
-  AddMetadata(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, algorithm_name);
-}
-
-std::shared_ptr<const AuthContext> ClientContext::auth_context() const {
-  if (auth_context_.get() == nullptr) {
-    auth_context_ = CreateAuthContext(call_);
-  }
-  return auth_context_;
+  AddMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name);
 }
 
 void ClientContext::TryCancel() {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
+  std::unique_lock<std::mutex> lock(mu_);
   if (call_) {
+    SendCancelToInterceptors();
     grpc_call_cancel(call_, nullptr);
   } else {
     call_canceled_ = true;
   }
 }
 
+void ClientContext::SendCancelToInterceptors() {
+  internal::CancelInterceptorBatchMethods cancel_methods;
+  for (size_t i = 0; i < rpc_info_.interceptors_.size(); i++) {
+    rpc_info_.RunInterceptor(&cancel_methods, i);
+  }
+}
+
 grpc::string ClientContext::peer() const {
   grpc::string peer;
   if (call_) {
@@ -141,9 +140,9 @@
 }
 
 void ClientContext::SetGlobalCallbacks(GlobalCallbacks* client_callbacks) {
-  GPR_ASSERT(g_client_callbacks == &g_default_client_callbacks);
-  GPR_ASSERT(client_callbacks != NULL);
-  GPR_ASSERT(client_callbacks != &g_default_client_callbacks);
+  GPR_ASSERT(g_client_callbacks == g_default_client_callbacks);
+  GPR_ASSERT(client_callbacks != nullptr);
+  GPR_ASSERT(client_callbacks != g_default_client_callbacks);
   g_client_callbacks = client_callbacks;
 }
 
diff --git a/third_party/grpc/src/cpp/client/client_interceptor.cc b/third_party/grpc/src/cpp/client/client_interceptor.cc
new file mode 100644
index 0000000..3a5cac9
--- /dev/null
+++ b/third_party/grpc/src/cpp/client/client_interceptor.cc
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/impl/codegen/client_interceptor.h>
+
+namespace grpc {
+
+namespace internal {
+experimental::ClientInterceptorFactoryInterface*
+    g_global_client_interceptor_factory = nullptr;
+}
+
+namespace experimental {
+void RegisterGlobalClientInterceptorFactory(
+    ClientInterceptorFactoryInterface* factory) {
+  internal::g_global_client_interceptor_factory = factory;
+}
+}  // namespace experimental
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/create_channel.cc b/third_party/grpc/src/cpp/client/create_channel.cc
index a1b65af..457daa6 100644
--- a/third_party/grpc/src/cpp/client/create_channel.cc
+++ b/third_party/grpc/src/cpp/client/create_channel.cc
@@ -1,43 +1,27 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
 #include <memory>
-#include <sstream>
 
-#include <grpc++/channel.h>
-#include <grpc++/create_channel.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/support/channel_arguments.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/support/channel_arguments.h>
 
 #include "src/cpp/client/create_channel_internal.h"
 
@@ -50,29 +34,50 @@
   return CreateCustomChannel(target, creds, ChannelArguments());
 }
 
-// GCC-specific features
-#if (defined(COMPILER_GCC3) || defined(__APPLE__)) && !defined(SWIG)
-#define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
-#else  // Not GCC
-#define ATTRIBUTE_UNUSED
-#endif  // GCC
-
 std::shared_ptr<Channel> CreateCustomChannel(
     const grpc::string& target,
     const std::shared_ptr<ChannelCredentials>& creds,
     const ChannelArguments& args) {
-  ATTRIBUTE_UNUSED internal::GrpcLibrary
-      init_lib;  // We need to call init in case of a bad creds.
-  ChannelArguments cp_args = args;
-  std::ostringstream user_agent_prefix;
-  user_agent_prefix << "grpc-c++/" << grpc_version_string();
-  cp_args.SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING,
-                    user_agent_prefix.str());
-  return creds
-             ? creds->CreateChannel(target, cp_args)
-             : CreateChannelInternal("", grpc_lame_client_channel_create(
-                                             NULL, GRPC_STATUS_INVALID_ARGUMENT,
-                                             "Invalid credentials."));
+  GrpcLibraryCodegen init_lib;  // We need to call init in case of a bad creds.
+  return creds ? creds->CreateChannel(target, args)
+               : CreateChannelInternal(
+                     "",
+                     grpc_lame_client_channel_create(
+                         nullptr, GRPC_STATUS_INVALID_ARGUMENT,
+                         "Invalid credentials."),
+                     std::vector<std::unique_ptr<
+                         experimental::ClientInterceptorFactoryInterface>>());
 }
 
+namespace experimental {
+/// Create a new \em custom \a Channel pointing to \a target with \a
+/// interceptors being invoked per call.
+///
+/// \warning For advanced use and testing ONLY. Override default channel
+/// arguments only if necessary.
+///
+/// \param target The URI of the endpoint to connect to.
+/// \param creds Credentials to use for the created channel. If it does not
+/// hold an object or is invalid, a lame channel (one on which all operations
+/// fail) is returned.
+/// \param args Options for channel creation.
+std::shared_ptr<Channel> CreateCustomChannelWithInterceptors(
+    const grpc::string& target,
+    const std::shared_ptr<ChannelCredentials>& creds,
+    const ChannelArguments& args,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators) {
+  return creds ? creds->CreateChannelWithInterceptors(
+                     target, args, std::move(interceptor_creators))
+               : CreateChannelInternal(
+                     "",
+                     grpc_lame_client_channel_create(
+                         nullptr, GRPC_STATUS_INVALID_ARGUMENT,
+                         "Invalid credentials."),
+                     std::vector<std::unique_ptr<
+                         experimental::ClientInterceptorFactoryInterface>>());
+}
+}  // namespace experimental
+
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/create_channel_internal.cc b/third_party/grpc/src/cpp/client/create_channel_internal.cc
index 9c5ab03..a0efb97 100644
--- a/third_party/grpc/src/cpp/client/create_channel_internal.cc
+++ b/third_party/grpc/src/cpp/client/create_channel_internal.cc
@@ -1,46 +1,35 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
 #include <memory>
 
-#include <grpc++/channel.h>
+#include <grpcpp/channel.h>
 
 struct grpc_channel;
 
 namespace grpc {
 
-std::shared_ptr<Channel> CreateChannelInternal(const grpc::string& host,
-                                               grpc_channel* c_channel) {
-  return std::shared_ptr<Channel>(new Channel(host, c_channel));
+std::shared_ptr<Channel> CreateChannelInternal(
+    const grpc::string& host, grpc_channel* c_channel,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators) {
+  return std::shared_ptr<Channel>(
+      new Channel(host, c_channel, std::move(interceptor_creators)));
 }
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/create_channel_internal.h b/third_party/grpc/src/cpp/client/create_channel_internal.h
index 4385ec7..a90c92c 100644
--- a/third_party/grpc/src/cpp/client/create_channel_internal.h
+++ b/third_party/grpc/src/cpp/client/create_channel_internal.h
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -36,15 +21,19 @@
 
 #include <memory>
 
-#include <grpc++/support/config.h>
+#include <grpcpp/impl/codegen/client_interceptor.h>
+#include <grpcpp/support/config.h>
 
 struct grpc_channel;
 
 namespace grpc {
 class Channel;
 
-std::shared_ptr<Channel> CreateChannelInternal(const grpc::string& host,
-                                               grpc_channel* c_channel);
+std::shared_ptr<Channel> CreateChannelInternal(
+    const grpc::string& host, grpc_channel* c_channel,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators);
 
 }  // namespace grpc
 
diff --git a/third_party/grpc/src/cpp/client/create_channel_posix.cc b/third_party/grpc/src/cpp/client/create_channel_posix.cc
new file mode 100644
index 0000000..3affc1e
--- /dev/null
+++ b/third_party/grpc/src/cpp/client/create_channel_posix.cc
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/grpc.h>
+#include <grpc/grpc_posix.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/create_channel.h>
+#include <grpcpp/impl/grpc_library.h>
+
+#include "src/cpp/client/create_channel_internal.h"
+
+namespace grpc {
+
+#ifdef GPR_SUPPORT_CHANNELS_FROM_FD
+
+std::shared_ptr<Channel> CreateInsecureChannelFromFd(const grpc::string& target,
+                                                     int fd) {
+  internal::GrpcLibrary init_lib;
+  init_lib.init();
+  return CreateChannelInternal(
+      "", grpc_insecure_channel_create_from_fd(target.c_str(), fd, nullptr),
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
+}
+
+std::shared_ptr<Channel> CreateCustomInsecureChannelFromFd(
+    const grpc::string& target, int fd, const ChannelArguments& args) {
+  internal::GrpcLibrary init_lib;
+  init_lib.init();
+  grpc_channel_args channel_args;
+  args.SetChannelArgs(&channel_args);
+  return CreateChannelInternal(
+      "",
+      grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args),
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
+}
+
+namespace experimental {
+
+std::shared_ptr<Channel> CreateCustomInsecureChannelWithInterceptorsFromFd(
+    const grpc::string& target, int fd, const ChannelArguments& args,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators) {
+  internal::GrpcLibrary init_lib;
+  init_lib.init();
+  grpc_channel_args channel_args;
+  args.SetChannelArgs(&channel_args);
+  return CreateChannelInternal(
+      "",
+      grpc_insecure_channel_create_from_fd(target.c_str(), fd, &channel_args),
+      std::move(interceptor_creators));
+}
+
+}  // namespace experimental
+
+#endif  // GPR_SUPPORT_CHANNELS_FROM_FD
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/credentials.cc b/third_party/grpc/src/cpp/client/credentials.cc
deleted file mode 100644
index 6fb620b..0000000
--- a/third_party/grpc/src/cpp/client/credentials.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/security/credentials.h>
-
-namespace grpc {
-
-static internal::GrpcLibraryInitializer g_gli_initializer;
-ChannelCredentials::ChannelCredentials() { g_gli_initializer.summon(); }
-
-ChannelCredentials::~ChannelCredentials() {}
-
-CallCredentials::CallCredentials() { g_gli_initializer.summon(); }
-
-CallCredentials::~CallCredentials() {}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/credentials_cc.cc b/third_party/grpc/src/cpp/client/credentials_cc.cc
new file mode 100644
index 0000000..2a0f06f
--- /dev/null
+++ b/third_party/grpc/src/cpp/client/credentials_cc.cc
@@ -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.
+ *
+ */
+
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/security/credentials.h>
+
+namespace grpc {
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+ChannelCredentials::ChannelCredentials() { g_gli_initializer.summon(); }
+
+ChannelCredentials::~ChannelCredentials() {}
+
+CallCredentials::CallCredentials() { g_gli_initializer.summon(); }
+
+CallCredentials::~CallCredentials() {}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/cronet_credentials.cc b/third_party/grpc/src/cpp/client/cronet_credentials.cc
new file mode 100644
index 0000000..b280176
--- /dev/null
+++ b/third_party/grpc/src/cpp/client/cronet_credentials.cc
@@ -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.
+ *
+ */
+
+#include <grpcpp/security/credentials.h>
+
+#include <grpc/grpc_cronet.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/support/channel_arguments.h>
+#include "src/cpp/client/create_channel_internal.h"
+
+namespace grpc {
+
+class CronetChannelCredentialsImpl final : public ChannelCredentials {
+ public:
+  CronetChannelCredentialsImpl(void* engine) : engine_(engine) {}
+
+  std::shared_ptr<grpc::Channel> CreateChannel(
+      const string& target, const grpc::ChannelArguments& args) override {
+    return CreateChannelWithInterceptors(
+        target, args,
+        std::vector<std::unique_ptr<
+            experimental::ClientInterceptorFactoryInterface>>());
+  }
+
+  SecureChannelCredentials* AsSecureCredentials() override { return nullptr; }
+
+ private:
+  std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
+      const string& target, const grpc::ChannelArguments& args,
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+          interceptor_creators) override {
+    grpc_channel_args channel_args;
+    args.SetChannelArgs(&channel_args);
+    return CreateChannelInternal(
+        "",
+        grpc_cronet_secure_channel_create(engine_, target.c_str(),
+                                          &channel_args, nullptr),
+        std::move(interceptor_creators));
+  }
+  void* engine_;
+};
+
+std::shared_ptr<ChannelCredentials> CronetChannelCredentials(void* engine) {
+  return std::shared_ptr<ChannelCredentials>(
+      new CronetChannelCredentialsImpl(engine));
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/generic_stub.cc b/third_party/grpc/src/cpp/client/generic_stub.cc
index 7a2fdf9..f61c1b5 100644
--- a/third_party/grpc/src/cpp/client/generic_stub.cc
+++ b/third_party/grpc/src/cpp/client/generic_stub.cc
@@ -1,50 +1,84 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/generic/generic_stub.h>
+#include <functional>
 
-#include <grpc++/impl/rpc_method.h>
+#include <grpcpp/generic/generic_stub.h>
+#include <grpcpp/impl/rpc_method.h>
+#include <grpcpp/support/client_callback.h>
 
 namespace grpc {
 
+namespace {
+std::unique_ptr<GenericClientAsyncReaderWriter> CallInternal(
+    ChannelInterface* channel, ClientContext* context,
+    const grpc::string& method, CompletionQueue* cq, bool start, void* tag) {
+  return std::unique_ptr<GenericClientAsyncReaderWriter>(
+      internal::ClientAsyncReaderWriterFactory<ByteBuffer, ByteBuffer>::Create(
+          channel, cq,
+          internal::RpcMethod(method.c_str(),
+                              internal::RpcMethod::BIDI_STREAMING),
+          context, start, tag));
+}
+
+}  // namespace
+
 // begin a call to a named method
 std::unique_ptr<GenericClientAsyncReaderWriter> GenericStub::Call(
     ClientContext* context, const grpc::string& method, CompletionQueue* cq,
     void* tag) {
-  return std::unique_ptr<GenericClientAsyncReaderWriter>(
-      new GenericClientAsyncReaderWriter(
+  return CallInternal(channel_.get(), context, method, cq, true, tag);
+}
+
+// setup a call to a named method
+std::unique_ptr<GenericClientAsyncReaderWriter> GenericStub::PrepareCall(
+    ClientContext* context, const grpc::string& method, CompletionQueue* cq) {
+  return CallInternal(channel_.get(), context, method, cq, false, nullptr);
+}
+
+// setup a unary call to a named method
+std::unique_ptr<GenericClientAsyncResponseReader> GenericStub::PrepareUnaryCall(
+    ClientContext* context, const grpc::string& method,
+    const ByteBuffer& request, CompletionQueue* cq) {
+  return std::unique_ptr<GenericClientAsyncResponseReader>(
+      internal::ClientAsyncResponseReaderFactory<ByteBuffer>::Create(
           channel_.get(), cq,
-          RpcMethod(method.c_str(), RpcMethod::BIDI_STREAMING), context, tag));
+          internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC),
+          context, request, false));
+}
+
+void GenericStub::experimental_type::UnaryCall(
+    ClientContext* context, const grpc::string& method,
+    const ByteBuffer* request, ByteBuffer* response,
+    std::function<void(Status)> on_completion) {
+  internal::CallbackUnaryCall(
+      stub_->channel_.get(),
+      internal::RpcMethod(method.c_str(), internal::RpcMethod::NORMAL_RPC),
+      context, request, response, std::move(on_completion));
+}
+
+void GenericStub::experimental_type::PrepareBidiStreamingCall(
+    ClientContext* context, const grpc::string& method,
+    experimental::ClientBidiReactor<ByteBuffer, ByteBuffer>* reactor) {
+  internal::ClientCallbackReaderWriterFactory<ByteBuffer, ByteBuffer>::Create(
+      stub_->channel_.get(),
+      internal::RpcMethod(method.c_str(), internal::RpcMethod::BIDI_STREAMING),
+      context, reactor);
 }
 
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/client/insecure_credentials.cc b/third_party/grpc/src/cpp/client/insecure_credentials.cc
index 1293203..241ce91 100644
--- a/third_party/grpc/src/cpp/client/insecure_credentials.cc
+++ b/third_party/grpc/src/cpp/client/insecure_credentials.cc
@@ -1,62 +1,57 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/security/credentials.h>
+#include <grpcpp/security/credentials.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
-#include <grpc++/channel.h>
-#include <grpc++/support/channel_arguments.h>
-#include <grpc++/support/config.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/support/channel_arguments.h>
+#include <grpcpp/support/config.h>
 #include "src/cpp/client/create_channel_internal.h"
 
 namespace grpc {
 
 namespace {
-class InsecureChannelCredentialsImpl GRPC_FINAL : public ChannelCredentials {
+class InsecureChannelCredentialsImpl final : public ChannelCredentials {
  public:
   std::shared_ptr<grpc::Channel> CreateChannel(
-      const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE {
+      const string& target, const grpc::ChannelArguments& args) override {
+    return CreateChannelWithInterceptors(
+        target, args,
+        std::vector<std::unique_ptr<
+            experimental::ClientInterceptorFactoryInterface>>());
+  }
+
+  std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
+      const string& target, const grpc::ChannelArguments& args,
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+          interceptor_creators) override {
     grpc_channel_args channel_args;
     args.SetChannelArgs(&channel_args);
     return CreateChannelInternal(
         "",
-        grpc_insecure_channel_create(target.c_str(), &channel_args, nullptr));
+        grpc_insecure_channel_create(target.c_str(), &channel_args, nullptr),
+        std::move(interceptor_creators));
   }
 
-  SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE {
-    return nullptr;
-  }
+  SecureChannelCredentials* AsSecureCredentials() override { return nullptr; }
 };
 }  // namespace
 
diff --git a/third_party/grpc/src/cpp/client/secure_credentials.cc b/third_party/grpc/src/cpp/client/secure_credentials.cc
index 074dae7..4d0ed35 100644
--- a/third_party/grpc/src/cpp/client/secure_credentials.cc
+++ b/third_party/grpc/src/cpp/client/secure_credentials.cc
@@ -1,42 +1,28 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/channel.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/support/channel_arguments.h>
-#include <grpc/support/log.h>
-#include "src/cpp/client/create_channel_internal.h"
 #include "src/cpp/client/secure_credentials.h"
+#include <grpc/support/log.h>
+#include <grpc/support/string_util.h>
+#include <grpcpp/channel.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/support/channel_arguments.h>
+#include "src/cpp/client/create_channel_internal.h"
 #include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
@@ -50,18 +36,30 @@
 
 std::shared_ptr<grpc::Channel> SecureChannelCredentials::CreateChannel(
     const string& target, const grpc::ChannelArguments& args) {
+  return CreateChannelWithInterceptors(
+      target, args,
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
+}
+
+std::shared_ptr<grpc::Channel>
+SecureChannelCredentials::CreateChannelWithInterceptors(
+    const string& target, const grpc::ChannelArguments& args,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators) {
   grpc_channel_args channel_args;
   args.SetChannelArgs(&channel_args);
   return CreateChannelInternal(
       args.GetSslTargetNameOverride(),
       grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args,
-                                 nullptr));
+                                 nullptr),
+      std::move(interceptor_creators));
 }
 
 SecureCallCredentials::SecureCallCredentials(grpc_call_credentials* c_creds)
     : c_creds_(c_creds) {
-  internal::GrpcLibraryInitializer gli_initializer;
-  gli_initializer.summon();
+  g_gli_initializer.summon();
 }
 
 bool SecureCallCredentials::ApplyToCall(grpc_call* call) {
@@ -71,38 +69,69 @@
 namespace {
 std::shared_ptr<ChannelCredentials> WrapChannelCredentials(
     grpc_channel_credentials* creds) {
-  return creds == nullptr ? nullptr : std::shared_ptr<ChannelCredentials>(
-                                          new SecureChannelCredentials(creds));
+  return creds == nullptr ? nullptr
+                          : std::shared_ptr<ChannelCredentials>(
+                                new SecureChannelCredentials(creds));
 }
 
 std::shared_ptr<CallCredentials> WrapCallCredentials(
     grpc_call_credentials* creds) {
-  return creds == nullptr ? nullptr : std::shared_ptr<CallCredentials>(
-                                          new SecureCallCredentials(creds));
+  return creds == nullptr ? nullptr
+                          : std::shared_ptr<CallCredentials>(
+                                new SecureCallCredentials(creds));
 }
 }  // namespace
 
 std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   return WrapChannelCredentials(grpc_google_default_credentials_create());
 }
 
 // Builds SSL Credentials given SSL specific options
 std::shared_ptr<ChannelCredentials> SslCredentials(
     const SslCredentialsOptions& options) {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
       options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
 
   grpc_channel_credentials* c_creds = grpc_ssl_credentials_create(
       options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
-      options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr);
+      options.pem_private_key.empty() ? nullptr : &pem_key_cert_pair, nullptr,
+      nullptr);
   return WrapChannelCredentials(c_creds);
 }
 
+namespace experimental {
+
+// Builds ALTS Credentials given ALTS specific options
+std::shared_ptr<ChannelCredentials> AltsCredentials(
+    const AltsCredentialsOptions& options) {
+  GrpcLibraryCodegen init;  // To call grpc_init().
+  grpc_alts_credentials_options* c_options =
+      grpc_alts_credentials_client_options_create();
+  for (auto service_account = options.target_service_accounts.begin();
+       service_account != options.target_service_accounts.end();
+       service_account++) {
+    grpc_alts_credentials_client_options_add_target_service_account(
+        c_options, service_account->c_str());
+  }
+  grpc_channel_credentials* c_creds = grpc_alts_credentials_create(c_options);
+  grpc_alts_credentials_options_destroy(c_options);
+  return WrapChannelCredentials(c_creds);
+}
+
+// Builds Local Credentials
+std::shared_ptr<ChannelCredentials> LocalCredentials(
+    grpc_local_connect_type type) {
+  GrpcLibraryCodegen init;  // To call grpc_init().
+  return WrapChannelCredentials(grpc_local_credentials_create(type));
+}
+
+}  // namespace experimental
+
 // Builds credentials for use when running in GCE
 std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   return WrapCallCredentials(
       grpc_google_compute_engine_credentials_create(nullptr));
 }
@@ -110,7 +139,7 @@
 // Builds JWT credentials.
 std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
     const grpc::string& json_key, long token_lifetime_seconds) {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   if (token_lifetime_seconds <= 0) {
     gpr_log(GPR_ERROR,
             "Trying to create JWTCredentials with non-positive lifetime");
@@ -125,7 +154,7 @@
 // Builds refresh token credentials.
 std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
     const grpc::string& json_refresh_token) {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
       json_refresh_token.c_str(), nullptr));
 }
@@ -133,7 +162,7 @@
 // Builds access token credentials.
 std::shared_ptr<CallCredentials> AccessTokenCredentials(
     const grpc::string& access_token) {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   return WrapCallCredentials(
       grpc_access_token_credentials_create(access_token.c_str(), nullptr));
 }
@@ -142,7 +171,7 @@
 std::shared_ptr<CallCredentials> GoogleIAMCredentials(
     const grpc::string& authorization_token,
     const grpc::string& authority_selector) {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   return WrapCallCredentials(grpc_google_iam_credentials_create(
       authorization_token.c_str(), authority_selector.c_str(), nullptr));
 }
@@ -166,56 +195,113 @@
   return nullptr;
 }
 
+std::shared_ptr<CallCredentials> CompositeCallCredentials(
+    const std::shared_ptr<CallCredentials>& creds1,
+    const std::shared_ptr<CallCredentials>& creds2) {
+  SecureCallCredentials* s_creds1 = creds1->AsSecureCredentials();
+  SecureCallCredentials* s_creds2 = creds2->AsSecureCredentials();
+  if (s_creds1 != nullptr && s_creds2 != nullptr) {
+    return WrapCallCredentials(grpc_composite_call_credentials_create(
+        s_creds1->GetRawCreds(), s_creds2->GetRawCreds(), nullptr));
+  }
+  return nullptr;
+}
+
 void MetadataCredentialsPluginWrapper::Destroy(void* wrapper) {
   if (wrapper == nullptr) return;
   MetadataCredentialsPluginWrapper* w =
-      reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
+      static_cast<MetadataCredentialsPluginWrapper*>(wrapper);
   delete w;
 }
 
-void MetadataCredentialsPluginWrapper::GetMetadata(
+int MetadataCredentialsPluginWrapper::GetMetadata(
     void* wrapper, grpc_auth_metadata_context context,
-    grpc_credentials_plugin_metadata_cb cb, void* user_data) {
+    grpc_credentials_plugin_metadata_cb cb, void* user_data,
+    grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
+    size_t* num_creds_md, grpc_status_code* status,
+    const char** error_details) {
   GPR_ASSERT(wrapper);
   MetadataCredentialsPluginWrapper* w =
-      reinterpret_cast<MetadataCredentialsPluginWrapper*>(wrapper);
+      static_cast<MetadataCredentialsPluginWrapper*>(wrapper);
   if (!w->plugin_) {
-    cb(user_data, NULL, 0, GRPC_STATUS_OK, NULL);
-    return;
+    *num_creds_md = 0;
+    *status = GRPC_STATUS_OK;
+    *error_details = nullptr;
+    return true;
   }
   if (w->plugin_->IsBlocking()) {
-    w->thread_pool_->Add(
-        std::bind(&MetadataCredentialsPluginWrapper::InvokePlugin, w, context,
-                  cb, user_data));
+    // Asynchronous return.
+    w->thread_pool_->Add([w, context, cb, user_data] {
+      w->MetadataCredentialsPluginWrapper::InvokePlugin(
+          context, cb, user_data, nullptr, nullptr, nullptr, nullptr);
+    });
+    return 0;
   } else {
-    w->InvokePlugin(context, cb, user_data);
+    // Synchronous return.
+    w->InvokePlugin(context, cb, user_data, creds_md, num_creds_md, status,
+                    error_details);
+    return 1;
   }
 }
 
+namespace {
+
+void UnrefMetadata(const std::vector<grpc_metadata>& md) {
+  for (auto it = md.begin(); it != md.end(); ++it) {
+    grpc_slice_unref(it->key);
+    grpc_slice_unref(it->value);
+  }
+}
+
+}  // namespace
+
 void MetadataCredentialsPluginWrapper::InvokePlugin(
     grpc_auth_metadata_context context, grpc_credentials_plugin_metadata_cb cb,
-    void* user_data) {
+    void* user_data, grpc_metadata creds_md[4], size_t* num_creds_md,
+    grpc_status_code* status_code, const char** error_details) {
   std::multimap<grpc::string, grpc::string> metadata;
 
-  // const_cast is safe since the SecureAuthContext does not take owndership and
-  // the object is passed as a const ref to plugin_->GetMetadata.
+  // const_cast is safe since the SecureAuthContext only inc/dec the refcount
+  // and the object is passed as a const ref to plugin_->GetMetadata.
   SecureAuthContext cpp_channel_auth_context(
-      const_cast<grpc_auth_context*>(context.channel_auth_context), false);
+      const_cast<grpc_auth_context*>(context.channel_auth_context));
 
   Status status = plugin_->GetMetadata(context.service_url, context.method_name,
                                        cpp_channel_auth_context, &metadata);
   std::vector<grpc_metadata> md;
   for (auto it = metadata.begin(); it != metadata.end(); ++it) {
     grpc_metadata md_entry;
-    md_entry.key = it->first.c_str();
-    md_entry.value = it->second.data();
-    md_entry.value_length = it->second.size();
+    md_entry.key = SliceFromCopiedString(it->first);
+    md_entry.value = SliceFromCopiedString(it->second);
     md_entry.flags = 0;
     md.push_back(md_entry);
   }
-  cb(user_data, md.empty() ? nullptr : &md[0], md.size(),
-     static_cast<grpc_status_code>(status.error_code()),
-     status.error_message().c_str());
+  if (creds_md != nullptr) {
+    // Synchronous return.
+    if (md.size() > GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX) {
+      *num_creds_md = 0;
+      *status_code = GRPC_STATUS_INTERNAL;
+      *error_details = gpr_strdup(
+          "blocking plugin credentials returned too many metadata keys");
+      UnrefMetadata(md);
+    } else {
+      for (const auto& elem : md) {
+        creds_md[*num_creds_md].key = elem.key;
+        creds_md[*num_creds_md].value = elem.value;
+        creds_md[*num_creds_md].flags = elem.flags;
+        ++(*num_creds_md);
+      }
+      *status_code = static_cast<grpc_status_code>(status.error_code());
+      *error_details =
+          status.ok() ? nullptr : gpr_strdup(status.error_message().c_str());
+    }
+  } else {
+    // Asynchronous return.
+    cb(user_data, md.empty() ? nullptr : &md[0], md.size(),
+       static_cast<grpc_status_code>(status.error_code()),
+       status.error_message().c_str());
+    UnrefMetadata(md);
+  }
 }
 
 MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
@@ -224,7 +310,7 @@
 
 std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
     std::unique_ptr<MetadataCredentialsPlugin> plugin) {
-  GrpcLibrary init;  // To call grpc_init().
+  GrpcLibraryCodegen init;  // To call grpc_init().
   const char* type = plugin->GetType();
   MetadataCredentialsPluginWrapper* wrapper =
       new MetadataCredentialsPluginWrapper(std::move(plugin));
diff --git a/third_party/grpc/src/cpp/client/secure_credentials.h b/third_party/grpc/src/cpp/client/secure_credentials.h
index 9e84102..4918bd5 100644
--- a/third_party/grpc/src/cpp/client/secure_credentials.h
+++ b/third_party/grpc/src/cpp/client/secure_credentials.h
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -36,53 +21,71 @@
 
 #include <grpc/grpc_security.h>
 
-#include <grpc++/support/config.h>
-#include <grpc++/security/credentials.h>
+#include <grpcpp/security/credentials.h>
+#include <grpcpp/support/config.h>
 
+#include "src/core/lib/security/credentials/credentials.h"
 #include "src/cpp/server/thread_pool_interface.h"
 
 namespace grpc {
 
-class SecureChannelCredentials GRPC_FINAL : public ChannelCredentials {
+class SecureChannelCredentials final : public ChannelCredentials {
  public:
   explicit SecureChannelCredentials(grpc_channel_credentials* c_creds);
-  ~SecureChannelCredentials() { grpc_channel_credentials_release(c_creds_); }
+  ~SecureChannelCredentials() {
+    if (c_creds_ != nullptr) c_creds_->Unref();
+  }
   grpc_channel_credentials* GetRawCreds() { return c_creds_; }
 
   std::shared_ptr<grpc::Channel> CreateChannel(
-      const string& target, const grpc::ChannelArguments& args) GRPC_OVERRIDE;
-  SecureChannelCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
+      const string& target, const grpc::ChannelArguments& args) override;
+
+  SecureChannelCredentials* AsSecureCredentials() override { return this; }
 
  private:
+  std::shared_ptr<grpc::Channel> CreateChannelWithInterceptors(
+      const string& target, const grpc::ChannelArguments& args,
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+          interceptor_creators) override;
   grpc_channel_credentials* const c_creds_;
 };
 
-class SecureCallCredentials GRPC_FINAL : public CallCredentials {
+class SecureCallCredentials final : public CallCredentials {
  public:
   explicit SecureCallCredentials(grpc_call_credentials* c_creds);
-  ~SecureCallCredentials() { grpc_call_credentials_release(c_creds_); }
+  ~SecureCallCredentials() {
+    if (c_creds_ != nullptr) c_creds_->Unref();
+  }
   grpc_call_credentials* GetRawCreds() { return c_creds_; }
 
-  bool ApplyToCall(grpc_call* call) GRPC_OVERRIDE;
-  SecureCallCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
+  bool ApplyToCall(grpc_call* call) override;
+  SecureCallCredentials* AsSecureCredentials() override { return this; }
 
  private:
   grpc_call_credentials* const c_creds_;
 };
 
-class MetadataCredentialsPluginWrapper GRPC_FINAL {
+class MetadataCredentialsPluginWrapper final : private GrpcLibraryCodegen {
  public:
   static void Destroy(void* wrapper);
-  static void GetMetadata(void* wrapper, grpc_auth_metadata_context context,
-                          grpc_credentials_plugin_metadata_cb cb,
-                          void* user_data);
+  static int GetMetadata(
+      void* wrapper, grpc_auth_metadata_context context,
+      grpc_credentials_plugin_metadata_cb cb, void* user_data,
+      grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
+      size_t* num_creds_md, grpc_status_code* status,
+      const char** error_details);
 
   explicit MetadataCredentialsPluginWrapper(
       std::unique_ptr<MetadataCredentialsPlugin> plugin);
 
  private:
-  void InvokePlugin(grpc_auth_metadata_context context,
-                    grpc_credentials_plugin_metadata_cb cb, void* user_data);
+  void InvokePlugin(
+      grpc_auth_metadata_context context,
+      grpc_credentials_plugin_metadata_cb cb, void* user_data,
+      grpc_metadata creds_md[GRPC_METADATA_CREDENTIALS_PLUGIN_SYNC_MAX],
+      size_t* num_creds_md, grpc_status_code* status_code,
+      const char** error_details);
   std::unique_ptr<ThreadPoolInterface> thread_pool_;
   std::unique_ptr<MetadataCredentialsPlugin> plugin_;
 };
diff --git a/third_party/grpc/src/cpp/codegen/codegen_init.cc b/third_party/grpc/src/cpp/codegen/codegen_init.cc
new file mode 100644
index 0000000..684d721
--- /dev/null
+++ b/third_party/grpc/src/cpp/codegen/codegen_init.cc
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/impl/codegen/core_codegen_interface.h>
+#include <grpcpp/impl/codegen/grpc_library.h>
+
+/// Null-initializes the global gRPC variables for the codegen library. These
+/// stay null in the absence of of grpc++ library. In this case, no gRPC
+/// features such as the ability to perform calls will be available. Trying to
+/// perform them would result in a segmentation fault when trying to deference
+/// the following nulled globals. These should be associated with actual
+/// as part of the instantiation of a \a grpc::GrpcLibraryInitializer variable.
+
+grpc::CoreCodegenInterface* grpc::g_core_codegen_interface;
+grpc::GrpcLibraryInterface* grpc::g_glip;
diff --git a/third_party/grpc/src/cpp/codegen/grpc_library.cc b/third_party/grpc/src/cpp/codegen/grpc_library.cc
deleted file mode 100644
index 48acec3..0000000
--- a/third_party/grpc/src/cpp/codegen/grpc_library.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *
- * Copyright 2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/impl/codegen/grpc_library.h>
-
-namespace grpc {
-
-GrpcLibraryInterface *g_glip = nullptr;
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/alarm.cc b/third_party/grpc/src/cpp/common/alarm.cc
index 807a67d..148f0b9b 100644
--- a/third_party/grpc/src/cpp/common/alarm.cc
+++ b/third_party/grpc/src/cpp/common/alarm.cc
@@ -1,50 +1,149 @@
 /*
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2018 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/alarm.h>
-#include <grpc++/completion_queue.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc/grpc.h>
+#include <grpcpp/alarm.h>
 
-namespace grpc {
+#include <memory>
 
-static internal::GrpcLibraryInitializer g_gli_initializer;
-Alarm::Alarm(CompletionQueue* cq, gpr_timespec deadline, void* tag)
-    : alarm_(grpc_alarm_create(cq->cq(), deadline, tag)) {
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/support/time.h>
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/timer.h"
+#include "src/core/lib/surface/completion_queue.h"
+
+#include <grpc/support/log.h>
+#include "src/core/lib/debug/trace.h"
+
+namespace grpc_impl {
+
+namespace internal {
+class AlarmImpl : public ::grpc::internal::CompletionQueueTag {
+ public:
+  AlarmImpl() : cq_(nullptr), tag_(nullptr) {
+    gpr_ref_init(&refs_, 1);
+    grpc_timer_init_unset(&timer_);
+  }
+  ~AlarmImpl() {
+    grpc_core::ExecCtx exec_ctx;
+    if (cq_ != nullptr) {
+      GRPC_CQ_INTERNAL_UNREF(cq_, "alarm");
+    }
+  }
+  bool FinalizeResult(void** tag, bool* status) override {
+    *tag = tag_;
+    Unref();
+    return true;
+  }
+  void Set(::grpc::CompletionQueue* cq, gpr_timespec deadline, void* tag) {
+    grpc_core::ExecCtx exec_ctx;
+    GRPC_CQ_INTERNAL_REF(cq->cq(), "alarm");
+    cq_ = cq->cq();
+    tag_ = tag;
+    GPR_ASSERT(grpc_cq_begin_op(cq_, this));
+    GRPC_CLOSURE_INIT(&on_alarm_,
+                      [](void* arg, grpc_error* error) {
+                        // queue the op on the completion queue
+                        AlarmImpl* alarm = static_cast<AlarmImpl*>(arg);
+                        alarm->Ref();
+                        grpc_cq_end_op(
+                            alarm->cq_, alarm, error,
+                            [](void* arg, grpc_cq_completion* completion) {},
+                            arg, &alarm->completion_);
+                      },
+                      this, grpc_schedule_on_exec_ctx);
+    grpc_timer_init(&timer_, grpc_timespec_to_millis_round_up(deadline),
+                    &on_alarm_);
+  }
+  void Set(gpr_timespec deadline, std::function<void(bool)> f) {
+    grpc_core::ExecCtx exec_ctx;
+    // Don't use any CQ at all. Instead just use the timer to fire the function
+    callback_ = std::move(f);
+    Ref();
+    GRPC_CLOSURE_INIT(&on_alarm_,
+                      [](void* arg, grpc_error* error) {
+                        AlarmImpl* alarm = static_cast<AlarmImpl*>(arg);
+                        alarm->callback_(error == GRPC_ERROR_NONE);
+                        alarm->Unref();
+                      },
+                      this, grpc_schedule_on_exec_ctx);
+    grpc_timer_init(&timer_, grpc_timespec_to_millis_round_up(deadline),
+                    &on_alarm_);
+  }
+  void Cancel() {
+    grpc_core::ExecCtx exec_ctx;
+    grpc_timer_cancel(&timer_);
+  }
+  void Destroy() {
+    Cancel();
+    Unref();
+  }
+
+ private:
+  void Ref() { gpr_ref(&refs_); }
+  void Unref() {
+    if (gpr_unref(&refs_)) {
+      delete this;
+    }
+  }
+
+  grpc_timer timer_;
+  gpr_refcount refs_;
+  grpc_closure on_alarm_;
+  grpc_cq_completion completion_;
+  // completion queue where events about this alarm will be posted
+  grpc_completion_queue* cq_;
+  void* tag_;
+  std::function<void(bool)> callback_;
+};
+}  // namespace internal
+
+static ::grpc::internal::GrpcLibraryInitializer g_gli_initializer;
+
+Alarm::Alarm() : alarm_(new internal::AlarmImpl()) {
   g_gli_initializer.summon();
 }
 
-Alarm::~Alarm() { grpc_alarm_destroy(alarm_); }
+void Alarm::SetInternal(::grpc::CompletionQueue* cq, gpr_timespec deadline,
+                        void* tag) {
+  // Note that we know that alarm_ is actually an internal::AlarmImpl
+  // but we declared it as the base pointer to avoid a forward declaration
+  // or exposing core data structures in the C++ public headers.
+  // Thus it is safe to use a static_cast to the subclass here, and the
+  // C++ style guide allows us to do so in this case
+  static_cast<internal::AlarmImpl*>(alarm_)->Set(cq, deadline, tag);
+}
 
-void Alarm::Cancel() { grpc_alarm_cancel(alarm_); }
+void Alarm::SetInternal(gpr_timespec deadline, std::function<void(bool)> f) {
+  // Note that we know that alarm_ is actually an internal::AlarmImpl
+  // but we declared it as the base pointer to avoid a forward declaration
+  // or exposing core data structures in the C++ public headers.
+  // Thus it is safe to use a static_cast to the subclass here, and the
+  // C++ style guide allows us to do so in this case
+  static_cast<internal::AlarmImpl*>(alarm_)->Set(deadline, std::move(f));
+}
 
-}  // namespace grpc
+Alarm::~Alarm() {
+  if (alarm_ != nullptr) {
+    static_cast<internal::AlarmImpl*>(alarm_)->Destroy();
+  }
+}
+
+void Alarm::Cancel() { static_cast<internal::AlarmImpl*>(alarm_)->Cancel(); }
+}  // namespace grpc_impl
diff --git a/third_party/grpc/src/cpp/common/auth_property_iterator.cc b/third_party/grpc/src/cpp/common/auth_property_iterator.cc
index a47abaf..fbb18e9 100644
--- a/third_party/grpc/src/cpp/common/auth_property_iterator.cc
+++ b/third_party/grpc/src/cpp/common/auth_property_iterator.cc
@@ -1,37 +1,22 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/security/auth_context.h>
+#include <grpcpp/security/auth_context.h>
 
 #include <grpc/grpc_security.h>
 
diff --git a/third_party/grpc/src/cpp/common/call.cc b/third_party/grpc/src/cpp/common/call.cc
deleted file mode 100644
index 5b87c2a..0000000
--- a/third_party/grpc/src/cpp/common/call.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/impl/call.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc++/channel.h>
-#include <grpc++/client_context.h>
-#include <grpc++/support/byte_buffer.h>
-#include "src/core/profiling/timers.h"
-
-namespace grpc {
-
-void FillMetadataMap(
-    grpc_metadata_array* arr,
-    std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
-  for (size_t i = 0; i < arr->count; i++) {
-    // TODO(yangg) handle duplicates?
-    metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
-        arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
-                                               arr->metadata[i].value_length)));
-  }
-  grpc_metadata_array_destroy(arr);
-  grpc_metadata_array_init(arr);
-}
-
-// TODO(yangg) if the map is changed before we send, the pointers will be a
-// mess. Make sure it does not happen.
-grpc_metadata* FillMetadataArray(
-    const std::multimap<grpc::string, grpc::string>& metadata) {
-  if (metadata.empty()) {
-    return nullptr;
-  }
-  grpc_metadata* metadata_array =
-      (grpc_metadata*)gpr_malloc(metadata.size() * sizeof(grpc_metadata));
-  size_t i = 0;
-  for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
-    metadata_array[i].key = iter->first.c_str();
-    metadata_array[i].value = iter->second.c_str();
-    metadata_array[i].value_length = iter->second.size();
-  }
-  return metadata_array;
-}
-
-Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
-    : call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
-
-Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
-           int max_message_size)
-    : call_hook_(call_hook),
-      cq_(cq),
-      call_(call),
-      max_message_size_(max_message_size) {}
-
-void Call::PerformOps(CallOpSetInterface* ops) {
-  if (max_message_size_ > 0) {
-    ops->set_max_message_size(max_message_size_);
-  }
-  call_hook_->PerformOpsOnCall(ops, this);
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/channel_arguments.cc b/third_party/grpc/src/cpp/common/channel_arguments.cc
index 90cd513..214d72f 100644
--- a/third_party/grpc/src/cpp/common/channel_arguments.cc
+++ b/third_party/grpc/src/cpp/common/channel_arguments.cc
@@ -1,43 +1,39 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
+#include <grpcpp/support/channel_arguments.h>
 
-#include <grpc++/support/channel_arguments.h>
+#include <sstream>
 
+#include <grpc/impl/codegen/grpc_types.h>
 #include <grpc/support/log.h>
-#include "src/core/channel/channel_args.h"
+#include <grpcpp/grpcpp.h>
+#include <grpcpp/resource_quota.h>
+#include "src/core/lib/channel/channel_args.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/iomgr/socket_mutator.h"
 
 namespace grpc {
 
+ChannelArguments::ChannelArguments() {
+  // This will be ignored if used on the server side.
+  SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING, "grpc-c++/" + Version());
+}
+
 ChannelArguments::ChannelArguments(const ChannelArguments& other)
     : strings_(other.strings_) {
   args_.reserve(other.args_.size());
@@ -62,15 +58,22 @@
         break;
       case GRPC_ARG_POINTER:
         ap.value.pointer = a->value.pointer;
-        ap.value.pointer.p = a->value.pointer.copy
-                                 ? a->value.pointer.copy(ap.value.pointer.p)
-                                 : ap.value.pointer.p;
+        ap.value.pointer.p = a->value.pointer.vtable->copy(ap.value.pointer.p);
         break;
     }
     args_.push_back(ap);
   }
 }
 
+ChannelArguments::~ChannelArguments() {
+  grpc_core::ExecCtx exec_ctx;
+  for (auto it = args_.begin(); it != args_.end(); ++it) {
+    if (it->type == GRPC_ARG_POINTER) {
+      it->value.pointer.vtable->destroy(it->value.pointer.p);
+    }
+  }
+}
+
 void ChannelArguments::Swap(ChannelArguments& other) {
   args_.swap(other.args_);
   strings_.swap(other.strings_);
@@ -78,7 +81,90 @@
 
 void ChannelArguments::SetCompressionAlgorithm(
     grpc_compression_algorithm algorithm) {
-  SetInt(GRPC_COMPRESSION_ALGORITHM_ARG, algorithm);
+  SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM, algorithm);
+}
+
+void ChannelArguments::SetGrpclbFallbackTimeout(int fallback_timeout) {
+  SetInt(GRPC_ARG_GRPCLB_FALLBACK_TIMEOUT_MS, fallback_timeout);
+}
+
+void ChannelArguments::SetSocketMutator(grpc_socket_mutator* mutator) {
+  if (!mutator) {
+    return;
+  }
+  grpc_arg mutator_arg = grpc_socket_mutator_to_arg(mutator);
+  bool replaced = false;
+  grpc_core::ExecCtx exec_ctx;
+  for (auto it = args_.begin(); it != args_.end(); ++it) {
+    if (it->type == mutator_arg.type &&
+        grpc::string(it->key) == grpc::string(mutator_arg.key)) {
+      GPR_ASSERT(!replaced);
+      it->value.pointer.vtable->destroy(it->value.pointer.p);
+      it->value.pointer = mutator_arg.value.pointer;
+      replaced = true;
+    }
+  }
+
+  if (!replaced) {
+    strings_.push_back(grpc::string(mutator_arg.key));
+    args_.push_back(mutator_arg);
+    args_.back().key = const_cast<char*>(strings_.back().c_str());
+  }
+}
+
+// Note: a second call to this will add in front the result of the first call.
+// An example is calling this on a copy of ChannelArguments which already has a
+// prefix. The user can build up a prefix string by calling this multiple times,
+// each with more significant identifier.
+void ChannelArguments::SetUserAgentPrefix(
+    const grpc::string& user_agent_prefix) {
+  if (user_agent_prefix.empty()) {
+    return;
+  }
+  bool replaced = false;
+  auto strings_it = strings_.begin();
+  for (auto it = args_.begin(); it != args_.end(); ++it) {
+    const grpc_arg& arg = *it;
+    ++strings_it;
+    if (arg.type == GRPC_ARG_STRING) {
+      if (grpc::string(arg.key) == GRPC_ARG_PRIMARY_USER_AGENT_STRING) {
+        GPR_ASSERT(arg.value.string == strings_it->c_str());
+        *(strings_it) = user_agent_prefix + " " + arg.value.string;
+        it->value.string = const_cast<char*>(strings_it->c_str());
+        replaced = true;
+        break;
+      }
+      ++strings_it;
+    }
+  }
+  if (!replaced) {
+    SetString(GRPC_ARG_PRIMARY_USER_AGENT_STRING, user_agent_prefix);
+  }
+}
+
+void ChannelArguments::SetResourceQuota(
+    const grpc::ResourceQuota& resource_quota) {
+  SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA,
+                       resource_quota.c_resource_quota(),
+                       grpc_resource_quota_arg_vtable());
+}
+
+void ChannelArguments::SetMaxReceiveMessageSize(int size) {
+  SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, size);
+}
+
+void ChannelArguments::SetMaxSendMessageSize(int size) {
+  SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, size);
+}
+
+void ChannelArguments::SetLoadBalancingPolicyName(
+    const grpc::string& lb_policy_name) {
+  SetString(GRPC_ARG_LB_POLICY_NAME, lb_policy_name);
+}
+
+void ChannelArguments::SetServiceConfigJSON(
+    const grpc::string& service_config_json) {
+  SetString(GRPC_ARG_SERVICE_CONFIG, service_config_json);
 }
 
 void ChannelArguments::SetInt(const grpc::string& key, int value) {
@@ -92,13 +178,21 @@
 }
 
 void ChannelArguments::SetPointer(const grpc::string& key, void* value) {
+  static const grpc_arg_pointer_vtable vtable = {
+      &PointerVtableMembers::Copy, &PointerVtableMembers::Destroy,
+      &PointerVtableMembers::Compare};
+  SetPointerWithVtable(key, value, &vtable);
+}
+
+void ChannelArguments::SetPointerWithVtable(
+    const grpc::string& key, void* value,
+    const grpc_arg_pointer_vtable* vtable) {
   grpc_arg arg;
   arg.type = GRPC_ARG_POINTER;
   strings_.push_back(key);
   arg.key = const_cast<char*>(strings_.back().c_str());
-  arg.value.pointer.p = value;
-  arg.value.pointer.copy = nullptr;
-  arg.value.pointer.destroy = nullptr;
+  arg.value.pointer.p = vtable->copy(value);
+  arg.value.pointer.vtable = vtable;
   args_.push_back(arg);
 }
 
diff --git a/third_party/grpc/src/cpp/common/channel_filter.cc b/third_party/grpc/src/cpp/common/channel_filter.cc
new file mode 100644
index 0000000..422e7bb
--- /dev/null
+++ b/third_party/grpc/src/cpp/common/channel_filter.cc
@@ -0,0 +1,99 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <string.h>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/cpp/common/channel_filter.h"
+
+#include <grpcpp/impl/codegen/slice.h>
+
+namespace grpc {
+
+// MetadataBatch
+
+grpc_linked_mdelem* MetadataBatch::AddMetadata(const string& key,
+                                               const string& value) {
+  grpc_linked_mdelem* storage = new grpc_linked_mdelem;
+  memset(storage, 0, sizeof(grpc_linked_mdelem));
+  storage->md = grpc_mdelem_from_slices(SliceFromCopiedString(key),
+                                        SliceFromCopiedString(value));
+  GRPC_LOG_IF_ERROR("MetadataBatch::AddMetadata",
+                    grpc_metadata_batch_link_head(batch_, storage));
+  return storage;
+}
+
+// ChannelData
+
+void ChannelData::StartTransportOp(grpc_channel_element* elem,
+                                   TransportOp* op) {
+  grpc_channel_next_op(elem, op->op());
+}
+
+void ChannelData::GetInfo(grpc_channel_element* elem,
+                          const grpc_channel_info* channel_info) {
+  grpc_channel_next_get_info(elem, channel_info);
+}
+
+// CallData
+
+void CallData::StartTransportStreamOpBatch(grpc_call_element* elem,
+                                           TransportStreamOpBatch* op) {
+  grpc_call_next_op(elem, op->op());
+}
+
+void CallData::SetPollsetOrPollsetSet(grpc_call_element* elem,
+                                      grpc_polling_entity* pollent) {
+  grpc_call_stack_ignore_set_pollset_or_pollset_set(elem, pollent);
+}
+
+// internal code used by RegisterChannelFilter()
+
+namespace internal {
+
+// Note: Implicitly initialized to nullptr due to static lifetime.
+std::vector<FilterRecord>* channel_filters;
+
+namespace {
+
+bool MaybeAddFilter(grpc_channel_stack_builder* builder, void* arg) {
+  const FilterRecord& filter = *static_cast<FilterRecord*>(arg);
+  if (filter.include_filter) {
+    const grpc_channel_args* args =
+        grpc_channel_stack_builder_get_channel_arguments(builder);
+    if (!filter.include_filter(*args)) return true;
+  }
+  return grpc_channel_stack_builder_prepend_filter(builder, &filter.filter,
+                                                   nullptr, nullptr);
+}
+
+}  // namespace
+
+void ChannelFilterPluginInit() {
+  for (size_t i = 0; i < channel_filters->size(); ++i) {
+    FilterRecord& filter = (*channel_filters)[i];
+    grpc_channel_init_register_stage(filter.stack_type, filter.priority,
+                                     MaybeAddFilter, (void*)&filter);
+  }
+}
+
+void ChannelFilterPluginShutdown() {}
+
+}  // namespace internal
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/channel_filter.h b/third_party/grpc/src/cpp/common/channel_filter.h
new file mode 100644
index 0000000..5e569c9
--- /dev/null
+++ b/third_party/grpc/src/cpp/common/channel_filter.h
@@ -0,0 +1,397 @@
+/*
+ *
+ * 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 GRPCXX_CHANNEL_FILTER_H
+#define GRPCXX_CHANNEL_FILTER_H
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpcpp/impl/codegen/config.h>
+
+#include <functional>
+#include <vector>
+
+#include "src/core/lib/channel/channel_stack.h"
+#include "src/core/lib/surface/channel_init.h"
+#include "src/core/lib/transport/metadata_batch.h"
+
+/// An interface to define filters.
+///
+/// To define a filter, implement a subclass of each of \c CallData and
+/// \c ChannelData. Then register the filter using something like this:
+/// \code{.cpp}
+///   RegisterChannelFilter<MyChannelDataSubclass, MyCallDataSubclass>(
+///       "name-of-filter", GRPC_SERVER_CHANNEL, INT_MAX, nullptr);
+/// \endcode
+
+namespace grpc {
+
+/// A C++ wrapper for the \c grpc_metadata_batch struct.
+class MetadataBatch {
+ public:
+  /// Borrows a pointer to \a batch, but does NOT take ownership.
+  /// The caller must ensure that \a batch continues to exist for as
+  /// long as the MetadataBatch object does.
+  explicit MetadataBatch(grpc_metadata_batch* batch) : batch_(batch) {}
+
+  grpc_metadata_batch* batch() const { return batch_; }
+
+  /// Adds metadata and returns the newly allocated storage.
+  /// The caller takes ownership of the result, which must exist for the
+  /// lifetime of the gRPC call.
+  grpc_linked_mdelem* AddMetadata(const string& key, const string& value);
+
+  class const_iterator : public std::iterator<std::bidirectional_iterator_tag,
+                                              const grpc_mdelem> {
+   public:
+    const grpc_mdelem& operator*() const { return elem_->md; }
+    const grpc_mdelem operator->() const { return elem_->md; }
+
+    const_iterator& operator++() {
+      elem_ = elem_->next;
+      return *this;
+    }
+    const_iterator operator++(int) {
+      const_iterator tmp(*this);
+      operator++();
+      return tmp;
+    }
+    const_iterator& operator--() {
+      elem_ = elem_->prev;
+      return *this;
+    }
+    const_iterator operator--(int) {
+      const_iterator tmp(*this);
+      operator--();
+      return tmp;
+    }
+
+    bool operator==(const const_iterator& other) const {
+      return elem_ == other.elem_;
+    }
+    bool operator!=(const const_iterator& other) const {
+      return elem_ != other.elem_;
+    }
+
+   private:
+    friend class MetadataBatch;
+    explicit const_iterator(grpc_linked_mdelem* elem) : elem_(elem) {}
+
+    grpc_linked_mdelem* elem_;
+  };
+
+  const_iterator begin() const { return const_iterator(batch_->list.head); }
+  const_iterator end() const { return const_iterator(nullptr); }
+
+ private:
+  grpc_metadata_batch* batch_;  // Not owned.
+};
+
+/// A C++ wrapper for the \c grpc_transport_op struct.
+class TransportOp {
+ public:
+  /// Borrows a pointer to \a op, but does NOT take ownership.
+  /// The caller must ensure that \a op continues to exist for as
+  /// long as the TransportOp object does.
+  explicit TransportOp(grpc_transport_op* op) : op_(op) {}
+
+  grpc_transport_op* op() const { return op_; }
+
+  // TODO(roth): Add a C++ wrapper for grpc_error?
+  grpc_error* disconnect_with_error() const {
+    return op_->disconnect_with_error;
+  }
+  bool send_goaway() const { return op_->goaway_error != GRPC_ERROR_NONE; }
+
+  // TODO(roth): Add methods for additional fields as needed.
+
+ private:
+  grpc_transport_op* op_;  // Not owned.
+};
+
+/// A C++ wrapper for the \c grpc_transport_stream_op_batch struct.
+class TransportStreamOpBatch {
+ public:
+  /// Borrows a pointer to \a op, but does NOT take ownership.
+  /// The caller must ensure that \a op continues to exist for as
+  /// long as the TransportStreamOpBatch object does.
+  explicit TransportStreamOpBatch(grpc_transport_stream_op_batch* op)
+      : op_(op),
+        send_initial_metadata_(
+            op->send_initial_metadata
+                ? op->payload->send_initial_metadata.send_initial_metadata
+                : nullptr),
+        send_trailing_metadata_(
+            op->send_trailing_metadata
+                ? op->payload->send_trailing_metadata.send_trailing_metadata
+                : nullptr),
+        recv_initial_metadata_(
+            op->recv_initial_metadata
+                ? op->payload->recv_initial_metadata.recv_initial_metadata
+                : nullptr),
+        recv_trailing_metadata_(
+            op->recv_trailing_metadata
+                ? op->payload->recv_trailing_metadata.recv_trailing_metadata
+                : nullptr) {}
+
+  grpc_transport_stream_op_batch* op() const { return op_; }
+
+  grpc_closure* on_complete() const { return op_->on_complete; }
+  void set_on_complete(grpc_closure* closure) { op_->on_complete = closure; }
+
+  MetadataBatch* send_initial_metadata() {
+    return op_->send_initial_metadata ? &send_initial_metadata_ : nullptr;
+  }
+  MetadataBatch* send_trailing_metadata() {
+    return op_->send_trailing_metadata ? &send_trailing_metadata_ : nullptr;
+  }
+  MetadataBatch* recv_initial_metadata() {
+    return op_->recv_initial_metadata ? &recv_initial_metadata_ : nullptr;
+  }
+  MetadataBatch* recv_trailing_metadata() {
+    return op_->recv_trailing_metadata ? &recv_trailing_metadata_ : nullptr;
+  }
+
+  uint32_t* send_initial_metadata_flags() const {
+    return op_->send_initial_metadata ? &op_->payload->send_initial_metadata
+                                             .send_initial_metadata_flags
+                                      : nullptr;
+  }
+
+  grpc_closure* recv_initial_metadata_ready() const {
+    return op_->recv_initial_metadata
+               ? op_->payload->recv_initial_metadata.recv_initial_metadata_ready
+               : nullptr;
+  }
+  void set_recv_initial_metadata_ready(grpc_closure* closure) {
+    op_->payload->recv_initial_metadata.recv_initial_metadata_ready = closure;
+  }
+
+  grpc_core::OrphanablePtr<grpc_core::ByteStream>* send_message() const {
+    return op_->send_message ? &op_->payload->send_message.send_message
+                             : nullptr;
+  }
+  void set_send_message(
+      grpc_core::OrphanablePtr<grpc_core::ByteStream> send_message) {
+    op_->send_message = true;
+    op_->payload->send_message.send_message = std::move(send_message);
+  }
+
+  grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message() const {
+    return op_->recv_message ? op_->payload->recv_message.recv_message
+                             : nullptr;
+  }
+  void set_recv_message(
+      grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message) {
+    op_->recv_message = true;
+    op_->payload->recv_message.recv_message = recv_message;
+  }
+
+  census_context* get_census_context() const {
+    return static_cast<census_context*>(
+        op_->payload->context[GRPC_CONTEXT_TRACING].value);
+  }
+
+  const gpr_atm* get_peer_string() const {
+    if (op_->send_initial_metadata &&
+        op_->payload->send_initial_metadata.peer_string != nullptr) {
+      return op_->payload->send_initial_metadata.peer_string;
+    } else if (op_->recv_initial_metadata &&
+               op_->payload->recv_initial_metadata.peer_string != nullptr) {
+      return op_->payload->recv_initial_metadata.peer_string;
+    } else {
+      return nullptr;
+    }
+  }
+
+ private:
+  grpc_transport_stream_op_batch* op_;  // Not owned.
+  MetadataBatch send_initial_metadata_;
+  MetadataBatch send_trailing_metadata_;
+  MetadataBatch recv_initial_metadata_;
+  MetadataBatch recv_trailing_metadata_;
+};
+
+/// Represents channel data.
+class ChannelData {
+ public:
+  ChannelData() {}
+  virtual ~ChannelData() {}
+
+  // TODO(roth): Come up with a more C++-like API for the channel element.
+
+  /// Initializes the channel data.
+  virtual grpc_error* Init(grpc_channel_element* elem,
+                           grpc_channel_element_args* args) {
+    return GRPC_ERROR_NONE;
+  }
+
+  // Called before destruction.
+  virtual void Destroy(grpc_channel_element* elem) {}
+
+  virtual void StartTransportOp(grpc_channel_element* elem, TransportOp* op);
+
+  virtual void GetInfo(grpc_channel_element* elem,
+                       const grpc_channel_info* channel_info);
+};
+
+/// Represents call data.
+class CallData {
+ public:
+  CallData() {}
+  virtual ~CallData() {}
+
+  // TODO(roth): Come up with a more C++-like API for the call element.
+
+  /// Initializes the call data.
+  virtual grpc_error* Init(grpc_call_element* elem,
+                           const grpc_call_element_args* args) {
+    return GRPC_ERROR_NONE;
+  }
+
+  // Called before destruction.
+  virtual void Destroy(grpc_call_element* elem,
+                       const grpc_call_final_info* final_info,
+                       grpc_closure* then_call_closure) {}
+
+  /// Starts a new stream operation.
+  virtual void StartTransportStreamOpBatch(grpc_call_element* elem,
+                                           TransportStreamOpBatch* op);
+
+  /// Sets a pollset or pollset set.
+  virtual void SetPollsetOrPollsetSet(grpc_call_element* elem,
+                                      grpc_polling_entity* pollent);
+};
+
+namespace internal {
+
+// Defines static members for passing to C core.
+// Members of this class correspond to the members of the C
+// grpc_channel_filter struct.
+template <typename ChannelDataType, typename CallDataType>
+class ChannelFilter final {
+ public:
+  static const size_t channel_data_size = sizeof(ChannelDataType);
+
+  static grpc_error* InitChannelElement(grpc_channel_element* elem,
+                                        grpc_channel_element_args* args) {
+    // Construct the object in the already-allocated memory.
+    ChannelDataType* channel_data = new (elem->channel_data) ChannelDataType();
+    return channel_data->Init(elem, args);
+  }
+
+  static void DestroyChannelElement(grpc_channel_element* elem) {
+    ChannelDataType* channel_data =
+        static_cast<ChannelDataType*>(elem->channel_data);
+    channel_data->Destroy(elem);
+    channel_data->~ChannelDataType();
+  }
+
+  static void StartTransportOp(grpc_channel_element* elem,
+                               grpc_transport_op* op) {
+    ChannelDataType* channel_data =
+        static_cast<ChannelDataType*>(elem->channel_data);
+    TransportOp op_wrapper(op);
+    channel_data->StartTransportOp(elem, &op_wrapper);
+  }
+
+  static void GetChannelInfo(grpc_channel_element* elem,
+                             const grpc_channel_info* channel_info) {
+    ChannelDataType* channel_data =
+        static_cast<ChannelDataType*>(elem->channel_data);
+    channel_data->GetInfo(elem, channel_info);
+  }
+
+  static const size_t call_data_size = sizeof(CallDataType);
+
+  static grpc_error* InitCallElement(grpc_call_element* elem,
+                                     const grpc_call_element_args* args) {
+    // Construct the object in the already-allocated memory.
+    CallDataType* call_data = new (elem->call_data) CallDataType();
+    return call_data->Init(elem, args);
+  }
+
+  static void DestroyCallElement(grpc_call_element* elem,
+                                 const grpc_call_final_info* final_info,
+                                 grpc_closure* then_call_closure) {
+    CallDataType* call_data = static_cast<CallDataType*>(elem->call_data);
+    call_data->Destroy(elem, final_info, then_call_closure);
+    call_data->~CallDataType();
+  }
+
+  static void StartTransportStreamOpBatch(grpc_call_element* elem,
+                                          grpc_transport_stream_op_batch* op) {
+    CallDataType* call_data = static_cast<CallDataType*>(elem->call_data);
+    TransportStreamOpBatch op_wrapper(op);
+    call_data->StartTransportStreamOpBatch(elem, &op_wrapper);
+  }
+
+  static void SetPollsetOrPollsetSet(grpc_call_element* elem,
+                                     grpc_polling_entity* pollent) {
+    CallDataType* call_data = static_cast<CallDataType*>(elem->call_data);
+    call_data->SetPollsetOrPollsetSet(elem, pollent);
+  }
+};
+
+struct FilterRecord {
+  grpc_channel_stack_type stack_type;
+  int priority;
+  std::function<bool(const grpc_channel_args&)> include_filter;
+  grpc_channel_filter filter;
+};
+extern std::vector<FilterRecord>* channel_filters;
+
+void ChannelFilterPluginInit();
+void ChannelFilterPluginShutdown();
+
+}  // namespace internal
+
+/// Registers a new filter.
+/// Must be called by only one thread at a time.
+/// The \a include_filter argument specifies a function that will be called
+/// to determine at run-time whether or not to add the filter. If the
+/// value is nullptr, the filter will be added unconditionally.
+template <typename ChannelDataType, typename CallDataType>
+void RegisterChannelFilter(
+    const char* name, grpc_channel_stack_type stack_type, int priority,
+    std::function<bool(const grpc_channel_args&)> include_filter) {
+  // If we haven't been called before, initialize channel_filters and
+  // call grpc_register_plugin().
+  if (internal::channel_filters == nullptr) {
+    grpc_register_plugin(internal::ChannelFilterPluginInit,
+                         internal::ChannelFilterPluginShutdown);
+    internal::channel_filters = new std::vector<internal::FilterRecord>();
+  }
+  // Add an entry to channel_filters. The filter will be added when the
+  // C-core initialization code calls ChannelFilterPluginInit().
+  typedef internal::ChannelFilter<ChannelDataType, CallDataType> FilterType;
+  internal::FilterRecord filter_record = {
+      stack_type,
+      priority,
+      include_filter,
+      {FilterType::StartTransportStreamOpBatch, FilterType::StartTransportOp,
+       FilterType::call_data_size, FilterType::InitCallElement,
+       FilterType::SetPollsetOrPollsetSet, FilterType::DestroyCallElement,
+       FilterType::channel_data_size, FilterType::InitChannelElement,
+       FilterType::DestroyChannelElement, FilterType::GetChannelInfo, name}};
+  internal::channel_filters->push_back(filter_record);
+}
+
+}  // namespace grpc
+
+#endif  // GRPCXX_CHANNEL_FILTER_H
diff --git a/third_party/grpc/src/cpp/common/completion_queue.cc b/third_party/grpc/src/cpp/common/completion_queue.cc
deleted file mode 100644
index 4f76dff..0000000
--- a/third_party/grpc/src/cpp/common/completion_queue.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/completion_queue.h>
-
-#include <memory>
-
-#include <grpc++/impl/codegen/completion_queue_tag.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/support/time.h>
-#include <grpc/grpc.h>
-#include <grpc/support/log.h>
-
-namespace grpc {
-
-static internal::GrpcLibraryInitializer g_gli_initializer;
-CompletionQueue::CompletionQueue() {
-  g_gli_initializer.summon();
-  cq_ = grpc_completion_queue_create(nullptr);
-}
-
-CompletionQueue::CompletionQueue(grpc_completion_queue* take) : cq_(take) {}
-
-CompletionQueue::~CompletionQueue() { grpc_completion_queue_destroy(cq_); }
-
-void CompletionQueue::Shutdown() { grpc_completion_queue_shutdown(cq_); }
-
-CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal(
-    void** tag, bool* ok, gpr_timespec deadline) {
-  for (;;) {
-    auto ev = grpc_completion_queue_next(cq_, deadline, nullptr);
-    switch (ev.type) {
-      case GRPC_QUEUE_TIMEOUT:
-        return TIMEOUT;
-      case GRPC_QUEUE_SHUTDOWN:
-        return SHUTDOWN;
-      case GRPC_OP_COMPLETE:
-        auto cq_tag = static_cast<CompletionQueueTag*>(ev.tag);
-        *ok = ev.success != 0;
-        *tag = cq_tag;
-        if (cq_tag->FinalizeResult(tag, ok)) {
-          return GOT_EVENT;
-        }
-        break;
-    }
-  }
-}
-
-bool CompletionQueue::Pluck(CompletionQueueTag* tag) {
-  auto deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
-  auto ev = grpc_completion_queue_pluck(cq_, tag, deadline, nullptr);
-  bool ok = ev.success != 0;
-  void* ignored = tag;
-  GPR_ASSERT(tag->FinalizeResult(&ignored, &ok));
-  GPR_ASSERT(ignored == tag);
-  // Ignore mutations by FinalizeResult: Pluck returns the C API status
-  return ev.success != 0;
-}
-
-void CompletionQueue::TryPluck(CompletionQueueTag* tag) {
-  auto deadline = gpr_time_0(GPR_CLOCK_REALTIME);
-  auto ev = 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_ASSERT(!tag->FinalizeResult(&ignored, &ok));
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/completion_queue_cc.cc b/third_party/grpc/src/cpp/common/completion_queue_cc.cc
new file mode 100644
index 0000000..d93a54a
--- /dev/null
+++ b/third_party/grpc/src/cpp/common/completion_queue_cc.cc
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ *
+ */
+
+#include <grpcpp/completion_queue.h>
+
+#include <memory>
+
+#include <grpc/grpc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/support/time.h>
+
+namespace grpc {
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+
+// 'CompletionQueue' constructor can safely call GrpcLibraryCodegen(false) here
+// i.e not have GrpcLibraryCodegen call grpc_init(). This is because, to create
+// a 'grpc_completion_queue' instance (which is being passed as the input to
+// this constructor), one must have already called grpc_init().
+CompletionQueue::CompletionQueue(grpc_completion_queue* take)
+    : GrpcLibraryCodegen(false), cq_(take) {
+  InitialAvalanching();
+}
+
+void CompletionQueue::Shutdown() {
+  g_gli_initializer.summon();
+  CompleteAvalanching();
+}
+
+void CompletionQueue::CompleteAvalanching() {
+  // Check if this was the last avalanching operation
+  if (gpr_atm_no_barrier_fetch_add(&avalanches_in_flight_,
+                                   static_cast<gpr_atm>(-1)) == 1) {
+    grpc_completion_queue_shutdown(cq_);
+  }
+}
+
+CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal(
+    void** tag, bool* ok, gpr_timespec deadline) {
+  for (;;) {
+    auto ev = grpc_completion_queue_next(cq_, deadline, nullptr);
+    switch (ev.type) {
+      case GRPC_QUEUE_TIMEOUT:
+        return TIMEOUT;
+      case GRPC_QUEUE_SHUTDOWN:
+        return SHUTDOWN;
+      case GRPC_OP_COMPLETE:
+        auto core_cq_tag = static_cast<internal::CompletionQueueTag*>(ev.tag);
+        *ok = ev.success != 0;
+        *tag = core_cq_tag;
+        if (core_cq_tag->FinalizeResult(tag, ok)) {
+          return GOT_EVENT;
+        }
+        break;
+    }
+  }
+}
+
+CompletionQueue::CompletionQueueTLSCache::CompletionQueueTLSCache(
+    CompletionQueue* cq)
+    : cq_(cq), flushed_(false) {
+  grpc_completion_queue_thread_local_cache_init(cq_->cq_);
+}
+
+CompletionQueue::CompletionQueueTLSCache::~CompletionQueueTLSCache() {
+  GPR_ASSERT(flushed_);
+}
+
+bool CompletionQueue::CompletionQueueTLSCache::Flush(void** tag, bool* ok) {
+  int res = 0;
+  void* res_tag;
+  flushed_ = true;
+  if (grpc_completion_queue_thread_local_cache_flush(cq_->cq_, &res_tag,
+                                                     &res)) {
+    auto core_cq_tag = static_cast<internal::CompletionQueueTag*>(res_tag);
+    *ok = res == 1;
+    if (core_cq_tag->FinalizeResult(tag, ok)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/core_codegen.cc b/third_party/grpc/src/cpp/common/core_codegen.cc
new file mode 100644
index 0000000..cfaa2e7
--- /dev/null
+++ b/third_party/grpc/src/cpp/common/core_codegen.cc
@@ -0,0 +1,228 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/impl/codegen/core_codegen.h>
+
+#include <stdlib.h>
+
+#include <grpc/byte_buffer.h>
+#include <grpc/byte_buffer_reader.h>
+#include <grpc/grpc.h>
+#include <grpc/slice.h>
+#include <grpc/slice_buffer.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpc/support/port_platform.h>
+#include <grpc/support/sync.h>
+#include <grpcpp/support/config.h>
+
+#include "src/core/lib/profiling/timers.h"
+
+struct grpc_byte_buffer;
+
+namespace grpc {
+
+const grpc_completion_queue_factory*
+CoreCodegen::grpc_completion_queue_factory_lookup(
+    const grpc_completion_queue_attributes* attributes) {
+  return ::grpc_completion_queue_factory_lookup(attributes);
+}
+
+grpc_completion_queue* CoreCodegen::grpc_completion_queue_create(
+    const grpc_completion_queue_factory* factory,
+    const grpc_completion_queue_attributes* attributes, void* reserved) {
+  return ::grpc_completion_queue_create(factory, attributes, reserved);
+}
+
+grpc_completion_queue* CoreCodegen::grpc_completion_queue_create_for_next(
+    void* reserved) {
+  return ::grpc_completion_queue_create_for_next(reserved);
+}
+
+grpc_completion_queue* CoreCodegen::grpc_completion_queue_create_for_pluck(
+    void* reserved) {
+  return ::grpc_completion_queue_create_for_pluck(reserved);
+}
+
+void CoreCodegen::grpc_completion_queue_destroy(grpc_completion_queue* cq) {
+  ::grpc_completion_queue_destroy(cq);
+}
+
+grpc_event CoreCodegen::grpc_completion_queue_pluck(grpc_completion_queue* cq,
+                                                    void* tag,
+                                                    gpr_timespec deadline,
+                                                    void* reserved) {
+  return ::grpc_completion_queue_pluck(cq, tag, deadline, reserved);
+}
+
+void* CoreCodegen::gpr_malloc(size_t size) { return ::gpr_malloc(size); }
+
+void CoreCodegen::gpr_free(void* p) { return ::gpr_free(p); }
+
+void CoreCodegen::grpc_init() { ::grpc_init(); }
+void CoreCodegen::grpc_shutdown() { ::grpc_shutdown(); }
+
+void CoreCodegen::gpr_mu_init(gpr_mu* mu) { ::gpr_mu_init(mu); };
+void CoreCodegen::gpr_mu_destroy(gpr_mu* mu) { ::gpr_mu_destroy(mu); }
+void CoreCodegen::gpr_mu_lock(gpr_mu* mu) { ::gpr_mu_lock(mu); }
+void CoreCodegen::gpr_mu_unlock(gpr_mu* mu) { ::gpr_mu_unlock(mu); }
+void CoreCodegen::gpr_cv_init(gpr_cv* cv) { ::gpr_cv_init(cv); }
+void CoreCodegen::gpr_cv_destroy(gpr_cv* cv) { ::gpr_cv_destroy(cv); }
+int CoreCodegen::gpr_cv_wait(gpr_cv* cv, gpr_mu* mu,
+                             gpr_timespec abs_deadline) {
+  return ::gpr_cv_wait(cv, mu, abs_deadline);
+}
+void CoreCodegen::gpr_cv_signal(gpr_cv* cv) { ::gpr_cv_signal(cv); }
+void CoreCodegen::gpr_cv_broadcast(gpr_cv* cv) { ::gpr_cv_broadcast(cv); }
+
+grpc_byte_buffer* CoreCodegen::grpc_byte_buffer_copy(grpc_byte_buffer* bb) {
+  return ::grpc_byte_buffer_copy(bb);
+}
+
+void CoreCodegen::grpc_byte_buffer_destroy(grpc_byte_buffer* bb) {
+  ::grpc_byte_buffer_destroy(bb);
+}
+
+size_t CoreCodegen::grpc_byte_buffer_length(grpc_byte_buffer* bb) {
+  return ::grpc_byte_buffer_length(bb);
+}
+
+grpc_call_error CoreCodegen::grpc_call_start_batch(grpc_call* call,
+                                                   const grpc_op* ops,
+                                                   size_t nops, void* tag,
+                                                   void* reserved) {
+  return ::grpc_call_start_batch(call, ops, nops, tag, reserved);
+}
+
+grpc_call_error CoreCodegen::grpc_call_cancel_with_status(
+    grpc_call* call, grpc_status_code status, const char* description,
+    void* reserved) {
+  return ::grpc_call_cancel_with_status(call, status, description, reserved);
+}
+void CoreCodegen::grpc_call_ref(grpc_call* call) { ::grpc_call_ref(call); }
+void CoreCodegen::grpc_call_unref(grpc_call* call) { ::grpc_call_unref(call); }
+void* CoreCodegen::grpc_call_arena_alloc(grpc_call* call, size_t length) {
+  return ::grpc_call_arena_alloc(call, length);
+}
+
+int CoreCodegen::grpc_byte_buffer_reader_init(grpc_byte_buffer_reader* reader,
+                                              grpc_byte_buffer* buffer) {
+  return ::grpc_byte_buffer_reader_init(reader, buffer);
+}
+
+void CoreCodegen::grpc_byte_buffer_reader_destroy(
+    grpc_byte_buffer_reader* reader) {
+  ::grpc_byte_buffer_reader_destroy(reader);
+}
+
+int CoreCodegen::grpc_byte_buffer_reader_next(grpc_byte_buffer_reader* reader,
+                                              grpc_slice* slice) {
+  return ::grpc_byte_buffer_reader_next(reader, slice);
+}
+
+grpc_byte_buffer* CoreCodegen::grpc_raw_byte_buffer_create(grpc_slice* slice,
+                                                           size_t nslices) {
+  return ::grpc_raw_byte_buffer_create(slice, nslices);
+}
+
+grpc_slice CoreCodegen::grpc_slice_new_with_user_data(void* p, size_t len,
+                                                      void (*destroy)(void*),
+                                                      void* user_data) {
+  return ::grpc_slice_new_with_user_data(p, len, destroy, user_data);
+}
+
+grpc_slice CoreCodegen::grpc_slice_new_with_len(void* p, size_t len,
+                                                void (*destroy)(void*,
+                                                                size_t)) {
+  return ::grpc_slice_new_with_len(p, len, destroy);
+}
+
+grpc_slice CoreCodegen::grpc_empty_slice() { return ::grpc_empty_slice(); }
+
+grpc_slice CoreCodegen::grpc_slice_malloc(size_t length) {
+  return ::grpc_slice_malloc(length);
+}
+
+void CoreCodegen::grpc_slice_unref(grpc_slice slice) {
+  ::grpc_slice_unref(slice);
+}
+
+grpc_slice CoreCodegen::grpc_slice_ref(grpc_slice slice) {
+  return ::grpc_slice_ref(slice);
+}
+
+grpc_slice CoreCodegen::grpc_slice_split_tail(grpc_slice* s, size_t split) {
+  return ::grpc_slice_split_tail(s, split);
+}
+
+grpc_slice CoreCodegen::grpc_slice_split_head(grpc_slice* s, size_t split) {
+  return ::grpc_slice_split_head(s, split);
+}
+
+grpc_slice CoreCodegen::grpc_slice_sub(grpc_slice s, size_t begin, size_t end) {
+  return ::grpc_slice_sub(s, begin, end);
+}
+
+grpc_slice CoreCodegen::grpc_slice_from_static_buffer(const void* buffer,
+                                                      size_t length) {
+  return ::grpc_slice_from_static_buffer(buffer, length);
+}
+
+grpc_slice CoreCodegen::grpc_slice_from_copied_buffer(const void* buffer,
+                                                      size_t length) {
+  return ::grpc_slice_from_copied_buffer(static_cast<const char*>(buffer),
+                                         length);
+}
+
+void CoreCodegen::grpc_slice_buffer_add(grpc_slice_buffer* sb,
+                                        grpc_slice slice) {
+  ::grpc_slice_buffer_add(sb, slice);
+}
+
+void CoreCodegen::grpc_slice_buffer_pop(grpc_slice_buffer* sb) {
+  ::grpc_slice_buffer_pop(sb);
+}
+
+void CoreCodegen::grpc_metadata_array_init(grpc_metadata_array* array) {
+  ::grpc_metadata_array_init(array);
+}
+
+void CoreCodegen::grpc_metadata_array_destroy(grpc_metadata_array* array) {
+  ::grpc_metadata_array_destroy(array);
+}
+
+const Status& CoreCodegen::ok() { return grpc::Status::OK; }
+
+const Status& CoreCodegen::cancelled() { return grpc::Status::CANCELLED; }
+
+gpr_timespec CoreCodegen::gpr_inf_future(gpr_clock_type type) {
+  return ::gpr_inf_future(type);
+}
+
+gpr_timespec CoreCodegen::gpr_time_0(gpr_clock_type type) {
+  return ::gpr_time_0(type);
+}
+
+void CoreCodegen::assert_fail(const char* failed_assertion, const char* file,
+                              int line) {
+  gpr_log(file, line, GPR_LOG_SEVERITY_ERROR, "assertion failed: %s",
+          failed_assertion);
+  abort();
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/create_auth_context.h b/third_party/grpc/src/cpp/common/create_auth_context.h
deleted file mode 100644
index 4f3da39..0000000
--- a/third_party/grpc/src/cpp/common/create_auth_context.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-#include <memory>
-
-#include <grpc/grpc.h>
-#include <grpc++/security/auth_context.h>
-
-namespace grpc {
-
-std::shared_ptr<const AuthContext> CreateAuthContext(grpc_call* call);
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/insecure_create_auth_context.cc b/third_party/grpc/src/cpp/common/insecure_create_auth_context.cc
index b2e1532..4e5cbd0 100644
--- a/third_party/grpc/src/cpp/common/insecure_create_auth_context.cc
+++ b/third_party/grpc/src/cpp/common/insecure_create_auth_context.cc
@@ -1,39 +1,24 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 #include <memory>
 
 #include <grpc/grpc.h>
-#include <grpc++/security/auth_context.h>
+#include <grpcpp/security/auth_context.h>
 
 namespace grpc {
 
diff --git a/third_party/grpc/src/cpp/common/resource_quota_cc.cc b/third_party/grpc/src/cpp/common/resource_quota_cc.cc
new file mode 100644
index 0000000..276e5f7
--- /dev/null
+++ b/third_party/grpc/src/cpp/common/resource_quota_cc.cc
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/grpc.h>
+#include <grpcpp/resource_quota.h>
+
+namespace grpc {
+
+ResourceQuota::ResourceQuota() : impl_(grpc_resource_quota_create(nullptr)) {}
+
+ResourceQuota::ResourceQuota(const grpc::string& name)
+    : impl_(grpc_resource_quota_create(name.c_str())) {}
+
+ResourceQuota::~ResourceQuota() { grpc_resource_quota_unref(impl_); }
+
+ResourceQuota& ResourceQuota::Resize(size_t new_size) {
+  grpc_resource_quota_resize(impl_, new_size);
+  return *this;
+}
+
+ResourceQuota& ResourceQuota::SetMaxThreads(int new_max_threads) {
+  grpc_resource_quota_set_max_threads(impl_, new_max_threads);
+  return *this;
+}
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/rpc_method.cc b/third_party/grpc/src/cpp/common/rpc_method.cc
index 1654d4a..a47dd3e 100644
--- a/third_party/grpc/src/cpp/common/rpc_method.cc
+++ b/third_party/grpc/src/cpp/common/rpc_method.cc
@@ -1,36 +1,21 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/impl/rpc_method.h>
+#include <grpcpp/impl/rpc_method.h>
 
 namespace grpc {}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/secure_auth_context.cc b/third_party/grpc/src/cpp/common/secure_auth_context.cc
index 8615ac8..7a2b5af 100644
--- a/third_party/grpc/src/cpp/common/secure_auth_context.cc
+++ b/third_party/grpc/src/cpp/common/secure_auth_context.cc
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -37,19 +22,12 @@
 
 namespace grpc {
 
-SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx,
-                                     bool take_ownership)
-    : ctx_(ctx), take_ownership_(take_ownership) {}
-
-SecureAuthContext::~SecureAuthContext() {
-  if (take_ownership_) grpc_auth_context_release(ctx_);
-}
-
 std::vector<grpc::string_ref> SecureAuthContext::GetPeerIdentity() const {
-  if (!ctx_) {
+  if (ctx_ == nullptr) {
     return std::vector<grpc::string_ref>();
   }
-  grpc_auth_property_iterator iter = grpc_auth_context_peer_identity(ctx_);
+  grpc_auth_property_iterator iter =
+      grpc_auth_context_peer_identity(ctx_.get());
   std::vector<grpc::string_ref> identity;
   const grpc_auth_property* property = nullptr;
   while ((property = grpc_auth_property_iterator_next(&iter))) {
@@ -60,20 +38,20 @@
 }
 
 grpc::string SecureAuthContext::GetPeerIdentityPropertyName() const {
-  if (!ctx_) {
+  if (ctx_ == nullptr) {
     return "";
   }
-  const char* name = grpc_auth_context_peer_identity_property_name(ctx_);
+  const char* name = grpc_auth_context_peer_identity_property_name(ctx_.get());
   return name == nullptr ? "" : name;
 }
 
 std::vector<grpc::string_ref> SecureAuthContext::FindPropertyValues(
     const grpc::string& name) const {
-  if (!ctx_) {
+  if (ctx_ == nullptr) {
     return std::vector<grpc::string_ref>();
   }
   grpc_auth_property_iterator iter =
-      grpc_auth_context_find_properties_by_name(ctx_, name.c_str());
+      grpc_auth_context_find_properties_by_name(ctx_.get(), name.c_str());
   const grpc_auth_property* property = nullptr;
   std::vector<grpc::string_ref> values;
   while ((property = grpc_auth_property_iterator_next(&iter))) {
@@ -83,9 +61,9 @@
 }
 
 AuthPropertyIterator SecureAuthContext::begin() const {
-  if (ctx_) {
+  if (ctx_ != nullptr) {
     grpc_auth_property_iterator iter =
-        grpc_auth_context_property_iterator(ctx_);
+        grpc_auth_context_property_iterator(ctx_.get());
     const grpc_auth_property* property =
         grpc_auth_property_iterator_next(&iter);
     return AuthPropertyIterator(property, &iter);
@@ -100,19 +78,20 @@
 
 void SecureAuthContext::AddProperty(const grpc::string& key,
                                     const grpc::string_ref& value) {
-  if (!ctx_) return;
-  grpc_auth_context_add_property(ctx_, key.c_str(), value.data(), value.size());
+  if (ctx_ == nullptr) return;
+  grpc_auth_context_add_property(ctx_.get(), key.c_str(), value.data(),
+                                 value.size());
 }
 
 bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) {
-  if (!ctx_) return false;
-  return grpc_auth_context_set_peer_identity_property_name(ctx_,
+  if (ctx_ == nullptr) return false;
+  return grpc_auth_context_set_peer_identity_property_name(ctx_.get(),
                                                            name.c_str()) != 0;
 }
 
 bool SecureAuthContext::IsPeerAuthenticated() const {
-  if (!ctx_) return false;
-  return grpc_auth_context_peer_is_authenticated(ctx_) != 0;
+  if (ctx_ == nullptr) return false;
+  return grpc_auth_context_peer_is_authenticated(ctx_.get()) != 0;
 }
 
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/secure_auth_context.h b/third_party/grpc/src/cpp/common/secure_auth_context.h
index c9f1dad..2e8f793 100644
--- a/third_party/grpc/src/cpp/common/secure_auth_context.h
+++ b/third_party/grpc/src/cpp/common/secure_auth_context.h
@@ -1,73 +1,58 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
 #define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
 
-#include <grpc++/security/auth_context.h>
+#include <grpcpp/security/auth_context.h>
 
-struct grpc_auth_context;
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
+#include "src/core/lib/security/context/security_context.h"
 
 namespace grpc {
 
-class SecureAuthContext GRPC_FINAL : public AuthContext {
+class SecureAuthContext final : public AuthContext {
  public:
-  SecureAuthContext(grpc_auth_context* ctx, bool take_ownership);
+  explicit SecureAuthContext(grpc_auth_context* ctx)
+      : ctx_(ctx != nullptr ? ctx->Ref() : nullptr) {}
 
-  ~SecureAuthContext() GRPC_OVERRIDE;
+  ~SecureAuthContext() override = default;
 
-  bool IsPeerAuthenticated() const GRPC_OVERRIDE;
+  bool IsPeerAuthenticated() const override;
 
-  std::vector<grpc::string_ref> GetPeerIdentity() const GRPC_OVERRIDE;
+  std::vector<grpc::string_ref> GetPeerIdentity() const override;
 
-  grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE;
+  grpc::string GetPeerIdentityPropertyName() const override;
 
   std::vector<grpc::string_ref> FindPropertyValues(
-      const grpc::string& name) const GRPC_OVERRIDE;
+      const grpc::string& name) const override;
 
-  AuthPropertyIterator begin() const GRPC_OVERRIDE;
+  AuthPropertyIterator begin() const override;
 
-  AuthPropertyIterator end() const GRPC_OVERRIDE;
+  AuthPropertyIterator end() const override;
 
   void AddProperty(const grpc::string& key,
-                   const grpc::string_ref& value) GRPC_OVERRIDE;
+                   const grpc::string_ref& value) override;
 
-  virtual bool SetPeerIdentityPropertyName(const grpc::string& name)
-      GRPC_OVERRIDE;
+  virtual bool SetPeerIdentityPropertyName(const grpc::string& name) override;
 
  private:
-  grpc_auth_context* ctx_;
-  bool take_ownership_;
+  grpc_core::RefCountedPtr<grpc_auth_context> ctx_;
 };
 
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/secure_channel_arguments.cc b/third_party/grpc/src/cpp/common/secure_channel_arguments.cc
index e17d3b5..2fb8ea4 100644
--- a/third_party/grpc/src/cpp/common/secure_channel_arguments.cc
+++ b/third_party/grpc/src/cpp/common/secure_channel_arguments.cc
@@ -1,40 +1,25 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/support/channel_arguments.h>
+#include <grpcpp/support/channel_arguments.h>
 
 #include <grpc/grpc_security.h>
-#include "src/core/channel/channel_args.h"
+#include "src/core/lib/channel/channel_args.h"
 
 namespace grpc {
 
diff --git a/third_party/grpc/src/cpp/common/secure_create_auth_context.cc b/third_party/grpc/src/cpp/common/secure_create_auth_context.cc
index 40bc298..908c466 100644
--- a/third_party/grpc/src/cpp/common/secure_create_auth_context.cc
+++ b/third_party/grpc/src/cpp/common/secure_create_auth_context.cc
@@ -1,40 +1,26 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 #include <memory>
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
-#include <grpc++/security/auth_context.h>
+#include <grpcpp/security/auth_context.h>
+#include "src/core/lib/gprpp/ref_counted_ptr.h"
 #include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
@@ -43,8 +29,8 @@
   if (call == nullptr) {
     return std::shared_ptr<const AuthContext>();
   }
-  return std::shared_ptr<const AuthContext>(
-      new SecureAuthContext(grpc_call_auth_context(call), true));
+  grpc_core::RefCountedPtr<grpc_auth_context> ctx(grpc_call_auth_context(call));
+  return std::make_shared<SecureAuthContext>(ctx.get());
 }
 
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/common/version_cc.cc b/third_party/grpc/src/cpp/common/version_cc.cc
new file mode 100644
index 0000000..768b0c6
--- /dev/null
+++ b/third_party/grpc/src/cpp/common/version_cc.cc
@@ -0,0 +1,26 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+/* This file is autogenerated from:
+   templates/src/core/surface/version.c.template */
+
+#include <grpcpp/grpcpp.h>
+
+namespace grpc {
+grpc::string Version() { return "1.18.0"; }
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/channel_filter.cc b/third_party/grpc/src/cpp/ext/filters/census/channel_filter.cc
new file mode 100644
index 0000000..4ac684d
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/channel_filter.cc
@@ -0,0 +1,30 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/channel_filter.h"
+
+namespace grpc {
+
+grpc_error* CensusChannelData::Init(grpc_channel_element* elem,
+                                    grpc_channel_element_args* args) {
+  return GRPC_ERROR_NONE;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/channel_filter.h b/third_party/grpc/src/cpp/ext/filters/census/channel_filter.h
new file mode 100644
index 0000000..0b7c682
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/channel_filter.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+class CensusChannelData : public ChannelData {
+ public:
+  grpc_error* Init(grpc_channel_element* elem,
+                   grpc_channel_element_args* args) override;
+};
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CHANNEL_FILTER_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/client_filter.cc b/third_party/grpc/src/cpp/ext/filters/census/client_filter.cc
new file mode 100644
index 0000000..940d42d
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/client_filter.cc
@@ -0,0 +1,165 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/client_filter.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "opencensus/stats/stats.h"
+#include "src/core/lib/surface/call.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+#include "src/cpp/ext/filters/census/measures.h"
+
+namespace grpc {
+
+constexpr uint32_t CensusClientCallData::kMaxTraceContextLen;
+constexpr uint32_t CensusClientCallData::kMaxTagsLen;
+
+namespace {
+
+void FilterTrailingMetadata(grpc_metadata_batch* b, uint64_t* elapsed_time) {
+  if (b->idx.named.grpc_server_stats_bin != nullptr) {
+    ServerStatsDeserialize(
+        reinterpret_cast<const char*>(GRPC_SLICE_START_PTR(
+            GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md))),
+        GRPC_SLICE_LENGTH(GRPC_MDVALUE(b->idx.named.grpc_server_stats_bin->md)),
+        elapsed_time);
+    grpc_metadata_batch_remove(b, b->idx.named.grpc_server_stats_bin);
+  }
+}
+
+}  // namespace
+
+void CensusClientCallData::OnDoneRecvTrailingMetadataCb(void* user_data,
+                                                        grpc_error* error) {
+  grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+  CensusClientCallData* calld =
+      reinterpret_cast<CensusClientCallData*>(elem->call_data);
+  GPR_ASSERT(calld != nullptr);
+  if (error == GRPC_ERROR_NONE) {
+    GPR_ASSERT(calld->recv_trailing_metadata_ != nullptr);
+    FilterTrailingMetadata(calld->recv_trailing_metadata_,
+                           &calld->elapsed_time_);
+  }
+  GRPC_CLOSURE_RUN(calld->initial_on_done_recv_trailing_metadata_,
+                   GRPC_ERROR_REF(error));
+}
+
+void CensusClientCallData::OnDoneRecvMessageCb(void* user_data,
+                                               grpc_error* error) {
+  grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+  CensusClientCallData* calld =
+      reinterpret_cast<CensusClientCallData*>(elem->call_data);
+  CensusChannelData* channeld =
+      reinterpret_cast<CensusChannelData*>(elem->channel_data);
+  GPR_ASSERT(calld != nullptr);
+  GPR_ASSERT(channeld != nullptr);
+  // Stream messages are no longer valid after receiving trailing metadata.
+  if ((*calld->recv_message_) != nullptr) {
+    calld->recv_message_count_++;
+  }
+  GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error));
+}
+
+void CensusClientCallData::StartTransportStreamOpBatch(
+    grpc_call_element* elem, TransportStreamOpBatch* op) {
+  if (op->send_initial_metadata() != nullptr) {
+    census_context* ctxt = op->get_census_context();
+    GenerateClientContext(
+        qualified_method_, &context_,
+        (ctxt == nullptr) ? nullptr : reinterpret_cast<CensusContext*>(ctxt));
+    size_t tracing_len = TraceContextSerialize(context_.Context(), tracing_buf_,
+                                               kMaxTraceContextLen);
+    if (tracing_len > 0) {
+      GRPC_LOG_IF_ERROR(
+          "census grpc_filter",
+          grpc_metadata_batch_add_tail(
+              op->send_initial_metadata()->batch(), &tracing_bin_,
+              grpc_mdelem_from_slices(
+                  GRPC_MDSTR_GRPC_TRACE_BIN,
+                  grpc_slice_from_copied_buffer(tracing_buf_, tracing_len))));
+    }
+    grpc_slice tags = grpc_empty_slice();
+    // TODO: Add in tagging serialization.
+    size_t encoded_tags_len = StatsContextSerialize(kMaxTagsLen, &tags);
+    if (encoded_tags_len > 0) {
+      GRPC_LOG_IF_ERROR(
+          "census grpc_filter",
+          grpc_metadata_batch_add_tail(
+              op->send_initial_metadata()->batch(), &stats_bin_,
+              grpc_mdelem_from_slices(GRPC_MDSTR_GRPC_TAGS_BIN, tags)));
+    }
+  }
+
+  if (op->send_message() != nullptr) {
+    ++sent_message_count_;
+  }
+  if (op->recv_message() != nullptr) {
+    recv_message_ = op->op()->payload->recv_message.recv_message;
+    initial_on_done_recv_message_ =
+        op->op()->payload->recv_message.recv_message_ready;
+    op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_;
+  }
+  if (op->recv_trailing_metadata() != nullptr) {
+    recv_trailing_metadata_ = op->recv_trailing_metadata()->batch();
+    initial_on_done_recv_trailing_metadata_ =
+        op->op()->payload->recv_trailing_metadata.recv_trailing_metadata_ready;
+    op->op()->payload->recv_trailing_metadata.recv_trailing_metadata_ready =
+        &on_done_recv_trailing_metadata_;
+  }
+  // Call next op.
+  grpc_call_next_op(elem, op->op());
+}
+
+grpc_error* CensusClientCallData::Init(grpc_call_element* elem,
+                                       const grpc_call_element_args* args) {
+  path_ = grpc_slice_ref_internal(args->path);
+  start_time_ = absl::Now();
+  method_ = GetMethod(&path_);
+  qualified_method_ = absl::StrCat("Sent.", method_);
+  GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&on_done_recv_trailing_metadata_,
+                    OnDoneRecvTrailingMetadataCb, elem,
+                    grpc_schedule_on_exec_ctx);
+  return GRPC_ERROR_NONE;
+}
+
+void CensusClientCallData::Destroy(grpc_call_element* elem,
+                                   const grpc_call_final_info* final_info,
+                                   grpc_closure* then_call_closure) {
+  const uint64_t request_size = GetOutgoingDataSize(final_info);
+  const uint64_t response_size = GetIncomingDataSize(final_info);
+  double latency_ms = absl::ToDoubleMilliseconds(absl::Now() - start_time_);
+  ::opencensus::stats::Record(
+      {{RpcClientSentBytesPerRpc(), static_cast<double>(request_size)},
+       {RpcClientReceivedBytesPerRpc(), static_cast<double>(response_size)},
+       {RpcClientRoundtripLatency(), latency_ms},
+       {RpcClientServerLatency(),
+        ToDoubleMilliseconds(absl::Nanoseconds(elapsed_time_))},
+       {RpcClientSentMessagesPerRpc(), sent_message_count_},
+       {RpcClientReceivedMessagesPerRpc(), recv_message_count_}},
+      {{ClientMethodTagKey(), method_},
+       {ClientStatusTagKey(), StatusCodeToString(final_info->final_status)}});
+  grpc_slice_unref_internal(path_);
+  context_.EndSpan();
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/client_filter.h b/third_party/grpc/src/cpp/ext/filters/census/client_filter.h
new file mode 100644
index 0000000..8510228
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/client_filter.h
@@ -0,0 +1,104 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/strings/string_view.h"
+#include "absl/time/time.h"
+#include "src/cpp/ext/filters/census/channel_filter.h"
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+// A CallData class will be created for every grpc call within a channel. It is
+// used to store data and methods specific to that call. CensusClientCallData is
+// thread-compatible, however typically only 1 thread should be interacting with
+// a call at a time.
+class CensusClientCallData : public CallData {
+ public:
+  // Maximum size of trace context is sent on the wire.
+  static constexpr uint32_t kMaxTraceContextLen = 64;
+  // Maximum size of tags that are sent on the wire.
+  static constexpr uint32_t kMaxTagsLen = 2048;
+
+  CensusClientCallData()
+      : recv_trailing_metadata_(nullptr),
+        initial_on_done_recv_trailing_metadata_(nullptr),
+        initial_on_done_recv_message_(nullptr),
+        elapsed_time_(0),
+        recv_message_(nullptr),
+        recv_message_count_(0),
+        sent_message_count_(0) {
+    memset(&stats_bin_, 0, sizeof(grpc_linked_mdelem));
+    memset(&tracing_bin_, 0, sizeof(grpc_linked_mdelem));
+    memset(&path_, 0, sizeof(grpc_slice));
+    memset(&on_done_recv_trailing_metadata_, 0, sizeof(grpc_closure));
+    memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
+  }
+
+  grpc_error* Init(grpc_call_element* elem,
+                   const grpc_call_element_args* args) override;
+
+  void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info,
+               grpc_closure* then_call_closure) override;
+
+  void StartTransportStreamOpBatch(grpc_call_element* elem,
+                                   TransportStreamOpBatch* op) override;
+
+  static void OnDoneRecvTrailingMetadataCb(void* user_data, grpc_error* error);
+
+  static void OnDoneSendInitialMetadataCb(void* user_data, grpc_error* error);
+
+  static void OnDoneRecvMessageCb(void* user_data, grpc_error* error);
+
+ private:
+  CensusContext context_;
+  // Metadata elements for tracing and census stats data.
+  grpc_linked_mdelem stats_bin_;
+  grpc_linked_mdelem tracing_bin_;
+  // Client method.
+  absl::string_view method_;
+  std::string qualified_method_;
+  grpc_slice path_;
+  // The recv trailing metadata callbacks.
+  grpc_metadata_batch* recv_trailing_metadata_;
+  grpc_closure* initial_on_done_recv_trailing_metadata_;
+  grpc_closure on_done_recv_trailing_metadata_;
+  // recv message
+  grpc_closure* initial_on_done_recv_message_;
+  grpc_closure on_done_recv_message_;
+  // Start time (for measuring latency).
+  absl::Time start_time_;
+  // Server elapsed time in nanoseconds.
+  uint64_t elapsed_time_;
+  // The received message--may be null.
+  grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_;
+  // Number of messages in this RPC.
+  uint64_t recv_message_count_;
+  uint64_t sent_message_count_;
+  // Buffer needed for grpc_slice to reference when adding trace context
+  // metatdata to outgoing message.
+  char tracing_buf_[kMaxTraceContextLen];
+};
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CLIENT_FILTER_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/context.cc b/third_party/grpc/src/cpp/ext/filters/census/context.cc
new file mode 100644
index 0000000..1605903
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/context.cc
@@ -0,0 +1,144 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+using ::opencensus::trace::Span;
+using ::opencensus::trace::SpanContext;
+
+void GenerateServerContext(absl::string_view tracing, absl::string_view stats,
+                           absl::string_view primary_role,
+                           absl::string_view method, CensusContext* context) {
+  // Destruct the current CensusContext to free the Span memory before
+  // overwriting it below.
+  context->~CensusContext();
+  GrpcTraceContext trace_ctxt;
+  if (TraceContextEncoding::Decode(tracing, &trace_ctxt) !=
+      TraceContextEncoding::kEncodeDecodeFailure) {
+    SpanContext parent_ctx = trace_ctxt.ToSpanContext();
+    if (parent_ctx.IsValid()) {
+      new (context) CensusContext(method, parent_ctx);
+      return;
+    }
+  }
+  new (context) CensusContext(method);
+}
+
+void GenerateClientContext(absl::string_view method, CensusContext* ctxt,
+                           CensusContext* parent_ctxt) {
+  // Destruct the current CensusContext to free the Span memory before
+  // overwriting it below.
+  ctxt->~CensusContext();
+  if (parent_ctxt != nullptr) {
+    SpanContext span_ctxt = parent_ctxt->Context();
+    Span span = parent_ctxt->Span();
+    if (span_ctxt.IsValid()) {
+      new (ctxt) CensusContext(method, &span);
+      return;
+    }
+  }
+  new (ctxt) CensusContext(method);
+}
+
+size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context,
+                             char* tracing_buf, size_t tracing_buf_size) {
+  GrpcTraceContext trace_ctxt(context);
+  return TraceContextEncoding::Encode(trace_ctxt, tracing_buf,
+                                      tracing_buf_size);
+}
+
+size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags) {
+  // TODO: Add implementation. Waiting on stats tagging to be added.
+  return 0;
+}
+
+size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf,
+                            size_t buf_size) {
+  return RpcServerStatsEncoding::Encode(server_elapsed_time, buf, buf_size);
+}
+
+size_t ServerStatsDeserialize(const char* buf, size_t buf_size,
+                              uint64_t* server_elapsed_time) {
+  return RpcServerStatsEncoding::Decode(absl::string_view(buf, buf_size),
+                                        server_elapsed_time);
+}
+
+uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info) {
+  return final_info->stats.transport_stream_stats.incoming.data_bytes;
+}
+
+uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info) {
+  return final_info->stats.transport_stream_stats.outgoing.data_bytes;
+}
+
+SpanContext SpanContextFromCensusContext(const census_context* ctxt) {
+  return reinterpret_cast<const CensusContext*>(ctxt)->Context();
+}
+
+Span SpanFromCensusContext(const census_context* ctxt) {
+  return reinterpret_cast<const CensusContext*>(ctxt)->Span();
+}
+
+absl::string_view StatusCodeToString(grpc_status_code code) {
+  switch (code) {
+    case GRPC_STATUS_OK:
+      return "OK";
+    case GRPC_STATUS_CANCELLED:
+      return "CANCELLED";
+    case GRPC_STATUS_UNKNOWN:
+      return "UNKNOWN";
+    case GRPC_STATUS_INVALID_ARGUMENT:
+      return "INVALID_ARGUMENT";
+    case GRPC_STATUS_DEADLINE_EXCEEDED:
+      return "DEADLINE_EXCEEDED";
+    case GRPC_STATUS_NOT_FOUND:
+      return "NOT_FOUND";
+    case GRPC_STATUS_ALREADY_EXISTS:
+      return "ALREADY_EXISTS";
+    case GRPC_STATUS_PERMISSION_DENIED:
+      return "PERMISSION_DENIED";
+    case GRPC_STATUS_UNAUTHENTICATED:
+      return "UNAUTHENTICATED";
+    case GRPC_STATUS_RESOURCE_EXHAUSTED:
+      return "RESOURCE_EXHAUSTED";
+    case GRPC_STATUS_FAILED_PRECONDITION:
+      return "FAILED_PRECONDITION";
+    case GRPC_STATUS_ABORTED:
+      return "ABORTED";
+    case GRPC_STATUS_OUT_OF_RANGE:
+      return "OUT_OF_RANGE";
+    case GRPC_STATUS_UNIMPLEMENTED:
+      return "UNIMPLEMENTED";
+    case GRPC_STATUS_INTERNAL:
+      return "INTERNAL";
+    case GRPC_STATUS_UNAVAILABLE:
+      return "UNAVAILABLE";
+    case GRPC_STATUS_DATA_LOSS:
+      return "DATA_LOSS";
+    default:
+      // gRPC wants users of this enum to include a default branch so that
+      // adding values is not a breaking change.
+      return "UNKNOWN_STATUS";
+  }
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/context.h b/third_party/grpc/src/cpp/ext/filters/census/context.h
new file mode 100644
index 0000000..1643fdd
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/context.h
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/status.h>
+#include "absl/memory/memory.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "opencensus/trace/span.h"
+#include "opencensus/trace/span_context.h"
+#include "opencensus/trace/trace_params.h"
+#include "src/core/lib/slice/slice_internal.h"
+#include "src/cpp/common/channel_filter.h"
+#include "src/cpp/ext/filters/census/rpc_encoding.h"
+
+// This is needed because grpc has hardcoded CensusContext with a
+// forward declaration of 'struct census_context;'
+struct census_context;
+
+namespace grpc {
+
+// Thread compatible.
+class CensusContext {
+ public:
+  CensusContext() : span_(::opencensus::trace::Span::BlankSpan()) {}
+
+  explicit CensusContext(absl::string_view name)
+      : span_(::opencensus::trace::Span::StartSpan(name)) {}
+
+  CensusContext(absl::string_view name, const ::opencensus::trace::Span* parent)
+      : span_(::opencensus::trace::Span::StartSpan(name, parent)) {}
+
+  CensusContext(absl::string_view name,
+                const ::opencensus::trace::SpanContext& parent_ctxt)
+      : span_(::opencensus::trace::Span::StartSpanWithRemoteParent(
+            name, parent_ctxt)) {}
+
+  ::opencensus::trace::SpanContext Context() const { return span_.context(); }
+  ::opencensus::trace::Span Span() const { return span_; }
+  void EndSpan() { span_.End(); }
+
+ private:
+  ::opencensus::trace::Span span_;
+};
+
+// Serializes the outgoing trace context. Field IDs are 1 byte followed by
+// field data. A 1 byte version ID is always encoded first.
+size_t TraceContextSerialize(const ::opencensus::trace::SpanContext& context,
+                             char* tracing_buf, size_t tracing_buf_size);
+
+// Serializes the outgoing stats context.  Field IDs are 1 byte followed by
+// field data. A 1 byte version ID is always encoded first. Tags are directly
+// serialized into the given grpc_slice.
+size_t StatsContextSerialize(size_t max_tags_len, grpc_slice* tags);
+
+// Serialize outgoing server stats. Returns the number of bytes serialized.
+size_t ServerStatsSerialize(uint64_t server_elapsed_time, char* buf,
+                            size_t buf_size);
+
+// Deserialize incoming server stats. Returns the number of bytes deserialized.
+size_t ServerStatsDeserialize(const char* buf, size_t buf_size,
+                              uint64_t* server_elapsed_time);
+
+// Deserialize the incoming SpanContext and generate a new server context based
+// on that. This new span will never be a root span. This should only be called
+// with a blank CensusContext as it overwrites it.
+void GenerateServerContext(absl::string_view tracing, absl::string_view stats,
+                           absl::string_view primary_role,
+                           absl::string_view method, CensusContext* context);
+
+// Creates a new client context that is by default a new root context.
+// If the current context is the default context then the newly created
+// span automatically becomes a root span. This should only be called with a
+// blank CensusContext as it overwrites it.
+void GenerateClientContext(absl::string_view method, CensusContext* ctxt,
+                           CensusContext* parent_ctx);
+
+// Returns the incoming data size from the grpc call final info.
+uint64_t GetIncomingDataSize(const grpc_call_final_info* final_info);
+
+// Returns the outgoing data size from the grpc call final info.
+uint64_t GetOutgoingDataSize(const grpc_call_final_info* final_info);
+
+// These helper functions return the SpanContext and Span, respectively
+// associated with the census_context* stored by grpc. The user will need to
+// call this for manual propagation of tracing data.
+::opencensus::trace::SpanContext SpanContextFromCensusContext(
+    const census_context* ctxt);
+::opencensus::trace::Span SpanFromCensusContext(const census_context* ctxt);
+
+// Returns a string representation of the StatusCode enum.
+absl::string_view StatusCodeToString(grpc_status_code code);
+
+inline absl::string_view GetMethod(const grpc_slice* path) {
+  if (GRPC_SLICE_IS_EMPTY(*path)) {
+    return "";
+  }
+  // Check for leading '/' and trim it if present.
+  return absl::StripPrefix(absl::string_view(reinterpret_cast<const char*>(
+                                                 GRPC_SLICE_START_PTR(*path)),
+                                             GRPC_SLICE_LENGTH(*path)),
+                           "/");
+}
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_CONTEXT_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/grpc_plugin.cc b/third_party/grpc/src/cpp/ext/filters/census/grpc_plugin.cc
new file mode 100644
index 0000000..f978ed3
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/grpc_plugin.cc
@@ -0,0 +1,130 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+#include <grpcpp/server_context.h>
+
+#include "opencensus/trace/span.h"
+#include "src/cpp/ext/filters/census/channel_filter.h"
+#include "src/cpp/ext/filters/census/client_filter.h"
+#include "src/cpp/ext/filters/census/measures.h"
+#include "src/cpp/ext/filters/census/server_filter.h"
+
+namespace grpc {
+
+void RegisterOpenCensusPlugin() {
+  RegisterChannelFilter<CensusChannelData, CensusClientCallData>(
+      "opencensus_client", GRPC_CLIENT_CHANNEL, INT_MAX /* priority */,
+      nullptr /* condition function */);
+  RegisterChannelFilter<CensusChannelData, CensusServerCallData>(
+      "opencensus_server", GRPC_SERVER_CHANNEL, INT_MAX /* priority */,
+      nullptr /* condition function */);
+
+  // Access measures to ensure they are initialized. Otherwise, creating a view
+  // before the first RPC would cause an error.
+  RpcClientSentBytesPerRpc();
+  RpcClientReceivedBytesPerRpc();
+  RpcClientRoundtripLatency();
+  RpcClientServerLatency();
+  RpcClientSentMessagesPerRpc();
+  RpcClientReceivedMessagesPerRpc();
+
+  RpcServerSentBytesPerRpc();
+  RpcServerReceivedBytesPerRpc();
+  RpcServerServerLatency();
+  RpcServerSentMessagesPerRpc();
+  RpcServerReceivedMessagesPerRpc();
+}
+
+::opencensus::trace::Span GetSpanFromServerContext(ServerContext* context) {
+  return reinterpret_cast<const CensusContext*>(context->census_context())
+      ->Span();
+}
+
+// These measure definitions should be kept in sync across opencensus
+// implementations--see
+// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
+::opencensus::stats::TagKey ClientMethodTagKey() {
+  static const auto method_tag_key =
+      ::opencensus::stats::TagKey::Register("grpc_client_method");
+  return method_tag_key;
+}
+
+::opencensus::stats::TagKey ClientStatusTagKey() {
+  static const auto status_tag_key =
+      ::opencensus::stats::TagKey::Register("grpc_client_status");
+  return status_tag_key;
+}
+
+::opencensus::stats::TagKey ServerMethodTagKey() {
+  static const auto method_tag_key =
+      ::opencensus::stats::TagKey::Register("grpc_server_method");
+  return method_tag_key;
+}
+
+::opencensus::stats::TagKey ServerStatusTagKey() {
+  static const auto status_tag_key =
+      ::opencensus::stats::TagKey::Register("grpc_server_status");
+  return status_tag_key;
+}
+
+// Client
+ABSL_CONST_INIT const absl::string_view
+    kRpcClientSentMessagesPerRpcMeasureName =
+        "grpc.io/client/sent_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcClientSentBytesPerRpcMeasureName =
+    "grpc.io/client/sent_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+    kRpcClientReceivedMessagesPerRpcMeasureName =
+        "grpc.io/client/received_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+    kRpcClientReceivedBytesPerRpcMeasureName =
+        "grpc.io/client/received_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcClientRoundtripLatencyMeasureName =
+    "grpc.io/client/roundtrip_latency";
+
+ABSL_CONST_INIT const absl::string_view kRpcClientServerLatencyMeasureName =
+    "grpc.io/client/server_latency";
+
+// Server
+ABSL_CONST_INIT const absl::string_view
+    kRpcServerSentMessagesPerRpcMeasureName =
+        "grpc.io/server/sent_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcServerSentBytesPerRpcMeasureName =
+    "grpc.io/server/sent_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+    kRpcServerReceivedMessagesPerRpcMeasureName =
+        "grpc.io/server/received_messages_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view
+    kRpcServerReceivedBytesPerRpcMeasureName =
+        "grpc.io/server/received_bytes_per_rpc";
+
+ABSL_CONST_INIT const absl::string_view kRpcServerServerLatencyMeasureName =
+    "grpc.io/server/server_latency";
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/grpc_plugin.h b/third_party/grpc/src/cpp/ext/filters/census/grpc_plugin.h
new file mode 100644
index 0000000..9e319cb
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/grpc_plugin.h
@@ -0,0 +1,107 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/strings/string_view.h"
+#include "include/grpcpp/opencensus.h"
+#include "opencensus/stats/stats.h"
+
+namespace grpc {
+
+class ServerContext;
+
+// The tag keys set when recording RPC stats.
+::opencensus::stats::TagKey ClientMethodTagKey();
+::opencensus::stats::TagKey ClientStatusTagKey();
+::opencensus::stats::TagKey ServerMethodTagKey();
+::opencensus::stats::TagKey ServerStatusTagKey();
+
+// Names of measures used by the plugin--users can create views on these
+// measures but should not record data for them.
+extern const absl::string_view kRpcClientSentMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcClientSentBytesPerRpcMeasureName;
+extern const absl::string_view kRpcClientReceivedMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcClientReceivedBytesPerRpcMeasureName;
+extern const absl::string_view kRpcClientRoundtripLatencyMeasureName;
+extern const absl::string_view kRpcClientServerLatencyMeasureName;
+
+extern const absl::string_view kRpcServerSentMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcServerSentBytesPerRpcMeasureName;
+extern const absl::string_view kRpcServerReceivedMessagesPerRpcMeasureName;
+extern const absl::string_view kRpcServerReceivedBytesPerRpcMeasureName;
+extern const absl::string_view kRpcServerServerLatencyMeasureName;
+
+// Canonical gRPC view definitions.
+const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ClientReceivedMessagesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ClientReceivedBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientServerLatencyCumulative();
+const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsCumulative();
+
+const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ServerReceivedBytesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerServerLatencyCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerStartedCountCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsCumulative();
+const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcCumulative();
+const ::opencensus::stats::ViewDescriptor&
+ServerReceivedMessagesPerRpcCumulative();
+
+const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyMinute();
+const ::opencensus::stats::ViewDescriptor& ClientServerLatencyMinute();
+const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsMinute();
+
+const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcMinute();
+const ::opencensus::stats::ViewDescriptor& ServerServerLatencyMinute();
+const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsMinute();
+
+const ::opencensus::stats::ViewDescriptor& ClientSentMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientSentBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientReceivedBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ClientRoundtripLatencyHour();
+const ::opencensus::stats::ViewDescriptor& ClientServerLatencyHour();
+const ::opencensus::stats::ViewDescriptor& ClientCompletedRpcsHour();
+
+const ::opencensus::stats::ViewDescriptor& ServerSentMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerSentBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedMessagesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerReceivedBytesPerRpcHour();
+const ::opencensus::stats::ViewDescriptor& ServerServerLatencyHour();
+const ::opencensus::stats::ViewDescriptor& ServerStartedCountHour();
+const ::opencensus::stats::ViewDescriptor& ServerCompletedRpcsHour();
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_GRPC_PLUGIN_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/measures.cc b/third_party/grpc/src/cpp/ext/filters/census/measures.cc
new file mode 100644
index 0000000..b522fae
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/measures.cc
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/measures.h"
+
+#include "opencensus/stats/stats.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+namespace grpc {
+
+using ::opencensus::stats::MeasureDouble;
+using ::opencensus::stats::MeasureInt64;
+
+// These measure definitions should be kept in sync across opencensus
+// implementations--see
+// https://github.com/census-instrumentation/opencensus-java/blob/master/contrib/grpc_metrics/src/main/java/io/opencensus/contrib/grpc/metrics/RpcMeasureConstants.java.
+
+namespace {
+
+// Unit constants
+constexpr char kUnitBytes[] = "By";
+constexpr char kUnitMilliseconds[] = "ms";
+constexpr char kCount[] = "1";
+
+}  // namespace
+
+// Client
+MeasureDouble RpcClientSentBytesPerRpc() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcClientSentBytesPerRpcMeasureName,
+      "Total bytes sent across all request messages per RPC", kUnitBytes);
+  return measure;
+}
+
+MeasureDouble RpcClientReceivedBytesPerRpc() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcClientReceivedBytesPerRpcMeasureName,
+      "Total bytes received across all response messages per RPC", kUnitBytes);
+  return measure;
+}
+
+MeasureDouble RpcClientRoundtripLatency() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcClientRoundtripLatencyMeasureName,
+      "Time between first byte of request sent to last byte of response "
+      "received, or terminal error",
+      kUnitMilliseconds);
+  return measure;
+}
+
+MeasureDouble RpcClientServerLatency() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcClientServerLatencyMeasureName,
+      "Time between first byte of request received to last byte of response "
+      "sent, or terminal error (propagated from the server)",
+      kUnitMilliseconds);
+  return measure;
+}
+
+MeasureInt64 RpcClientSentMessagesPerRpc() {
+  static const auto measure =
+      MeasureInt64::Register(kRpcClientSentMessagesPerRpcMeasureName,
+                             "Number of messages sent per RPC", kCount);
+  return measure;
+}
+
+MeasureInt64 RpcClientReceivedMessagesPerRpc() {
+  static const auto measure =
+      MeasureInt64::Register(kRpcClientReceivedMessagesPerRpcMeasureName,
+                             "Number of messages received per RPC", kCount);
+  return measure;
+}
+
+// Server
+MeasureDouble RpcServerSentBytesPerRpc() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcServerSentBytesPerRpcMeasureName,
+      "Total bytes sent across all messages per RPC", kUnitBytes);
+  return measure;
+}
+
+MeasureDouble RpcServerReceivedBytesPerRpc() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcServerReceivedBytesPerRpcMeasureName,
+      "Total bytes received across all messages per RPC", kUnitBytes);
+  return measure;
+}
+
+MeasureDouble RpcServerServerLatency() {
+  static const auto measure = MeasureDouble::Register(
+      kRpcServerServerLatencyMeasureName,
+      "Time between first byte of request received to last byte of response "
+      "sent, or terminal error",
+      kUnitMilliseconds);
+  return measure;
+}
+
+MeasureInt64 RpcServerSentMessagesPerRpc() {
+  static const auto measure =
+      MeasureInt64::Register(kRpcServerSentMessagesPerRpcMeasureName,
+                             "Number of messages sent per RPC", kCount);
+  return measure;
+}
+
+MeasureInt64 RpcServerReceivedMessagesPerRpc() {
+  static const auto measure =
+      MeasureInt64::Register(kRpcServerReceivedMessagesPerRpcMeasureName,
+                             "Number of messages received per RPC", kCount);
+  return measure;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/measures.h b/third_party/grpc/src/cpp/ext/filters/census/measures.h
new file mode 100644
index 0000000..8f8e72a
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/measures.h
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H
+
+#include <grpc/support/port_platform.h>
+
+#include "opencensus/stats/stats.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+namespace grpc {
+
+::opencensus::stats::MeasureInt64 RpcClientSentMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcClientSentBytesPerRpc();
+::opencensus::stats::MeasureInt64 RpcClientReceivedMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcClientReceivedBytesPerRpc();
+::opencensus::stats::MeasureDouble RpcClientRoundtripLatency();
+::opencensus::stats::MeasureDouble RpcClientServerLatency();
+::opencensus::stats::MeasureInt64 RpcClientCompletedRpcs();
+
+::opencensus::stats::MeasureInt64 RpcServerSentMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcServerSentBytesPerRpc();
+::opencensus::stats::MeasureInt64 RpcServerReceivedMessagesPerRpc();
+::opencensus::stats::MeasureDouble RpcServerReceivedBytesPerRpc();
+::opencensus::stats::MeasureDouble RpcServerServerLatency();
+::opencensus::stats::MeasureInt64 RpcServerCompletedRpcs();
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_MEASURES_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/rpc_encoding.cc b/third_party/grpc/src/cpp/ext/filters/census/rpc_encoding.cc
new file mode 100644
index 0000000..45a66d9
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/rpc_encoding.cc
@@ -0,0 +1,39 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/rpc_encoding.h"
+
+namespace grpc {
+
+constexpr size_t TraceContextEncoding::kGrpcTraceContextSize;
+constexpr size_t TraceContextEncoding::kEncodeDecodeFailure;
+constexpr size_t TraceContextEncoding::kVersionIdSize;
+constexpr size_t TraceContextEncoding::kFieldIdSize;
+constexpr size_t TraceContextEncoding::kVersionIdOffset;
+constexpr size_t TraceContextEncoding::kVersionId;
+
+constexpr size_t RpcServerStatsEncoding::kRpcServerStatsSize;
+constexpr size_t RpcServerStatsEncoding::kEncodeDecodeFailure;
+constexpr size_t RpcServerStatsEncoding::kVersionIdSize;
+constexpr size_t RpcServerStatsEncoding::kFieldIdSize;
+constexpr size_t RpcServerStatsEncoding::kVersionIdOffset;
+constexpr size_t RpcServerStatsEncoding::kVersionId;
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/rpc_encoding.h b/third_party/grpc/src/cpp/ext/filters/census/rpc_encoding.h
new file mode 100644
index 0000000..ffffa60
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/rpc_encoding.h
@@ -0,0 +1,284 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H
+
+#include <grpc/support/port_platform.h>
+
+#include <string.h>
+
+#include "absl/base/internal/endian.h"
+#include "absl/strings/string_view.h"
+#include "opencensus/trace/span_context.h"
+#include "opencensus/trace/span_id.h"
+#include "opencensus/trace/trace_id.h"
+
+namespace grpc {
+
+// TODO: Rename to GrpcTraceContextV0.
+struct GrpcTraceContext {
+  GrpcTraceContext() {}
+
+  explicit GrpcTraceContext(const ::opencensus::trace::SpanContext& ctx) {
+    ctx.trace_id().CopyTo(trace_id);
+    ctx.span_id().CopyTo(span_id);
+    ctx.trace_options().CopyTo(trace_options);
+  }
+
+  ::opencensus::trace::SpanContext ToSpanContext() const {
+    return ::opencensus::trace::SpanContext(
+        ::opencensus::trace::TraceId(trace_id),
+        ::opencensus::trace::SpanId(span_id),
+        ::opencensus::trace::TraceOptions(trace_options));
+  }
+
+  // TODO: For performance:
+  // uint8_t version;
+  // uint8_t trace_id_field_id;
+  uint8_t trace_id[::opencensus::trace::TraceId::kSize];
+  // uint8_t span_id_field_id;
+  uint8_t span_id[::opencensus::trace::SpanId::kSize];
+  // uint8_t trace_options_field_id;
+  uint8_t trace_options[::opencensus::trace::TraceOptions::kSize];
+};
+
+// TraceContextEncoding encapsulates the logic for encoding and decoding of
+// trace contexts.
+class TraceContextEncoding {
+ public:
+  // Size of encoded GrpcTraceContext. (16 + 8 + 1 + 4)
+  static constexpr size_t kGrpcTraceContextSize = 29;
+  // Error value.
+  static constexpr size_t kEncodeDecodeFailure = 0;
+
+  // Deserializes a GrpcTraceContext from the incoming buffer. Returns the
+  // number of bytes deserialized from the buffer. If the incoming buffer is
+  // empty or the encoding version is not supported it will return 0 bytes,
+  // currently only version 0 is supported. If an unknown field ID is
+  // encountered it will return immediately without parsing the rest of the
+  // buffer. Inlined for performance reasons.
+  static size_t Decode(absl::string_view buf, GrpcTraceContext* tc) {
+    if (buf.empty()) {
+      return kEncodeDecodeFailure;
+    }
+    uint8_t version = buf[kVersionIdOffset];
+    // TODO: Support other versions later. Only support version 0 for
+    // now.
+    if (version != kVersionId) {
+      return kEncodeDecodeFailure;
+    }
+
+    size_t pos = kVersionIdSize;
+    while (pos < buf.size()) {
+      size_t bytes_read =
+          ParseField(absl::string_view(&buf[pos], buf.size() - pos), tc);
+      if (bytes_read == 0) {
+        break;
+      } else {
+        pos += bytes_read;
+      }
+    }
+    return pos;
+  }
+
+  // Serializes a GrpcTraceContext into the provided buffer. Returns the number
+  // of bytes serialized into the buffer. If the buffer is not of sufficient
+  // size (it must be at least kGrpcTraceContextSize bytes) it will drop
+  // everything and return 0 bytes serialized. Inlined for performance reasons.
+  static size_t Encode(const GrpcTraceContext& tc, char* buf, size_t buf_size) {
+    if (buf_size < kGrpcTraceContextSize) {
+      return kEncodeDecodeFailure;
+    }
+    buf[kVersionIdOffset] = kVersionId;
+    buf[kTraceIdOffset] = kTraceIdField;
+    memcpy(&buf[kTraceIdOffset + 1], tc.trace_id,
+           opencensus::trace::TraceId::kSize);
+    buf[kSpanIdOffset] = kSpanIdField;
+    memcpy(&buf[kSpanIdOffset + 1], tc.span_id,
+           opencensus::trace::SpanId::kSize);
+    buf[kTraceOptionsOffset] = kTraceOptionsField;
+    memcpy(&buf[kTraceOptionsOffset + 1], tc.trace_options,
+           opencensus::trace::TraceOptions::kSize);
+    return kGrpcTraceContextSize;
+  }
+
+ private:
+  // Parses the next field from the incoming buffer and stores the parsed value
+  // in a GrpcTraceContext struct.  If it does not recognize the field ID it
+  // will return 0, otherwise it returns the number of bytes read.
+  static size_t ParseField(absl::string_view buf, GrpcTraceContext* tc) {
+    // TODO: Add support for multi-byte field IDs.
+    if (buf.empty()) {
+      return 0;
+    }
+    // Field ID is always the first byte in a field.
+    uint32_t field_id = buf[0];
+    size_t bytes_read = kFieldIdSize;
+    switch (field_id) {
+      case kTraceIdField:
+        bytes_read += kTraceIdSize;
+        if (bytes_read > buf.size()) {
+          return 0;
+        }
+        memcpy(tc->trace_id, &buf[kFieldIdSize],
+               opencensus::trace::TraceId::kSize);
+        break;
+      case kSpanIdField:
+        bytes_read += kSpanIdSize;
+        if (bytes_read > buf.size()) {
+          return 0;
+        }
+        memcpy(tc->span_id, &buf[kFieldIdSize],
+               opencensus::trace::SpanId::kSize);
+        break;
+      case kTraceOptionsField:
+        bytes_read += kTraceOptionsSize;
+        if (bytes_read > buf.size()) {
+          return 0;
+        }
+        memcpy(tc->trace_options, &buf[kFieldIdSize],
+               opencensus::trace::TraceOptions::kSize);
+        break;
+      default:  // Invalid field ID
+        return 0;
+    }
+
+    return bytes_read;
+  }
+
+  // Size of Version ID.
+  static constexpr size_t kVersionIdSize = 1;
+  // Size of Field ID.
+  static constexpr size_t kFieldIdSize = 1;
+
+  // Offset and value for currently supported version ID.
+  static constexpr size_t kVersionIdOffset = 0;
+  static constexpr size_t kVersionId = 0;
+
+  // Fixed Field ID values:
+  enum FieldIdValue {
+    kTraceIdField = 0,
+    kSpanIdField = 1,
+    kTraceOptionsField = 2,
+  };
+
+  // Field data sizes in bytes
+  enum FieldSize {
+    kTraceIdSize = 16,
+    kSpanIdSize = 8,
+    kTraceOptionsSize = 1,
+  };
+
+  // Fixed size offsets for field ID start positions during encoding.  Field
+  // data immediately follows.
+  enum FieldIdOffset {
+    kTraceIdOffset = kVersionIdSize,
+    kSpanIdOffset = kTraceIdOffset + kFieldIdSize + kTraceIdSize,
+    kTraceOptionsOffset = kSpanIdOffset + kFieldIdSize + kSpanIdSize,
+  };
+
+  TraceContextEncoding() = delete;
+  TraceContextEncoding(const TraceContextEncoding&) = delete;
+  TraceContextEncoding(TraceContextEncoding&&) = delete;
+  TraceContextEncoding operator=(const TraceContextEncoding&) = delete;
+  TraceContextEncoding operator=(TraceContextEncoding&&) = delete;
+};
+
+// TODO: This may not be needed. Check to see if opencensus requires
+// a trailing server response.
+// RpcServerStatsEncoding encapsulates the logic for encoding and decoding of
+// rpc server stats messages. Rpc server stats consists of a uint64_t time
+// value (server latency in nanoseconds).
+class RpcServerStatsEncoding {
+ public:
+  // Size of encoded RPC server stats.
+  static constexpr size_t kRpcServerStatsSize = 10;
+  // Error value.
+  static constexpr size_t kEncodeDecodeFailure = 0;
+
+  // Deserializes rpc server stats from the incoming 'buf' into *time.  Returns
+  // number of bytes decoded. If the buffer is of insufficient size (it must be
+  // at least kRpcServerStatsSize bytes) or the encoding version or field ID are
+  // unrecognized, *time will be set to 0 and it will return
+  // kEncodeDecodeFailure. Inlined for performance reasons.
+  static size_t Decode(absl::string_view buf, uint64_t* time) {
+    if (buf.size() < kRpcServerStatsSize) {
+      *time = 0;
+      return kEncodeDecodeFailure;
+    }
+
+    uint8_t version = buf[kVersionIdOffset];
+    uint32_t fieldID = buf[kServerElapsedTimeOffset];
+    if (version != kVersionId || fieldID != kServerElapsedTimeField) {
+      *time = 0;
+      return kEncodeDecodeFailure;
+    }
+    *time = absl::little_endian::Load64(
+        &buf[kServerElapsedTimeOffset + kFieldIdSize]);
+    return kRpcServerStatsSize;
+  }
+
+  // Serializes rpc server stats into the provided buffer.  It returns the
+  // number of bytes written to the buffer. If the buffer is smaller than
+  // kRpcServerStatsSize bytes it will return kEncodeDecodeFailure. Inlined for
+  // performance reasons.
+  static size_t Encode(uint64_t time, char* buf, size_t buf_size) {
+    if (buf_size < kRpcServerStatsSize) {
+      return kEncodeDecodeFailure;
+    }
+
+    buf[kVersionIdOffset] = kVersionId;
+    buf[kServerElapsedTimeOffset] = kServerElapsedTimeField;
+    absl::little_endian::Store64(&buf[kServerElapsedTimeOffset + kFieldIdSize],
+                                 time);
+    return kRpcServerStatsSize;
+  }
+
+ private:
+  // Size of Version ID.
+  static constexpr size_t kVersionIdSize = 1;
+  // Size of Field ID.
+  static constexpr size_t kFieldIdSize = 1;
+
+  // Offset and value for currently supported version ID.
+  static constexpr size_t kVersionIdOffset = 0;
+  static constexpr size_t kVersionId = 0;
+
+  enum FieldIdValue {
+    kServerElapsedTimeField = 0,
+  };
+
+  enum FieldSize {
+    kServerElapsedTimeSize = 8,
+  };
+
+  enum FieldIdOffset {
+    kServerElapsedTimeOffset = kVersionIdSize,
+  };
+
+  RpcServerStatsEncoding() = delete;
+  RpcServerStatsEncoding(const RpcServerStatsEncoding&) = delete;
+  RpcServerStatsEncoding(RpcServerStatsEncoding&&) = delete;
+  RpcServerStatsEncoding operator=(const RpcServerStatsEncoding&) = delete;
+  RpcServerStatsEncoding operator=(RpcServerStatsEncoding&&) = delete;
+};
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_RPC_ENCODING_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/server_filter.cc b/third_party/grpc/src/cpp/ext/filters/census/server_filter.cc
new file mode 100644
index 0000000..b5f3d5a
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/server_filter.cc
@@ -0,0 +1,198 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/server_filter.h"
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "opencensus/stats/stats.h"
+#include "src/core/lib/surface/call.h"
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+#include "src/cpp/ext/filters/census/measures.h"
+
+namespace grpc {
+
+constexpr uint32_t CensusServerCallData::kMaxServerStatsLen;
+
+namespace {
+
+// server metadata elements
+struct ServerMetadataElements {
+  grpc_slice path;
+  grpc_slice tracing_slice;
+  grpc_slice census_proto;
+};
+
+void FilterInitialMetadata(grpc_metadata_batch* b,
+                           ServerMetadataElements* sml) {
+  if (b->idx.named.path != nullptr) {
+    sml->path = grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.path->md));
+  }
+  if (b->idx.named.grpc_trace_bin != nullptr) {
+    sml->tracing_slice =
+        grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_trace_bin->md));
+    grpc_metadata_batch_remove(b, b->idx.named.grpc_trace_bin);
+  }
+  if (b->idx.named.grpc_tags_bin != nullptr) {
+    sml->census_proto =
+        grpc_slice_ref_internal(GRPC_MDVALUE(b->idx.named.grpc_tags_bin->md));
+    grpc_metadata_batch_remove(b, b->idx.named.grpc_tags_bin);
+  }
+}
+
+}  // namespace
+
+void CensusServerCallData::OnDoneRecvMessageCb(void* user_data,
+                                               grpc_error* error) {
+  grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+  CensusServerCallData* calld =
+      reinterpret_cast<CensusServerCallData*>(elem->call_data);
+  CensusChannelData* channeld =
+      reinterpret_cast<CensusChannelData*>(elem->channel_data);
+  GPR_ASSERT(calld != nullptr);
+  GPR_ASSERT(channeld != nullptr);
+  // Stream messages are no longer valid after receiving trailing metadata.
+  if ((*calld->recv_message_) != nullptr) {
+    ++calld->recv_message_count_;
+  }
+  GRPC_CLOSURE_RUN(calld->initial_on_done_recv_message_, GRPC_ERROR_REF(error));
+}
+
+void CensusServerCallData::OnDoneRecvInitialMetadataCb(void* user_data,
+                                                       grpc_error* error) {
+  grpc_call_element* elem = reinterpret_cast<grpc_call_element*>(user_data);
+  CensusServerCallData* calld =
+      reinterpret_cast<CensusServerCallData*>(elem->call_data);
+  GPR_ASSERT(calld != nullptr);
+  if (error == GRPC_ERROR_NONE) {
+    grpc_metadata_batch* initial_metadata = calld->recv_initial_metadata_;
+    GPR_ASSERT(initial_metadata != nullptr);
+    ServerMetadataElements sml;
+    sml.path = grpc_empty_slice();
+    sml.tracing_slice = grpc_empty_slice();
+    sml.census_proto = grpc_empty_slice();
+    FilterInitialMetadata(initial_metadata, &sml);
+    calld->path_ = grpc_slice_ref_internal(sml.path);
+    calld->method_ = GetMethod(&calld->path_);
+    calld->qualified_method_ = absl::StrCat("Recv.", calld->method_);
+    const char* tracing_str =
+        GRPC_SLICE_IS_EMPTY(sml.tracing_slice)
+            ? ""
+            : reinterpret_cast<const char*>(
+                  GRPC_SLICE_START_PTR(sml.tracing_slice));
+    size_t tracing_str_len = GRPC_SLICE_IS_EMPTY(sml.tracing_slice)
+                                 ? 0
+                                 : GRPC_SLICE_LENGTH(sml.tracing_slice);
+    const char* census_str = GRPC_SLICE_IS_EMPTY(sml.census_proto)
+                                 ? ""
+                                 : reinterpret_cast<const char*>(
+                                       GRPC_SLICE_START_PTR(sml.census_proto));
+    size_t census_str_len = GRPC_SLICE_IS_EMPTY(sml.census_proto)
+                                ? 0
+                                : GRPC_SLICE_LENGTH(sml.census_proto);
+
+    GenerateServerContext(absl::string_view(tracing_str, tracing_str_len),
+                          absl::string_view(census_str, census_str_len),
+                          /*primary_role*/ "", calld->qualified_method_,
+                          &calld->context_);
+
+    grpc_slice_unref_internal(sml.tracing_slice);
+    grpc_slice_unref_internal(sml.census_proto);
+    grpc_slice_unref_internal(sml.path);
+    grpc_census_call_set_context(
+        calld->gc_, reinterpret_cast<census_context*>(&calld->context_));
+  }
+  GRPC_CLOSURE_RUN(calld->initial_on_done_recv_initial_metadata_,
+                   GRPC_ERROR_REF(error));
+}
+
+void CensusServerCallData::StartTransportStreamOpBatch(
+    grpc_call_element* elem, TransportStreamOpBatch* op) {
+  if (op->recv_initial_metadata() != nullptr) {
+    // substitute our callback for the op callback
+    recv_initial_metadata_ = op->recv_initial_metadata()->batch();
+    initial_on_done_recv_initial_metadata_ = op->recv_initial_metadata_ready();
+    op->set_recv_initial_metadata_ready(&on_done_recv_initial_metadata_);
+  }
+  if (op->send_message() != nullptr) {
+    ++sent_message_count_;
+  }
+  if (op->recv_message() != nullptr) {
+    recv_message_ = op->op()->payload->recv_message.recv_message;
+    initial_on_done_recv_message_ =
+        op->op()->payload->recv_message.recv_message_ready;
+    op->op()->payload->recv_message.recv_message_ready = &on_done_recv_message_;
+  }
+  // We need to record the time when the trailing metadata was sent to mark the
+  // completeness of the request.
+  if (op->send_trailing_metadata() != nullptr) {
+    elapsed_time_ = absl::Now() - start_time_;
+    size_t len = ServerStatsSerialize(absl::ToInt64Nanoseconds(elapsed_time_),
+                                      stats_buf_, kMaxServerStatsLen);
+    if (len > 0) {
+      GRPC_LOG_IF_ERROR(
+          "census grpc_filter",
+          grpc_metadata_batch_add_tail(
+              op->send_trailing_metadata()->batch(), &census_bin_,
+              grpc_mdelem_from_slices(
+                  GRPC_MDSTR_GRPC_SERVER_STATS_BIN,
+                  grpc_slice_from_copied_buffer(stats_buf_, len))));
+    }
+  }
+  // Call next op.
+  grpc_call_next_op(elem, op->op());
+}
+
+grpc_error* CensusServerCallData::Init(grpc_call_element* elem,
+                                       const grpc_call_element_args* args) {
+  start_time_ = absl::Now();
+  gc_ =
+      grpc_call_from_top_element(grpc_call_stack_element(args->call_stack, 0));
+  GRPC_CLOSURE_INIT(&on_done_recv_initial_metadata_,
+                    OnDoneRecvInitialMetadataCb, elem,
+                    grpc_schedule_on_exec_ctx);
+  GRPC_CLOSURE_INIT(&on_done_recv_message_, OnDoneRecvMessageCb, elem,
+                    grpc_schedule_on_exec_ctx);
+  auth_context_ = grpc_call_auth_context(gc_);
+  return GRPC_ERROR_NONE;
+}
+
+void CensusServerCallData::Destroy(grpc_call_element* elem,
+                                   const grpc_call_final_info* final_info,
+                                   grpc_closure* then_call_closure) {
+  const uint64_t request_size = GetOutgoingDataSize(final_info);
+  const uint64_t response_size = GetIncomingDataSize(final_info);
+  double elapsed_time_ms = absl::ToDoubleMilliseconds(elapsed_time_);
+  grpc_auth_context_release(auth_context_);
+  ::opencensus::stats::Record(
+      {{RpcServerSentBytesPerRpc(), static_cast<double>(response_size)},
+       {RpcServerReceivedBytesPerRpc(), static_cast<double>(request_size)},
+       {RpcServerServerLatency(), elapsed_time_ms},
+       {RpcServerSentMessagesPerRpc(), sent_message_count_},
+       {RpcServerReceivedMessagesPerRpc(), recv_message_count_}},
+      {{ServerMethodTagKey(), method_},
+       {ServerStatusTagKey(), StatusCodeToString(final_info->final_status)}});
+  grpc_slice_unref_internal(path_);
+  context_.EndSpan();
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/filters/census/server_filter.h b/third_party/grpc/src/cpp/ext/filters/census/server_filter.h
new file mode 100644
index 0000000..e393ed3
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/server_filter.h
@@ -0,0 +1,101 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H
+#define GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include "absl/strings/string_view.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "include/grpc/grpc_security.h"
+#include "src/cpp/ext/filters/census/channel_filter.h"
+#include "src/cpp/ext/filters/census/context.h"
+
+namespace grpc {
+
+// A CallData class will be created for every grpc call within a channel. It is
+// used to store data and methods specific to that call. CensusServerCallData is
+// thread-compatible, however typically only 1 thread should be interacting with
+// a call at a time.
+class CensusServerCallData : public CallData {
+ public:
+  // Maximum size of server stats that are sent on the wire.
+  static constexpr uint32_t kMaxServerStatsLen = 16;
+
+  CensusServerCallData()
+      : gc_(nullptr),
+        auth_context_(nullptr),
+        recv_initial_metadata_(nullptr),
+        initial_on_done_recv_initial_metadata_(nullptr),
+        initial_on_done_recv_message_(nullptr),
+        recv_message_(nullptr),
+        recv_message_count_(0),
+        sent_message_count_(0) {
+    memset(&census_bin_, 0, sizeof(grpc_linked_mdelem));
+    memset(&path_, 0, sizeof(grpc_slice));
+    memset(&on_done_recv_initial_metadata_, 0, sizeof(grpc_closure));
+    memset(&on_done_recv_message_, 0, sizeof(grpc_closure));
+  }
+
+  grpc_error* Init(grpc_call_element* elem,
+                   const grpc_call_element_args* args) override;
+
+  void Destroy(grpc_call_element* elem, const grpc_call_final_info* final_info,
+               grpc_closure* then_call_closure) override;
+
+  void StartTransportStreamOpBatch(grpc_call_element* elem,
+                                   TransportStreamOpBatch* op) override;
+
+  static void OnDoneRecvInitialMetadataCb(void* user_data, grpc_error* error);
+
+  static void OnDoneRecvMessageCb(void* user_data, grpc_error* error);
+
+ private:
+  CensusContext context_;
+  // server method
+  absl::string_view method_;
+  std::string qualified_method_;
+  grpc_slice path_;
+  // Pointer to the grpc_call element
+  grpc_call* gc_;
+  // Authorization context for the call.
+  grpc_auth_context* auth_context_;
+  // Metadata element for census stats.
+  grpc_linked_mdelem census_bin_;
+  // recv callback
+  grpc_metadata_batch* recv_initial_metadata_;
+  grpc_closure* initial_on_done_recv_initial_metadata_;
+  grpc_closure on_done_recv_initial_metadata_;
+  // recv message
+  grpc_closure* initial_on_done_recv_message_;
+  grpc_closure on_done_recv_message_;
+  absl::Time start_time_;
+  absl::Duration elapsed_time_;
+  grpc_core::OrphanablePtr<grpc_core::ByteStream>* recv_message_;
+  uint64_t recv_message_count_;
+  uint64_t sent_message_count_;
+  // Buffer needed for grpc_slice to reference it when adding metatdata to
+  // response.
+  char stats_buf_[kMaxServerStatsLen];
+};
+
+}  // namespace grpc
+
+#endif /* GRPC_INTERNAL_CPP_EXT_FILTERS_CENSUS_SERVER_FILTER_H */
diff --git a/third_party/grpc/src/cpp/ext/filters/census/views.cc b/third_party/grpc/src/cpp/ext/filters/census/views.cc
new file mode 100644
index 0000000..2c0c5f7
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/filters/census/views.cc
@@ -0,0 +1,491 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/ext/filters/census/grpc_plugin.h"
+
+#include "absl/time/time.h"
+#include "opencensus/stats/internal/aggregation_window.h"
+#include "opencensus/stats/internal/set_aggregation_window.h"
+#include "opencensus/stats/stats.h"
+
+namespace grpc {
+
+using ::opencensus::stats::Aggregation;
+using ::opencensus::stats::AggregationWindow;
+using ::opencensus::stats::BucketBoundaries;
+using ::opencensus::stats::ViewDescriptor;
+
+// These measure definitions should be kept in sync across opencensus
+// implementations.
+
+namespace {
+
+Aggregation BytesDistributionAggregation() {
+  return Aggregation::Distribution(BucketBoundaries::Explicit(
+      {0, 1024, 2048, 4096, 16384, 65536, 262144, 1048576, 4194304, 16777216,
+       67108864, 268435456, 1073741824, 4294967296}));
+}
+
+Aggregation MillisDistributionAggregation() {
+  return Aggregation::Distribution(BucketBoundaries::Explicit(
+      {0,   0.01, 0.05, 0.1,  0.3,   0.6,   0.8,   1,     2,   3,   4,
+       5,   6,    8,    10,   13,    16,    20,    25,    30,  40,  50,
+       65,  80,   100,  130,  160,   200,   250,   300,   400, 500, 650,
+       800, 1000, 2000, 5000, 10000, 20000, 50000, 100000}));
+}
+
+Aggregation CountDistributionAggregation() {
+  return Aggregation::Distribution(BucketBoundaries::Exponential(17, 1.0, 2.0));
+}
+
+ViewDescriptor MinuteDescriptor() {
+  auto descriptor = ViewDescriptor();
+  SetAggregationWindow(AggregationWindow::Interval(absl::Minutes(1)),
+                       &descriptor);
+  return descriptor;
+}
+
+ViewDescriptor HourDescriptor() {
+  auto descriptor = ViewDescriptor();
+  SetAggregationWindow(AggregationWindow::Interval(absl::Hours(1)),
+                       &descriptor);
+  return descriptor;
+}
+
+}  // namespace
+
+void RegisterOpenCensusViewsForExport() {
+  ClientSentMessagesPerRpcCumulative().RegisterForExport();
+  ClientSentBytesPerRpcCumulative().RegisterForExport();
+  ClientReceivedMessagesPerRpcCumulative().RegisterForExport();
+  ClientReceivedBytesPerRpcCumulative().RegisterForExport();
+  ClientRoundtripLatencyCumulative().RegisterForExport();
+  ClientServerLatencyCumulative().RegisterForExport();
+
+  ServerSentMessagesPerRpcCumulative().RegisterForExport();
+  ServerSentBytesPerRpcCumulative().RegisterForExport();
+  ServerReceivedMessagesPerRpcCumulative().RegisterForExport();
+  ServerReceivedBytesPerRpcCumulative().RegisterForExport();
+  ServerServerLatencyCumulative().RegisterForExport();
+}
+
+// client cumulative
+const ViewDescriptor& ClientSentBytesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/sent_bytes_per_rpc/cumulative")
+          .set_measure(kRpcClientSentBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedBytesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/received_bytes_per_rpc/cumulative")
+          .set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientRoundtripLatencyCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/roundtrip_latency/cumulative")
+          .set_measure(kRpcClientRoundtripLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientServerLatencyCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/server_latency/cumulative")
+          .set_measure(kRpcClientServerLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientCompletedRpcsCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/completed_rpcs/cumulative")
+          .set_measure(kRpcClientRoundtripLatencyMeasureName)
+          .set_aggregation(Aggregation::Count())
+          .add_column(ClientMethodTagKey())
+          .add_column(ClientStatusTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientSentMessagesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/received_messages_per_rpc/cumulative")
+          .set_measure(kRpcClientSentMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedMessagesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/client/sent_messages_per_rpc/cumulative")
+          .set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+// server cumulative
+const ViewDescriptor& ServerSentBytesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/server/received_bytes_per_rpc/cumulative")
+          .set_measure(kRpcServerSentBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedBytesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/server/sent_bytes_per_rpc/cumulative")
+          .set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerServerLatencyCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/server/elapsed_time/cumulative")
+          .set_measure(kRpcServerServerLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerCompletedRpcsCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/server/completed_rpcs/cumulative")
+          .set_measure(kRpcServerServerLatencyMeasureName)
+          .set_aggregation(Aggregation::Count())
+          .add_column(ServerMethodTagKey())
+          .add_column(ServerStatusTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerSentMessagesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/server/received_messages_per_rpc/cumulative")
+          .set_measure(kRpcServerSentMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedMessagesPerRpcCumulative() {
+  const static ViewDescriptor descriptor =
+      ViewDescriptor()
+          .set_name("grpc.io/server/sent_messages_per_rpc/cumulative")
+          .set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+// client minute
+const ViewDescriptor& ClientSentBytesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/sent_bytes_per_rpc/minute")
+          .set_measure(kRpcClientSentBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedBytesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/received_bytes_per_rpc/minute")
+          .set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientRoundtripLatencyMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/roundtrip_latency/minute")
+          .set_measure(kRpcClientRoundtripLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientServerLatencyMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/server_latency/minute")
+          .set_measure(kRpcClientServerLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientCompletedRpcsMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/completed_rpcs/minute")
+          .set_measure(kRpcClientRoundtripLatencyMeasureName)
+          .set_aggregation(Aggregation::Count())
+          .add_column(ClientMethodTagKey())
+          .add_column(ClientStatusTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientSentMessagesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/sent_messages_per_rpc/minute")
+          .set_measure(kRpcClientSentMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedMessagesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/client/received_messages_per_rpc/minute")
+          .set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+// server minute
+const ViewDescriptor& ServerSentBytesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/server/sent_bytes_per_rpc/minute")
+          .set_measure(kRpcServerSentBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedBytesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/server/received_bytes_per_rpc/minute")
+          .set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerServerLatencyMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/server/server_latency/minute")
+          .set_measure(kRpcServerServerLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerCompletedRpcsMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/server/completed_rpcs/minute")
+          .set_measure(kRpcServerServerLatencyMeasureName)
+          .set_aggregation(Aggregation::Count())
+          .add_column(ServerMethodTagKey())
+          .add_column(ServerStatusTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerSentMessagesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/server/sent_messages_per_rpc/minute")
+          .set_measure(kRpcServerSentMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedMessagesPerRpcMinute() {
+  const static ViewDescriptor descriptor =
+      MinuteDescriptor()
+          .set_name("grpc.io/server/received_messages_per_rpc/minute")
+          .set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+// client hour
+const ViewDescriptor& ClientSentBytesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/sent_bytes_per_rpc/hour")
+          .set_measure(kRpcClientSentBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedBytesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/received_bytes_per_rpc/hour")
+          .set_measure(kRpcClientReceivedBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientRoundtripLatencyHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/roundtrip_latency/hour")
+          .set_measure(kRpcClientRoundtripLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientServerLatencyHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/server_latency/hour")
+          .set_measure(kRpcClientServerLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientCompletedRpcsHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/completed_rpcs/hour")
+          .set_measure(kRpcClientRoundtripLatencyMeasureName)
+          .set_aggregation(Aggregation::Count())
+          .add_column(ClientMethodTagKey())
+          .add_column(ClientStatusTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientSentMessagesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/sent_messages_per_rpc/hour")
+          .set_measure(kRpcClientSentMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ClientReceivedMessagesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/client/received_messages_per_rpc/hour")
+          .set_measure(kRpcClientReceivedMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ClientMethodTagKey());
+  return descriptor;
+}
+
+// server hour
+const ViewDescriptor& ServerSentBytesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/server/sent_bytes_per_rpc/hour")
+          .set_measure(kRpcServerSentBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedBytesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/server/received_bytes_per_rpc/hour")
+          .set_measure(kRpcServerReceivedBytesPerRpcMeasureName)
+          .set_aggregation(BytesDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerServerLatencyHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/server/server_latency/hour")
+          .set_measure(kRpcServerServerLatencyMeasureName)
+          .set_aggregation(MillisDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerCompletedRpcsHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/server/completed_rpcs/hour")
+          .set_measure(kRpcServerServerLatencyMeasureName)
+          .set_aggregation(Aggregation::Count())
+          .add_column(ServerMethodTagKey())
+          .add_column(ServerStatusTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerSentMessagesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/server/sent_messages_per_rpc/hour")
+          .set_measure(kRpcServerSentMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+const ViewDescriptor& ServerReceivedMessagesPerRpcHour() {
+  const static ViewDescriptor descriptor =
+      HourDescriptor()
+          .set_name("grpc.io/server/received_messages_per_rpc/hour")
+          .set_measure(kRpcServerReceivedMessagesPerRpcMeasureName)
+          .set_aggregation(CountDistributionAggregation())
+          .add_column(ServerMethodTagKey());
+  return descriptor;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/proto_server_reflection.cc b/third_party/grpc/src/cpp/ext/proto_server_reflection.cc
new file mode 100644
index 0000000..f26f007
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/proto_server_reflection.cc
@@ -0,0 +1,212 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <unordered_set>
+#include <vector>
+
+#include <grpcpp/grpcpp.h>
+
+#include "src/cpp/ext/proto_server_reflection.h"
+
+using grpc::Status;
+using grpc::StatusCode;
+using grpc::reflection::v1alpha::ErrorResponse;
+using grpc::reflection::v1alpha::ExtensionNumberResponse;
+using grpc::reflection::v1alpha::ExtensionRequest;
+using grpc::reflection::v1alpha::FileDescriptorResponse;
+using grpc::reflection::v1alpha::ListServiceResponse;
+using grpc::reflection::v1alpha::ServerReflectionRequest;
+using grpc::reflection::v1alpha::ServerReflectionResponse;
+using grpc::reflection::v1alpha::ServiceResponse;
+
+namespace grpc {
+
+ProtoServerReflection::ProtoServerReflection()
+    : descriptor_pool_(protobuf::DescriptorPool::generated_pool()) {}
+
+void ProtoServerReflection::SetServiceList(
+    const std::vector<grpc::string>* services) {
+  services_ = services;
+}
+
+Status ProtoServerReflection::ServerReflectionInfo(
+    ServerContext* context,
+    ServerReaderWriter<ServerReflectionResponse, ServerReflectionRequest>*
+        stream) {
+  ServerReflectionRequest request;
+  ServerReflectionResponse response;
+  Status status;
+  while (stream->Read(&request)) {
+    switch (request.message_request_case()) {
+      case ServerReflectionRequest::MessageRequestCase::kFileByFilename:
+        status = GetFileByName(context, request.file_by_filename(), &response);
+        break;
+      case ServerReflectionRequest::MessageRequestCase::kFileContainingSymbol:
+        status = GetFileContainingSymbol(
+            context, request.file_containing_symbol(), &response);
+        break;
+      case ServerReflectionRequest::MessageRequestCase::
+          kFileContainingExtension:
+        status = GetFileContainingExtension(
+            context, &request.file_containing_extension(), &response);
+        break;
+      case ServerReflectionRequest::MessageRequestCase::
+          kAllExtensionNumbersOfType:
+        status = GetAllExtensionNumbers(
+            context, request.all_extension_numbers_of_type(),
+            response.mutable_all_extension_numbers_response());
+        break;
+      case ServerReflectionRequest::MessageRequestCase::kListServices:
+        status =
+            ListService(context, response.mutable_list_services_response());
+        break;
+      default:
+        status = Status(StatusCode::UNIMPLEMENTED, "");
+    }
+
+    if (!status.ok()) {
+      FillErrorResponse(status, response.mutable_error_response());
+    }
+    response.set_valid_host(request.host());
+    response.set_allocated_original_request(
+        new ServerReflectionRequest(request));
+    stream->Write(response);
+  }
+
+  return Status::OK;
+}
+
+void ProtoServerReflection::FillErrorResponse(const Status& status,
+                                              ErrorResponse* error_response) {
+  error_response->set_error_code(status.error_code());
+  error_response->set_error_message(status.error_message());
+}
+
+Status ProtoServerReflection::ListService(ServerContext* context,
+                                          ListServiceResponse* response) {
+  if (services_ == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "Services not found.");
+  }
+  for (auto it = services_->begin(); it != services_->end(); ++it) {
+    ServiceResponse* service_response = response->add_service();
+    service_response->set_name(*it);
+  }
+  return Status::OK;
+}
+
+Status ProtoServerReflection::GetFileByName(
+    ServerContext* context, const grpc::string& filename,
+    ServerReflectionResponse* response) {
+  if (descriptor_pool_ == nullptr) {
+    return Status::CANCELLED;
+  }
+
+  const protobuf::FileDescriptor* file_desc =
+      descriptor_pool_->FindFileByName(filename);
+  if (file_desc == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "File not found.");
+  }
+  std::unordered_set<grpc::string> seen_files;
+  FillFileDescriptorResponse(file_desc, response, &seen_files);
+  return Status::OK;
+}
+
+Status ProtoServerReflection::GetFileContainingSymbol(
+    ServerContext* context, const grpc::string& symbol,
+    ServerReflectionResponse* response) {
+  if (descriptor_pool_ == nullptr) {
+    return Status::CANCELLED;
+  }
+
+  const protobuf::FileDescriptor* file_desc =
+      descriptor_pool_->FindFileContainingSymbol(symbol);
+  if (file_desc == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "Symbol not found.");
+  }
+  std::unordered_set<grpc::string> seen_files;
+  FillFileDescriptorResponse(file_desc, response, &seen_files);
+  return Status::OK;
+}
+
+Status ProtoServerReflection::GetFileContainingExtension(
+    ServerContext* context, const ExtensionRequest* request,
+    ServerReflectionResponse* response) {
+  if (descriptor_pool_ == nullptr) {
+    return Status::CANCELLED;
+  }
+
+  const protobuf::Descriptor* desc =
+      descriptor_pool_->FindMessageTypeByName(request->containing_type());
+  if (desc == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "Type not found.");
+  }
+
+  const protobuf::FieldDescriptor* field_desc =
+      descriptor_pool_->FindExtensionByNumber(desc,
+                                              request->extension_number());
+  if (field_desc == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "Extension not found.");
+  }
+  std::unordered_set<grpc::string> seen_files;
+  FillFileDescriptorResponse(field_desc->file(), response, &seen_files);
+  return Status::OK;
+}
+
+Status ProtoServerReflection::GetAllExtensionNumbers(
+    ServerContext* context, const grpc::string& type,
+    ExtensionNumberResponse* response) {
+  if (descriptor_pool_ == nullptr) {
+    return Status::CANCELLED;
+  }
+
+  const protobuf::Descriptor* desc =
+      descriptor_pool_->FindMessageTypeByName(type);
+  if (desc == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "Type not found.");
+  }
+
+  std::vector<const protobuf::FieldDescriptor*> extensions;
+  descriptor_pool_->FindAllExtensions(desc, &extensions);
+  for (auto it = extensions.begin(); it != extensions.end(); it++) {
+    response->add_extension_number((*it)->number());
+  }
+  response->set_base_type_name(type);
+  return Status::OK;
+}
+
+void ProtoServerReflection::FillFileDescriptorResponse(
+    const protobuf::FileDescriptor* file_desc,
+    ServerReflectionResponse* response,
+    std::unordered_set<grpc::string>* seen_files) {
+  if (seen_files->find(file_desc->name()) != seen_files->end()) {
+    return;
+  }
+  seen_files->insert(file_desc->name());
+
+  protobuf::FileDescriptorProto file_desc_proto;
+  grpc::string data;
+  file_desc->CopyTo(&file_desc_proto);
+  file_desc_proto.SerializeToString(&data);
+  response->mutable_file_descriptor_response()->add_file_descriptor_proto(data);
+
+  for (int i = 0; i < file_desc->dependency_count(); ++i) {
+    FillFileDescriptorResponse(file_desc->dependency(i), response, seen_files);
+  }
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/ext/proto_server_reflection.h b/third_party/grpc/src/cpp/ext/proto_server_reflection.h
new file mode 100644
index 0000000..bf40c3c
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/proto_server_reflection.h
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H
+#define GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H
+
+#include <unordered_set>
+#include <vector>
+
+#include <grpcpp/grpcpp.h>
+#include "src/proto/grpc/reflection/v1alpha/reflection.grpc.pb.h"
+
+namespace grpc {
+
+class ProtoServerReflection final
+    : public reflection::v1alpha::ServerReflection::Service {
+ public:
+  ProtoServerReflection();
+
+  // Add the full names of registered services
+  void SetServiceList(const std::vector<grpc::string>* services);
+
+  // implementation of ServerReflectionInfo(stream ServerReflectionRequest) rpc
+  // in ServerReflection service
+  Status ServerReflectionInfo(
+      ServerContext* context,
+      ServerReaderWriter<reflection::v1alpha::ServerReflectionResponse,
+                         reflection::v1alpha::ServerReflectionRequest>* stream)
+      override;
+
+ private:
+  Status ListService(ServerContext* context,
+                     reflection::v1alpha::ListServiceResponse* response);
+
+  Status GetFileByName(ServerContext* context, const grpc::string& file_name,
+                       reflection::v1alpha::ServerReflectionResponse* response);
+
+  Status GetFileContainingSymbol(
+      ServerContext* context, const grpc::string& symbol,
+      reflection::v1alpha::ServerReflectionResponse* response);
+
+  Status GetFileContainingExtension(
+      ServerContext* context,
+      const reflection::v1alpha::ExtensionRequest* request,
+      reflection::v1alpha::ServerReflectionResponse* response);
+
+  Status GetAllExtensionNumbers(
+      ServerContext* context, const grpc::string& type,
+      reflection::v1alpha::ExtensionNumberResponse* response);
+
+  void FillFileDescriptorResponse(
+      const protobuf::FileDescriptor* file_desc,
+      reflection::v1alpha::ServerReflectionResponse* response,
+      std::unordered_set<grpc::string>* seen_files);
+
+  void FillErrorResponse(const Status& status,
+                         reflection::v1alpha::ErrorResponse* error_response);
+
+  const protobuf::DescriptorPool* descriptor_pool_;
+  const std::vector<string>* services_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPC_INTERNAL_CPP_EXT_PROTO_SERVER_REFLECTION_H
diff --git a/third_party/grpc/src/cpp/ext/proto_server_reflection_plugin.cc b/third_party/grpc/src/cpp/ext/proto_server_reflection_plugin.cc
new file mode 100644
index 0000000..ee3ac3f
--- /dev/null
+++ b/third_party/grpc/src/cpp/ext/proto_server_reflection_plugin.cc
@@ -0,0 +1,82 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/ext/proto_server_reflection_plugin.h>
+#include <grpcpp/impl/server_builder_plugin.h>
+#include <grpcpp/impl/server_initializer.h>
+#include <grpcpp/server.h>
+
+#include "src/cpp/ext/proto_server_reflection.h"
+
+namespace grpc {
+namespace reflection {
+
+ProtoServerReflectionPlugin::ProtoServerReflectionPlugin()
+    : reflection_service_(new grpc::ProtoServerReflection()) {}
+
+grpc::string ProtoServerReflectionPlugin::name() {
+  return "proto_server_reflection";
+}
+
+void ProtoServerReflectionPlugin::InitServer(grpc::ServerInitializer* si) {
+  si->RegisterService(reflection_service_);
+}
+
+void ProtoServerReflectionPlugin::Finish(grpc::ServerInitializer* si) {
+  reflection_service_->SetServiceList(si->GetServiceList());
+}
+
+void ProtoServerReflectionPlugin::ChangeArguments(const grpc::string& name,
+                                                  void* value) {}
+
+bool ProtoServerReflectionPlugin::has_sync_methods() const {
+  if (reflection_service_) {
+    return reflection_service_->has_synchronous_methods();
+  }
+  return false;
+}
+
+bool ProtoServerReflectionPlugin::has_async_methods() const {
+  if (reflection_service_) {
+    return reflection_service_->has_async_methods();
+  }
+  return false;
+}
+
+static std::unique_ptr< ::grpc::ServerBuilderPlugin> CreateProtoReflection() {
+  return std::unique_ptr< ::grpc::ServerBuilderPlugin>(
+      new ProtoServerReflectionPlugin());
+}
+
+void InitProtoReflectionServerBuilderPlugin() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  ::grpc::ServerBuilder::InternalAddPluginFactory(&CreateProtoReflection);
+}
+
+// Force InitProtoReflectionServerBuilderPlugin() to be called at static
+// initialization time.
+struct StaticProtoReflectionPluginInitializer {
+  StaticProtoReflectionPluginInitializer() {
+    InitProtoReflectionServerBuilderPlugin();
+  }
+} static_proto_reflection_plugin_initializer;
+
+}  // namespace reflection
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/proto/proto_utils.cc b/third_party/grpc/src/cpp/proto/proto_utils.cc
deleted file mode 100644
index 79e7bf1..0000000
--- a/third_party/grpc/src/cpp/proto/proto_utils.cc
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/impl/proto_utils.h>
-
-#include <climits>
-
-#include <grpc/grpc.h>
-#include <grpc/byte_buffer.h>
-#include <grpc/byte_buffer_reader.h>
-#include <grpc/support/log.h>
-#include <grpc/support/slice.h>
-#include <grpc/support/slice_buffer.h>
-#include <grpc/support/port_platform.h>
-#include <grpc++/support/config.h>
-
-#include "src/core/profiling/timers.h"
-
-const int kMaxBufferLength = 8192;
-
-class GrpcBufferWriter GRPC_FINAL
-    : public ::grpc::protobuf::io::ZeroCopyOutputStream {
- public:
-  explicit GrpcBufferWriter(grpc_byte_buffer** bp,
-                            int block_size = kMaxBufferLength)
-      : block_size_(block_size), byte_count_(0), have_backup_(false) {
-    *bp = grpc_raw_byte_buffer_create(NULL, 0);
-    slice_buffer_ = &(*bp)->data.raw.slice_buffer;
-  }
-
-  ~GrpcBufferWriter() GRPC_OVERRIDE {
-    if (have_backup_) {
-      gpr_slice_unref(backup_slice_);
-    }
-  }
-
-  bool Next(void** data, int* size) GRPC_OVERRIDE {
-    if (have_backup_) {
-      slice_ = backup_slice_;
-      have_backup_ = false;
-    } else {
-      slice_ = gpr_slice_malloc(block_size_);
-    }
-    *data = GPR_SLICE_START_PTR(slice_);
-    // On win x64, int is only 32bit
-    GPR_ASSERT(GPR_SLICE_LENGTH(slice_) <= INT_MAX);
-    byte_count_ += * size = (int)GPR_SLICE_LENGTH(slice_);
-    gpr_slice_buffer_add(slice_buffer_, slice_);
-    return true;
-  }
-
-  void BackUp(int count) GRPC_OVERRIDE {
-    gpr_slice_buffer_pop(slice_buffer_);
-    if (count == block_size_) {
-      backup_slice_ = slice_;
-    } else {
-      backup_slice_ =
-          gpr_slice_split_tail(&slice_, GPR_SLICE_LENGTH(slice_) - count);
-      gpr_slice_buffer_add(slice_buffer_, slice_);
-    }
-    have_backup_ = true;
-    byte_count_ -= count;
-  }
-
-  grpc::protobuf::int64 ByteCount() const GRPC_OVERRIDE { return byte_count_; }
-
- private:
-  const int block_size_;
-  int64_t byte_count_;
-  gpr_slice_buffer* slice_buffer_;
-  bool have_backup_;
-  gpr_slice backup_slice_;
-  gpr_slice slice_;
-};
-
-class GrpcBufferReader GRPC_FINAL
-    : public ::grpc::protobuf::io::ZeroCopyInputStream {
- public:
-  explicit GrpcBufferReader(grpc_byte_buffer* buffer)
-      : byte_count_(0), backup_count_(0) {
-    grpc_byte_buffer_reader_init(&reader_, buffer);
-  }
-  ~GrpcBufferReader() GRPC_OVERRIDE {
-    grpc_byte_buffer_reader_destroy(&reader_);
-  }
-
-  bool Next(const void** data, int* size) GRPC_OVERRIDE {
-    if (backup_count_ > 0) {
-      *data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) -
-              backup_count_;
-      GPR_ASSERT(backup_count_ <= INT_MAX);
-      *size = (int)backup_count_;
-      backup_count_ = 0;
-      return true;
-    }
-    if (!grpc_byte_buffer_reader_next(&reader_, &slice_)) {
-      return false;
-    }
-    gpr_slice_unref(slice_);
-    *data = GPR_SLICE_START_PTR(slice_);
-    // On win x64, int is only 32bit
-    GPR_ASSERT(GPR_SLICE_LENGTH(slice_) <= INT_MAX);
-    byte_count_ += * size = (int)GPR_SLICE_LENGTH(slice_);
-    return true;
-  }
-
-  void BackUp(int count) GRPC_OVERRIDE { backup_count_ = count; }
-
-  bool Skip(int count) GRPC_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;
-  }
-
-  grpc::protobuf::int64 ByteCount() const GRPC_OVERRIDE {
-    return byte_count_ - backup_count_;
-  }
-
- private:
-  int64_t byte_count_;
-  int64_t backup_count_;
-  grpc_byte_buffer_reader reader_;
-  gpr_slice slice_;
-};
-
-namespace grpc {
-
-Status SerializeProto(const grpc::protobuf::Message& msg,
-                      grpc_byte_buffer** bp) {
-  GPR_TIMER_SCOPE("SerializeProto", 0);
-  int byte_size = msg.ByteSize();
-  if (byte_size <= kMaxBufferLength) {
-    gpr_slice slice = gpr_slice_malloc(byte_size);
-    GPR_ASSERT(GPR_SLICE_END_PTR(slice) ==
-               msg.SerializeWithCachedSizesToArray(GPR_SLICE_START_PTR(slice)));
-    *bp = grpc_raw_byte_buffer_create(&slice, 1);
-    gpr_slice_unref(slice);
-    return Status::OK;
-  } else {
-    GrpcBufferWriter writer(bp);
-    return msg.SerializeToZeroCopyStream(&writer)
-               ? Status::OK
-               : Status(StatusCode::INTERNAL, "Failed to serialize message");
-  }
-}
-
-Status DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg,
-                        int max_message_size) {
-  GPR_TIMER_SCOPE("DeserializeProto", 0);
-  if (!buffer) {
-    return Status(StatusCode::INTERNAL, "No payload");
-  }
-  GrpcBufferReader reader(buffer);
-  ::grpc::protobuf::io::CodedInputStream decoder(&reader);
-  if (max_message_size > 0) {
-    decoder.SetTotalBytesLimit(max_message_size, max_message_size);
-  }
-  if (!msg->ParseFromCodedStream(&decoder)) {
-    return Status(StatusCode::INTERNAL, msg->InitializationErrorString());
-  }
-  if (!decoder.ConsumedEntireMessage()) {
-    return Status(StatusCode::INTERNAL, "Did not read entire message");
-  }
-  return Status::OK;
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/async_generic_service.cc b/third_party/grpc/src/cpp/server/async_generic_service.cc
index 6b9ea53..3061376 100644
--- a/third_party/grpc/src/cpp/server/async_generic_service.cc
+++ b/third_party/grpc/src/cpp/server/async_generic_service.cc
@@ -1,39 +1,24 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/generic/async_generic_service.h>
+#include <grpcpp/generic/async_generic_service.h>
 
-#include <grpc++/server.h>
+#include <grpcpp/server.h>
 
 namespace grpc {
 
diff --git a/third_party/grpc/src/cpp/server/channel_argument_option.cc b/third_party/grpc/src/cpp/server/channel_argument_option.cc
new file mode 100644
index 0000000..4d6be90
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/channel_argument_option.cc
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/impl/channel_argument_option.h>
+
+namespace grpc {
+
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+    const grpc::string& name, const grpc::string& value) {
+  class StringOption final : public ServerBuilderOption {
+   public:
+    StringOption(const grpc::string& name, const grpc::string& value)
+        : name_(name), value_(value) {}
+
+    virtual void UpdateArguments(ChannelArguments* args) override {
+      args->SetString(name_, value_);
+    }
+    virtual void UpdatePlugins(
+        std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override {}
+
+   private:
+    const grpc::string name_;
+    const grpc::string value_;
+  };
+  return std::unique_ptr<ServerBuilderOption>(new StringOption(name, value));
+}
+
+std::unique_ptr<ServerBuilderOption> MakeChannelArgumentOption(
+    const grpc::string& name, int value) {
+  class IntOption final : public ServerBuilderOption {
+   public:
+    IntOption(const grpc::string& name, int value)
+        : name_(name), value_(value) {}
+
+    virtual void UpdateArguments(ChannelArguments* args) override {
+      args->SetInt(name_, value_);
+    }
+    virtual void UpdatePlugins(
+        std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) override {}
+
+   private:
+    const grpc::string name_;
+    const int value_;
+  };
+  return std::unique_ptr<ServerBuilderOption>(new IntOption(name, value));
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/channelz/channelz_service.cc b/third_party/grpc/src/cpp/server/channelz/channelz_service.cc
new file mode 100644
index 0000000..c44a9ac
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/channelz/channelz_service.cc
@@ -0,0 +1,146 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/server/channelz/channelz_service.h"
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+
+namespace grpc {
+
+Status ChannelzService::GetTopChannels(
+    ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request,
+    channelz::v1::GetTopChannelsResponse* response) {
+  char* json_str = grpc_channelz_get_top_channels(request->start_channel_id());
+  if (json_str == nullptr) {
+    return Status(StatusCode::INTERNAL,
+                  "grpc_channelz_get_top_channels returned null");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+Status ChannelzService::GetServers(
+    ServerContext* unused, const channelz::v1::GetServersRequest* request,
+    channelz::v1::GetServersResponse* response) {
+  char* json_str = grpc_channelz_get_servers(request->start_server_id());
+  if (json_str == nullptr) {
+    return Status(StatusCode::INTERNAL,
+                  "grpc_channelz_get_servers returned null");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+Status ChannelzService::GetServer(ServerContext* unused,
+                                  const channelz::v1::GetServerRequest* request,
+                                  channelz::v1::GetServerResponse* response) {
+  char* json_str = grpc_channelz_get_server(request->server_id());
+  if (json_str == nullptr) {
+    return Status(StatusCode::INTERNAL,
+                  "grpc_channelz_get_server returned null");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+Status ChannelzService::GetServerSockets(
+    ServerContext* unused, const channelz::v1::GetServerSocketsRequest* request,
+    channelz::v1::GetServerSocketsResponse* response) {
+  char* json_str = grpc_channelz_get_server_sockets(
+      request->server_id(), request->start_socket_id(), request->max_results());
+  if (json_str == nullptr) {
+    return Status(StatusCode::INTERNAL,
+                  "grpc_channelz_get_server_sockets returned null");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+Status ChannelzService::GetChannel(
+    ServerContext* unused, const channelz::v1::GetChannelRequest* request,
+    channelz::v1::GetChannelResponse* response) {
+  char* json_str = grpc_channelz_get_channel(request->channel_id());
+  if (json_str == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "No object found for that ChannelId");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+Status ChannelzService::GetSubchannel(
+    ServerContext* unused, const channelz::v1::GetSubchannelRequest* request,
+    channelz::v1::GetSubchannelResponse* response) {
+  char* json_str = grpc_channelz_get_subchannel(request->subchannel_id());
+  if (json_str == nullptr) {
+    return Status(StatusCode::NOT_FOUND,
+                  "No object found for that SubchannelId");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+Status ChannelzService::GetSocket(ServerContext* unused,
+                                  const channelz::v1::GetSocketRequest* request,
+                                  channelz::v1::GetSocketResponse* response) {
+  char* json_str = grpc_channelz_get_socket(request->socket_id());
+  if (json_str == nullptr) {
+    return Status(StatusCode::NOT_FOUND, "No object found for that SocketId");
+  }
+  grpc::protobuf::util::Status s =
+      grpc::protobuf::json::JsonStringToMessage(json_str, response);
+  gpr_free(json_str);
+  if (!s.ok()) {
+    return Status(StatusCode::INTERNAL, s.ToString());
+  }
+  return Status::OK;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/channelz/channelz_service.h b/third_party/grpc/src/cpp/server/channelz/channelz_service.h
new file mode 100644
index 0000000..b4a66ba
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/channelz/channelz_service.h
@@ -0,0 +1,64 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_SERVER_CHANNELZ_SERVICE_H
+#define GRPC_INTERNAL_CPP_SERVER_CHANNELZ_SERVICE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpcpp/grpcpp.h>
+#include "src/proto/grpc/channelz/channelz.grpc.pb.h"
+
+namespace grpc {
+
+class ChannelzService final : public channelz::v1::Channelz::Service {
+ private:
+  // implementation of GetTopChannels rpc
+  Status GetTopChannels(
+      ServerContext* unused, const channelz::v1::GetTopChannelsRequest* request,
+      channelz::v1::GetTopChannelsResponse* response) override;
+  // implementation of GetServers rpc
+  Status GetServers(ServerContext* unused,
+                    const channelz::v1::GetServersRequest* request,
+                    channelz::v1::GetServersResponse* response) override;
+  // implementation of GetServer rpc
+  Status GetServer(ServerContext* unused,
+                   const channelz::v1::GetServerRequest* request,
+                   channelz::v1::GetServerResponse* response) override;
+  // implementation of GetServerSockets rpc
+  Status GetServerSockets(
+      ServerContext* unused,
+      const channelz::v1::GetServerSocketsRequest* request,
+      channelz::v1::GetServerSocketsResponse* response) override;
+  // implementation of GetChannel rpc
+  Status GetChannel(ServerContext* unused,
+                    const channelz::v1::GetChannelRequest* request,
+                    channelz::v1::GetChannelResponse* response) override;
+  // implementation of GetSubchannel rpc
+  Status GetSubchannel(ServerContext* unused,
+                       const channelz::v1::GetSubchannelRequest* request,
+                       channelz::v1::GetSubchannelResponse* response) override;
+  // implementation of GetSocket rpc
+  Status GetSocket(ServerContext* unused,
+                   const channelz::v1::GetSocketRequest* request,
+                   channelz::v1::GetSocketResponse* response) override;
+};
+
+}  // namespace grpc
+
+#endif  // GRPC_INTERNAL_CPP_SERVER_CHANNELZ_SERVICE_H
diff --git a/third_party/grpc/src/cpp/server/channelz/channelz_service_plugin.cc b/third_party/grpc/src/cpp/server/channelz/channelz_service_plugin.cc
new file mode 100644
index 0000000..b93e5b5
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/channelz/channelz_service_plugin.cc
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include <grpcpp/ext/channelz_service_plugin.h>
+#include <grpcpp/impl/server_builder_plugin.h>
+#include <grpcpp/impl/server_initializer.h>
+#include <grpcpp/server.h>
+
+#include "src/cpp/server/channelz/channelz_service.h"
+
+namespace grpc {
+namespace channelz {
+namespace experimental {
+
+class ChannelzServicePlugin : public ::grpc::ServerBuilderPlugin {
+ public:
+  ChannelzServicePlugin() : channelz_service_(new grpc::ChannelzService()) {}
+
+  grpc::string name() override { return "channelz_service"; }
+
+  void InitServer(grpc::ServerInitializer* si) override {
+    si->RegisterService(channelz_service_);
+  }
+
+  void Finish(grpc::ServerInitializer* si) override {}
+
+  void ChangeArguments(const grpc::string& name, void* value) override {}
+
+  bool has_sync_methods() const override {
+    if (channelz_service_) {
+      return channelz_service_->has_synchronous_methods();
+    }
+    return false;
+  }
+
+  bool has_async_methods() const override {
+    if (channelz_service_) {
+      return channelz_service_->has_async_methods();
+    }
+    return false;
+  }
+
+ private:
+  std::shared_ptr<grpc::ChannelzService> channelz_service_;
+};
+
+static std::unique_ptr< ::grpc::ServerBuilderPlugin>
+CreateChannelzServicePlugin() {
+  return std::unique_ptr< ::grpc::ServerBuilderPlugin>(
+      new ChannelzServicePlugin());
+}
+
+void InitChannelzService() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  ::grpc::ServerBuilder::InternalAddPluginFactory(&CreateChannelzServicePlugin);
+}
+
+}  // namespace experimental
+}  // namespace channelz
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/create_default_thread_pool.cc b/third_party/grpc/src/cpp/server/create_default_thread_pool.cc
index f3b07ec..8ca3e32 100644
--- a/third_party/grpc/src/cpp/server/create_default_thread_pool.cc
+++ b/third_party/grpc/src/cpp/server/create_default_thread_pool.cc
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -38,13 +23,22 @@
 #ifndef GRPC_CUSTOM_DEFAULT_THREAD_POOL
 
 namespace grpc {
+namespace {
 
-ThreadPoolInterface* CreateDefaultThreadPool() {
+ThreadPoolInterface* CreateDefaultThreadPoolImpl() {
   int cores = gpr_cpu_num_cores();
   if (!cores) cores = 4;
   return new DynamicThreadPool(cores);
 }
 
+CreateThreadPoolFunc g_ctp_impl = CreateDefaultThreadPoolImpl;
+
+}  // namespace
+
+ThreadPoolInterface* CreateDefaultThreadPool() { return g_ctp_impl(); }
+
+void SetCreateThreadPool(CreateThreadPoolFunc func) { g_ctp_impl = func; }
+
 }  // namespace grpc
 
 #endif  // !GRPC_CUSTOM_DEFAULT_THREAD_POOL
diff --git a/third_party/grpc/src/cpp/server/dynamic_thread_pool.cc b/third_party/grpc/src/cpp/server/dynamic_thread_pool.cc
index 4b226c2..ef99d64 100644
--- a/third_party/grpc/src/cpp/server/dynamic_thread_pool.cc
+++ b/third_party/grpc/src/cpp/server/dynamic_thread_pool.cc
@@ -1,55 +1,46 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/impl/sync.h>
-#include <grpc++/impl/thd.h>
-
 #include "src/cpp/server/dynamic_thread_pool.h"
 
+#include <mutex>
+
+#include <grpc/support/log.h>
+
+#include "src/core/lib/gprpp/thd.h"
+
 namespace grpc {
+
 DynamicThreadPool::DynamicThread::DynamicThread(DynamicThreadPool* pool)
     : pool_(pool),
-      thd_(new grpc::thread(&DynamicThreadPool::DynamicThread::ThreadFunc,
-                            this)) {}
-DynamicThreadPool::DynamicThread::~DynamicThread() {
-  thd_->join();
-  thd_.reset();
+      thd_("grpcpp_dynamic_pool",
+           [](void* th) {
+             static_cast<DynamicThreadPool::DynamicThread*>(th)->ThreadFunc();
+           },
+           this) {
+  thd_.Start();
 }
+DynamicThreadPool::DynamicThread::~DynamicThread() { thd_.Join(); }
 
 void DynamicThreadPool::DynamicThread::ThreadFunc() {
   pool_->ThreadFunc();
   // Now that we have killed ourselves, we should reduce the thread count
-  grpc::unique_lock<grpc::mutex> lock(pool_->mu_);
+  std::unique_lock<std::mutex> lock(pool_->mu_);
   pool_->nthreads_--;
   // Move ourselves to dead list
   pool_->dead_threads_.push_back(this);
@@ -62,7 +53,7 @@
 void DynamicThreadPool::ThreadFunc() {
   for (;;) {
     // Wait until work is available or we are shutting down.
-    grpc::unique_lock<grpc::mutex> lock(mu_);
+    std::unique_lock<std::mutex> lock(mu_);
     if (!shutdown_ && callbacks_.empty()) {
       // If there are too many threads waiting, then quit this thread
       if (threads_waiting_ >= reserve_threads_) {
@@ -91,7 +82,7 @@
       nthreads_(0),
       threads_waiting_(0) {
   for (int i = 0; i < reserve_threads_; i++) {
-    grpc::lock_guard<grpc::mutex> lock(mu_);
+    std::lock_guard<std::mutex> lock(mu_);
     nthreads_++;
     new DynamicThread(this);
   }
@@ -104,7 +95,7 @@
 }
 
 DynamicThreadPool::~DynamicThreadPool() {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
+  std::unique_lock<std::mutex> lock(mu_);
   shutdown_ = true;
   cv_.notify_all();
   while (nthreads_ != 0) {
@@ -114,7 +105,7 @@
 }
 
 void DynamicThreadPool::Add(const std::function<void()>& callback) {
-  grpc::lock_guard<grpc::mutex> lock(mu_);
+  std::lock_guard<std::mutex> lock(mu_);
   // Add works to the callbacks list
   callbacks_.push(callback);
   // Increase pool size or notify as needed
diff --git a/third_party/grpc/src/cpp/server/dynamic_thread_pool.h b/third_party/grpc/src/cpp/server/dynamic_thread_pool.h
index 5ba7533..5df8cf2 100644
--- a/third_party/grpc/src/cpp/server/dynamic_thread_pool.h
+++ b/third_party/grpc/src/cpp/server/dynamic_thread_pool.h
@@ -1,57 +1,43 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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 GRPC_INTERNAL_CPP_DYNAMIC_THREAD_POOL_H
 #define GRPC_INTERNAL_CPP_DYNAMIC_THREAD_POOL_H
 
+#include <condition_variable>
 #include <list>
 #include <memory>
+#include <mutex>
 #include <queue>
 
-#include <grpc++/impl/sync.h>
-#include <grpc++/impl/thd.h>
-#include <grpc++/support/config.h>
+#include <grpcpp/support/config.h>
 
+#include "src/core/lib/gprpp/thd.h"
 #include "src/cpp/server/thread_pool_interface.h"
 
 namespace grpc {
 
-class DynamicThreadPool GRPC_FINAL : public ThreadPoolInterface {
+class DynamicThreadPool final : public ThreadPoolInterface {
  public:
   explicit DynamicThreadPool(int reserve_threads);
   ~DynamicThreadPool();
 
-  void Add(const std::function<void()>& callback) GRPC_OVERRIDE;
+  void Add(const std::function<void()>& callback) override;
 
  private:
   class DynamicThread {
@@ -61,12 +47,12 @@
 
    private:
     DynamicThreadPool* pool_;
-    std::unique_ptr<grpc::thread> thd_;
+    grpc_core::Thread thd_;
     void ThreadFunc();
   };
-  grpc::mutex mu_;
-  grpc::condition_variable cv_;
-  grpc::condition_variable shutdown_cv_;
+  std::mutex mu_;
+  std::condition_variable cv_;
+  std::condition_variable shutdown_cv_;
   bool shutdown_;
   std::queue<std::function<void()>> callbacks_;
   int reserve_threads_;
diff --git a/third_party/grpc/src/cpp/server/fixed_size_thread_pool.cc b/third_party/grpc/src/cpp/server/fixed_size_thread_pool.cc
deleted file mode 100644
index 2bdc44b..0000000
--- a/third_party/grpc/src/cpp/server/fixed_size_thread_pool.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/impl/sync.h>
-#include <grpc++/impl/thd.h>
-#include "src/cpp/server/fixed_size_thread_pool.h"
-
-namespace grpc {
-
-void FixedSizeThreadPool::ThreadFunc() {
-  for (;;) {
-    // Wait until work is available or we are shutting down.
-    grpc::unique_lock<grpc::mutex> lock(mu_);
-    if (!shutdown_ && callbacks_.empty()) {
-      cv_.wait(lock);
-    }
-    // Drain callbacks before considering shutdown to ensure all work
-    // gets completed.
-    if (!callbacks_.empty()) {
-      auto cb = callbacks_.front();
-      callbacks_.pop();
-      lock.unlock();
-      cb();
-    } else if (shutdown_) {
-      return;
-    }
-  }
-}
-
-FixedSizeThreadPool::FixedSizeThreadPool(int num_threads) : shutdown_(false) {
-  for (int i = 0; i < num_threads; i++) {
-    threads_.push_back(
-        new grpc::thread(&FixedSizeThreadPool::ThreadFunc, this));
-  }
-}
-
-FixedSizeThreadPool::~FixedSizeThreadPool() {
-  {
-    grpc::lock_guard<grpc::mutex> lock(mu_);
-    shutdown_ = true;
-    cv_.notify_all();
-  }
-  for (auto t = threads_.begin(); t != threads_.end(); t++) {
-    (*t)->join();
-    delete *t;
-  }
-}
-
-void FixedSizeThreadPool::Add(const std::function<void()>& callback) {
-  grpc::lock_guard<grpc::mutex> lock(mu_);
-  callbacks_.push(callback);
-  cv_.notify_one();
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/fixed_size_thread_pool.h b/third_party/grpc/src/cpp/server/fixed_size_thread_pool.h
deleted file mode 100644
index 394ae58..0000000
--- a/third_party/grpc/src/cpp/server/fixed_size_thread_pool.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#ifndef GRPC_INTERNAL_CPP_FIXED_SIZE_THREAD_POOL_H
-#define GRPC_INTERNAL_CPP_FIXED_SIZE_THREAD_POOL_H
-
-#include <queue>
-#include <vector>
-
-#include <grpc++/impl/sync.h>
-#include <grpc++/impl/thd.h>
-#include <grpc++/support/config.h>
-
-#include "src/cpp/server/thread_pool_interface.h"
-
-namespace grpc {
-
-class FixedSizeThreadPool GRPC_FINAL : public ThreadPoolInterface {
- public:
-  explicit FixedSizeThreadPool(int num_threads);
-  ~FixedSizeThreadPool();
-
-  void Add(const std::function<void()>& callback) GRPC_OVERRIDE;
-
- private:
-  grpc::mutex mu_;
-  grpc::condition_variable cv_;
-  bool shutdown_;
-  std::queue<std::function<void()>> callbacks_;
-  std::vector<grpc::thread*> threads_;
-
-  void ThreadFunc();
-};
-
-}  // namespace grpc
-
-#endif  // GRPC_INTERNAL_CPP_FIXED_SIZE_THREAD_POOL_H
diff --git a/third_party/grpc/src/cpp/server/health/default_health_check_service.cc b/third_party/grpc/src/cpp/server/health/default_health_check_service.cc
new file mode 100644
index 0000000..44aebd2
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/health/default_health_check_service.cc
@@ -0,0 +1,499 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <memory>
+#include <mutex>
+
+#include <grpc/slice.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/method_handler_impl.h>
+
+#include "pb_decode.h"
+#include "pb_encode.h"
+#include "src/core/ext/filters/client_channel/health/health.pb.h"
+#include "src/cpp/server/health/default_health_check_service.h"
+
+namespace grpc {
+
+//
+// DefaultHealthCheckService
+//
+
+DefaultHealthCheckService::DefaultHealthCheckService() {
+  services_map_[""].SetServingStatus(SERVING);
+}
+
+void DefaultHealthCheckService::SetServingStatus(
+    const grpc::string& service_name, bool serving) {
+  std::unique_lock<std::mutex> lock(mu_);
+  if (shutdown_) {
+    // Set to NOT_SERVING in case service_name is not in the map.
+    serving = false;
+  }
+  services_map_[service_name].SetServingStatus(serving ? SERVING : NOT_SERVING);
+}
+
+void DefaultHealthCheckService::SetServingStatus(bool serving) {
+  const ServingStatus status = serving ? SERVING : NOT_SERVING;
+  std::unique_lock<std::mutex> lock(mu_);
+  if (shutdown_) {
+    return;
+  }
+  for (auto& p : services_map_) {
+    ServiceData& service_data = p.second;
+    service_data.SetServingStatus(status);
+  }
+}
+
+void DefaultHealthCheckService::Shutdown() {
+  std::unique_lock<std::mutex> lock(mu_);
+  if (shutdown_) {
+    return;
+  }
+  shutdown_ = true;
+  for (auto& p : services_map_) {
+    ServiceData& service_data = p.second;
+    service_data.SetServingStatus(NOT_SERVING);
+  }
+}
+
+DefaultHealthCheckService::ServingStatus
+DefaultHealthCheckService::GetServingStatus(
+    const grpc::string& service_name) const {
+  std::lock_guard<std::mutex> lock(mu_);
+  auto it = services_map_.find(service_name);
+  if (it == services_map_.end()) {
+    return NOT_FOUND;
+  }
+  const ServiceData& service_data = it->second;
+  return service_data.GetServingStatus();
+}
+
+void DefaultHealthCheckService::RegisterCallHandler(
+    const grpc::string& service_name,
+    std::shared_ptr<HealthCheckServiceImpl::CallHandler> handler) {
+  std::unique_lock<std::mutex> lock(mu_);
+  ServiceData& service_data = services_map_[service_name];
+  service_data.AddCallHandler(handler /* copies ref */);
+  HealthCheckServiceImpl::CallHandler* h = handler.get();
+  h->SendHealth(std::move(handler), service_data.GetServingStatus());
+}
+
+void DefaultHealthCheckService::UnregisterCallHandler(
+    const grpc::string& service_name,
+    const std::shared_ptr<HealthCheckServiceImpl::CallHandler>& handler) {
+  std::unique_lock<std::mutex> lock(mu_);
+  auto it = services_map_.find(service_name);
+  if (it == services_map_.end()) return;
+  ServiceData& service_data = it->second;
+  service_data.RemoveCallHandler(handler);
+  if (service_data.Unused()) {
+    services_map_.erase(it);
+  }
+}
+
+DefaultHealthCheckService::HealthCheckServiceImpl*
+DefaultHealthCheckService::GetHealthCheckService(
+    std::unique_ptr<ServerCompletionQueue> cq) {
+  GPR_ASSERT(impl_ == nullptr);
+  impl_.reset(new HealthCheckServiceImpl(this, std::move(cq)));
+  return impl_.get();
+}
+
+//
+// DefaultHealthCheckService::ServiceData
+//
+
+void DefaultHealthCheckService::ServiceData::SetServingStatus(
+    ServingStatus status) {
+  status_ = status;
+  for (auto& call_handler : call_handlers_) {
+    call_handler->SendHealth(call_handler /* copies ref */, status);
+  }
+}
+
+void DefaultHealthCheckService::ServiceData::AddCallHandler(
+    std::shared_ptr<HealthCheckServiceImpl::CallHandler> handler) {
+  call_handlers_.insert(std::move(handler));
+}
+
+void DefaultHealthCheckService::ServiceData::RemoveCallHandler(
+    const std::shared_ptr<HealthCheckServiceImpl::CallHandler>& handler) {
+  call_handlers_.erase(handler);
+}
+
+//
+// DefaultHealthCheckService::HealthCheckServiceImpl
+//
+
+namespace {
+const char kHealthCheckMethodName[] = "/grpc.health.v1.Health/Check";
+const char kHealthWatchMethodName[] = "/grpc.health.v1.Health/Watch";
+}  // namespace
+
+DefaultHealthCheckService::HealthCheckServiceImpl::HealthCheckServiceImpl(
+    DefaultHealthCheckService* database,
+    std::unique_ptr<ServerCompletionQueue> cq)
+    : database_(database), cq_(std::move(cq)) {
+  // Add Check() method.
+  AddMethod(new internal::RpcServiceMethod(
+      kHealthCheckMethodName, internal::RpcMethod::NORMAL_RPC, nullptr));
+  // Add Watch() method.
+  AddMethod(new internal::RpcServiceMethod(
+      kHealthWatchMethodName, internal::RpcMethod::SERVER_STREAMING, nullptr));
+  // Create serving thread.
+  thread_ = std::unique_ptr<::grpc_core::Thread>(
+      new ::grpc_core::Thread("grpc_health_check_service", Serve, this));
+}
+
+DefaultHealthCheckService::HealthCheckServiceImpl::~HealthCheckServiceImpl() {
+  // We will reach here after the server starts shutting down.
+  shutdown_ = true;
+  {
+    std::unique_lock<std::mutex> lock(cq_shutdown_mu_);
+    cq_->Shutdown();
+  }
+  thread_->Join();
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::StartServingThread() {
+  // Request the calls we're interested in.
+  // We do this before starting the serving thread, so that we know it's
+  // done before server startup is complete.
+  CheckCallHandler::CreateAndStart(cq_.get(), database_, this);
+  WatchCallHandler::CreateAndStart(cq_.get(), database_, this);
+  // Start serving thread.
+  thread_->Start();
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::Serve(void* arg) {
+  HealthCheckServiceImpl* service =
+      reinterpret_cast<HealthCheckServiceImpl*>(arg);
+  void* tag;
+  bool ok;
+  while (true) {
+    if (!service->cq_->Next(&tag, &ok)) {
+      // The completion queue is shutting down.
+      GPR_ASSERT(service->shutdown_);
+      break;
+    }
+    auto* next_step = static_cast<CallableTag*>(tag);
+    next_step->Run(ok);
+  }
+}
+
+bool DefaultHealthCheckService::HealthCheckServiceImpl::DecodeRequest(
+    const ByteBuffer& request, grpc::string* service_name) {
+  std::vector<Slice> slices;
+  if (!request.Dump(&slices).ok()) return false;
+  uint8_t* request_bytes = nullptr;
+  size_t request_size = 0;
+  grpc_health_v1_HealthCheckRequest request_struct;
+  request_struct.has_service = false;
+  if (slices.size() == 1) {
+    request_bytes = const_cast<uint8_t*>(slices[0].begin());
+    request_size = slices[0].size();
+  } else if (slices.size() > 1) {
+    request_bytes = static_cast<uint8_t*>(gpr_malloc(request.Length()));
+    uint8_t* copy_to = request_bytes;
+    for (size_t i = 0; i < slices.size(); i++) {
+      memcpy(copy_to, slices[i].begin(), slices[i].size());
+      copy_to += slices[i].size();
+    }
+  }
+  pb_istream_t istream = pb_istream_from_buffer(request_bytes, request_size);
+  bool decode_status = pb_decode(
+      &istream, grpc_health_v1_HealthCheckRequest_fields, &request_struct);
+  if (slices.size() > 1) {
+    gpr_free(request_bytes);
+  }
+  if (!decode_status) return false;
+  *service_name = request_struct.has_service ? request_struct.service : "";
+  return true;
+}
+
+bool DefaultHealthCheckService::HealthCheckServiceImpl::EncodeResponse(
+    ServingStatus status, ByteBuffer* response) {
+  grpc_health_v1_HealthCheckResponse response_struct;
+  response_struct.has_status = true;
+  response_struct.status =
+      status == NOT_FOUND
+          ? grpc_health_v1_HealthCheckResponse_ServingStatus_SERVICE_UNKNOWN
+          : status == SERVING
+                ? grpc_health_v1_HealthCheckResponse_ServingStatus_SERVING
+                : grpc_health_v1_HealthCheckResponse_ServingStatus_NOT_SERVING;
+  pb_ostream_t ostream;
+  memset(&ostream, 0, sizeof(ostream));
+  pb_encode(&ostream, grpc_health_v1_HealthCheckResponse_fields,
+            &response_struct);
+  grpc_slice response_slice = grpc_slice_malloc(ostream.bytes_written);
+  ostream = pb_ostream_from_buffer(GRPC_SLICE_START_PTR(response_slice),
+                                   GRPC_SLICE_LENGTH(response_slice));
+  bool encode_status = pb_encode(
+      &ostream, grpc_health_v1_HealthCheckResponse_fields, &response_struct);
+  if (!encode_status) return false;
+  Slice encoded_response(response_slice, Slice::STEAL_REF);
+  ByteBuffer response_buffer(&encoded_response, 1);
+  response->Swap(&response_buffer);
+  return true;
+}
+
+//
+// DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler
+//
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler::
+    CreateAndStart(ServerCompletionQueue* cq,
+                   DefaultHealthCheckService* database,
+                   HealthCheckServiceImpl* service) {
+  std::shared_ptr<CallHandler> self =
+      std::make_shared<CheckCallHandler>(cq, database, service);
+  CheckCallHandler* handler = static_cast<CheckCallHandler*>(self.get());
+  {
+    std::unique_lock<std::mutex> lock(service->cq_shutdown_mu_);
+    if (service->shutdown_) return;
+    // Request a Check() call.
+    handler->next_ =
+        CallableTag(std::bind(&CheckCallHandler::OnCallReceived, handler,
+                              std::placeholders::_1, std::placeholders::_2),
+                    std::move(self));
+    service->RequestAsyncUnary(0, &handler->ctx_, &handler->request_,
+                               &handler->writer_, cq, cq, &handler->next_);
+  }
+}
+
+DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler::
+    CheckCallHandler(ServerCompletionQueue* cq,
+                     DefaultHealthCheckService* database,
+                     HealthCheckServiceImpl* service)
+    : cq_(cq), database_(database), service_(service), writer_(&ctx_) {}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler::
+    OnCallReceived(std::shared_ptr<CallHandler> self, bool ok) {
+  if (!ok) {
+    // The value of ok being false means that the server is shutting down.
+    return;
+  }
+  // Spawn a new handler instance to serve the next new client. Every handler
+  // instance will deallocate itself when it's done.
+  CreateAndStart(cq_, database_, service_);
+  // Process request.
+  gpr_log(GPR_DEBUG, "[HCS %p] Health check started for handler %p", service_,
+          this);
+  grpc::string service_name;
+  grpc::Status status = Status::OK;
+  ByteBuffer response;
+  if (!service_->DecodeRequest(request_, &service_name)) {
+    status = Status(StatusCode::INVALID_ARGUMENT, "could not parse request");
+  } else {
+    ServingStatus serving_status = database_->GetServingStatus(service_name);
+    if (serving_status == NOT_FOUND) {
+      status = Status(StatusCode::NOT_FOUND, "service name unknown");
+    } else if (!service_->EncodeResponse(serving_status, &response)) {
+      status = Status(StatusCode::INTERNAL, "could not encode response");
+    }
+  }
+  // Send response.
+  {
+    std::unique_lock<std::mutex> lock(service_->cq_shutdown_mu_);
+    if (!service_->shutdown_) {
+      next_ =
+          CallableTag(std::bind(&CheckCallHandler::OnFinishDone, this,
+                                std::placeholders::_1, std::placeholders::_2),
+                      std::move(self));
+      if (status.ok()) {
+        writer_.Finish(response, status, &next_);
+      } else {
+        writer_.FinishWithError(status, &next_);
+      }
+    }
+  }
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::CheckCallHandler::
+    OnFinishDone(std::shared_ptr<CallHandler> self, bool ok) {
+  if (ok) {
+    gpr_log(GPR_DEBUG, "[HCS %p] Health check call finished for handler %p",
+            service_, this);
+  }
+  self.reset();  // To appease clang-tidy.
+}
+
+//
+// DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler
+//
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    CreateAndStart(ServerCompletionQueue* cq,
+                   DefaultHealthCheckService* database,
+                   HealthCheckServiceImpl* service) {
+  std::shared_ptr<CallHandler> self =
+      std::make_shared<WatchCallHandler>(cq, database, service);
+  WatchCallHandler* handler = static_cast<WatchCallHandler*>(self.get());
+  {
+    std::unique_lock<std::mutex> lock(service->cq_shutdown_mu_);
+    if (service->shutdown_) return;
+    // Request AsyncNotifyWhenDone().
+    handler->on_done_notified_ =
+        CallableTag(std::bind(&WatchCallHandler::OnDoneNotified, handler,
+                              std::placeholders::_1, std::placeholders::_2),
+                    self /* copies ref */);
+    handler->ctx_.AsyncNotifyWhenDone(&handler->on_done_notified_);
+    // Request a Watch() call.
+    handler->next_ =
+        CallableTag(std::bind(&WatchCallHandler::OnCallReceived, handler,
+                              std::placeholders::_1, std::placeholders::_2),
+                    std::move(self));
+    service->RequestAsyncServerStreaming(1, &handler->ctx_, &handler->request_,
+                                         &handler->stream_, cq, cq,
+                                         &handler->next_);
+  }
+}
+
+DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    WatchCallHandler(ServerCompletionQueue* cq,
+                     DefaultHealthCheckService* database,
+                     HealthCheckServiceImpl* service)
+    : cq_(cq), database_(database), service_(service), stream_(&ctx_) {}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    OnCallReceived(std::shared_ptr<CallHandler> self, bool ok) {
+  if (!ok) {
+    // Server shutting down.
+    //
+    // AsyncNotifyWhenDone() needs to be called before the call starts, but the
+    // tag will not pop out if the call never starts (
+    // https://github.com/grpc/grpc/issues/10136). So we need to manually
+    // release the ownership of the handler in this case.
+    GPR_ASSERT(on_done_notified_.ReleaseHandler() != nullptr);
+    return;
+  }
+  // Spawn a new handler instance to serve the next new client. Every handler
+  // instance will deallocate itself when it's done.
+  CreateAndStart(cq_, database_, service_);
+  // Parse request.
+  if (!service_->DecodeRequest(request_, &service_name_)) {
+    SendFinish(std::move(self),
+               Status(StatusCode::INVALID_ARGUMENT, "could not parse request"));
+    return;
+  }
+  // Register the call for updates to the service.
+  gpr_log(GPR_DEBUG,
+          "[HCS %p] Health watch started for service \"%s\" (handler: %p)",
+          service_, service_name_.c_str(), this);
+  database_->RegisterCallHandler(service_name_, std::move(self));
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    SendHealth(std::shared_ptr<CallHandler> self, ServingStatus status) {
+  std::unique_lock<std::mutex> lock(send_mu_);
+  // If there's already a send in flight, cache the new status, and
+  // we'll start a new send for it when the one in flight completes.
+  if (send_in_flight_) {
+    pending_status_ = status;
+    return;
+  }
+  // Start a send.
+  SendHealthLocked(std::move(self), status);
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    SendHealthLocked(std::shared_ptr<CallHandler> self, ServingStatus status) {
+  send_in_flight_ = true;
+  // Construct response.
+  ByteBuffer response;
+  bool success = service_->EncodeResponse(status, &response);
+  // Grab shutdown lock and send response.
+  std::unique_lock<std::mutex> cq_lock(service_->cq_shutdown_mu_);
+  if (service_->shutdown_) {
+    SendFinishLocked(std::move(self), Status::CANCELLED);
+    return;
+  }
+  if (!success) {
+    SendFinishLocked(std::move(self),
+                     Status(StatusCode::INTERNAL, "could not encode response"));
+    return;
+  }
+  next_ = CallableTag(std::bind(&WatchCallHandler::OnSendHealthDone, this,
+                                std::placeholders::_1, std::placeholders::_2),
+                      std::move(self));
+  stream_.Write(response, &next_);
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    OnSendHealthDone(std::shared_ptr<CallHandler> self, bool ok) {
+  if (!ok) {
+    SendFinish(std::move(self), Status::CANCELLED);
+    return;
+  }
+  std::unique_lock<std::mutex> lock(send_mu_);
+  send_in_flight_ = false;
+  // If we got a new status since we started the last send, start a
+  // new send for it.
+  if (pending_status_ != NOT_FOUND) {
+    auto status = pending_status_;
+    pending_status_ = NOT_FOUND;
+    SendHealthLocked(std::move(self), status);
+  }
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    SendFinish(std::shared_ptr<CallHandler> self, const Status& status) {
+  if (finish_called_) return;
+  std::unique_lock<std::mutex> cq_lock(service_->cq_shutdown_mu_);
+  if (service_->shutdown_) return;
+  SendFinishLocked(std::move(self), status);
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    SendFinishLocked(std::shared_ptr<CallHandler> self, const Status& status) {
+  on_finish_done_ =
+      CallableTag(std::bind(&WatchCallHandler::OnFinishDone, this,
+                            std::placeholders::_1, std::placeholders::_2),
+                  std::move(self));
+  stream_.Finish(status, &on_finish_done_);
+  finish_called_ = true;
+}
+
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    OnFinishDone(std::shared_ptr<CallHandler> self, bool ok) {
+  if (ok) {
+    gpr_log(GPR_DEBUG,
+            "[HCS %p] Health watch call finished (service_name: \"%s\", "
+            "handler: %p).",
+            service_, service_name_.c_str(), this);
+  }
+  self.reset();  // To appease clang-tidy.
+}
+
+// TODO(roth): This method currently assumes that there will be only one
+// thread polling the cq and invoking the corresponding callbacks.  If
+// that changes, we will need to add synchronization here.
+void DefaultHealthCheckService::HealthCheckServiceImpl::WatchCallHandler::
+    OnDoneNotified(std::shared_ptr<CallHandler> self, bool ok) {
+  GPR_ASSERT(ok);
+  gpr_log(GPR_DEBUG,
+          "[HCS %p] Health watch call is notified done (handler: %p, "
+          "is_cancelled: %d).",
+          service_, this, static_cast<int>(ctx_.IsCancelled()));
+  database_->UnregisterCallHandler(service_name_, self);
+  SendFinish(std::move(self), Status::CANCELLED);
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/health/default_health_check_service.h b/third_party/grpc/src/cpp/server/health/default_health_check_service.h
new file mode 100644
index 0000000..9551cd2
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/health/default_health_check_service.h
@@ -0,0 +1,284 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
+#define GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
+
+#include <atomic>
+#include <mutex>
+#include <set>
+
+#include <grpc/support/log.h>
+#include <grpcpp/grpcpp.h>
+#include <grpcpp/health_check_service_interface.h>
+#include <grpcpp/impl/codegen/async_generic_service.h>
+#include <grpcpp/impl/codegen/async_unary_call.h>
+#include <grpcpp/impl/codegen/service_type.h>
+#include <grpcpp/support/byte_buffer.h>
+
+#include "src/core/lib/gprpp/thd.h"
+
+namespace grpc {
+
+// Default implementation of HealthCheckServiceInterface. Server will create and
+// own it.
+class DefaultHealthCheckService final : public HealthCheckServiceInterface {
+ public:
+  enum ServingStatus { NOT_FOUND, SERVING, NOT_SERVING };
+
+  // The service impl to register with the server.
+  class HealthCheckServiceImpl : public Service {
+   public:
+    // Base class for call handlers.
+    class CallHandler {
+     public:
+      virtual ~CallHandler() = default;
+      virtual void SendHealth(std::shared_ptr<CallHandler> self,
+                              ServingStatus status) = 0;
+    };
+
+    HealthCheckServiceImpl(DefaultHealthCheckService* database,
+                           std::unique_ptr<ServerCompletionQueue> cq);
+
+    ~HealthCheckServiceImpl();
+
+    void StartServingThread();
+
+   private:
+    // A tag that can be called with a bool argument. It's tailored for
+    // CallHandler's use. Before being used, it should be constructed with a
+    // method of CallHandler and a shared pointer to the handler. The
+    // shared pointer will be moved to the invoked function and the function
+    // can only be invoked once. That makes ref counting of the handler easier,
+    // because the shared pointer is not bound to the function and can be gone
+    // once the invoked function returns (if not used any more).
+    class CallableTag {
+     public:
+      using HandlerFunction =
+          std::function<void(std::shared_ptr<CallHandler>, bool)>;
+
+      CallableTag() {}
+
+      CallableTag(HandlerFunction func, std::shared_ptr<CallHandler> handler)
+          : handler_function_(std::move(func)), handler_(std::move(handler)) {
+        GPR_ASSERT(handler_function_ != nullptr);
+        GPR_ASSERT(handler_ != nullptr);
+      }
+
+      // Runs the tag. This should be called only once. The handler is no
+      // longer owned by this tag after this method is invoked.
+      void Run(bool ok) {
+        GPR_ASSERT(handler_function_ != nullptr);
+        GPR_ASSERT(handler_ != nullptr);
+        handler_function_(std::move(handler_), ok);
+      }
+
+      // Releases and returns the shared pointer to the handler.
+      std::shared_ptr<CallHandler> ReleaseHandler() {
+        return std::move(handler_);
+      }
+
+     private:
+      HandlerFunction handler_function_ = nullptr;
+      std::shared_ptr<CallHandler> handler_;
+    };
+
+    // Call handler for Check method.
+    // Each handler takes care of one call. It contains per-call data and it
+    // will access the members of the parent class (i.e.,
+    // DefaultHealthCheckService) for per-service health data.
+    class CheckCallHandler : public CallHandler {
+     public:
+      // Instantiates a CheckCallHandler and requests the next health check
+      // call. The handler object will manage its own lifetime, so no action is
+      // needed from the caller any more regarding that object.
+      static void CreateAndStart(ServerCompletionQueue* cq,
+                                 DefaultHealthCheckService* database,
+                                 HealthCheckServiceImpl* service);
+
+      // This ctor is public because we want to use std::make_shared<> in
+      // CreateAndStart(). This ctor shouldn't be used elsewhere.
+      CheckCallHandler(ServerCompletionQueue* cq,
+                       DefaultHealthCheckService* database,
+                       HealthCheckServiceImpl* service);
+
+      // Not used for Check.
+      void SendHealth(std::shared_ptr<CallHandler> self,
+                      ServingStatus status) override {}
+
+     private:
+      // Called when we receive a call.
+      // Spawns a new handler so that we can keep servicing future calls.
+      void OnCallReceived(std::shared_ptr<CallHandler> self, bool ok);
+
+      // Called when Finish() is done.
+      void OnFinishDone(std::shared_ptr<CallHandler> self, bool ok);
+
+      // The members passed down from HealthCheckServiceImpl.
+      ServerCompletionQueue* cq_;
+      DefaultHealthCheckService* database_;
+      HealthCheckServiceImpl* service_;
+
+      ByteBuffer request_;
+      GenericServerAsyncResponseWriter writer_;
+      ServerContext ctx_;
+
+      CallableTag next_;
+    };
+
+    // Call handler for Watch method.
+    // Each handler takes care of one call. It contains per-call data and it
+    // will access the members of the parent class (i.e.,
+    // DefaultHealthCheckService) for per-service health data.
+    class WatchCallHandler : public CallHandler {
+     public:
+      // Instantiates a WatchCallHandler and requests the next health check
+      // call. The handler object will manage its own lifetime, so no action is
+      // needed from the caller any more regarding that object.
+      static void CreateAndStart(ServerCompletionQueue* cq,
+                                 DefaultHealthCheckService* database,
+                                 HealthCheckServiceImpl* service);
+
+      // This ctor is public because we want to use std::make_shared<> in
+      // CreateAndStart(). This ctor shouldn't be used elsewhere.
+      WatchCallHandler(ServerCompletionQueue* cq,
+                       DefaultHealthCheckService* database,
+                       HealthCheckServiceImpl* service);
+
+      void SendHealth(std::shared_ptr<CallHandler> self,
+                      ServingStatus status) override;
+
+     private:
+      // Called when we receive a call.
+      // Spawns a new handler so that we can keep servicing future calls.
+      void OnCallReceived(std::shared_ptr<CallHandler> self, bool ok);
+
+      // Requires holding send_mu_.
+      void SendHealthLocked(std::shared_ptr<CallHandler> self,
+                            ServingStatus status);
+
+      // When sending a health result finishes.
+      void OnSendHealthDone(std::shared_ptr<CallHandler> self, bool ok);
+
+      void SendFinish(std::shared_ptr<CallHandler> self, const Status& status);
+
+      // Requires holding service_->cq_shutdown_mu_.
+      void SendFinishLocked(std::shared_ptr<CallHandler> self,
+                            const Status& status);
+
+      // Called when Finish() is done.
+      void OnFinishDone(std::shared_ptr<CallHandler> self, bool ok);
+
+      // Called when AsyncNotifyWhenDone() notifies us.
+      void OnDoneNotified(std::shared_ptr<CallHandler> self, bool ok);
+
+      // The members passed down from HealthCheckServiceImpl.
+      ServerCompletionQueue* cq_;
+      DefaultHealthCheckService* database_;
+      HealthCheckServiceImpl* service_;
+
+      ByteBuffer request_;
+      grpc::string service_name_;
+      GenericServerAsyncWriter stream_;
+      ServerContext ctx_;
+
+      std::mutex send_mu_;
+      bool send_in_flight_ = false;               // Guarded by mu_.
+      ServingStatus pending_status_ = NOT_FOUND;  // Guarded by mu_.
+
+      bool finish_called_ = false;
+      CallableTag next_;
+      CallableTag on_done_notified_;
+      CallableTag on_finish_done_;
+    };
+
+    // Handles the incoming requests and drives the completion queue in a loop.
+    static void Serve(void* arg);
+
+    // Returns true on success.
+    static bool DecodeRequest(const ByteBuffer& request,
+                              grpc::string* service_name);
+    static bool EncodeResponse(ServingStatus status, ByteBuffer* response);
+
+    // Needed to appease Windows compilers, which don't seem to allow
+    // nested classes to access protected members in the parent's
+    // superclass.
+    using Service::RequestAsyncServerStreaming;
+    using Service::RequestAsyncUnary;
+
+    DefaultHealthCheckService* database_;
+    std::unique_ptr<ServerCompletionQueue> cq_;
+
+    // To synchronize the operations related to shutdown state of cq_, so that
+    // we don't enqueue new tags into cq_ after it is already shut down.
+    std::mutex cq_shutdown_mu_;
+    std::atomic_bool shutdown_{false};
+    std::unique_ptr<::grpc_core::Thread> thread_;
+  };
+
+  DefaultHealthCheckService();
+
+  void SetServingStatus(const grpc::string& service_name,
+                        bool serving) override;
+  void SetServingStatus(bool serving) override;
+
+  void Shutdown() override;
+
+  ServingStatus GetServingStatus(const grpc::string& service_name) const;
+
+  HealthCheckServiceImpl* GetHealthCheckService(
+      std::unique_ptr<ServerCompletionQueue> cq);
+
+ private:
+  // Stores the current serving status of a service and any call
+  // handlers registered for updates when the service's status changes.
+  class ServiceData {
+   public:
+    void SetServingStatus(ServingStatus status);
+    ServingStatus GetServingStatus() const { return status_; }
+    void AddCallHandler(
+        std::shared_ptr<HealthCheckServiceImpl::CallHandler> handler);
+    void RemoveCallHandler(
+        const std::shared_ptr<HealthCheckServiceImpl::CallHandler>& handler);
+    bool Unused() const {
+      return call_handlers_.empty() && status_ == NOT_FOUND;
+    }
+
+   private:
+    ServingStatus status_ = NOT_FOUND;
+    std::set<std::shared_ptr<HealthCheckServiceImpl::CallHandler>>
+        call_handlers_;
+  };
+
+  void RegisterCallHandler(
+      const grpc::string& service_name,
+      std::shared_ptr<HealthCheckServiceImpl::CallHandler> handler);
+
+  void UnregisterCallHandler(
+      const grpc::string& service_name,
+      const std::shared_ptr<HealthCheckServiceImpl::CallHandler>& handler);
+
+  mutable std::mutex mu_;
+  bool shutdown_ = false;                             // Guarded by mu_.
+  std::map<grpc::string, ServiceData> services_map_;  // Guarded by mu_.
+  std::unique_ptr<HealthCheckServiceImpl> impl_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPC_INTERNAL_CPP_SERVER_DEFAULT_HEALTH_CHECK_SERVICE_H
diff --git a/third_party/grpc/src/cpp/server/health/health_check_service.cc b/third_party/grpc/src/cpp/server/health/health_check_service.cc
new file mode 100644
index 0000000..a0fa2d6
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/health/health_check_service.cc
@@ -0,0 +1,34 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/health_check_service_interface.h>
+
+namespace grpc {
+namespace {
+bool g_grpc_default_health_check_service_enabled = false;
+}  // namespace
+
+bool DefaultHealthCheckServiceEnabled() {
+  return g_grpc_default_health_check_service_enabled;
+}
+
+void EnableDefaultHealthCheckService(bool enable) {
+  g_grpc_default_health_check_service_enabled = enable;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/health/health_check_service_server_builder_option.cc b/third_party/grpc/src/cpp/server/health/health_check_service_server_builder_option.cc
new file mode 100644
index 0000000..7148265
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/health/health_check_service_server_builder_option.cc
@@ -0,0 +1,35 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/ext/health_check_service_server_builder_option.h>
+
+namespace grpc {
+
+HealthCheckServiceServerBuilderOption::HealthCheckServiceServerBuilderOption(
+    std::unique_ptr<HealthCheckServiceInterface> hc)
+    : hc_(std::move(hc)) {}
+// Hand over hc_ to the server.
+void HealthCheckServiceServerBuilderOption::UpdateArguments(
+    ChannelArguments* args) {
+  args->SetPointer(kHealthCheckServiceInterfaceArg, hc_.release());
+}
+
+void HealthCheckServiceServerBuilderOption::UpdatePlugins(
+    std::vector<std::unique_ptr<ServerBuilderPlugin>>* plugins) {}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/insecure_server_credentials.cc b/third_party/grpc/src/cpp/server/insecure_server_credentials.cc
index ef3cae5..7d749dd 100644
--- a/third_party/grpc/src/cpp/server/insecure_server_credentials.cc
+++ b/third_party/grpc/src/cpp/server/insecure_server_credentials.cc
@@ -1,51 +1,35 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/security/server_credentials.h>
+#include <grpcpp/security/server_credentials.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
 
 namespace grpc {
 namespace {
-class InsecureServerCredentialsImpl GRPC_FINAL : public ServerCredentials {
+class InsecureServerCredentialsImpl final : public ServerCredentials {
  public:
-  int AddPortToServer(const grpc::string& addr,
-                      grpc_server* server) GRPC_OVERRIDE {
+  int AddPortToServer(const grpc::string& addr, grpc_server* server) override {
     return grpc_server_add_insecure_http2_port(server, addr.c_str());
   }
   void SetAuthMetadataProcessor(
-      const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE {
+      const std::shared_ptr<AuthMetadataProcessor>& processor) override {
     (void)processor;
     GPR_ASSERT(0);  // Should not be called on InsecureServerCredentials.
   }
diff --git a/third_party/grpc/src/cpp/server/load_reporter/constants.h b/third_party/grpc/src/cpp/server/load_reporter/constants.h
new file mode 100644
index 0000000..00ad794
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/constants.h
@@ -0,0 +1,81 @@
+/*
+ *
+ * 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 GRPC_SRC_CPP_SERVER_LOAD_REPORTER_UTIL_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_UTIL_H
+
+#include <grpc/impl/codegen/port_platform.h>
+
+namespace grpc {
+namespace load_reporter {
+
+// TODO(juanlishen): Update the version number with the PR number every time
+// there is any change to the server load reporter.
+constexpr uint32_t kVersion = 15853;
+
+// TODO(juanlishen): This window size is from the internal spec for the load
+// reporter. Need to ask the gRPC LB team whether we should make this and the
+// fetching interval configurable.
+constexpr uint32_t kFeedbackSampleWindowSeconds = 10;
+constexpr uint32_t kFetchAndSampleIntervalSeconds = 1;
+
+constexpr size_t kLbIdLength = 8;
+constexpr size_t kIpv4AddressLength = 8;
+constexpr size_t kIpv6AddressLength = 32;
+
+constexpr char kInvalidLbId[] = "<INVALID_LBID_238dsb234890rb>";
+
+// Call statuses.
+
+constexpr char kCallStatusOk[] = "OK";
+constexpr char kCallStatusServerError[] = "5XX";
+constexpr char kCallStatusClientError[] = "4XX";
+
+// Tag keys.
+
+constexpr char kTagKeyToken[] = "token";
+constexpr char kTagKeyHost[] = "host";
+constexpr char kTagKeyUserId[] = "user_id";
+constexpr char kTagKeyStatus[] = "status";
+constexpr char kTagKeyMetricName[] = "metric_name";
+
+// Measure names.
+
+constexpr char kMeasureStartCount[] = "grpc.io/lb/start_count";
+constexpr char kMeasureEndCount[] = "grpc.io/lb/end_count";
+constexpr char kMeasureEndBytesSent[] = "grpc.io/lb/bytes_sent";
+constexpr char kMeasureEndBytesReceived[] = "grpc.io/lb/bytes_received";
+constexpr char kMeasureEndLatencyMs[] = "grpc.io/lb/latency_ms";
+constexpr char kMeasureOtherCallMetric[] = "grpc.io/lb/other_call_metric";
+
+// View names.
+
+constexpr char kViewStartCount[] = "grpc.io/lb_view/start_count";
+constexpr char kViewEndCount[] = "grpc.io/lb_view/end_count";
+constexpr char kViewEndBytesSent[] = "grpc.io/lb_view/bytes_sent";
+constexpr char kViewEndBytesReceived[] = "grpc.io/lb_view/bytes_received";
+constexpr char kViewEndLatencyMs[] = "grpc.io/lb_view/latency_ms";
+constexpr char kViewOtherCallMetricCount[] =
+    "grpc.io/lb_view/other_call_metric_count";
+constexpr char kViewOtherCallMetricValue[] =
+    "grpc.io/lb_view/other_call_metric_value";
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_UTIL_H
diff --git a/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats.h b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats.h
new file mode 100644
index 0000000..f514b07
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats.h
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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 GRPC_SRC_CPP_SERVER_LOAD_REPORTER_GET_CPU_STATS_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_GET_CPU_STATS_H
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <utility>
+
+namespace grpc {
+namespace load_reporter {
+
+// Reads the CPU stats (in a pair of busy and total numbers) from the system.
+// The units of the stats should be the same.
+std::pair<uint64_t, uint64_t> GetCpuStatsImpl();
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_GET_CPU_STATS_H
diff --git a/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_linux.cc b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_linux.cc
new file mode 100644
index 0000000..9c1fd0c
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_linux.cc
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_LINUX
+
+#include <cstdio>
+
+#include "src/cpp/server/load_reporter/get_cpu_stats.h"
+
+namespace grpc {
+namespace load_reporter {
+
+std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
+  uint64_t busy = 0, total = 0;
+  FILE* fp;
+  fp = fopen("/proc/stat", "r");
+  uint64_t user, nice, system, idle;
+  fscanf(fp, "cpu %lu %lu %lu %lu", &user, &nice, &system, &idle);
+  fclose(fp);
+  busy = user + nice + system;
+  total = busy + idle;
+  return std::make_pair(busy, total);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GPR_LINUX
diff --git a/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_macos.cc b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_macos.cc
new file mode 100644
index 0000000..dbdde30
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_macos.cc
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_APPLE
+
+#include <mach/mach.h>
+
+#include "src/cpp/server/load_reporter/get_cpu_stats.h"
+
+namespace grpc {
+namespace load_reporter {
+
+std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
+  uint64_t busy = 0, total = 0;
+  host_cpu_load_info_data_t cpuinfo;
+  mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT;
+  if (host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO,
+                      (host_info_t)&cpuinfo, &count) == KERN_SUCCESS) {
+    for (int i = 0; i < CPU_STATE_MAX; i++) total += cpuinfo.cpu_ticks[i];
+    busy = total - cpuinfo.cpu_ticks[CPU_STATE_IDLE];
+  }
+  return std::make_pair(busy, total);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GPR_APPLE
diff --git a/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc
new file mode 100644
index 0000000..80fb8b6
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_unsupported.cc
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#if !defined(GPR_LINUX) && !defined(GPR_WINDOWS) && !defined(GPR_APPLE)
+
+#include <grpc/support/log.h>
+
+#include "src/cpp/server/load_reporter/get_cpu_stats.h"
+
+namespace grpc {
+namespace load_reporter {
+
+std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
+  uint64_t busy = 0, total = 0;
+  gpr_log(GPR_ERROR,
+          "Platforms other than Linux, Windows, and MacOS are not supported.");
+  return std::make_pair(busy, total);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // !defined(GPR_LINUX) && !defined(GPR_WINDOWS) && !defined(GPR_APPLE)
diff --git a/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_windows.cc b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_windows.cc
new file mode 100644
index 0000000..0a98e84
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/get_cpu_stats_windows.cc
@@ -0,0 +1,55 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#ifdef GPR_WINDOWS
+
+#include <windows.h>
+#include <cstdint>
+
+#include "src/cpp/server/load_reporter/get_cpu_stats.h"
+
+namespace grpc {
+namespace load_reporter {
+
+namespace {
+
+uint64_t FiletimeToInt(const FILETIME& ft) {
+  ULARGE_INTEGER i;
+  i.LowPart = ft.dwLowDateTime;
+  i.HighPart = ft.dwHighDateTime;
+  return i.QuadPart;
+}
+
+}  // namespace
+
+std::pair<uint64_t, uint64_t> GetCpuStatsImpl() {
+  uint64_t busy = 0, total = 0;
+  FILETIME idle, kernel, user;
+  if (GetSystemTimes(&idle, &kernel, &user) != 0) {
+    total = FiletimeToInt(kernel) + FiletimeToInt(user);
+    busy = total - FiletimeToInt(idle);
+  }
+  return std::make_pair(busy, total);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GPR_WINDOWS
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_data_store.cc b/third_party/grpc/src/cpp/server/load_reporter/load_data_store.cc
new file mode 100644
index 0000000..594473f
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_data_store.cc
@@ -0,0 +1,338 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <stdio.h>
+#include <cstdlib>
+#include <set>
+#include <unordered_map>
+#include <vector>
+
+#include "src/core/lib/iomgr/socket_utils.h"
+#include "src/cpp/server/load_reporter/load_data_store.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// Some helper functions.
+namespace {
+
+// Given a map from type K to a set of value type V, finds the set associated
+// with the given key and erases the value from the set. If the set becomes
+// empty, also erases the key-set pair. Returns true if the value is erased
+// successfully.
+template <typename K, typename V>
+bool UnorderedMapOfSetEraseKeyValue(std::unordered_map<K, std::set<V>>& map,
+                                    const K& key, const V& value) {
+  auto it = map.find(key);
+  if (it != map.end()) {
+    size_t erased = it->second.erase(value);
+    if (it->second.size() == 0) {
+      map.erase(it);
+    }
+    return erased;
+  }
+  return false;
+};
+
+// Given a map from type K to a set of value type V, removes the given key and
+// the associated set, and returns the set. Returns an empty set if the key is
+// not found.
+template <typename K, typename V>
+std::set<V> UnorderedMapOfSetExtract(std::unordered_map<K, std::set<V>>& map,
+                                     const K& key) {
+  auto it = map.find(key);
+  if (it != map.end()) {
+    auto set = std::move(it->second);
+    map.erase(it);
+    return set;
+  }
+  return {};
+};
+
+// From a non-empty container, returns a pointer to a random element.
+template <typename C>
+const typename C::value_type* RandomElement(const C& container) {
+  GPR_ASSERT(!container.empty());
+  auto it = container.begin();
+  std::advance(it, std::rand() % container.size());
+  return &(*it);
+}
+
+}  // namespace
+
+LoadRecordKey::LoadRecordKey(const grpc::string& client_ip_and_token,
+                             grpc::string user_id)
+    : user_id_(std::move(user_id)) {
+  GPR_ASSERT(client_ip_and_token.size() >= 2);
+  int ip_hex_size;
+  GPR_ASSERT(sscanf(client_ip_and_token.substr(0, 2).c_str(), "%d",
+                    &ip_hex_size) == 1);
+  GPR_ASSERT(ip_hex_size == 0 || ip_hex_size == kIpv4AddressLength ||
+             ip_hex_size == kIpv6AddressLength);
+  size_t cur_pos = 2;
+  client_ip_hex_ = client_ip_and_token.substr(cur_pos, ip_hex_size);
+  cur_pos += ip_hex_size;
+  if (client_ip_and_token.size() - cur_pos < kLbIdLength) {
+    lb_id_ = kInvalidLbId;
+    lb_tag_ = "";
+  } else {
+    lb_id_ = client_ip_and_token.substr(cur_pos, kLbIdLength);
+    lb_tag_ = client_ip_and_token.substr(cur_pos + kLbIdLength);
+  }
+}
+
+grpc::string LoadRecordKey::GetClientIpBytes() const {
+  if (client_ip_hex_.empty()) {
+    return "";
+  } else if (client_ip_hex_.size() == kIpv4AddressLength) {
+    uint32_t ip_bytes;
+    if (sscanf(client_ip_hex_.c_str(), "%x", &ip_bytes) != 1) {
+      gpr_log(GPR_ERROR,
+              "Can't parse client IP (%s) from a hex string to an integer.",
+              client_ip_hex_.c_str());
+      return "";
+    }
+    ip_bytes = grpc_htonl(ip_bytes);
+    return grpc::string(reinterpret_cast<const char*>(&ip_bytes),
+                        sizeof(ip_bytes));
+  } else if (client_ip_hex_.size() == kIpv6AddressLength) {
+    uint32_t ip_bytes[4];
+    for (size_t i = 0; i < 4; ++i) {
+      if (sscanf(client_ip_hex_.substr(i * 8, (i + 1) * 8).c_str(), "%x",
+                 ip_bytes + i) != 1) {
+        gpr_log(
+            GPR_ERROR,
+            "Can't parse client IP part (%s) from a hex string to an integer.",
+            client_ip_hex_.substr(i * 8, (i + 1) * 8).c_str());
+        return "";
+      }
+      ip_bytes[i] = grpc_htonl(ip_bytes[i]);
+    }
+    return grpc::string(reinterpret_cast<const char*>(ip_bytes),
+                        sizeof(ip_bytes));
+  } else {
+    GPR_UNREACHABLE_CODE(return "");
+  }
+}
+
+LoadRecordValue::LoadRecordValue(grpc::string metric_name, uint64_t num_calls,
+                                 double total_metric_value) {
+  call_metrics_.emplace(std::move(metric_name),
+                        CallMetricValue(num_calls, total_metric_value));
+}
+
+void PerBalancerStore::MergeRow(const LoadRecordKey& key,
+                                const LoadRecordValue& value) {
+  // During suspension, the load data received will be dropped.
+  if (!suspended_) {
+    load_record_map_[key].MergeFrom(value);
+    gpr_log(GPR_DEBUG,
+            "[PerBalancerStore %p] Load data merged (Key: %s, Value: %s).",
+            this, key.ToString().c_str(), value.ToString().c_str());
+  } else {
+    gpr_log(GPR_DEBUG,
+            "[PerBalancerStore %p] Load data dropped (Key: %s, Value: %s).",
+            this, key.ToString().c_str(), value.ToString().c_str());
+  }
+  // We always keep track of num_calls_in_progress_, so that when this
+  // store is resumed, we still have a correct value of
+  // num_calls_in_progress_.
+  GPR_ASSERT(static_cast<int64_t>(num_calls_in_progress_) +
+                 value.GetNumCallsInProgressDelta() >=
+             0);
+  num_calls_in_progress_ += value.GetNumCallsInProgressDelta();
+}
+
+void PerBalancerStore::Suspend() {
+  suspended_ = true;
+  load_record_map_.clear();
+  gpr_log(GPR_DEBUG, "[PerBalancerStore %p] Suspended.", this);
+}
+
+void PerBalancerStore::Resume() {
+  suspended_ = false;
+  gpr_log(GPR_DEBUG, "[PerBalancerStore %p] Resumed.", this);
+}
+
+uint64_t PerBalancerStore::GetNumCallsInProgressForReport() {
+  GPR_ASSERT(!suspended_);
+  last_reported_num_calls_in_progress_ = num_calls_in_progress_;
+  return num_calls_in_progress_;
+}
+
+void PerHostStore::ReportStreamCreated(const grpc::string& lb_id,
+                                       const grpc::string& load_key) {
+  GPR_ASSERT(lb_id != kInvalidLbId);
+  SetUpForNewLbId(lb_id, load_key);
+  // Prior to this one, there was no load balancer receiving report, so we may
+  // have unassigned orphaned stores to assign to this new balancer.
+  // TODO(juanlishen): If the load key of this new stream is the same with
+  // some previously adopted orphan store, we may want to take the orphan to
+  // this stream. Need to discuss with LB team.
+  if (assigned_stores_.size() == 1) {
+    for (const auto& p : per_balancer_stores_) {
+      const grpc::string& other_lb_id = p.first;
+      const std::unique_ptr<PerBalancerStore>& orphaned_store = p.second;
+      if (other_lb_id != lb_id) {
+        orphaned_store->Resume();
+        AssignOrphanedStore(orphaned_store.get(), lb_id);
+      }
+    }
+  }
+  // The first connected balancer will adopt the kInvalidLbId.
+  if (per_balancer_stores_.size() == 1) {
+    SetUpForNewLbId(kInvalidLbId, "");
+    ReportStreamClosed(kInvalidLbId);
+  }
+}
+
+void PerHostStore::ReportStreamClosed(const grpc::string& lb_id) {
+  auto it_store_for_gone_lb = per_balancer_stores_.find(lb_id);
+  GPR_ASSERT(it_store_for_gone_lb != per_balancer_stores_.end());
+  // Remove this closed stream from our records.
+  GPR_ASSERT(UnorderedMapOfSetEraseKeyValue(
+      load_key_to_receiving_lb_ids_, it_store_for_gone_lb->second->load_key(),
+      lb_id));
+  std::set<PerBalancerStore*> orphaned_stores =
+      UnorderedMapOfSetExtract(assigned_stores_, lb_id);
+  // The stores that were assigned to this balancer are orphaned now. They
+  // should be re-assigned to other balancers which are still receiving reports.
+  for (PerBalancerStore* orphaned_store : orphaned_stores) {
+    const grpc::string* new_receiver = nullptr;
+    auto it = load_key_to_receiving_lb_ids_.find(orphaned_store->load_key());
+    if (it != load_key_to_receiving_lb_ids_.end()) {
+      // First, try to pick from the active balancers with the same load key.
+      new_receiver = RandomElement(it->second);
+    } else if (!assigned_stores_.empty()) {
+      // If failed, pick from all the remaining active balancers.
+      new_receiver = &(RandomElement(assigned_stores_)->first);
+    }
+    if (new_receiver != nullptr) {
+      AssignOrphanedStore(orphaned_store, *new_receiver);
+    } else {
+      // Load data for an LB ID that can't be assigned to any stream should
+      // be dropped.
+      orphaned_store->Suspend();
+    }
+  }
+}
+
+PerBalancerStore* PerHostStore::FindPerBalancerStore(
+    const grpc::string& lb_id) const {
+  return per_balancer_stores_.find(lb_id) != per_balancer_stores_.end()
+             ? per_balancer_stores_.find(lb_id)->second.get()
+             : nullptr;
+}
+
+const std::set<PerBalancerStore*>* PerHostStore::GetAssignedStores(
+    const grpc::string& lb_id) const {
+  auto it = assigned_stores_.find(lb_id);
+  if (it == assigned_stores_.end()) return nullptr;
+  return &(it->second);
+}
+
+void PerHostStore::AssignOrphanedStore(PerBalancerStore* orphaned_store,
+                                       const grpc::string& new_receiver) {
+  auto it = assigned_stores_.find(new_receiver);
+  GPR_ASSERT(it != assigned_stores_.end());
+  it->second.insert(orphaned_store);
+  gpr_log(GPR_INFO,
+          "[PerHostStore %p] Re-assigned orphaned store (%p) with original LB"
+          " ID of %s to new receiver %s",
+          this, orphaned_store, orphaned_store->lb_id().c_str(),
+          new_receiver.c_str());
+}
+
+void PerHostStore::SetUpForNewLbId(const grpc::string& lb_id,
+                                   const grpc::string& load_key) {
+  // The top-level caller (i.e., LoadReportService) should guarantee the
+  // lb_id is unique for each reporting stream.
+  GPR_ASSERT(per_balancer_stores_.find(lb_id) == per_balancer_stores_.end());
+  GPR_ASSERT(assigned_stores_.find(lb_id) == assigned_stores_.end());
+  load_key_to_receiving_lb_ids_[load_key].insert(lb_id);
+  std::unique_ptr<PerBalancerStore> per_balancer_store(
+      new PerBalancerStore(lb_id, load_key));
+  assigned_stores_[lb_id] = {per_balancer_store.get()};
+  per_balancer_stores_[lb_id] = std::move(per_balancer_store);
+}
+
+PerBalancerStore* LoadDataStore::FindPerBalancerStore(
+    const string& hostname, const string& lb_id) const {
+  auto it = per_host_stores_.find(hostname);
+  if (it != per_host_stores_.end()) {
+    const PerHostStore& per_host_store = it->second;
+    return per_host_store.FindPerBalancerStore(lb_id);
+  } else {
+    return nullptr;
+  }
+}
+
+void LoadDataStore::MergeRow(const grpc::string& hostname,
+                             const LoadRecordKey& key,
+                             const LoadRecordValue& value) {
+  PerBalancerStore* per_balancer_store =
+      FindPerBalancerStore(hostname, key.lb_id());
+  if (per_balancer_store != nullptr) {
+    per_balancer_store->MergeRow(key, value);
+    return;
+  }
+  // Unknown LB ID. Track it until its number of in-progress calls drops to
+  // zero.
+  int64_t in_progress_delta = value.GetNumCallsInProgressDelta();
+  if (in_progress_delta != 0) {
+    auto it_tracker = unknown_balancer_id_trackers_.find(key.lb_id());
+    if (it_tracker == unknown_balancer_id_trackers_.end()) {
+      gpr_log(
+          GPR_DEBUG,
+          "[LoadDataStore %p] Start tracking unknown balancer (lb_id_: %s).",
+          this, key.lb_id().c_str());
+      unknown_balancer_id_trackers_.insert(
+          {key.lb_id(), static_cast<uint64_t>(in_progress_delta)});
+    } else if ((it_tracker->second += in_progress_delta) == 0) {
+      unknown_balancer_id_trackers_.erase(it_tracker);
+      gpr_log(GPR_DEBUG,
+              "[LoadDataStore %p] Stop tracking unknown balancer (lb_id_: %s).",
+              this, key.lb_id().c_str());
+    }
+  }
+}
+
+const std::set<PerBalancerStore*>* LoadDataStore::GetAssignedStores(
+    const grpc::string& hostname, const grpc::string& lb_id) {
+  auto it = per_host_stores_.find(hostname);
+  if (it == per_host_stores_.end()) return nullptr;
+  return it->second.GetAssignedStores(lb_id);
+}
+
+void LoadDataStore::ReportStreamCreated(const grpc::string& hostname,
+                                        const grpc::string& lb_id,
+                                        const grpc::string& load_key) {
+  per_host_stores_[hostname].ReportStreamCreated(lb_id, load_key);
+}
+
+void LoadDataStore::ReportStreamClosed(const grpc::string& hostname,
+                                       const grpc::string& lb_id) {
+  auto it_per_host_store = per_host_stores_.find(hostname);
+  GPR_ASSERT(it_per_host_store != per_host_stores_.end());
+  it_per_host_store->second.ReportStreamClosed(lb_id);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_data_store.h b/third_party/grpc/src/cpp/server/load_reporter/load_data_store.h
new file mode 100644
index 0000000..dc08ecf
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_data_store.h
@@ -0,0 +1,348 @@
+/*
+ *
+ * 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 GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
+
+#include <grpc/support/port_platform.h>
+
+#include <memory>
+#include <set>
+#include <unordered_map>
+
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/config.h>
+
+#include "src/cpp/server/load_reporter/constants.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// The load data storage is organized in hierarchy. The LoadDataStore is the
+// top-level data store. In LoadDataStore, for each host we keep a
+// PerHostStore, in which for each balancer we keep a PerBalancerStore. Each
+// PerBalancerStore maintains a map of load records, mapping from LoadRecordKey
+// to LoadRecordValue. The LoadRecordValue contains a map of customized call
+// metrics, mapping from a call metric name to the CallMetricValue.
+
+// The value of a customized call metric.
+class CallMetricValue {
+ public:
+  explicit CallMetricValue(uint64_t num_calls = 0,
+                           double total_metric_value = 0)
+      : num_calls_(num_calls), total_metric_value_(total_metric_value) {}
+
+  void MergeFrom(CallMetricValue other) {
+    num_calls_ += other.num_calls_;
+    total_metric_value_ += other.total_metric_value_;
+  }
+
+  // Getters.
+  uint64_t num_calls() const { return num_calls_; }
+  double total_metric_value() const { return total_metric_value_; }
+
+ private:
+  // The number of calls that finished with this metric.
+  uint64_t num_calls_ = 0;
+  // The sum of metric values across all the calls that finished with this
+  // metric.
+  double total_metric_value_ = 0;
+};
+
+// The key of a load record.
+class LoadRecordKey {
+ public:
+  LoadRecordKey(grpc::string lb_id, grpc::string lb_tag, grpc::string user_id,
+                grpc::string client_ip_hex)
+      : lb_id_(std::move(lb_id)),
+        lb_tag_(std::move(lb_tag)),
+        user_id_(std::move(user_id)),
+        client_ip_hex_(std::move(client_ip_hex)) {}
+
+  // Parses the input client_ip_and_token to set client IP, LB ID, and LB tag.
+  LoadRecordKey(const grpc::string& client_ip_and_token, grpc::string user_id);
+
+  grpc::string ToString() const {
+    return "[lb_id_=" + lb_id_ + ", lb_tag_=" + lb_tag_ +
+           ", user_id_=" + user_id_ + ", client_ip_hex_=" + client_ip_hex_ +
+           "]";
+  }
+
+  bool operator==(const LoadRecordKey& other) const {
+    return lb_id_ == other.lb_id_ && lb_tag_ == other.lb_tag_ &&
+           user_id_ == other.user_id_ && client_ip_hex_ == other.client_ip_hex_;
+  }
+
+  // Gets the client IP bytes in network order (i.e., big-endian).
+  grpc::string GetClientIpBytes() const;
+
+  // Getters.
+  const grpc::string& lb_id() const { return lb_id_; }
+  const grpc::string& lb_tag() const { return lb_tag_; }
+  const grpc::string& user_id() const { return user_id_; }
+  const grpc::string& client_ip_hex() const { return client_ip_hex_; }
+
+  struct Hasher {
+    void hash_combine(size_t* seed, const grpc::string& k) const {
+      *seed ^= std::hash<grpc::string>()(k) + 0x9e3779b9 + (*seed << 6) +
+               (*seed >> 2);
+    }
+
+    size_t operator()(const LoadRecordKey& k) const {
+      size_t h = 0;
+      hash_combine(&h, k.lb_id_);
+      hash_combine(&h, k.lb_tag_);
+      hash_combine(&h, k.user_id_);
+      hash_combine(&h, k.client_ip_hex_);
+      return h;
+    }
+  };
+
+ private:
+  grpc::string lb_id_;
+  grpc::string lb_tag_;
+  grpc::string user_id_;
+  grpc::string client_ip_hex_;
+};
+
+// The value of a load record.
+class LoadRecordValue {
+ public:
+  explicit LoadRecordValue(uint64_t start_count = 0, uint64_t ok_count = 0,
+                           uint64_t error_count = 0, uint64_t bytes_sent = 0,
+                           uint64_t bytes_recv = 0, uint64_t latency_ms = 0)
+      : start_count_(start_count),
+        ok_count_(ok_count),
+        error_count_(error_count),
+        bytes_sent_(bytes_sent),
+        bytes_recv_(bytes_recv),
+        latency_ms_(latency_ms) {}
+
+  LoadRecordValue(grpc::string metric_name, uint64_t num_calls,
+                  double total_metric_value);
+
+  void MergeFrom(const LoadRecordValue& other) {
+    start_count_ += other.start_count_;
+    ok_count_ += other.ok_count_;
+    error_count_ += other.error_count_;
+    bytes_sent_ += other.bytes_sent_;
+    bytes_recv_ += other.bytes_recv_;
+    latency_ms_ += other.latency_ms_;
+    for (const auto& p : other.call_metrics_) {
+      const grpc::string& key = p.first;
+      const CallMetricValue& value = p.second;
+      call_metrics_[key].MergeFrom(value);
+    }
+  }
+
+  int64_t GetNumCallsInProgressDelta() const {
+    return static_cast<int64_t>(start_count_ - ok_count_ - error_count_);
+  }
+
+  grpc::string ToString() const {
+    return "[start_count_=" + grpc::to_string(start_count_) +
+           ", ok_count_=" + grpc::to_string(ok_count_) +
+           ", error_count_=" + grpc::to_string(error_count_) +
+           ", bytes_sent_=" + grpc::to_string(bytes_sent_) +
+           ", bytes_recv_=" + grpc::to_string(bytes_recv_) +
+           ", latency_ms_=" + grpc::to_string(latency_ms_) + ", " +
+           grpc::to_string(call_metrics_.size()) + " other call metric(s)]";
+  }
+
+  bool InsertCallMetric(const grpc::string& metric_name,
+                        const CallMetricValue& metric_value) {
+    return call_metrics_.insert({metric_name, metric_value}).second;
+  }
+
+  // Getters.
+  uint64_t start_count() const { return start_count_; }
+  uint64_t ok_count() const { return ok_count_; }
+  uint64_t error_count() const { return error_count_; }
+  uint64_t bytes_sent() const { return bytes_sent_; }
+  uint64_t bytes_recv() const { return bytes_recv_; }
+  uint64_t latency_ms() const { return latency_ms_; }
+  const std::unordered_map<grpc::string, CallMetricValue>& call_metrics()
+      const {
+    return call_metrics_;
+  }
+
+ private:
+  uint64_t start_count_ = 0;
+  uint64_t ok_count_ = 0;
+  uint64_t error_count_ = 0;
+  uint64_t bytes_sent_ = 0;
+  uint64_t bytes_recv_ = 0;
+  uint64_t latency_ms_ = 0;
+  std::unordered_map<grpc::string, CallMetricValue> call_metrics_;
+};
+
+// Stores the data associated with a particular LB ID.
+class PerBalancerStore {
+ public:
+  using LoadRecordMap =
+      std::unordered_map<LoadRecordKey, LoadRecordValue, LoadRecordKey::Hasher>;
+
+  PerBalancerStore(grpc::string lb_id, grpc::string load_key)
+      : lb_id_(std::move(lb_id)), load_key_(std::move(load_key)) {}
+
+  // Merge a load record with the given key and value if the store is not
+  // suspended.
+  void MergeRow(const LoadRecordKey& key, const LoadRecordValue& value);
+
+  // Suspend this store, so that no detailed load data will be recorded.
+  void Suspend();
+  // Resume this store from suspension.
+  void Resume();
+  // Is this store suspended or not?
+  bool IsSuspended() const { return suspended_; }
+
+  bool IsNumCallsInProgressChangedSinceLastReport() const {
+    return num_calls_in_progress_ != last_reported_num_calls_in_progress_;
+  }
+
+  uint64_t GetNumCallsInProgressForReport();
+
+  grpc::string ToString() {
+    return "[PerBalancerStore lb_id_=" + lb_id_ + " load_key_=" + load_key_ +
+           "]";
+  }
+
+  void ClearLoadRecordMap() { load_record_map_.clear(); }
+
+  // Getters.
+  const grpc::string& lb_id() const { return lb_id_; }
+  const grpc::string& load_key() const { return load_key_; }
+  const LoadRecordMap& load_record_map() const { return load_record_map_; }
+
+ private:
+  grpc::string lb_id_;
+  // TODO(juanlishen): Use bytestring protobuf type?
+  grpc::string load_key_;
+  LoadRecordMap load_record_map_;
+  uint64_t num_calls_in_progress_ = 0;
+  uint64_t last_reported_num_calls_in_progress_ = 0;
+  bool suspended_ = false;
+};
+
+// Stores the data associated with a particular host.
+class PerHostStore {
+ public:
+  // When a report stream is created, a PerBalancerStore is created for the
+  // LB ID (guaranteed unique) associated with that stream. If it is the only
+  // active store, adopt all the orphaned stores. If it is the first created
+  // store, adopt the store of kInvalidLbId.
+  void ReportStreamCreated(const grpc::string& lb_id,
+                           const grpc::string& load_key);
+
+  // When a report stream is closed, the PerBalancerStores assigned to the
+  // associate LB ID need to be re-assigned to other active balancers,
+  // ideally with the same load key. If there is no active balancer, we have
+  // to suspend those stores and drop the incoming load data until they are
+  // resumed.
+  void ReportStreamClosed(const grpc::string& lb_id);
+
+  // Returns null if not found. Caller doesn't own the returned store.
+  PerBalancerStore* FindPerBalancerStore(const grpc::string& lb_id) const;
+
+  // Returns null if lb_id is not found. The returned pointer points to the
+  // underlying data structure, which is not owned by the caller.
+  const std::set<PerBalancerStore*>* GetAssignedStores(
+      const grpc::string& lb_id) const;
+
+ private:
+  // Creates a PerBalancerStore for the given LB ID, assigns the store to
+  // itself, and records the LB ID to the load key.
+  void SetUpForNewLbId(const grpc::string& lb_id, const grpc::string& load_key);
+
+  void AssignOrphanedStore(PerBalancerStore* orphaned_store,
+                           const grpc::string& new_receiver);
+
+  std::unordered_map<grpc::string, std::set<grpc::string>>
+      load_key_to_receiving_lb_ids_;
+
+  // Key: LB ID. The key set includes all the LB IDs that have been
+  // allocated for reporting streams so far.
+  // Value: the unique pointer to the PerBalancerStore of the LB ID.
+  std::unordered_map<grpc::string, std::unique_ptr<PerBalancerStore>>
+      per_balancer_stores_;
+
+  // Key: LB ID. The key set includes the LB IDs of the balancers that are
+  // currently receiving report.
+  // Value: the set of raw pointers to the PerBalancerStores assigned to the LB
+  // ID. Note that the sets in assigned_stores_ form a division of the value set
+  // of per_balancer_stores_.
+  std::unordered_map<grpc::string, std::set<PerBalancerStore*>>
+      assigned_stores_;
+};
+
+// Thread-unsafe two-level bookkeeper of all the load data.
+// Note: We never remove any store objects from this class, as per the
+// current spec. That's because premature removal of the store objects
+// may lead to loss of critical information, e.g., mapping from lb_id to
+// load_key, and the number of in-progress calls. Such loss will cause
+// information inconsistency when the balancer is re-connected. Keeping
+// all the stores should be fine for PerHostStore, since we assume there
+// should only be a few hostnames. But it's a potential problem for
+// PerBalancerStore.
+class LoadDataStore {
+ public:
+  // Returns null if not found. Caller doesn't own the returned store.
+  PerBalancerStore* FindPerBalancerStore(const grpc::string& hostname,
+                                         const grpc::string& lb_id) const;
+
+  // Returns null if hostname or lb_id is not found. The returned pointer points
+  // to the underlying data structure, which is not owned by the caller.
+  const std::set<PerBalancerStore*>* GetAssignedStores(const string& hostname,
+                                                       const string& lb_id);
+
+  // If a PerBalancerStore can be found by the hostname and LB ID in
+  // LoadRecordKey, the load data will be merged to that store. Otherwise,
+  // only track the number of the in-progress calls for this unknown LB ID.
+  void MergeRow(const grpc::string& hostname, const LoadRecordKey& key,
+                const LoadRecordValue& value);
+
+  // Is the given lb_id a tracked unknown LB ID (i.e., the LB ID was associated
+  // with some received load data but unknown to this load data store)?
+  bool IsTrackedUnknownBalancerId(const grpc::string& lb_id) const {
+    return unknown_balancer_id_trackers_.find(lb_id) !=
+           unknown_balancer_id_trackers_.end();
+  }
+
+  // Wrapper around PerHostStore::ReportStreamCreated.
+  void ReportStreamCreated(const grpc::string& hostname,
+                           const grpc::string& lb_id,
+                           const grpc::string& load_key);
+
+  // Wrapper around PerHostStore::ReportStreamClosed.
+  void ReportStreamClosed(const grpc::string& hostname,
+                          const grpc::string& lb_id);
+
+ private:
+  // Buffered data that was fetched from Census but hasn't been sent to
+  // balancer. We need to keep this data ourselves because Census will
+  // delete the data once it's returned.
+  std::unordered_map<grpc::string, PerHostStore> per_host_stores_;
+
+  // Tracks the number of in-progress calls for each unknown LB ID.
+  std::unordered_map<grpc::string, uint64_t> unknown_balancer_id_trackers_;
+};
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_DATA_STORE_H
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporter.cc b/third_party/grpc/src/cpp/server/load_reporter/load_reporter.cc
new file mode 100644
index 0000000..464063a
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporter.cc
@@ -0,0 +1,509 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <stdint.h>
+#include <stdio.h>
+#include <chrono>
+#include <ctime>
+#include <iterator>
+
+#include "src/cpp/server/load_reporter/constants.h"
+#include "src/cpp/server/load_reporter/get_cpu_stats.h"
+#include "src/cpp/server/load_reporter/load_reporter.h"
+
+#include "opencensus/stats/internal/set_aggregation_window.h"
+
+namespace grpc {
+namespace load_reporter {
+
+CpuStatsProvider::CpuStatsSample CpuStatsProviderDefaultImpl::GetCpuStats() {
+  return GetCpuStatsImpl();
+}
+
+CensusViewProvider::CensusViewProvider()
+    : tag_key_token_(::opencensus::stats::TagKey::Register(kTagKeyToken)),
+      tag_key_host_(::opencensus::stats::TagKey::Register(kTagKeyHost)),
+      tag_key_user_id_(::opencensus::stats::TagKey::Register(kTagKeyUserId)),
+      tag_key_status_(::opencensus::stats::TagKey::Register(kTagKeyStatus)),
+      tag_key_metric_name_(
+          ::opencensus::stats::TagKey::Register(kTagKeyMetricName)) {
+  // One view related to starting a call.
+  auto vd_start_count =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewStartCount)
+          .set_measure(kMeasureStartCount)
+          .set_aggregation(::opencensus::stats::Aggregation::Sum())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .set_description(
+              "Delta count of calls started broken down by <token, host, "
+              "user_id>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_start_count);
+  view_descriptor_map_.emplace(kViewStartCount, vd_start_count);
+  // Four views related to ending a call.
+  // If this view is set as Count of kMeasureEndBytesSent (in hope of saving one
+  // measure), it's infeasible to prepare fake data for testing. That's because
+  // the OpenCensus API to make up view data will add the input data as separate
+  // measurements instead of setting the data values directly.
+  auto vd_end_count =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewEndCount)
+          .set_measure(kMeasureEndCount)
+          .set_aggregation(::opencensus::stats::Aggregation::Sum())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .add_column(tag_key_status_)
+          .set_description(
+              "Delta count of calls ended broken down by <token, host, "
+              "user_id, status>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_end_count);
+  view_descriptor_map_.emplace(kViewEndCount, vd_end_count);
+  auto vd_end_bytes_sent =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewEndBytesSent)
+          .set_measure(kMeasureEndBytesSent)
+          .set_aggregation(::opencensus::stats::Aggregation::Sum())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .add_column(tag_key_status_)
+          .set_description(
+              "Delta sum of bytes sent broken down by <token, host, user_id, "
+              "status>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_end_bytes_sent);
+  view_descriptor_map_.emplace(kViewEndBytesSent, vd_end_bytes_sent);
+  auto vd_end_bytes_received =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewEndBytesReceived)
+          .set_measure(kMeasureEndBytesReceived)
+          .set_aggregation(::opencensus::stats::Aggregation::Sum())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .add_column(tag_key_status_)
+          .set_description(
+              "Delta sum of bytes received broken down by <token, host, "
+              "user_id, status>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_end_bytes_received);
+  view_descriptor_map_.emplace(kViewEndBytesReceived, vd_end_bytes_received);
+  auto vd_end_latency_ms =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewEndLatencyMs)
+          .set_measure(kMeasureEndLatencyMs)
+          .set_aggregation(::opencensus::stats::Aggregation::Sum())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .add_column(tag_key_status_)
+          .set_description(
+              "Delta sum of latency in ms broken down by <token, host, "
+              "user_id, status>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_end_latency_ms);
+  view_descriptor_map_.emplace(kViewEndLatencyMs, vd_end_latency_ms);
+  // Two views related to other call metrics.
+  auto vd_metric_call_count =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewOtherCallMetricCount)
+          .set_measure(kMeasureOtherCallMetric)
+          .set_aggregation(::opencensus::stats::Aggregation::Count())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .add_column(tag_key_metric_name_)
+          .set_description(
+              "Delta count of calls broken down by <token, host, user_id, "
+              "metric_name>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_metric_call_count);
+  view_descriptor_map_.emplace(kViewOtherCallMetricCount, vd_metric_call_count);
+  auto vd_metric_value =
+      ::opencensus::stats::ViewDescriptor()
+          .set_name(kViewOtherCallMetricValue)
+          .set_measure(kMeasureOtherCallMetric)
+          .set_aggregation(::opencensus::stats::Aggregation::Sum())
+          .add_column(tag_key_token_)
+          .add_column(tag_key_host_)
+          .add_column(tag_key_user_id_)
+          .add_column(tag_key_metric_name_)
+          .set_description(
+              "Delta sum of call metric value broken down "
+              "by <token, host, user_id, metric_name>.");
+  ::opencensus::stats::SetAggregationWindow(
+      ::opencensus::stats::AggregationWindow::Delta(), &vd_metric_value);
+  view_descriptor_map_.emplace(kViewOtherCallMetricValue, vd_metric_value);
+}
+
+double CensusViewProvider::GetRelatedViewDataRowDouble(
+    const ViewDataMap& view_data_map, const char* view_name,
+    size_t view_name_len, const std::vector<grpc::string>& tag_values) {
+  auto it_vd = view_data_map.find(grpc::string(view_name, view_name_len));
+  GPR_ASSERT(it_vd != view_data_map.end());
+  GPR_ASSERT(it_vd->second.type() ==
+             ::opencensus::stats::ViewData::Type::kDouble);
+  auto it_row = it_vd->second.double_data().find(tag_values);
+  GPR_ASSERT(it_row != it_vd->second.double_data().end());
+  return it_row->second;
+}
+
+uint64_t CensusViewProvider::GetRelatedViewDataRowInt(
+    const ViewDataMap& view_data_map, const char* view_name,
+    size_t view_name_len, const std::vector<grpc::string>& tag_values) {
+  auto it_vd = view_data_map.find(grpc::string(view_name, view_name_len));
+  GPR_ASSERT(it_vd != view_data_map.end());
+  GPR_ASSERT(it_vd->second.type() ==
+             ::opencensus::stats::ViewData::Type::kInt64);
+  auto it_row = it_vd->second.int_data().find(tag_values);
+  GPR_ASSERT(it_row != it_vd->second.int_data().end());
+  GPR_ASSERT(it_row->second >= 0);
+  return it_row->second;
+}
+
+CensusViewProviderDefaultImpl::CensusViewProviderDefaultImpl() {
+  for (const auto& p : view_descriptor_map()) {
+    const grpc::string& view_name = p.first;
+    const ::opencensus::stats::ViewDescriptor& vd = p.second;
+    // We need to use pair's piecewise ctor here, otherwise the deleted copy
+    // ctor of View will be called.
+    view_map_.emplace(std::piecewise_construct,
+                      std::forward_as_tuple(view_name),
+                      std::forward_as_tuple(vd));
+  }
+}
+
+CensusViewProvider::ViewDataMap CensusViewProviderDefaultImpl::FetchViewData() {
+  gpr_log(GPR_DEBUG, "[CVP %p] Starts fetching Census view data.", this);
+  ViewDataMap view_data_map;
+  for (auto& p : view_map_) {
+    const grpc::string& view_name = p.first;
+    ::opencensus::stats::View& view = p.second;
+    if (view.IsValid()) {
+      view_data_map.emplace(view_name, view.GetData());
+      gpr_log(GPR_DEBUG, "[CVP %p] Fetched view data (view: %s).", this,
+              view_name.c_str());
+    } else {
+      gpr_log(
+          GPR_DEBUG,
+          "[CVP %p] Can't fetch view data because view is invalid (view: %s).",
+          this, view_name.c_str());
+    }
+  }
+  return view_data_map;
+}
+
+grpc::string LoadReporter::GenerateLbId() {
+  while (true) {
+    if (next_lb_id_ > UINT32_MAX) {
+      gpr_log(GPR_ERROR, "[LR %p] The LB ID exceeds the max valid value!",
+              this);
+      return "";
+    }
+    int64_t lb_id = next_lb_id_++;
+    // Overflow should never happen.
+    GPR_ASSERT(lb_id >= 0);
+    // Convert to padded hex string for a 32-bit LB ID. E.g, "0000ca5b".
+    char buf[kLbIdLength + 1];
+    snprintf(buf, sizeof(buf), "%08lx", lb_id);
+    grpc::string lb_id_str(buf, kLbIdLength);
+    // The client may send requests with LB ID that has never been allocated
+    // by this load reporter. Those IDs are tracked and will be skipped when
+    // we generate a new ID.
+    if (!load_data_store_.IsTrackedUnknownBalancerId(lb_id_str)) {
+      return lb_id_str;
+    }
+  }
+}
+
+::grpc::lb::v1::LoadBalancingFeedback
+LoadReporter::GenerateLoadBalancingFeedback() {
+  std::unique_lock<std::mutex> lock(feedback_mu_);
+  auto now = std::chrono::system_clock::now();
+  // Discard records outside the window until there is only one record
+  // outside the window, which is used as the base for difference.
+  while (feedback_records_.size() > 1 &&
+         !IsRecordInWindow(feedback_records_[1], now)) {
+    feedback_records_.pop_front();
+  }
+  if (feedback_records_.size() < 2) {
+    return ::grpc::lb::v1::LoadBalancingFeedback::default_instance();
+  }
+  // Find the longest range with valid ends.
+  auto oldest = feedback_records_.begin();
+  auto newest = feedback_records_.end() - 1;
+  while (std::distance(oldest, newest) > 0 &&
+         (newest->cpu_limit == 0 || oldest->cpu_limit == 0)) {
+    // A zero limit means that the system info reading was failed, so these
+    // records can't be used to calculate CPU utilization.
+    if (newest->cpu_limit == 0) --newest;
+    if (oldest->cpu_limit == 0) ++oldest;
+  }
+  if (std::distance(oldest, newest) < 1 ||
+      oldest->end_time == newest->end_time ||
+      newest->cpu_limit == oldest->cpu_limit) {
+    return ::grpc::lb::v1::LoadBalancingFeedback::default_instance();
+  }
+  uint64_t rpcs = 0;
+  uint64_t errors = 0;
+  for (auto p = newest; p != oldest; --p) {
+    // Because these two numbers are counters, the oldest record shouldn't be
+    // included.
+    rpcs += p->rpcs;
+    errors += p->errors;
+  }
+  double cpu_usage = newest->cpu_usage - oldest->cpu_usage;
+  double cpu_limit = newest->cpu_limit - oldest->cpu_limit;
+  std::chrono::duration<double> duration_seconds =
+      newest->end_time - oldest->end_time;
+  lock.unlock();
+  ::grpc::lb::v1::LoadBalancingFeedback feedback;
+  feedback.set_server_utilization(static_cast<float>(cpu_usage / cpu_limit));
+  feedback.set_calls_per_second(
+      static_cast<float>(rpcs / duration_seconds.count()));
+  feedback.set_errors_per_second(
+      static_cast<float>(errors / duration_seconds.count()));
+  return feedback;
+}
+
+::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load>
+LoadReporter::GenerateLoads(const grpc::string& hostname,
+                            const grpc::string& lb_id) {
+  std::lock_guard<std::mutex> lock(store_mu_);
+  auto assigned_stores = load_data_store_.GetAssignedStores(hostname, lb_id);
+  GPR_ASSERT(assigned_stores != nullptr);
+  GPR_ASSERT(!assigned_stores->empty());
+  ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> loads;
+  for (PerBalancerStore* per_balancer_store : *assigned_stores) {
+    GPR_ASSERT(!per_balancer_store->IsSuspended());
+    if (!per_balancer_store->load_record_map().empty()) {
+      for (const auto& p : per_balancer_store->load_record_map()) {
+        const auto& key = p.first;
+        const auto& value = p.second;
+        auto load = loads.Add();
+        load->set_load_balance_tag(key.lb_tag());
+        load->set_user_id(key.user_id());
+        load->set_client_ip_address(key.GetClientIpBytes());
+        load->set_num_calls_started(static_cast<int64_t>(value.start_count()));
+        load->set_num_calls_finished_without_error(
+            static_cast<int64_t>(value.ok_count()));
+        load->set_num_calls_finished_with_error(
+            static_cast<int64_t>(value.error_count()));
+        load->set_total_bytes_sent(static_cast<int64_t>(value.bytes_sent()));
+        load->set_total_bytes_received(
+            static_cast<int64_t>(value.bytes_recv()));
+        load->mutable_total_latency()->set_seconds(
+            static_cast<int64_t>(value.latency_ms() / 1000));
+        load->mutable_total_latency()->set_nanos(
+            (static_cast<int32_t>(value.latency_ms()) % 1000) * 1000000);
+        for (const auto& p : value.call_metrics()) {
+          const grpc::string& metric_name = p.first;
+          const CallMetricValue& metric_value = p.second;
+          auto call_metric_data = load->add_metric_data();
+          call_metric_data->set_metric_name(metric_name);
+          call_metric_data->set_num_calls_finished_with_metric(
+              metric_value.num_calls());
+          call_metric_data->set_total_metric_value(
+              metric_value.total_metric_value());
+        }
+        if (per_balancer_store->lb_id() != lb_id) {
+          // This per-balancer store is an orphan assigned to this receiving
+          // balancer.
+          AttachOrphanLoadId(load, *per_balancer_store);
+        }
+      }
+      per_balancer_store->ClearLoadRecordMap();
+    }
+    if (per_balancer_store->IsNumCallsInProgressChangedSinceLastReport()) {
+      auto load = loads.Add();
+      load->set_num_calls_in_progress(
+          per_balancer_store->GetNumCallsInProgressForReport());
+      if (per_balancer_store->lb_id() != lb_id) {
+        // This per-balancer store is an orphan assigned to this receiving
+        // balancer.
+        AttachOrphanLoadId(load, *per_balancer_store);
+      }
+    }
+  }
+  return loads;
+}
+
+void LoadReporter::AttachOrphanLoadId(
+    ::grpc::lb::v1::Load* load, const PerBalancerStore& per_balancer_store) {
+  if (per_balancer_store.lb_id() == kInvalidLbId) {
+    load->set_load_key_unknown(true);
+  } else {
+    // We shouldn't set load_key_unknown to any value in this case because
+    // load_key_unknown and orphaned_load_identifier are under an oneof struct.
+    load->mutable_orphaned_load_identifier()->set_load_key(
+        per_balancer_store.load_key());
+    load->mutable_orphaned_load_identifier()->set_load_balancer_id(
+        per_balancer_store.lb_id());
+  }
+}
+
+void LoadReporter::AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors) {
+  CpuStatsProvider::CpuStatsSample cpu_stats;
+  if (cpu_stats_provider_ != nullptr) {
+    cpu_stats = cpu_stats_provider_->GetCpuStats();
+  } else {
+    // This will make the load balancing feedback generation a no-op.
+    cpu_stats = {0, 0};
+  }
+  std::unique_lock<std::mutex> lock(feedback_mu_);
+  feedback_records_.emplace_back(std::chrono::system_clock::now(), rpcs, errors,
+                                 cpu_stats.first, cpu_stats.second);
+}
+
+void LoadReporter::ReportStreamCreated(const grpc::string& hostname,
+                                       const grpc::string& lb_id,
+                                       const grpc::string& load_key) {
+  std::lock_guard<std::mutex> lock(store_mu_);
+  load_data_store_.ReportStreamCreated(hostname, lb_id, load_key);
+  gpr_log(GPR_INFO,
+          "[LR %p] Report stream created (host: %s, LB ID: %s, load key: %s).",
+          this, hostname.c_str(), lb_id.c_str(), load_key.c_str());
+}
+
+void LoadReporter::ReportStreamClosed(const grpc::string& hostname,
+                                      const grpc::string& lb_id) {
+  std::lock_guard<std::mutex> lock(store_mu_);
+  load_data_store_.ReportStreamClosed(hostname, lb_id);
+  gpr_log(GPR_INFO, "[LR %p] Report stream closed (host: %s, LB ID: %s).", this,
+          hostname.c_str(), lb_id.c_str());
+}
+
+void LoadReporter::ProcessViewDataCallStart(
+    const CensusViewProvider::ViewDataMap& view_data_map) {
+  auto it = view_data_map.find(kViewStartCount);
+  if (it != view_data_map.end()) {
+    for (const auto& p : it->second.int_data()) {
+      const std::vector<grpc::string>& tag_values = p.first;
+      const uint64_t start_count = static_cast<uint64_t>(p.second);
+      const grpc::string& client_ip_and_token = tag_values[0];
+      const grpc::string& host = tag_values[1];
+      const grpc::string& user_id = tag_values[2];
+      LoadRecordKey key(client_ip_and_token, user_id);
+      LoadRecordValue value = LoadRecordValue(start_count);
+      {
+        std::unique_lock<std::mutex> lock(store_mu_);
+        load_data_store_.MergeRow(host, key, value);
+      }
+    }
+  }
+}
+
+void LoadReporter::ProcessViewDataCallEnd(
+    const CensusViewProvider::ViewDataMap& view_data_map) {
+  uint64_t total_end_count = 0;
+  uint64_t total_error_count = 0;
+  auto it = view_data_map.find(kViewEndCount);
+  if (it != view_data_map.end()) {
+    for (const auto& p : it->second.int_data()) {
+      const std::vector<grpc::string>& tag_values = p.first;
+      const uint64_t end_count = static_cast<uint64_t>(p.second);
+      const grpc::string& client_ip_and_token = tag_values[0];
+      const grpc::string& host = tag_values[1];
+      const grpc::string& user_id = tag_values[2];
+      const grpc::string& status = tag_values[3];
+      // This is due to a bug reported internally of Java server load reporting
+      // implementation.
+      // TODO(juanlishen): Check whether this situation happens in OSS C++.
+      if (client_ip_and_token.size() == 0) {
+        gpr_log(GPR_DEBUG,
+                "Skipping processing Opencensus record with empty "
+                "client_ip_and_token tag.");
+        continue;
+      }
+      LoadRecordKey key(client_ip_and_token, user_id);
+      const uint64_t bytes_sent = CensusViewProvider::GetRelatedViewDataRowInt(
+          view_data_map, kViewEndBytesSent, sizeof(kViewEndBytesSent) - 1,
+          tag_values);
+      const uint64_t bytes_received =
+          CensusViewProvider::GetRelatedViewDataRowInt(
+              view_data_map, kViewEndBytesReceived,
+              sizeof(kViewEndBytesReceived) - 1, tag_values);
+      const uint64_t latency_ms = CensusViewProvider::GetRelatedViewDataRowInt(
+          view_data_map, kViewEndLatencyMs, sizeof(kViewEndLatencyMs) - 1,
+          tag_values);
+      uint64_t ok_count = 0;
+      uint64_t error_count = 0;
+      total_end_count += end_count;
+      if (std::strcmp(status.c_str(), kCallStatusOk) == 0) {
+        ok_count = end_count;
+      } else {
+        error_count = end_count;
+        total_error_count += end_count;
+      }
+      LoadRecordValue value = LoadRecordValue(
+          0, ok_count, error_count, bytes_sent, bytes_received, latency_ms);
+      {
+        std::unique_lock<std::mutex> lock(store_mu_);
+        load_data_store_.MergeRow(host, key, value);
+      }
+    }
+  }
+  AppendNewFeedbackRecord(total_end_count, total_error_count);
+}
+
+void LoadReporter::ProcessViewDataOtherCallMetrics(
+    const CensusViewProvider::ViewDataMap& view_data_map) {
+  auto it = view_data_map.find(kViewOtherCallMetricCount);
+  if (it != view_data_map.end()) {
+    for (const auto& p : it->second.int_data()) {
+      const std::vector<grpc::string>& tag_values = p.first;
+      const int64_t num_calls = p.second;
+      const grpc::string& client_ip_and_token = tag_values[0];
+      const grpc::string& host = tag_values[1];
+      const grpc::string& user_id = tag_values[2];
+      const grpc::string& metric_name = tag_values[3];
+      LoadRecordKey key(client_ip_and_token, user_id);
+      const double total_metric_value =
+          CensusViewProvider::GetRelatedViewDataRowDouble(
+              view_data_map, kViewOtherCallMetricValue,
+              sizeof(kViewOtherCallMetricValue) - 1, tag_values);
+      LoadRecordValue value = LoadRecordValue(
+          metric_name, static_cast<uint64_t>(num_calls), total_metric_value);
+      {
+        std::unique_lock<std::mutex> lock(store_mu_);
+        load_data_store_.MergeRow(host, key, value);
+      }
+    }
+  }
+}
+
+void LoadReporter::FetchAndSample() {
+  gpr_log(GPR_DEBUG,
+          "[LR %p] Starts fetching Census view data and sampling LB feedback "
+          "record.",
+          this);
+  CensusViewProvider::ViewDataMap view_data_map =
+      census_view_provider_->FetchViewData();
+  ProcessViewDataCallStart(view_data_map);
+  ProcessViewDataCallEnd(view_data_map);
+  ProcessViewDataOtherCallMetrics(view_data_map);
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporter.h b/third_party/grpc/src/cpp/server/load_reporter/load_reporter.h
new file mode 100644
index 0000000..b2254d5
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporter.h
@@ -0,0 +1,228 @@
+/*
+ *
+ * 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 GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
+
+#include <grpc/support/port_platform.h>
+
+#include <atomic>
+#include <chrono>
+#include <deque>
+#include <vector>
+
+#include <grpc/support/log.h>
+#include <grpcpp/impl/codegen/config.h>
+
+#include "src/cpp/server/load_reporter/load_data_store.h"
+#include "src/proto/grpc/lb/v1/load_reporter.grpc.pb.h"
+
+#include "opencensus/stats/stats.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// The interface to get the Census stats. Abstracted for mocking.
+class CensusViewProvider {
+ public:
+  // Maps from the view name to the view data.
+  using ViewDataMap =
+      std::unordered_map<grpc::string, ::opencensus::stats::ViewData>;
+  // Maps from the view name to the view descriptor.
+  using ViewDescriptorMap =
+      std::unordered_map<grpc::string, ::opencensus::stats::ViewDescriptor>;
+
+  CensusViewProvider();
+  virtual ~CensusViewProvider() = default;
+
+  // Fetches the view data accumulated since last fetching, and returns it as a
+  // map from the view name to the view data.
+  virtual ViewDataMap FetchViewData() = 0;
+
+  // A helper function that gets a row with the input tag values from the view
+  // data. Only used when we know that row must exist because we have seen a row
+  // with the same tag values in a related view data. Several ViewData's are
+  // considered related if their views are based on the measures that are always
+  // recorded at the same time.
+  static double GetRelatedViewDataRowDouble(
+      const ViewDataMap& view_data_map, const char* view_name,
+      size_t view_name_len, const std::vector<grpc::string>& tag_values);
+  static uint64_t GetRelatedViewDataRowInt(
+      const ViewDataMap& view_data_map, const char* view_name,
+      size_t view_name_len, const std::vector<grpc::string>& tag_values);
+
+ protected:
+  const ViewDescriptorMap& view_descriptor_map() const {
+    return view_descriptor_map_;
+  }
+
+ private:
+  ViewDescriptorMap view_descriptor_map_;
+  // Tag keys.
+  ::opencensus::stats::TagKey tag_key_token_;
+  ::opencensus::stats::TagKey tag_key_host_;
+  ::opencensus::stats::TagKey tag_key_user_id_;
+  ::opencensus::stats::TagKey tag_key_status_;
+  ::opencensus::stats::TagKey tag_key_metric_name_;
+};
+
+// The default implementation fetches the real stats from Census.
+class CensusViewProviderDefaultImpl : public CensusViewProvider {
+ public:
+  CensusViewProviderDefaultImpl();
+
+  ViewDataMap FetchViewData() override;
+
+ private:
+  std::unordered_map<grpc::string, ::opencensus::stats::View> view_map_;
+};
+
+// The interface to get the CPU stats. Abstracted for mocking.
+class CpuStatsProvider {
+ public:
+  // The used and total amounts of CPU usage.
+  using CpuStatsSample = std::pair<uint64_t, uint64_t>;
+
+  virtual ~CpuStatsProvider() = default;
+
+  // Gets the cumulative used CPU and total CPU resource.
+  virtual CpuStatsSample GetCpuStats() = 0;
+};
+
+// The default implementation reads CPU jiffies from the system to calculate CPU
+// utilization.
+class CpuStatsProviderDefaultImpl : public CpuStatsProvider {
+ public:
+  CpuStatsSample GetCpuStats() override;
+};
+
+// Maintains all the load data and load reporting streams.
+class LoadReporter {
+ public:
+  // TODO(juanlishen): Allow config for providers from users.
+  LoadReporter(uint32_t feedback_sample_window_seconds,
+               std::unique_ptr<CensusViewProvider> census_view_provider,
+               std::unique_ptr<CpuStatsProvider> cpu_stats_provider)
+      : feedback_sample_window_seconds_(feedback_sample_window_seconds),
+        census_view_provider_(std::move(census_view_provider)),
+        cpu_stats_provider_(std::move(cpu_stats_provider)) {
+    // Append the initial record so that the next real record can have a base.
+    AppendNewFeedbackRecord(0, 0);
+  }
+
+  // Fetches the latest data from Census and merge it into the data store.
+  // Also adds a new sample to the LB feedback sliding window.
+  // Thread-unsafe. (1). The access to the load data store and feedback records
+  // has locking. (2). The access to the Census view provider and CPU stats
+  // provider lacks locking, but we only access these two members in this method
+  // (in testing, we also access them when setting up expectation). So the
+  // invocations of this method must be serialized.
+  void FetchAndSample();
+
+  // Generates a report for that host and balancer. The report contains
+  // all the stats data accumulated between the last report (i.e., the last
+  // consumption) and the last fetch from Census (i.e., the last production).
+  // Thread-safe.
+  ::google::protobuf::RepeatedPtrField<::grpc::lb::v1::Load> GenerateLoads(
+      const grpc::string& hostname, const grpc::string& lb_id);
+
+  // The feedback is calculated from the stats data recorded in the sliding
+  // window. Outdated records are discarded.
+  // Thread-safe.
+  ::grpc::lb::v1::LoadBalancingFeedback GenerateLoadBalancingFeedback();
+
+  // Wrapper around LoadDataStore::ReportStreamCreated.
+  // Thread-safe.
+  void ReportStreamCreated(const grpc::string& hostname,
+                           const grpc::string& lb_id,
+                           const grpc::string& load_key);
+
+  // Wrapper around LoadDataStore::ReportStreamClosed.
+  // Thread-safe.
+  void ReportStreamClosed(const grpc::string& hostname,
+                          const grpc::string& lb_id);
+
+  // Generates a unique LB ID of length kLbIdLength. Returns an empty string
+  // upon failure. Thread-safe.
+  grpc::string GenerateLbId();
+
+  // Accessors only for testing.
+  CensusViewProvider* census_view_provider() {
+    return census_view_provider_.get();
+  }
+  CpuStatsProvider* cpu_stats_provider() { return cpu_stats_provider_.get(); }
+
+ private:
+  struct LoadBalancingFeedbackRecord {
+    std::chrono::system_clock::time_point end_time;
+    uint64_t rpcs;
+    uint64_t errors;
+    uint64_t cpu_usage;
+    uint64_t cpu_limit;
+
+    LoadBalancingFeedbackRecord(
+        const std::chrono::system_clock::time_point& end_time, uint64_t rpcs,
+        uint64_t errors, uint64_t cpu_usage, uint64_t cpu_limit)
+        : end_time(end_time),
+          rpcs(rpcs),
+          errors(errors),
+          cpu_usage(cpu_usage),
+          cpu_limit(cpu_limit) {}
+  };
+
+  // Finds the view data about starting call from the view_data_map and merges
+  // the data to the load data store.
+  void ProcessViewDataCallStart(
+      const CensusViewProvider::ViewDataMap& view_data_map);
+  // Finds the view data about ending call from the view_data_map and merges the
+  // data to the load data store.
+  void ProcessViewDataCallEnd(
+      const CensusViewProvider::ViewDataMap& view_data_map);
+  // Finds the view data about the customized call metrics from the
+  // view_data_map and merges the data to the load data store.
+  void ProcessViewDataOtherCallMetrics(
+      const CensusViewProvider::ViewDataMap& view_data_map);
+
+  bool IsRecordInWindow(const LoadBalancingFeedbackRecord& record,
+                        std::chrono::system_clock::time_point now) {
+    return record.end_time > now - feedback_sample_window_seconds_;
+  }
+
+  void AppendNewFeedbackRecord(uint64_t rpcs, uint64_t errors);
+
+  // Extracts an OrphanedLoadIdentifier from the per-balancer store and attaches
+  // it to the load.
+  void AttachOrphanLoadId(::grpc::lb::v1::Load* load,
+                          const PerBalancerStore& per_balancer_store);
+
+  std::atomic<int64_t> next_lb_id_{0};
+  const std::chrono::seconds feedback_sample_window_seconds_;
+  std::mutex feedback_mu_;
+  std::deque<LoadBalancingFeedbackRecord> feedback_records_;
+  // TODO(juanlishen): Lock in finer grain. Locking the whole store may be
+  // too expensive.
+  std::mutex store_mu_;
+  LoadDataStore load_data_store_;
+  std::unique_ptr<CensusViewProvider> census_view_provider_;
+  std::unique_ptr<CpuStatsProvider> cpu_stats_provider_;
+};
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_LOAD_REPORTER_H
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc b/third_party/grpc/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc
new file mode 100644
index 0000000..d001199
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporter_async_service_impl.cc
@@ -0,0 +1,370 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/server/load_reporter/load_reporter_async_service_impl.h"
+
+namespace grpc {
+namespace load_reporter {
+
+void LoadReporterAsyncServiceImpl::CallableTag::Run(bool ok) {
+  GPR_ASSERT(handler_function_ != nullptr);
+  GPR_ASSERT(handler_ != nullptr);
+  handler_function_(std::move(handler_), ok);
+}
+
+LoadReporterAsyncServiceImpl::LoadReporterAsyncServiceImpl(
+    std::unique_ptr<ServerCompletionQueue> cq)
+    : cq_(std::move(cq)) {
+  thread_ = std::unique_ptr<::grpc_core::Thread>(
+      new ::grpc_core::Thread("server_load_reporting", Work, this));
+  std::unique_ptr<CpuStatsProvider> cpu_stats_provider = nullptr;
+#if defined(GPR_LINUX) || defined(GPR_WINDOWS) || defined(GPR_APPLE)
+  cpu_stats_provider.reset(new CpuStatsProviderDefaultImpl());
+#endif
+  load_reporter_ = std::unique_ptr<LoadReporter>(new LoadReporter(
+      kFeedbackSampleWindowSeconds,
+      std::unique_ptr<CensusViewProvider>(new CensusViewProviderDefaultImpl()),
+      std::move(cpu_stats_provider)));
+}
+
+LoadReporterAsyncServiceImpl::~LoadReporterAsyncServiceImpl() {
+  // We will reach here after the server starts shutting down.
+  shutdown_ = true;
+  {
+    std::unique_lock<std::mutex> lock(cq_shutdown_mu_);
+    cq_->Shutdown();
+  }
+  if (next_fetch_and_sample_alarm_ != nullptr)
+    next_fetch_and_sample_alarm_->Cancel();
+  thread_->Join();
+}
+
+void LoadReporterAsyncServiceImpl::ScheduleNextFetchAndSample() {
+  auto next_fetch_and_sample_time =
+      gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                   gpr_time_from_millis(kFetchAndSampleIntervalSeconds * 1000,
+                                        GPR_TIMESPAN));
+  {
+    std::unique_lock<std::mutex> lock(cq_shutdown_mu_);
+    if (shutdown_) return;
+    // TODO(juanlishen): Improve the Alarm implementation to reuse a single
+    // instance for multiple events.
+    next_fetch_and_sample_alarm_.reset(new Alarm);
+    next_fetch_and_sample_alarm_->Set(cq_.get(), next_fetch_and_sample_time,
+                                      this);
+  }
+  gpr_log(GPR_DEBUG, "[LRS %p] Next fetch-and-sample scheduled.", this);
+}
+
+void LoadReporterAsyncServiceImpl::FetchAndSample(bool ok) {
+  if (!ok) {
+    gpr_log(GPR_INFO, "[LRS %p] Fetch-and-sample is stopped.", this);
+    return;
+  }
+  gpr_log(GPR_DEBUG, "[LRS %p] Starting a fetch-and-sample...", this);
+  load_reporter_->FetchAndSample();
+  ScheduleNextFetchAndSample();
+}
+
+void LoadReporterAsyncServiceImpl::Work(void* arg) {
+  LoadReporterAsyncServiceImpl* service =
+      reinterpret_cast<LoadReporterAsyncServiceImpl*>(arg);
+  service->FetchAndSample(true /* ok */);
+  // TODO(juanlishen): This is a workaround to wait for the cq to be ready. Need
+  // to figure out why cq is not ready after service starts.
+  gpr_sleep_until(gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                               gpr_time_from_seconds(1, GPR_TIMESPAN)));
+  ReportLoadHandler::CreateAndStart(service->cq_.get(), service,
+                                    service->load_reporter_.get());
+  void* tag;
+  bool ok;
+  while (true) {
+    if (!service->cq_->Next(&tag, &ok)) {
+      // The completion queue is shutting down.
+      GPR_ASSERT(service->shutdown_);
+      break;
+    }
+    if (tag == service) {
+      service->FetchAndSample(ok);
+    } else {
+      auto* next_step = static_cast<CallableTag*>(tag);
+      next_step->Run(ok);
+    }
+  }
+}
+
+void LoadReporterAsyncServiceImpl::StartThread() { thread_->Start(); }
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::CreateAndStart(
+    ServerCompletionQueue* cq, LoadReporterAsyncServiceImpl* service,
+    LoadReporter* load_reporter) {
+  std::shared_ptr<ReportLoadHandler> handler =
+      std::make_shared<ReportLoadHandler>(cq, service, load_reporter);
+  ReportLoadHandler* p = handler.get();
+  {
+    std::unique_lock<std::mutex> lock(service->cq_shutdown_mu_);
+    if (service->shutdown_) return;
+    p->on_done_notified_ =
+        CallableTag(std::bind(&ReportLoadHandler::OnDoneNotified, p,
+                              std::placeholders::_1, std::placeholders::_2),
+                    handler);
+    p->next_inbound_ =
+        CallableTag(std::bind(&ReportLoadHandler::OnRequestDelivered, p,
+                              std::placeholders::_1, std::placeholders::_2),
+                    std::move(handler));
+    p->ctx_.AsyncNotifyWhenDone(&p->on_done_notified_);
+    service->RequestReportLoad(&p->ctx_, &p->stream_, cq, cq,
+                               &p->next_inbound_);
+  }
+}
+
+LoadReporterAsyncServiceImpl::ReportLoadHandler::ReportLoadHandler(
+    ServerCompletionQueue* cq, LoadReporterAsyncServiceImpl* service,
+    LoadReporter* load_reporter)
+    : cq_(cq),
+      service_(service),
+      load_reporter_(load_reporter),
+      stream_(&ctx_),
+      call_status_(WAITING_FOR_DELIVERY) {}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnRequestDelivered(
+    std::shared_ptr<ReportLoadHandler> self, bool ok) {
+  if (ok) {
+    call_status_ = DELIVERED;
+  } else {
+    // AsyncNotifyWhenDone() needs to be called before the call starts, but the
+    // tag will not pop out if the call never starts (
+    // https://github.com/grpc/grpc/issues/10136). So we need to manually
+    // release the ownership of the handler in this case.
+    GPR_ASSERT(on_done_notified_.ReleaseHandler() != nullptr);
+  }
+  if (!ok || shutdown_) {
+    // The value of ok being false means that the server is shutting down.
+    Shutdown(std::move(self), "OnRequestDelivered");
+    return;
+  }
+  // Spawn a new handler instance to serve the next new client. Every handler
+  // instance will deallocate itself when it's done.
+  CreateAndStart(cq_, service_, load_reporter_);
+  {
+    std::unique_lock<std::mutex> lock(service_->cq_shutdown_mu_);
+    if (service_->shutdown_) {
+      lock.release()->unlock();
+      Shutdown(std::move(self), "OnRequestDelivered");
+      return;
+    }
+    next_inbound_ =
+        CallableTag(std::bind(&ReportLoadHandler::OnReadDone, this,
+                              std::placeholders::_1, std::placeholders::_2),
+                    std::move(self));
+    stream_.Read(&request_, &next_inbound_);
+  }
+  // LB ID is unique for each load reporting stream.
+  lb_id_ = load_reporter_->GenerateLbId();
+  gpr_log(GPR_INFO,
+          "[LRS %p] Call request delivered (lb_id_: %s, handler: %p). "
+          "Start reading the initial request...",
+          service_, lb_id_.c_str(), this);
+}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnReadDone(
+    std::shared_ptr<ReportLoadHandler> self, bool ok) {
+  if (!ok || shutdown_) {
+    if (!ok && call_status_ < INITIAL_REQUEST_RECEIVED) {
+      // The client may have half-closed the stream or the stream is broken.
+      gpr_log(GPR_INFO,
+              "[LRS %p] Failed reading the initial request from the stream "
+              "(lb_id_: %s, handler: %p, done_notified: %d, is_cancelled: %d).",
+              service_, lb_id_.c_str(), this, static_cast<int>(done_notified_),
+              static_cast<int>(is_cancelled_));
+    }
+    Shutdown(std::move(self), "OnReadDone");
+    return;
+  }
+  // We only receive one request, which is the initial request.
+  if (call_status_ < INITIAL_REQUEST_RECEIVED) {
+    if (!request_.has_initial_request()) {
+      Shutdown(std::move(self), "OnReadDone+initial_request_not_found");
+    } else {
+      call_status_ = INITIAL_REQUEST_RECEIVED;
+      const auto& initial_request = request_.initial_request();
+      load_balanced_hostname_ = initial_request.load_balanced_hostname();
+      load_key_ = initial_request.load_key();
+      load_reporter_->ReportStreamCreated(load_balanced_hostname_, lb_id_,
+                                          load_key_);
+      const auto& load_report_interval = initial_request.load_report_interval();
+      load_report_interval_ms_ =
+          static_cast<uint64_t>(load_report_interval.seconds() * 1000 +
+                                load_report_interval.nanos() / 1000);
+      gpr_log(
+          GPR_INFO,
+          "[LRS %p] Initial request received. Start load reporting (load "
+          "balanced host: %s, interval: %lu ms, lb_id_: %s, handler: %p)...",
+          service_, load_balanced_hostname_.c_str(), load_report_interval_ms_,
+          lb_id_.c_str(), this);
+      SendReport(self, true /* ok */);
+      // Expect this read to fail.
+      {
+        std::unique_lock<std::mutex> lock(service_->cq_shutdown_mu_);
+        if (service_->shutdown_) {
+          lock.release()->unlock();
+          Shutdown(std::move(self), "OnReadDone");
+          return;
+        }
+        next_inbound_ =
+            CallableTag(std::bind(&ReportLoadHandler::OnReadDone, this,
+                                  std::placeholders::_1, std::placeholders::_2),
+                        std::move(self));
+        stream_.Read(&request_, &next_inbound_);
+      }
+    }
+  } else {
+    // Another request received! This violates the spec.
+    gpr_log(GPR_ERROR,
+            "[LRS %p] Another request received (lb_id_: %s, handler: %p).",
+            service_, lb_id_.c_str(), this);
+    Shutdown(std::move(self), "OnReadDone+second_request");
+  }
+}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::ScheduleNextReport(
+    std::shared_ptr<ReportLoadHandler> self, bool ok) {
+  if (!ok || shutdown_) {
+    Shutdown(std::move(self), "ScheduleNextReport");
+    return;
+  }
+  auto next_report_time = gpr_time_add(
+      gpr_now(GPR_CLOCK_MONOTONIC),
+      gpr_time_from_millis(load_report_interval_ms_, GPR_TIMESPAN));
+  {
+    std::unique_lock<std::mutex> lock(service_->cq_shutdown_mu_);
+    if (service_->shutdown_) {
+      lock.release()->unlock();
+      Shutdown(std::move(self), "ScheduleNextReport");
+      return;
+    }
+    next_outbound_ =
+        CallableTag(std::bind(&ReportLoadHandler::SendReport, this,
+                              std::placeholders::_1, std::placeholders::_2),
+                    std::move(self));
+    // TODO(juanlishen): Improve the Alarm implementation to reuse a single
+    // instance for multiple events.
+    next_report_alarm_.reset(new Alarm);
+    next_report_alarm_->Set(cq_, next_report_time, &next_outbound_);
+  }
+  gpr_log(GPR_DEBUG,
+          "[LRS %p] Next load report scheduled (lb_id_: %s, handler: %p).",
+          service_, lb_id_.c_str(), this);
+}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::SendReport(
+    std::shared_ptr<ReportLoadHandler> self, bool ok) {
+  if (!ok || shutdown_) {
+    Shutdown(std::move(self), "SendReport");
+    return;
+  }
+  ::grpc::lb::v1::LoadReportResponse response;
+  auto loads = load_reporter_->GenerateLoads(load_balanced_hostname_, lb_id_);
+  response.mutable_load()->Swap(&loads);
+  auto feedback = load_reporter_->GenerateLoadBalancingFeedback();
+  response.mutable_load_balancing_feedback()->Swap(&feedback);
+  if (call_status_ < INITIAL_RESPONSE_SENT) {
+    auto initial_response = response.mutable_initial_response();
+    initial_response->set_load_balancer_id(lb_id_);
+    initial_response->set_implementation_id(
+        ::grpc::lb::v1::InitialLoadReportResponse::CPP);
+    initial_response->set_server_version(kVersion);
+    call_status_ = INITIAL_RESPONSE_SENT;
+  }
+  {
+    std::unique_lock<std::mutex> lock(service_->cq_shutdown_mu_);
+    if (service_->shutdown_) {
+      lock.release()->unlock();
+      Shutdown(std::move(self), "SendReport");
+      return;
+    }
+    next_outbound_ =
+        CallableTag(std::bind(&ReportLoadHandler::ScheduleNextReport, this,
+                              std::placeholders::_1, std::placeholders::_2),
+                    std::move(self));
+    stream_.Write(response, &next_outbound_);
+    gpr_log(GPR_INFO,
+            "[LRS %p] Sending load report (lb_id_: %s, handler: %p, loads "
+            "count: %d)...",
+            service_, lb_id_.c_str(), this, response.load().size());
+  }
+}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnDoneNotified(
+    std::shared_ptr<ReportLoadHandler> self, bool ok) {
+  GPR_ASSERT(ok);
+  done_notified_ = true;
+  if (ctx_.IsCancelled()) {
+    is_cancelled_ = true;
+  }
+  gpr_log(GPR_INFO,
+          "[LRS %p] Load reporting call is notified done (handler: %p, "
+          "is_cancelled: %d).",
+          service_, this, static_cast<int>(is_cancelled_));
+  Shutdown(std::move(self), "OnDoneNotified");
+}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::Shutdown(
+    std::shared_ptr<ReportLoadHandler> self, const char* reason) {
+  if (!shutdown_) {
+    gpr_log(GPR_INFO,
+            "[LRS %p] Shutting down the handler (lb_id_: %s, handler: %p, "
+            "reason: %s).",
+            service_, lb_id_.c_str(), this, reason);
+    shutdown_ = true;
+    if (call_status_ >= INITIAL_REQUEST_RECEIVED) {
+      load_reporter_->ReportStreamClosed(load_balanced_hostname_, lb_id_);
+      next_report_alarm_->Cancel();
+    }
+  }
+  // OnRequestDelivered() may be called after OnDoneNotified(), so we need to
+  // try to Finish() every time we are in Shutdown().
+  if (call_status_ >= DELIVERED && call_status_ < FINISH_CALLED) {
+    std::unique_lock<std::mutex> lock(service_->cq_shutdown_mu_);
+    if (!service_->shutdown_) {
+      on_finish_done_ =
+          CallableTag(std::bind(&ReportLoadHandler::OnFinishDone, this,
+                                std::placeholders::_1, std::placeholders::_2),
+                      std::move(self));
+      // TODO(juanlishen): Maybe add a message proto for the client to
+      // explicitly cancel the stream so that we can return OK status in such
+      // cases.
+      stream_.Finish(Status::CANCELLED, &on_finish_done_);
+      call_status_ = FINISH_CALLED;
+    }
+  }
+}
+
+void LoadReporterAsyncServiceImpl::ReportLoadHandler::OnFinishDone(
+    std::shared_ptr<ReportLoadHandler> self, bool ok) {
+  if (ok) {
+    gpr_log(GPR_INFO,
+            "[LRS %p] Load reporting finished (lb_id_: %s, handler: %p).",
+            service_, lb_id_.c_str(), this);
+  }
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporter_async_service_impl.h b/third_party/grpc/src/cpp/server/load_reporter/load_reporter_async_service_impl.h
new file mode 100644
index 0000000..6fc577f
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporter_async_service_impl.h
@@ -0,0 +1,194 @@
+/*
+ *
+ * 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 GRPC_SRC_CPP_SERVER_LOAD_REPORTER_ASYNC_SERVICE_IMPL_H
+#define GRPC_SRC_CPP_SERVER_LOAD_REPORTER_ASYNC_SERVICE_IMPL_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpc/support/log.h>
+#include <grpcpp/alarm.h>
+#include <grpcpp/grpcpp.h>
+
+#include "src/core/lib/gprpp/thd.h"
+#include "src/cpp/server/load_reporter/load_reporter.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// Async load reporting service. It's mainly responsible for controlling the
+// procedure of incoming requests. The real business logic is handed off to the
+// LoadReporter. There should be at most one instance of this service on a
+// server to avoid spreading the load data into multiple places.
+class LoadReporterAsyncServiceImpl
+    : public grpc::lb::v1::LoadReporter::AsyncService {
+ public:
+  explicit LoadReporterAsyncServiceImpl(
+      std::unique_ptr<ServerCompletionQueue> cq);
+  ~LoadReporterAsyncServiceImpl();
+
+  // Starts the working thread.
+  void StartThread();
+
+  // Not copyable nor movable.
+  LoadReporterAsyncServiceImpl(const LoadReporterAsyncServiceImpl&) = delete;
+  LoadReporterAsyncServiceImpl& operator=(const LoadReporterAsyncServiceImpl&) =
+      delete;
+
+ private:
+  class ReportLoadHandler;
+
+  // A tag that can be called with a bool argument. It's tailored for
+  // ReportLoadHandler's use. Before being used, it should be constructed with a
+  // method of ReportLoadHandler and a shared pointer to the handler. The
+  // shared pointer will be moved to the invoked function and the function can
+  // only be invoked once. That makes ref counting of the handler easier,
+  // because the shared pointer is not bound to the function and can be gone
+  // once the invoked function returns (if not used any more).
+  class CallableTag {
+   public:
+    using HandlerFunction =
+        std::function<void(std::shared_ptr<ReportLoadHandler>, bool)>;
+
+    CallableTag() {}
+
+    CallableTag(HandlerFunction func,
+                std::shared_ptr<ReportLoadHandler> handler)
+        : handler_function_(std::move(func)), handler_(std::move(handler)) {
+      GPR_ASSERT(handler_function_ != nullptr);
+      GPR_ASSERT(handler_ != nullptr);
+    }
+
+    // Runs the tag. This should be called only once. The handler is no longer
+    // owned by this tag after this method is invoked.
+    void Run(bool ok);
+
+    // Releases and returns the shared pointer to the handler.
+    std::shared_ptr<ReportLoadHandler> ReleaseHandler() {
+      return std::move(handler_);
+    }
+
+   private:
+    HandlerFunction handler_function_ = nullptr;
+    std::shared_ptr<ReportLoadHandler> handler_;
+  };
+
+  // Each handler takes care of one load reporting stream. It contains
+  // per-stream data and it will access the members of the parent class (i.e.,
+  // LoadReporterAsyncServiceImpl) for service-wide data (e.g., the load data).
+  class ReportLoadHandler {
+   public:
+    // Instantiates a ReportLoadHandler and requests the next load reporting
+    // call. The handler object will manage its own lifetime, so no action is
+    // needed from the caller any more regarding that object.
+    static void CreateAndStart(ServerCompletionQueue* cq,
+                               LoadReporterAsyncServiceImpl* service,
+                               LoadReporter* load_reporter);
+
+    // This ctor is public because we want to use std::make_shared<> in
+    // CreateAndStart(). This ctor shouldn't be used elsewhere.
+    ReportLoadHandler(ServerCompletionQueue* cq,
+                      LoadReporterAsyncServiceImpl* service,
+                      LoadReporter* load_reporter);
+
+   private:
+    // After the handler has a call request delivered, it starts reading the
+    // initial request. Also, a new handler is spawned so that we can keep
+    // servicing future calls.
+    void OnRequestDelivered(std::shared_ptr<ReportLoadHandler> self, bool ok);
+
+    // The first Read() is expected to succeed, after which the handler starts
+    // sending load reports back to the balancer. The second Read() is
+    // expected to fail, which happens when the balancer half-closes the
+    // stream to signal that it's no longer interested in the load reports. For
+    // the latter case, the handler will then close the stream.
+    void OnReadDone(std::shared_ptr<ReportLoadHandler> self, bool ok);
+
+    // The report sending operations are sequential as: send report -> send
+    // done, schedule the next send -> waiting for the alarm to fire -> alarm
+    // fires, send report -> ...
+    void SendReport(std::shared_ptr<ReportLoadHandler> self, bool ok);
+    void ScheduleNextReport(std::shared_ptr<ReportLoadHandler> self, bool ok);
+
+    // Called when Finish() is done.
+    void OnFinishDone(std::shared_ptr<ReportLoadHandler> self, bool ok);
+
+    // Called when AsyncNotifyWhenDone() notifies us.
+    void OnDoneNotified(std::shared_ptr<ReportLoadHandler> self, bool ok);
+
+    void Shutdown(std::shared_ptr<ReportLoadHandler> self, const char* reason);
+
+    // The key fields of the stream.
+    grpc::string lb_id_;
+    grpc::string load_balanced_hostname_;
+    grpc::string load_key_;
+    uint64_t load_report_interval_ms_;
+
+    // The data for RPC communication with the load reportee.
+    ServerContext ctx_;
+    ::grpc::lb::v1::LoadReportRequest request_;
+
+    // The members passed down from LoadReporterAsyncServiceImpl.
+    ServerCompletionQueue* cq_;
+    LoadReporterAsyncServiceImpl* service_;
+    LoadReporter* load_reporter_;
+    ServerAsyncReaderWriter<::grpc::lb::v1::LoadReportResponse,
+                            ::grpc::lb::v1::LoadReportRequest>
+        stream_;
+
+    // The status of the RPC progress.
+    enum CallStatus {
+      WAITING_FOR_DELIVERY,
+      DELIVERED,
+      INITIAL_REQUEST_RECEIVED,
+      INITIAL_RESPONSE_SENT,
+      FINISH_CALLED
+    } call_status_;
+    bool shutdown_{false};
+    bool done_notified_{false};
+    bool is_cancelled_{false};
+    CallableTag on_done_notified_;
+    CallableTag on_finish_done_;
+    CallableTag next_inbound_;
+    CallableTag next_outbound_;
+    std::unique_ptr<Alarm> next_report_alarm_;
+  };
+
+  // Handles the incoming requests and drives the completion queue in a loop.
+  static void Work(void* arg);
+
+  // Schedules the next data fetching from Census and LB feedback sampling.
+  void ScheduleNextFetchAndSample();
+
+  // Fetches data from Census and samples LB feedback.
+  void FetchAndSample(bool ok);
+
+  std::unique_ptr<ServerCompletionQueue> cq_;
+  // To synchronize the operations related to shutdown state of cq_, so that we
+  // don't enqueue new tags into cq_ after it is already shut down.
+  std::mutex cq_shutdown_mu_;
+  std::atomic_bool shutdown_{false};
+  std::unique_ptr<::grpc_core::Thread> thread_;
+  std::unique_ptr<LoadReporter> load_reporter_;
+  std::unique_ptr<Alarm> next_fetch_and_sample_alarm_;
+};
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_SERVER_LOAD_REPORTER_ASYNC_SERVICE_IMPL_H
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc b/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc
new file mode 100644
index 0000000..81cf6ac
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_option.cc
@@ -0,0 +1,41 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include <grpcpp/ext/server_load_reporting.h>
+
+#include "src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h"
+
+namespace grpc {
+namespace load_reporter {
+namespace experimental {
+
+void LoadReportingServiceServerBuilderOption::UpdateArguments(
+    ::grpc::ChannelArguments* args) {
+  args->SetInt(GRPC_ARG_ENABLE_LOAD_REPORTING, true);
+}
+
+void LoadReportingServiceServerBuilderOption::UpdatePlugins(
+    std::vector<std::unique_ptr<::grpc::ServerBuilderPlugin>>* plugins) {
+  plugins->emplace_back(new LoadReportingServiceServerBuilderPlugin());
+}
+
+}  // namespace experimental
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.cc b/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.cc
new file mode 100644
index 0000000..c2c5dd5
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.cc
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+
+#include "src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h"
+
+#include <grpcpp/impl/server_initializer.h>
+
+namespace grpc {
+namespace load_reporter {
+
+bool LoadReportingServiceServerBuilderPlugin::has_sync_methods() const {
+  if (service_ != nullptr) {
+    return service_->has_synchronous_methods();
+  }
+  return false;
+}
+
+bool LoadReportingServiceServerBuilderPlugin::has_async_methods() const {
+  if (service_ != nullptr) {
+    return service_->has_async_methods();
+  }
+  return false;
+}
+
+void LoadReportingServiceServerBuilderPlugin::UpdateServerBuilder(
+    grpc::ServerBuilder* builder) {
+  auto cq = builder->AddCompletionQueue();
+  service_ = std::make_shared<LoadReporterAsyncServiceImpl>(std::move(cq));
+}
+
+void LoadReportingServiceServerBuilderPlugin::InitServer(
+    grpc::ServerInitializer* si) {
+  si->RegisterService(service_);
+}
+
+void LoadReportingServiceServerBuilderPlugin::Finish(
+    grpc::ServerInitializer* si) {
+  service_->StartThread();
+  service_.reset();
+}
+
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h b/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h
new file mode 100644
index 0000000..1f09859
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/load_reporting_service_server_builder_plugin.h
@@ -0,0 +1,62 @@
+/*
+ *
+ * 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 GRPC_SRC_CPP_LOAD_REPORTING_SERVICE_SERVER_BUILDER_PLUGIN_H
+#define GRPC_SRC_CPP_LOAD_REPORTING_SERVICE_SERVER_BUILDER_PLUGIN_H
+
+#include <grpc/support/port_platform.h>
+
+#include <grpcpp/impl/server_builder_plugin.h>
+
+#include "src/cpp/server/load_reporter/load_reporter_async_service_impl.h"
+
+namespace grpc {
+namespace load_reporter {
+
+// The plugin that registers and starts load reporting service when starting a
+// server.
+class LoadReportingServiceServerBuilderPlugin : public ServerBuilderPlugin {
+ public:
+  ~LoadReportingServiceServerBuilderPlugin() override = default;
+  grpc::string name() override { return "load_reporting_service"; }
+
+  // Creates a load reporting service.
+  void UpdateServerBuilder(grpc::ServerBuilder* builder) override;
+
+  // Registers the load reporter service.
+  void InitServer(grpc::ServerInitializer* si) override;
+
+  // Starts the load reporter service.
+  void Finish(grpc::ServerInitializer* si) override;
+
+  void ChangeArguments(const grpc::string& name, void* value) override {}
+  void UpdateChannelArguments(grpc::ChannelArguments* args) override {}
+  bool has_sync_methods() const override;
+  bool has_async_methods() const override;
+
+ private:
+  std::shared_ptr<LoadReporterAsyncServiceImpl> service_;
+};
+
+std::unique_ptr<grpc::ServerBuilderPlugin>
+CreateLoadReportingServiceServerBuilderPlugin();
+
+}  // namespace load_reporter
+}  // namespace grpc
+
+#endif  // GRPC_SRC_CPP_LOAD_REPORTING_SERVICE_SERVER_BUILDER_PLUGIN_H
diff --git a/third_party/grpc/src/cpp/server/load_reporter/util.cc b/third_party/grpc/src/cpp/server/load_reporter/util.cc
new file mode 100644
index 0000000..89bdf57
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/load_reporter/util.cc
@@ -0,0 +1,47 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/impl/codegen/port_platform.h>
+
+#include <grpcpp/ext/server_load_reporting.h>
+
+#include <cmath>
+
+#include <grpc/support/log.h>
+
+namespace grpc {
+namespace load_reporter {
+namespace experimental {
+
+void AddLoadReportingCost(grpc::ServerContext* ctx,
+                          const grpc::string& cost_name, double cost_value) {
+  if (std::isnormal(cost_value)) {
+    grpc::string buf;
+    buf.resize(sizeof(cost_value) + cost_name.size());
+    memcpy(&(*buf.begin()), &cost_value, sizeof(cost_value));
+    memcpy(&(*buf.begin()) + sizeof(cost_value), cost_name.data(),
+           cost_name.size());
+    ctx->AddTrailingMetadata(GRPC_LB_COST_MD_KEY, buf);
+  } else {
+    gpr_log(GPR_ERROR, "Call metric value is not normal.");
+  }
+}
+
+}  // namespace experimental
+}  // namespace load_reporter
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/secure_server_credentials.cc b/third_party/grpc/src/cpp/server/secure_server_credentials.cc
index d472667..453e76e 100644
--- a/third_party/grpc/src/cpp/server/secure_server_credentials.cc
+++ b/third_party/grpc/src/cpp/server/secure_server_credentials.cc
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -35,31 +20,33 @@
 #include <map>
 #include <memory>
 
+#include <grpcpp/impl/codegen/slice.h>
+#include <grpcpp/security/auth_metadata_processor.h>
+
 #include "src/cpp/common/secure_auth_context.h"
 #include "src/cpp/server/secure_server_credentials.h"
 
-#include <grpc++/security/auth_metadata_processor.h>
-
 namespace grpc {
 
 void AuthMetadataProcessorAyncWrapper::Destroy(void* wrapper) {
-  auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
+  auto* w = static_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
   delete w;
 }
 
 void AuthMetadataProcessorAyncWrapper::Process(
     void* wrapper, grpc_auth_context* context, const grpc_metadata* md,
     size_t num_md, grpc_process_auth_metadata_done_cb cb, void* user_data) {
-  auto* w = reinterpret_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
+  auto* w = static_cast<AuthMetadataProcessorAyncWrapper*>(wrapper);
   if (!w->processor_) {
     // Early exit.
     cb(user_data, nullptr, 0, nullptr, 0, GRPC_STATUS_OK, nullptr);
     return;
   }
   if (w->processor_->IsBlocking()) {
-    w->thread_pool_->Add(
-        std::bind(&AuthMetadataProcessorAyncWrapper::InvokeProcessor, w,
-                  context, md, num_md, cb, user_data));
+    w->thread_pool_->Add([w, context, md, num_md, cb, user_data] {
+      w->AuthMetadataProcessorAyncWrapper::InvokeProcessor(context, md, num_md,
+                                                           cb, user_data);
+    });
   } else {
     // invoke directly.
     w->InvokeProcessor(context, md, num_md, cb, user_data);
@@ -71,10 +58,10 @@
     grpc_process_auth_metadata_done_cb cb, void* user_data) {
   AuthMetadataProcessor::InputMetadata metadata;
   for (size_t i = 0; i < num_md; i++) {
-    metadata.insert(std::make_pair(
-        md[i].key, grpc::string_ref(md[i].value, md[i].value_length)));
+    metadata.insert(std::make_pair(StringRefFromSlice(&md[i].key),
+                                   StringRefFromSlice(&md[i].value)));
   }
-  SecureAuthContext context(ctx, false);
+  SecureAuthContext context(ctx);
   AuthMetadataProcessor::OutputMetadata consumed_metadata;
   AuthMetadataProcessor::OutputMetadata response_metadata;
 
@@ -85,9 +72,8 @@
   for (auto it = consumed_metadata.begin(); it != consumed_metadata.end();
        ++it) {
     grpc_metadata md_entry;
-    md_entry.key = it->first.c_str();
-    md_entry.value = it->second.data();
-    md_entry.value_length = it->second.size();
+    md_entry.key = SliceReferencingString(it->first);
+    md_entry.value = SliceReferencingString(it->second);
     md_entry.flags = 0;
     consumed_md.push_back(md_entry);
   }
@@ -95,9 +81,8 @@
   for (auto it = response_metadata.begin(); it != response_metadata.end();
        ++it) {
     grpc_metadata md_entry;
-    md_entry.key = it->first.c_str();
-    md_entry.value = it->second.data();
-    md_entry.value_length = it->second.size();
+    md_entry.key = SliceReferencingString(it->first);
+    md_entry.value = SliceReferencingString(it->second);
     md_entry.flags = 0;
     response_md.push_back(md_entry);
   }
@@ -130,12 +115,36 @@
                                     key_cert_pair->cert_chain.c_str()};
     pem_key_cert_pairs.push_back(p);
   }
-  grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create(
+  grpc_server_credentials* c_creds = grpc_ssl_server_credentials_create_ex(
       options.pem_root_certs.empty() ? nullptr : options.pem_root_certs.c_str(),
       pem_key_cert_pairs.empty() ? nullptr : &pem_key_cert_pairs[0],
-      pem_key_cert_pairs.size(), options.force_client_auth, nullptr);
+      pem_key_cert_pairs.size(),
+      options.force_client_auth
+          ? GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY
+          : options.client_certificate_request,
+      nullptr);
   return std::shared_ptr<ServerCredentials>(
       new SecureServerCredentials(c_creds));
 }
 
+namespace experimental {
+
+std::shared_ptr<ServerCredentials> AltsServerCredentials(
+    const AltsServerCredentialsOptions& options) {
+  grpc_alts_credentials_options* c_options =
+      grpc_alts_credentials_server_options_create();
+  grpc_server_credentials* c_creds =
+      grpc_alts_server_credentials_create(c_options);
+  grpc_alts_credentials_options_destroy(c_options);
+  return std::shared_ptr<ServerCredentials>(
+      new SecureServerCredentials(c_creds));
+}
+
+std::shared_ptr<ServerCredentials> LocalServerCredentials(
+    grpc_local_connect_type type) {
+  return std::shared_ptr<ServerCredentials>(
+      new SecureServerCredentials(grpc_local_server_credentials_create(type)));
+}
+
+}  // namespace experimental
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/secure_server_credentials.h b/third_party/grpc/src/cpp/server/secure_server_credentials.h
index 5460f4a..8a81af2 100644
--- a/third_party/grpc/src/cpp/server/secure_server_credentials.h
+++ b/third_party/grpc/src/cpp/server/secure_server_credentials.h
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -36,7 +21,7 @@
 
 #include <memory>
 
-#include <grpc++/security/server_credentials.h>
+#include <grpcpp/security/server_credentials.h>
 
 #include <grpc/grpc_security.h>
 
@@ -44,7 +29,7 @@
 
 namespace grpc {
 
-class AuthMetadataProcessorAyncWrapper GRPC_FINAL {
+class AuthMetadataProcessorAyncWrapper final {
  public:
   static void Destroy(void* wrapper);
 
@@ -64,19 +49,18 @@
   std::shared_ptr<AuthMetadataProcessor> processor_;
 };
 
-class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
+class SecureServerCredentials final : public ServerCredentials {
  public:
   explicit SecureServerCredentials(grpc_server_credentials* creds)
       : creds_(creds) {}
-  ~SecureServerCredentials() GRPC_OVERRIDE {
+  ~SecureServerCredentials() override {
     grpc_server_credentials_release(creds_);
   }
 
-  int AddPortToServer(const grpc::string& addr,
-                      grpc_server* server) GRPC_OVERRIDE;
+  int AddPortToServer(const grpc::string& addr, grpc_server* server) override;
 
   void SetAuthMetadataProcessor(
-      const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE;
+      const std::shared_ptr<AuthMetadataProcessor>& processor) override;
 
  private:
   grpc_server_credentials* creds_;
diff --git a/third_party/grpc/src/cpp/server/server.cc b/third_party/grpc/src/cpp/server/server.cc
deleted file mode 100644
index 0d31140..0000000
--- a/third_party/grpc/src/cpp/server/server.cc
+++ /dev/null
@@ -1,588 +0,0 @@
-/*
- *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/server.h>
-
-#include <utility>
-
-#include <grpc++/completion_queue.h>
-#include <grpc++/generic/async_generic_service.h>
-#include <grpc++/impl/codegen/completion_queue_tag.h>
-#include <grpc++/impl/grpc_library.h>
-#include <grpc++/impl/method_handler_impl.h>
-#include <grpc++/impl/rpc_service_method.h>
-#include <grpc++/impl/service_type.h>
-#include <grpc++/security/server_credentials.h>
-#include <grpc++/server_context.h>
-#include <grpc++/support/time.h>
-#include <grpc/grpc.h>
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/profiling/timers.h"
-#include "src/cpp/server/thread_pool_interface.h"
-
-namespace grpc {
-
-class DefaultGlobalCallbacks GRPC_FINAL : public Server::GlobalCallbacks {
- public:
-  ~DefaultGlobalCallbacks() GRPC_OVERRIDE {}
-  void PreSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
-  void PostSynchronousRequest(ServerContext* context) GRPC_OVERRIDE {}
-};
-
-static std::shared_ptr<Server::GlobalCallbacks> g_callbacks = nullptr;
-static gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
-
-static void InitGlobalCallbacks() {
-  if (g_callbacks == nullptr) {
-    g_callbacks.reset(new DefaultGlobalCallbacks());
-  }
-}
-
-class Server::UnimplementedAsyncRequestContext {
- protected:
-  UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {}
-
-  GenericServerContext server_context_;
-  GenericServerAsyncReaderWriter generic_stream_;
-};
-
-class Server::UnimplementedAsyncRequest GRPC_FINAL
-    : public UnimplementedAsyncRequestContext,
-      public GenericAsyncRequest {
- public:
-  UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq)
-      : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq,
-                            NULL, false),
-        server_(server),
-        cq_(cq) {}
-
-  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
-
-  ServerContext* context() { return &server_context_; }
-  GenericServerAsyncReaderWriter* stream() { return &generic_stream_; }
-
- private:
-  Server* const server_;
-  ServerCompletionQueue* const cq_;
-};
-
-typedef SneakyCallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus>
-    UnimplementedAsyncResponseOp;
-class Server::UnimplementedAsyncResponse GRPC_FINAL
-    : public UnimplementedAsyncResponseOp {
- public:
-  UnimplementedAsyncResponse(UnimplementedAsyncRequest* request);
-  ~UnimplementedAsyncResponse() { delete request_; }
-
-  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
-    bool r = UnimplementedAsyncResponseOp::FinalizeResult(tag, status);
-    delete this;
-    return r;
-  }
-
- private:
-  UnimplementedAsyncRequest* const request_;
-};
-
-class Server::ShutdownRequest GRPC_FINAL : public CompletionQueueTag {
- public:
-  bool FinalizeResult(void** tag, bool* status) {
-    delete this;
-    return false;
-  }
-};
-
-class Server::SyncRequest GRPC_FINAL : public CompletionQueueTag {
- public:
-  SyncRequest(RpcServiceMethod* method, void* tag)
-      : method_(method),
-        tag_(tag),
-        in_flight_(false),
-        has_request_payload_(method->method_type() == RpcMethod::NORMAL_RPC ||
-                             method->method_type() ==
-                                 RpcMethod::SERVER_STREAMING),
-        call_details_(nullptr),
-        cq_(nullptr) {
-    grpc_metadata_array_init(&request_metadata_);
-  }
-
-  ~SyncRequest() {
-    if (call_details_) {
-      delete call_details_;
-    }
-    grpc_metadata_array_destroy(&request_metadata_);
-  }
-
-  static SyncRequest* Wait(CompletionQueue* cq, bool* ok) {
-    void* tag = nullptr;
-    *ok = false;
-    if (!cq->Next(&tag, ok)) {
-      return nullptr;
-    }
-    auto* mrd = static_cast<SyncRequest*>(tag);
-    GPR_ASSERT(mrd->in_flight_);
-    return mrd;
-  }
-
-  static bool AsyncWait(CompletionQueue* cq, SyncRequest** req, bool* ok,
-                        gpr_timespec deadline) {
-    void* tag = nullptr;
-    *ok = false;
-    switch (cq->AsyncNext(&tag, ok, deadline)) {
-      case CompletionQueue::TIMEOUT:
-        *req = nullptr;
-        return true;
-      case CompletionQueue::SHUTDOWN:
-        *req = nullptr;
-        return false;
-      case CompletionQueue::GOT_EVENT:
-        *req = static_cast<SyncRequest*>(tag);
-        GPR_ASSERT((*req)->in_flight_);
-        return true;
-    }
-    GPR_UNREACHABLE_CODE(return false);
-  }
-
-  void SetupRequest() { cq_ = grpc_completion_queue_create(nullptr); }
-
-  void TeardownRequest() {
-    grpc_completion_queue_destroy(cq_);
-    cq_ = nullptr;
-  }
-
-  void Request(grpc_server* server, grpc_completion_queue* notify_cq) {
-    GPR_ASSERT(cq_ && !in_flight_);
-    in_flight_ = true;
-    if (tag_) {
-      GPR_ASSERT(GRPC_CALL_OK ==
-                 grpc_server_request_registered_call(
-                     server, tag_, &call_, &deadline_, &request_metadata_,
-                     has_request_payload_ ? &request_payload_ : nullptr, cq_,
-                     notify_cq, this));
-    } else {
-      if (!call_details_) {
-        call_details_ = new grpc_call_details;
-        grpc_call_details_init(call_details_);
-      }
-      GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
-                                     server, &call_, call_details_,
-                                     &request_metadata_, cq_, notify_cq, this));
-    }
-  }
-
-  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE {
-    if (!*status) {
-      grpc_completion_queue_destroy(cq_);
-    }
-    if (call_details_) {
-      deadline_ = call_details_->deadline;
-      grpc_call_details_destroy(call_details_);
-      grpc_call_details_init(call_details_);
-    }
-    return true;
-  }
-
-  class CallData GRPC_FINAL {
-   public:
-    explicit CallData(Server* server, SyncRequest* mrd)
-        : cq_(mrd->cq_),
-          call_(mrd->call_, server, &cq_, server->max_message_size_),
-          ctx_(mrd->deadline_, mrd->request_metadata_.metadata,
-               mrd->request_metadata_.count),
-          has_request_payload_(mrd->has_request_payload_),
-          request_payload_(mrd->request_payload_),
-          method_(mrd->method_) {
-      ctx_.set_call(mrd->call_);
-      ctx_.cq_ = &cq_;
-      GPR_ASSERT(mrd->in_flight_);
-      mrd->in_flight_ = false;
-      mrd->request_metadata_.count = 0;
-    }
-
-    ~CallData() {
-      if (has_request_payload_ && request_payload_) {
-        grpc_byte_buffer_destroy(request_payload_);
-      }
-    }
-
-    void Run(std::shared_ptr<GlobalCallbacks> global_callbacks) {
-      ctx_.BeginCompletionOp(&call_);
-      global_callbacks->PreSynchronousRequest(&ctx_);
-      method_->handler()->RunHandler(MethodHandler::HandlerParameter(
-          &call_, &ctx_, request_payload_, call_.max_message_size()));
-      global_callbacks->PostSynchronousRequest(&ctx_);
-      request_payload_ = nullptr;
-      void* ignored_tag;
-      bool ignored_ok;
-      cq_.Shutdown();
-      GPR_ASSERT(cq_.Next(&ignored_tag, &ignored_ok) == false);
-    }
-
-   private:
-    CompletionQueue cq_;
-    Call call_;
-    ServerContext ctx_;
-    const bool has_request_payload_;
-    grpc_byte_buffer* request_payload_;
-    RpcServiceMethod* const method_;
-  };
-
- private:
-  RpcServiceMethod* const method_;
-  void* const tag_;
-  bool in_flight_;
-  const bool has_request_payload_;
-  grpc_call* call_;
-  grpc_call_details* call_details_;
-  gpr_timespec deadline_;
-  grpc_metadata_array request_metadata_;
-  grpc_byte_buffer* request_payload_;
-  grpc_completion_queue* cq_;
-};
-
-static grpc_server* CreateServer(const ChannelArguments& args) {
-  grpc_channel_args channel_args;
-  args.SetChannelArgs(&channel_args);
-  return grpc_server_create(&channel_args, nullptr);
-}
-
-static internal::GrpcLibraryInitializer g_gli_initializer;
-Server::Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
-               int max_message_size, const ChannelArguments& args)
-    : max_message_size_(max_message_size),
-      started_(false),
-      shutdown_(false),
-      num_running_cb_(0),
-      sync_methods_(new std::list<SyncRequest>),
-      has_generic_service_(false),
-      server_(CreateServer(args)),
-      thread_pool_(thread_pool),
-      thread_pool_owned_(thread_pool_owned) {
-  g_gli_initializer.summon();
-  gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
-  global_callbacks_ = g_callbacks;
-  grpc_server_register_completion_queue(server_, cq_.cq(), nullptr);
-}
-
-Server::~Server() {
-  {
-    grpc::unique_lock<grpc::mutex> lock(mu_);
-    if (started_ && !shutdown_) {
-      lock.unlock();
-      Shutdown();
-    } else if (!started_) {
-      cq_.Shutdown();
-    }
-  }
-  void* got_tag;
-  bool ok;
-  GPR_ASSERT(!cq_.Next(&got_tag, &ok));
-  grpc_server_destroy(server_);
-  if (thread_pool_owned_) {
-    delete thread_pool_;
-  }
-  delete sync_methods_;
-}
-
-void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
-  GPR_ASSERT(g_callbacks == nullptr);
-  GPR_ASSERT(callbacks != nullptr);
-  g_callbacks.reset(callbacks);
-}
-
-bool Server::RegisterService(const grpc::string* host, Service* service) {
-  bool has_async_methods = service->has_async_methods();
-  if (has_async_methods) {
-    GPR_ASSERT(service->server_ == nullptr &&
-               "Can only register an asynchronous service against one server.");
-    service->server_ = this;
-  }
-  for (auto it = service->methods_.begin(); it != service->methods_.end();
-       ++it) {
-    if (it->get() == nullptr) {  // Handled by generic service if any.
-      continue;
-    }
-    RpcServiceMethod* method = it->get();
-    void* tag = grpc_server_register_method(server_, method->name(),
-                                            host ? host->c_str() : nullptr);
-    if (tag == nullptr) {
-      gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
-              method->name());
-      return false;
-    }
-    if (method->handler() == nullptr) {
-      method->set_server_tag(tag);
-    } else {
-      sync_methods_->emplace_back(method, tag);
-    }
-  }
-  return true;
-}
-
-void Server::RegisterAsyncGenericService(AsyncGenericService* service) {
-  GPR_ASSERT(service->server_ == nullptr &&
-             "Can only register an async generic service against one server.");
-  service->server_ = this;
-  has_generic_service_ = true;
-}
-
-int Server::AddListeningPort(const grpc::string& addr,
-                             ServerCredentials* creds) {
-  GPR_ASSERT(!started_);
-  return creds->AddPortToServer(addr, server_);
-}
-
-bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
-  GPR_ASSERT(!started_);
-  started_ = true;
-  grpc_server_start(server_);
-
-  if (!has_generic_service_) {
-    if (!sync_methods_->empty()) {
-      unknown_method_.reset(new RpcServiceMethod(
-          "unknown", RpcMethod::BIDI_STREAMING, new UnknownMethodHandler));
-      // Use of emplace_back with just constructor arguments is not accepted
-      // here by gcc-4.4 because it can't match the anonymous nullptr with a
-      // proper constructor implicitly. Construct the object and use push_back.
-      sync_methods_->push_back(SyncRequest(unknown_method_.get(), nullptr));
-    }
-    for (size_t i = 0; i < num_cqs; i++) {
-      new UnimplementedAsyncRequest(this, cqs[i]);
-    }
-  }
-  // Start processing rpcs.
-  if (!sync_methods_->empty()) {
-    for (auto m = sync_methods_->begin(); m != sync_methods_->end(); m++) {
-      m->SetupRequest();
-      m->Request(server_, cq_.cq());
-    }
-
-    ScheduleCallback();
-  }
-
-  return true;
-}
-
-void Server::ShutdownInternal(gpr_timespec deadline) {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
-  if (started_ && !shutdown_) {
-    shutdown_ = true;
-    grpc_server_shutdown_and_notify(server_, cq_.cq(), new ShutdownRequest());
-    cq_.Shutdown();
-    lock.unlock();
-    // Spin, eating requests until the completion queue is completely shutdown.
-    // If the deadline expires then cancel anything that's pending and keep
-    // spinning forever until the work is actually drained.
-    // Since nothing else needs to touch state guarded by mu_, holding it
-    // through this loop is fine.
-    SyncRequest* request;
-    bool ok;
-    while (SyncRequest::AsyncWait(&cq_, &request, &ok, deadline)) {
-      if (request == NULL) {  // deadline expired
-        grpc_server_cancel_all_calls(server_);
-        deadline = gpr_inf_future(GPR_CLOCK_MONOTONIC);
-      } else if (ok) {
-        SyncRequest::CallData call_data(this, request);
-      }
-    }
-    lock.lock();
-
-    // Wait for running callbacks to finish.
-    while (num_running_cb_ != 0) {
-      callback_cv_.wait(lock);
-    }
-  }
-}
-
-void Server::Wait() {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
-  while (num_running_cb_ != 0) {
-    callback_cv_.wait(lock);
-  }
-}
-
-void Server::PerformOpsOnCall(CallOpSetInterface* ops, Call* call) {
-  static const size_t MAX_OPS = 8;
-  size_t nops = 0;
-  grpc_op cops[MAX_OPS];
-  ops->FillOps(cops, &nops);
-  auto result = grpc_call_start_batch(call->call(), cops, nops, ops, nullptr);
-  GPR_ASSERT(GRPC_CALL_OK == result);
-}
-
-ServerInterface::BaseAsyncRequest::BaseAsyncRequest(
-    ServerInterface* server, ServerContext* context,
-    ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag,
-    bool delete_on_finalize)
-    : server_(server),
-      context_(context),
-      stream_(stream),
-      call_cq_(call_cq),
-      tag_(tag),
-      delete_on_finalize_(delete_on_finalize),
-      call_(nullptr) {
-  memset(&initial_metadata_array_, 0, sizeof(initial_metadata_array_));
-}
-
-bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
-                                                       bool* status) {
-  if (*status) {
-    for (size_t i = 0; i < initial_metadata_array_.count; i++) {
-      context_->client_metadata_.insert(
-          std::pair<grpc::string_ref, grpc::string_ref>(
-              initial_metadata_array_.metadata[i].key,
-              grpc::string_ref(
-                  initial_metadata_array_.metadata[i].value,
-                  initial_metadata_array_.metadata[i].value_length)));
-    }
-  }
-  grpc_metadata_array_destroy(&initial_metadata_array_);
-  context_->set_call(call_);
-  context_->cq_ = call_cq_;
-  Call call(call_, server_, call_cq_, server_->max_message_size());
-  if (*status && call_) {
-    context_->BeginCompletionOp(&call);
-  }
-  // just the pointers inside call are copied here
-  stream_->BindCall(&call);
-  *tag = tag_;
-  if (delete_on_finalize_) {
-    delete this;
-  }
-  return true;
-}
-
-ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest(
-    ServerInterface* server, ServerContext* context,
-    ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq, void* tag)
-    : BaseAsyncRequest(server, context, stream, call_cq, tag, true) {}
-
-void ServerInterface::RegisteredAsyncRequest::IssueRequest(
-    void* registered_method, grpc_byte_buffer** payload,
-    ServerCompletionQueue* notification_cq) {
-  grpc_server_request_registered_call(
-      server_->server(), registered_method, &call_, &context_->deadline_,
-      &initial_metadata_array_, payload, call_cq_->cq(), notification_cq->cq(),
-      this);
-}
-
-ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
-    ServerInterface* server, GenericServerContext* context,
-    ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
-    ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
-    : BaseAsyncRequest(server, context, stream, call_cq, tag,
-                       delete_on_finalize) {
-  grpc_call_details_init(&call_details_);
-  GPR_ASSERT(notification_cq);
-  GPR_ASSERT(call_cq);
-  grpc_server_request_call(server->server(), &call_, &call_details_,
-                           &initial_metadata_array_, call_cq->cq(),
-                           notification_cq->cq(), this);
-}
-
-bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag,
-                                                          bool* status) {
-  // TODO(yangg) remove the copy here.
-  if (*status) {
-    static_cast<GenericServerContext*>(context_)->method_ =
-        call_details_.method;
-    static_cast<GenericServerContext*>(context_)->host_ = call_details_.host;
-  }
-  gpr_free(call_details_.method);
-  gpr_free(call_details_.host);
-  return BaseAsyncRequest::FinalizeResult(tag, status);
-}
-
-bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag,
-                                                       bool* status) {
-  if (GenericAsyncRequest::FinalizeResult(tag, status) && *status) {
-    new UnimplementedAsyncRequest(server_, cq_);
-    new UnimplementedAsyncResponse(this);
-  } else {
-    delete this;
-  }
-  return false;
-}
-
-Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse(
-    UnimplementedAsyncRequest* request)
-    : request_(request) {
-  Status status(StatusCode::UNIMPLEMENTED, "");
-  UnknownMethodHandler::FillOps(request_->context(), this);
-  request_->stream()->call_.PerformOps(this);
-}
-
-void Server::ScheduleCallback() {
-  {
-    grpc::unique_lock<grpc::mutex> lock(mu_);
-    num_running_cb_++;
-  }
-  thread_pool_->Add(std::bind(&Server::RunRpc, this));
-}
-
-void Server::RunRpc() {
-  // Wait for one more incoming rpc.
-  bool ok;
-  GPR_TIMER_SCOPE("Server::RunRpc", 0);
-  auto* mrd = SyncRequest::Wait(&cq_, &ok);
-  if (mrd) {
-    ScheduleCallback();
-    if (ok) {
-      SyncRequest::CallData cd(this, mrd);
-      {
-        mrd->SetupRequest();
-        grpc::unique_lock<grpc::mutex> lock(mu_);
-        if (!shutdown_) {
-          mrd->Request(server_, cq_.cq());
-        } else {
-          // destroy the structure that was created
-          mrd->TeardownRequest();
-        }
-      }
-      GPR_TIMER_SCOPE("cd.Run()", 0);
-      cd.Run(global_callbacks_);
-    }
-  }
-
-  {
-    grpc::unique_lock<grpc::mutex> lock(mu_);
-    num_running_cb_--;
-    if (shutdown_) {
-      callback_cv_.notify_all();
-    }
-  }
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/server_builder.cc b/third_party/grpc/src/cpp/server/server_builder.cc
index a8c188e..0dc03b6 100644
--- a/third_party/grpc/src/cpp/server/server_builder.cc
+++ b/third_party/grpc/src/cpp/server/server_builder.cc
@@ -1,120 +1,346 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2015-2016 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/server_builder.h>
+#include <grpcpp/server_builder.h>
 
 #include <grpc/support/cpu.h>
 #include <grpc/support/log.h>
-#include <grpc++/impl/service_type.h>
-#include <grpc++/server.h>
+#include <grpcpp/impl/service_type.h>
+#include <grpcpp/resource_quota.h>
+#include <grpcpp/server.h>
+
+#include <utility>
+
+#include "src/core/lib/gpr/useful.h"
 #include "src/cpp/server/thread_pool_interface.h"
-#include "src/cpp/server/fixed_size_thread_pool.h"
 
 namespace grpc {
 
-ServerBuilder::ServerBuilder()
-    : max_message_size_(-1), generic_service_(nullptr) {
-  grpc_compression_options_init(&compression_options_);
+static std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>*
+    g_plugin_factory_list;
+static gpr_once once_init_plugin_list = GPR_ONCE_INIT;
+
+static void do_plugin_list_init(void) {
+  g_plugin_factory_list =
+      new std::vector<std::unique_ptr<ServerBuilderPlugin> (*)()>();
 }
 
-std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue() {
-  ServerCompletionQueue* cq = new ServerCompletionQueue();
+ServerBuilder::ServerBuilder()
+    : max_receive_message_size_(INT_MIN),
+      max_send_message_size_(INT_MIN),
+      sync_server_settings_(SyncServerSettings()),
+      resource_quota_(nullptr),
+      generic_service_(nullptr) {
+  gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
+  for (auto it = g_plugin_factory_list->begin();
+       it != g_plugin_factory_list->end(); it++) {
+    auto& factory = *it;
+    plugins_.emplace_back(factory());
+  }
+
+  // all compression algorithms enabled by default.
+  enabled_compression_algorithms_bitset_ =
+      (1u << GRPC_COMPRESS_ALGORITHMS_COUNT) - 1;
+  memset(&maybe_default_compression_level_, 0,
+         sizeof(maybe_default_compression_level_));
+  memset(&maybe_default_compression_algorithm_, 0,
+         sizeof(maybe_default_compression_algorithm_));
+}
+
+ServerBuilder::~ServerBuilder() {
+  if (resource_quota_ != nullptr) {
+    grpc_resource_quota_unref(resource_quota_);
+  }
+}
+
+std::unique_ptr<ServerCompletionQueue> ServerBuilder::AddCompletionQueue(
+    bool is_frequently_polled) {
+  ServerCompletionQueue* cq = new ServerCompletionQueue(
+      GRPC_CQ_NEXT,
+      is_frequently_polled ? GRPC_CQ_DEFAULT_POLLING : GRPC_CQ_NON_LISTENING,
+      nullptr);
   cqs_.push_back(cq);
   return std::unique_ptr<ServerCompletionQueue>(cq);
 }
 
-void ServerBuilder::RegisterService(Service* service) {
+ServerBuilder& ServerBuilder::RegisterService(Service* service) {
   services_.emplace_back(new NamedService(service));
+  return *this;
 }
 
-void ServerBuilder::RegisterService(const grpc::string& addr,
-                                    Service* service) {
+ServerBuilder& ServerBuilder::RegisterService(const grpc::string& addr,
+                                              Service* service) {
   services_.emplace_back(new NamedService(addr, service));
+  return *this;
 }
 
-void ServerBuilder::RegisterAsyncGenericService(AsyncGenericService* service) {
+ServerBuilder& ServerBuilder::RegisterAsyncGenericService(
+    AsyncGenericService* service) {
   if (generic_service_) {
     gpr_log(GPR_ERROR,
             "Adding multiple AsyncGenericService is unsupported for now. "
             "Dropping the service %p",
-            service);
-    return;
+            (void*)service);
+  } else {
+    generic_service_ = service;
   }
-  generic_service_ = service;
+  return *this;
 }
 
-void ServerBuilder::SetOption(std::unique_ptr<ServerBuilderOption> option) {
+ServerBuilder& ServerBuilder::SetOption(
+    std::unique_ptr<ServerBuilderOption> option) {
   options_.push_back(std::move(option));
+  return *this;
 }
 
-void ServerBuilder::AddListeningPort(const grpc::string& addr,
-                                     std::shared_ptr<ServerCredentials> creds,
-                                     int* selected_port) {
-  Port port = {addr, creds, selected_port};
+ServerBuilder& ServerBuilder::SetSyncServerOption(
+    ServerBuilder::SyncServerOption option, int val) {
+  switch (option) {
+    case NUM_CQS:
+      sync_server_settings_.num_cqs = val;
+      break;
+    case MIN_POLLERS:
+      sync_server_settings_.min_pollers = val;
+      break;
+    case MAX_POLLERS:
+      sync_server_settings_.max_pollers = val;
+      break;
+    case CQ_TIMEOUT_MSEC:
+      sync_server_settings_.cq_timeout_msec = val;
+      break;
+  }
+  return *this;
+}
+
+ServerBuilder& ServerBuilder::SetCompressionAlgorithmSupportStatus(
+    grpc_compression_algorithm algorithm, bool enabled) {
+  if (enabled) {
+    GPR_BITSET(&enabled_compression_algorithms_bitset_, algorithm);
+  } else {
+    GPR_BITCLEAR(&enabled_compression_algorithms_bitset_, algorithm);
+  }
+  return *this;
+}
+
+ServerBuilder& ServerBuilder::SetDefaultCompressionLevel(
+    grpc_compression_level level) {
+  maybe_default_compression_level_.level = level;
+  return *this;
+}
+
+ServerBuilder& ServerBuilder::SetDefaultCompressionAlgorithm(
+    grpc_compression_algorithm algorithm) {
+  maybe_default_compression_algorithm_.is_set = true;
+  maybe_default_compression_algorithm_.algorithm = algorithm;
+  return *this;
+}
+
+ServerBuilder& ServerBuilder::SetResourceQuota(
+    const grpc::ResourceQuota& resource_quota) {
+  if (resource_quota_ != nullptr) {
+    grpc_resource_quota_unref(resource_quota_);
+  }
+  resource_quota_ = resource_quota.c_resource_quota();
+  grpc_resource_quota_ref(resource_quota_);
+  return *this;
+}
+
+ServerBuilder& ServerBuilder::AddListeningPort(
+    const grpc::string& addr_uri, std::shared_ptr<ServerCredentials> creds,
+    int* selected_port) {
+  const grpc::string uri_scheme = "dns:";
+  grpc::string addr = addr_uri;
+  if (addr_uri.compare(0, uri_scheme.size(), uri_scheme) == 0) {
+    size_t pos = uri_scheme.size();
+    while (addr_uri[pos] == '/') ++pos;  // Skip slashes.
+    addr = addr_uri.substr(pos);
+  }
+  Port port = {addr, std::move(creds), selected_port};
   ports_.push_back(port);
+  return *this;
 }
 
 std::unique_ptr<Server> ServerBuilder::BuildAndStart() {
-  std::unique_ptr<ThreadPoolInterface> thread_pool;
+  ChannelArguments args;
+  for (auto option = options_.begin(); option != options_.end(); ++option) {
+    (*option)->UpdateArguments(&args);
+    (*option)->UpdatePlugins(&plugins_);
+  }
+
+  for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
+    (*plugin)->UpdateServerBuilder(this);
+    (*plugin)->UpdateChannelArguments(&args);
+  }
+
+  if (max_receive_message_size_ >= -1) {
+    args.SetInt(GRPC_ARG_MAX_RECEIVE_MESSAGE_LENGTH, max_receive_message_size_);
+  }
+
+  // The default message size is -1 (max), so no need to explicitly set it for
+  // -1.
+  if (max_send_message_size_ >= 0) {
+    args.SetInt(GRPC_ARG_MAX_SEND_MESSAGE_LENGTH, max_send_message_size_);
+  }
+
+  args.SetInt(GRPC_COMPRESSION_CHANNEL_ENABLED_ALGORITHMS_BITSET,
+              enabled_compression_algorithms_bitset_);
+  if (maybe_default_compression_level_.is_set) {
+    args.SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_LEVEL,
+                maybe_default_compression_level_.level);
+  }
+  if (maybe_default_compression_algorithm_.is_set) {
+    args.SetInt(GRPC_COMPRESSION_CHANNEL_DEFAULT_ALGORITHM,
+                maybe_default_compression_algorithm_.algorithm);
+  }
+
+  if (resource_quota_ != nullptr) {
+    args.SetPointerWithVtable(GRPC_ARG_RESOURCE_QUOTA, resource_quota_,
+                              grpc_resource_quota_arg_vtable());
+  }
+
+  // == Determine if the server has any syncrhonous methods ==
+  bool has_sync_methods = false;
   for (auto it = services_.begin(); it != services_.end(); ++it) {
     if ((*it)->service->has_synchronous_methods()) {
-      if (thread_pool == nullptr) {
-        thread_pool.reset(CreateDefaultThreadPool());
+      has_sync_methods = true;
+      break;
+    }
+  }
+
+  if (!has_sync_methods) {
+    for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
+      if ((*plugin)->has_sync_methods()) {
+        has_sync_methods = true;
         break;
       }
     }
   }
-  ChannelArguments args;
-  for (auto option = options_.begin(); option != options_.end(); ++option) {
-    (*option)->UpdateArguments(&args);
+
+  // If this is a Sync server, i.e a server expositing sync API, then the server
+  // needs to create some completion queues to listen for incoming requests.
+  // 'sync_server_cqs' are those internal completion queues.
+  //
+  // This is different from the completion queues added to the server via
+  // ServerBuilder's AddCompletionQueue() method (those completion queues
+  // are in 'cqs_' member variable of ServerBuilder object)
+  std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
+      sync_server_cqs(std::make_shared<
+                      std::vector<std::unique_ptr<ServerCompletionQueue>>>());
+
+  int num_frequently_polled_cqs = 0;
+  for (auto it = cqs_.begin(); it != cqs_.end(); ++it) {
+    if ((*it)->IsFrequentlyPolled()) {
+      num_frequently_polled_cqs++;
+    }
   }
-  if (max_message_size_ > 0) {
-    args.SetInt(GRPC_ARG_MAX_MESSAGE_LENGTH, max_message_size_);
+
+  const bool is_hybrid_server =
+      has_sync_methods && num_frequently_polled_cqs > 0;
+
+  if (has_sync_methods) {
+    grpc_cq_polling_type polling_type =
+        is_hybrid_server ? GRPC_CQ_NON_POLLING : GRPC_CQ_DEFAULT_POLLING;
+
+    // Create completion queues to listen to incoming rpc requests
+    for (int i = 0; i < sync_server_settings_.num_cqs; i++) {
+      sync_server_cqs->emplace_back(
+          new ServerCompletionQueue(GRPC_CQ_NEXT, polling_type, nullptr));
+    }
   }
-  args.SetInt(GRPC_COMPRESSION_ALGORITHM_STATE_ARG,
-              compression_options_.enabled_algorithms_bitset);
-  std::unique_ptr<Server> server(
-      new Server(thread_pool.release(), true, max_message_size_, args));
-  for (auto cq = cqs_.begin(); cq != cqs_.end(); ++cq) {
-    grpc_server_register_completion_queue(server->server_, (*cq)->cq(),
+
+  // == Determine if the server has any callback methods ==
+  bool has_callback_methods = false;
+  for (auto it = services_.begin(); it != services_.end(); ++it) {
+    if ((*it)->service->has_callback_methods()) {
+      has_callback_methods = true;
+      break;
+    }
+  }
+
+  // TODO(vjpai): Add a section here for plugins once they can support callback
+  // methods
+
+  if (has_sync_methods) {
+    // This is a Sync server
+    gpr_log(GPR_INFO,
+            "Synchronous server. Num CQs: %d, Min pollers: %d, Max Pollers: "
+            "%d, CQ timeout (msec): %d",
+            sync_server_settings_.num_cqs, sync_server_settings_.min_pollers,
+            sync_server_settings_.max_pollers,
+            sync_server_settings_.cq_timeout_msec);
+  }
+
+  if (has_callback_methods) {
+    gpr_log(GPR_INFO, "Callback server.");
+  }
+
+  std::unique_ptr<Server> server(new Server(
+      max_receive_message_size_, &args, sync_server_cqs,
+      sync_server_settings_.min_pollers, sync_server_settings_.max_pollers,
+      sync_server_settings_.cq_timeout_msec, resource_quota_,
+      std::move(interceptor_creators_)));
+
+  ServerInitializer* initializer = server->initializer();
+
+  // Register all the completion queues with the server. i.e
+  //  1. sync_server_cqs: internal completion queues created IF this is a sync
+  //     server
+  //  2. cqs_: Completion queues added via AddCompletionQueue() call
+
+  for (auto it = sync_server_cqs->begin(); it != sync_server_cqs->end(); ++it) {
+    grpc_server_register_completion_queue(server->server_, (*it)->cq(),
+                                          nullptr);
+    num_frequently_polled_cqs++;
+  }
+
+  if (has_callback_methods) {
+    auto* cq = server->CallbackCQ();
+    grpc_server_register_completion_queue(server->server_, cq->cq(), nullptr);
+    num_frequently_polled_cqs++;
+  }
+
+  // cqs_ contains the completion queue added by calling the ServerBuilder's
+  // AddCompletionQueue() API. Some of them may not be frequently polled (i.e by
+  // calling Next() or AsyncNext()) and hence are not safe to be used for
+  // listening to incoming channels. Such completion queues must be registered
+  // as non-listening queues
+  for (auto it = cqs_.begin(); it != cqs_.end(); ++it) {
+    grpc_server_register_completion_queue(server->server_, (*it)->cq(),
                                           nullptr);
   }
+
+  if (num_frequently_polled_cqs == 0) {
+    gpr_log(GPR_ERROR,
+            "At least one of the completion queues must be frequently polled");
+    return nullptr;
+  }
+
   for (auto service = services_.begin(); service != services_.end();
        service++) {
     if (!server->RegisterService((*service)->host.get(), (*service)->service)) {
       return nullptr;
     }
   }
+
+  for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
+    (*plugin)->InitServer(initializer);
+  }
+
   if (generic_service_) {
     server->RegisterAsyncGenericService(generic_service_);
   } else {
@@ -127,18 +353,44 @@
       }
     }
   }
+
+  bool added_port = false;
   for (auto port = ports_.begin(); port != ports_.end(); port++) {
     int r = server->AddListeningPort(port->addr, port->creds.get());
-    if (!r) return nullptr;
+    if (!r) {
+      if (added_port) server->Shutdown();
+      return nullptr;
+    }
+    added_port = true;
     if (port->selected_port != nullptr) {
       *port->selected_port = r;
     }
   }
+
   auto cqs_data = cqs_.empty() ? nullptr : &cqs_[0];
-  if (!server->Start(cqs_data, cqs_.size())) {
-    return nullptr;
+  server->Start(cqs_data, cqs_.size());
+
+  for (auto plugin = plugins_.begin(); plugin != plugins_.end(); plugin++) {
+    (*plugin)->Finish(initializer);
   }
+
   return server;
 }
 
+void ServerBuilder::InternalAddPluginFactory(
+    std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)()) {
+  gpr_once_init(&once_init_plugin_list, do_plugin_list_init);
+  (*g_plugin_factory_list).push_back(CreatePlugin);
+}
+
+ServerBuilder& ServerBuilder::EnableWorkaround(grpc_workaround_list id) {
+  switch (id) {
+    case GRPC_WORKAROUND_ID_CRONET_COMPRESSION:
+      return AddChannelArgument(GRPC_ARG_WORKAROUND_CRONET_COMPRESSION, 1);
+    default:
+      gpr_log(GPR_ERROR, "Workaround %u does not exist or is obsolete.", id);
+      return *this;
+  }
+}
+
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/server_cc.cc b/third_party/grpc/src/cpp/server/server_cc.cc
new file mode 100644
index 0000000..1e3c574
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/server_cc.cc
@@ -0,0 +1,1166 @@
+/*
+ * 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.
+ *
+ */
+
+#include <grpcpp/server.h>
+
+#include <cstdlib>
+#include <sstream>
+#include <utility>
+
+#include <grpc/grpc.h>
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/generic/async_generic_service.h>
+#include <grpcpp/impl/codegen/async_unary_call.h>
+#include <grpcpp/impl/codegen/call.h>
+#include <grpcpp/impl/codegen/completion_queue_tag.h>
+#include <grpcpp/impl/codegen/server_interceptor.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/impl/method_handler_impl.h>
+#include <grpcpp/impl/rpc_service_method.h>
+#include <grpcpp/impl/server_initializer.h>
+#include <grpcpp/impl/service_type.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server_context.h>
+#include <grpcpp/support/time.h>
+
+#include "src/core/ext/transport/inproc/inproc_transport.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+#include "src/core/lib/profiling/timers.h"
+#include "src/core/lib/surface/call.h"
+#include "src/core/lib/surface/completion_queue.h"
+#include "src/cpp/client/create_channel_internal.h"
+#include "src/cpp/server/health/default_health_check_service.h"
+#include "src/cpp/thread_manager/thread_manager.h"
+
+namespace grpc {
+namespace {
+
+// The default value for maximum number of threads that can be created in the
+// sync server. This value of INT_MAX is chosen to match the default behavior if
+// no ResourceQuota is set. To modify the max number of threads in a sync
+// server, pass a custom ResourceQuota object  (with the desired number of
+// max-threads set) to the server builder.
+#define DEFAULT_MAX_SYNC_SERVER_THREADS INT_MAX
+
+// How many callback requests of each method should we pre-register at start
+#define DEFAULT_CALLBACK_REQS_PER_METHOD 32
+
+class DefaultGlobalCallbacks final : public Server::GlobalCallbacks {
+ public:
+  ~DefaultGlobalCallbacks() override {}
+  void PreSynchronousRequest(ServerContext* context) override {}
+  void PostSynchronousRequest(ServerContext* context) override {}
+};
+
+std::shared_ptr<Server::GlobalCallbacks> g_callbacks = nullptr;
+gpr_once g_once_init_callbacks = GPR_ONCE_INIT;
+
+void InitGlobalCallbacks() {
+  if (!g_callbacks) {
+    g_callbacks.reset(new DefaultGlobalCallbacks());
+  }
+}
+
+class ShutdownTag : public internal::CompletionQueueTag {
+ public:
+  bool FinalizeResult(void** tag, bool* status) { return false; }
+};
+
+class DummyTag : public internal::CompletionQueueTag {
+ public:
+  bool FinalizeResult(void** tag, bool* status) { return true; }
+};
+
+class UnimplementedAsyncRequestContext {
+ protected:
+  UnimplementedAsyncRequestContext() : generic_stream_(&server_context_) {}
+
+  GenericServerContext server_context_;
+  GenericServerAsyncReaderWriter generic_stream_;
+};
+
+}  // namespace
+
+/// Use private inheritance rather than composition only to establish order
+/// of construction, since the public base class should be constructed after the
+/// elements belonging to the private base class are constructed. This is not
+/// possible using true composition.
+class Server::UnimplementedAsyncRequest final
+    : private UnimplementedAsyncRequestContext,
+      public GenericAsyncRequest {
+ public:
+  UnimplementedAsyncRequest(Server* server, ServerCompletionQueue* cq)
+      : GenericAsyncRequest(server, &server_context_, &generic_stream_, cq, cq,
+                            nullptr, false),
+        server_(server),
+        cq_(cq) {}
+
+  bool FinalizeResult(void** tag, bool* status) override;
+
+  ServerContext* context() { return &server_context_; }
+  GenericServerAsyncReaderWriter* stream() { return &generic_stream_; }
+
+ private:
+  Server* const server_;
+  ServerCompletionQueue* const cq_;
+};
+
+/// UnimplementedAsyncResponse should not post user-visible completions to the
+/// C++ completion queue, but is generated as a CQ event by the core
+class Server::UnimplementedAsyncResponse final
+    : public internal::CallOpSet<internal::CallOpSendInitialMetadata,
+                                 internal::CallOpServerSendStatus> {
+ public:
+  UnimplementedAsyncResponse(UnimplementedAsyncRequest* request);
+  ~UnimplementedAsyncResponse() { delete request_; }
+
+  bool FinalizeResult(void** tag, bool* status) override {
+    if (internal::CallOpSet<
+            internal::CallOpSendInitialMetadata,
+            internal::CallOpServerSendStatus>::FinalizeResult(tag, status)) {
+      delete this;
+    } else {
+      // The tag was swallowed due to interception. We will see it again.
+    }
+    return false;
+  }
+
+ private:
+  UnimplementedAsyncRequest* const request_;
+};
+
+class Server::SyncRequest final : public internal::CompletionQueueTag {
+ public:
+  SyncRequest(internal::RpcServiceMethod* method, void* method_tag)
+      : method_(method),
+        method_tag_(method_tag),
+        in_flight_(false),
+        has_request_payload_(
+            method->method_type() == internal::RpcMethod::NORMAL_RPC ||
+            method->method_type() == internal::RpcMethod::SERVER_STREAMING),
+        call_details_(nullptr),
+        cq_(nullptr) {
+    grpc_metadata_array_init(&request_metadata_);
+  }
+
+  ~SyncRequest() {
+    if (call_details_) {
+      delete call_details_;
+    }
+    grpc_metadata_array_destroy(&request_metadata_);
+  }
+
+  void SetupRequest() { cq_ = grpc_completion_queue_create_for_pluck(nullptr); }
+
+  void TeardownRequest() {
+    grpc_completion_queue_destroy(cq_);
+    cq_ = nullptr;
+  }
+
+  void Request(grpc_server* server, grpc_completion_queue* notify_cq) {
+    GPR_ASSERT(cq_ && !in_flight_);
+    in_flight_ = true;
+    if (method_tag_) {
+      if (GRPC_CALL_OK !=
+          grpc_server_request_registered_call(
+              server, method_tag_, &call_, &deadline_, &request_metadata_,
+              has_request_payload_ ? &request_payload_ : nullptr, cq_,
+              notify_cq, this)) {
+        TeardownRequest();
+        return;
+      }
+    } else {
+      if (!call_details_) {
+        call_details_ = new grpc_call_details;
+        grpc_call_details_init(call_details_);
+      }
+      if (grpc_server_request_call(server, &call_, call_details_,
+                                   &request_metadata_, cq_, notify_cq,
+                                   this) != GRPC_CALL_OK) {
+        TeardownRequest();
+        return;
+      }
+    }
+  }
+
+  void PostShutdownCleanup() {
+    if (call_) {
+      grpc_call_unref(call_);
+      call_ = nullptr;
+    }
+    if (cq_) {
+      grpc_completion_queue_destroy(cq_);
+      cq_ = nullptr;
+    }
+  }
+
+  bool FinalizeResult(void** tag, bool* status) override {
+    if (!*status) {
+      grpc_completion_queue_destroy(cq_);
+      cq_ = nullptr;
+    }
+    if (call_details_) {
+      deadline_ = call_details_->deadline;
+      grpc_call_details_destroy(call_details_);
+      grpc_call_details_init(call_details_);
+    }
+    return true;
+  }
+
+  // The CallData class represents a call that is "active" as opposed
+  // to just being requested. It wraps and takes ownership of the cq from
+  // the call request
+  class CallData final {
+   public:
+    explicit CallData(Server* server, SyncRequest* mrd)
+        : cq_(mrd->cq_),
+          ctx_(mrd->deadline_, &mrd->request_metadata_),
+          has_request_payload_(mrd->has_request_payload_),
+          request_payload_(has_request_payload_ ? mrd->request_payload_
+                                                : nullptr),
+          request_(nullptr),
+          method_(mrd->method_),
+          call_(
+              mrd->call_, server, &cq_, server->max_receive_message_size(),
+              ctx_.set_server_rpc_info(method_->name(), method_->method_type(),
+                                       server->interceptor_creators_)),
+          server_(server),
+          global_callbacks_(nullptr),
+          resources_(false) {
+      ctx_.set_call(mrd->call_);
+      ctx_.cq_ = &cq_;
+      GPR_ASSERT(mrd->in_flight_);
+      mrd->in_flight_ = false;
+      mrd->request_metadata_.count = 0;
+    }
+
+    ~CallData() {
+      if (has_request_payload_ && request_payload_) {
+        grpc_byte_buffer_destroy(request_payload_);
+      }
+    }
+
+    void Run(const std::shared_ptr<GlobalCallbacks>& global_callbacks,
+             bool resources) {
+      global_callbacks_ = global_callbacks;
+      resources_ = resources;
+
+      interceptor_methods_.SetCall(&call_);
+      interceptor_methods_.SetReverse();
+      // Set interception point for RECV INITIAL METADATA
+      interceptor_methods_.AddInterceptionHookPoint(
+          experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
+      interceptor_methods_.SetRecvInitialMetadata(&ctx_.client_metadata_);
+
+      if (has_request_payload_) {
+        // Set interception point for RECV MESSAGE
+        auto* handler = resources_ ? method_->handler()
+                                   : server_->resource_exhausted_handler_.get();
+        request_ = handler->Deserialize(call_.call(), request_payload_,
+                                        &request_status_);
+
+        request_payload_ = nullptr;
+        interceptor_methods_.AddInterceptionHookPoint(
+            experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+        interceptor_methods_.SetRecvMessage(request_);
+      }
+
+      if (interceptor_methods_.RunInterceptors(
+              [this]() { ContinueRunAfterInterception(); })) {
+        ContinueRunAfterInterception();
+      } else {
+        // There were interceptors to be run, so ContinueRunAfterInterception
+        // will be run when interceptors are done.
+      }
+    }
+
+    void ContinueRunAfterInterception() {
+      {
+        ctx_.BeginCompletionOp(&call_, nullptr, nullptr);
+        global_callbacks_->PreSynchronousRequest(&ctx_);
+        auto* handler = resources_ ? method_->handler()
+                                   : server_->resource_exhausted_handler_.get();
+        handler->RunHandler(internal::MethodHandler::HandlerParameter(
+            &call_, &ctx_, request_, request_status_, nullptr));
+        request_ = nullptr;
+        global_callbacks_->PostSynchronousRequest(&ctx_);
+
+        cq_.Shutdown();
+
+        internal::CompletionQueueTag* op_tag = ctx_.GetCompletionOpTag();
+        cq_.TryPluck(op_tag, gpr_inf_future(GPR_CLOCK_REALTIME));
+
+        /* Ensure the cq_ is shutdown */
+        DummyTag ignored_tag;
+        GPR_ASSERT(cq_.Pluck(&ignored_tag) == false);
+      }
+      delete this;
+    }
+
+   private:
+    CompletionQueue cq_;
+    ServerContext ctx_;
+    const bool has_request_payload_;
+    grpc_byte_buffer* request_payload_;
+    void* request_;
+    Status request_status_;
+    internal::RpcServiceMethod* const method_;
+    internal::Call call_;
+    Server* server_;
+    std::shared_ptr<GlobalCallbacks> global_callbacks_;
+    bool resources_;
+    internal::InterceptorBatchMethodsImpl interceptor_methods_;
+  };
+
+ private:
+  internal::RpcServiceMethod* const method_;
+  void* const method_tag_;
+  bool in_flight_;
+  const bool has_request_payload_;
+  grpc_call* call_;
+  grpc_call_details* call_details_;
+  gpr_timespec deadline_;
+  grpc_metadata_array request_metadata_;
+  grpc_byte_buffer* request_payload_;
+  grpc_completion_queue* cq_;
+};
+
+class Server::CallbackRequest final : public internal::CompletionQueueTag {
+ public:
+  CallbackRequest(Server* server, internal::RpcServiceMethod* method,
+                  void* method_tag)
+      : server_(server),
+        method_(method),
+        method_tag_(method_tag),
+        has_request_payload_(
+            method->method_type() == internal::RpcMethod::NORMAL_RPC ||
+            method->method_type() == internal::RpcMethod::SERVER_STREAMING),
+        cq_(server->CallbackCQ()),
+        tag_(this) {
+    Setup();
+  }
+
+  ~CallbackRequest() { Clear(); }
+
+  void Request() {
+    if (method_tag_) {
+      if (GRPC_CALL_OK !=
+          grpc_server_request_registered_call(
+              server_->c_server(), method_tag_, &call_, &deadline_,
+              &request_metadata_,
+              has_request_payload_ ? &request_payload_ : nullptr, cq_->cq(),
+              cq_->cq(), static_cast<void*>(&tag_))) {
+        return;
+      }
+    } else {
+      if (!call_details_) {
+        call_details_ = new grpc_call_details;
+        grpc_call_details_init(call_details_);
+      }
+      if (grpc_server_request_call(server_->c_server(), &call_, call_details_,
+                                   &request_metadata_, cq_->cq(), cq_->cq(),
+                                   static_cast<void*>(&tag_)) != GRPC_CALL_OK) {
+        return;
+      }
+    }
+  }
+
+  bool FinalizeResult(void** tag, bool* status) override { return false; }
+
+ private:
+  class CallbackCallTag : public grpc_experimental_completion_queue_functor {
+   public:
+    CallbackCallTag(Server::CallbackRequest* req) : req_(req) {
+      functor_run = &CallbackCallTag::StaticRun;
+    }
+
+    // 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); }
+
+   private:
+    Server::CallbackRequest* req_;
+    internal::Call* call_;
+
+    static void StaticRun(grpc_experimental_completion_queue_functor* cb,
+                          int ok) {
+      static_cast<CallbackCallTag*>(cb)->Run(static_cast<bool>(ok));
+    }
+    void Run(bool ok) {
+      void* ignored = req_;
+      bool new_ok = ok;
+      GPR_ASSERT(!req_->FinalizeResult(&ignored, &new_ok));
+      GPR_ASSERT(ignored == req_);
+
+      if (!ok) {
+        // The call has been shutdown
+        req_->Clear();
+        return;
+      }
+
+      // Bind the call, deadline, and metadata from what we got
+      req_->ctx_.set_call(req_->call_);
+      req_->ctx_.cq_ = req_->cq_;
+      req_->ctx_.BindDeadlineAndMetadata(req_->deadline_,
+                                         &req_->request_metadata_);
+      req_->request_metadata_.count = 0;
+
+      // Create a C++ Call to control the underlying core call
+      call_ = new (grpc_call_arena_alloc(req_->call_, sizeof(internal::Call)))
+          internal::Call(
+              req_->call_, req_->server_, req_->cq_,
+              req_->server_->max_receive_message_size(),
+              req_->ctx_.set_server_rpc_info(
+                  req_->method_->name(), req_->method_->method_type(),
+                  req_->server_->interceptor_creators_));
+
+      req_->interceptor_methods_.SetCall(call_);
+      req_->interceptor_methods_.SetReverse();
+      // Set interception point for RECV INITIAL METADATA
+      req_->interceptor_methods_.AddInterceptionHookPoint(
+          experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
+      req_->interceptor_methods_.SetRecvInitialMetadata(
+          &req_->ctx_.client_metadata_);
+
+      if (req_->has_request_payload_) {
+        // Set interception point for RECV MESSAGE
+        req_->request_ = req_->method_->handler()->Deserialize(
+            req_->call_, req_->request_payload_, &req_->request_status_);
+        req_->request_payload_ = nullptr;
+        req_->interceptor_methods_.AddInterceptionHookPoint(
+            experimental::InterceptionHookPoints::POST_RECV_MESSAGE);
+        req_->interceptor_methods_.SetRecvMessage(req_->request_);
+      }
+
+      if (req_->interceptor_methods_.RunInterceptors(
+              [this] { ContinueRunAfterInterception(); })) {
+        ContinueRunAfterInterception();
+      } else {
+        // There were interceptors to be run, so ContinueRunAfterInterception
+        // will be run when interceptors are done.
+      }
+    }
+    void ContinueRunAfterInterception() {
+      req_->method_->handler()->RunHandler(
+          internal::MethodHandler::HandlerParameter(
+              call_, &req_->ctx_, req_->request_, req_->request_status_,
+              [this] {
+                req_->Reset();
+                req_->Request();
+              }));
+    }
+  };
+
+  void Reset() {
+    Clear();
+    Setup();
+  }
+
+  void Clear() {
+    if (call_details_) {
+      delete call_details_;
+      call_details_ = nullptr;
+    }
+    grpc_metadata_array_destroy(&request_metadata_);
+    if (has_request_payload_ && request_payload_) {
+      grpc_byte_buffer_destroy(request_payload_);
+    }
+    ctx_.Clear();
+    interceptor_methods_.ClearState();
+  }
+
+  void Setup() {
+    grpc_metadata_array_init(&request_metadata_);
+    ctx_.Setup(gpr_inf_future(GPR_CLOCK_REALTIME));
+    request_payload_ = nullptr;
+    request_ = nullptr;
+    request_status_ = Status();
+  }
+
+  Server* const server_;
+  internal::RpcServiceMethod* const method_;
+  void* const method_tag_;
+  const bool has_request_payload_;
+  grpc_byte_buffer* request_payload_;
+  void* request_;
+  Status request_status_;
+  grpc_call_details* call_details_ = nullptr;
+  grpc_call* call_;
+  gpr_timespec deadline_;
+  grpc_metadata_array request_metadata_;
+  CompletionQueue* cq_;
+  CallbackCallTag tag_;
+  ServerContext ctx_;
+  internal::InterceptorBatchMethodsImpl interceptor_methods_;
+};
+
+// Implementation of ThreadManager. Each instance of SyncRequestThreadManager
+// manages a pool of threads that poll for incoming Sync RPCs and call the
+// appropriate RPC handlers
+class Server::SyncRequestThreadManager : public ThreadManager {
+ public:
+  SyncRequestThreadManager(Server* server, CompletionQueue* server_cq,
+                           std::shared_ptr<GlobalCallbacks> global_callbacks,
+                           grpc_resource_quota* rq, int min_pollers,
+                           int max_pollers, int cq_timeout_msec)
+      : ThreadManager("SyncServer", rq, min_pollers, max_pollers),
+        server_(server),
+        server_cq_(server_cq),
+        cq_timeout_msec_(cq_timeout_msec),
+        global_callbacks_(std::move(global_callbacks)) {}
+
+  WorkStatus PollForWork(void** tag, bool* ok) override {
+    *tag = nullptr;
+    // TODO(ctiller): workaround for GPR_TIMESPAN based deadlines not working
+    // right now
+    gpr_timespec deadline =
+        gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC),
+                     gpr_time_from_millis(cq_timeout_msec_, GPR_TIMESPAN));
+
+    switch (server_cq_->AsyncNext(tag, ok, deadline)) {
+      case CompletionQueue::TIMEOUT:
+        return TIMEOUT;
+      case CompletionQueue::SHUTDOWN:
+        return SHUTDOWN;
+      case CompletionQueue::GOT_EVENT:
+        return WORK_FOUND;
+    }
+
+    GPR_UNREACHABLE_CODE(return TIMEOUT);
+  }
+
+  void DoWork(void* tag, bool ok, bool resources) override {
+    SyncRequest* sync_req = static_cast<SyncRequest*>(tag);
+
+    if (!sync_req) {
+      // No tag. Nothing to work on. This is an unlikley scenario and possibly a
+      // bug in RPC Manager implementation.
+      gpr_log(GPR_ERROR, "Sync server. DoWork() was called with NULL tag");
+      return;
+    }
+
+    if (ok) {
+      // Calldata takes ownership of the completion queue and interceptors
+      // inside sync_req
+      auto* cd = new SyncRequest::CallData(server_, sync_req);
+      // Prepare for the next request
+      if (!IsShutdown()) {
+        sync_req->SetupRequest();  // Create new completion queue for sync_req
+        sync_req->Request(server_->c_server(), server_cq_->cq());
+      }
+
+      GPR_TIMER_SCOPE("cd.Run()", 0);
+      cd->Run(global_callbacks_, resources);
+    }
+    // TODO (sreek) If ok is false here (which it isn't in case of
+    // grpc_request_registered_call), we should still re-queue the request
+    // object
+  }
+
+  void AddSyncMethod(internal::RpcServiceMethod* method, void* tag) {
+    sync_requests_.emplace_back(new SyncRequest(method, tag));
+  }
+
+  void AddUnknownSyncMethod() {
+    if (!sync_requests_.empty()) {
+      unknown_method_.reset(new internal::RpcServiceMethod(
+          "unknown", internal::RpcMethod::BIDI_STREAMING,
+          new internal::UnknownMethodHandler));
+      sync_requests_.emplace_back(
+          new SyncRequest(unknown_method_.get(), nullptr));
+    }
+  }
+
+  void Shutdown() override {
+    ThreadManager::Shutdown();
+    server_cq_->Shutdown();
+  }
+
+  void Wait() override {
+    ThreadManager::Wait();
+    // Drain any pending items from the queue
+    void* tag;
+    bool ok;
+    while (server_cq_->Next(&tag, &ok)) {
+      if (ok) {
+        // If a request was pulled off the queue, it means that the thread
+        // handling the request added it to the completion queue after shutdown
+        // was called - because the thread had already started and checked the
+        // shutdown flag before shutdown was called. In this case, we simply
+        // clean it up here, *after* calling wait on all the worker threads, at
+        // which point we are certain no in-flight requests will add more to the
+        // queue. This fixes an intermittent memory leak on shutdown.
+        SyncRequest* sync_req = static_cast<SyncRequest*>(tag);
+        sync_req->PostShutdownCleanup();
+      }
+    }
+  }
+
+  void Start() {
+    if (!sync_requests_.empty()) {
+      for (auto m = sync_requests_.begin(); m != sync_requests_.end(); m++) {
+        (*m)->SetupRequest();
+        (*m)->Request(server_->c_server(), server_cq_->cq());
+      }
+
+      Initialize();  // ThreadManager's Initialize()
+    }
+  }
+
+ private:
+  Server* server_;
+  CompletionQueue* server_cq_;
+  int cq_timeout_msec_;
+  std::vector<std::unique_ptr<SyncRequest>> sync_requests_;
+  std::unique_ptr<internal::RpcServiceMethod> unknown_method_;
+  std::shared_ptr<Server::GlobalCallbacks> global_callbacks_;
+};
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+Server::Server(
+    int max_receive_message_size, ChannelArguments* args,
+    std::shared_ptr<std::vector<std::unique_ptr<ServerCompletionQueue>>>
+        sync_server_cqs,
+    int min_pollers, int max_pollers, int sync_cq_timeout_msec,
+    grpc_resource_quota* server_rq,
+    std::vector<
+        std::unique_ptr<experimental::ServerInterceptorFactoryInterface>>
+        interceptor_creators)
+    : interceptor_creators_(std::move(interceptor_creators)),
+      max_receive_message_size_(max_receive_message_size),
+      sync_server_cqs_(std::move(sync_server_cqs)),
+      started_(false),
+      shutdown_(false),
+      shutdown_notified_(false),
+      has_generic_service_(false),
+      server_(nullptr),
+      server_initializer_(new ServerInitializer(this)),
+      health_check_service_disabled_(false) {
+  g_gli_initializer.summon();
+  gpr_once_init(&g_once_init_callbacks, InitGlobalCallbacks);
+  global_callbacks_ = g_callbacks;
+  global_callbacks_->UpdateArguments(args);
+
+  if (sync_server_cqs_ != nullptr) {
+    bool default_rq_created = false;
+    if (server_rq == nullptr) {
+      server_rq = grpc_resource_quota_create("SyncServer-default-rq");
+      grpc_resource_quota_set_max_threads(server_rq,
+                                          DEFAULT_MAX_SYNC_SERVER_THREADS);
+      default_rq_created = true;
+    }
+
+    for (const auto& it : *sync_server_cqs_) {
+      sync_req_mgrs_.emplace_back(new SyncRequestThreadManager(
+          this, it.get(), global_callbacks_, server_rq, min_pollers,
+          max_pollers, sync_cq_timeout_msec));
+    }
+
+    if (default_rq_created) {
+      grpc_resource_quota_unref(server_rq);
+    }
+  }
+
+  grpc_channel_args channel_args;
+  args->SetChannelArgs(&channel_args);
+
+  for (size_t i = 0; i < channel_args.num_args; i++) {
+    if (0 ==
+        strcmp(channel_args.args[i].key, kHealthCheckServiceInterfaceArg)) {
+      if (channel_args.args[i].value.pointer.p == nullptr) {
+        health_check_service_disabled_ = true;
+      } else {
+        health_check_service_.reset(static_cast<HealthCheckServiceInterface*>(
+            channel_args.args[i].value.pointer.p));
+      }
+      break;
+    }
+  }
+
+  server_ = grpc_server_create(&channel_args, nullptr);
+}
+
+Server::~Server() {
+  {
+    std::unique_lock<std::mutex> lock(mu_);
+    if (callback_cq_ != nullptr) {
+      callback_cq_->Shutdown();
+    }
+    if (started_ && !shutdown_) {
+      lock.unlock();
+      Shutdown();
+    } else if (!started_) {
+      // Shutdown the completion queues
+      for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
+        (*it)->Shutdown();
+      }
+    }
+  }
+
+  grpc_server_destroy(server_);
+}
+
+void Server::SetGlobalCallbacks(GlobalCallbacks* callbacks) {
+  GPR_ASSERT(!g_callbacks);
+  GPR_ASSERT(callbacks);
+  g_callbacks.reset(callbacks);
+}
+
+grpc_server* Server::c_server() { return server_; }
+
+std::shared_ptr<Channel> Server::InProcessChannel(
+    const ChannelArguments& args) {
+  grpc_channel_args channel_args = args.c_channel_args();
+  return CreateChannelInternal(
+      "inproc", grpc_inproc_channel_create(server_, &channel_args, nullptr),
+      std::vector<
+          std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>());
+}
+
+std::shared_ptr<Channel>
+Server::experimental_type::InProcessChannelWithInterceptors(
+    const ChannelArguments& args,
+    std::vector<
+        std::unique_ptr<experimental::ClientInterceptorFactoryInterface>>
+        interceptor_creators) {
+  grpc_channel_args channel_args = args.c_channel_args();
+  return CreateChannelInternal(
+      "inproc",
+      grpc_inproc_channel_create(server_->server_, &channel_args, nullptr),
+      std::move(interceptor_creators));
+}
+
+static grpc_server_register_method_payload_handling PayloadHandlingForMethod(
+    internal::RpcServiceMethod* method) {
+  switch (method->method_type()) {
+    case internal::RpcMethod::NORMAL_RPC:
+    case internal::RpcMethod::SERVER_STREAMING:
+      return GRPC_SRM_PAYLOAD_READ_INITIAL_BYTE_BUFFER;
+    case internal::RpcMethod::CLIENT_STREAMING:
+    case internal::RpcMethod::BIDI_STREAMING:
+      return GRPC_SRM_PAYLOAD_NONE;
+  }
+  GPR_UNREACHABLE_CODE(return GRPC_SRM_PAYLOAD_NONE;);
+}
+
+bool Server::RegisterService(const grpc::string* host, Service* service) {
+  bool has_async_methods = service->has_async_methods();
+  if (has_async_methods) {
+    GPR_ASSERT(service->server_ == nullptr &&
+               "Can only register an asynchronous service against one server.");
+    service->server_ = this;
+  }
+
+  const char* method_name = nullptr;
+  for (auto it = service->methods_.begin(); it != service->methods_.end();
+       ++it) {
+    if (it->get() == nullptr) {  // Handled by generic service if any.
+      continue;
+    }
+
+    internal::RpcServiceMethod* method = it->get();
+    void* method_registration_tag = grpc_server_register_method(
+        server_, method->name(), host ? host->c_str() : nullptr,
+        PayloadHandlingForMethod(method), 0);
+    if (method_registration_tag == nullptr) {
+      gpr_log(GPR_DEBUG, "Attempt to register %s multiple times",
+              method->name());
+      return false;
+    }
+
+    if (method->handler() == nullptr) {  // Async method without handler
+      method->set_server_tag(method_registration_tag);
+    } else if (method->api_type() ==
+               internal::RpcServiceMethod::ApiType::SYNC) {
+      for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
+        (*it)->AddSyncMethod(method, method_registration_tag);
+      }
+    } else {
+      // a callback method. Register at least some callback requests
+      // TODO(vjpai): Register these dynamically based on need
+      for (int i = 0; i < DEFAULT_CALLBACK_REQS_PER_METHOD; i++) {
+        auto* req = new CallbackRequest(this, method, method_registration_tag);
+        callback_reqs_.emplace_back(req);
+      }
+      // Enqueue it so that it will be Request'ed later once
+      // all request matchers are created at core server startup
+    }
+
+    method_name = method->name();
+  }
+
+  // Parse service name.
+  if (method_name != nullptr) {
+    std::stringstream ss(method_name);
+    grpc::string service_name;
+    if (std::getline(ss, service_name, '/') &&
+        std::getline(ss, service_name, '/')) {
+      services_.push_back(service_name);
+    }
+  }
+  return true;
+}
+
+void Server::RegisterAsyncGenericService(AsyncGenericService* service) {
+  GPR_ASSERT(service->server_ == nullptr &&
+             "Can only register an async generic service against one server.");
+  service->server_ = this;
+  has_generic_service_ = true;
+}
+
+int Server::AddListeningPort(const grpc::string& addr,
+                             ServerCredentials* creds) {
+  GPR_ASSERT(!started_);
+  int port = creds->AddPortToServer(addr, server_);
+  global_callbacks_->AddPort(this, addr, creds, port);
+  return port;
+}
+
+void Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
+  GPR_ASSERT(!started_);
+  global_callbacks_->PreServerStart(this);
+  started_ = true;
+
+  // Only create default health check service when user did not provide an
+  // explicit one.
+  ServerCompletionQueue* health_check_cq = nullptr;
+  DefaultHealthCheckService::HealthCheckServiceImpl*
+      default_health_check_service_impl = nullptr;
+  if (health_check_service_ == nullptr && !health_check_service_disabled_ &&
+      DefaultHealthCheckServiceEnabled()) {
+    auto* default_hc_service = new DefaultHealthCheckService;
+    health_check_service_.reset(default_hc_service);
+    // We create a non-polling CQ to avoid impacting application
+    // performance.  This ensures that we don't introduce thread hops
+    // for application requests that wind up on this CQ, which is polled
+    // in its own thread.
+    health_check_cq =
+        new ServerCompletionQueue(GRPC_CQ_NEXT, GRPC_CQ_NON_POLLING, nullptr);
+    grpc_server_register_completion_queue(server_, health_check_cq->cq(),
+                                          nullptr);
+    default_health_check_service_impl =
+        default_hc_service->GetHealthCheckService(
+            std::unique_ptr<ServerCompletionQueue>(health_check_cq));
+    RegisterService(nullptr, default_health_check_service_impl);
+  }
+
+  grpc_server_start(server_);
+
+  if (!has_generic_service_) {
+    for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
+      (*it)->AddUnknownSyncMethod();
+    }
+
+    for (size_t i = 0; i < num_cqs; i++) {
+      if (cqs[i]->IsFrequentlyPolled()) {
+        new UnimplementedAsyncRequest(this, cqs[i]);
+      }
+    }
+    if (health_check_cq != nullptr) {
+      new UnimplementedAsyncRequest(this, health_check_cq);
+    }
+  }
+
+  // If this server has any support for synchronous methods (has any sync
+  // server CQs), make sure that we have a ResourceExhausted handler
+  // to deal with the case of thread exhaustion
+  if (sync_server_cqs_ != nullptr && !sync_server_cqs_->empty()) {
+    resource_exhausted_handler_.reset(new internal::ResourceExhaustedHandler);
+  }
+
+  for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
+    (*it)->Start();
+  }
+
+  for (auto& cbreq : callback_reqs_) {
+    cbreq->Request();
+  }
+
+  if (default_health_check_service_impl != nullptr) {
+    default_health_check_service_impl->StartServingThread();
+  }
+}
+
+void Server::ShutdownInternal(gpr_timespec deadline) {
+  std::unique_lock<std::mutex> lock(mu_);
+  if (!shutdown_) {
+    shutdown_ = true;
+
+    /// The completion queue to use for server shutdown completion notification
+    CompletionQueue shutdown_cq;
+    ShutdownTag shutdown_tag;  // Dummy shutdown tag
+    grpc_server_shutdown_and_notify(server_, shutdown_cq.cq(), &shutdown_tag);
+
+    shutdown_cq.Shutdown();
+
+    void* tag;
+    bool ok;
+    CompletionQueue::NextStatus status =
+        shutdown_cq.AsyncNext(&tag, &ok, deadline);
+
+    // If this timed out, it means we are done with the grace period for a clean
+    // shutdown. We should force a shutdown now by cancelling all inflight calls
+    if (status == CompletionQueue::NextStatus::TIMEOUT) {
+      grpc_server_cancel_all_calls(server_);
+    }
+    // Else in case of SHUTDOWN or GOT_EVENT, it means that the server has
+    // successfully shutdown
+
+    // Shutdown all ThreadManagers. This will try to gracefully stop all the
+    // threads in the ThreadManagers (once they process any inflight requests)
+    for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
+      (*it)->Shutdown();  // ThreadManager's Shutdown()
+    }
+
+    // Wait for threads in all ThreadManagers to terminate
+    for (auto it = sync_req_mgrs_.begin(); it != sync_req_mgrs_.end(); it++) {
+      (*it)->Wait();
+    }
+
+    // Drain the shutdown queue (if the previous call to AsyncNext() timed out
+    // and we didn't remove the tag from the queue yet)
+    while (shutdown_cq.Next(&tag, &ok)) {
+      // Nothing to be done here. Just ignore ok and tag values
+    }
+
+    shutdown_notified_ = true;
+    shutdown_cv_.notify_all();
+  }
+}
+
+void Server::Wait() {
+  std::unique_lock<std::mutex> lock(mu_);
+  while (started_ && !shutdown_notified_) {
+    shutdown_cv_.wait(lock);
+  }
+}
+
+void Server::PerformOpsOnCall(internal::CallOpSetInterface* ops,
+                              internal::Call* call) {
+  ops->FillOps(call);
+}
+
+ServerInterface::BaseAsyncRequest::BaseAsyncRequest(
+    ServerInterface* server, ServerContext* context,
+    internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+    ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
+    : server_(server),
+      context_(context),
+      stream_(stream),
+      call_cq_(call_cq),
+      notification_cq_(notification_cq),
+      tag_(tag),
+      delete_on_finalize_(delete_on_finalize),
+      call_(nullptr),
+      done_intercepting_(false) {
+  /* Set up interception state partially for the receive ops. call_wrapper_ is
+   * not filled at this point, but it will be filled before the interceptors are
+   * run. */
+  interceptor_methods_.SetCall(&call_wrapper_);
+  interceptor_methods_.SetReverse();
+  call_cq_->RegisterAvalanching();  // This op will trigger more ops
+}
+
+ServerInterface::BaseAsyncRequest::~BaseAsyncRequest() {
+  call_cq_->CompleteAvalanching();
+}
+
+bool ServerInterface::BaseAsyncRequest::FinalizeResult(void** tag,
+                                                       bool* status) {
+  if (done_intercepting_) {
+    *tag = tag_;
+    if (delete_on_finalize_) {
+      delete this;
+    }
+    return true;
+  }
+  context_->set_call(call_);
+  context_->cq_ = call_cq_;
+  if (call_wrapper_.call() == nullptr) {
+    // Fill it since it is empty.
+    call_wrapper_ = internal::Call(
+        call_, server_, call_cq_, server_->max_receive_message_size(), nullptr);
+  }
+
+  // just the pointers inside call are copied here
+  stream_->BindCall(&call_wrapper_);
+
+  if (*status && call_ && call_wrapper_.server_rpc_info()) {
+    done_intercepting_ = true;
+    // Set interception point for RECV INITIAL METADATA
+    interceptor_methods_.AddInterceptionHookPoint(
+        experimental::InterceptionHookPoints::POST_RECV_INITIAL_METADATA);
+    interceptor_methods_.SetRecvInitialMetadata(&context_->client_metadata_);
+    if (interceptor_methods_.RunInterceptors(
+            [this]() { ContinueFinalizeResultAfterInterception(); })) {
+      // There are no interceptors to run. Continue
+    } else {
+      // There were interceptors to be run, so
+      // ContinueFinalizeResultAfterInterception will be run when interceptors
+      // are done.
+      return false;
+    }
+  }
+  if (*status && call_) {
+    context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr);
+  }
+  *tag = tag_;
+  if (delete_on_finalize_) {
+    delete this;
+  }
+  return true;
+}
+
+void ServerInterface::BaseAsyncRequest::
+    ContinueFinalizeResultAfterInterception() {
+  context_->BeginCompletionOp(&call_wrapper_, nullptr, nullptr);
+  // Queue a tag which will be returned immediately
+  grpc_core::ExecCtx exec_ctx;
+  grpc_cq_begin_op(notification_cq_->cq(), this);
+  grpc_cq_end_op(
+      notification_cq_->cq(), this, GRPC_ERROR_NONE,
+      [](void* arg, grpc_cq_completion* completion) { delete completion; },
+      nullptr, new grpc_cq_completion());
+}
+
+ServerInterface::RegisteredAsyncRequest::RegisteredAsyncRequest(
+    ServerInterface* server, ServerContext* context,
+    internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+    ServerCompletionQueue* notification_cq, void* tag, const char* name,
+    internal::RpcMethod::RpcType type)
+    : BaseAsyncRequest(server, context, stream, call_cq, notification_cq, tag,
+                       true),
+      name_(name),
+      type_(type) {}
+
+void ServerInterface::RegisteredAsyncRequest::IssueRequest(
+    void* registered_method, grpc_byte_buffer** payload,
+    ServerCompletionQueue* notification_cq) {
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_registered_call(
+                                 server_->server(), registered_method, &call_,
+                                 &context_->deadline_,
+                                 context_->client_metadata_.arr(), payload,
+                                 call_cq_->cq(), notification_cq->cq(), this));
+}
+
+ServerInterface::GenericAsyncRequest::GenericAsyncRequest(
+    ServerInterface* server, GenericServerContext* context,
+    internal::ServerAsyncStreamingInterface* stream, CompletionQueue* call_cq,
+    ServerCompletionQueue* notification_cq, void* tag, bool delete_on_finalize)
+    : BaseAsyncRequest(server, context, stream, call_cq, notification_cq, tag,
+                       delete_on_finalize) {
+  grpc_call_details_init(&call_details_);
+  GPR_ASSERT(notification_cq);
+  GPR_ASSERT(call_cq);
+  GPR_ASSERT(GRPC_CALL_OK == grpc_server_request_call(
+                                 server->server(), &call_, &call_details_,
+                                 context->client_metadata_.arr(), call_cq->cq(),
+                                 notification_cq->cq(), this));
+}
+
+bool ServerInterface::GenericAsyncRequest::FinalizeResult(void** tag,
+                                                          bool* status) {
+  // If we are done intercepting, there is nothing more for us to do
+  if (done_intercepting_) {
+    return BaseAsyncRequest::FinalizeResult(tag, status);
+  }
+  // TODO(yangg) remove the copy here.
+  if (*status) {
+    static_cast<GenericServerContext*>(context_)->method_ =
+        StringFromCopiedSlice(call_details_.method);
+    static_cast<GenericServerContext*>(context_)->host_ =
+        StringFromCopiedSlice(call_details_.host);
+    context_->deadline_ = call_details_.deadline;
+  }
+  grpc_slice_unref(call_details_.method);
+  grpc_slice_unref(call_details_.host);
+  call_wrapper_ = internal::Call(
+      call_, server_, call_cq_, server_->max_receive_message_size(),
+      context_->set_server_rpc_info(
+          static_cast<GenericServerContext*>(context_)->method_.c_str(),
+          internal::RpcMethod::BIDI_STREAMING,
+          *server_->interceptor_creators()));
+  return BaseAsyncRequest::FinalizeResult(tag, status);
+}
+
+bool Server::UnimplementedAsyncRequest::FinalizeResult(void** tag,
+                                                       bool* status) {
+  if (GenericAsyncRequest::FinalizeResult(tag, status)) {
+    // We either had no interceptors run or we are done intercepting
+    if (*status) {
+      new UnimplementedAsyncRequest(server_, cq_);
+      new UnimplementedAsyncResponse(this);
+    } else {
+      delete this;
+    }
+  } else {
+    // The tag was swallowed due to interception. We will see it again.
+  }
+  return false;
+}
+
+Server::UnimplementedAsyncResponse::UnimplementedAsyncResponse(
+    UnimplementedAsyncRequest* request)
+    : request_(request) {
+  Status status(StatusCode::UNIMPLEMENTED, "");
+  internal::UnknownMethodHandler::FillOps(request_->context(), this);
+  request_->stream()->call_.PerformOps(this);
+}
+
+ServerInitializer* Server::initializer() { return server_initializer_.get(); }
+
+namespace {
+class ShutdownCallback : public grpc_experimental_completion_queue_functor {
+ public:
+  ShutdownCallback() { functor_run = &ShutdownCallback::Run; }
+  // TakeCQ takes ownership of the cq into the shutdown callback
+  // so that the shutdown callback will be responsible for destroying it
+  void TakeCQ(CompletionQueue* cq) { cq_ = cq; }
+
+  // The Run function will get invoked by the completion queue library
+  // when the shutdown is actually complete
+  static void Run(grpc_experimental_completion_queue_functor* cb, int) {
+    auto* callback = static_cast<ShutdownCallback*>(cb);
+    delete callback->cq_;
+    delete callback;
+  }
+
+ private:
+  CompletionQueue* cq_ = nullptr;
+};
+}  // namespace
+
+CompletionQueue* Server::CallbackCQ() {
+  // TODO(vjpai): Consider using a single global CQ for the default CQ
+  // if there is no explicit per-server CQ registered
+  std::lock_guard<std::mutex> l(mu_);
+  if (callback_cq_ == nullptr) {
+    auto* shutdown_callback = new ShutdownCallback;
+    callback_cq_ = new CompletionQueue(grpc_completion_queue_attributes{
+        GRPC_CQ_CURRENT_VERSION, GRPC_CQ_CALLBACK, GRPC_CQ_DEFAULT_POLLING,
+        shutdown_callback});
+
+    // Transfer ownership of the new cq to its own shutdown callback
+    shutdown_callback->TakeCQ(callback_cq_);
+  }
+  return callback_cq_;
+};
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/server_context.cc b/third_party/grpc/src/cpp/server/server_context.cc
index e205a19..1b524bc 100644
--- a/third_party/grpc/src/cpp/server/server_context.cc
+++ b/third_party/grpc/src/cpp/server/server_context.cc
@@ -1,168 +1,309 @@
 /*
  *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/server_context.h>
+#include <grpcpp/server_context.h>
+#include <grpcpp/support/server_callback.h>
 
-#include <grpc++/completion_queue.h>
-#include <grpc++/impl/call.h>
-#include <grpc++/impl/sync.h>
-#include <grpc++/support/time.h>
+#include <algorithm>
+#include <mutex>
+#include <utility>
+
 #include <grpc/compression.h>
 #include <grpc/grpc.h>
+#include <grpc/load_reporting.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/log.h>
+#include <grpcpp/completion_queue.h>
+#include <grpcpp/impl/call.h>
+#include <grpcpp/support/time.h>
 
-#include "src/core/channel/compress_filter.h"
-#include "src/cpp/common/create_auth_context.h"
+#include "src/core/lib/surface/call.h"
 
 namespace grpc {
 
 // CompletionOp
 
-class ServerContext::CompletionOp GRPC_FINAL : public CallOpSetInterface {
+class ServerContext::CompletionOp final : public internal::CallOpSetInterface {
  public:
   // initial refs: one in the server context, one in the cq
-  CompletionOp()
-      : has_tag_(false),
+  // must ref the call before calling constructor and after deleting this
+  CompletionOp(internal::Call* call, internal::ServerReactor* reactor)
+      : call_(*call),
+        reactor_(reactor),
+        has_tag_(false),
         tag_(nullptr),
+        core_cq_tag_(this),
         refs_(2),
         finalized_(false),
-        cancelled_(0) {}
+        cancelled_(0),
+        done_intercepting_(false) {}
 
-  void FillOps(grpc_op* ops, size_t* nops) GRPC_OVERRIDE;
-  bool FinalizeResult(void** tag, bool* status) GRPC_OVERRIDE;
+  // CompletionOp isn't copyable or movable
+  CompletionOp(const CompletionOp&) = delete;
+  CompletionOp& operator=(const CompletionOp&) = delete;
+  CompletionOp(CompletionOp&&) = delete;
+  CompletionOp& operator=(CompletionOp&&) = delete;
 
-  bool CheckCancelled(CompletionQueue* cq);
+  ~CompletionOp() {
+    if (call_.server_rpc_info()) {
+      call_.server_rpc_info()->Unref();
+    }
+  }
+
+  void FillOps(internal::Call* call) override;
+
+  // This should always be arena allocated in the call, so override delete.
+  // But this class is not trivially destructible, so must actually call delete
+  // before allowing the arena to be freed
+  static void operator delete(void* ptr, std::size_t size) {
+    assert(size == sizeof(CompletionOp));
+  }
+
+  // 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); }
+
+  bool FinalizeResult(void** tag, bool* status) override;
+
+  bool CheckCancelled(CompletionQueue* cq) {
+    cq->TryPluck(this);
+    return CheckCancelledNoPluck();
+  }
+  bool CheckCancelledAsync() { return CheckCancelledNoPluck(); }
 
   void set_tag(void* tag) {
     has_tag_ = true;
     tag_ = tag;
   }
 
+  void set_core_cq_tag(void* core_cq_tag) { core_cq_tag_ = core_cq_tag; }
+
+  void* core_cq_tag() override { return core_cq_tag_; }
+
   void Unref();
 
+  // 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 {
+    /* Servers don't allow hijacking */
+    GPR_CODEGEN_ASSERT(false);
+  }
+
+  /* Should be called after interceptors are done running */
+  void ContinueFillOpsAfterInterception() override {}
+
+  /* Should be called after interceptors are done running on the finalize result
+   * path */
+  void ContinueFinalizeResultAfterInterception() override {
+    done_intercepting_ = true;
+    if (!has_tag_) {
+      /* We don't have a tag to return. */
+      std::unique_lock<std::mutex> lock(mu_);
+      if (--refs_ == 0) {
+        lock.unlock();
+        grpc_call* call = call_.call();
+        delete this;
+        grpc_call_unref(call);
+      }
+      return;
+    }
+    /* Start a dummy op so that we can return the tag */
+    GPR_CODEGEN_ASSERT(
+        GRPC_CALL_OK ==
+        grpc_call_start_batch(call_.call(), nullptr, 0, core_cq_tag_, nullptr));
+  }
+
  private:
+  bool CheckCancelledNoPluck() {
+    std::lock_guard<std::mutex> g(mu_);
+    return finalized_ ? (cancelled_ != 0) : false;
+  }
+
+  internal::Call call_;
+  internal::ServerReactor* reactor_;
   bool has_tag_;
   void* tag_;
-  grpc::mutex mu_;
+  void* core_cq_tag_;
+  std::mutex mu_;
   int refs_;
   bool finalized_;
-  int cancelled_;
+  int cancelled_;  // This is an int (not bool) because it is passed to core
+  bool done_intercepting_;
+  internal::InterceptorBatchMethodsImpl interceptor_methods_;
 };
 
 void ServerContext::CompletionOp::Unref() {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
+  std::unique_lock<std::mutex> lock(mu_);
   if (--refs_ == 0) {
     lock.unlock();
+    grpc_call* call = call_.call();
     delete this;
+    grpc_call_unref(call);
   }
 }
 
-bool ServerContext::CompletionOp::CheckCancelled(CompletionQueue* cq) {
-  cq->TryPluck(this);
-  grpc::lock_guard<grpc::mutex> g(mu_);
-  return finalized_ ? cancelled_ != 0 : false;
-}
-
-void ServerContext::CompletionOp::FillOps(grpc_op* ops, size_t* nops) {
-  ops->op = GRPC_OP_RECV_CLOSE_ON_SERVER;
-  ops->data.recv_close_on_server.cancelled = &cancelled_;
-  ops->flags = 0;
-  ops->reserved = NULL;
-  *nops = 1;
+void ServerContext::CompletionOp::FillOps(internal::Call* call) {
+  grpc_op ops;
+  ops.op = GRPC_OP_RECV_CLOSE_ON_SERVER;
+  ops.data.recv_close_on_server.cancelled = &cancelled_;
+  ops.flags = 0;
+  ops.reserved = nullptr;
+  interceptor_methods_.SetCall(&call_);
+  interceptor_methods_.SetReverse();
+  interceptor_methods_.SetCallOpSetInterface(this);
+  GPR_ASSERT(GRPC_CALL_OK == grpc_call_start_batch(call->call(), &ops, 1,
+                                                   core_cq_tag_, nullptr));
+  /* No interceptors to run here */
 }
 
 bool ServerContext::CompletionOp::FinalizeResult(void** tag, bool* status) {
-  grpc::unique_lock<grpc::mutex> lock(mu_);
-  finalized_ = true;
   bool ret = false;
-  if (has_tag_) {
-    *tag = tag_;
-    ret = true;
+  std::unique_lock<std::mutex> lock(mu_);
+  if (done_intercepting_) {
+    /* We are done intercepting. */
+    if (has_tag_) {
+      *tag = tag_;
+      ret = true;
+    }
+    if (--refs_ == 0) {
+      lock.unlock();
+      grpc_call* call = call_.call();
+      delete this;
+      grpc_call_unref(call);
+    }
+    return ret;
   }
-  if (!*status) cancelled_ = 1;
-  if (--refs_ == 0) {
-    lock.unlock();
-    delete this;
+  finalized_ = true;
+
+  // If for some reason the incoming status is false, mark that as a
+  // cancellation.
+  // TODO(vjpai): does this ever happen?
+  if (!*status) {
+    cancelled_ = 1;
   }
-  return ret;
+
+  if (cancelled_ && (reactor_ != nullptr)) {
+    reactor_->OnCancel();
+  }
+  /* Release the lock since we are going to be running through interceptors now
+   */
+  lock.unlock();
+  /* Add interception point and run through interceptors */
+  interceptor_methods_.AddInterceptionHookPoint(
+      experimental::InterceptionHookPoints::POST_RECV_CLOSE);
+  if (interceptor_methods_.RunInterceptors()) {
+    /* No interceptors were run */
+    if (has_tag_) {
+      *tag = tag_;
+      ret = true;
+    }
+    lock.lock();
+    if (--refs_ == 0) {
+      lock.unlock();
+      grpc_call* call = call_.call();
+      delete this;
+      grpc_call_unref(call);
+    }
+    return ret;
+  }
+  /* There are interceptors to be run. Return false for now */
+  return false;
 }
 
 // ServerContext body
 
-ServerContext::ServerContext()
-    : completion_op_(nullptr),
-      has_notify_when_done_tag_(false),
-      async_notify_when_done_tag_(nullptr),
-      deadline_(gpr_inf_future(GPR_CLOCK_REALTIME)),
-      call_(nullptr),
-      cq_(nullptr),
-      sent_initial_metadata_(false) {}
+ServerContext::ServerContext() { Setup(gpr_inf_future(GPR_CLOCK_REALTIME)); }
 
-ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
-                             size_t metadata_count)
-    : completion_op_(nullptr),
-      has_notify_when_done_tag_(false),
-      async_notify_when_done_tag_(nullptr),
-      deadline_(deadline),
-      call_(nullptr),
-      cq_(nullptr),
-      sent_initial_metadata_(false) {
-  for (size_t i = 0; i < metadata_count; i++) {
-    client_metadata_.insert(std::pair<grpc::string_ref, grpc::string_ref>(
-        metadata[i].key,
-        grpc::string_ref(metadata[i].value, metadata[i].value_length)));
-  }
+ServerContext::ServerContext(gpr_timespec deadline, grpc_metadata_array* arr) {
+  Setup(deadline);
+  std::swap(*client_metadata_.arr(), *arr);
 }
 
-ServerContext::~ServerContext() {
-  if (call_) {
-    grpc_call_destroy(call_);
-  }
+void ServerContext::Setup(gpr_timespec deadline) {
+  completion_op_ = nullptr;
+  has_notify_when_done_tag_ = false;
+  async_notify_when_done_tag_ = nullptr;
+  deadline_ = deadline;
+  call_ = nullptr;
+  cq_ = nullptr;
+  sent_initial_metadata_ = false;
+  compression_level_set_ = false;
+  has_pending_ops_ = false;
+  rpc_info_ = nullptr;
+}
+
+void ServerContext::BindDeadlineAndMetadata(gpr_timespec deadline,
+                                            grpc_metadata_array* arr) {
+  deadline_ = deadline;
+  std::swap(*client_metadata_.arr(), *arr);
+}
+
+ServerContext::~ServerContext() { Clear(); }
+
+void ServerContext::Clear() {
+  auth_context_.reset();
+  initial_metadata_.clear();
+  trailing_metadata_.clear();
+  client_metadata_.Reset();
   if (completion_op_) {
     completion_op_->Unref();
+    completion_op_ = nullptr;
+    completion_tag_.Clear();
+  }
+  if (rpc_info_) {
+    rpc_info_->Unref();
+    rpc_info_ = nullptr;
+  }
+  if (call_) {
+    auto* call = call_;
+    call_ = nullptr;
+    grpc_call_unref(call);
   }
 }
 
-void ServerContext::BeginCompletionOp(Call* call) {
+void ServerContext::BeginCompletionOp(internal::Call* call,
+                                      std::function<void(bool)> callback,
+                                      internal::ServerReactor* reactor) {
   GPR_ASSERT(!completion_op_);
-  completion_op_ = new CompletionOp();
-  if (has_notify_when_done_tag_) {
+  if (rpc_info_) {
+    rpc_info_->Ref();
+  }
+  grpc_call_ref(call->call());
+  completion_op_ =
+      new (grpc_call_arena_alloc(call->call(), sizeof(CompletionOp)))
+          CompletionOp(call, reactor);
+  if (callback != nullptr) {
+    completion_tag_.Set(call->call(), std::move(callback), completion_op_);
+    completion_op_->set_core_cq_tag(&completion_tag_);
+    completion_op_->set_tag(completion_op_);
+  } else if (has_notify_when_done_tag_) {
     completion_op_->set_tag(async_notify_when_done_tag_);
   }
   call->PerformOps(completion_op_);
 }
 
+internal::CompletionQueueTag* ServerContext::GetCompletionOpTag() {
+  return static_cast<internal::CompletionQueueTag*>(completion_op_);
+}
+
 void ServerContext::AddInitialMetadata(const grpc::string& key,
                                        const grpc::string& value) {
   initial_metadata_.insert(std::make_pair(key, value));
@@ -174,45 +315,44 @@
 }
 
 void ServerContext::TryCancel() const {
+  internal::CancelInterceptorBatchMethods cancel_methods;
+  if (rpc_info_) {
+    for (size_t i = 0; i < rpc_info_->interceptors_.size(); i++) {
+      rpc_info_->RunInterceptor(&cancel_methods, i);
+    }
+  }
   grpc_call_error err = grpc_call_cancel_with_status(
-      call_, GRPC_STATUS_CANCELLED, "Cancelled on the server side", NULL);
+      call_, GRPC_STATUS_CANCELLED, "Cancelled on the server side", nullptr);
   if (err != GRPC_CALL_OK) {
     gpr_log(GPR_ERROR, "TryCancel failed with: %d", err);
   }
 }
 
 bool ServerContext::IsCancelled() const {
-  return completion_op_ && completion_op_->CheckCancelled(cq_);
-}
-
-void ServerContext::set_compression_level(grpc_compression_level level) {
-  const grpc_compression_algorithm algorithm_for_level =
-      grpc_compression_algorithm_for_level(level);
-  set_compression_algorithm(algorithm_for_level);
+  if (completion_tag_) {
+    // When using callback API, this result is always valid.
+    return completion_op_->CheckCancelledAsync();
+  } else if (has_notify_when_done_tag_) {
+    // When using async API, the result is only valid
+    // if the tag has already been delivered at the completion queue
+    return completion_op_ && completion_op_->CheckCancelledAsync();
+  } else {
+    // when using sync API, the result is always valid
+    return completion_op_ && completion_op_->CheckCancelled(cq_);
+  }
 }
 
 void ServerContext::set_compression_algorithm(
     grpc_compression_algorithm algorithm) {
-  char* algorithm_name = NULL;
+  compression_algorithm_ = algorithm;
+  const char* algorithm_name = nullptr;
   if (!grpc_compression_algorithm_name(algorithm, &algorithm_name)) {
     gpr_log(GPR_ERROR, "Name for compression algorithm '%d' unknown.",
             algorithm);
     abort();
   }
-  GPR_ASSERT(algorithm_name != NULL);
-  AddInitialMetadata(GRPC_COMPRESS_REQUEST_ALGORITHM_KEY, algorithm_name);
-}
-
-void ServerContext::set_call(grpc_call* call) {
-  call_ = call;
-  auth_context_ = CreateAuthContext(call);
-}
-
-std::shared_ptr<const AuthContext> ServerContext::auth_context() const {
-  if (auth_context_.get() == nullptr) {
-    auth_context_ = CreateAuthContext(call_);
-  }
-  return auth_context_;
+  GPR_ASSERT(algorithm_name != nullptr);
+  AddInitialMetadata(GRPC_COMPRESSION_REQUEST_ALGORITHM_MD_KEY, algorithm_name);
 }
 
 grpc::string ServerContext::peer() const {
@@ -229,4 +369,12 @@
   return grpc_census_call_get_context(call_);
 }
 
+void ServerContext::SetLoadReportingCosts(
+    const std::vector<grpc::string>& cost_data) {
+  if (call_ == nullptr) return;
+  for (const auto& cost_datum : cost_data) {
+    AddTrailingMetadata(GRPC_LB_COST_MD_KEY, cost_datum);
+  }
+}
+
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/server_credentials.cc b/third_party/grpc/src/cpp/server/server_credentials.cc
index 8495916..c3b3a8b 100644
--- a/third_party/grpc/src/cpp/server/server_credentials.cc
+++ b/third_party/grpc/src/cpp/server/server_credentials.cc
@@ -1,37 +1,22 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/security/server_credentials.h>
+#include <grpcpp/security/server_credentials.h>
 
 namespace grpc {
 
diff --git a/third_party/grpc/src/cpp/server/server_posix.cc b/third_party/grpc/src/cpp/server/server_posix.cc
new file mode 100644
index 0000000..7c221ed
--- /dev/null
+++ b/third_party/grpc/src/cpp/server/server_posix.cc
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/server_posix.h>
+
+#include <grpc/grpc_posix.h>
+
+namespace grpc {
+
+#ifdef GPR_SUPPORT_CHANNELS_FROM_FD
+
+void AddInsecureChannelFromFd(Server* server, int fd) {
+  grpc_server_add_insecure_channel_from_fd(server->c_server(), nullptr, fd);
+}
+
+#endif  // GPR_SUPPORT_CHANNELS_FROM_FD
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/server/thread_pool_interface.h b/third_party/grpc/src/cpp/server/thread_pool_interface.h
index 1ebe30f..028842a 100644
--- a/third_party/grpc/src/cpp/server/thread_pool_interface.h
+++ b/third_party/grpc/src/cpp/server/thread_pool_interface.h
@@ -1,33 +1,18 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
@@ -47,6 +32,10 @@
   virtual void Add(const std::function<void()>& callback) = 0;
 };
 
+// Allows different codebases to use their own thread pool impls
+typedef ThreadPoolInterface* (*CreateThreadPoolFunc)(void);
+void SetCreateThreadPool(CreateThreadPoolFunc func);
+
 ThreadPoolInterface* CreateDefaultThreadPool();
 
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/thread_manager/thread_manager.cc b/third_party/grpc/src/cpp/thread_manager/thread_manager.cc
new file mode 100644
index 0000000..3e8606a
--- /dev/null
+++ b/third_party/grpc/src/cpp/thread_manager/thread_manager.cc
@@ -0,0 +1,252 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/cpp/thread_manager/thread_manager.h"
+
+#include <climits>
+#include <mutex>
+
+#include <grpc/support/log.h>
+#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/iomgr/exec_ctx.h"
+
+namespace grpc {
+
+ThreadManager::WorkerThread::WorkerThread(ThreadManager* thd_mgr)
+    : thd_mgr_(thd_mgr) {
+  // Make thread creation exclusive with respect to its join happening in
+  // ~WorkerThread().
+  thd_ = grpc_core::Thread(
+      "grpcpp_sync_server",
+      [](void* th) { static_cast<ThreadManager::WorkerThread*>(th)->Run(); },
+      this);
+  thd_.Start();
+}
+
+void ThreadManager::WorkerThread::Run() {
+  thd_mgr_->MainWorkLoop();
+  thd_mgr_->MarkAsCompleted(this);
+}
+
+ThreadManager::WorkerThread::~WorkerThread() {
+  // Don't join until the thread is fully constructed.
+  thd_.Join();
+}
+
+ThreadManager::ThreadManager(const char* name,
+                             grpc_resource_quota* resource_quota,
+                             int min_pollers, int max_pollers)
+    : shutdown_(false),
+      num_pollers_(0),
+      min_pollers_(min_pollers),
+      max_pollers_(max_pollers == -1 ? INT_MAX : max_pollers),
+      num_threads_(0),
+      max_active_threads_sofar_(0) {
+  resource_user_ = grpc_resource_user_create(resource_quota, name);
+}
+
+ThreadManager::~ThreadManager() {
+  {
+    std::lock_guard<std::mutex> lock(mu_);
+    GPR_ASSERT(num_threads_ == 0);
+  }
+
+  grpc_core::ExecCtx exec_ctx;  // grpc_resource_user_unref needs an exec_ctx
+  grpc_resource_user_unref(resource_user_);
+  CleanupCompletedThreads();
+}
+
+void ThreadManager::Wait() {
+  std::unique_lock<std::mutex> lock(mu_);
+  while (num_threads_ != 0) {
+    shutdown_cv_.wait(lock);
+  }
+}
+
+void ThreadManager::Shutdown() {
+  std::lock_guard<std::mutex> lock(mu_);
+  shutdown_ = true;
+}
+
+bool ThreadManager::IsShutdown() {
+  std::lock_guard<std::mutex> lock(mu_);
+  return shutdown_;
+}
+
+int ThreadManager::GetMaxActiveThreadsSoFar() {
+  std::lock_guard<std::mutex> list_lock(list_mu_);
+  return max_active_threads_sofar_;
+}
+
+void ThreadManager::MarkAsCompleted(WorkerThread* thd) {
+  {
+    std::lock_guard<std::mutex> list_lock(list_mu_);
+    completed_threads_.push_back(thd);
+  }
+
+  {
+    std::lock_guard<std::mutex> lock(mu_);
+    num_threads_--;
+    if (num_threads_ == 0) {
+      shutdown_cv_.notify_one();
+    }
+  }
+
+  // Give a thread back to the resource quota
+  grpc_resource_user_free_threads(resource_user_, 1);
+}
+
+void ThreadManager::CleanupCompletedThreads() {
+  std::list<WorkerThread*> completed_threads;
+  {
+    // swap out the completed threads list: allows other threads to clean up
+    // more quickly
+    std::unique_lock<std::mutex> lock(list_mu_);
+    completed_threads.swap(completed_threads_);
+  }
+  for (auto thd : completed_threads) delete thd;
+}
+
+void ThreadManager::Initialize() {
+  if (!grpc_resource_user_allocate_threads(resource_user_, min_pollers_)) {
+    gpr_log(GPR_ERROR,
+            "No thread quota available to even create the minimum required "
+            "polling threads (i.e %d). Unable to start the thread manager",
+            min_pollers_);
+    abort();
+  }
+
+  {
+    std::unique_lock<std::mutex> lock(mu_);
+    num_pollers_ = min_pollers_;
+    num_threads_ = min_pollers_;
+    max_active_threads_sofar_ = min_pollers_;
+  }
+
+  for (int i = 0; i < min_pollers_; i++) {
+    new WorkerThread(this);
+  }
+}
+
+void ThreadManager::MainWorkLoop() {
+  while (true) {
+    void* tag;
+    bool ok;
+    WorkStatus work_status = PollForWork(&tag, &ok);
+
+    std::unique_lock<std::mutex> lock(mu_);
+    // Reduce the number of pollers by 1 and check what happened with the poll
+    num_pollers_--;
+    bool done = false;
+    switch (work_status) {
+      case TIMEOUT:
+        // If we timed out and we have more pollers than we need (or we are
+        // shutdown), finish this thread
+        if (shutdown_ || num_pollers_ > max_pollers_) done = true;
+        break;
+      case SHUTDOWN:
+        // If the thread manager is shutdown, finish this thread
+        done = true;
+        break;
+      case WORK_FOUND:
+        // If we got work and there are now insufficient pollers and there is
+        // quota available to create a new thread, start a new poller thread
+        bool resource_exhausted = false;
+        if (!shutdown_ && num_pollers_ < min_pollers_) {
+          if (grpc_resource_user_allocate_threads(resource_user_, 1)) {
+            // We can allocate a new poller thread
+            num_pollers_++;
+            num_threads_++;
+            if (num_threads_ > max_active_threads_sofar_) {
+              max_active_threads_sofar_ = num_threads_;
+            }
+            // Drop lock before spawning thread to avoid contention
+            lock.unlock();
+            new WorkerThread(this);
+          } else if (num_pollers_ > 0) {
+            // There is still at least some thread polling, so we can go on
+            // even though we are below the number of pollers that we would
+            // like to have (min_pollers_)
+            lock.unlock();
+          } else {
+            // There are no pollers to spare and we couldn't allocate
+            // a new thread, so resources are exhausted!
+            lock.unlock();
+            resource_exhausted = true;
+          }
+        } else {
+          // There are a sufficient number of pollers available so we can do
+          // the work and continue polling with our existing poller threads
+          lock.unlock();
+        }
+        // Lock is always released at this point - do the application work
+        // or return resource exhausted if there is new work but we couldn't
+        // get a thread in which to do it.
+        DoWork(tag, ok, !resource_exhausted);
+        // Take the lock again to check post conditions
+        lock.lock();
+        // If we're shutdown, we should finish at this point.
+        if (shutdown_) done = true;
+        break;
+    }
+    // If we decided to finish the thread, break out of the while loop
+    if (done) break;
+
+    // Otherwise go back to polling as long as it doesn't exceed max_pollers_
+    //
+    // **WARNING**:
+    // There is a possibility of threads thrashing here (i.e excessive thread
+    // shutdowns and creations than the ideal case). This happens if max_poller_
+    // count is small and the rate of incoming requests is also small. In such
+    // scenarios we can possibly configure max_pollers_ to a higher value and/or
+    // increase the cq timeout.
+    //
+    // However, not doing this check here and unconditionally incrementing
+    // num_pollers (and hoping that the system will eventually settle down) has
+    // far worse consequences i.e huge number of threads getting created to the
+    // point of thread-exhaustion. For example: if the incoming request rate is
+    // very high, all the polling threads will return very quickly from
+    // PollForWork() with WORK_FOUND. They all briefly decrement num_pollers_
+    // counter thereby possibly - and briefly - making it go below min_pollers;
+    // This will most likely result in the creation of a new poller since
+    // num_pollers_ dipped below min_pollers_.
+    //
+    // Now, If we didn't do the max_poller_ check here, all these threads will
+    // go back to doing PollForWork() and the whole cycle repeats (with a new
+    // thread being added in each cycle). Once the total number of threads in
+    // the system crosses a certain threshold (around ~1500), there is heavy
+    // contention on mutexes (the mu_ here or the mutexes in gRPC core like the
+    // pollset mutex) that makes DoWork() take longer to finish thereby causing
+    // new poller threads to be created even faster. This results in a thread
+    // avalanche.
+    if (num_pollers_ < max_pollers_) {
+      num_pollers_++;
+    } else {
+      break;
+    }
+  };
+
+  // This thread is exiting. Do some cleanup work i.e delete already completed
+  // worker threads
+  CleanupCompletedThreads();
+
+  // If we are here, either ThreadManager is shutting down or it already has
+  // enough threads.
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/thread_manager/thread_manager.h b/third_party/grpc/src/cpp/thread_manager/thread_manager.h
new file mode 100644
index 0000000..6f0bd17
--- /dev/null
+++ b/third_party/grpc/src/cpp/thread_manager/thread_manager.h
@@ -0,0 +1,178 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_THREAD_MANAGER_H
+#define GRPC_INTERNAL_CPP_THREAD_MANAGER_H
+
+#include <condition_variable>
+#include <list>
+#include <memory>
+#include <mutex>
+
+#include <grpcpp/support/config.h>
+
+#include "src/core/lib/gprpp/thd.h"
+#include "src/core/lib/iomgr/resource_quota.h"
+
+namespace grpc {
+
+class ThreadManager {
+ public:
+  explicit ThreadManager(const char* name, grpc_resource_quota* resource_quota,
+                         int min_pollers, int max_pollers);
+  virtual ~ThreadManager();
+
+  // Initializes and Starts the Rpc Manager threads
+  void Initialize();
+
+  // The return type of PollForWork() function
+  enum WorkStatus { WORK_FOUND, SHUTDOWN, TIMEOUT };
+
+  // "Polls" for new work.
+  // If the return value is WORK_FOUND:
+  //  - The implementaion of PollForWork() MAY set some opaque identifier to
+  //    (identify the work item found) via the '*tag' parameter
+  //  - The implementaion MUST set the value of 'ok' to 'true' or 'false'. A
+  //    value of 'false' indicates some implemenation specific error (that is
+  //    neither SHUTDOWN nor TIMEOUT)
+  //  - ThreadManager does not interpret the values of 'tag' and 'ok'
+  //  - ThreadManager WILL call DoWork() and pass '*tag' and 'ok' as input to
+  //    DoWork()
+  //
+  // If the return value is SHUTDOWN:,
+  //  - ThreadManager WILL NOT call DoWork() and terminates the thead
+  //
+  // If the return value is TIMEOUT:,
+  //  - ThreadManager WILL NOT call DoWork()
+  //  - ThreadManager MAY terminate the thread depending on the current number
+  //    of active poller threads and mix_pollers/max_pollers settings
+  //  - Also, the value of timeout is specific to the derived class
+  //    implementation
+  virtual WorkStatus PollForWork(void** tag, bool* ok) = 0;
+
+  // The implementation of DoWork() is supposed to perform the work found by
+  // PollForWork(). The tag and ok parameters are the same as returned by
+  // PollForWork(). The resources parameter indicates that the call actually
+  // has the resources available for performing the RPC's work. If it doesn't,
+  // the implementation should fail it appropriately.
+  //
+  // The implementation of DoWork() should also do any setup needed to ensure
+  // that the next call to PollForWork() (not necessarily by the current thread)
+  // actually finds some work
+  virtual void DoWork(void* tag, bool ok, bool resources) = 0;
+
+  // Mark the ThreadManager as shutdown and begin draining the work. This is a
+  // non-blocking call and the caller should call Wait(), a blocking call which
+  // returns only once the shutdown is complete
+  virtual void Shutdown();
+
+  // Has Shutdown() been called
+  bool IsShutdown();
+
+  // A blocking call that returns only after the ThreadManager has shutdown and
+  // all the threads have drained all the outstanding work
+  virtual void Wait();
+
+  // Max number of concurrent threads that were ever active in this thread
+  // manager so far. This is useful for debugging purposes (and in unit tests)
+  // to check if resource_quota is properly being enforced.
+  int GetMaxActiveThreadsSoFar();
+
+ private:
+  // Helper wrapper class around grpc_core::Thread. Takes a ThreadManager object
+  // and starts a new grpc_core::Thread to calls the Run() function.
+  //
+  // The Run() function calls ThreadManager::MainWorkLoop() function and once
+  // that completes, it marks the WorkerThread completed by calling
+  // ThreadManager::MarkAsCompleted()
+  //
+  // WHY IS THIS NEEDED?:
+  // When a thread terminates, some other thread *must* call Join() on that
+  // thread so that the resources are released. Having a WorkerThread wrapper
+  // will make this easier. Once Run() completes, each thread calls the
+  // following two functions:
+  //    ThreadManager::CleanupCompletedThreads()
+  //    ThreadManager::MarkAsCompleted()
+  //
+  //  - MarkAsCompleted() puts the WorkerThread object in the ThreadManger's
+  //    completed_threads_ list
+  //  - CleanupCompletedThreads() calls "Join()" on the threads that are already
+  //    in the completed_threads_ list  (since a thread cannot call Join() on
+  //    itself, it calls CleanupCompletedThreads() *before* calling
+  //    MarkAsCompleted())
+  //
+  // TODO(sreek): Consider creating the threads 'detached' so that Join() need
+  // not be called (and the need for this WorkerThread class is eliminated)
+  class WorkerThread {
+   public:
+    WorkerThread(ThreadManager* thd_mgr);
+    ~WorkerThread();
+
+   private:
+    // Calls thd_mgr_->MainWorkLoop() and once that completes, calls
+    // thd_mgr_>MarkAsCompleted(this) to mark the thread as completed
+    void Run();
+
+    ThreadManager* const thd_mgr_;
+    grpc_core::Thread thd_;
+  };
+
+  // The main funtion in ThreadManager
+  void MainWorkLoop();
+
+  void MarkAsCompleted(WorkerThread* thd);
+  void CleanupCompletedThreads();
+
+  // Protects shutdown_, num_pollers_, num_threads_ and
+  // max_active_threads_sofar_
+  std::mutex mu_;
+
+  bool shutdown_;
+  std::condition_variable shutdown_cv_;
+
+  // The resource user object to use when requesting quota to create threads
+  //
+  // Note: The user of this ThreadManager object must create grpc_resource_quota
+  // object (that contains the actual max thread quota) and a grpc_resource_user
+  // object through which quota is requested whenver new threads need to be
+  // created
+  grpc_resource_user* resource_user_;
+
+  // Number of threads doing polling
+  int num_pollers_;
+
+  // The minimum and maximum number of threads that should be doing polling
+  int min_pollers_;
+  int max_pollers_;
+
+  // The total number of threads currently active (includes threads includes the
+  // threads that are currently polling i.e num_pollers_)
+  int num_threads_;
+
+  // See GetMaxActiveThreadsSoFar()'s description.
+  // To be more specific, this variable tracks the max value num_threads_ was
+  // ever set so far
+  int max_active_threads_sofar_;
+
+  std::mutex list_mu_;
+  std::list<WorkerThread*> completed_threads_;
+};
+
+}  // namespace grpc
+
+#endif  // GRPC_INTERNAL_CPP_THREAD_MANAGER_H
diff --git a/third_party/grpc/src/cpp/util/byte_buffer.cc b/third_party/grpc/src/cpp/util/byte_buffer.cc
deleted file mode 100644
index 3a2318d..0000000
--- a/third_party/grpc/src/cpp/util/byte_buffer.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- *
- * Copyright 2015-2016, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/support/byte_buffer.h>
-#include <grpc/byte_buffer_reader.h>
-
-namespace grpc {
-
-ByteBuffer::ByteBuffer(const Slice* slices, size_t nslices) {
-  // TODO(yangg) maybe expose some core API to simplify this
-  std::vector<gpr_slice> c_slices(nslices);
-  for (size_t i = 0; i < nslices; i++) {
-    c_slices[i] = slices[i].slice_;
-  }
-  buffer_ = grpc_raw_byte_buffer_create(c_slices.data(), nslices);
-}
-
-ByteBuffer::~ByteBuffer() {
-  if (buffer_) {
-    grpc_byte_buffer_destroy(buffer_);
-  }
-}
-
-void ByteBuffer::Clear() {
-  if (buffer_) {
-    grpc_byte_buffer_destroy(buffer_);
-    buffer_ = nullptr;
-  }
-}
-
-void ByteBuffer::Dump(std::vector<Slice>* slices) const {
-  slices->clear();
-  if (!buffer_) {
-    return;
-  }
-  grpc_byte_buffer_reader reader;
-  grpc_byte_buffer_reader_init(&reader, buffer_);
-  gpr_slice s;
-  while (grpc_byte_buffer_reader_next(&reader, &s)) {
-    slices->push_back(Slice(s, Slice::STEAL_REF));
-  }
-  grpc_byte_buffer_reader_destroy(&reader);
-}
-
-size_t ByteBuffer::Length() const {
-  if (buffer_) {
-    return grpc_byte_buffer_length(buffer_);
-  } else {
-    return 0;
-  }
-}
-
-ByteBuffer::ByteBuffer(const ByteBuffer& buf)
-    : buffer_(grpc_byte_buffer_copy(buf.buffer_)) {}
-
-ByteBuffer& ByteBuffer::operator=(const ByteBuffer& buf) {
-  Clear();  // first remove existing data
-  if (buf.buffer_) {
-    buffer_ = grpc_byte_buffer_copy(buf.buffer_);  // then copy
-  }
-  return *this;
-}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/util/byte_buffer_cc.cc b/third_party/grpc/src/cpp/util/byte_buffer_cc.cc
new file mode 100644
index 0000000..a7e1645
--- /dev/null
+++ b/third_party/grpc/src/cpp/util/byte_buffer_cc.cc
@@ -0,0 +1,60 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/byte_buffer.h>
+#include <grpc/byte_buffer_reader.h>
+#include <grpcpp/impl/grpc_library.h>
+#include <grpcpp/support/byte_buffer.h>
+
+namespace grpc {
+
+static internal::GrpcLibraryInitializer g_gli_initializer;
+
+Status ByteBuffer::Dump(std::vector<Slice>* slices) const {
+  slices->clear();
+  if (!buffer_) {
+    return Status(StatusCode::FAILED_PRECONDITION, "Buffer not initialized");
+  }
+  grpc_byte_buffer_reader reader;
+  if (!grpc_byte_buffer_reader_init(&reader, buffer_)) {
+    return Status(StatusCode::INTERNAL,
+                  "Couldn't initialize byte buffer reader");
+  }
+  grpc_slice s;
+  while (grpc_byte_buffer_reader_next(&reader, &s)) {
+    slices->push_back(Slice(s, Slice::STEAL_REF));
+  }
+  grpc_byte_buffer_reader_destroy(&reader);
+  return Status::OK;
+}
+
+ByteBuffer::ByteBuffer(const ByteBuffer& buf) : buffer_(nullptr) {
+  operator=(buf);
+}
+
+ByteBuffer& ByteBuffer::operator=(const ByteBuffer& buf) {
+  if (this != &buf) {
+    Clear();  // first remove existing data
+  }
+  if (buf.buffer_) {
+    buffer_ = grpc_byte_buffer_copy(buf.buffer_);  // then copy
+  }
+  return *this;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/util/core_stats.cc b/third_party/grpc/src/cpp/util/core_stats.cc
new file mode 100644
index 0000000..edf0b1b
--- /dev/null
+++ b/third_party/grpc/src/cpp/util/core_stats.cc
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include "src/cpp/util/core_stats.h"
+
+#include <grpc/support/log.h>
+
+using grpc::core::Bucket;
+using grpc::core::Histogram;
+using grpc::core::Metric;
+using grpc::core::Stats;
+
+namespace grpc {
+
+void CoreStatsToProto(const grpc_stats_data& core, Stats* proto) {
+  for (int i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
+    Metric* m = proto->add_metrics();
+    m->set_name(grpc_stats_counter_name[i]);
+    m->set_count(core.counters[i]);
+  }
+  for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
+    Metric* m = proto->add_metrics();
+    m->set_name(grpc_stats_histogram_name[i]);
+    Histogram* h = m->mutable_histogram();
+    for (int j = 0; j < grpc_stats_histo_buckets[i]; j++) {
+      Bucket* b = h->add_buckets();
+      b->set_start(grpc_stats_histo_bucket_boundaries[i][j]);
+      b->set_count(core.histograms[grpc_stats_histo_start[i] + j]);
+    }
+  }
+}
+
+void ProtoToCoreStats(const grpc::core::Stats& proto, grpc_stats_data* core) {
+  memset(core, 0, sizeof(*core));
+  for (const auto& m : proto.metrics()) {
+    switch (m.value_case()) {
+      case Metric::VALUE_NOT_SET:
+        break;
+      case Metric::kCount:
+        for (int i = 0; i < GRPC_STATS_COUNTER_COUNT; i++) {
+          if (m.name() == grpc_stats_counter_name[i]) {
+            core->counters[i] = m.count();
+            break;
+          }
+        }
+        break;
+      case Metric::kHistogram:
+        for (int i = 0; i < GRPC_STATS_HISTOGRAM_COUNT; i++) {
+          if (m.name() == grpc_stats_histogram_name[i]) {
+            const auto& h = m.histogram();
+            bool valid = true;
+            if (grpc_stats_histo_buckets[i] != h.buckets_size()) valid = false;
+            for (int j = 0; valid && j < h.buckets_size(); j++) {
+              if (grpc_stats_histo_bucket_boundaries[i][j] !=
+                  h.buckets(j).start()) {
+                valid = false;
+              }
+            }
+            if (!valid) {
+              gpr_log(GPR_ERROR,
+                      "Found histogram %s but shape is different from proto",
+                      m.name().c_str());
+            }
+            for (int j = 0; valid && j < h.buckets_size(); j++) {
+              core->histograms[grpc_stats_histo_start[i] + j] =
+                  h.buckets(j).count();
+            }
+          }
+        }
+        break;
+    }
+  }
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/util/core_stats.h b/third_party/grpc/src/cpp/util/core_stats.h
new file mode 100644
index 0000000..6366d7d
--- /dev/null
+++ b/third_party/grpc/src/cpp/util/core_stats.h
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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 GRPC_INTERNAL_CPP_UTIL_CORE_STATS_H
+#define GRPC_INTERNAL_CPP_UTIL_CORE_STATS_H
+
+#include "src/proto/grpc/core/stats.pb.h"
+
+#include "src/core/lib/debug/stats.h"
+
+namespace grpc {
+
+void CoreStatsToProto(const grpc_stats_data& core, grpc::core::Stats* proto);
+void ProtoToCoreStats(const grpc::core::Stats& proto, grpc_stats_data* core);
+
+}  // namespace grpc
+
+#endif  // GRPC_INTERNAL_CPP_UTIL_CORE_STATS_H
diff --git a/third_party/grpc/src/cpp/util/error_details.cc b/third_party/grpc/src/cpp/util/error_details.cc
new file mode 100644
index 0000000..42c887a
--- /dev/null
+++ b/third_party/grpc/src/cpp/util/error_details.cc
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpcpp/support/error_details.h>
+
+#include "src/proto/grpc/status/status.pb.h"
+
+namespace grpc {
+
+Status ExtractErrorDetails(const Status& from, ::google::rpc::Status* to) {
+  if (to == nullptr) {
+    return Status(StatusCode::FAILED_PRECONDITION, "");
+  }
+  if (!to->ParseFromString(from.error_details())) {
+    return Status(StatusCode::INVALID_ARGUMENT, "");
+  }
+  return Status::OK;
+}
+
+Status SetErrorDetails(const ::google::rpc::Status& from, Status* to) {
+  if (to == nullptr) {
+    return Status(StatusCode::FAILED_PRECONDITION, "");
+  }
+  StatusCode code = StatusCode::UNKNOWN;
+  if (from.code() >= StatusCode::OK &&
+      from.code() <= StatusCode::UNAUTHENTICATED) {
+    code = static_cast<StatusCode>(from.code());
+  }
+  *to = Status(code, from.message(), from.SerializeAsString());
+  return Status::OK;
+}
+
+}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/util/slice.cc b/third_party/grpc/src/cpp/util/slice.cc
deleted file mode 100644
index 7e88423..0000000
--- a/third_party/grpc/src/cpp/util/slice.cc
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/support/slice.h>
-
-namespace grpc {
-
-Slice::Slice() : slice_(gpr_empty_slice()) {}
-
-Slice::~Slice() { gpr_slice_unref(slice_); }
-
-Slice::Slice(gpr_slice slice, AddRef) : slice_(gpr_slice_ref(slice)) {}
-
-Slice::Slice(gpr_slice slice, StealRef) : slice_(slice) {}
-
-Slice::Slice(const Slice& other) : slice_(gpr_slice_ref(other.slice_)) {}
-
-}  // namespace grpc
diff --git a/third_party/grpc/src/cpp/util/status.cc b/third_party/grpc/src/cpp/util/status.cc
index ad9850c..93696d8 100644
--- a/third_party/grpc/src/cpp/util/status.cc
+++ b/third_party/grpc/src/cpp/util/status.cc
@@ -1,37 +1,22 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/support/status.h>
+#include <grpcpp/support/status.h>
 
 namespace grpc {
 
diff --git a/third_party/grpc/src/cpp/util/string_ref.cc b/third_party/grpc/src/cpp/util/string_ref.cc
index 66c79a1..8b09a82 100644
--- a/third_party/grpc/src/cpp/util/string_ref.cc
+++ b/third_party/grpc/src/cpp/util/string_ref.cc
@@ -1,104 +1,25 @@
 /*
  *
- * Copyright 2015, Google Inc.
- * All rights reserved.
+ * Copyright 2015 gRPC authors.
  *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
+ * 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
  *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
+ *     http://www.apache.org/licenses/LICENSE-2.0
  *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * 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.
  *
  */
 
-#include <grpc++/support/string_ref.h>
-
-#include <string.h>
-
-#include <algorithm>
-#include <iostream>
+#include <grpcpp/support/string_ref.h>
 
 namespace grpc {
 
 const size_t string_ref::npos = size_t(-1);
 
-string_ref& string_ref::operator=(const string_ref& rhs) {
-  data_ = rhs.data_;
-  length_ = rhs.length_;
-  return *this;
-}
-
-string_ref::string_ref(const char* s) : data_(s), length_(strlen(s)) {}
-
-string_ref string_ref::substr(size_t pos, size_t n) const {
-  if (pos > length_) pos = length_;
-  if (n > (length_ - pos)) n = length_ - pos;
-  return string_ref(data_ + pos, n);
-}
-
-int string_ref::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 string_ref::starts_with(string_ref x) const {
-  return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0);
-}
-
-bool string_ref::ends_with(string_ref x) const {
-  return length_ >= x.length_ &&
-         (memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0);
-}
-
-size_t string_ref::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 string_ref::find(char c) const {
-  auto it = std::find(cbegin(), cend(), c);
-  return it == cend() ? npos : std::distance(cbegin(), it);
-}
-
-bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
-
-bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
-
-bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
-
-bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; }
-
-bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; }
-
-bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; }
-
-std::ostream& operator<<(std::ostream& out, const string_ref& string) {
-  return out << grpc::string(string.begin(), string.end());
-}
-
 }  // namespace grpc
diff --git a/third_party/grpc/src/cpp/util/time.cc b/third_party/grpc/src/cpp/util/time.cc
deleted file mode 100644
index 2685e31..0000000
--- a/third_party/grpc/src/cpp/util/time.cc
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- * Copyright 2015, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <grpc++/support/config.h>
-
-#ifndef GRPC_CXX0X_NO_CHRONO
-
-#include <grpc/support/time.h>
-#include <grpc++/support/time.h>
-
-using std::chrono::duration_cast;
-using std::chrono::nanoseconds;
-using std::chrono::seconds;
-using std::chrono::system_clock;
-using std::chrono::high_resolution_clock;
-
-namespace grpc {
-
-void Timepoint2Timespec(const system_clock::time_point& from,
-                        gpr_timespec* to) {
-  system_clock::duration deadline = from.time_since_epoch();
-  seconds secs = duration_cast<seconds>(deadline);
-  if (from == system_clock::time_point::max() ||
-      secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec ||
-      secs.count() < 0) {
-    *to = gpr_inf_future(GPR_CLOCK_REALTIME);
-    return;
-  }
-  nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);
-  to->tv_sec = (int64_t)secs.count();
-  to->tv_nsec = (int32_t)nsecs.count();
-  to->clock_type = GPR_CLOCK_REALTIME;
-}
-
-void TimepointHR2Timespec(const high_resolution_clock::time_point& from,
-                          gpr_timespec* to) {
-  high_resolution_clock::duration deadline = from.time_since_epoch();
-  seconds secs = duration_cast<seconds>(deadline);
-  if (from == high_resolution_clock::time_point::max() ||
-      secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec ||
-      secs.count() < 0) {
-    *to = gpr_inf_future(GPR_CLOCK_REALTIME);
-    return;
-  }
-  nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);
-  to->tv_sec = (int64_t)secs.count();
-  to->tv_nsec = (int32_t)nsecs.count();
-  to->clock_type = GPR_CLOCK_REALTIME;
-}
-
-system_clock::time_point Timespec2Timepoint(gpr_timespec t) {
-  if (gpr_time_cmp(t, gpr_inf_future(t.clock_type)) == 0) {
-    return system_clock::time_point::max();
-  }
-  t = gpr_convert_clock_type(t, GPR_CLOCK_REALTIME);
-  system_clock::time_point tp;
-  tp += duration_cast<system_clock::time_point::duration>(seconds(t.tv_sec));
-  tp +=
-      duration_cast<system_clock::time_point::duration>(nanoseconds(t.tv_nsec));
-  return tp;
-}
-
-}  // namespace grpc
-
-#endif  // !GRPC_CXX0X_NO_CHRONO
diff --git a/third_party/grpc/src/cpp/util/time_cc.cc b/third_party/grpc/src/cpp/util/time_cc.cc
new file mode 100644
index 0000000..6c9c228
--- /dev/null
+++ b/third_party/grpc/src/cpp/util/time_cc.cc
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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.
+ *
+ */
+
+#include <grpc/support/time.h>
+#include <grpcpp/support/config.h>
+#include <grpcpp/support/time.h>
+
+using std::chrono::duration_cast;
+using std::chrono::high_resolution_clock;
+using std::chrono::nanoseconds;
+using std::chrono::seconds;
+using std::chrono::system_clock;
+
+namespace grpc {
+
+void Timepoint2Timespec(const system_clock::time_point& from,
+                        gpr_timespec* to) {
+  system_clock::duration deadline = from.time_since_epoch();
+  seconds secs = duration_cast<seconds>(deadline);
+  if (from == system_clock::time_point::max() ||
+      secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec ||
+      secs.count() < 0) {
+    *to = gpr_inf_future(GPR_CLOCK_REALTIME);
+    return;
+  }
+  nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);
+  to->tv_sec = static_cast<int64_t>(secs.count());
+  to->tv_nsec = static_cast<int32_t>(nsecs.count());
+  to->clock_type = GPR_CLOCK_REALTIME;
+}
+
+void TimepointHR2Timespec(const high_resolution_clock::time_point& from,
+                          gpr_timespec* to) {
+  high_resolution_clock::duration deadline = from.time_since_epoch();
+  seconds secs = duration_cast<seconds>(deadline);
+  if (from == high_resolution_clock::time_point::max() ||
+      secs.count() >= gpr_inf_future(GPR_CLOCK_REALTIME).tv_sec ||
+      secs.count() < 0) {
+    *to = gpr_inf_future(GPR_CLOCK_REALTIME);
+    return;
+  }
+  nanoseconds nsecs = duration_cast<nanoseconds>(deadline - secs);
+  to->tv_sec = static_cast<int64_t>(secs.count());
+  to->tv_nsec = static_cast<int32_t>(nsecs.count());
+  to->clock_type = GPR_CLOCK_REALTIME;
+}
+
+system_clock::time_point Timespec2Timepoint(gpr_timespec t) {
+  if (gpr_time_cmp(t, gpr_inf_future(t.clock_type)) == 0) {
+    return system_clock::time_point::max();
+  }
+  t = gpr_convert_clock_type(t, GPR_CLOCK_REALTIME);
+  system_clock::time_point tp;
+  tp += duration_cast<system_clock::time_point::duration>(seconds(t.tv_sec));
+  tp +=
+      duration_cast<system_clock::time_point::duration>(nanoseconds(t.tv_nsec));
+  return tp;
+}
+
+}  // namespace grpc