Merge pull request #3172 from tbetbetbe/grpc_ruby_bump_version

Bumps the ruby version to beta
diff --git a/BUILD b/BUILD
index c30fd5b..72a496d 100644
--- a/BUILD
+++ b/BUILD
@@ -727,7 +727,6 @@
     "include/grpc++/client_context.h",
     "include/grpc++/completion_queue.h",
     "include/grpc++/create_channel.h",
-    "include/grpc++/credentials.h",
     "include/grpc++/generic/async_generic_service.h",
     "include/grpc++/generic/generic_stub.h",
     "include/grpc++/impl/call.h",
@@ -744,13 +743,15 @@
     "include/grpc++/impl/thd.h",
     "include/grpc++/impl/thd_cxx11.h",
     "include/grpc++/impl/thd_no_cxx11.h",
+    "include/grpc++/security/auth_context.h",
+    "include/grpc++/security/auth_metadata_processor.h",
+    "include/grpc++/security/credentials.h",
+    "include/grpc++/security/server_credentials.h",
     "include/grpc++/server.h",
     "include/grpc++/server_builder.h",
     "include/grpc++/server_context.h",
-    "include/grpc++/server_credentials.h",
     "include/grpc++/support/async_stream.h",
     "include/grpc++/support/async_unary_call.h",
-    "include/grpc++/support/auth_context.h",
     "include/grpc++/support/byte_buffer.h",
     "include/grpc++/support/channel_arguments.h",
     "include/grpc++/support/config.h",
@@ -816,7 +817,6 @@
     "include/grpc++/client_context.h",
     "include/grpc++/completion_queue.h",
     "include/grpc++/create_channel.h",
-    "include/grpc++/credentials.h",
     "include/grpc++/generic/async_generic_service.h",
     "include/grpc++/generic/generic_stub.h",
     "include/grpc++/impl/call.h",
@@ -833,13 +833,15 @@
     "include/grpc++/impl/thd.h",
     "include/grpc++/impl/thd_cxx11.h",
     "include/grpc++/impl/thd_no_cxx11.h",
+    "include/grpc++/security/auth_context.h",
+    "include/grpc++/security/auth_metadata_processor.h",
+    "include/grpc++/security/credentials.h",
+    "include/grpc++/security/server_credentials.h",
     "include/grpc++/server.h",
     "include/grpc++/server_builder.h",
     "include/grpc++/server_context.h",
-    "include/grpc++/server_credentials.h",
     "include/grpc++/support/async_stream.h",
     "include/grpc++/support/async_unary_call.h",
-    "include/grpc++/support/auth_context.h",
     "include/grpc++/support/byte_buffer.h",
     "include/grpc++/support/channel_arguments.h",
     "include/grpc++/support/config.h",
diff --git a/Makefile b/Makefile
index 1d1ce18..1c2fca3 100644
--- a/Makefile
+++ b/Makefile
@@ -4591,7 +4591,6 @@
     include/grpc++/client_context.h \
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
-    include/grpc++/credentials.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/impl/call.h \
@@ -4608,13 +4607,15 @@
     include/grpc++/impl/thd.h \
     include/grpc++/impl/thd_cxx11.h \
     include/grpc++/impl/thd_no_cxx11.h \
+    include/grpc++/security/auth_context.h \
+    include/grpc++/security/auth_metadata_processor.h \
+    include/grpc++/security/credentials.h \
+    include/grpc++/security/server_credentials.h \
     include/grpc++/server.h \
     include/grpc++/server_builder.h \
     include/grpc++/server_context.h \
-    include/grpc++/server_credentials.h \
     include/grpc++/support/async_stream.h \
     include/grpc++/support/async_unary_call.h \
-    include/grpc++/support/auth_context.h \
     include/grpc++/support/byte_buffer.h \
     include/grpc++/support/channel_arguments.h \
     include/grpc++/support/config.h \
@@ -4835,7 +4836,6 @@
     include/grpc++/client_context.h \
     include/grpc++/completion_queue.h \
     include/grpc++/create_channel.h \
-    include/grpc++/credentials.h \
     include/grpc++/generic/async_generic_service.h \
     include/grpc++/generic/generic_stub.h \
     include/grpc++/impl/call.h \
@@ -4852,13 +4852,15 @@
     include/grpc++/impl/thd.h \
     include/grpc++/impl/thd_cxx11.h \
     include/grpc++/impl/thd_no_cxx11.h \
+    include/grpc++/security/auth_context.h \
+    include/grpc++/security/auth_metadata_processor.h \
+    include/grpc++/security/credentials.h \
+    include/grpc++/security/server_credentials.h \
     include/grpc++/server.h \
     include/grpc++/server_builder.h \
     include/grpc++/server_context.h \
-    include/grpc++/server_credentials.h \
     include/grpc++/support/async_stream.h \
     include/grpc++/support/async_unary_call.h \
-    include/grpc++/support/auth_context.h \
     include/grpc++/support/byte_buffer.h \
     include/grpc++/support/channel_arguments.h \
     include/grpc++/support/config.h \
diff --git a/build.json b/build.json
index cec692b..1e00771 100644
--- a/build.json
+++ b/build.json
@@ -36,7 +36,6 @@
         "include/grpc++/client_context.h",
         "include/grpc++/completion_queue.h",
         "include/grpc++/create_channel.h",
-        "include/grpc++/credentials.h",
         "include/grpc++/generic/async_generic_service.h",
         "include/grpc++/generic/generic_stub.h",
         "include/grpc++/impl/call.h",
@@ -53,13 +52,15 @@
         "include/grpc++/impl/thd.h",
         "include/grpc++/impl/thd_cxx11.h",
         "include/grpc++/impl/thd_no_cxx11.h",
+        "include/grpc++/security/auth_context.h",
+        "include/grpc++/security/auth_metadata_processor.h",
+        "include/grpc++/security/credentials.h",
+        "include/grpc++/security/server_credentials.h",
         "include/grpc++/server.h",
         "include/grpc++/server_builder.h",
         "include/grpc++/server_context.h",
-        "include/grpc++/server_credentials.h",
         "include/grpc++/support/async_stream.h",
         "include/grpc++/support/async_unary_call.h",
-        "include/grpc++/support/auth_context.h",
         "include/grpc++/support/byte_buffer.h",
         "include/grpc++/support/channel_arguments.h",
         "include/grpc++/support/config.h",
diff --git a/examples/README.md b/examples/README.md
index 6465115..cc4b239 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -10,16 +10,16 @@
 <a name="quickstart"></a>
 ## Quick start
 You can find quick start guides for each language, including installation instructions, examples, and tutorials here:
-* [C++](examples/cpp)
+* [C++](cpp)
 * [Java](https://github.com/grpc/grpc-java/tree/master/examples)
 * [Go](https://github.com/grpc/grpc-go/tree/master/examples)
-* [Ruby](examples/ruby)
-* [Node.js](examples/node)
-* [Android Java](examples/java/android)
-* [Python](examples/python/helloworld)
-* [C#](examples/csharp)
-* [Objective-C](examples/objective-c/route_guide)
-* [PHP](examples/php)
+* [Ruby](ruby)
+* [Node.js](node)
+* [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
+* [Python](python/helloworld)
+* [C#](csharp)
+* [Objective-C](objective-c/route_guide)
+* [PHP](php)
 
 ## What's in this repository?
 
diff --git a/examples/cpp/README.md b/examples/cpp/README.md
index 70418b4..85c4950 100644
--- a/examples/cpp/README.md
+++ b/examples/cpp/README.md
@@ -2,12 +2,11 @@
 
 ## Installation
 
-To install gRPC on your system, follow the instructions here:
-[https://github.com/grpc/grpc/blob/master/INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL).
+To install gRPC on your system, follow the instructions [here](../../INSTALL).
 
 ## Hello C++ gRPC!
 
-Here's how to build and run the C++ implementation of the [Hello World](examples/protos/helloworld.proto) example used in [Getting started](https://github.com/grpc/grpc/tree/master/examples).
+Here's how to build and run the C++ implementation of the [Hello World](../protos/helloworld.proto) example used in [Getting started](..).
 
 The example code for this and our other examples lives in the `examples`
 directory. Clone this repository to your local machine by running the
@@ -41,9 +40,9 @@
 
 ### Client and server implementations
 
-The client implementation is at [greeter_client.cc](examples/cpp/helloworld/greeter_client.cc).
+The client implementation is at [greeter_client.cc](helloworld/greeter_client.cc).
 
-The server implementation is at [greeter_server.cc](examples/cpp/helloworld/greeter_server.cc).
+The server implementation is at [greeter_server.cc](helloworld/greeter_server.cc).
 
 ### Try it!
 Build client and server:
@@ -62,4 +61,4 @@
 
 ## Tutorial
 
-You can find a more detailed tutorial in [gRPC Basics: C++](examples/cpp/cpptutorial.md)
+You can find a more detailed tutorial in [gRPC Basics: C++](cpptutorial.md)
diff --git a/examples/cpp/cpptutorial.md b/examples/cpp/cpptutorial.md
index 22be42d..78de014 100644
--- a/examples/cpp/cpptutorial.md
+++ b/examples/cpp/cpptutorial.md
@@ -6,7 +6,7 @@
 - Generate server and client code using the protocol buffer compiler.
 - Use the C++ gRPC API to write a simple client and server for your service.
 
-It assumes that you have read the [Getting started](https://github.com/grpc/grpc/tree/master/examples) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository.
+It assumes that you have read the [Getting started](..) guide and are familiar with [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto3 version of the protocol buffers language, which is currently in alpha release: you can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3) and see the [release notes](https://github.com/google/protobuf/releases) for the new version in the protocol buffers Github repository.
 
 This isn't a comprehensive guide to using gRPC in C++: more reference documentation is coming soon.
 
@@ -18,7 +18,7 @@
 
 ## Example code and setup
 
-The example code for our tutorial is in [examples/cpp/route_guide](examples/cpp/route_guide). To download the example, clone this repository by running the following command:
+The example code for our tutorial is in [examples/cpp/route_guide](route_guide). To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
 ```
@@ -28,12 +28,12 @@
 $ cd examples/cpp/route_guide
 ```
 
-You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the C++ quick start guide](examples/cpp).
+You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [gRPC in 3 minutes](README.md).
 
 
 ## Defining the service
 
-Our first step (as you'll know from [Getting started](examples/) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto).
+Our first step (as you'll know from [Getting started](..) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](../protos/route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -91,7 +91,7 @@
 
 Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C++ plugin.
 
-For simplicity, we've provided a [makefile](examples/cpp/route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](https://github.com/grpc/grpc/blob/master/INSTALL) first):
+For simplicity, we've provided a [makefile](route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](../../INSTALL) first):
 
 ```shell
 $ make route_guide.grpc.pb.cc route_guide.pb.cc
@@ -126,7 +126,7 @@
 - Implementing the service interface generated from our service definition: doing the actual "work" of our service.
 - Running a gRPC server to listen for requests from clients and return the service responses.
 
-You can find our example `RouteGuide` server in [examples/cpp/route_guide/route_guide_server.cc](examples/cpp/route_guide/route_guide_server.cc). Let's take a closer look at how it works.
+You can find our example `RouteGuide` server in [route_guide/route_guide_server.cc](route_guide/route_guide_server.cc). Let's take a closer look at how it works.
 
 ### Implementing RouteGuide
 
@@ -236,16 +236,16 @@
 <a name="client"></a>
 ## Creating the client
 
-In this section, we'll look at creating a C++ client for our `RouteGuide` service. You can see our complete example client code in [examples/cpp/route_guide/route_guide_client.cc](examples/cpp/route_guide/route_guide_client.cc).
+In this section, we'll look at creating a C++ client for our `RouteGuide` service. You can see our complete example client code in [route_guide/route_guide_client.cc](route_guide/route_guide_client.cc).
 
 ### Creating a stub
 
 To call service methods, we first need to create a *stub*.
 
-First we need to create a gRPC *channel* for our stub, specifying the server address and port we want to connect to and any special channel arguments - in our case we'll use the default `ChannelArguments` and no SSL:
+First we need to create a gRPC *channel* for our stub, specifying the server address and port we want to connect to without SSL:
 
 ```cpp
-grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials(), ChannelArguments());
+grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials());
 ```
 
 Now we can use the channel to create our stub using the `NewStub` method provided in the `RouteGuide` class we generated from our .proto.
diff --git a/examples/cpp/helloworld/README.md b/examples/cpp/helloworld/README.md
index 641aadd..b16c084 100644
--- a/examples/cpp/helloworld/README.md
+++ b/examples/cpp/helloworld/README.md
@@ -2,7 +2,7 @@
 
 ### Install gRPC
 Make sure you have installed gRPC on your system. Follow the instructions here:
-[https://github.com/grpc/grpc/blob/master/INSTALL](https://github.com/grpc/grpc/blob/master/INSTALL).
+[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL).
 
 ### Get the tutorial source code
 
@@ -34,7 +34,7 @@
 server use interface code generated from the service definition.
 
 Here's our example service definition, defined using protocol buffers IDL in
-[helloworld.proto](examples/protos/helloworld.proto). The `Greeting`
+[helloworld.proto](../../protos/helloworld.proto). The `Greeting`
 service has one method, `hello`, that lets the server receive a single
 `HelloRequest`
 message from the remote client containing the user's name, then send back
@@ -94,7 +94,7 @@
   arguments as follows
 
     ```
-    auto channel = CreateChannel("localhost:50051", InsecureCredentials(), ChannelArguments());
+    auto channel = CreateChannel("localhost:50051", InsecureCredentials());
     ```
 
 - Create a stub. A stub implements the rpc methods of a service and in the
@@ -124,7 +124,7 @@
     }
     ```
 
-For a working example, refer to [greeter_client.cc](examples/cpp/helloworld/greeter_client.cc).
+For a working example, refer to [greeter_client.cc](greeter_client.cc).
 
 ### Writing a server
 
@@ -152,7 +152,7 @@
     std::unique_ptr<Server> server(builder.BuildAndStart());
     ```
 
-For a working example, refer to [greeter_server.cc](examples/cpp/helloworld/greeter_server.cc).
+For a working example, refer to [greeter_server.cc](greeter_server.cc).
 
 ### Writing asynchronous client and server
 
@@ -194,7 +194,7 @@
     }
     ```
 
-For a working example, refer to [greeter_async_client.cc](examples/cpp/helloworld/greeter_async_client.cc).
+For a working example, refer to [greeter_async_client.cc](greeter_async_client.cc).
 
 #### Async server
 
@@ -253,7 +253,7 @@
 simplicity the server only uses one completion queue for all events, and runs a
 main loop in `HandleRpcs` to query the queue.
 
-For a working example, refer to [greeter_async_server.cc](examples/cpp/helloworld/greeter_async_server.cc).
+For a working example, refer to [greeter_async_server.cc](greeter_async_server.cc).
 
 
 
diff --git a/examples/cpp/helloworld/greeter_async_client.cc b/examples/cpp/helloworld/greeter_async_client.cc
index d99f89b..875599e 100644
--- a/examples/cpp/helloworld/greeter_async_client.cc
+++ b/examples/cpp/helloworld/greeter_async_client.cc
@@ -45,7 +45,6 @@
 #include "helloworld.grpc.pb.h"
 
 using grpc::Channel;
-using grpc::ChannelArguments;
 using grpc::ClientAsyncResponseReader;
 using grpc::ClientContext;
 using grpc::CompletionQueue;
@@ -89,7 +88,7 @@
 
 int main(int argc, char** argv) {
   GreeterClient greeter(grpc::CreateChannel(
-      "localhost:50051", grpc::InsecureCredentials(), ChannelArguments()));
+      "localhost:50051", grpc::InsecureCredentials()));
   std::string user("world");
   std::string reply = greeter.SayHello(user);
   std::cout << "Greeter received: " << reply << std::endl;
diff --git a/examples/cpp/helloworld/greeter_client.cc b/examples/cpp/helloworld/greeter_client.cc
index dd0358a..3d2fcba 100644
--- a/examples/cpp/helloworld/greeter_client.cc
+++ b/examples/cpp/helloworld/greeter_client.cc
@@ -43,7 +43,6 @@
 #include "helloworld.grpc.pb.h"
 
 using grpc::Channel;
-using grpc::ChannelArguments;
 using grpc::ClientContext;
 using grpc::Status;
 using helloworld::HelloRequest;
@@ -75,8 +74,7 @@
 
 int main(int argc, char** argv) {
   GreeterClient greeter(
-      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials(),
-                          ChannelArguments()));
+      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()));
   std::string user("world");
   std::string reply = greeter.SayHello(user);
   std::cout << "Greeter received: " << reply << std::endl;
diff --git a/examples/cpp/route_guide/route_guide_client.cc b/examples/cpp/route_guide/route_guide_client.cc
index 814def2..ec0a75e 100644
--- a/examples/cpp/route_guide/route_guide_client.cc
+++ b/examples/cpp/route_guide/route_guide_client.cc
@@ -47,7 +47,6 @@
 #include "route_guide.grpc.pb.h"
 
 using grpc::Channel;
-using grpc::ChannelArguments;
 using grpc::ClientContext;
 using grpc::ClientReader;
 using grpc::ClientReaderWriter;
@@ -235,8 +234,7 @@
   // Expect only arg: --db_path=path/to/route_guide_db.json.
   std::string db = examples::GetDbFileContent(argc, argv);
   RouteGuideClient guide(
-      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials(),
-                          ChannelArguments()),
+      grpc::CreateChannel("localhost:50051", grpc::InsecureCredentials()),
       db);
 
   std::cout << "-------------- GetFeature --------------" << std::endl;
diff --git a/examples/csharp/README.md b/examples/csharp/README.md
index fcdcc73..3719080 100644
--- a/examples/csharp/README.md
+++ b/examples/csharp/README.md
@@ -69,4 +69,4 @@
 Tutorial
 --------
 
-You can find a more detailed tutorial in [gRPC Basics: C#](examples/csharp/route_guide/README.md)
+You can find a more detailed tutorial in [gRPC Basics: C#](route_guide/README.md)
diff --git a/examples/csharp/route_guide/README.md b/examples/csharp/route_guide/README.md
index c3262c9..ec9a0c0 100644
--- a/examples/csharp/route_guide/README.md
+++ b/examples/csharp/route_guide/README.md
@@ -18,7 +18,7 @@
 
 ## Example code and setup
 
-The example code for our tutorial is in [examples/csharp/route_guide](examples/csharp/route_guide). To download the example, clone this repository by running the following command:
+The example code for our tutorial is in [examples/csharp/route_guide](.). To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
 ```
@@ -34,7 +34,7 @@
 
 ## Defining the service
 
-Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/csharp/route_guide/RouteGuide/protos/route_guide.proto`](examples/csharp/route_guide/RouteGuide/protos/route_guide.proto).
+Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`RouteGuide/protos/route_guide.proto`](RouteGuide/protos/route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -127,7 +127,7 @@
 - Implementing the service interface generated from our service definition: doing the actual "work" of our service.
 - Running a gRPC server to listen for requests from clients and return the service responses.
 
-You can find our example `RouteGuide` server in [examples/csharp/route_guide/RouteGuideServer/RouteGuideImpl.cs](examples/csharp/route_guide/RouteGuideServer/RouteGuideServerImpl.cs). Let's take a closer look at how it works.
+You can find our example `RouteGuide` server in [RouteGuideServer/RouteGuideImpl.cs](RouteGuideServer/RouteGuideServerImpl.cs). Let's take a closer look at how it works.
 
 ### Implementing RouteGuide
 
@@ -288,7 +288,7 @@
 <a name="client"></a>
 ## Creating the client
 
-In this section, we'll look at creating a C# client for our `RouteGuide` service. You can see our complete example client code in [examples/csharp/route_guide/RouteGuideClient/Program.cs](examples/csharp/route_guide/RouteGuideClient/Program.cs).
+In this section, we'll look at creating a C# client for our `RouteGuide` service. You can see our complete example client code in [RouteGuideClient/Program.cs](RouteGuideClient/Program.cs).
 
 ### Creating a stub
 
diff --git a/examples/node/greeter_client.js b/examples/node/greeter_client.js
index ab7050a..ddc8abb 100644
--- a/examples/node/greeter_client.js
+++ b/examples/node/greeter_client.js
@@ -37,7 +37,8 @@
 var hello_proto = grpc.load(PROTO_PATH).helloworld;
 
 function main() {
-  var client = new hello_proto.Greeter('localhost:50051');
+  var client = new hello_proto.Greeter('localhost:50051',
+                                       grpc.Credentials.createInsecure());
   var user;
   if (process.argv.length >= 3) {
     user = process.argv[2];
diff --git a/examples/node/greeter_server.js b/examples/node/greeter_server.js
index 2fb95f0..44b44af 100644
--- a/examples/node/greeter_server.js
+++ b/examples/node/greeter_server.js
@@ -36,8 +36,6 @@
 var grpc = require('grpc');
 var hello_proto = grpc.load(PROTO_PATH).helloworld;
 
-var Server = grpc.buildServer([hello_proto.Greeter.service]);
-
 /**
  * Implements the SayHello RPC method.
  */
@@ -50,14 +48,10 @@
  * sample server port
  */
 function main() {
-  var server = new Server({
-    "helloworld.Greeter": {
-      sayHello: sayHello
-    }
-  });
-
-  server.bind('0.0.0.0:50051');
-  server.listen();
+  var server = new grpc.Server();
+  server.addProtoService(hello_proto.Greeter.service, {sayHello: sayHello});
+  server.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
+  server.start();
 }
 
 main();
diff --git a/examples/node/package.json b/examples/node/package.json
index caf5395..6c4f95b 100644
--- a/examples/node/package.json
+++ b/examples/node/package.json
@@ -3,7 +3,7 @@
   "version": "0.5.0",
   "dependencies": {
     "async": "^0.9.0",
-    "grpc": "~0.9.0",
+    "grpc": "~0.11.0",
     "minimist": "^1.1.0",
     "underscore": "^1.8.2"
   }
diff --git a/examples/node/route_guide/README.md b/examples/node/route_guide/README.md
index 2efc5a5..1dbaac9 100644
--- a/examples/node/route_guide/README.md
+++ b/examples/node/route_guide/README.md
@@ -17,7 +17,7 @@
 
 ## Example code and setup
 
-The example code for our tutorial is in [examples/node/route_guide](examples/node/route_guide). To download the example, clone this repository by running the following command:
+The example code for our tutorial is in [examples/node/route_guide](.). To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
 ```
@@ -27,12 +27,12 @@
 $ cd examples/node/route_guide
 ```
 
-You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Node.js quick start guide](examples/node).
+You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Node.js quick start guide](..).
 
 
 ## Defining the service
 
-Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto).
+Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](../../route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -110,7 +110,7 @@
 - Implementing the service interface generated from our service definition: doing the actual "work" of our service.
 - Running a gRPC server to listen for requests from clients and return the service responses.
 
-You can find our example `RouteGuide` server in [examples/node/route_guide/route_guide_server.js](examples/node/route_guide/route_guide_server.js). Let's take a closer look at how it works.
+You can find our example `RouteGuide` server in [route_guide_server.js](route_guide_server.js). Let's take a closer look at how it works.
 
 ### Implementing RouteGuide
 
@@ -244,7 +244,7 @@
 <a name="client"></a>
 ## Creating the client
 
-In this section, we'll look at creating a Node.js client for our `RouteGuide` service. You can see our complete example client code in [examples/node/route_guide/route_guide_client.js](examples/node/route_guide/route_guide_client.js).
+In this section, we'll look at creating a Node.js client for our `RouteGuide` service. You can see our complete example client code in [route_guide_client.js](route_guide_client.js).
 
 ### Creating a stub
 
diff --git a/examples/node/route_guide/route_guide_client.js b/examples/node/route_guide/route_guide_client.js
index 60c47a4..3550d79 100644
--- a/examples/node/route_guide/route_guide_client.js
+++ b/examples/node/route_guide/route_guide_client.js
@@ -34,7 +34,8 @@
 var _ = require('underscore');
 var grpc = require('grpc');
 var examples = grpc.load(__dirname + '/route_guide.proto').examples;
-var client = new examples.RouteGuide('localhost:50051');
+var client = new examples.RouteGuide('localhost:50051',
+                                     grpc.Credentials.createInsecure());
 
 var COORD_FACTOR = 1e7;
 
diff --git a/examples/node/route_guide/route_guide_server.js b/examples/node/route_guide/route_guide_server.js
index 5dd8412..38e1f94 100644
--- a/examples/node/route_guide/route_guide_server.js
+++ b/examples/node/route_guide/route_guide_server.js
@@ -34,8 +34,6 @@
 var grpc = require('grpc');
 var examples = grpc.load(__dirname + '/route_guide.proto').examples;
 
-var Server = grpc.buildServer([examples.RouteGuide.service]);
-
 var COORD_FACTOR = 1e7;
 
 /**
@@ -222,27 +220,27 @@
  * @return {Server} The new server object
  */
 function getServer() {
-  return new Server({
-    'examples.RouteGuide' : {
-      getFeature: getFeature,
-      listFeatures: listFeatures,
-      recordRoute: recordRoute,
-      routeChat: routeChat
-    }
+  var server = new grpc.Server();
+  server.addProtoService(examples.RouteGuide.service, {
+    getFeature: getFeature,
+    listFeatures: listFeatures,
+    recordRoute: recordRoute,
+    routeChat: routeChat
   });
+  return server;
 }
 
 if (require.main === module) {
   // If this is run as a script, start a server on an unused port
   var routeServer = getServer();
-  routeServer.bind('0.0.0.0:50051');
+  routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
   var argv = parseArgs(process.argv, {
     string: 'db_path'
   });
   fs.readFile(path.resolve(argv.db_path), function(err, data) {
     if (err) throw err;
     feature_list = JSON.parse(data);
-    routeServer.listen();
+    routeServer.start();
   });
 }
 
diff --git a/examples/objective-c/auth_sample/README.md b/examples/objective-c/auth_sample/README.md
index 3dbe7e3..5ae6452 100644
--- a/examples/objective-c/auth_sample/README.md
+++ b/examples/objective-c/auth_sample/README.md
@@ -9,8 +9,8 @@
 - Read response metadata from a call, which is equivalent to HTTP response headers and trailers.
 
 It assumes you know the basics on how to make gRPC API calls using the Objective-C client library,
-as shown in the [Hello World](examples/objective-c/helloworld)
-or [Route Guide](examples/objective-c/route_guide) tutorials,
+as shown in the [Hello World](../helloworld)
+or [Route Guide](../route_guide) tutorials,
 and are familiar with OAuth2 concepts like _access token_.
 
 - [Example code and setup](#setup)
@@ -22,7 +22,7 @@
 <a name="setup"></a>
 ## Example code and setup
 
-The example code for our tutorial is in [examples/objective-c/auth_sample](examples/objective-c/auth_sample).
+The example code for our tutorial is in [examples/objective-c/auth_sample](.).
 To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
diff --git a/examples/objective-c/helloworld/README.md b/examples/objective-c/helloworld/README.md
index 3b852f8..75df1a7 100644
--- a/examples/objective-c/helloworld/README.md
+++ b/examples/objective-c/helloworld/README.md
@@ -8,7 +8,7 @@
 
 ## Hello Objective-C gRPC!
 
-Here's how to build and run the Objective-C implementation of the [Hello World](examples/protos/helloworld.proto)
+Here's how to build and run the Objective-C implementation of the [Hello World](../../protos/helloworld.proto)
 example used in [Getting started](https://github.com/grpc/grpc/tree/master/examples).
 
 The example code for this and our other examples lives in the `examples` directory. Clone
@@ -53,4 +53,4 @@
 
 ## Tutorial
 
-You can find a more detailed tutorial in [gRPC Basics: Objective-C](examples/objective-c/route_guide/README.md).
+You can find a more detailed tutorial in [gRPC Basics: Objective-C](../route_guide/README.md).
diff --git a/examples/objective-c/route_guide/README.md b/examples/objective-c/route_guide/README.md
index dd20a07..15864c0 100644
--- a/examples/objective-c/route_guide/README.md
+++ b/examples/objective-c/route_guide/README.md
@@ -43,7 +43,7 @@
 <a name="setup"></a>
 ## Example code and setup
 
-The example code for our tutorial is in [examples/objective-c/route_guide](examples/objective-c/route_guide).
+The example code for our tutorial is in [examples/objective-c/route_guide](.).
 To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
@@ -97,7 +97,7 @@
 
 First let's look at how the service we're using is defined. A gRPC *service* and its method
 *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview).
-You can see the complete .proto file for our example in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto).
+You can see the complete .proto file for our example in [`examples/protos/route_guide.proto`](../../protos/route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -177,7 +177,7 @@
 Next we need to generate the gRPC client interfaces from our .proto service definition. We do this
 using the protocol buffer compiler (`protoc`) with a special gRPC Objective-C plugin.
 
-For simplicity, we've provided a [Podspec file](examples/objective-c/route_guide/RouteGuide.podspec)
+For simplicity, we've provided a [Podspec file](RouteGuide.podspec)
 that runs `protoc` for you with the appropriate plugin, input, and output, and describes how to
 compile the generated files. You just need to run in this directory (`examples/objective-c/route_guide`):
 
@@ -211,7 +211,7 @@
 ## Creating the client
 
 In this section, we'll look at creating an Objective-C client for our `RouteGuide` service. You can
-see our complete example client code in [examples/objective-c/route_guide/ViewControllers.m](examples/objective-c/route_guide/ViewControllers.m).
+see our complete example client code in [ViewControllers.m](ViewControllers.m).
 (Note: In your apps, for maintainability and readability reasons, you shouldn't put all of your view
 controllers in a single file; it's done here only to simplify the learning process).
 
diff --git a/examples/php/route_guide/README.md b/examples/php/route_guide/README.md
index e5230ae..258158d 100644
--- a/examples/php/route_guide/README.md
+++ b/examples/php/route_guide/README.md
@@ -8,7 +8,7 @@
 
 It assumes a passing familiarity with [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). Note that the example in this tutorial uses the proto2 version of the protocol buffers language.
 
-Also note that currently you can only create clients in PHP for gRPC services - you can find out how to create gRPC servers in our other tutorials, e.g. [Node.js](examples/node/route_guide).
+Also note that currently you can only create clients in PHP for gRPC services - you can find out how to create gRPC servers in our other tutorials, e.g. [Node.js](../node/route_guide).
 
 This isn't a comprehensive guide to using gRPC in PHP: more reference documentation is coming soon.
 
@@ -29,7 +29,7 @@
 <a name="setup"></a>
 ## Example code and setup
 
-The example code for our tutorial is in [examples/php/route_guide](examples/php/route_guide). To download the example, clone this repository by running the following command:
+The example code for our tutorial is in [examples/php/route_guide](.). To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
 ```
@@ -68,7 +68,7 @@
 <a name="proto"></a>
 ## Defining the service
 
-First let's look at how the service we're using is defined. A gRPC *service* and its method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file for our example in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto).
+First let's look at how the service we're using is defined. A gRPC *service* and its method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file for our example in [`route_guide.proto`](route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -159,7 +159,7 @@
 <a name="client"></a>
 ## Creating the client
 
-In this section, we'll look at creating a PHP client for our `RouteGuide` service. You can see our complete example client code in [examples/php/route_guide/route_guide_client.php](examples/php/route_guide/route_guide_client.php).
+In this section, we'll look at creating a PHP client for our `RouteGuide` service. You can see our complete example client code in [route_guide_client.php](route_guide_client.php).
 
 ### Constructing a client object
 
diff --git a/examples/python/helloworld/README.md b/examples/python/helloworld/README.md
index d199c40..8fde0d2 100644
--- a/examples/python/helloworld/README.md
+++ b/examples/python/helloworld/README.md
@@ -1,6 +1,6 @@
 # gRPC Python Hello World
 
-This is a quick introduction with a simple example and installation instructions: for a more complete tutorial see [gRPC Basics: Python](examples/python/route_guide).
+This is a quick introduction with a simple example and installation instructions: for a more complete tutorial see [gRPC Basics: Python](../route_guide).
 
 ### Install gRPC
 Make sure you have built gRPC Python from source on your system. Follow the instructions here:
@@ -96,7 +96,7 @@
 
 ### The client
 
-Client-side code can be found in [greeter_client.py](examples/python/helloworld/greeter_client.py).
+Client-side code can be found in [greeter_client.py](greeter_client.py).
 
 You can run the client using:
 
@@ -107,7 +107,7 @@
 
 ### The server
 
-Server side code can be found in [greeter_server.py](examples/python/helloworld/greeter_server.py). 
+Server side code can be found in [greeter_server.py](greeter_server.py). 
 
 You can run the server using:
 
diff --git a/examples/python/route_guide/README.md b/examples/python/route_guide/README.md
index dc97892..636e134 100644
--- a/examples/python/route_guide/README.md
+++ b/examples/python/route_guide/README.md
@@ -19,7 +19,7 @@
 
 ## Example code and setup
 
-The example code for this tutorial is in [examples/python/route_guide](examples/python/route_guide). To download the example, clone this repository by running the following command:
+The example code for this tutorial is in [examples/python/route_guide](.). To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
 ```
@@ -29,11 +29,11 @@
 $ cd examples/python/route_guide
 ```
 
-You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Python quick start guide](examples/python).
+You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Python quick start guide](../python).
 
 ## Defining the service
 
-Your first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto).
+Your first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers](https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](../../protos/route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -115,7 +115,7 @@
 - Implementing the servicer interface generated from our service definition with functions that perform the actual "work" of the service.
 - Running a gRPC server to listen for requests from clients and transmit responses.
 
-You can find the example `RouteGuide` server in [examples/python/route_guide/route_guide_server.py](examples/python/route_guide/route_guide_server.py).
+You can find the example `RouteGuide` server in [route_guide_server.py](route_guide_server.py).
 
 ### Implementing RouteGuide
 
@@ -222,7 +222,7 @@
 <a name="client"></a>
 ## Creating the client
 
-You can see the complete example client code in [examples/python/route_guide/route_guide_client.py](examples/python/route_guide/route_guide_client.py).
+You can see the complete example client code in [route_guide_client.py](route_guide_client.py).
 
 ### Creating a stub
 
diff --git a/examples/ruby/README.md b/examples/ruby/README.md
index dc21f5d..36f3527 100644
--- a/examples/ruby/README.md
+++ b/examples/ruby/README.md
@@ -55,7 +55,7 @@
 Tutorial
 --------
 
-You can find a more detailed tutorial in [gRPC Basics: Ruby](examples/ruby/route_guide/README.md)
+You can find a more detailed tutorial in [gRPC Basics: Ruby](route_guide/README.md)
 
-[helloworld.proto]:examples/protos/helloworld.proto
+[helloworld.proto]:../protos/helloworld.proto
 [RVM]:https://www.rvm.io/
diff --git a/examples/ruby/route_guide/README.md b/examples/ruby/route_guide/README.md
index c7231fb..77e93d8 100644
--- a/examples/ruby/route_guide/README.md
+++ b/examples/ruby/route_guide/README.md
@@ -18,7 +18,7 @@
 
 ## Example code and setup
 
-The example code for our tutorial is in [examples/ruby/route_guide](examples/ruby/route_guide). To download the example, clone this repository by running the following command:
+The example code for our tutorial is in [examples/ruby/route_guide](.). To download the example, clone this repository by running the following command:
 ```shell
 $ git clone https://github.com/grpc/grpc.git
 ```
@@ -28,12 +28,12 @@
 $ cd examples/ruby/route_guide
 ```
 
-You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Ruby quick start guide](examples/ruby).
+You also should have the relevant tools installed to generate the server and client interface code - if you don't already, follow the setup instructions in [the Ruby quick start guide](..).
 
 
 ## Defining the service
 
-Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](examples/protos/route_guide.proto).
+Our first step (as you'll know from [Getting started](https://github.com/grpc/grpc/tree/master/examples)) is to define the gRPC *service* and the method *request* and *response* types using [protocol buffers] (https://developers.google.com/protocol-buffers/docs/overview). You can see the complete .proto file in [`examples/protos/route_guide.proto`](../../route_guide.proto).
 
 To define a service, you specify a named `service` in your .proto file:
 
@@ -116,7 +116,7 @@
 - Implementing the service interface generated from our service definition: doing the actual "work" of our service.
 - Running a gRPC server to listen for requests from clients and return the service responses.
 
-You can find our example `RouteGuide` server in [examples/ruby/route_guide/route_guide_server.rb](examples/ruby/route_guide/route_guide_server.rb). Let's take a closer look at how it works.
+You can find our example `RouteGuide` server in [route_guide_server.rb](route_guide_server.rb). Let's take a closer look at how it works.
 
 ### Implementing RouteGuide
 
@@ -199,7 +199,7 @@
 <a name="client"></a>
 ## Creating the client
 
-In this section, we'll look at creating a Ruby client for our `RouteGuide` service. You can see our complete example client code in [examples/ruby/route_guide/route_guide_client.rb](examples/ruby/route_guide/route_guide_client.rb).
+In this section, we'll look at creating a Ruby client for our `RouteGuide` service. You can see our complete example client code in [route_guide_client.rb](route_guide_client.rb).
 
 ### Creating a stub
 
diff --git a/include/grpc++/client_context.h b/include/grpc++/client_context.h
index 62e5260..917a122 100644
--- a/include/grpc++/client_context.h
+++ b/include/grpc++/client_context.h
@@ -42,7 +42,7 @@
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
 #include <grpc/support/time.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 #include <grpc++/support/string_ref.h>
diff --git a/include/grpc++/create_channel.h b/include/grpc++/create_channel.h
index 916f3b0..72f0517 100644
--- a/include/grpc++/create_channel.h
+++ b/include/grpc++/create_channel.h
@@ -36,7 +36,7 @@
 
 #include <memory>
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/support/channel_arguments.h>
 #include <grpc++/support/config.h>
 
diff --git a/include/grpc++/support/auth_context.h b/include/grpc++/security/auth_context.h
similarity index 90%
rename from include/grpc++/support/auth_context.h
rename to include/grpc++/security/auth_context.h
index 67e3e66..fc2701e 100644
--- a/include/grpc++/support/auth_context.h
+++ b/include/grpc++/security/auth_context.h
@@ -77,6 +77,9 @@
  public:
   virtual ~AuthContext() {}
 
+  // Returns true if the peer is authenticated.
+  virtual bool IsPeerAuthenticated() const = 0;
+
   // A peer identity, in general is one or more properties (in which case they
   // have the same name).
   virtual std::vector<grpc::string_ref> GetPeerIdentity() const = 0;
@@ -89,6 +92,11 @@
   // Iteration over all the properties.
   virtual AuthPropertyIterator begin() const = 0;
   virtual AuthPropertyIterator end() const = 0;
+
+  // Mutation functions: should only be used by an AuthMetadataProcessor.
+  virtual void AddProperty(const grpc::string& key,
+                           const grpc::string_ref& value) = 0;
+  virtual bool SetPeerIdentityPropertyName(const grpc::string& name) = 0;
 };
 
 }  // namespace grpc
diff --git a/include/grpc++/security/auth_metadata_processor.h b/include/grpc++/security/auth_metadata_processor.h
new file mode 100644
index 0000000..18ad922
--- /dev/null
+++ b/include/grpc++/security/auth_metadata_processor.h
@@ -0,0 +1,74 @@
+/*
+ *
+ * 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 GRPCXX_AUTH_METADATA_PROCESSOR_H_
+#define GRPCXX_AUTH_METADATA_PROCESSOR_H_
+
+#include <map>
+
+#include <grpc++/security/auth_context.h>
+#include <grpc++/support/status.h>
+#include <grpc++/support/string_ref.h>
+
+namespace grpc {
+
+class AuthMetadataProcessor {
+ public:
+  typedef std::multimap<grpc::string_ref, grpc::string_ref> InputMetadata;
+  typedef std::multimap<grpc::string, grpc::string_ref> OutputMetadata;
+
+  virtual ~AuthMetadataProcessor() {}
+
+  // If this method returns true, the Process function will be scheduled in
+  // a different thread from the one processing the call.
+  virtual bool IsBlocking() const { return true; }
+
+  // context is read/write: it contains the properties of the channel peer and
+  // it is the job of the Process method to augment it with properties derived
+  // from the passed-in auth_metadata.
+  // consumed_auth_metadata needs to be filled with metadata that has been
+  // consumed by the processor and will be removed from the call.
+  // response_metadata is the metadata that will be sent as part of the
+  // response.
+  // If the return value is not Status::OK, the rpc call will be aborted with
+  // the error code and error message sent back to the client.
+  virtual Status Process(const InputMetadata& auth_metadata,
+                         AuthContext* context,
+                         OutputMetadata* consumed_auth_metadata,
+                         OutputMetadata* response_metadata) = 0;
+};
+
+}  // namespace grpc
+
+#endif  // GRPCXX_AUTH_METADATA_PROCESSOR_H_
+
diff --git a/include/grpc++/credentials.h b/include/grpc++/security/credentials.h
similarity index 100%
rename from include/grpc++/credentials.h
rename to include/grpc++/security/credentials.h
diff --git a/include/grpc++/server_credentials.h b/include/grpc++/security/server_credentials.h
similarity index 89%
rename from include/grpc++/server_credentials.h
rename to include/grpc++/security/server_credentials.h
index 16b78c0..2094c74 100644
--- a/include/grpc++/server_credentials.h
+++ b/include/grpc++/security/server_credentials.h
@@ -37,6 +37,7 @@
 #include <memory>
 #include <vector>
 
+#include <grpc++/security/auth_metadata_processor.h>
 #include <grpc++/support/config.h>
 
 struct grpc_server;
@@ -49,6 +50,11 @@
  public:
   virtual ~ServerCredentials();
 
+  // This method is not thread-safe and has to be called before the server is
+  // started. The last call to this function wins.
+  virtual void SetAuthMetadataProcessor(
+      const std::shared_ptr<AuthMetadataProcessor>& processor) = 0;
+
  private:
   friend class ::grpc::Server;
 
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index c8979e4..22d14ee 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -41,6 +41,7 @@
 #include <grpc++/impl/call.h>
 #include <grpc++/impl/grpc_library.h>
 #include <grpc++/impl/sync.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/status.h>
 
@@ -54,7 +55,6 @@
 class RpcService;
 class RpcServiceMethod;
 class ServerAsyncStreamingInterface;
-class ServerCredentials;
 class ThreadPoolInterface;
 
 // Currently it only supports handling rpcs in a single thread.
diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h
index 4b17a28..85f384d 100644
--- a/include/grpc++/server_context.h
+++ b/include/grpc++/server_context.h
@@ -39,7 +39,7 @@
 
 #include <grpc/compression.h>
 #include <grpc/support/time.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <grpc++/support/config.h>
 #include <grpc++/support/string_ref.h>
 #include <grpc++/support/time.h>
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index 049ab3c..87bc250 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -275,10 +275,12 @@
 typedef struct {
   /* The context object is read/write: it contains the properties of the
      channel peer and it is the job of the process function to augment it with
-     properties derived from the passed-in metadata. */
+     properties derived from the passed-in metadata.
+     The lifetime of these objects is guaranteed until cb is invoked. */
   void (*process)(void *state, grpc_auth_context *context,
-                  const grpc_metadata *md, size_t md_count,
+                  const grpc_metadata *md, size_t num_md,
                   grpc_process_auth_metadata_done_cb cb, void *user_data);
+  void (*destroy)(void *state);
   void *state;
 } grpc_auth_metadata_processor;
 
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc
index 72c457a..fe2b9fa 100644
--- a/src/compiler/python_generator.cc
+++ b/src/compiler/python_generator.cc
@@ -148,8 +148,8 @@
 // END FORMATTING BOILERPLATE //
 ////////////////////////////////
 
-bool PrintServicer(const ServiceDescriptor* service,
-                   Printer* out) {
+bool PrintAlphaServicer(const ServiceDescriptor* service,
+                        Printer* out) {
   grpc::string doc = "<fill me in later!>";
   map<grpc::string, grpc::string> dict = ListToDict({
         "Service", service->name(),
@@ -176,7 +176,7 @@
   return true;
 }
 
-bool PrintServer(const ServiceDescriptor* service, Printer* out) {
+bool PrintAlphaServer(const ServiceDescriptor* service, Printer* out) {
   grpc::string doc = "<fill me in later!>";
   map<grpc::string, grpc::string> dict = ListToDict({
         "Service", service->name(),
@@ -204,8 +204,8 @@
   return true;
 }
 
-bool PrintStub(const ServiceDescriptor* service,
-               Printer* out) {
+bool PrintAlphaStub(const ServiceDescriptor* service,
+                    Printer* out) {
   grpc::string doc = "<fill me in later!>";
   map<grpc::string, grpc::string> dict = ListToDict({
         "Service", service->name(),
@@ -268,8 +268,8 @@
   return true;
 }
 
-bool PrintServerFactory(const grpc::string& package_qualified_service_name,
-                        const ServiceDescriptor* service, Printer* out) {
+bool PrintAlphaServerFactory(const grpc::string& package_qualified_service_name,
+                             const ServiceDescriptor* service, Printer* out) {
   out->Print("def early_adopter_create_$Service$_server(servicer, port, "
              "private_key=None, certificate_chain=None):\n",
              "Service", service->name());
@@ -320,7 +320,7 @@
           input_message_modules_and_classes.find(method_name);
       auto output_message_module_and_class =
           output_message_modules_and_classes.find(method_name);
-      out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method",
+      out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method",
                  method_name, "Constructor",
                  name_and_description_constructor->second);
       {
@@ -348,8 +348,8 @@
   return true;
 }
 
-bool PrintStubFactory(const grpc::string& package_qualified_service_name,
-                      const ServiceDescriptor* service, Printer* out) {
+bool PrintAlphaStubFactory(const grpc::string& package_qualified_service_name,
+                           const ServiceDescriptor* service, Printer* out) {
   map<grpc::string, grpc::string> dict = ListToDict({
         "Service", service->name(),
       });
@@ -404,7 +404,7 @@
           input_message_modules_and_classes.find(method_name);
       auto output_message_module_and_class =
           output_message_modules_and_classes.find(method_name);
-      out->Print("\"$Method$\": utilities.$Constructor$(\n", "Method",
+      out->Print("\"$Method$\": alpha_utilities.$Constructor$(\n", "Method",
                  method_name, "Constructor",
                  name_and_description_constructor->second);
       {
@@ -434,12 +434,280 @@
   return true;
 }
 
+bool PrintBetaServicer(const ServiceDescriptor* service,
+                       Printer* out) {
+  grpc::string doc = "<fill me in later!>";
+  map<grpc::string, grpc::string> dict = ListToDict({
+        "Service", service->name(),
+        "Documentation", doc,
+      });
+  out->Print("\n");
+  out->Print(dict, "class Beta$Service$Servicer(object):\n");
+  {
+    IndentScope raii_class_indent(out);
+    out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
+    out->Print("__metaclass__ = abc.ABCMeta\n");
+    for (int i = 0; i < service->method_count(); ++i) {
+      auto meth = service->method(i);
+      grpc::string arg_name = meth->client_streaming() ?
+          "request_iterator" : "request";
+      out->Print("@abc.abstractmethod\n");
+      out->Print("def $Method$(self, $ArgName$, context):\n",
+                 "Method", meth->name(), "ArgName", arg_name);
+      {
+        IndentScope raii_method_indent(out);
+        out->Print("raise NotImplementedError()\n");
+      }
+    }
+  }
+  return true;
+}
+
+bool PrintBetaStub(const ServiceDescriptor* service,
+                   Printer* out) {
+  grpc::string doc = "The interface to which stubs will conform.";
+  map<grpc::string, grpc::string> dict = ListToDict({
+        "Service", service->name(),
+        "Documentation", doc,
+      });
+  out->Print("\n");
+  out->Print(dict, "class Beta$Service$Stub(object):\n");
+  {
+    IndentScope raii_class_indent(out);
+    out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
+    out->Print("__metaclass__ = abc.ABCMeta\n");
+    for (int i = 0; i < service->method_count(); ++i) {
+      const MethodDescriptor* meth = service->method(i);
+      grpc::string arg_name = meth->client_streaming() ?
+          "request_iterator" : "request";
+      auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
+      out->Print("@abc.abstractmethod\n");
+      out->Print(methdict, "def $Method$(self, $ArgName$, timeout):\n");
+      {
+        IndentScope raii_method_indent(out);
+        out->Print("raise NotImplementedError()\n");
+      }
+      if (!meth->server_streaming()) {
+        out->Print(methdict, "$Method$.future = None\n");
+      }
+    }
+  }
+  return true;
+}
+
+bool PrintBetaServerFactory(const grpc::string& package_qualified_service_name,
+                            const ServiceDescriptor* service, Printer* out) {
+  out->Print("\n");
+  out->Print("def beta_create_$Service$_server(servicer, pool=None, "
+             "pool_size=None, default_timeout=None, maximum_timeout=None):\n",
+             "Service", service->name());
+  {
+    IndentScope raii_create_server_indent(out);
+    map<grpc::string, grpc::string> method_implementation_constructors;
+    map<grpc::string, pair<grpc::string, grpc::string>>
+        input_message_modules_and_classes;
+    map<grpc::string, pair<grpc::string, grpc::string>>
+        output_message_modules_and_classes;
+    for (int i = 0; i < service->method_count(); ++i) {
+      const MethodDescriptor* method = service->method(i);
+      const grpc::string method_implementation_constructor =
+          grpc::string(method->client_streaming() ? "stream_" : "unary_") +
+          grpc::string(method->server_streaming() ? "stream_" : "unary_") +
+          "inline";
+      pair<grpc::string, grpc::string> input_message_module_and_class;
+      if (!GetModuleAndMessagePath(method->input_type(),
+                                   &input_message_module_and_class)) {
+        return false;
+      }
+      pair<grpc::string, grpc::string> output_message_module_and_class;
+      if (!GetModuleAndMessagePath(method->output_type(),
+                                   &output_message_module_and_class)) {
+        return false;
+      }
+      // Import the modules that define the messages used in RPCs.
+      out->Print("import $Module$\n", "Module",
+                 input_message_module_and_class.first);
+      out->Print("import $Module$\n", "Module",
+                 output_message_module_and_class.first);
+      method_implementation_constructors.insert(
+          make_pair(method->name(), method_implementation_constructor));
+      input_message_modules_and_classes.insert(
+          make_pair(method->name(), input_message_module_and_class));
+      output_message_modules_and_classes.insert(
+          make_pair(method->name(), output_message_module_and_class));
+    }
+    out->Print("request_deserializers = {\n");
+    for (auto name_and_input_module_class_pair =
+           input_message_modules_and_classes.begin();
+         name_and_input_module_class_pair !=
+           input_message_modules_and_classes.end();
+         name_and_input_module_class_pair++) {
+      IndentScope raii_indent(out);
+      out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
+                 "$InputTypeModule$.$InputTypeClass$.FromString,\n",
+                 "PackageQualifiedServiceName", package_qualified_service_name,
+                 "MethodName", name_and_input_module_class_pair->first,
+                 "InputTypeModule",
+                 name_and_input_module_class_pair->second.first,
+                 "InputTypeClass",
+                 name_and_input_module_class_pair->second.second);
+    }
+    out->Print("}\n");
+    out->Print("response_serializers = {\n");
+    for (auto name_and_output_module_class_pair =
+           output_message_modules_and_classes.begin();
+         name_and_output_module_class_pair !=
+           output_message_modules_and_classes.end();
+         name_and_output_module_class_pair++) {
+      IndentScope raii_indent(out);
+      out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
+                 "$OutputTypeModule$.$OutputTypeClass$.SerializeToString,\n",
+                 "PackageQualifiedServiceName", package_qualified_service_name,
+                 "MethodName", name_and_output_module_class_pair->first,
+                 "OutputTypeModule",
+                 name_and_output_module_class_pair->second.first,
+                 "OutputTypeClass",
+                 name_and_output_module_class_pair->second.second);
+    }
+    out->Print("}\n");
+    out->Print("method_implementations = {\n");
+    for (auto name_and_implementation_constructor =
+	   method_implementation_constructors.begin();
+	 name_and_implementation_constructor !=
+	   method_implementation_constructors.end();
+	 name_and_implementation_constructor++) {
+      IndentScope raii_descriptions_indent(out);
+      const grpc::string method_name =
+          name_and_implementation_constructor->first;
+      out->Print("(\'$PackageQualifiedServiceName$\', \'$Method$\'): "
+                 "face_utilities.$Constructor$(servicer.$Method$),\n",
+                 "PackageQualifiedServiceName", package_qualified_service_name,
+                 "Method", name_and_implementation_constructor->first,
+                 "Constructor", name_and_implementation_constructor->second);
+    }
+    out->Print("}\n");
+    out->Print("server_options = beta.server_options("
+               "request_deserializers=request_deserializers, "
+               "response_serializers=response_serializers, "
+               "thread_pool=pool, thread_pool_size=pool_size, "
+               "default_timeout=default_timeout, "
+               "maximum_timeout=maximum_timeout)\n");
+    out->Print("return beta.server(method_implementations, "
+               "options=server_options)\n");
+  }
+  return true;
+}
+
+bool PrintBetaStubFactory(const grpc::string& package_qualified_service_name,
+                          const ServiceDescriptor* service, Printer* out) {
+  map<grpc::string, grpc::string> dict = ListToDict({
+        "Service", service->name(),
+      });
+  out->Print("\n");
+  out->Print(dict, "def beta_create_$Service$_stub(channel, host=None,"
+             " metadata_transformer=None, pool=None, pool_size=None):\n");
+  {
+    IndentScope raii_create_server_indent(out);
+    map<grpc::string, grpc::string> method_cardinalities;
+    map<grpc::string, pair<grpc::string, grpc::string>>
+        input_message_modules_and_classes;
+    map<grpc::string, pair<grpc::string, grpc::string>>
+        output_message_modules_and_classes;
+    for (int i = 0; i < service->method_count(); ++i) {
+      const MethodDescriptor* method = service->method(i);
+      const grpc::string method_cardinality =
+          grpc::string(method->client_streaming() ? "STREAM" : "UNARY") +
+          "_" +
+	  grpc::string(method->server_streaming() ? "STREAM" : "UNARY");
+      pair<grpc::string, grpc::string> input_message_module_and_class;
+      if (!GetModuleAndMessagePath(method->input_type(),
+                                   &input_message_module_and_class)) {
+        return false;
+      }
+      pair<grpc::string, grpc::string> output_message_module_and_class;
+      if (!GetModuleAndMessagePath(method->output_type(),
+                                   &output_message_module_and_class)) {
+        return false;
+      }
+      // Import the modules that define the messages used in RPCs.
+      out->Print("import $Module$\n", "Module",
+                 input_message_module_and_class.first);
+      out->Print("import $Module$\n", "Module",
+                 output_message_module_and_class.first);
+      method_cardinalities.insert(
+          make_pair(method->name(), method_cardinality));
+      input_message_modules_and_classes.insert(
+          make_pair(method->name(), input_message_module_and_class));
+      output_message_modules_and_classes.insert(
+          make_pair(method->name(), output_message_module_and_class));
+    }
+    out->Print("request_serializers = {\n");
+    for (auto name_and_input_module_class_pair =
+           input_message_modules_and_classes.begin();
+         name_and_input_module_class_pair !=
+           input_message_modules_and_classes.end();
+         name_and_input_module_class_pair++) {
+      IndentScope raii_indent(out);
+      out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
+                 "$InputTypeModule$.$InputTypeClass$.SerializeToString,\n",
+                 "PackageQualifiedServiceName", package_qualified_service_name,
+                 "MethodName", name_and_input_module_class_pair->first,
+                 "InputTypeModule",
+                 name_and_input_module_class_pair->second.first,
+                 "InputTypeClass",
+                 name_and_input_module_class_pair->second.second);
+    }
+    out->Print("}\n");
+    out->Print("response_deserializers = {\n");
+    for (auto name_and_output_module_class_pair =
+           output_message_modules_and_classes.begin();
+         name_and_output_module_class_pair !=
+           output_message_modules_and_classes.end();
+         name_and_output_module_class_pair++) {
+      IndentScope raii_indent(out);
+      out->Print("(\'$PackageQualifiedServiceName$\', \'$MethodName$\'): "
+                 "$OutputTypeModule$.$OutputTypeClass$.FromString,\n",
+                 "PackageQualifiedServiceName", package_qualified_service_name,
+                 "MethodName", name_and_output_module_class_pair->first,
+                 "OutputTypeModule",
+                 name_and_output_module_class_pair->second.first,
+                 "OutputTypeClass",
+                 name_and_output_module_class_pair->second.second);
+    }
+    out->Print("}\n");
+    out->Print("cardinalities = {\n");
+    for (auto name_and_cardinality = method_cardinalities.begin();
+         name_and_cardinality != method_cardinalities.end();
+         name_and_cardinality++) {
+      IndentScope raii_descriptions_indent(out);
+      out->Print("\'$Method$\': cardinality.Cardinality.$Cardinality$,\n",
+                 "Method", name_and_cardinality->first,
+                 "Cardinality", name_and_cardinality->second);
+    }
+    out->Print("}\n");
+    out->Print("stub_options = beta.stub_options("
+               "host=host, metadata_transformer=metadata_transformer, "
+               "request_serializers=request_serializers, "
+               "response_deserializers=response_deserializers, "
+               "thread_pool=pool, thread_pool_size=pool_size)\n");
+    out->Print(
+        "return beta.dynamic_stub(channel, \'$PackageQualifiedServiceName$\', "
+        "cardinalities, options=stub_options)\n",
+        "PackageQualifiedServiceName", package_qualified_service_name);
+  }
+  return true;
+}
+
 bool PrintPreamble(const FileDescriptor* file,
                    const GeneratorConfiguration& config, Printer* out) {
   out->Print("import abc\n");
+  out->Print("from $Package$ import beta\n",
+             "Package", config.beta_package_root);
   out->Print("from $Package$ import implementations\n",
-             "Package", config.implementations_package_root);
-  out->Print("from grpc.framework.alpha import utilities\n");
+             "Package", config.early_adopter_package_root);
+  out->Print("from grpc.framework.alpha import utilities as alpha_utilities\n");
+  out->Print("from grpc.framework.common import cardinality\n");
+  out->Print("from grpc.framework.interfaces.face import utilities as face_utilities\n");
   return true;
 }
 
@@ -462,11 +730,15 @@
     for (int i = 0; i < file->service_count(); ++i) {
       auto service = file->service(i);
       auto package_qualified_service_name = package + service->name();
-      if (!(PrintServicer(service, &out) &&
-            PrintServer(service, &out) &&
-            PrintStub(service, &out) &&
-            PrintServerFactory(package_qualified_service_name, service, &out) &&
-            PrintStubFactory(package_qualified_service_name, service, &out))) {
+      if (!(PrintAlphaServicer(service, &out) &&
+            PrintAlphaServer(service, &out) &&
+            PrintAlphaStub(service, &out) &&
+            PrintAlphaServerFactory(package_qualified_service_name, service, &out) &&
+            PrintAlphaStubFactory(package_qualified_service_name, service, &out) &&
+            PrintBetaServicer(service, &out) &&
+            PrintBetaStub(service, &out) &&
+            PrintBetaServerFactory(package_qualified_service_name, service, &out) &&
+            PrintBetaStubFactory(package_qualified_service_name, service, &out))) {
         return make_pair(false, "");
       }
     }
diff --git a/src/compiler/python_generator.h b/src/compiler/python_generator.h
index b47f3c1..44ed4b3 100644
--- a/src/compiler/python_generator.h
+++ b/src/compiler/python_generator.h
@@ -43,7 +43,8 @@
 // Data pertaining to configuration of the generator with respect to anything
 // that may be used internally at Google.
 struct GeneratorConfiguration {
-  grpc::string implementations_package_root;
+  grpc::string early_adopter_package_root;
+  grpc::string beta_package_root;
 };
 
 class PythonGrpcGenerator : public grpc::protobuf::compiler::CodeGenerator {
diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc
index d1f4944..c7cef54 100644
--- a/src/compiler/python_plugin.cc
+++ b/src/compiler/python_plugin.cc
@@ -38,7 +38,8 @@
 
 int main(int argc, char* argv[]) {
   grpc_python_generator::GeneratorConfiguration config;
-  config.implementations_package_root = "grpc.early_adopter";
+  config.early_adopter_package_root = "grpc.early_adopter";
+  config.beta_package_root = "grpc.beta";
   grpc_python_generator::PythonGrpcGenerator generator(config);
   return grpc::protobuf::compiler::PluginMain(argc, argv, &generator);
 }
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 1c665f1..a764413 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -87,7 +87,10 @@
 
 void grpc_credentials_unref(grpc_credentials *creds) {
   if (creds == NULL) return;
-  if (gpr_unref(&creds->refcount)) creds->vtable->destroy(creds);
+  if (gpr_unref(&creds->refcount)) {
+    creds->vtable->destruct(creds);
+    gpr_free(creds);
+  }
 }
 
 void grpc_credentials_release(grpc_credentials *creds) {
@@ -135,9 +138,26 @@
       creds, target, args, request_metadata_creds, sc, new_args);
 }
 
-void grpc_server_credentials_release(grpc_server_credentials *creds) {
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds) {
+  if (creds == NULL) return NULL;
+  gpr_ref(&creds->refcount);
+  return creds;
+}
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds) {
   if (creds == NULL) return;
-  creds->vtable->destroy(creds);
+  if (gpr_unref(&creds->refcount)) {
+    creds->vtable->destruct(creds);
+    if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+      creds->processor.destroy(creds->processor.state);
+    }
+    gpr_free(creds);
+  }
+}
+
+void grpc_server_credentials_release(grpc_server_credentials *creds) {
+  grpc_server_credentials_unref(creds);
 }
 
 grpc_security_status grpc_server_credentials_create_security_connector(
@@ -152,20 +172,22 @@
 void grpc_server_credentials_set_auth_metadata_processor(
     grpc_server_credentials *creds, grpc_auth_metadata_processor processor) {
   if (creds == NULL) return;
+  if (creds->processor.destroy != NULL && creds->processor.state != NULL) {
+    creds->processor.destroy(creds->processor.state);
+  }
   creds->processor = processor;
 }
 
 /* -- Ssl credentials. -- */
 
-static void ssl_destroy(grpc_credentials *creds) {
+static void ssl_destruct(grpc_credentials *creds) {
   grpc_ssl_credentials *c = (grpc_ssl_credentials *)creds;
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
   if (c->config.pem_private_key != NULL) gpr_free(c->config.pem_private_key);
   if (c->config.pem_cert_chain != NULL) gpr_free(c->config.pem_cert_chain);
-  gpr_free(creds);
 }
 
-static void ssl_server_destroy(grpc_server_credentials *creds) {
+static void ssl_server_destruct(grpc_server_credentials *creds) {
   grpc_ssl_server_credentials *c = (grpc_ssl_server_credentials *)creds;
   size_t i;
   for (i = 0; i < c->config.num_key_cert_pairs; i++) {
@@ -185,7 +207,6 @@
     gpr_free(c->config.pem_cert_chains_sizes);
   }
   if (c->config.pem_root_certs != NULL) gpr_free(c->config.pem_root_certs);
-  gpr_free(creds);
 }
 
 static int ssl_has_request_metadata(const grpc_credentials *creds) { return 0; }
@@ -231,11 +252,11 @@
 }
 
 static grpc_credentials_vtable ssl_vtable = {
-    ssl_destroy, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
+    ssl_destruct, ssl_has_request_metadata, ssl_has_request_metadata_only, NULL,
     ssl_create_security_connector};
 
 static grpc_server_credentials_vtable ssl_server_vtable = {
-    ssl_server_destroy, ssl_server_create_security_connector};
+    ssl_server_destruct, ssl_server_create_security_connector};
 
 static void ssl_copy_key_material(const char *input, unsigned char **output,
                                   size_t *output_size) {
@@ -316,9 +337,9 @@
   grpc_ssl_server_credentials *c =
       gpr_malloc(sizeof(grpc_ssl_server_credentials));
   GPR_ASSERT(reserved == NULL);
-  memset(c, 0, sizeof(grpc_ssl_credentials));
   memset(c, 0, sizeof(grpc_ssl_server_credentials));
   c->base.type = GRPC_CREDENTIALS_TYPE_SSL;
+  gpr_ref_init(&c->base.refcount, 1);
   c->base.vtable = &ssl_server_vtable;
   ssl_build_server_config(pem_root_certs, pem_key_cert_pairs,
                           num_key_cert_pairs, force_client_auth, &c->config);
@@ -339,13 +360,12 @@
   c->cached.jwt_expiration = gpr_inf_past(GPR_CLOCK_REALTIME);
 }
 
-static void jwt_destroy(grpc_credentials *creds) {
+static void jwt_destruct(grpc_credentials *creds) {
   grpc_service_account_jwt_access_credentials *c =
       (grpc_service_account_jwt_access_credentials *)creds;
   grpc_auth_json_key_destruct(&c->key);
   jwt_reset_cache(c);
   gpr_mu_destroy(&c->cache_mu);
-  gpr_free(c);
 }
 
 static int jwt_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -410,7 +430,7 @@
 }
 
 static grpc_credentials_vtable jwt_vtable = {
-    jwt_destroy, jwt_has_request_metadata, jwt_has_request_metadata_only,
+    jwt_destruct, jwt_has_request_metadata, jwt_has_request_metadata_only,
     jwt_get_request_metadata, NULL};
 
 grpc_credentials *
@@ -442,13 +462,12 @@
 
 /* -- Oauth2TokenFetcher credentials -- */
 
-static void oauth2_token_fetcher_destroy(grpc_credentials *creds) {
+static void oauth2_token_fetcher_destruct(grpc_credentials *creds) {
   grpc_oauth2_token_fetcher_credentials *c =
       (grpc_oauth2_token_fetcher_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
   gpr_mu_destroy(&c->mu);
   grpc_httpcli_context_destroy(&c->httpcli_context);
-  gpr_free(c);
 }
 
 static int oauth2_token_fetcher_has_request_metadata(
@@ -621,7 +640,7 @@
 /* -- GoogleComputeEngine credentials. -- */
 
 static grpc_credentials_vtable compute_engine_vtable = {
-    oauth2_token_fetcher_destroy, oauth2_token_fetcher_has_request_metadata,
+    oauth2_token_fetcher_destruct, oauth2_token_fetcher_has_request_metadata,
     oauth2_token_fetcher_has_request_metadata_only,
     oauth2_token_fetcher_get_request_metadata, NULL};
 
@@ -652,15 +671,15 @@
 
 /* -- GoogleRefreshToken credentials. -- */
 
-static void refresh_token_destroy(grpc_credentials *creds) {
+static void refresh_token_destruct(grpc_credentials *creds) {
   grpc_google_refresh_token_credentials *c =
       (grpc_google_refresh_token_credentials *)creds;
   grpc_auth_refresh_token_destruct(&c->refresh_token);
-  oauth2_token_fetcher_destroy(&c->base.base);
+  oauth2_token_fetcher_destruct(&c->base.base);
 }
 
 static grpc_credentials_vtable refresh_token_vtable = {
-    refresh_token_destroy, oauth2_token_fetcher_has_request_metadata,
+    refresh_token_destruct, oauth2_token_fetcher_has_request_metadata,
     oauth2_token_fetcher_has_request_metadata_only,
     oauth2_token_fetcher_get_request_metadata, NULL};
 
@@ -713,10 +732,9 @@
 
 /* -- Metadata-only credentials. -- */
 
-static void md_only_test_destroy(grpc_credentials *creds) {
+static void md_only_test_destruct(grpc_credentials *creds) {
   grpc_md_only_test_credentials *c = (grpc_md_only_test_credentials *)creds;
   grpc_credentials_md_store_unref(c->md_store);
-  gpr_free(c);
 }
 
 static int md_only_test_has_request_metadata(const grpc_credentials *creds) {
@@ -757,7 +775,7 @@
 }
 
 static grpc_credentials_vtable md_only_test_vtable = {
-    md_only_test_destroy, md_only_test_has_request_metadata,
+    md_only_test_destruct, md_only_test_has_request_metadata,
     md_only_test_has_request_metadata_only, md_only_test_get_request_metadata,
     NULL};
 
@@ -778,10 +796,9 @@
 
 /* -- Oauth2 Access Token credentials. -- */
 
-static void access_token_destroy(grpc_credentials *creds) {
+static void access_token_destruct(grpc_credentials *creds) {
   grpc_access_token_credentials *c = (grpc_access_token_credentials *)creds;
   grpc_credentials_md_store_unref(c->access_token_md);
-  gpr_free(c);
 }
 
 static int access_token_has_request_metadata(const grpc_credentials *creds) {
@@ -803,7 +820,7 @@
 }
 
 static grpc_credentials_vtable access_token_vtable = {
-    access_token_destroy, access_token_has_request_metadata,
+    access_token_destruct, access_token_has_request_metadata,
     access_token_has_request_metadata_only, access_token_get_request_metadata,
     NULL};
 
@@ -827,14 +844,14 @@
 
 /* -- Fake transport security credentials. -- */
 
-static void fake_transport_security_credentials_destroy(
+static void fake_transport_security_credentials_destruct(
     grpc_credentials *creds) {
-  gpr_free(creds);
+  /* Nothing to do here. */
 }
 
-static void fake_transport_security_server_credentials_destroy(
+static void fake_transport_security_server_credentials_destruct(
     grpc_server_credentials *creds) {
-  gpr_free(creds);
+  /* Nothing to do here. */
 }
 
 static int fake_transport_security_has_request_metadata(
@@ -863,14 +880,14 @@
 }
 
 static grpc_credentials_vtable fake_transport_security_credentials_vtable = {
-    fake_transport_security_credentials_destroy,
+    fake_transport_security_credentials_destruct,
     fake_transport_security_has_request_metadata,
     fake_transport_security_has_request_metadata_only, NULL,
     fake_transport_security_create_security_connector};
 
 static grpc_server_credentials_vtable
     fake_transport_security_server_credentials_vtable = {
-        fake_transport_security_server_credentials_destroy,
+        fake_transport_security_server_credentials_destruct,
         fake_transport_security_server_create_security_connector};
 
 grpc_credentials *grpc_fake_transport_security_credentials_create(void) {
@@ -887,6 +904,7 @@
   grpc_server_credentials *c = gpr_malloc(sizeof(grpc_server_credentials));
   memset(c, 0, sizeof(grpc_server_credentials));
   c->type = GRPC_CREDENTIALS_TYPE_FAKE_TRANSPORT_SECURITY;
+  gpr_ref_init(&c->refcount, 1);
   c->vtable = &fake_transport_security_server_credentials_vtable;
   return c;
 }
@@ -903,14 +921,13 @@
   grpc_credentials_metadata_cb cb;
 } grpc_composite_credentials_metadata_context;
 
-static void composite_destroy(grpc_credentials *creds) {
+static void composite_destruct(grpc_credentials *creds) {
   grpc_composite_credentials *c = (grpc_composite_credentials *)creds;
   size_t i;
   for (i = 0; i < c->inner.num_creds; i++) {
     grpc_credentials_unref(c->inner.creds_array[i]);
   }
   gpr_free(c->inner.creds_array);
-  gpr_free(creds);
 }
 
 static int composite_has_request_metadata(const grpc_credentials *creds) {
@@ -1026,7 +1043,7 @@
 }
 
 static grpc_credentials_vtable composite_credentials_vtable = {
-    composite_destroy, composite_has_request_metadata,
+    composite_destruct, composite_has_request_metadata,
     composite_has_request_metadata_only, composite_get_request_metadata,
     composite_create_security_connector};
 
@@ -1125,10 +1142,9 @@
 
 /* -- IAM credentials. -- */
 
-static void iam_destroy(grpc_credentials *creds) {
+static void iam_destruct(grpc_credentials *creds) {
   grpc_google_iam_credentials *c = (grpc_google_iam_credentials *)creds;
   grpc_credentials_md_store_unref(c->iam_md);
-  gpr_free(c);
 }
 
 static int iam_has_request_metadata(const grpc_credentials *creds) { return 1; }
@@ -1148,7 +1164,7 @@
 }
 
 static grpc_credentials_vtable iam_vtable = {
-    iam_destroy, iam_has_request_metadata, iam_has_request_metadata_only,
+    iam_destruct, iam_has_request_metadata, iam_has_request_metadata_only,
     iam_get_request_metadata, NULL};
 
 grpc_credentials *grpc_google_iam_credentials_create(
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index d9bd53a..8e4fed7 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -129,7 +129,7 @@
                                              grpc_credentials_status status);
 
 typedef struct {
-  void (*destroy)(grpc_credentials *c);
+  void (*destruct)(grpc_credentials *c);
   int (*has_request_metadata)(const grpc_credentials *c);
   int (*has_request_metadata_only)(const grpc_credentials *c);
   void (*get_request_metadata)(grpc_credentials *c, grpc_pollset *pollset,
@@ -210,20 +210,28 @@
 /* --- grpc_server_credentials. --- */
 
 typedef struct {
-  void (*destroy)(grpc_server_credentials *c);
+  void (*destruct)(grpc_server_credentials *c);
   grpc_security_status (*create_security_connector)(
       grpc_server_credentials *c, grpc_security_connector **sc);
 } grpc_server_credentials_vtable;
 
+
+/* TODO(jboeuf): Add a refcount. */
 struct grpc_server_credentials {
   const grpc_server_credentials_vtable *vtable;
   const char *type;
+  gpr_refcount refcount;
   grpc_auth_metadata_processor processor;
 };
 
 grpc_security_status grpc_server_credentials_create_security_connector(
     grpc_server_credentials *creds, grpc_security_connector **sc);
 
+grpc_server_credentials *grpc_server_credentials_ref(
+    grpc_server_credentials *creds);
+
+void grpc_server_credentials_unref(grpc_server_credentials *creds);
+
 /* -- Ssl credentials. -- */
 
 typedef struct {
diff --git a/src/core/security/security_context.c b/src/core/security/security_context.c
index c1b434f..95d80ba 100644
--- a/src/core/security/security_context.c
+++ b/src/core/security/security_context.c
@@ -42,19 +42,6 @@
 #include <grpc/support/log.h>
 #include <grpc/support/string_util.h>
 
-/* --- grpc_process_auth_metadata_func --- */
-
-static grpc_auth_metadata_processor server_processor = {NULL, NULL};
-
-grpc_auth_metadata_processor grpc_server_get_auth_metadata_processor(void) {
-  return server_processor;
-}
-
-void grpc_server_register_auth_metadata_processor(
-    grpc_auth_metadata_processor processor) {
-  server_processor = processor;
-}
-
 /* --- grpc_call --- */
 
 grpc_call_error grpc_call_set_credentials(grpc_call *call,
diff --git a/src/core/security/server_auth_filter.c b/src/core/security/server_auth_filter.c
index 6e83143..b767f85 100644
--- a/src/core/security/server_auth_filter.c
+++ b/src/core/security/server_auth_filter.c
@@ -50,6 +50,7 @@
      handling it. */
   grpc_iomgr_closure auth_on_recv;
   grpc_transport_stream_op transport_op;
+  grpc_metadata_array md;
   const grpc_metadata *consumed_md;
   size_t num_consumed_md;
   grpc_stream_op *md_op;
@@ -90,13 +91,17 @@
   call_data *calld = elem->call_data;
   size_t i;
   for (i = 0; i < calld->num_consumed_md; i++) {
+    const grpc_metadata *consumed_md = &calld->consumed_md[i];
     /* Maybe we could do a pointer comparison but we do not have any guarantee
        that the metadata processor used the same pointers for consumed_md in the
        callback. */
-    if (memcmp(GPR_SLICE_START_PTR(md->key->slice), calld->consumed_md[i].key,
+    if (GPR_SLICE_LENGTH(md->key->slice) != strlen(consumed_md->key) ||
+        GPR_SLICE_LENGTH(md->value->slice) != consumed_md->value_length) {
+      continue;
+    }
+    if (memcmp(GPR_SLICE_START_PTR(md->key->slice), consumed_md->key,
                GPR_SLICE_LENGTH(md->key->slice)) == 0 &&
-        memcmp(GPR_SLICE_START_PTR(md->value->slice),
-               calld->consumed_md[i].value,
+        memcmp(GPR_SLICE_START_PTR(md->value->slice), consumed_md->value,
                GPR_SLICE_LENGTH(md->value->slice)) == 0) {
       return NULL; /* Delete. */
     }
@@ -134,6 +139,7 @@
     grpc_transport_stream_op_add_close(&calld->transport_op, status, &message);
     grpc_call_next_op(elem, &calld->transport_op);
   }
+  grpc_metadata_array_destroy(&calld->md);
 }
 
 static void auth_on_recv(void *user_data, int success) {
@@ -145,17 +151,15 @@
     size_t nops = calld->recv_ops->nops;
     grpc_stream_op *ops = calld->recv_ops->ops;
     for (i = 0; i < nops; i++) {
-      grpc_metadata_array md_array;
       grpc_stream_op *op = &ops[i];
       if (op->type != GRPC_OP_METADATA || calld->got_client_metadata) continue;
       calld->got_client_metadata = 1;
       if (chand->processor.process == NULL) continue;
       calld->md_op = op;
-      md_array = metadata_batch_to_md_array(&op->data.metadata);
+      calld->md = metadata_batch_to_md_array(&op->data.metadata);
       chand->processor.process(chand->processor.state, calld->auth_context,
-                               md_array.metadata, md_array.count,
+                               calld->md.metadata, calld->md.count,
                                on_md_processing_done, elem);
-      grpc_metadata_array_destroy(&md_array);
       return;
     }
   }
diff --git a/src/core/security/server_secure_chttp2.c b/src/core/security/server_secure_chttp2.c
index 8d9d036..4749f5f 100644
--- a/src/core/security/server_secure_chttp2.c
+++ b/src/core/security/server_secure_chttp2.c
@@ -61,7 +61,7 @@
   grpc_server *server;
   grpc_tcp_server *tcp;
   grpc_security_connector *sc;
-  grpc_auth_metadata_processor processor;
+  grpc_server_credentials *creds;
   tcp_endpoint_list *handshaking_tcp_endpoints;
   int is_shutdown;
   gpr_mu mu;
@@ -79,6 +79,7 @@
     gpr_mu_unlock(&state->mu);
     /* clean up */
     GRPC_SECURITY_CONNECTOR_UNREF(state->sc, "server");
+    grpc_server_credentials_unref(state->creds);
     gpr_free(state);
   }
 }
@@ -91,7 +92,8 @@
   grpc_channel_args *args_copy;
   grpc_arg args_to_add[2];
   args_to_add[0] = grpc_security_connector_to_arg(state->sc);
-  args_to_add[1] = grpc_auth_metadata_processor_to_arg(&state->processor);
+  args_to_add[1] =
+      grpc_auth_metadata_processor_to_arg(&state->creds->processor);
   args_copy = grpc_channel_args_copy_and_add(
       grpc_server_get_channel_args(state->server), args_to_add,
       GPR_ARRAY_SIZE(args_to_add));
@@ -262,7 +264,8 @@
   state->server = server;
   state->tcp = tcp;
   state->sc = sc;
-  state->processor = creds->processor;
+  state->creds = grpc_server_credentials_ref(creds);
+
   state->handshaking_tcp_endpoints = NULL;
   state->is_shutdown = 0;
   gpr_mu_init(&state->mu);
diff --git a/src/cpp/client/channel.cc b/src/cpp/client/channel.cc
index 8bf2e46..dc8e304 100644
--- a/src/cpp/client/channel.cc
+++ b/src/cpp/client/channel.cc
@@ -40,7 +40,7 @@
 #include <grpc/support/slice.h>
 #include <grpc++/client_context.h>
 #include <grpc++/completion_queue.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/impl/call.h>
 #include <grpc++/impl/rpc_method.h>
 #include <grpc++/support/channel_arguments.h>
diff --git a/src/cpp/client/client_context.cc b/src/cpp/client/client_context.cc
index c4d7cf2..574656a 100644
--- a/src/cpp/client/client_context.cc
+++ b/src/cpp/client/client_context.cc
@@ -36,7 +36,7 @@
 #include <grpc/grpc.h>
 #include <grpc/support/alloc.h>
 #include <grpc/support/string_util.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/server_context.h>
 #include <grpc++/support/time.h>
 
diff --git a/src/cpp/client/create_channel.cc b/src/cpp/client/create_channel.cc
index 1dac960..d2b2d30 100644
--- a/src/cpp/client/create_channel.cc
+++ b/src/cpp/client/create_channel.cc
@@ -51,6 +51,7 @@
 std::shared_ptr<Channel> CreateCustomChannel(
     const grpc::string& target, const std::shared_ptr<Credentials>& creds,
     const ChannelArguments& args) {
+  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();
diff --git a/src/cpp/client/credentials.cc b/src/cpp/client/credentials.cc
index e806284..7a8149e 100644
--- a/src/cpp/client/credentials.cc
+++ b/src/cpp/client/credentials.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 namespace grpc {
 
diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc
index 4a4d2cb..c476f3c 100644
--- a/src/cpp/client/insecure_credentials.cc
+++ b/src/cpp/client/insecure_credentials.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include <grpc/grpc.h>
 #include <grpc/support/log.h>
diff --git a/src/cpp/client/secure_credentials.h b/src/cpp/client/secure_credentials.h
index 62d3185..8deff85 100644
--- a/src/cpp/client/secure_credentials.h
+++ b/src/cpp/client/secure_credentials.h
@@ -37,7 +37,7 @@
 #include <grpc/grpc_security.h>
 
 #include <grpc++/support/config.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/auth_property_iterator.cc b/src/cpp/common/auth_property_iterator.cc
index fa6da9d..a47abaf 100644
--- a/src/cpp/common/auth_property_iterator.cc
+++ b/src/cpp/common/auth_property_iterator.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 #include <grpc/grpc_security.h>
 
diff --git a/src/cpp/common/create_auth_context.h b/src/cpp/common/create_auth_context.h
index b4962ba..4f3da39 100644
--- a/src/cpp/common/create_auth_context.h
+++ b/src/cpp/common/create_auth_context.h
@@ -33,7 +33,7 @@
 #include <memory>
 
 #include <grpc/grpc.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/insecure_create_auth_context.cc b/src/cpp/common/insecure_create_auth_context.cc
index fe80c1a..b2e1532 100644
--- a/src/cpp/common/insecure_create_auth_context.cc
+++ b/src/cpp/common/insecure_create_auth_context.cc
@@ -33,7 +33,7 @@
 #include <memory>
 
 #include <grpc/grpc.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 namespace grpc {
 
diff --git a/src/cpp/common/secure_auth_context.cc b/src/cpp/common/secure_auth_context.cc
index b18a853..8615ac8 100644
--- a/src/cpp/common/secure_auth_context.cc
+++ b/src/cpp/common/secure_auth_context.cc
@@ -37,9 +37,13 @@
 
 namespace grpc {
 
-SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx) : ctx_(ctx) {}
+SecureAuthContext::SecureAuthContext(grpc_auth_context* ctx,
+                                     bool take_ownership)
+    : ctx_(ctx), take_ownership_(take_ownership) {}
 
-SecureAuthContext::~SecureAuthContext() { grpc_auth_context_release(ctx_); }
+SecureAuthContext::~SecureAuthContext() {
+  if (take_ownership_) grpc_auth_context_release(ctx_);
+}
 
 std::vector<grpc::string_ref> SecureAuthContext::GetPeerIdentity() const {
   if (!ctx_) {
@@ -94,4 +98,21 @@
   return AuthPropertyIterator();
 }
 
+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());
+}
+
+bool SecureAuthContext::SetPeerIdentityPropertyName(const grpc::string& name) {
+  if (!ctx_) return false;
+  return grpc_auth_context_set_peer_identity_property_name(ctx_,
+                                                           name.c_str()) != 0;
+}
+
+bool SecureAuthContext::IsPeerAuthenticated() const {
+  if (!ctx_) return false;
+  return grpc_auth_context_peer_is_authenticated(ctx_) != 0;
+}
+
 }  // namespace grpc
diff --git a/src/cpp/common/secure_auth_context.h b/src/cpp/common/secure_auth_context.h
index 7f622b8..c9f1dad 100644
--- a/src/cpp/common/secure_auth_context.h
+++ b/src/cpp/common/secure_auth_context.h
@@ -34,7 +34,7 @@
 #ifndef GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
 #define GRPC_INTERNAL_CPP_COMMON_SECURE_AUTH_CONTEXT_H
 
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 
 struct grpc_auth_context;
 
@@ -42,10 +42,12 @@
 
 class SecureAuthContext GRPC_FINAL : public AuthContext {
  public:
-  SecureAuthContext(grpc_auth_context* ctx);
+  SecureAuthContext(grpc_auth_context* ctx, bool take_ownership);
 
   ~SecureAuthContext() GRPC_OVERRIDE;
 
+  bool IsPeerAuthenticated() const GRPC_OVERRIDE;
+
   std::vector<grpc::string_ref> GetPeerIdentity() const GRPC_OVERRIDE;
 
   grpc::string GetPeerIdentityPropertyName() const GRPC_OVERRIDE;
@@ -57,8 +59,15 @@
 
   AuthPropertyIterator end() const GRPC_OVERRIDE;
 
+  void AddProperty(const grpc::string& key,
+                   const grpc::string_ref& value) GRPC_OVERRIDE;
+
+  virtual bool SetPeerIdentityPropertyName(const grpc::string& name)
+      GRPC_OVERRIDE;
+
  private:
   grpc_auth_context* ctx_;
+  bool take_ownership_;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/common/secure_create_auth_context.cc b/src/cpp/common/secure_create_auth_context.cc
index f13d25a..40bc298 100644
--- a/src/cpp/common/secure_create_auth_context.cc
+++ b/src/cpp/common/secure_create_auth_context.cc
@@ -34,7 +34,7 @@
 
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include "src/cpp/common/secure_auth_context.h"
 
 namespace grpc {
@@ -44,7 +44,7 @@
     return std::shared_ptr<const AuthContext>();
   }
   return std::shared_ptr<const AuthContext>(
-      new SecureAuthContext(grpc_call_auth_context(call)));
+      new SecureAuthContext(grpc_call_auth_context(call), true));
 }
 
 }  // namespace grpc
diff --git a/src/cpp/server/insecure_server_credentials.cc b/src/cpp/server/insecure_server_credentials.cc
index 800cd36..ef3cae5 100644
--- a/src/cpp/server/insecure_server_credentials.cc
+++ b/src/cpp/server/insecure_server_credentials.cc
@@ -31,9 +31,10 @@
  *
  */
 
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include <grpc/grpc.h>
+#include <grpc/support/log.h>
 
 namespace grpc {
 namespace {
@@ -43,6 +44,11 @@
                       grpc_server* server) GRPC_OVERRIDE {
     return grpc_server_add_insecure_http2_port(server, addr.c_str());
   }
+  void SetAuthMetadataProcessor(
+      const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE {
+    (void)processor;
+    GPR_ASSERT(0);  // Should not be called on InsecureServerCredentials.
+  }
 };
 }  // namespace
 
diff --git a/src/cpp/server/secure_server_credentials.cc b/src/cpp/server/secure_server_credentials.cc
index 5bce9ca..dfa9229 100644
--- a/src/cpp/server/secure_server_credentials.cc
+++ b/src/cpp/server/secure_server_credentials.cc
@@ -31,15 +31,94 @@
  *
  */
 
+#include <functional>
+#include <map>
+#include <memory>
+
+
+#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);
+  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);
+  if (w->processor_ == nullptr) {
+    // 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));
+  } else {
+    // invoke directly.
+    w->InvokeProcessor(context, md, num_md, cb, user_data);
+  }
+}
+
+void AuthMetadataProcessorAyncWrapper::InvokeProcessor(
+    grpc_auth_context* ctx,
+    const grpc_metadata* md, size_t num_md,
+    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)));
+  }
+  SecureAuthContext context(ctx, false);
+  AuthMetadataProcessor::OutputMetadata consumed_metadata;
+  AuthMetadataProcessor::OutputMetadata response_metadata;
+
+  Status status = processor_->Process(metadata, &context, &consumed_metadata,
+                                      &response_metadata);
+
+  std::vector<grpc_metadata> consumed_md;
+  for (auto it = consumed_metadata.begin(); it != consumed_metadata.end();
+       ++it) {
+    consumed_md.push_back({it->first.c_str(),
+                           it->second.data(),
+                           it->second.size(),
+                           0,
+                           {{nullptr, nullptr, nullptr, nullptr}}});
+  }
+  std::vector<grpc_metadata> response_md;
+  for (auto it = response_metadata.begin(); it != response_metadata.end();
+       ++it) {
+    response_md.push_back({it->first.c_str(),
+                           it->second.data(),
+                           it->second.size(),
+                           0,
+                           {{nullptr, nullptr, nullptr, nullptr}}});
+  }
+  cb(user_data, &consumed_md[0], consumed_md.size(), &response_md[0],
+     response_md.size(), static_cast<grpc_status_code>(status.error_code()),
+     status.error_message().c_str());
+}
+
 int SecureServerCredentials::AddPortToServer(const grpc::string& addr,
                                              grpc_server* server) {
   return grpc_server_add_secure_http2_port(server, addr.c_str(), creds_);
 }
 
+void SecureServerCredentials::SetAuthMetadataProcessor(
+    const std::shared_ptr<AuthMetadataProcessor>& processor) {
+  auto *wrapper = new AuthMetadataProcessorAyncWrapper(processor);
+  grpc_server_credentials_set_auth_metadata_processor(
+      creds_, {AuthMetadataProcessorAyncWrapper::Process,
+               AuthMetadataProcessorAyncWrapper::Destroy, wrapper});
+}
+
 std::shared_ptr<ServerCredentials> SslServerCredentials(
     const SslServerCredentialsOptions& options) {
   std::vector<grpc_ssl_pem_key_cert_pair> pem_key_cert_pairs;
diff --git a/src/cpp/server/secure_server_credentials.h b/src/cpp/server/secure_server_credentials.h
index d3d37b1..4f003c6 100644
--- a/src/cpp/server/secure_server_credentials.h
+++ b/src/cpp/server/secure_server_credentials.h
@@ -34,12 +34,36 @@
 #ifndef GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
 #define GRPC_INTERNAL_CPP_SERVER_SECURE_SERVER_CREDENTIALS_H
 
-#include <grpc++/server_credentials.h>
+#include <memory>
+
+#include <grpc++/security/server_credentials.h>
 
 #include <grpc/grpc_security.h>
 
+#include "src/cpp/server/thread_pool_interface.h"
+
 namespace grpc {
 
+class AuthMetadataProcessorAyncWrapper GRPC_FINAL {
+ public:
+  static void Destroy(void *wrapper);
+
+  static void 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);
+
+  AuthMetadataProcessorAyncWrapper(
+      const std::shared_ptr<AuthMetadataProcessor>& processor)
+      : thread_pool_(CreateDefaultThreadPool()), processor_(processor) {}
+
+ private:
+  void InvokeProcessor(grpc_auth_context* context, const grpc_metadata* md,
+                       size_t num_md, grpc_process_auth_metadata_done_cb cb,
+                       void* user_data);
+  std::unique_ptr<ThreadPoolInterface> thread_pool_;
+  std::shared_ptr<AuthMetadataProcessor> processor_;
+};
+
 class SecureServerCredentials GRPC_FINAL : public ServerCredentials {
  public:
   explicit SecureServerCredentials(grpc_server_credentials* creds)
@@ -51,8 +75,12 @@
   int AddPortToServer(const grpc::string& addr,
                       grpc_server* server) GRPC_OVERRIDE;
 
+  void SetAuthMetadataProcessor(
+      const std::shared_ptr<AuthMetadataProcessor>& processor) GRPC_OVERRIDE;
+
  private:
-  grpc_server_credentials* const creds_;
+  grpc_server_credentials* creds_;
+  std::unique_ptr<AuthMetadataProcessorAyncWrapper> processor_;
 };
 
 }  // namespace grpc
diff --git a/src/cpp/server/server.cc b/src/cpp/server/server.cc
index bb83c7d..d67205e 100644
--- a/src/cpp/server/server.cc
+++ b/src/cpp/server/server.cc
@@ -43,7 +43,7 @@
 #include <grpc++/impl/rpc_service_method.h>
 #include <grpc++/impl/service_type.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/support/time.h>
 
 #include "src/core/profiling/timers.h"
@@ -354,7 +354,7 @@
       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 
+      // 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));
     }
@@ -384,7 +384,7 @@
     // 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 
+    // Since nothing else needs to touch state guarded by mu_, holding it
     // through this loop is fine.
     SyncRequest* request;
     bool ok;
diff --git a/src/cpp/server/server_credentials.cc b/src/cpp/server/server_credentials.cc
index be3a742..8495916 100644
--- a/src/cpp/server/server_credentials.cc
+++ b/src/cpp/server/server_credentials.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 namespace grpc {
 
diff --git a/src/csharp/Grpc.Core/Grpc.Core.nuspec b/src/csharp/Grpc.Core/Grpc.Core.nuspec
index fe49efc..06de55c 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.nuspec
+++ b/src/csharp/Grpc.Core/Grpc.Core.nuspec
@@ -14,15 +14,16 @@
     <releaseNotes>Release $version$ of gRPC C#</releaseNotes>
     <copyright>Copyright 2015, Google Inc.</copyright>
     <tags>gRPC RPC Protocol HTTP/2</tags>
-	<dependencies>
-	  <dependency id="Ix-Async" version="1.2.3" />
-	  <dependency id="grpc.native.csharp_ext" version="$GrpcNativeCsharpExtVersion$" />
+    <dependencies>
+      <dependency id="Ix-Async" version="1.2.3" />
+      <dependency id="grpc.native.csharp_ext" version="$GrpcNativeCsharpExtVersion$" />
     </dependencies>
   </metadata>
   <files>
+    <file src="..\..\..\etc\roots.pem" target="tools" />
     <file src="bin/ReleaseSigned/Grpc.Core.dll" target="lib/net45" />
-	<file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" />
-	<file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" />
-	<file src="**\*.cs" target="src" />
+    <file src="bin/ReleaseSigned/Grpc.Core.pdb" target="lib/net45" />
+    <file src="bin/ReleaseSigned/Grpc.Core.xml" target="lib/net45" />
+    <file src="**\*.cs" target="src" />
   </files>
 </package>
diff --git a/src/node/examples/route_guide.proto b/src/node/examples/route_guide.proto
deleted file mode 100644
index fceb632..0000000
--- a/src/node/examples/route_guide.proto
+++ /dev/null
@@ -1,120 +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.
-
-syntax = "proto3";
-
-option java_package = "io.grpc.examples";
-
-package examples;
-
-// Interface exported by the server.
-service RouteGuide {
-  // A simple RPC.
-  //
-  // Obtains the feature at a given position.
-  rpc GetFeature(Point) returns (Feature) {}
-
-  // A server-to-client streaming RPC.
-  //
-  // Obtains the Features available within the given Rectangle.  Results are
-  // streamed rather than returned at once (e.g. in a response message with a
-  // repeated field), as the rectangle may cover a large area and contain a
-  // huge number of features.
-  rpc ListFeatures(Rectangle) returns (stream Feature) {}
-
-  // A client-to-server streaming RPC.
-  //
-  // Accepts a stream of Points on a route being traversed, returning a
-  // RouteSummary when traversal is completed.
-  rpc RecordRoute(stream Point) returns (RouteSummary) {}
-
-  // A Bidirectional streaming RPC.
-  //
-  // Accepts a stream of RouteNotes sent while a route is being traversed,
-  // while receiving other RouteNotes (e.g. from other users).
-  rpc RouteChat(stream RouteNote) returns (stream RouteNote) {}
-}
-
-// Points are represented as latitude-longitude pairs in the E7 representation
-// (degrees multiplied by 10**7 and rounded to the nearest integer).
-// Latitudes should be in the range +/- 90 degrees and longitude should be in
-// the range +/- 180 degrees (inclusive).
-message Point {
-  int32 latitude = 1;
-  int32 longitude = 2;
-}
-
-// A latitude-longitude rectangle, represented as two diagonally opposite
-// points "lo" and "hi".
-message Rectangle {
-  // One corner of the rectangle.
-  Point lo = 1;
-
-  // The other corner of the rectangle.
-  Point hi = 2;
-}
-
-// A feature names something at a given point.
-//
-// If a feature could not be named, the name is empty.
-message Feature {
-  // The name of the feature.
-  string name = 1;
-
-  // The point where the feature is detected.
-  Point location = 2;
-}
-
-// A RouteNote is a message sent while at a given point.
-message RouteNote {
-  // The location from which the message is sent.
-  Point location = 1;
-
-  // The message to be sent.
-  string message = 2;
-}
-
-// A RouteSummary is received in response to a RecordRoute rpc.
-//
-// It contains the number of individual points received, the number of
-// detected features, and the total distance covered as the cumulative sum of
-// the distance between each point.
-message RouteSummary {
-  // The number of points received.
-  int32 point_count = 1;
-
-  // The number of known features passed while traversing the route.
-  int32 feature_count = 2;
-
-  // The distance covered in metres.
-  int32 distance = 3;
-
-  // The duration of the traversal in seconds.
-  int32 elapsed_time = 4;
-}
diff --git a/src/node/examples/route_guide_client.js b/src/node/examples/route_guide_client.js
deleted file mode 100644
index 647f3ff..0000000
--- a/src/node/examples/route_guide_client.js
+++ /dev/null
@@ -1,240 +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.
- *
- */
-
-'use strict';
-
-var async = require('async');
-var fs = require('fs');
-var parseArgs = require('minimist');
-var path = require('path');
-var _ = require('lodash');
-var grpc = require('..');
-var examples = grpc.load(__dirname + '/route_guide.proto').examples;
-var client = new examples.RouteGuide('localhost:50051',
-                                     grpc.Credentials.createInsecure());
-
-var COORD_FACTOR = 1e7;
-
-/**
- * Run the getFeature demo. Calls getFeature with a point known to have a
- * feature and a point known not to have a feature.
- * @param {function} callback Called when this demo is complete
- */
-function runGetFeature(callback) {
-  var next = _.after(2, callback);
-  function featureCallback(error, feature) {
-    if (error) {
-      callback(error);
-    }
-    if (feature.name === '') {
-      console.log('Found no feature at ' +
-          feature.location.latitude/COORD_FACTOR + ', ' +
-          feature.location.longitude/COORD_FACTOR);
-    } else {
-      console.log('Found feature called "' + feature.name + '" at ' +
-          feature.location.latitude/COORD_FACTOR + ', ' +
-          feature.location.longitude/COORD_FACTOR);
-    }
-    next();
-  }
-  var point1 = {
-    latitude: 409146138,
-    longitude: -746188906
-  };
-  var point2 = {
-    latitude: 0,
-    longitude: 0
-  };
-  client.getFeature(point1, featureCallback);
-  client.getFeature(point2, featureCallback);
-}
-
-/**
- * Run the listFeatures demo. Calls listFeatures with a rectangle containing all
- * of the features in the pre-generated database. Prints each response as it
- * comes in.
- * @param {function} callback Called when this demo is complete
- */
-function runListFeatures(callback) {
-  var rectangle = {
-    lo: {
-      latitude: 400000000,
-      longitude: -750000000
-    },
-    hi: {
-      latitude: 420000000,
-      longitude: -730000000
-    }
-  };
-  console.log('Looking for features between 40, -75 and 42, -73');
-  var call = client.listFeatures(rectangle);
-  call.on('data', function(feature) {
-      console.log('Found feature called "' + feature.name + '" at ' +
-          feature.location.latitude/COORD_FACTOR + ', ' +
-          feature.location.longitude/COORD_FACTOR);
-  });
-  call.on('end', callback);
-}
-
-/**
- * Run the recordRoute demo. Sends several randomly chosen points from the
- * pre-generated feature database with a variable delay in between. Prints the
- * statistics when they are sent from the server.
- * @param {function} callback Called when this demo is complete
- */
-function runRecordRoute(callback) {
-  var argv = parseArgs(process.argv, {
-    string: 'db_path'
-  });
-  fs.readFile(path.resolve(argv.db_path), function(err, data) {
-    if (err) {
-      callback(err);
-    }
-    var feature_list = JSON.parse(data);
-
-    var num_points = 10;
-    var call = client.recordRoute(function(error, stats) {
-      if (error) {
-        callback(error);
-      }
-      console.log('Finished trip with', stats.point_count, 'points');
-      console.log('Passed', stats.feature_count, 'features');
-      console.log('Travelled', stats.distance, 'meters');
-      console.log('It took', stats.elapsed_time, 'seconds');
-      callback();
-    });
-    /**
-     * Constructs a function that asynchronously sends the given point and then
-     * delays sending its callback
-     * @param {number} lat The latitude to send
-     * @param {number} lng The longitude to send
-     * @return {function(function)} The function that sends the point
-     */
-    function pointSender(lat, lng) {
-      /**
-       * Sends the point, then calls the callback after a delay
-       * @param {function} callback Called when complete
-       */
-      return function(callback) {
-        console.log('Visiting point ' + lat/COORD_FACTOR + ', ' +
-            lng/COORD_FACTOR);
-        call.write({
-          latitude: lat,
-          longitude: lng
-        });
-        _.delay(callback, _.random(500, 1500));
-      };
-    }
-    var point_senders = [];
-    for (var i = 0; i < num_points; i++) {
-      var rand_point = feature_list[_.random(0, feature_list.length - 1)];
-      point_senders[i] = pointSender(rand_point.location.latitude,
-                                     rand_point.location.longitude);
-    }
-    async.series(point_senders, function() {
-      call.end();
-    });
-  });
-}
-
-/**
- * Run the routeChat demo. Send some chat messages, and print any chat messages
- * that are sent from the server.
- * @param {function} callback Called when the demo is complete
- */
-function runRouteChat(callback) {
-  var call = client.routeChat();
-  call.on('data', function(note) {
-    console.log('Got message "' + note.message + '" at ' +
-        note.location.latitude + ', ' + note.location.longitude);
-  });
-
-  call.on('end', callback);
-
-  var notes = [{
-    location: {
-      latitude: 0,
-      longitude: 0
-    },
-    message: 'First message'
-  }, {
-    location: {
-      latitude: 0,
-      longitude: 1
-    },
-    message: 'Second message'
-  }, {
-    location: {
-      latitude: 1,
-      longitude: 0
-    },
-    message: 'Third message'
-  }, {
-    location: {
-      latitude: 0,
-      longitude: 0
-    },
-    message: 'Fourth message'
-  }];
-  for (var i = 0; i < notes.length; i++) {
-    var note = notes[i];
-    console.log('Sending message "' + note.message + '" at ' +
-        note.location.latitude + ', ' + note.location.longitude);
-    call.write(note);
-  }
-  call.end();
-}
-
-/**
- * Run all of the demos in order
- */
-function main() {
-  async.series([
-    runGetFeature,
-    runListFeatures,
-    runRecordRoute,
-    runRouteChat
-  ]);
-}
-
-if (require.main === module) {
-  main();
-}
-
-exports.runGetFeature = runGetFeature;
-
-exports.runListFeatures = runListFeatures;
-
-exports.runRecordRoute = runRecordRoute;
-
-exports.runRouteChat = runRouteChat;
diff --git a/src/node/examples/route_guide_db.json b/src/node/examples/route_guide_db.json
deleted file mode 100644
index 9d6a980..0000000
--- a/src/node/examples/route_guide_db.json
+++ /dev/null
@@ -1,601 +0,0 @@
-[{
-    "location": {
-        "latitude": 407838351,
-        "longitude": -746143763
-    },
-    "name": "Patriots Path, Mendham, NJ 07945, USA"
-}, {
-    "location": {
-        "latitude": 408122808,
-        "longitude": -743999179
-    },
-    "name": "101 New Jersey 10, Whippany, NJ 07981, USA"
-}, {
-    "location": {
-        "latitude": 413628156,
-        "longitude": -749015468
-    },
-    "name": "U.S. 6, Shohola, PA 18458, USA"
-}, {
-    "location": {
-        "latitude": 419999544,
-        "longitude": -740371136
-    },
-    "name": "5 Conners Road, Kingston, NY 12401, USA"
-}, {
-    "location": {
-        "latitude": 414008389,
-        "longitude": -743951297
-    },
-    "name": "Mid Hudson Psychiatric Center, New Hampton, NY 10958, USA"
-}, {
-    "location": {
-        "latitude": 419611318,
-        "longitude": -746524769
-    },
-    "name": "287 Flugertown Road, Livingston Manor, NY 12758, USA"
-}, {
-    "location": {
-        "latitude": 406109563,
-        "longitude": -742186778
-    },
-    "name": "4001 Tremley Point Road, Linden, NJ 07036, USA"
-}, {
-    "location": {
-        "latitude": 416802456,
-        "longitude": -742370183
-    },
-    "name": "352 South Mountain Road, Wallkill, NY 12589, USA"
-}, {
-    "location": {
-        "latitude": 412950425,
-        "longitude": -741077389
-    },
-    "name": "Bailey Turn Road, Harriman, NY 10926, USA"
-}, {
-    "location": {
-        "latitude": 412144655,
-        "longitude": -743949739
-    },
-    "name": "193-199 Wawayanda Road, Hewitt, NJ 07421, USA"
-}, {
-    "location": {
-        "latitude": 415736605,
-        "longitude": -742847522
-    },
-    "name": "406-496 Ward Avenue, Pine Bush, NY 12566, USA"
-}, {
-    "location": {
-        "latitude": 413843930,
-        "longitude": -740501726
-    },
-    "name": "162 Merrill Road, Highland Mills, NY 10930, USA"
-}, {
-    "location": {
-        "latitude": 410873075,
-        "longitude": -744459023
-    },
-    "name": "Clinton Road, West Milford, NJ 07480, USA"
-}, {
-    "location": {
-        "latitude": 412346009,
-        "longitude": -744026814
-    },
-    "name": "16 Old Brook Lane, Warwick, NY 10990, USA"
-}, {
-    "location": {
-        "latitude": 402948455,
-        "longitude": -747903913
-    },
-    "name": "3 Drake Lane, Pennington, NJ 08534, USA"
-}, {
-    "location": {
-        "latitude": 406337092,
-        "longitude": -740122226
-    },
-    "name": "6324 8th Avenue, Brooklyn, NY 11220, USA"
-}, {
-    "location": {
-        "latitude": 406421967,
-        "longitude": -747727624
-    },
-    "name": "1 Merck Access Road, Whitehouse Station, NJ 08889, USA"
-}, {
-    "location": {
-        "latitude": 416318082,
-        "longitude": -749677716
-    },
-    "name": "78-98 Schalck Road, Narrowsburg, NY 12764, USA"
-}, {
-    "location": {
-        "latitude": 415301720,
-        "longitude": -748416257
-    },
-    "name": "282 Lakeview Drive Road, Highland Lake, NY 12743, USA"
-}, {
-    "location": {
-        "latitude": 402647019,
-        "longitude": -747071791
-    },
-    "name": "330 Evelyn Avenue, Hamilton Township, NJ 08619, USA"
-}, {
-    "location": {
-        "latitude": 412567807,
-        "longitude": -741058078
-    },
-    "name": "New York State Reference Route 987E, Southfields, NY 10975, USA"
-}, {
-    "location": {
-        "latitude": 416855156,
-        "longitude": -744420597
-    },
-    "name": "103-271 Tempaloni Road, Ellenville, NY 12428, USA"
-}, {
-    "location": {
-        "latitude": 404663628,
-        "longitude": -744820157
-    },
-    "name": "1300 Airport Road, North Brunswick Township, NJ 08902, USA"
-}, {
-    "location": {
-        "latitude": 407113723,
-        "longitude": -749746483
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 402133926,
-        "longitude": -743613249
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 400273442,
-        "longitude": -741220915
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 411236786,
-        "longitude": -744070769
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 411633782,
-        "longitude": -746784970
-    },
-    "name": "211-225 Plains Road, Augusta, NJ 07822, USA"
-}, {
-    "location": {
-        "latitude": 415830701,
-        "longitude": -742952812
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 413447164,
-        "longitude": -748712898
-    },
-    "name": "165 Pedersen Ridge Road, Milford, PA 18337, USA"
-}, {
-    "location": {
-        "latitude": 405047245,
-        "longitude": -749800722
-    },
-    "name": "100-122 Locktown Road, Frenchtown, NJ 08825, USA"
-}, {
-    "location": {
-        "latitude": 418858923,
-        "longitude": -746156790
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 417951888,
-        "longitude": -748484944
-    },
-    "name": "650-652 Willi Hill Road, Swan Lake, NY 12783, USA"
-}, {
-    "location": {
-        "latitude": 407033786,
-        "longitude": -743977337
-    },
-    "name": "26 East 3rd Street, New Providence, NJ 07974, USA"
-}, {
-    "location": {
-        "latitude": 417548014,
-        "longitude": -740075041
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 410395868,
-        "longitude": -744972325
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 404615353,
-        "longitude": -745129803
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 406589790,
-        "longitude": -743560121
-    },
-    "name": "611 Lawrence Avenue, Westfield, NJ 07090, USA"
-}, {
-    "location": {
-        "latitude": 414653148,
-        "longitude": -740477477
-    },
-    "name": "18 Lannis Avenue, New Windsor, NY 12553, USA"
-}, {
-    "location": {
-        "latitude": 405957808,
-        "longitude": -743255336
-    },
-    "name": "82-104 Amherst Avenue, Colonia, NJ 07067, USA"
-}, {
-    "location": {
-        "latitude": 411733589,
-        "longitude": -741648093
-    },
-    "name": "170 Seven Lakes Drive, Sloatsburg, NY 10974, USA"
-}, {
-    "location": {
-        "latitude": 412676291,
-        "longitude": -742606606
-    },
-    "name": "1270 Lakes Road, Monroe, NY 10950, USA"
-}, {
-    "location": {
-        "latitude": 409224445,
-        "longitude": -748286738
-    },
-    "name": "509-535 Alphano Road, Great Meadows, NJ 07838, USA"
-}, {
-    "location": {
-        "latitude": 406523420,
-        "longitude": -742135517
-    },
-    "name": "652 Garden Street, Elizabeth, NJ 07202, USA"
-}, {
-    "location": {
-        "latitude": 401827388,
-        "longitude": -740294537
-    },
-    "name": "349 Sea Spray Court, Neptune City, NJ 07753, USA"
-}, {
-    "location": {
-        "latitude": 410564152,
-        "longitude": -743685054
-    },
-    "name": "13-17 Stanley Street, West Milford, NJ 07480, USA"
-}, {
-    "location": {
-        "latitude": 408472324,
-        "longitude": -740726046
-    },
-    "name": "47 Industrial Avenue, Teterboro, NJ 07608, USA"
-}, {
-    "location": {
-        "latitude": 412452168,
-        "longitude": -740214052
-    },
-    "name": "5 White Oak Lane, Stony Point, NY 10980, USA"
-}, {
-    "location": {
-        "latitude": 409146138,
-        "longitude": -746188906
-    },
-    "name": "Berkshire Valley Management Area Trail, Jefferson, NJ, USA"
-}, {
-    "location": {
-        "latitude": 404701380,
-        "longitude": -744781745
-    },
-    "name": "1007 Jersey Avenue, New Brunswick, NJ 08901, USA"
-}, {
-    "location": {
-        "latitude": 409642566,
-        "longitude": -746017679
-    },
-    "name": "6 East Emerald Isle Drive, Lake Hopatcong, NJ 07849, USA"
-}, {
-    "location": {
-        "latitude": 408031728,
-        "longitude": -748645385
-    },
-    "name": "1358-1474 New Jersey 57, Port Murray, NJ 07865, USA"
-}, {
-    "location": {
-        "latitude": 413700272,
-        "longitude": -742135189
-    },
-    "name": "367 Prospect Road, Chester, NY 10918, USA"
-}, {
-    "location": {
-        "latitude": 404310607,
-        "longitude": -740282632
-    },
-    "name": "10 Simon Lake Drive, Atlantic Highlands, NJ 07716, USA"
-}, {
-    "location": {
-        "latitude": 409319800,
-        "longitude": -746201391
-    },
-    "name": "11 Ward Street, Mount Arlington, NJ 07856, USA"
-}, {
-    "location": {
-        "latitude": 406685311,
-        "longitude": -742108603
-    },
-    "name": "300-398 Jefferson Avenue, Elizabeth, NJ 07201, USA"
-}, {
-    "location": {
-        "latitude": 419018117,
-        "longitude": -749142781
-    },
-    "name": "43 Dreher Road, Roscoe, NY 12776, USA"
-}, {
-    "location": {
-        "latitude": 412856162,
-        "longitude": -745148837
-    },
-    "name": "Swan Street, Pine Island, NY 10969, USA"
-}, {
-    "location": {
-        "latitude": 416560744,
-        "longitude": -746721964
-    },
-    "name": "66 Pleasantview Avenue, Monticello, NY 12701, USA"
-}, {
-    "location": {
-        "latitude": 405314270,
-        "longitude": -749836354
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 414219548,
-        "longitude": -743327440
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 415534177,
-        "longitude": -742900616
-    },
-    "name": "565 Winding Hills Road, Montgomery, NY 12549, USA"
-}, {
-    "location": {
-        "latitude": 406898530,
-        "longitude": -749127080
-    },
-    "name": "231 Rocky Run Road, Glen Gardner, NJ 08826, USA"
-}, {
-    "location": {
-        "latitude": 407586880,
-        "longitude": -741670168
-    },
-    "name": "100 Mount Pleasant Avenue, Newark, NJ 07104, USA"
-}, {
-    "location": {
-        "latitude": 400106455,
-        "longitude": -742870190
-    },
-    "name": "517-521 Huntington Drive, Manchester Township, NJ 08759, USA"
-}, {
-    "location": {
-        "latitude": 400066188,
-        "longitude": -746793294
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 418803880,
-        "longitude": -744102673
-    },
-    "name": "40 Mountain Road, Napanoch, NY 12458, USA"
-}, {
-    "location": {
-        "latitude": 414204288,
-        "longitude": -747895140
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 414777405,
-        "longitude": -740615601
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 415464475,
-        "longitude": -747175374
-    },
-    "name": "48 North Road, Forestburgh, NY 12777, USA"
-}, {
-    "location": {
-        "latitude": 404062378,
-        "longitude": -746376177
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 405688272,
-        "longitude": -749285130
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 400342070,
-        "longitude": -748788996
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 401809022,
-        "longitude": -744157964
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 404226644,
-        "longitude": -740517141
-    },
-    "name": "9 Thompson Avenue, Leonardo, NJ 07737, USA"
-}, {
-    "location": {
-        "latitude": 410322033,
-        "longitude": -747871659
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 407100674,
-        "longitude": -747742727
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 418811433,
-        "longitude": -741718005
-    },
-    "name": "213 Bush Road, Stone Ridge, NY 12484, USA"
-}, {
-    "location": {
-        "latitude": 415034302,
-        "longitude": -743850945
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 411349992,
-        "longitude": -743694161
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 404839914,
-        "longitude": -744759616
-    },
-    "name": "1-17 Bergen Court, New Brunswick, NJ 08901, USA"
-}, {
-    "location": {
-        "latitude": 414638017,
-        "longitude": -745957854
-    },
-    "name": "35 Oakland Valley Road, Cuddebackville, NY 12729, USA"
-}, {
-    "location": {
-        "latitude": 412127800,
-        "longitude": -740173578
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 401263460,
-        "longitude": -747964303
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 412843391,
-        "longitude": -749086026
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 418512773,
-        "longitude": -743067823
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 404318328,
-        "longitude": -740835638
-    },
-    "name": "42-102 Main Street, Belford, NJ 07718, USA"
-}, {
-    "location": {
-        "latitude": 419020746,
-        "longitude": -741172328
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 404080723,
-        "longitude": -746119569
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 401012643,
-        "longitude": -744035134
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 404306372,
-        "longitude": -741079661
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 403966326,
-        "longitude": -748519297
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 405002031,
-        "longitude": -748407866
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 409532885,
-        "longitude": -742200683
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 416851321,
-        "longitude": -742674555
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 406411633,
-        "longitude": -741722051
-    },
-    "name": "3387 Richmond Terrace, Staten Island, NY 10303, USA"
-}, {
-    "location": {
-        "latitude": 413069058,
-        "longitude": -744597778
-    },
-    "name": "261 Van Sickle Road, Goshen, NY 10924, USA"
-}, {
-    "location": {
-        "latitude": 418465462,
-        "longitude": -746859398
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 411733222,
-        "longitude": -744228360
-    },
-    "name": ""
-}, {
-    "location": {
-        "latitude": 410248224,
-        "longitude": -747127767
-    },
-    "name": "3 Hasta Way, Newton, NJ 07860, USA"
-}]
diff --git a/src/node/examples/route_guide_server.js b/src/node/examples/route_guide_server.js
deleted file mode 100644
index 465b32f..0000000
--- a/src/node/examples/route_guide_server.js
+++ /dev/null
@@ -1,255 +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.
- *
- */
-
-'use strict';
-
-var fs = require('fs');
-var parseArgs = require('minimist');
-var path = require('path');
-var _ = require('lodash');
-var grpc = require('..');
-var examples = grpc.load(__dirname + '/route_guide.proto').examples;
-
-var COORD_FACTOR = 1e7;
-
-/**
- * For simplicity, a point is a record type that looks like
- * {latitude: number, longitude: number}, and a feature is a record type that
- * looks like {name: string, location: point}. feature objects with name===''
- * are points with no feature.
- */
-
-/**
- * List of feature objects at points that have been requested so far.
- */
-var feature_list = [];
-
-/**
- * Get a feature object at the given point.
- * @param {point} point The point to check
- * @return {feature} The feature object at the point. Note that an empty name
- *     indicates no feature
- */
-function checkFeature(point) {
-  var feature;
-  // Check if there is already a feature object for the given point
-  for (var i = 0; i < feature_list.length; i++) {
-    feature = feature_list[i];
-    if (feature.location.latitude === point.latitude &&
-        feature.location.longitude === point.longitude) {
-      return feature;
-    }
-  }
-  var name = '';
-  feature = {
-    name: name,
-    location: point
-  };
-  return feature;
-}
-
-/**
- * getFeature request handler. Gets a request with a point, and responds with a
- * feature object indicating whether there is a feature at that point.
- * @param {EventEmitter} call Call object for the handler to process
- * @param {function(Error, feature)} callback Response callback
- */
-function getFeature(call, callback) {
-  callback(null, checkFeature(call.request));
-}
-
-/**
- * listFeatures request handler. Gets a request with two points, and responds
- * with a stream of all features in the bounding box defined by those points.
- * @param {Writable} call Writable stream for responses with an additional
- *     request property for the request value.
- */
-function listFeatures(call) {
-  var lo = call.request.lo;
-  var hi = call.request.hi;
-  var left = _.min([lo.longitude, hi.longitude]);
-  var right = _.max([lo.longitude, hi.longitude]);
-  var top = _.max([lo.latitude, hi.latitude]);
-  var bottom = _.min([lo.latitude, hi.latitude]);
-  // For each feature, check if it is in the given bounding box
-  _.each(feature_list, function(feature) {
-    if (feature.name === '') {
-      return;
-    }
-    if (feature.location.longitude >= left &&
-        feature.location.longitude <= right &&
-        feature.location.latitude >= bottom &&
-        feature.location.latitude <= top) {
-      call.write(feature);
-    }
-  });
-  call.end();
-}
-
-/**
- * Calculate the distance between two points using the "haversine" formula.
- * This code was taken from http://www.movable-type.co.uk/scripts/latlong.html.
- * @param start The starting point
- * @param end The end point
- * @return The distance between the points in meters
- */
-function getDistance(start, end) {
-  function toRadians(num) {
-    return num * Math.PI / 180;
-  }
-  var lat1 = start.latitude / COORD_FACTOR;
-  var lat2 = end.latitude / COORD_FACTOR;
-  var lon1 = start.longitude / COORD_FACTOR;
-  var lon2 = end.longitude / COORD_FACTOR;
-  var R = 6371000; // metres
-  var φ1 = toRadians(lat1);
-  var φ2 = toRadians(lat2);
-  var Δφ = toRadians(lat2-lat1);
-  var Δλ = toRadians(lon2-lon1);
-
-  var a = Math.sin(Δφ/2) * Math.sin(Δφ/2) +
-      Math.cos(φ1) * Math.cos(φ2) *
-      Math.sin(Δλ/2) * Math.sin(Δλ/2);
-  var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
-
-  return R * c;
-}
-
-/**
- * recordRoute handler. Gets a stream of points, and responds with statistics
- * about the "trip": number of points, number of known features visited, total
- * distance traveled, and total time spent.
- * @param {Readable} call The request point stream.
- * @param {function(Error, routeSummary)} callback The callback to pass the
- *     response to
- */
-function recordRoute(call, callback) {
-  var point_count = 0;
-  var feature_count = 0;
-  var distance = 0;
-  var previous = null;
-  // Start a timer
-  var start_time = process.hrtime();
-  call.on('data', function(point) {
-    point_count += 1;
-    if (checkFeature(point).name !== '') {
-      feature_count += 1;
-    }
-    /* For each point after the first, add the incremental distance from the
-     * previous point to the total distance value */
-    if (previous !== null) {
-      distance += getDistance(previous, point);
-    }
-    previous = point;
-  });
-  call.on('end', function() {
-    callback(null, {
-      point_count: point_count,
-      feature_count: feature_count,
-      // Cast the distance to an integer
-      distance: Math.floor(distance),
-      // End the timer
-      elapsed_time: process.hrtime(start_time)[0]
-    });
-  });
-}
-
-var route_notes = {};
-
-/**
- * Turn the point into a dictionary key.
- * @param {point} point The point to use
- * @return {string} The key for an object
- */
-function pointKey(point) {
-  return point.latitude + ' ' + point.longitude;
-}
-
-/**
- * routeChat handler. Receives a stream of message/location pairs, and responds
- * with a stream of all previous messages at each of those locations.
- * @param {Duplex} call The stream for incoming and outgoing messages
- */
-function routeChat(call) {
-  call.on('data', function(note) {
-    var key = pointKey(note.location);
-    /* For each note sent, respond with all previous notes that correspond to
-     * the same point */
-    if (route_notes.hasOwnProperty(key)) {
-      _.each(route_notes[key], function(note) {
-        call.write(note);
-      });
-    } else {
-      route_notes[key] = [];
-    }
-    // Then add the new note to the list
-    route_notes[key].push(JSON.parse(JSON.stringify(note)));
-  });
-  call.on('end', function() {
-    call.end();
-  });
-}
-
-/**
- * Get a new server with the handler functions in this file bound to the methods
- * it serves.
- * @return {Server} The new server object
- */
-function getServer() {
-  var server = new grpc.Server();
-  server.addProtoService(examples.RouteGuide.service, {
-    getFeature: getFeature,
-    listFeatures: listFeatures,
-    recordRoute: recordRoute,
-    routeChat: routeChat
-  });
-  return server;
-}
-
-if (require.main === module) {
-  // If this is run as a script, start a server on an unused port
-  var routeServer = getServer();
-  routeServer.bind('0.0.0.0:50051', grpc.ServerCredentials.createInsecure());
-  var argv = parseArgs(process.argv, {
-    string: 'db_path'
-  });
-  fs.readFile(path.resolve(argv.db_path), function(err, data) {
-    if (err) {
-      throw err;
-    }
-    feature_list = JSON.parse(data);
-    routeServer.start();
-  });
-}
-
-exports.getServer = getServer;
diff --git a/src/node/index.js b/src/node/index.js
index 51d3fa5..02b73f6 100644
--- a/src/node/index.js
+++ b/src/node/index.js
@@ -164,3 +164,13 @@
  * @see module:src/client.makeClientConstructor
  */
 exports.makeGenericClientConstructor = client.makeClientConstructor;
+
+/**
+ * @see module:src/client.getClientChannel
+ */
+exports.getClientChannel = client.getClientChannel;
+
+/**
+ * @see module:src/client.waitForClientReady
+ */
+exports.waitForClientReady = client.waitForClientReady;
diff --git a/src/node/interop/interop_client.js b/src/node/interop/interop_client.js
index 8fb8d66..6a8d263 100644
--- a/src/node/interop/interop_client.js
+++ b/src/node/interop/interop_client.js
@@ -285,7 +285,7 @@
     if (credential.createScopedRequired() && scope) {
       credential = credential.createScoped(scope);
     }
-    client.updateMetadata = grpc.getGoogleAuthDelegate(credential);
+    client.$updateMetadata = grpc.getGoogleAuthDelegate(credential);
     var arg = {
       response_type: 'COMPRESSABLE',
       response_size: 314159,
@@ -338,7 +338,7 @@
       if (per_rpc) {
         updateMetadata('', {}, makeTestCall);
       } else {
-        client.updateMetadata = updateMetadata;
+        client.$updateMetadata = updateMetadata;
         makeTestCall(null, {});
       }
     });
diff --git a/src/node/src/client.js b/src/node/src/client.js
index 6a49490..b427297 100644
--- a/src/node/src/client.js
+++ b/src/node/src/client.js
@@ -32,7 +32,7 @@
  */
 
 /**
- * Server module
+ * Client module
  * @module
  */
 
@@ -270,7 +270,7 @@
   function makeUnaryRequest(argument, callback, metadata, options) {
     /* jshint validthis: true */
     var emitter = new EventEmitter();
-    var call = getCall(this.channel, method, options);
+    var call = getCall(this.$channel, method, options);
     if (metadata === null || metadata === undefined) {
       metadata = new Metadata();
     } else {
@@ -282,7 +282,7 @@
     emitter.getPeer = function getPeer() {
       return call.getPeer();
     };
-    this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
+    this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) {
       if (error) {
         call.cancel();
         callback(error);
@@ -364,14 +364,14 @@
    */
   function makeClientStreamRequest(callback, metadata, options) {
     /* jshint validthis: true */
-    var call = getCall(this.channel, method, options);
+    var call = getCall(this.$channel, method, options);
     if (metadata === null || metadata === undefined) {
       metadata = new Metadata();
     } else {
       metadata = metadata.clone();
     }
     var stream = new ClientWritableStream(call, serialize);
-    this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
+    this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) {
       if (error) {
         call.cancel();
         callback(error);
@@ -455,14 +455,14 @@
    */
   function makeServerStreamRequest(argument, metadata, options) {
     /* jshint validthis: true */
-    var call = getCall(this.channel, method, options);
+    var call = getCall(this.$channel, method, options);
     if (metadata === null || metadata === undefined) {
       metadata = new Metadata();
     } else {
       metadata = metadata.clone();
     }
     var stream = new ClientReadableStream(call, deserialize);
-    this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
+    this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) {
       if (error) {
         call.cancel();
         stream.emit('error', error);
@@ -533,14 +533,14 @@
    */
   function makeBidiStreamRequest(metadata, options) {
     /* jshint validthis: true */
-    var call = getCall(this.channel, method, options);
+    var call = getCall(this.$channel, method, options);
     if (metadata === null || metadata === undefined) {
       metadata = new Metadata();
     } else {
       metadata = metadata.clone();
     }
     var stream = new ClientDuplexStream(call, serialize, deserialize);
-    this.updateMetadata(this.auth_uri, metadata, function(error, metadata) {
+    this.$updateMetadata(this.$auth_uri, metadata, function(error, metadata) {
       if (error) {
         call.cancel();
         stream.emit('error', error);
@@ -631,45 +631,21 @@
       options = {};
     }
     options['grpc.primary_user_agent'] = 'grpc-node/' + version;
-    this.channel = new grpc.Channel(address, credentials, options);
+    /* Private fields use $ as a prefix instead of _ because it is an invalid
+     * prefix of a method name */
+    this.$channel = new grpc.Channel(address, credentials, options);
     // Remove the optional DNS scheme, trailing port, and trailing backslash
     address = address.replace(/^(dns:\/{3})?([^:\/]+)(:\d+)?\/?$/, '$2');
-    this.server_address = address;
-    this.auth_uri = 'https://' + this.server_address + '/' + serviceName;
-    this.updateMetadata = updateMetadata;
+    this.$server_address = address;
+    this.$auth_uri = 'https://' + this.server_address + '/' + serviceName;
+    this.$updateMetadata = updateMetadata;
   }
 
-  /**
-   * Wait for the client to be ready. The callback will be called when the
-   * client has successfully connected to the server, and it will be called
-   * with an error if the attempt to connect to the server has unrecoverablly
-   * failed or if the deadline expires. This function will make the channel
-   * start connecting if it has not already done so.
-   * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass
-   *     Infinity to wait forever.
-   * @param {function(Error)} callback The callback to call when done attempting
-   *     to connect.
-   */
-  Client.prototype.$waitForReady = function(deadline, callback) {
-    var self = this;
-    var checkState = function(err) {
-      if (err) {
-        callback(new Error('Failed to connect before the deadline'));
-      }
-      var new_state = self.channel.getConnectivityState(true);
-      if (new_state === grpc.connectivityState.READY) {
-        callback();
-      } else if (new_state === grpc.connectivityState.FATAL_FAILURE) {
-        callback(new Error('Failed to connect to server'));
-      } else {
-        self.channel.watchConnectivityState(new_state, deadline, checkState);
-      }
-    };
-    checkState();
-  };
-
   _.each(methods, function(attrs, name) {
     var method_type;
+    if (_.startsWith(name, '$')) {
+      throw new Error('Method names cannot start with $');
+    }
     if (attrs.requestStream) {
       if (attrs.responseStream) {
         method_type = 'bidi';
@@ -695,6 +671,44 @@
 };
 
 /**
+ * Return the underlying channel object for the specified client
+ * @param {Client} client
+ * @return {Channel} The channel
+ */
+exports.getClientChannel = function(client) {
+  return client.$channel;
+};
+
+/**
+ * Wait for the client to be ready. The callback will be called when the
+ * client has successfully connected to the server, and it will be called
+ * with an error if the attempt to connect to the server has unrecoverablly
+ * failed or if the deadline expires. This function will make the channel
+ * start connecting if it has not already done so.
+ * @param {Client} client The client to wait on
+ * @param {(Date|Number)} deadline When to stop waiting for a connection. Pass
+ *     Infinity to wait forever.
+ * @param {function(Error)} callback The callback to call when done attempting
+ *     to connect.
+ */
+exports.waitForClientReady = function(client, deadline, callback) {
+  var checkState = function(err) {
+    if (err) {
+      callback(new Error('Failed to connect before the deadline'));
+    }
+    var new_state = client.$channel.getConnectivityState(true);
+    if (new_state === grpc.connectivityState.READY) {
+      callback();
+    } else if (new_state === grpc.connectivityState.FATAL_FAILURE) {
+      callback(new Error('Failed to connect to server'));
+    } else {
+      client.$channel.watchConnectivityState(new_state, deadline, checkState);
+    }
+  };
+  checkState();
+};
+
+/**
  * Creates a constructor for clients for the given service
  * @param {ProtoBuf.Reflect.Service} service The service to generate a client
  *     for
diff --git a/src/node/test/surface_test.js b/src/node/test/surface_test.js
index 7c2a8d7..d917c7a 100644
--- a/src/node/test/surface_test.js
+++ b/src/node/test/surface_test.js
@@ -133,7 +133,25 @@
     });
   });
 });
-describe('Client#$waitForReady', function() {
+describe('Client constructor building', function() {
+  var illegal_service_attrs = {
+    $method : {
+      path: '/illegal/$method',
+      requestStream: false,
+      responseStream: false,
+      requestSerialize: _.identity,
+      requestDeserialize: _.identity,
+      responseSerialize: _.identity,
+      responseDeserialize: _.identity
+    }
+  };
+  it('Should reject method names starting with $', function() {
+    assert.throws(function() {
+      grpc.makeGenericClientConstructor(illegal_service_attrs);
+    }, /\$/);
+  });
+});
+describe('waitForClientReady', function() {
   var server;
   var port;
   var Client;
@@ -151,13 +169,13 @@
     server.forceShutdown();
   });
   it('should complete when called alone', function(done) {
-    client.$waitForReady(Infinity, function(error) {
+    grpc.waitForClientReady(client, Infinity, function(error) {
       assert.ifError(error);
       done();
     });
   });
   it('should complete when a call is initiated', function(done) {
-    client.$waitForReady(Infinity, function(error) {
+    grpc.waitForClientReady(client, Infinity, function(error) {
       assert.ifError(error);
       done();
     });
@@ -166,19 +184,19 @@
   });
   it('should complete if called more than once', function(done) {
     done = multiDone(done, 2);
-    client.$waitForReady(Infinity, function(error) {
+    grpc.waitForClientReady(client, Infinity, function(error) {
       assert.ifError(error);
       done();
     });
-    client.$waitForReady(Infinity, function(error) {
+    grpc.waitForClientReady(client, Infinity, function(error) {
       assert.ifError(error);
       done();
     });
   });
   it('should complete if called when already ready', function(done) {
-    client.$waitForReady(Infinity, function(error) {
+    grpc.waitForClientReady(client, Infinity, function(error) {
       assert.ifError(error);
-      client.$waitForReady(Infinity, function(error) {
+      grpc.waitForClientReady(client, Infinity, function(error) {
         assert.ifError(error);
         done();
       });
@@ -426,7 +444,8 @@
     server.forceShutdown();
   });
   it('channel.getTarget should be available', function() {
-    assert.strictEqual(typeof client.channel.getTarget(), 'string');
+    assert.strictEqual(typeof grpc.getClientChannel(client).getTarget(),
+                       'string');
   });
   describe('Server recieving bad input', function() {
     var misbehavingClient;
diff --git a/src/objective-c/GRPCClient/private/GRPCHost.m b/src/objective-c/GRPCClient/private/GRPCHost.m
index a7142d0..a8cd3a0 100644
--- a/src/objective-c/GRPCClient/private/GRPCHost.m
+++ b/src/objective-c/GRPCClient/private/GRPCHost.m
@@ -57,13 +57,16 @@
 
 // Default initializer.
 - (instancetype)initWithAddress:(NSString *)address {
+  if (!address) {
+    return nil;
+  }
 
   // To provide a default port, we try to interpret the address. If it's just a host name without
   // scheme and without port, we'll use port 443. If it has a scheme, we pass it untouched to the C
   // gRPC library.
   // TODO(jcanizales): Add unit tests for the types of addresses we want to let pass untouched.
   NSURL *hostURL = [NSURL URLWithString:[@"https://" stringByAppendingString:address]];
-  if (hostURL && !hostURL.port) {
+  if (hostURL.host && !hostURL.port) {
     address = [hostURL.host stringByAppendingString:@":443"];
   }
 
diff --git a/src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py b/src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py
new file mode 100644
index 0000000..b200d12
--- /dev/null
+++ b/src/python/grpcio_test/grpc_protoc_plugin/alpha_python_plugin_test.py
@@ -0,0 +1,541 @@
+# 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.
+
+import argparse
+import contextlib
+import distutils.spawn
+import errno
+import itertools
+import os
+import pkg_resources
+import shutil
+import subprocess
+import sys
+import tempfile
+import threading
+import time
+import unittest
+
+from grpc.framework.alpha import exceptions
+from grpc.framework.foundation import future
+
+# Identifiers of entities we expect to find in the generated module.
+SERVICER_IDENTIFIER = 'EarlyAdopterTestServiceServicer'
+SERVER_IDENTIFIER = 'EarlyAdopterTestServiceServer'
+STUB_IDENTIFIER = 'EarlyAdopterTestServiceStub'
+SERVER_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_server'
+STUB_FACTORY_IDENTIFIER = 'early_adopter_create_TestService_stub'
+
+# The timeout used in tests of RPCs that are supposed to expire.
+SHORT_TIMEOUT = 2
+# The timeout used in tests of RPCs that are not supposed to expire. The
+# absurdly large value doesn't matter since no passing execution of this test
+# module will ever wait the duration.
+LONG_TIMEOUT = 600
+NO_DELAY = 0
+
+
+class _ServicerMethods(object):
+
+  def __init__(self, test_pb2, delay):
+    self._condition = threading.Condition()
+    self._delay = delay
+    self._paused = False
+    self._fail = False
+    self._test_pb2 = test_pb2
+
+  @contextlib.contextmanager
+  def pause(self):  # pylint: disable=invalid-name
+    with self._condition:
+      self._paused = True
+    yield
+    with self._condition:
+      self._paused = False
+      self._condition.notify_all()
+
+  @contextlib.contextmanager
+  def fail(self):  # pylint: disable=invalid-name
+    with self._condition:
+      self._fail = True
+    yield
+    with self._condition:
+      self._fail = False
+
+  def _control(self):  # pylint: disable=invalid-name
+    with self._condition:
+      if self._fail:
+        raise ValueError()
+      while self._paused:
+        self._condition.wait()
+    time.sleep(self._delay)
+
+  def UnaryCall(self, request, unused_rpc_context):
+    response = self._test_pb2.SimpleResponse()
+    response.payload.payload_type = self._test_pb2.COMPRESSABLE
+    response.payload.payload_compressable = 'a' * request.response_size
+    self._control()
+    return response
+
+  def StreamingOutputCall(self, request, unused_rpc_context):
+    for parameter in request.response_parameters:
+      response = self._test_pb2.StreamingOutputCallResponse()
+      response.payload.payload_type = self._test_pb2.COMPRESSABLE
+      response.payload.payload_compressable = 'a' * parameter.size
+      self._control()
+      yield response
+
+  def StreamingInputCall(self, request_iter, unused_rpc_context):
+    response = self._test_pb2.StreamingInputCallResponse()
+    aggregated_payload_size = 0
+    for request in request_iter:
+      aggregated_payload_size += len(request.payload.payload_compressable)
+    response.aggregated_payload_size = aggregated_payload_size
+    self._control()
+    return response
+
+  def FullDuplexCall(self, request_iter, unused_rpc_context):
+    for request in request_iter:
+      for parameter in request.response_parameters:
+        response = self._test_pb2.StreamingOutputCallResponse()
+        response.payload.payload_type = self._test_pb2.COMPRESSABLE
+        response.payload.payload_compressable = 'a' * parameter.size
+        self._control()
+        yield response
+
+  def HalfDuplexCall(self, request_iter, unused_rpc_context):
+    responses = []
+    for request in request_iter:
+      for parameter in request.response_parameters:
+        response = self._test_pb2.StreamingOutputCallResponse()
+        response.payload.payload_type = self._test_pb2.COMPRESSABLE
+        response.payload.payload_compressable = 'a' * parameter.size
+        self._control()
+        responses.append(response)
+    for response in responses:
+      yield response
+
+
+@contextlib.contextmanager
+def _CreateService(test_pb2, delay):
+  """Provides a servicer backend and a stub.
+
+  The servicer is just the implementation
+  of the actual servicer passed to the face player of the python RPC
+  implementation; the two are detached.
+
+  Non-zero delay puts a delay on each call to the servicer, representative of
+  communication latency. Timeout is the default timeout for the stub while
+  waiting for the service.
+
+  Args:
+    test_pb2: The test_pb2 module generated by this test.
+    delay: Delay in seconds per response from the servicer.
+
+  Yields:
+    A (servicer_methods, servicer, stub) three-tuple where servicer_methods is
+      the back-end of the service bound to the stub and the server and stub
+      are both activated and ready for use.
+  """
+  servicer_methods = _ServicerMethods(test_pb2, delay)
+
+  class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)):
+
+    def UnaryCall(self, request, context):
+      return servicer_methods.UnaryCall(request, context)
+
+    def StreamingOutputCall(self, request, context):
+      return servicer_methods.StreamingOutputCall(request, context)
+
+    def StreamingInputCall(self, request_iter, context):
+      return servicer_methods.StreamingInputCall(request_iter, context)
+
+    def FullDuplexCall(self, request_iter, context):
+      return servicer_methods.FullDuplexCall(request_iter, context)
+
+    def HalfDuplexCall(self, request_iter, context):
+      return servicer_methods.HalfDuplexCall(request_iter, context)
+
+  servicer = Servicer()
+  server = getattr(
+      test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer, 0)
+  with server:
+    port = server.port()
+    stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)('localhost', port)
+    with stub:
+      yield servicer_methods, stub, server
+
+
+def _streaming_input_request_iterator(test_pb2):
+  for _ in range(3):
+    request = test_pb2.StreamingInputCallRequest()
+    request.payload.payload_type = test_pb2.COMPRESSABLE
+    request.payload.payload_compressable = 'a'
+    yield request
+
+
+def _streaming_output_request(test_pb2):
+  request = test_pb2.StreamingOutputCallRequest()
+  sizes = [1, 2, 3]
+  request.response_parameters.add(size=sizes[0], interval_us=0)
+  request.response_parameters.add(size=sizes[1], interval_us=0)
+  request.response_parameters.add(size=sizes[2], interval_us=0)
+  return request
+
+
+def _full_duplex_request_iterator(test_pb2):
+  request = test_pb2.StreamingOutputCallRequest()
+  request.response_parameters.add(size=1, interval_us=0)
+  yield request
+  request = test_pb2.StreamingOutputCallRequest()
+  request.response_parameters.add(size=2, interval_us=0)
+  request.response_parameters.add(size=3, interval_us=0)
+  yield request
+
+
+class PythonPluginTest(unittest.TestCase):
+  """Test case for the gRPC Python protoc-plugin.
+
+  While reading these tests, remember that the futures API
+  (`stub.method.async()`) only gives futures for the *non-streaming* responses,
+  else it behaves like its blocking cousin.
+  """
+
+  def setUp(self):
+    # Assume that the appropriate protoc and grpc_python_plugins are on the
+    # path.
+    protoc_command = 'protoc'
+    protoc_plugin_filename = distutils.spawn.find_executable(
+        'grpc_python_plugin')
+    test_proto_filename = pkg_resources.resource_filename(
+        'grpc_protoc_plugin', 'test.proto')
+    if not os.path.isfile(protoc_command):
+      # Assume that if we haven't built protoc that it's on the system.
+      protoc_command = 'protoc'
+
+    # Ensure that the output directory exists.
+    self.outdir = tempfile.mkdtemp()
+
+    # Invoke protoc with the plugin.
+    cmd = [
+        protoc_command,
+        '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename,
+        '-I .',
+        '--python_out=%s' % self.outdir,
+        '--python-grpc_out=%s' % self.outdir,
+        os.path.basename(test_proto_filename),
+    ]
+    subprocess.check_call(' '.join(cmd), shell=True, env=os.environ,
+                          cwd=os.path.dirname(test_proto_filename))
+    sys.path.append(self.outdir)
+
+  def tearDown(self):
+    try:
+      shutil.rmtree(self.outdir)
+    except OSError as exc:
+      if exc.errno != errno.ENOENT:
+        raise
+
+  # TODO(atash): Figure out which of these tests is hanging flakily with small
+  # probability.
+
+  def testImportAttributes(self):
+    # check that we can access the generated module and its members.
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, SERVER_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None))
+
+  def testUpDown(self):
+    import test_pb2
+    with _CreateService(
+        test_pb2, NO_DELAY) as (servicer, stub, unused_server):
+      request = test_pb2.SimpleRequest(response_size=13)
+
+  def testUnaryCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server):
+      timeout = 6  # TODO(issue 2039): LONG_TIMEOUT like the other methods.
+      request = test_pb2.SimpleRequest(response_size=13)
+      response = stub.UnaryCall(request, timeout)
+    expected_response = methods.UnaryCall(request, 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testUnaryCallAsync(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = test_pb2.SimpleRequest(response_size=13)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      # Check that the call does not block waiting for the server to respond.
+      with methods.pause():
+        response_future = stub.UnaryCall.async(request, LONG_TIMEOUT)
+      response = response_future.result()
+    expected_response = methods.UnaryCall(request, 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testUnaryCallAsyncExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      request = test_pb2.SimpleRequest(response_size=13)
+      with methods.pause():
+        response_future = stub.UnaryCall.async(request, SHORT_TIMEOUT)
+        with self.assertRaises(exceptions.ExpirationError):
+          response_future.result()
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testUnaryCallAsyncCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = test_pb2.SimpleRequest(response_size=13)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.pause():
+        response_future = stub.UnaryCall.async(request, 1)
+        response_future.cancel()
+        self.assertTrue(response_future.cancelled())
+
+  def testUnaryCallAsyncFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = test_pb2.SimpleRequest(response_size=13)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.fail():
+        response_future = stub.UnaryCall.async(request, LONG_TIMEOUT)
+        self.assertIsNotNone(response_future.exception())
+
+  def testStreamingOutputCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server):
+      responses = stub.StreamingOutputCall(request, LONG_TIMEOUT)
+      expected_responses = methods.StreamingOutputCall(
+          request, 'not a real RpcContext!')
+      for expected_response, response in itertools.izip_longest(
+          expected_responses, responses):
+        self.assertEqual(expected_response, response)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testStreamingOutputCallExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.pause():
+        responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT)
+        with self.assertRaises(exceptions.ExpirationError):
+          list(responses)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testStreamingOutputCallCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        unused_methods, stub, unused_server):
+      responses = stub.StreamingOutputCall(request, SHORT_TIMEOUT)
+      next(responses)
+      responses.cancel()
+      with self.assertRaises(future.CancelledError):
+        next(responses)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this times out '
+                 'instead of raising the proper error.')
+  def testStreamingOutputCallFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.fail():
+        responses = stub.StreamingOutputCall(request, 1)
+        self.assertIsNotNone(responses)
+        with self.assertRaises(exceptions.ServicerError):
+          next(responses)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testStreamingInputCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server):
+      response = stub.StreamingInputCall(
+          _streaming_input_request_iterator(test_pb2), LONG_TIMEOUT)
+    expected_response = methods.StreamingInputCall(
+        _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testStreamingInputCallAsync(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.pause():
+        response_future = stub.StreamingInputCall.async(
+            _streaming_input_request_iterator(test_pb2), LONG_TIMEOUT)
+      response = response_future.result()
+    expected_response = methods.StreamingInputCall(
+        _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testStreamingInputCallAsyncExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.pause():
+        response_future = stub.StreamingInputCall.async(
+            _streaming_input_request_iterator(test_pb2), SHORT_TIMEOUT)
+        with self.assertRaises(exceptions.ExpirationError):
+          response_future.result()
+        self.assertIsInstance(
+            response_future.exception(), exceptions.ExpirationError)
+
+  def testStreamingInputCallAsyncCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.pause():
+        timeout = 6  # TODO(issue 2039): LONG_TIMEOUT like the other methods.
+        response_future = stub.StreamingInputCall.async(
+            _streaming_input_request_iterator(test_pb2), timeout)
+        response_future.cancel()
+        self.assertTrue(response_future.cancelled())
+      with self.assertRaises(future.CancelledError):
+        response_future.result()
+
+  def testStreamingInputCallAsyncFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.fail():
+        response_future = stub.StreamingInputCall.async(
+            _streaming_input_request_iterator(test_pb2), SHORT_TIMEOUT)
+        self.assertIsNotNone(response_future.exception())
+
+  def testFullDuplexCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server):
+      responses = stub.FullDuplexCall(
+          _full_duplex_request_iterator(test_pb2), LONG_TIMEOUT)
+      expected_responses = methods.FullDuplexCall(
+          _full_duplex_request_iterator(test_pb2), 'not a real RpcContext!')
+      for expected_response, response in itertools.izip_longest(
+          expected_responses, responses):
+        self.assertEqual(expected_response, response)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testFullDuplexCallExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request_iterator = _full_duplex_request_iterator(test_pb2)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.pause():
+        responses = stub.FullDuplexCall(request_iterator, SHORT_TIMEOUT)
+        with self.assertRaises(exceptions.ExpirationError):
+          list(responses)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testFullDuplexCallCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server):
+      request_iterator = _full_duplex_request_iterator(test_pb2)
+      responses = stub.FullDuplexCall(request_iterator, LONG_TIMEOUT)
+      next(responses)
+      responses.cancel()
+      with self.assertRaises(future.CancelledError):
+        next(responses)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this hangs forever '
+                 'and fix.')
+  def testFullDuplexCallFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request_iterator = _full_duplex_request_iterator(test_pb2)
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      with methods.fail():
+        responses = stub.FullDuplexCall(request_iterator, LONG_TIMEOUT)
+        self.assertIsNotNone(responses)
+        with self.assertRaises(exceptions.ServicerError):
+          next(responses)
+
+  @unittest.skip('TODO(atash,nathaniel): figure out why this flakily hangs '
+                 'forever and fix.')
+  def testHalfDuplexCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2, NO_DELAY) as (
+        methods, stub, unused_server):
+      def half_duplex_request_iterator():
+        request = test_pb2.StreamingOutputCallRequest()
+        request.response_parameters.add(size=1, interval_us=0)
+        yield request
+        request = test_pb2.StreamingOutputCallRequest()
+        request.response_parameters.add(size=2, interval_us=0)
+        request.response_parameters.add(size=3, interval_us=0)
+        yield request
+      responses = stub.HalfDuplexCall(
+          half_duplex_request_iterator(), LONG_TIMEOUT)
+      expected_responses = methods.HalfDuplexCall(
+          half_duplex_request_iterator(), 'not a real RpcContext!')
+      for check in itertools.izip_longest(expected_responses, responses):
+        expected_response, response = check
+        self.assertEqual(expected_response, response)
+
+  def testHalfDuplexCallWedged(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    condition = threading.Condition()
+    wait_cell = [False]
+    @contextlib.contextmanager
+    def wait():  # pylint: disable=invalid-name
+      # Where's Python 3's 'nonlocal' statement when you need it?
+      with condition:
+        wait_cell[0] = True
+      yield
+      with condition:
+        wait_cell[0] = False
+        condition.notify_all()
+    def half_duplex_request_iterator():
+      request = test_pb2.StreamingOutputCallRequest()
+      request.response_parameters.add(size=1, interval_us=0)
+      yield request
+      with condition:
+        while wait_cell[0]:
+          condition.wait()
+    with _CreateService(test_pb2, NO_DELAY) as (methods, stub, unused_server):
+      with wait():
+        responses = stub.HalfDuplexCall(
+            half_duplex_request_iterator(), SHORT_TIMEOUT)
+        # half-duplex waits for the client to send all info
+        with self.assertRaises(exceptions.ExpirationError):
+          next(responses)
+
+
+if __name__ == '__main__':
+  os.chdir(os.path.dirname(sys.argv[0]))
+  unittest.main(verbosity=2)
diff --git a/src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py b/src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py
new file mode 100644
index 0000000..4c8c64b
--- /dev/null
+++ b/src/python/grpcio_test/grpc_protoc_plugin/beta_python_plugin_test.py
@@ -0,0 +1,501 @@
+# 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.
+
+import argparse
+import contextlib
+import distutils.spawn
+import errno
+import itertools
+import os
+import pkg_resources
+import shutil
+import subprocess
+import sys
+import tempfile
+import threading
+import time
+import unittest
+
+from grpc.beta import beta
+from grpc.framework.foundation import future
+from grpc.framework.interfaces.face import face
+from grpc_test.framework.common import test_constants
+
+# Identifiers of entities we expect to find in the generated module.
+SERVICER_IDENTIFIER = 'BetaTestServiceServicer'
+STUB_IDENTIFIER = 'BetaTestServiceStub'
+SERVER_FACTORY_IDENTIFIER = 'beta_create_TestService_server'
+STUB_FACTORY_IDENTIFIER = 'beta_create_TestService_stub'
+
+
+class _ServicerMethods(object):
+
+  def __init__(self, test_pb2):
+    self._condition = threading.Condition()
+    self._paused = False
+    self._fail = False
+    self._test_pb2 = test_pb2
+
+  @contextlib.contextmanager
+  def pause(self):  # pylint: disable=invalid-name
+    with self._condition:
+      self._paused = True
+    yield
+    with self._condition:
+      self._paused = False
+      self._condition.notify_all()
+
+  @contextlib.contextmanager
+  def fail(self):  # pylint: disable=invalid-name
+    with self._condition:
+      self._fail = True
+    yield
+    with self._condition:
+      self._fail = False
+
+  def _control(self):  # pylint: disable=invalid-name
+    with self._condition:
+      if self._fail:
+        raise ValueError()
+      while self._paused:
+        self._condition.wait()
+
+  def UnaryCall(self, request, unused_rpc_context):
+    response = self._test_pb2.SimpleResponse()
+    response.payload.payload_type = self._test_pb2.COMPRESSABLE
+    response.payload.payload_compressable = 'a' * request.response_size
+    self._control()
+    return response
+
+  def StreamingOutputCall(self, request, unused_rpc_context):
+    for parameter in request.response_parameters:
+      response = self._test_pb2.StreamingOutputCallResponse()
+      response.payload.payload_type = self._test_pb2.COMPRESSABLE
+      response.payload.payload_compressable = 'a' * parameter.size
+      self._control()
+      yield response
+
+  def StreamingInputCall(self, request_iter, unused_rpc_context):
+    response = self._test_pb2.StreamingInputCallResponse()
+    aggregated_payload_size = 0
+    for request in request_iter:
+      aggregated_payload_size += len(request.payload.payload_compressable)
+    response.aggregated_payload_size = aggregated_payload_size
+    self._control()
+    return response
+
+  def FullDuplexCall(self, request_iter, unused_rpc_context):
+    for request in request_iter:
+      for parameter in request.response_parameters:
+        response = self._test_pb2.StreamingOutputCallResponse()
+        response.payload.payload_type = self._test_pb2.COMPRESSABLE
+        response.payload.payload_compressable = 'a' * parameter.size
+        self._control()
+        yield response
+
+  def HalfDuplexCall(self, request_iter, unused_rpc_context):
+    responses = []
+    for request in request_iter:
+      for parameter in request.response_parameters:
+        response = self._test_pb2.StreamingOutputCallResponse()
+        response.payload.payload_type = self._test_pb2.COMPRESSABLE
+        response.payload.payload_compressable = 'a' * parameter.size
+        self._control()
+        responses.append(response)
+    for response in responses:
+      yield response
+
+
+@contextlib.contextmanager
+def _CreateService(test_pb2):
+  """Provides a servicer backend and a stub.
+
+  The servicer is just the implementation of the actual servicer passed to the
+  face player of the python RPC implementation; the two are detached.
+
+  Args:
+    test_pb2: The test_pb2 module generated by this test.
+
+  Yields:
+    A (servicer_methods, stub) pair where servicer_methods is the back-end of
+      the service bound to the stub and and stub is the stub on which to invoke
+      RPCs.
+  """
+  servicer_methods = _ServicerMethods(test_pb2)
+
+  class Servicer(getattr(test_pb2, SERVICER_IDENTIFIER)):
+
+    def UnaryCall(self, request, context):
+      return servicer_methods.UnaryCall(request, context)
+
+    def StreamingOutputCall(self, request, context):
+      return servicer_methods.StreamingOutputCall(request, context)
+
+    def StreamingInputCall(self, request_iter, context):
+      return servicer_methods.StreamingInputCall(request_iter, context)
+
+    def FullDuplexCall(self, request_iter, context):
+      return servicer_methods.FullDuplexCall(request_iter, context)
+
+    def HalfDuplexCall(self, request_iter, context):
+      return servicer_methods.HalfDuplexCall(request_iter, context)
+
+  servicer = Servicer()
+  server = getattr(test_pb2, SERVER_FACTORY_IDENTIFIER)(servicer)
+  port = server.add_insecure_port('[::]:0')
+  server.start()
+  channel = beta.create_insecure_channel('localhost', port)
+  stub = getattr(test_pb2, STUB_FACTORY_IDENTIFIER)(channel)
+  yield servicer_methods, stub
+  server.stop(0)
+
+
+def _streaming_input_request_iterator(test_pb2):
+  for _ in range(3):
+    request = test_pb2.StreamingInputCallRequest()
+    request.payload.payload_type = test_pb2.COMPRESSABLE
+    request.payload.payload_compressable = 'a'
+    yield request
+
+
+def _streaming_output_request(test_pb2):
+  request = test_pb2.StreamingOutputCallRequest()
+  sizes = [1, 2, 3]
+  request.response_parameters.add(size=sizes[0], interval_us=0)
+  request.response_parameters.add(size=sizes[1], interval_us=0)
+  request.response_parameters.add(size=sizes[2], interval_us=0)
+  return request
+
+
+def _full_duplex_request_iterator(test_pb2):
+  request = test_pb2.StreamingOutputCallRequest()
+  request.response_parameters.add(size=1, interval_us=0)
+  yield request
+  request = test_pb2.StreamingOutputCallRequest()
+  request.response_parameters.add(size=2, interval_us=0)
+  request.response_parameters.add(size=3, interval_us=0)
+  yield request
+
+
+class PythonPluginTest(unittest.TestCase):
+  """Test case for the gRPC Python protoc-plugin.
+
+  While reading these tests, remember that the futures API
+  (`stub.method.future()`) only gives futures for the *response-unary*
+  methods and does not exist for response-streaming methods.
+  """
+
+  def setUp(self):
+    # Assume that the appropriate protoc and grpc_python_plugins are on the
+    # path.
+    protoc_command = 'protoc'
+    protoc_plugin_filename = distutils.spawn.find_executable(
+        'grpc_python_plugin')
+    test_proto_filename = pkg_resources.resource_filename(
+        'grpc_protoc_plugin', 'test.proto')
+    if not os.path.isfile(protoc_command):
+      # Assume that if we haven't built protoc that it's on the system.
+      protoc_command = 'protoc'
+
+    # Ensure that the output directory exists.
+    self.outdir = tempfile.mkdtemp()
+
+    # Invoke protoc with the plugin.
+    cmd = [
+        protoc_command,
+        '--plugin=protoc-gen-python-grpc=%s' % protoc_plugin_filename,
+        '-I .',
+        '--python_out=%s' % self.outdir,
+        '--python-grpc_out=%s' % self.outdir,
+        os.path.basename(test_proto_filename),
+    ]
+    subprocess.check_call(' '.join(cmd), shell=True, env=os.environ,
+                          cwd=os.path.dirname(test_proto_filename))
+    sys.path.append(self.outdir)
+
+  def tearDown(self):
+    try:
+      shutil.rmtree(self.outdir)
+    except OSError as exc:
+      if exc.errno != errno.ENOENT:
+        raise
+
+  def testImportAttributes(self):
+    # check that we can access the generated module and its members.
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    self.assertIsNotNone(getattr(test_pb2, SERVICER_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, STUB_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, SERVER_FACTORY_IDENTIFIER, None))
+    self.assertIsNotNone(getattr(test_pb2, STUB_FACTORY_IDENTIFIER, None))
+
+  def testUpDown(self):
+    import test_pb2
+    with _CreateService(test_pb2) as (servicer, stub):
+      request = test_pb2.SimpleRequest(response_size=13)
+
+  def testUnaryCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      request = test_pb2.SimpleRequest(response_size=13)
+      response = stub.UnaryCall(request, test_constants.LONG_TIMEOUT)
+    expected_response = methods.UnaryCall(request, 'not a real context!')
+    self.assertEqual(expected_response, response)
+
+  def testUnaryCallFuture(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = test_pb2.SimpleRequest(response_size=13)
+    with _CreateService(test_pb2) as (methods, stub):
+      # Check that the call does not block waiting for the server to respond.
+      with methods.pause():
+        response_future = stub.UnaryCall.future(
+            request, test_constants.LONG_TIMEOUT)
+      response = response_future.result()
+    expected_response = methods.UnaryCall(request, 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testUnaryCallFutureExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      request = test_pb2.SimpleRequest(response_size=13)
+      with methods.pause():
+        response_future = stub.UnaryCall.future(
+            request, test_constants.SHORT_TIMEOUT)
+        with self.assertRaises(face.ExpirationError):
+          response_future.result()
+
+  def testUnaryCallFutureCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = test_pb2.SimpleRequest(response_size=13)
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.pause():
+        response_future = stub.UnaryCall.future(request, 1)
+        response_future.cancel()
+        self.assertTrue(response_future.cancelled())
+
+  def testUnaryCallFutureFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = test_pb2.SimpleRequest(response_size=13)
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.fail():
+        response_future = stub.UnaryCall.future(
+            request, test_constants.LONG_TIMEOUT)
+        self.assertIsNotNone(response_future.exception())
+
+  def testStreamingOutputCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2) as (methods, stub):
+      responses = stub.StreamingOutputCall(
+          request, test_constants.LONG_TIMEOUT)
+      expected_responses = methods.StreamingOutputCall(
+          request, 'not a real RpcContext!')
+      for expected_response, response in itertools.izip_longest(
+          expected_responses, responses):
+        self.assertEqual(expected_response, response)
+
+  def testStreamingOutputCallExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.pause():
+        responses = stub.StreamingOutputCall(
+            request, test_constants.SHORT_TIMEOUT)
+        with self.assertRaises(face.ExpirationError):
+          list(responses)
+
+  def testStreamingOutputCallCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2) as (unused_methods, stub):
+      responses = stub.StreamingOutputCall(
+          request, test_constants.LONG_TIMEOUT)
+      next(responses)
+      responses.cancel()
+      with self.assertRaises(face.CancellationError):
+        next(responses)
+
+  def testStreamingOutputCallFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request = _streaming_output_request(test_pb2)
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.fail():
+        responses = stub.StreamingOutputCall(request, 1)
+        self.assertIsNotNone(responses)
+        with self.assertRaises(face.RemoteError):
+          next(responses)
+
+  def testStreamingInputCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      response = stub.StreamingInputCall(
+          _streaming_input_request_iterator(test_pb2),
+          test_constants.LONG_TIMEOUT)
+    expected_response = methods.StreamingInputCall(
+        _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testStreamingInputCallFuture(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.pause():
+        response_future = stub.StreamingInputCall.future(
+            _streaming_input_request_iterator(test_pb2),
+            test_constants.LONG_TIMEOUT)
+      response = response_future.result()
+    expected_response = methods.StreamingInputCall(
+        _streaming_input_request_iterator(test_pb2), 'not a real RpcContext!')
+    self.assertEqual(expected_response, response)
+
+  def testStreamingInputCallFutureExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.pause():
+        response_future = stub.StreamingInputCall.future(
+            _streaming_input_request_iterator(test_pb2),
+            test_constants.SHORT_TIMEOUT)
+        with self.assertRaises(face.ExpirationError):
+          response_future.result()
+        self.assertIsInstance(
+            response_future.exception(), face.ExpirationError)
+
+  def testStreamingInputCallFutureCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.pause():
+        response_future = stub.StreamingInputCall.future(
+            _streaming_input_request_iterator(test_pb2),
+            test_constants.LONG_TIMEOUT)
+        response_future.cancel()
+        self.assertTrue(response_future.cancelled())
+      with self.assertRaises(future.CancelledError):
+        response_future.result()
+
+  def testStreamingInputCallFutureFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.fail():
+        response_future = stub.StreamingInputCall.future(
+            _streaming_input_request_iterator(test_pb2),
+            test_constants.LONG_TIMEOUT)
+        self.assertIsNotNone(response_future.exception())
+
+  def testFullDuplexCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      responses = stub.FullDuplexCall(
+          _full_duplex_request_iterator(test_pb2), test_constants.LONG_TIMEOUT)
+      expected_responses = methods.FullDuplexCall(
+          _full_duplex_request_iterator(test_pb2), 'not a real RpcContext!')
+      for expected_response, response in itertools.izip_longest(
+          expected_responses, responses):
+        self.assertEqual(expected_response, response)
+
+  def testFullDuplexCallExpired(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request_iterator = _full_duplex_request_iterator(test_pb2)
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.pause():
+        responses = stub.FullDuplexCall(
+            request_iterator, test_constants.SHORT_TIMEOUT)
+        with self.assertRaises(face.ExpirationError):
+          list(responses)
+
+  def testFullDuplexCallCancelled(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      request_iterator = _full_duplex_request_iterator(test_pb2)
+      responses = stub.FullDuplexCall(
+          request_iterator, test_constants.LONG_TIMEOUT)
+      next(responses)
+      responses.cancel()
+      with self.assertRaises(face.CancellationError):
+        next(responses)
+
+  def testFullDuplexCallFailed(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    request_iterator = _full_duplex_request_iterator(test_pb2)
+    with _CreateService(test_pb2) as (methods, stub):
+      with methods.fail():
+        responses = stub.FullDuplexCall(
+            request_iterator, test_constants.LONG_TIMEOUT)
+        self.assertIsNotNone(responses)
+        with self.assertRaises(face.RemoteError):
+          next(responses)
+
+  def testHalfDuplexCall(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    with _CreateService(test_pb2) as (methods, stub):
+      def half_duplex_request_iterator():
+        request = test_pb2.StreamingOutputCallRequest()
+        request.response_parameters.add(size=1, interval_us=0)
+        yield request
+        request = test_pb2.StreamingOutputCallRequest()
+        request.response_parameters.add(size=2, interval_us=0)
+        request.response_parameters.add(size=3, interval_us=0)
+        yield request
+      responses = stub.HalfDuplexCall(
+          half_duplex_request_iterator(), test_constants.LONG_TIMEOUT)
+      expected_responses = methods.HalfDuplexCall(
+          half_duplex_request_iterator(), 'not a real RpcContext!')
+      for check in itertools.izip_longest(expected_responses, responses):
+        expected_response, response = check
+        self.assertEqual(expected_response, response)
+
+  def testHalfDuplexCallWedged(self):
+    import test_pb2  # pylint: disable=g-import-not-at-top
+    condition = threading.Condition()
+    wait_cell = [False]
+    @contextlib.contextmanager
+    def wait():  # pylint: disable=invalid-name
+      # Where's Python 3's 'nonlocal' statement when you need it?
+      with condition:
+        wait_cell[0] = True
+      yield
+      with condition:
+        wait_cell[0] = False
+        condition.notify_all()
+    def half_duplex_request_iterator():
+      request = test_pb2.StreamingOutputCallRequest()
+      request.response_parameters.add(size=1, interval_us=0)
+      yield request
+      with condition:
+        while wait_cell[0]:
+          condition.wait()
+    with _CreateService(test_pb2) as (methods, stub):
+      with wait():
+        responses = stub.HalfDuplexCall(
+            half_duplex_request_iterator(), test_constants.SHORT_TIMEOUT)
+        # half-duplex waits for the client to send all info
+        with self.assertRaises(face.ExpirationError):
+          next(responses)
+
+
+if __name__ == '__main__':
+  os.chdir(os.path.dirname(sys.argv[0]))
+  unittest.main(verbosity=2)
diff --git a/src/ruby/bin/math_server.rb b/src/ruby/bin/math_server.rb
index 9a921b1..562f197 100755
--- a/src/ruby/bin/math_server.rb
+++ b/src/ruby/bin/math_server.rb
@@ -171,7 +171,8 @@
 
 def test_server_creds
   certs = load_test_certs
-  GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
+  GRPC::Core::ServerCredentials.new(
+    nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
 end
 
 def main
diff --git a/src/ruby/bin/noproto_server.rb b/src/ruby/bin/noproto_server.rb
index 90baaf9..72a5762 100755
--- a/src/ruby/bin/noproto_server.rb
+++ b/src/ruby/bin/noproto_server.rb
@@ -77,7 +77,8 @@
 
 def test_server_creds
   certs = load_test_certs
-  GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
+  GRPC::Core::ServerCredentials.new(
+    nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
 end
 
 def main
diff --git a/src/ruby/ext/grpc/rb_server.c b/src/ruby/ext/grpc/rb_server.c
index bd19b2f..4469658 100644
--- a/src/ruby/ext/grpc/rb_server.c
+++ b/src/ruby/ext/grpc/rb_server.c
@@ -49,6 +49,9 @@
 /* id_at is the constructor method of the ruby standard Time class. */
 static ID id_at;
 
+/* id_insecure_server is used to indicate that a server is insecure */
+static VALUE id_insecure_server;
+
 /* grpc_rb_server wraps a grpc_server.  It provides a peer ruby object,
   'mark' to minimize copying when a server is created from ruby. */
 typedef struct grpc_rb_server {
@@ -314,7 +317,7 @@
   call-seq:
     // insecure port
     insecure_server = Server.new(cq, {'arg1': 'value1'})
-    insecure_server.add_http2_port('mydomain:50051')
+    insecure_server.add_http2_port('mydomain:50051', :this_port_is_insecure)
 
     // secure port
     server_creds = ...
@@ -322,21 +325,22 @@
     secure_server.add_http_port('mydomain:50051', server_creds)
 
     Adds a http2 port to server */
-static VALUE grpc_rb_server_add_http2_port(int argc, VALUE *argv, VALUE self) {
-  VALUE port = Qnil;
-  VALUE rb_creds = Qnil;
+static VALUE grpc_rb_server_add_http2_port(VALUE self, VALUE port,
+                                           VALUE rb_creds) {
   grpc_rb_server *s = NULL;
   grpc_server_credentials *creds = NULL;
   int recvd_port = 0;
 
-  /* "11" == 1 mandatory args, 1 (rb_creds) is optional */
-  rb_scan_args(argc, argv, "11", &port, &rb_creds);
-
   TypedData_Get_Struct(self, grpc_rb_server, &grpc_rb_server_data_type, s);
   if (s->wrapped == NULL) {
     rb_raise(rb_eRuntimeError, "destroyed!");
     return Qnil;
-  } else if (rb_creds == Qnil) {
+  } else if (TYPE(rb_creds) == T_SYMBOL) {
+    if (id_insecure_server != SYM2ID(rb_creds)) {
+      rb_raise(rb_eTypeError,
+               "bad creds symbol, want :this_port_is_insecure");
+      return Qnil;
+    }
     recvd_port =
         grpc_server_add_insecure_http2_port(s->wrapped, StringValueCStr(port));
     if (recvd_port == 0) {
@@ -378,8 +382,9 @@
   rb_define_alias(grpc_rb_cServer, "close", "destroy");
   rb_define_method(grpc_rb_cServer, "add_http2_port",
                    grpc_rb_server_add_http2_port,
-                   -1);
+                   2);
   id_at = rb_intern("at");
+  id_insecure_server = rb_intern("this_port_is_insecure");
 }
 
 /* Gets the wrapped server from the ruby wrapper */
diff --git a/src/ruby/ext/grpc/rb_server_credentials.c b/src/ruby/ext/grpc/rb_server_credentials.c
index 6af4c86..ea4d0d8 100644
--- a/src/ruby/ext/grpc/rb_server_credentials.c
+++ b/src/ruby/ext/grpc/rb_server_credentials.c
@@ -135,63 +135,117 @@
   return copy;
 }
 
-/* The attribute used on the mark object to hold the pem_root_certs. */
+/* The attribute used on the mark object to preserve the pem_root_certs. */
 static ID id_pem_root_certs;
 
-/* The attribute used on the mark object to hold the pem_private_key. */
-static ID id_pem_private_key;
+/* The attribute used on the mark object to preserve the pem_key_certs */
+static ID id_pem_key_certs;
 
-/* The attribute used on the mark object to hold the pem_private_key. */
-static ID id_pem_cert_chain;
+/* The key used to access the pem cert in a key_cert pair hash */
+static VALUE sym_cert_chain;
+
+/* The key used to access the pem private key in a key_cert pair hash */
+static VALUE sym_private_key;
 
 /*
   call-seq:
-    creds = ServerCredentials.new(pem_root_certs, pem_private_key,
-                                  pem_cert_chain)
-    creds = ServerCredentials.new(nil, pem_private_key,
-                                  pem_cert_chain)
+    creds = ServerCredentials.new(nil,
+                                  [{private_key: <pem_private_key1>,
+                                   {cert_chain: <pem_cert_chain1>}],
+                                  force_client_auth)
+    creds = ServerCredentials.new(pem_root_certs,
+                                  [{private_key: <pem_private_key1>,
+                                   {cert_chain: <pem_cert_chain1>}],
+                                  force_client_auth)
 
-    pem_root_certs: (required) PEM encoding of the server root certificate
-    pem_private_key: (optional) PEM encoding of the server's private key
-    pem_cert_chain: (optional) PEM encoding of the server's cert chain
+    pem_root_certs: (optional) PEM encoding of the server root certificate
+    pem_private_key: (required) PEM encoding of the server's private keys
+    force_client_auth: indicatees
 
     Initializes ServerCredential instances. */
 static VALUE grpc_rb_server_credentials_init(VALUE self, VALUE pem_root_certs,
-                                             VALUE pem_private_key,
-                                             VALUE pem_cert_chain) {
-  /* TODO support multiple key cert pairs in the ruby API. */
+                                             VALUE pem_key_certs,
+                                             VALUE force_client_auth) {
   grpc_rb_server_credentials *wrapper = NULL;
   grpc_server_credentials *creds = NULL;
-  grpc_ssl_pem_key_cert_pair key_cert_pair = {NULL, NULL};
+  grpc_ssl_pem_key_cert_pair *key_cert_pairs = NULL;
+  VALUE cert = Qnil;
+  VALUE key = Qnil;
+  VALUE key_cert = Qnil;
+  int auth_client = 0;
+  int num_key_certs = 0;
+  int i;
+
+  if (NIL_P(force_client_auth) ||
+      !(force_client_auth == Qfalse || force_client_auth == Qtrue)) {
+    rb_raise(rb_eTypeError,
+             "bad force_client_auth: got:<%s> want: <True|False|nil>",
+             rb_obj_classname(force_client_auth));
+    return Qnil;
+  }
+  if (NIL_P(pem_key_certs) || TYPE(pem_key_certs) != T_ARRAY) {
+    rb_raise(rb_eTypeError, "bad pem_key_certs: got:<%s> want: <Array>",
+             rb_obj_classname(pem_key_certs));
+    return Qnil;
+  }
+  num_key_certs = RARRAY_LEN(pem_key_certs);
+  if (num_key_certs == 0) {
+    rb_raise(rb_eTypeError, "bad pem_key_certs: it had no elements");
+    return Qnil;
+  }
+  for (i = 0; i < num_key_certs; i++) {
+    key_cert = rb_ary_entry(pem_key_certs, i);
+    if (key_cert == Qnil) {
+      rb_raise(rb_eTypeError,
+               "could not create a server credential: nil key_cert");
+      return Qnil;
+    } else if (TYPE(key_cert) != T_HASH) {
+      rb_raise(rb_eTypeError,
+               "could not create a server credential: want <Hash>, got <%s>",
+               rb_obj_classname(key_cert));
+      return Qnil;
+    } else if (rb_hash_aref(key_cert, sym_private_key) == Qnil) {
+      rb_raise(rb_eTypeError,
+               "could not create a server credential: want nil private key");
+      return Qnil;
+    } else if (rb_hash_aref(key_cert, sym_cert_chain) == Qnil) {
+      rb_raise(rb_eTypeError,
+               "could not create a server credential: want nil cert chain");
+      return Qnil;
+    }
+  }
+
+  auth_client = TYPE(force_client_auth) == T_TRUE;
+  key_cert_pairs = ALLOC_N(grpc_ssl_pem_key_cert_pair, num_key_certs);
+  for (i = 0; i < num_key_certs; i++) {
+    key_cert = rb_ary_entry(pem_key_certs, i);
+    key = rb_hash_aref(key_cert, sym_private_key);
+    cert = rb_hash_aref(key_cert, sym_cert_chain);
+    key_cert_pairs[i].private_key = RSTRING_PTR(key);
+    key_cert_pairs[i].cert_chain = RSTRING_PTR(cert);
+  }
+
   TypedData_Get_Struct(self, grpc_rb_server_credentials,
                        &grpc_rb_server_credentials_data_type, wrapper);
-  if (pem_cert_chain == Qnil) {
-    rb_raise(rb_eRuntimeError,
-             "could not create a server credential: nil pem_cert_chain");
-    return Qnil;
-  } else if (pem_private_key == Qnil) {
-    rb_raise(rb_eRuntimeError,
-             "could not create a server credential: nil pem_private_key");
-    return Qnil;
-  }
-  key_cert_pair.private_key = RSTRING_PTR(pem_private_key);
-  key_cert_pair.cert_chain = RSTRING_PTR(pem_cert_chain);
-  /* TODO Add a force_client_auth parameter and pass it here. */
+
   if (pem_root_certs == Qnil) {
-    creds =
-        grpc_ssl_server_credentials_create(NULL, &key_cert_pair, 1, 0, NULL);
+    creds = grpc_ssl_server_credentials_create(NULL, key_cert_pairs,
+                                               num_key_certs,
+                                               auth_client, NULL);
   } else {
     creds = grpc_ssl_server_credentials_create(RSTRING_PTR(pem_root_certs),
-                                               &key_cert_pair, 1, 0, NULL);
+                                               key_cert_pairs, num_key_certs,
+                                               auth_client, NULL);
   }
+  xfree(key_cert_pairs);
   if (creds == NULL) {
     rb_raise(rb_eRuntimeError, "could not create a credentials, not sure why");
+    return Qnil;
   }
   wrapper->wrapped = creds;
 
   /* Add the input objects as hidden fields to preserve them. */
-  rb_ivar_set(self, id_pem_cert_chain, pem_cert_chain);
-  rb_ivar_set(self, id_pem_private_key, pem_private_key);
+  rb_ivar_set(self, id_pem_key_certs, pem_key_certs);
   rb_ivar_set(self, id_pem_root_certs, pem_root_certs);
 
   return self;
@@ -211,9 +265,10 @@
   rb_define_method(grpc_rb_cServerCredentials, "initialize_copy",
                    grpc_rb_server_credentials_init_copy, 1);
 
-  id_pem_cert_chain = rb_intern("__pem_cert_chain");
-  id_pem_private_key = rb_intern("__pem_private_key");
+  id_pem_key_certs = rb_intern("__pem_key_certs");
   id_pem_root_certs = rb_intern("__pem_root_certs");
+  sym_private_key = ID2SYM(rb_intern("private_key"));
+  sym_cert_chain = ID2SYM(rb_intern("cert_chain"));
 }
 
 /* Gets the wrapped grpc_server_credentials from the ruby wrapper */
diff --git a/src/ruby/pb/test/server.rb b/src/ruby/pb/test/server.rb
index e2e1ecb..a311bb7 100755
--- a/src/ruby/pb/test/server.rb
+++ b/src/ruby/pb/test/server.rb
@@ -64,7 +64,8 @@
 # creates a ServerCredentials from the test certificates.
 def test_server_creds
   certs = load_test_certs
-  GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
+  GRPC::Core::ServerCredentials.new(
+      nil, [{private_key: certs[1], cert_chain: certs[2]}], false)
 end
 
 # produces a string of null chars (\0) of length l.
diff --git a/src/ruby/spec/client_server_spec.rb b/src/ruby/spec/client_server_spec.rb
index 2e673ff..387f2ba 100644
--- a/src/ruby/spec/client_server_spec.rb
+++ b/src/ruby/spec/client_server_spec.rb
@@ -32,12 +32,6 @@
 
 include GRPC::Core
 
-def load_test_certs
-  test_root = File.join(File.dirname(__FILE__), 'testdata')
-  files = ['ca.pem', 'server1.key', 'server1.pem']
-  files.map { |f| File.open(File.join(test_root, f)).read }
-end
-
 shared_context 'setup: tags' do
   let(:sent_message) { 'sent message' }
   let(:reply_text) { 'the reply' }
@@ -402,7 +396,7 @@
     @client_queue = GRPC::Core::CompletionQueue.new
     @server_queue = GRPC::Core::CompletionQueue.new
     @server = GRPC::Core::Server.new(@server_queue, nil)
-    server_port = @server.add_http2_port(server_host)
+    server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
     @server.start
     @ch = Channel.new("0.0.0.0:#{server_port}", nil)
   end
@@ -420,12 +414,19 @@
 end
 
 describe 'the secure http client/server' do
+  def load_test_certs
+    test_root = File.join(File.dirname(__FILE__), 'testdata')
+    files = ['ca.pem', 'server1.key', 'server1.pem']
+    files.map { |f| File.open(File.join(test_root, f)).read }
+  end
+
   before(:example) do
     certs = load_test_certs
     server_host = '0.0.0.0:0'
     @client_queue = GRPC::Core::CompletionQueue.new
     @server_queue = GRPC::Core::CompletionQueue.new
-    server_creds = GRPC::Core::ServerCredentials.new(nil, certs[1], certs[2])
+    server_creds = GRPC::Core::ServerCredentials.new(
+      nil, [{ private_key: certs[1], cert_chain: certs[2] }], false)
     @server = GRPC::Core::Server.new(@server_queue, nil)
     server_port = @server.add_http2_port(server_host, server_creds)
     @server.start
diff --git a/src/ruby/spec/credentials_spec.rb b/src/ruby/spec/credentials_spec.rb
index 8e72e85..b02219d 100644
--- a/src/ruby/spec/credentials_spec.rb
+++ b/src/ruby/spec/credentials_spec.rb
@@ -29,15 +29,15 @@
 
 require 'grpc'
 
-def load_test_certs
-  test_root = File.join(File.dirname(__FILE__), 'testdata')
-  files = ['ca.pem', 'server1.pem', 'server1.key']
-  files.map { |f| File.open(File.join(test_root, f)).read }
-end
+describe GRPC::Core::Credentials do
+  Credentials = GRPC::Core::Credentials
 
-Credentials = GRPC::Core::Credentials
+  def load_test_certs
+    test_root = File.join(File.dirname(__FILE__), 'testdata')
+    files = ['ca.pem', 'server1.pem', 'server1.key']
+    files.map { |f| File.open(File.join(test_root, f)).read }
+  end
 
-describe Credentials do
   describe '#new' do
     it 'can be constructed with fake inputs' do
       expect { Credentials.new('root_certs', 'key', 'cert') }.not_to raise_error
diff --git a/src/ruby/spec/generic/active_call_spec.rb b/src/ruby/spec/generic/active_call_spec.rb
index fcd7bd0..b05e328 100644
--- a/src/ruby/spec/generic/active_call_spec.rb
+++ b/src/ruby/spec/generic/active_call_spec.rb
@@ -46,7 +46,7 @@
     @server_queue = GRPC::Core::CompletionQueue.new
     host = '0.0.0.0:0'
     @server = GRPC::Core::Server.new(@server_queue, nil)
-    server_port = @server.add_http2_port(host)
+    server_port = @server.add_http2_port(host, :this_port_is_insecure)
     @server.start
     @ch = GRPC::Core::Channel.new("0.0.0.0:#{server_port}", nil)
   end
diff --git a/src/ruby/spec/generic/client_stub_spec.rb b/src/ruby/spec/generic/client_stub_spec.rb
index edcc962..a05433d 100644
--- a/src/ruby/spec/generic/client_stub_spec.rb
+++ b/src/ruby/spec/generic/client_stub_spec.rb
@@ -498,7 +498,7 @@
   def create_test_server
     @server_queue = GRPC::Core::CompletionQueue.new
     @server = GRPC::Core::Server.new(@server_queue, nil)
-    @server.add_http2_port('0.0.0.0:0')
+    @server.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
   end
 
   def expect_server_to_be_invoked(notifier)
diff --git a/src/ruby/spec/generic/rpc_server_spec.rb b/src/ruby/spec/generic/rpc_server_spec.rb
index 1295fd7..e484a9e 100644
--- a/src/ruby/spec/generic/rpc_server_spec.rb
+++ b/src/ruby/spec/generic/rpc_server_spec.rb
@@ -139,7 +139,7 @@
     @server_queue = GRPC::Core::CompletionQueue.new
     server_host = '0.0.0.0:0'
     @server = GRPC::Core::Server.new(@server_queue, nil)
-    server_port = @server.add_http2_port(server_host)
+    server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
     @host = "localhost:#{server_port}"
     @ch = GRPC::Core::Channel.new(@host, nil)
   end
diff --git a/src/ruby/spec/pb/health/checker_spec.rb b/src/ruby/spec/pb/health/checker_spec.rb
index 6999a69..d7b7535 100644
--- a/src/ruby/spec/pb/health/checker_spec.rb
+++ b/src/ruby/spec/pb/health/checker_spec.rb
@@ -186,7 +186,7 @@
       @server_queue = GRPC::Core::CompletionQueue.new
       server_host = '0.0.0.0:0'
       @server = GRPC::Core::Server.new(@server_queue, nil)
-      server_port = @server.add_http2_port(server_host)
+      server_port = @server.add_http2_port(server_host, :this_port_is_insecure)
       @host = "localhost:#{server_port}"
       @ch = GRPC::Core::Channel.new(@host, nil)
       @client_opts = { channel_override: @ch }
diff --git a/src/ruby/spec/server_credentials_spec.rb b/src/ruby/spec/server_credentials_spec.rb
index 55598bc..8ae5770 100644
--- a/src/ruby/spec/server_credentials_spec.rb
+++ b/src/ruby/spec/server_credentials_spec.rb
@@ -31,8 +31,9 @@
 
 def load_test_certs
   test_root = File.join(File.dirname(__FILE__), 'testdata')
-  files = ['ca.pem', 'server1.pem', 'server1.key']
-  files.map { |f| File.open(File.join(test_root, f)).read }
+  files = ['ca.pem', 'server1.key', 'server1.pem']
+  contents = files.map { |f| File.open(File.join(test_root, f)).read }
+  [contents[0], [{ private_key: contents[1], cert_chain: contents[2] }], false]
 end
 
 describe GRPC::Core::ServerCredentials do
@@ -40,7 +41,8 @@
 
   describe '#new' do
     it 'can be constructed from a fake CA PEM, server PEM and a server key' do
-      expect { Creds.new('a', 'b', 'c') }.not_to raise_error
+      creds = Creds.new('a', [{ private_key: 'a', cert_chain: 'b' }], false)
+      expect(creds).to_not be_nil
     end
 
     it 'can be constructed using the test certificates' do
@@ -48,21 +50,44 @@
       expect { Creds.new(*certs) }.not_to raise_error
     end
 
+    it 'cannot be constructed without a nil key_cert pair array' do
+      root_cert, _, _ = load_test_certs
+      blk = proc do
+        Creds.new(root_cert, nil, false)
+      end
+      expect(&blk).to raise_error
+    end
+
+    it 'cannot be constructed without any key_cert pairs' do
+      root_cert, _, _ = load_test_certs
+      blk = proc do
+        Creds.new(root_cert, [], false)
+      end
+      expect(&blk).to raise_error
+    end
+
     it 'cannot be constructed without a server cert chain' do
       root_cert, server_key, _ = load_test_certs
-      blk = proc { Creds.new(root_cert, server_key, nil) }
+      blk = proc do
+        Creds.new(root_cert,
+                  [{ server_key: server_key, cert_chain: nil }],
+                  false)
+      end
       expect(&blk).to raise_error
     end
 
     it 'cannot be constructed without a server key' do
       root_cert, _, _ = load_test_certs
-      blk = proc { Creds.new(root_cert, nil, cert_chain) }
+      blk = proc do
+        Creds.new(root_cert,
+                  [{ server_key: nil, cert_chain: cert_chain }])
+      end
       expect(&blk).to raise_error
     end
 
     it 'can be constructed without a root_cret' do
-      _, server_key, cert_chain = load_test_certs
-      blk = proc { Creds.new(nil, server_key, cert_chain) }
+      _, cert_pairs, _ = load_test_certs
+      blk = proc { Creds.new(nil, cert_pairs, false) }
       expect(&blk).to_not raise_error
     end
   end
diff --git a/src/ruby/spec/server_spec.rb b/src/ruby/spec/server_spec.rb
index 47fe575..439b19fb 100644
--- a/src/ruby/spec/server_spec.rb
+++ b/src/ruby/spec/server_spec.rb
@@ -32,7 +32,8 @@
 def load_test_certs
   test_root = File.join(File.dirname(__FILE__), 'testdata')
   files = ['ca.pem', 'server1.key', 'server1.pem']
-  files.map { |f| File.open(File.join(test_root, f)).read }
+  contents = files.map { |f| File.open(File.join(test_root, f)).read }
+  [contents[0], [{ private_key: contents[1], cert_chain: contents[2] }], false]
 end
 
 Server = GRPC::Core::Server
@@ -104,7 +105,7 @@
       it 'runs without failing' do
         blk = proc do
           s = Server.new(@cq, nil)
-          s.add_http2_port('localhost:0')
+          s.add_http2_port('localhost:0', :this_port_is_insecure)
           s.close(@cq)
         end
         expect(&blk).to_not raise_error
@@ -113,7 +114,10 @@
       it 'fails if the server is closed' do
         s = Server.new(@cq, nil)
         s.close(@cq)
-        expect { s.add_http2_port('localhost:0') }.to raise_error(RuntimeError)
+        blk = proc do
+          s.add_http2_port('localhost:0', :this_port_is_insecure)
+        end
+        expect(&blk).to raise_error(RuntimeError)
       end
     end
 
@@ -198,7 +202,7 @@
 
   def start_a_server
     s = Server.new(@cq, nil)
-    s.add_http2_port('0.0.0.0:0')
+    s.add_http2_port('0.0.0.0:0', :this_port_is_insecure)
     s.start
     s
   end
diff --git a/test/core/end2end/fixtures/chttp2_fake_security.c b/test/core/end2end/fixtures/chttp2_fake_security.c
index b4a248f..3e64cc0 100644
--- a/test/core/end2end/fixtures/chttp2_fake_security.c
+++ b/test/core/end2end/fixtures/chttp2_fake_security.c
@@ -128,7 +128,7 @@
   grpc_server_credentials *fake_ts_creds =
       grpc_fake_transport_security_server_credentials_create();
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(fake_ts_creds,
                                                         processor);
   }
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
index 201d202..9193a09 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack.c
@@ -138,7 +138,7 @@
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
   }
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
index e7375f1..2c605d1 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_poll.c
@@ -138,7 +138,7 @@
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
   }
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c
index be0dda2..8133a69 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_fullstack_with_proxy.c
@@ -167,7 +167,7 @@
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_cert_key_pair, 1, 0, NULL);
   if (fail_server_auth_check(server_args)) {
-    grpc_auth_metadata_processor processor = {process_auth_failure, NULL};
+    grpc_auth_metadata_processor processor = {process_auth_failure, NULL, NULL};
     grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
   }
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
diff --git a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
index 9a545b1..e61e276 100644
--- a/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
+++ b/test/core/end2end/fixtures/chttp2_simple_ssl_with_oauth2_fullstack.c
@@ -67,13 +67,21 @@
   return NULL;
 }
 
+typedef struct {
+  size_t pseudo_refcount;
+} test_processor_state;
+
 static void process_oauth2_success(void *state, grpc_auth_context *ctx,
                                    const grpc_metadata *md, size_t md_count,
                                    grpc_process_auth_metadata_done_cb cb,
                                    void *user_data) {
   const grpc_metadata *oauth2 =
       find_metadata(md, md_count, "Authorization", oauth2_md);
-  GPR_ASSERT(state == NULL);
+  test_processor_state *s;
+
+  GPR_ASSERT(state != NULL);
+  s = (test_processor_state *)state;
+  GPR_ASSERT(s->pseudo_refcount == 1);
   GPR_ASSERT(oauth2 != NULL);
   grpc_auth_context_add_cstring_property(ctx, client_identity_property_name,
                                          client_identity);
@@ -88,7 +96,10 @@
                                    void *user_data) {
   const grpc_metadata *oauth2 =
       find_metadata(md, md_count, "Authorization", oauth2_md);
-  GPR_ASSERT(state == NULL);
+  test_processor_state *s;
+  GPR_ASSERT(state != NULL);
+  s = (test_processor_state *)state;
+  GPR_ASSERT(s->pseudo_refcount == 1);
   GPR_ASSERT(oauth2 != NULL);
   cb(user_data, oauth2, 1, NULL, 0, GRPC_STATUS_UNAUTHENTICATED, NULL);
 }
@@ -171,20 +182,34 @@
   return 0;
 }
 
+static void processor_destroy(void *state) {
+  test_processor_state *s = (test_processor_state *)state;
+  GPR_ASSERT((s->pseudo_refcount--) == 1);
+  gpr_free(s);
+}
+
+static grpc_auth_metadata_processor test_processor_create(int failing) {
+  test_processor_state *s = gpr_malloc(sizeof(*s));
+  grpc_auth_metadata_processor result;
+  s->pseudo_refcount = 1;
+  result.state = s;
+  result.destroy = processor_destroy;
+  if (failing) {
+    result.process = process_oauth2_failure;
+  } else {
+    result.process = process_oauth2_success;
+  }
+  return result;
+}
+
 static void chttp2_init_server_simple_ssl_secure_fullstack(
     grpc_end2end_test_fixture *f, grpc_channel_args *server_args) {
   grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {test_server1_key,
                                                   test_server1_cert};
   grpc_server_credentials *ssl_creds =
       grpc_ssl_server_credentials_create(NULL, &pem_key_cert_pair, 1, 0, NULL);
-  grpc_auth_metadata_processor processor;
-  processor.state = NULL;
-  if (fail_server_auth_check(server_args)) {
-    processor.process = process_oauth2_failure;
-  } else {
-    processor.process = process_oauth2_success;
-  }
-  grpc_server_credentials_set_auth_metadata_processor(ssl_creds, processor);
+  grpc_server_credentials_set_auth_metadata_processor(
+      ssl_creds, test_processor_create(fail_server_auth_check(server_args)));
   chttp2_init_server_secure_fullstack(f, server_args, ssl_creds);
 }
 
diff --git a/test/cpp/client/credentials_test.cc b/test/cpp/client/credentials_test.cc
index 18fcffe..743ad06 100644
--- a/test/cpp/client/credentials_test.cc
+++ b/test/cpp/client/credentials_test.cc
@@ -31,7 +31,7 @@
  *
  */
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include <memory>
 
diff --git a/test/cpp/common/auth_property_iterator_test.cc b/test/cpp/common/auth_property_iterator_test.cc
index e6226d6..a629ff5 100644
--- a/test/cpp/common/auth_property_iterator_test.cc
+++ b/test/cpp/common/auth_property_iterator_test.cc
@@ -32,7 +32,7 @@
  */
 
 #include <grpc/grpc_security.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <gtest/gtest.h>
 #include "src/cpp/common/secure_auth_context.h"
 #include "test/cpp/util/string_ref_helper.h"
diff --git a/test/cpp/common/secure_auth_context_test.cc b/test/cpp/common/secure_auth_context_test.cc
index 25538c1..11de646 100644
--- a/test/cpp/common/secure_auth_context_test.cc
+++ b/test/cpp/common/secure_auth_context_test.cc
@@ -32,7 +32,7 @@
  */
 
 #include <grpc/grpc_security.h>
-#include <grpc++/support/auth_context.h>
+#include <grpc++/security/auth_context.h>
 #include <gtest/gtest.h>
 #include "src/cpp/common/secure_auth_context.h"
 #include "test/cpp/util/string_ref_helper.h"
@@ -50,7 +50,7 @@
 
 // Created with nullptr
 TEST_F(SecureAuthContextTest, EmptyContext) {
-  SecureAuthContext context(nullptr);
+  SecureAuthContext context(nullptr, true);
   EXPECT_TRUE(context.GetPeerIdentity().empty());
   EXPECT_TRUE(context.GetPeerIdentityPropertyName().empty());
   EXPECT_TRUE(context.FindPropertyValues("").empty());
@@ -60,12 +60,12 @@
 
 TEST_F(SecureAuthContextTest, Properties) {
   grpc_auth_context* ctx = grpc_auth_context_create(NULL);
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
-  grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
-  EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
+  SecureAuthContext context(ctx, true);
+  context.AddProperty("name", "chapi");
+  context.AddProperty("name", "chapo");
+  context.AddProperty("foo", "bar");
+  EXPECT_TRUE(context.SetPeerIdentityPropertyName("name"));
 
-  SecureAuthContext context(ctx);
   std::vector<grpc::string_ref> peer_identity = context.GetPeerIdentity();
   EXPECT_EQ(2u, peer_identity.size());
   EXPECT_EQ("chapi", ToString(peer_identity[0]));
@@ -78,12 +78,12 @@
 
 TEST_F(SecureAuthContextTest, Iterators) {
   grpc_auth_context* ctx = grpc_auth_context_create(NULL);
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapi");
-  grpc_auth_context_add_cstring_property(ctx, "name", "chapo");
-  grpc_auth_context_add_cstring_property(ctx, "foo", "bar");
-  EXPECT_EQ(1, grpc_auth_context_set_peer_identity_property_name(ctx, "name"));
+  SecureAuthContext context(ctx, true);
+  context.AddProperty("name", "chapi");
+  context.AddProperty("name", "chapo");
+  context.AddProperty("foo", "bar");
+  EXPECT_TRUE(context.SetPeerIdentityPropertyName("name"));
 
-  SecureAuthContext context(ctx);
   AuthPropertyIterator iter = context.begin();
   EXPECT_TRUE(context.end() != iter);
   AuthProperty p0 = *iter;
diff --git a/test/cpp/end2end/async_end2end_test.cc b/test/cpp/end2end/async_end2end_test.cc
index bbcac9b..686e762 100644
--- a/test/cpp/end2end/async_end2end_test.cc
+++ b/test/cpp/end2end/async_end2end_test.cc
@@ -39,11 +39,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/client_crash_test.cc b/test/cpp/end2end/client_crash_test.cc
index 3a6e552..058e696 100644
--- a/test/cpp/end2end/client_crash_test.cc
+++ b/test/cpp/end2end/client_crash_test.cc
@@ -37,11 +37,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/client_crash_test_server.cc b/test/cpp/end2end/client_crash_test_server.cc
index 79a7832..7ffeecc 100644
--- a/test/cpp/end2end/client_crash_test_server.cc
+++ b/test/cpp/end2end/client_crash_test_server.cc
@@ -39,7 +39,6 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include "test/cpp/util/echo.grpc.pb.h"
 
 DEFINE_string(address, "", "Address to bind to");
diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc
index 5e2332c..10a4c5a 100644
--- a/test/cpp/end2end/end2end_test.cc
+++ b/test/cpp/end2end/end2end_test.cc
@@ -40,11 +40,12 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/auth_metadata_processor.h>
+#include <grpc++/security/credentials.h>
+#include <grpc++/security/server_credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "src/core/security/credentials.h"
@@ -79,14 +80,23 @@
   }
 }
 
-void CheckServerAuthContext(const ServerContext* context) {
+void CheckServerAuthContext(const ServerContext* context,
+                            const grpc::string& expected_client_identity) {
   std::shared_ptr<const AuthContext> auth_ctx = context->auth_context();
   std::vector<grpc::string_ref> ssl =
       auth_ctx->FindPropertyValues("transport_security_type");
   EXPECT_EQ(1u, ssl.size());
   EXPECT_EQ("ssl", ToString(ssl[0]));
-  EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
-  EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());
+  if (expected_client_identity.length() == 0) {
+    EXPECT_TRUE(auth_ctx->GetPeerIdentityPropertyName().empty());
+    EXPECT_TRUE(auth_ctx->GetPeerIdentity().empty());
+    EXPECT_FALSE(auth_ctx->IsPeerAuthenticated());
+  } else {
+    auto identity = auth_ctx->GetPeerIdentity();
+    EXPECT_TRUE(auth_ctx->IsPeerAuthenticated());
+    EXPECT_EQ(1u, identity.size());
+    EXPECT_EQ(expected_client_identity, identity[0]);
+  }
 }
 
 bool CheckIsLocalhost(const grpc::string& addr) {
@@ -98,6 +108,54 @@
          addr.substr(0, kIpv6.size()) == kIpv6;
 }
 
+class TestAuthMetadataProcessor : public AuthMetadataProcessor {
+ public:
+  static const char kGoodGuy[];
+
+  TestAuthMetadataProcessor(bool is_blocking) : is_blocking_(is_blocking) {}
+
+  std::shared_ptr<Credentials> GetCompatibleClientCreds() {
+    return AccessTokenCredentials(kGoodGuy);
+  }
+  std::shared_ptr<Credentials> GetIncompatibleClientCreds() {
+    return AccessTokenCredentials("Mr Hyde");
+  }
+
+  // Interface implementation
+  bool IsBlocking() const GRPC_OVERRIDE { return is_blocking_; }
+
+  Status Process(const InputMetadata& auth_metadata, AuthContext* context,
+                 OutputMetadata* consumed_auth_metadata,
+                 OutputMetadata* response_metadata) GRPC_OVERRIDE {
+    EXPECT_TRUE(consumed_auth_metadata != nullptr);
+    EXPECT_TRUE(context != nullptr);
+    EXPECT_TRUE(response_metadata != nullptr);
+    auto auth_md = auth_metadata.find(GRPC_AUTHORIZATION_METADATA_KEY);
+    EXPECT_NE(auth_md, auth_metadata.end());
+    string_ref auth_md_value = auth_md->second;
+    if (auth_md_value.ends_with(kGoodGuy)) {
+      context->AddProperty(kIdentityPropName, kGoodGuy);
+      context->SetPeerIdentityPropertyName(kIdentityPropName);
+      consumed_auth_metadata->insert(
+          std::make_pair(string(auth_md->first.data(), auth_md->first.length()),
+                         auth_md->second));
+      return Status::OK;
+    } else {
+      return Status(StatusCode::UNAUTHENTICATED,
+                    string("Invalid principal: ") +
+                        string(auth_md_value.data(), auth_md_value.length()));
+    }
+  }
+
+ protected:
+  static const char kIdentityPropName[];
+  bool is_blocking_;
+};
+
+const char TestAuthMetadataProcessor::kGoodGuy[] = "Dr Jekyll";
+const char TestAuthMetadataProcessor::kIdentityPropName[] = "novel identity";
+
+
 }  // namespace
 
 class Proxy : public ::grpc::cpp::test::util::TestService::Service {
@@ -162,8 +220,10 @@
                                      ToString(iter->second));
       }
     }
-    if (request->has_param() && request->param().check_auth_context()) {
-      CheckServerAuthContext(context);
+    if (request->has_param() &&
+        (request->param().expected_client_identity().length() > 0 ||
+         request->param().check_auth_context())) {
+      CheckServerAuthContext(context, request->param().expected_client_identity());
     }
     if (request->has_param() &&
         request->param().response_message_length() > 0) {
@@ -259,9 +319,18 @@
 class End2endTest : public ::testing::TestWithParam<bool> {
  protected:
   End2endTest()
-      : kMaxMessageSize_(8192), special_service_("special") {}
+      : is_server_started_(false),
+        kMaxMessageSize_(8192),
+        special_service_("special") {}
 
-  void SetUp() GRPC_OVERRIDE {
+  void TearDown() GRPC_OVERRIDE {
+    if (is_server_started_) {
+      server_->Shutdown();
+      if (proxy_server_) proxy_server_->Shutdown();
+    }
+  }
+
+  void StartServer(const std::shared_ptr<AuthMetadataProcessor>& processor) {
     int port = grpc_pick_unused_port_or_die();
     server_address_ << "127.0.0.1:" << port;
     // Setup server
@@ -271,22 +340,23 @@
     SslServerCredentialsOptions ssl_opts;
     ssl_opts.pem_root_certs = "";
     ssl_opts.pem_key_cert_pairs.push_back(pkcp);
-    builder.AddListeningPort(server_address_.str(),
-                             SslServerCredentials(ssl_opts));
+    auto server_creds = SslServerCredentials(ssl_opts);
+    server_creds->SetAuthMetadataProcessor(processor);
+    builder.AddListeningPort(server_address_.str(), server_creds);
     builder.RegisterService(&service_);
     builder.RegisterService("foo.test.youtube.com", &special_service_);
     builder.SetMaxMessageSize(
         kMaxMessageSize_);  // For testing max message size.
     builder.RegisterService(&dup_pkg_service_);
     server_ = builder.BuildAndStart();
-  }
-
-  void TearDown() GRPC_OVERRIDE {
-    server_->Shutdown();
-    if (proxy_server_) proxy_server_->Shutdown();
+    is_server_started_ = true;
   }
 
   void ResetChannel() {
+    if (!is_server_started_) {
+      StartServer(std::shared_ptr<AuthMetadataProcessor>());
+    }
+    EXPECT_TRUE(is_server_started_);
     SslCredentialsOptions ssl_opts = {test_root_cert, "", ""};
     ChannelArguments args;
     args.SetSslTargetNameOverride("foo.test.google.fr");
@@ -313,6 +383,7 @@
     stub_ = std::move(grpc::cpp::test::util::TestService::NewStub(channel_));
   }
 
+  bool is_server_started_;
   std::shared_ptr<Channel> channel_;
   std::unique_ptr<grpc::cpp::test::util::TestService::Stub> stub_;
   std::unique_ptr<Server> server_;
@@ -805,6 +876,82 @@
   EXPECT_TRUE(s.ok());
 }
 
+TEST_F(End2endTest, NonBlockingAuthMetadataProcessorSuccess) {
+  auto* processor = new TestAuthMetadataProcessor(false);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetCompatibleClientCreds());
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
+  request.mutable_param()->set_expected_client_identity(
+      TestAuthMetadataProcessor::kGoodGuy);
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_EQ(request.message(), response.message());
+  EXPECT_TRUE(s.ok());
+
+  // Metadata should have been consumed by the processor.
+  EXPECT_FALSE(MetadataContains(
+      context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY,
+      grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
+}
+
+TEST_F(End2endTest, NonBlockingAuthMetadataProcessorFailure) {
+  auto* processor = new TestAuthMetadataProcessor(false);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetIncompatibleClientCreds());
+  request.set_message("Hello");
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_FALSE(s.ok());
+  EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+}
+
+TEST_F(End2endTest, BlockingAuthMetadataProcessorSuccess) {
+  auto* processor = new TestAuthMetadataProcessor(true);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetCompatibleClientCreds());
+  request.set_message("Hello");
+  request.mutable_param()->set_echo_metadata(true);
+  request.mutable_param()->set_expected_client_identity(
+      TestAuthMetadataProcessor::kGoodGuy);
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_EQ(request.message(), response.message());
+  EXPECT_TRUE(s.ok());
+
+  // Metadata should have been consumed by the processor.
+  EXPECT_FALSE(MetadataContains(
+      context.GetServerTrailingMetadata(), GRPC_AUTHORIZATION_METADATA_KEY,
+      grpc::string("Bearer ") + TestAuthMetadataProcessor::kGoodGuy));
+}
+
+TEST_F(End2endTest, BlockingAuthMetadataProcessorFailure) {
+  auto* processor = new TestAuthMetadataProcessor(true);
+  StartServer(std::shared_ptr<AuthMetadataProcessor>(processor));
+  ResetStub(false);
+  EchoRequest request;
+  EchoResponse response;
+  ClientContext context;
+  context.set_credentials(processor->GetIncompatibleClientCreds());
+  request.set_message("Hello");
+
+  Status s = stub_->Echo(&context, request, &response);
+  EXPECT_FALSE(s.ok());
+  EXPECT_EQ(s.error_code(), StatusCode::UNAUTHENTICATED);
+}
+
 // Client sends 20 requests and the server returns CANCELLED status after
 // reading 10 requests.
 TEST_F(End2endTest, RequestStreamServerEarlyCancelTest) {
diff --git a/test/cpp/end2end/generic_end2end_test.cc b/test/cpp/end2end/generic_end2end_test.cc
index 7acbc71..6a46916 100644
--- a/test/cpp/end2end/generic_end2end_test.cc
+++ b/test/cpp/end2end/generic_end2end_test.cc
@@ -40,13 +40,11 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/generic/async_generic_service.h>
 #include <grpc++/generic/generic_stub.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <grpc++/support/slice.h>
 #include <gtest/gtest.h>
 
diff --git a/test/cpp/end2end/mock_test.cc b/test/cpp/end2end/mock_test.cc
index 077d21a..4450e29 100644
--- a/test/cpp/end2end/mock_test.cc
+++ b/test/cpp/end2end/mock_test.cc
@@ -39,11 +39,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/server_crash_test.cc b/test/cpp/end2end/server_crash_test.cc
index 1a0f04e..4b6793a 100644
--- a/test/cpp/end2end/server_crash_test.cc
+++ b/test/cpp/end2end/server_crash_test.cc
@@ -37,11 +37,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/server_crash_test_client.cc b/test/cpp/end2end/server_crash_test_client.cc
index 6ff42fc..1786936 100644
--- a/test/cpp/end2end/server_crash_test_client.cc
+++ b/test/cpp/end2end/server_crash_test_client.cc
@@ -40,7 +40,6 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include "test/cpp/util/echo.grpc.pb.h"
 
 DEFINE_string(address, "", "Address to connect to");
diff --git a/test/cpp/end2end/shutdown_test.cc b/test/cpp/end2end/shutdown_test.cc
index 59fec6a..a25f85c 100644
--- a/test/cpp/end2end/shutdown_test.cc
+++ b/test/cpp/end2end/shutdown_test.cc
@@ -38,11 +38,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "src/core/support/env.h"
diff --git a/test/cpp/end2end/thread_stress_test.cc b/test/cpp/end2end/thread_stress_test.cc
index 2a16481..539e141 100644
--- a/test/cpp/end2end/thread_stress_test.cc
+++ b/test/cpp/end2end/thread_stress_test.cc
@@ -40,11 +40,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/end2end/zookeeper_test.cc b/test/cpp/end2end/zookeeper_test.cc
index 931541c..d4c7f04 100644
--- a/test/cpp/end2end/zookeeper_test.cc
+++ b/test/cpp/end2end/zookeeper_test.cc
@@ -34,11 +34,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 #include <grpc/grpc.h>
 #include <grpc/grpc_zookeeper.h>
diff --git a/test/cpp/interop/client_helper.cc b/test/cpp/interop/client_helper.cc
index 7093463..f85aa6a 100644
--- a/test/cpp/interop/client_helper.cc
+++ b/test/cpp/interop/client_helper.cc
@@ -45,7 +45,7 @@
 #include <gflags/gflags.h>
 #include <grpc++/channel.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include "src/cpp/client/secure_credentials.h"
 #include "test/core/security/oauth2_utils.h"
diff --git a/test/cpp/interop/interop_client.cc b/test/cpp/interop/interop_client.cc
index 73d1a14..48ccf06 100644
--- a/test/cpp/interop/interop_client.cc
+++ b/test/cpp/interop/interop_client.cc
@@ -44,7 +44,7 @@
 #include <grpc/support/useful.h>
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include "src/core/transport/stream_op.h"
 #include "test/cpp/interop/client_helper.h"
diff --git a/test/cpp/interop/reconnect_interop_server.cc b/test/cpp/interop/reconnect_interop_server.cc
index d4f171b..f52417b 100644
--- a/test/cpp/interop/reconnect_interop_server.cc
+++ b/test/cpp/interop/reconnect_interop_server.cc
@@ -45,7 +45,6 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 
 #include "test/core/util/reconnect_server.h"
 #include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/server.cc b/test/cpp/interop/server.cc
index 4921fde..03b6532 100644
--- a/test/cpp/interop/server.cc
+++ b/test/cpp/interop/server.cc
@@ -46,7 +46,7 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "test/cpp/interop/server_helper.h"
 #include "test/cpp/util/test_config.h"
diff --git a/test/cpp/interop/server_helper.cc b/test/cpp/interop/server_helper.cc
index e897f4e..0151983 100644
--- a/test/cpp/interop/server_helper.cc
+++ b/test/cpp/interop/server_helper.cc
@@ -36,7 +36,7 @@
 #include <memory>
 
 #include <gflags/gflags.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "src/core/surface/call.h"
 #include "test/core/end2end/data/ssl_test_data.h"
diff --git a/test/cpp/interop/server_helper.h b/test/cpp/interop/server_helper.h
index 7b6b12c..dc0ae1d 100644
--- a/test/cpp/interop/server_helper.h
+++ b/test/cpp/interop/server_helper.h
@@ -38,7 +38,7 @@
 
 #include <grpc/compression.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 namespace grpc {
 namespace testing {
diff --git a/test/cpp/qps/perf_db_client.h b/test/cpp/qps/perf_db_client.h
index ae5d170..72ebe79 100644
--- a/test/cpp/qps/perf_db_client.h
+++ b/test/cpp/qps/perf_db_client.h
@@ -41,7 +41,7 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include "test/cpp/qps/perf_db.grpc.pb.h"
 
 namespace grpc {
diff --git a/test/cpp/qps/qps_worker.cc b/test/cpp/qps/qps_worker.cc
index 51e955a..4b4ca1a 100644
--- a/test/cpp/qps/qps_worker.cc
+++ b/test/cpp/qps/qps_worker.cc
@@ -49,7 +49,7 @@
 #include <grpc++/client_context.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "test/core/util/grpc_profiler.h"
 #include "test/cpp/qps/qpstest.pb.h"
diff --git a/test/cpp/qps/server_async.cc b/test/cpp/qps/server_async.cc
index 77415f4..4160392 100644
--- a/test/cpp/qps/server_async.cc
+++ b/test/cpp/qps/server_async.cc
@@ -49,7 +49,7 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/cpp/qps/qpstest.grpc.pb.h"
diff --git a/test/cpp/qps/server_sync.cc b/test/cpp/qps/server_sync.cc
index 29ec19c..01ae348 100644
--- a/test/cpp/qps/server_sync.cc
+++ b/test/cpp/qps/server_sync.cc
@@ -43,7 +43,7 @@
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
+#include <grpc++/security/server_credentials.h>
 
 #include "test/cpp/qps/qpstest.grpc.pb.h"
 #include "test/cpp/qps/server.h"
diff --git a/test/cpp/util/cli_call_test.cc b/test/cpp/util/cli_call_test.cc
index 0efa201..b4133aa 100644
--- a/test/cpp/util/cli_call_test.cc
+++ b/test/cpp/util/cli_call_test.cc
@@ -37,11 +37,9 @@
 #include <grpc++/channel.h>
 #include <grpc++/client_context.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
 #include <grpc++/server.h>
 #include <grpc++/server_builder.h>
 #include <grpc++/server_context.h>
-#include <grpc++/server_credentials.h>
 #include <gtest/gtest.h>
 
 #include "test/core/util/port.h"
diff --git a/test/cpp/util/create_test_channel.cc b/test/cpp/util/create_test_channel.cc
index e993d14..f0d5bfc 100644
--- a/test/cpp/util/create_test_channel.cc
+++ b/test/cpp/util/create_test_channel.cc
@@ -34,7 +34,7 @@
 #include "test/cpp/util/create_test_channel.h"
 
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 #include "test/core/end2end/data/ssl_test_data.h"
 
diff --git a/test/cpp/util/create_test_channel.h b/test/cpp/util/create_test_channel.h
index 1263d4e..a475068 100644
--- a/test/cpp/util/create_test_channel.h
+++ b/test/cpp/util/create_test_channel.h
@@ -36,7 +36,7 @@
 
 #include <memory>
 
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 
 namespace grpc {
 class Channel;
diff --git a/test/cpp/util/grpc_cli.cc b/test/cpp/util/grpc_cli.cc
index 22cac21..334b6ef 100644
--- a/test/cpp/util/grpc_cli.cc
+++ b/test/cpp/util/grpc_cli.cc
@@ -1,5 +1,5 @@
 /*
- *
+
  * Copyright 2015, Google Inc.
  * All rights reserved.
  *
@@ -67,7 +67,7 @@
 #include <grpc/grpc.h>
 #include <grpc++/channel.h>
 #include <grpc++/create_channel.h>
-#include <grpc++/credentials.h>
+#include <grpc++/security/credentials.h>
 #include <grpc++/support/string_ref.h>
 
 #include "test/cpp/util/cli_call.h"
diff --git a/test/cpp/util/messages.proto b/test/cpp/util/messages.proto
index 359d1db..a022707 100644
--- a/test/cpp/util/messages.proto
+++ b/test/cpp/util/messages.proto
@@ -40,6 +40,7 @@
   bool check_auth_context = 5;
   int32 response_message_length = 6;
   bool echo_peer = 7;
+  string expected_client_identity = 8;  // will force check_auth_context.
 }
 
 message EchoRequest {
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index 887f616..96708c0 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -764,7 +764,6 @@
 include/grpc++/client_context.h \
 include/grpc++/completion_queue.h \
 include/grpc++/create_channel.h \
-include/grpc++/credentials.h \
 include/grpc++/generic/async_generic_service.h \
 include/grpc++/generic/generic_stub.h \
 include/grpc++/impl/call.h \
@@ -781,13 +780,15 @@
 include/grpc++/impl/thd.h \
 include/grpc++/impl/thd_cxx11.h \
 include/grpc++/impl/thd_no_cxx11.h \
+include/grpc++/security/auth_context.h \
+include/grpc++/security/auth_metadata_processor.h \
+include/grpc++/security/credentials.h \
+include/grpc++/security/server_credentials.h \
 include/grpc++/server.h \
 include/grpc++/server_builder.h \
 include/grpc++/server_context.h \
-include/grpc++/server_credentials.h \
 include/grpc++/support/async_stream.h \
 include/grpc++/support/async_unary_call.h \
-include/grpc++/support/auth_context.h \
 include/grpc++/support/byte_buffer.h \
 include/grpc++/support/channel_arguments.h \
 include/grpc++/support/config.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index 84b13f9..185d247 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -764,7 +764,6 @@
 include/grpc++/client_context.h \
 include/grpc++/completion_queue.h \
 include/grpc++/create_channel.h \
-include/grpc++/credentials.h \
 include/grpc++/generic/async_generic_service.h \
 include/grpc++/generic/generic_stub.h \
 include/grpc++/impl/call.h \
@@ -781,13 +780,15 @@
 include/grpc++/impl/thd.h \
 include/grpc++/impl/thd_cxx11.h \
 include/grpc++/impl/thd_no_cxx11.h \
+include/grpc++/security/auth_context.h \
+include/grpc++/security/auth_metadata_processor.h \
+include/grpc++/security/credentials.h \
+include/grpc++/security/server_credentials.h \
 include/grpc++/server.h \
 include/grpc++/server_builder.h \
 include/grpc++/server_context.h \
-include/grpc++/server_credentials.h \
 include/grpc++/support/async_stream.h \
 include/grpc++/support/async_unary_call.h \
-include/grpc++/support/auth_context.h \
 include/grpc++/support/byte_buffer.h \
 include/grpc++/support/channel_arguments.h \
 include/grpc++/support/config.h \
diff --git a/tools/run_tests/sources_and_headers.json b/tools/run_tests/sources_and_headers.json
index 7ce66de..939261d 100644
--- a/tools/run_tests/sources_and_headers.json
+++ b/tools/run_tests/sources_and_headers.json
@@ -13092,7 +13092,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13109,13 +13108,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
@@ -13143,7 +13144,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13160,13 +13160,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
@@ -13272,7 +13274,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13289,13 +13290,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
@@ -13320,7 +13323,6 @@
       "include/grpc++/client_context.h", 
       "include/grpc++/completion_queue.h", 
       "include/grpc++/create_channel.h", 
-      "include/grpc++/credentials.h", 
       "include/grpc++/generic/async_generic_service.h", 
       "include/grpc++/generic/generic_stub.h", 
       "include/grpc++/impl/call.h", 
@@ -13337,13 +13339,15 @@
       "include/grpc++/impl/thd.h", 
       "include/grpc++/impl/thd_cxx11.h", 
       "include/grpc++/impl/thd_no_cxx11.h", 
+      "include/grpc++/security/auth_context.h", 
+      "include/grpc++/security/auth_metadata_processor.h", 
+      "include/grpc++/security/credentials.h", 
+      "include/grpc++/security/server_credentials.h", 
       "include/grpc++/server.h", 
       "include/grpc++/server_builder.h", 
       "include/grpc++/server_context.h", 
-      "include/grpc++/server_credentials.h", 
       "include/grpc++/support/async_stream.h", 
       "include/grpc++/support/async_unary_call.h", 
-      "include/grpc++/support/auth_context.h", 
       "include/grpc++/support/byte_buffer.h", 
       "include/grpc++/support/channel_arguments.h", 
       "include/grpc++/support/config.h", 
diff --git a/vsprojects/grpc++/grpc++.vcxproj b/vsprojects/grpc++/grpc++.vcxproj
index 53930c1..5f8b7d8 100644
--- a/vsprojects/grpc++/grpc++.vcxproj
+++ b/vsprojects/grpc++/grpc++.vcxproj
@@ -217,7 +217,6 @@
     <ClInclude Include="..\..\include\grpc++\client_context.h" />
     <ClInclude Include="..\..\include\grpc++\completion_queue.h" />
     <ClInclude Include="..\..\include\grpc++\create_channel.h" />
-    <ClInclude Include="..\..\include\grpc++\credentials.h" />
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h" />
     <ClInclude Include="..\..\include\grpc++\generic\generic_stub.h" />
     <ClInclude Include="..\..\include\grpc++\impl\call.h" />
@@ -234,13 +233,15 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h" />
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h" />
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\server.h" />
     <ClInclude Include="..\..\include\grpc++\server_builder.h" />
     <ClInclude Include="..\..\include\grpc++\server_context.h" />
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h" />
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h" />
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h" />
     <ClInclude Include="..\..\include\grpc++\support\channel_arguments.h" />
     <ClInclude Include="..\..\include\grpc++\support\config.h" />
diff --git a/vsprojects/grpc++/grpc++.vcxproj.filters b/vsprojects/grpc++/grpc++.vcxproj.filters
index 6bc9ed6..38b5e14 100644
--- a/vsprojects/grpc++/grpc++.vcxproj.filters
+++ b/vsprojects/grpc++/grpc++.vcxproj.filters
@@ -111,9 +111,6 @@
     <ClInclude Include="..\..\include\grpc++\create_channel.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h">
       <Filter>include\grpc++\generic</Filter>
     </ClInclude>
@@ -162,6 +159,18 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\server.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
@@ -171,18 +180,12 @@
     <ClInclude Include="..\..\include\grpc++\server_context.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
@@ -257,6 +260,9 @@
     <Filter Include="include\grpc++\impl">
       <UniqueIdentifier>{0da8cd95-314f-da1b-5ce7-7791a5be1f1a}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\security">
+      <UniqueIdentifier>{a80eb32b-1be9-1187-5f40-30d92accecc8}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{a5c10dae-f715-2a30-1066-d22f8bc94cb2}</UniqueIdentifier>
     </Filter>
diff --git a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
index 12fa1b7..68154c6 100644
--- a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
+++ b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj
@@ -217,7 +217,6 @@
     <ClInclude Include="..\..\include\grpc++\client_context.h" />
     <ClInclude Include="..\..\include\grpc++\completion_queue.h" />
     <ClInclude Include="..\..\include\grpc++\create_channel.h" />
-    <ClInclude Include="..\..\include\grpc++\credentials.h" />
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h" />
     <ClInclude Include="..\..\include\grpc++\generic\generic_stub.h" />
     <ClInclude Include="..\..\include\grpc++\impl\call.h" />
@@ -234,13 +233,15 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_cxx11.h" />
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h" />
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h" />
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h" />
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\server.h" />
     <ClInclude Include="..\..\include\grpc++\server_builder.h" />
     <ClInclude Include="..\..\include\grpc++\server_context.h" />
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h" />
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h" />
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h" />
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h" />
     <ClInclude Include="..\..\include\grpc++\support\channel_arguments.h" />
     <ClInclude Include="..\..\include\grpc++\support\config.h" />
diff --git a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
index 17d9d53..52582d3 100644
--- a/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
+++ b/vsprojects/grpc++_unsecure/grpc++_unsecure.vcxproj.filters
@@ -96,9 +96,6 @@
     <ClInclude Include="..\..\include\grpc++\create_channel.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\generic\async_generic_service.h">
       <Filter>include\grpc++\generic</Filter>
     </ClInclude>
@@ -147,6 +144,18 @@
     <ClInclude Include="..\..\include\grpc++\impl\thd_no_cxx11.h">
       <Filter>include\grpc++\impl</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_context.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\auth_metadata_processor.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\include\grpc++\security\server_credentials.h">
+      <Filter>include\grpc++\security</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\server.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
@@ -156,18 +165,12 @@
     <ClInclude Include="..\..\include\grpc++\server_context.h">
       <Filter>include\grpc++</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\server_credentials.h">
-      <Filter>include\grpc++</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_stream.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\async_unary_call.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
-    <ClInclude Include="..\..\include\grpc++\support\auth_context.h">
-      <Filter>include\grpc++\support</Filter>
-    </ClInclude>
     <ClInclude Include="..\..\include\grpc++\support\byte_buffer.h">
       <Filter>include\grpc++\support</Filter>
     </ClInclude>
@@ -233,6 +236,9 @@
     <Filter Include="include\grpc++\impl">
       <UniqueIdentifier>{dadc0002-f2ac-451b-a9b8-33b8de10b5fc}</UniqueIdentifier>
     </Filter>
+    <Filter Include="include\grpc++\security">
+      <UniqueIdentifier>{64bf60ff-9192-bb59-dcc8-8a0021e1d016}</UniqueIdentifier>
+    </Filter>
     <Filter Include="include\grpc++\support">
       <UniqueIdentifier>{0ebf8008-80b9-d6da-e1dc-854bf1ec2195}</UniqueIdentifier>
     </Filter>