Merge pull request #983 from jboeuf/refresh_token_parsing

Adding refresh token credentials.
diff --git a/Makefile b/Makefile
index 8c6fc32..3e1efc7 100644
--- a/Makefile
+++ b/Makefile
@@ -159,9 +159,14 @@
 $(error Invalid CONFIG value '$(CONFIG)')
 endif
 
+ifeq ($(SYSTEM),Linux)
+TMPOUT = /dev/null
+else
+TMPOUT = `mktemp /tmp/test-out-XXXXXX`
+endif
 
 # Detect if we can use C++11
-CXX11_CHECK_CMD = $(CXX) -std=c++11 -o /dev/null -c test/build/c++11.cc
+CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc
 HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false)
 
 # The HOST compiler settings are used to compile the protoc plugins.
@@ -194,9 +199,25 @@
 
 INCLUDES = . include $(GENDIR)
 ifeq ($(SYSTEM),Darwin)
-INCLUDES += /usr/local/ssl/include /opt/local/include
+ifneq ($(wildcard /usr/local/ssl/include),)
+INCLUDES += /usr/local/ssl/include
+endif
+ifneq ($(wildcard /opt/local/include),)
+INCLUDES += /opt/local/include
+endif
+ifneq ($(wildcard /usr/local/include),)
+INCLUDES += /usr/local/include
+endif
 LIBS = m z
-LDFLAGS += -L/usr/local/ssl/lib -L/opt/local/lib
+ifneq ($(wildcard /usr/local/ssl/lib),)
+LDFLAGS += -L/usr/local/ssl/lib
+endif
+ifneq ($(wildcard /opt/local/lib),)
+LDFLAGS += -L/opt/local/lib
+endif
+ifneq ($(wildcard /usr/local/lib),)
+LDFLAGS += -L/usr/local/lib
+endif
 else
 LIBS = rt m z pthread
 LDFLAGS += -pthread
@@ -251,10 +272,10 @@
 IS_GIT_FOLDER = true
 endif
 
-OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS)
-ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS)
-PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS)
-PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o /dev/null test/build/protobuf.cc -lprotobuf $(LDFLAGS)
+OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS)
+ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
+PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS)
+PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
 PROTOC_CMD = which protoc
 PROTOC_CHECK_CMD = protoc --version | grep -q libprotoc.3
 
@@ -2036,10 +2057,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/gpr.$(SHARED_EXT) $(prefix)/lib/gpr.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr-imp.a $(prefix)/lib/libgpr-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing libgpr.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgpr.$(SHARED_EXT) $(prefix)/lib/libgpr.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf libgpr.$(SHARED_EXT) $(prefix)/lib/libgpr.so
 endif
 endif
@@ -2049,10 +2070,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc.$(SHARED_EXT) $(prefix)/lib/grpc.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc-imp.a $(prefix)/lib/libgrpc-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing libgrpc.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc.$(SHARED_EXT) $(prefix)/lib/libgrpc.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf libgrpc.$(SHARED_EXT) $(prefix)/lib/libgrpc.so
 endif
 endif
@@ -2062,10 +2083,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc_unsecure.$(SHARED_EXT) $(prefix)/lib/grpc_unsecure.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure-imp.a $(prefix)/lib/libgrpc_unsecure-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing libgrpc_unsecure.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc_unsecure.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf libgrpc_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc_unsecure.so
 endif
 endif
@@ -2083,10 +2104,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc++.$(SHARED_EXT) $(prefix)/lib/grpc++.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++-imp.a $(prefix)/lib/libgrpc++-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing libgrpc++.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++.$(SHARED_EXT) $(prefix)/lib/libgrpc++.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf libgrpc++.$(SHARED_EXT) $(prefix)/lib/libgrpc++.so
 endif
 endif
@@ -2096,10 +2117,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc++_unsecure.$(SHARED_EXT) $(prefix)/lib/grpc++_unsecure.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure-imp.a $(prefix)/lib/libgrpc++_unsecure-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing libgrpc++_unsecure.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc++_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc++_unsecure.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf libgrpc++_unsecure.$(SHARED_EXT) $(prefix)/lib/libgrpc++_unsecure.so
 endif
 endif
@@ -2117,10 +2138,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/grpc_csharp_ext.$(SHARED_EXT) $(prefix)/lib/grpc_csharp_ext.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext-imp.a $(prefix)/lib/libgrpc_csharp_ext-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing libgrpc_csharp_ext.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/libgrpc_csharp_ext.$(SHARED_EXT) $(prefix)/lib/libgrpc_csharp_ext.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf libgrpc_csharp_ext.$(SHARED_EXT) $(prefix)/lib/libgrpc_csharp_ext.so
 endif
 endif
diff --git a/include/grpc++/async_unary_call.h b/include/grpc++/async_unary_call.h
index f86a1ea..658941b 100644
--- a/include/grpc++/async_unary_call.h
+++ b/include/grpc++/async_unary_call.h
@@ -92,7 +92,7 @@
   explicit ServerAsyncResponseWriter(ServerContext* ctx)
       : call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
 
-  void SendInitialMetadata(void* tag) {
+  void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
     GPR_ASSERT(!ctx_->sent_initial_metadata_);
 
     meta_buf_.Reset(tag);
diff --git a/include/grpc++/channel_arguments.h b/include/grpc++/channel_arguments.h
index b649ba2..8d338c6 100644
--- a/include/grpc++/channel_arguments.h
+++ b/include/grpc++/channel_arguments.h
@@ -66,7 +66,7 @@
   void SetChannelArgs(grpc_channel_args* channel_args) const;
 
  private:
-  friend class Channel;
+  friend class SecureCredentials;
   friend class testing::ChannelArgumentsTest;
 
   // TODO(yangg) implement copy and assign
diff --git a/include/grpc++/server.h b/include/grpc++/server.h
index cc9cbe2..43c8432 100644
--- a/include/grpc++/server.h
+++ b/include/grpc++/server.h
@@ -96,7 +96,7 @@
   void RequestAsyncCall(void* registered_method, ServerContext* context,
                         grpc::protobuf::Message* request,
                         ServerAsyncStreamingInterface* stream,
-                        CompletionQueue* cq, void* tag);
+                        CompletionQueue* cq, void* tag) GRPC_OVERRIDE;
 
   // Completion queue.
   CompletionQueue cq_;
diff --git a/include/grpc/grpc_security.h b/include/grpc/grpc_security.h
index f941834..586cfcf 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -176,10 +176,9 @@
 grpc_server_credentials *grpc_fake_transport_security_server_credentials_create(
     void);
 
-/* --- Secure server creation. --- */
+/* --- Server-side secure ports. --- */
 
 /* Add a HTTP2 over an encrypted link over tcp listener.
-   Server must have been created with grpc_secure_server_create.
    Returns bound port number on success, 0 on failure.
    REQUIRES: server not started */
 int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr,
diff --git a/include/grpc/support/slice_buffer.h b/include/grpc/support/slice_buffer.h
index 56f71ef..c7e5dbc 100644
--- a/include/grpc/support/slice_buffer.h
+++ b/include/grpc/support/slice_buffer.h
@@ -74,6 +74,8 @@
 /* add a very small (less than 8 bytes) amount of data to the end of a slice
    buffer: returns a pointer into which to add the data */
 gpr_uint8 *gpr_slice_buffer_tiny_add(gpr_slice_buffer *sb, unsigned len);
+/* pop the last buffer, but don't unref it */
+void gpr_slice_buffer_pop(gpr_slice_buffer *sb);
 /* clear a slice buffer, unref all elements */
 void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb);
 
diff --git a/src/core/support/slice_buffer.c b/src/core/support/slice_buffer.c
index 6cd51f9..b280e4b 100644
--- a/src/core/support/slice_buffer.c
+++ b/src/core/support/slice_buffer.c
@@ -143,6 +143,13 @@
   }
 }
 
+void gpr_slice_buffer_pop(gpr_slice_buffer *sb) {
+  if (sb->count != 0) {
+    size_t count = --sb->count;
+    sb->length -= GPR_SLICE_LENGTH(sb->slices[count]);
+  }
+}
+
 void gpr_slice_buffer_reset_and_unref(gpr_slice_buffer *sb) {
   size_t i;
 
diff --git a/src/cpp/client/insecure_credentials.cc b/src/cpp/client/insecure_credentials.cc
index 2dcfe69..f3ca430 100644
--- a/src/cpp/client/insecure_credentials.cc
+++ b/src/cpp/client/insecure_credentials.cc
@@ -54,7 +54,7 @@
         target, grpc_channel_create(target.c_str(), &channel_args)));
   }
 
-  SecureCredentials* AsSecureCredentials() { return nullptr; }
+  SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return nullptr; }
 };
 }  // namespace
 
diff --git a/src/cpp/client/secure_credentials.cc b/src/cpp/client/secure_credentials.cc
index 5eb5c54..6ca702e 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -54,11 +54,12 @@
     grpc_channel_args channel_args;
     args.SetChannelArgs(&channel_args);
     return std::shared_ptr<ChannelInterface>(new Channel(
-        target,
+        args.GetSslTargetNameOverride().empty()
+            ? target : args.GetSslTargetNameOverride(),
         grpc_secure_channel_create(c_creds_, target.c_str(), &channel_args)));
   }
 
-  SecureCredentials* AsSecureCredentials() { return this; }
+  SecureCredentials* AsSecureCredentials() GRPC_OVERRIDE { return this; }
 
  private:
   grpc_credentials* const c_creds_;
diff --git a/src/cpp/proto/proto_utils.cc b/src/cpp/proto/proto_utils.cc
index 72f1bf7..e4e51bf 100644
--- a/src/cpp/proto/proto_utils.cc
+++ b/src/cpp/proto/proto_utils.cc
@@ -35,38 +35,135 @@
 #include <grpc++/config.h>
 
 #include <grpc/grpc.h>
+#include <grpc/byte_buffer.h>
 #include <grpc/support/slice.h>
+#include <grpc/support/slice_buffer.h>
+#include <grpc/support/port_platform.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+
+const int kMaxBufferLength = 8192;
+
+class GrpcBufferWriter GRPC_FINAL
+    : public ::google::protobuf::io::ZeroCopyOutputStream {
+ public:
+  explicit GrpcBufferWriter(grpc_byte_buffer **bp,
+                            int block_size = kMaxBufferLength)
+      : block_size_(block_size), byte_count_(0), have_backup_(false) {
+    *bp = grpc_byte_buffer_create(NULL, 0);
+    slice_buffer_ = &(*bp)->data.slice_buffer;
+  }
+
+  ~GrpcBufferWriter() GRPC_OVERRIDE {
+    if (have_backup_) {
+      gpr_slice_unref(backup_slice_);
+    }
+  }
+
+  bool Next(void **data, int *size) GRPC_OVERRIDE {
+    if (have_backup_) {
+      slice_ = backup_slice_;
+      have_backup_ = false;
+    } else {
+      slice_ = gpr_slice_malloc(block_size_);
+    }
+    *data = GPR_SLICE_START_PTR(slice_);
+    byte_count_ += *size = GPR_SLICE_LENGTH(slice_);
+    gpr_slice_buffer_add(slice_buffer_, slice_);
+    return true;
+  }
+
+  void BackUp(int count) GRPC_OVERRIDE {
+    gpr_slice_buffer_pop(slice_buffer_);
+    if (count == block_size_) {
+      backup_slice_ = slice_;
+    } else {
+      backup_slice_ =
+          gpr_slice_split_tail(&slice_, GPR_SLICE_LENGTH(slice_) - count);
+      gpr_slice_buffer_add(slice_buffer_, slice_);
+    }
+    have_backup_ = true;
+    byte_count_ -= count;
+  }
+
+  gpr_int64 ByteCount() const GRPC_OVERRIDE { return byte_count_; }
+
+ private:
+  const int block_size_;
+  gpr_int64 byte_count_;
+  gpr_slice_buffer *slice_buffer_;
+  bool have_backup_;
+  gpr_slice backup_slice_;
+  gpr_slice slice_;
+};
+
+class GrpcBufferReader GRPC_FINAL
+    : public ::google::protobuf::io::ZeroCopyInputStream {
+ public:
+  explicit GrpcBufferReader(grpc_byte_buffer *buffer)
+      : byte_count_(0), backup_count_(0) {
+    reader_ = grpc_byte_buffer_reader_create(buffer);
+  }
+  ~GrpcBufferReader() GRPC_OVERRIDE {
+    grpc_byte_buffer_reader_destroy(reader_);
+  }
+
+  bool Next(const void **data, int *size) GRPC_OVERRIDE {
+    if (backup_count_ > 0) {
+      *data = GPR_SLICE_START_PTR(slice_) + GPR_SLICE_LENGTH(slice_) -
+              backup_count_;
+      *size = backup_count_;
+      backup_count_ = 0;
+      return true;
+    }
+    if (!grpc_byte_buffer_reader_next(reader_, &slice_)) {
+      return false;
+    }
+    gpr_slice_unref(slice_);
+    *data = GPR_SLICE_START_PTR(slice_);
+    byte_count_ += *size = GPR_SLICE_LENGTH(slice_);
+    return true;
+  }
+
+  void BackUp(int count) GRPC_OVERRIDE {
+    backup_count_ = count;
+  }
+
+  bool Skip(int count) GRPC_OVERRIDE {
+    const void *data;
+    int size;
+    while (Next(&data, &size)) {
+      if (size >= count) {
+        BackUp(size - count);
+        return true;
+      }
+      // size < count;
+      count -= size;
+    }
+    // error or we have too large count;
+    return false;
+  }
+
+  gpr_int64 ByteCount() const GRPC_OVERRIDE {
+    return byte_count_ - backup_count_;
+  }
+
+ private:
+  gpr_int64 byte_count_;
+  gpr_int64 backup_count_;
+  grpc_byte_buffer_reader *reader_;
+  gpr_slice slice_;
+};
 
 namespace grpc {
 
-bool SerializeProto(const grpc::protobuf::Message &msg,
-                    grpc_byte_buffer **bp) {
-  grpc::string msg_str;
-  bool success = msg.SerializeToString(&msg_str);
-  if (success) {
-    gpr_slice slice =
-        gpr_slice_from_copied_buffer(msg_str.data(), msg_str.length());
-    *bp = grpc_byte_buffer_create(&slice, 1);
-    gpr_slice_unref(slice);
-  }
-  return success;
+bool SerializeProto(const grpc::protobuf::Message &msg, grpc_byte_buffer **bp) {
+  GrpcBufferWriter writer(bp);
+  return msg.SerializeToZeroCopyStream(&writer);
 }
 
-bool DeserializeProto(grpc_byte_buffer *buffer,
-                      grpc::protobuf::Message *msg) {
-  grpc::string msg_string;
-  grpc_byte_buffer_reader *reader = grpc_byte_buffer_reader_create(buffer);
-  gpr_slice slice;
-  while (grpc_byte_buffer_reader_next(reader, &slice)) {
-    const char *data = reinterpret_cast<const char *>(
-        slice.refcount ? slice.data.refcounted.bytes
-                       : slice.data.inlined.bytes);
-    msg_string.append(data, slice.refcount ? slice.data.refcounted.length
-                                           : slice.data.inlined.length);
-    gpr_slice_unref(slice);
-  }
-  grpc_byte_buffer_reader_destroy(reader);
-  return msg->ParseFromString(msg_string);
+bool DeserializeProto(grpc_byte_buffer *buffer, grpc::protobuf::Message *msg) {
+  GrpcBufferReader reader(buffer);
+  return msg->ParseFromZeroCopyStream(&reader);
 }
 
 }  // namespace grpc
diff --git a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
index 39be35c..e73159b 100644
--- a/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ClientServerTest.cs
@@ -122,10 +122,13 @@
             {
                 var call = new Call<string, string>(unaryEchoStringMethod, channel);
 
-                try {
+                try
+                {
                     Calls.BlockingUnaryCall(call, "ABC", default(CancellationToken));
                     Assert.Fail();
-                } catch(RpcException e) {
+                }
+                catch (RpcException e)
+                {
                     Assert.AreEqual(StatusCode.Unimplemented, e.Status.StatusCode);
                 }
             }
@@ -140,4 +143,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
index 596918c..6a132a5 100644
--- a/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
+++ b/src/csharp/Grpc.Core.Tests/GrpcEnvironmentTest.cs
@@ -68,7 +68,7 @@
             var tp2 = GrpcEnvironment.ThreadPool;
             GrpcEnvironment.Shutdown();
 
-            Assert.IsFalse(Object.ReferenceEquals(tp1, tp2));
+            Assert.IsFalse(object.ReferenceEquals(tp1, tp2));
         }
     }
 }
diff --git a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
index 9db08d2..3beffc3 100644
--- a/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
+++ b/src/csharp/Grpc.Core.Tests/PInvokeTest.cs
@@ -33,13 +33,13 @@
 
 using System;
 using System.Diagnostics;
+using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
 using Grpc.Core;
 using Grpc.Core.Internal;
 using Grpc.Core.Utils;
 using NUnit.Framework;
-using System.Runtime.InteropServices;
 
 namespace Grpc.Core.Tests
 {
@@ -73,14 +73,13 @@
         {
             BenchmarkUtil.RunBenchmark(
                 100000, 1000000,
-                () => {
+                () =>
+                {
                     CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create();
                     cq.Dispose();
-                }
-            );
+                });
         }
 
-
         /// <summary>
         /// Approximate results:
         /// (~80ns Mono Linux)
@@ -94,10 +93,10 @@
             counter = 0;
             BenchmarkUtil.RunBenchmark(
                 1000000, 10000000,
-                () => {
+                () =>
+                {
                     grpcsharp_test_callback(handler);
-                }
-            );
+                });
             Assert.AreNotEqual(0, counter);
         }
 
@@ -113,10 +112,10 @@
             counter = 0;
             BenchmarkUtil.RunBenchmark(
                 10000, 10000,
-                () => {
-                grpcsharp_test_callback(new CompletionCallbackDelegate(Handler));
-            }
-            );
+                () =>
+                {
+                    grpcsharp_test_callback(new CompletionCallbackDelegate(Handler));
+                });
             Assert.AreNotEqual(0, counter);
         }
 
@@ -129,15 +128,15 @@
         {
             BenchmarkUtil.RunBenchmark(
                 1000000, 100000000,
-                () => {
+                () =>
+                {
                     grpcsharp_test_nop(IntPtr.Zero);
-                }
-            );
+                });
         }
 
-        private void Handler(GRPCOpError op, IntPtr ptr) {
-            counter ++;
+        private void Handler(GRPCOpError op, IntPtr ptr)
+        {
+            counter++;
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
index 499d931..e432880 100644
--- a/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core.Tests/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
 [assembly: AssemblyTitle("Grpc.Core.Tests")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@
 [assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 [assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.Core.Tests/ServerTest.cs b/src/csharp/Grpc.Core.Tests/ServerTest.cs
index dd30366..12f914b 100644
--- a/src/csharp/Grpc.Core.Tests/ServerTest.cs
+++ b/src/csharp/Grpc.Core.Tests/ServerTest.cs
@@ -53,6 +53,5 @@
 
             GrpcEnvironment.Shutdown();
         }
-
     }
 }
diff --git a/src/csharp/Grpc.Core.Tests/TimespecTest.cs b/src/csharp/Grpc.Core.Tests/TimespecTest.cs
index 0ca84ec..f5bae6d 100644
--- a/src/csharp/Grpc.Core.Tests/TimespecTest.cs
+++ b/src/csharp/Grpc.Core.Tests/TimespecTest.cs
@@ -86,4 +86,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Call.cs b/src/csharp/Grpc.Core/Call.cs
index 72dca68..d84d594 100644
--- a/src/csharp/Grpc.Core/Call.cs
+++ b/src/csharp/Grpc.Core/Call.cs
@@ -47,7 +47,8 @@
                     Func<TRequest, byte[]> requestSerializer,
                     Func<byte[], TResponse> responseDeserializer,
                     TimeSpan timeout,
-                    Channel channel) {
+                    Channel channel)
+        {
             this.methodName = methodName;
             this.requestSerializer = requestSerializer;
             this.responseDeserializer = responseDeserializer;
@@ -95,4 +96,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Calls.cs b/src/csharp/Grpc.Core/Calls.cs
index ee2208e..cc1d67a 100644
--- a/src/csharp/Grpc.Core/Calls.cs
+++ b/src/csharp/Grpc.Core/Calls.cs
@@ -38,8 +38,6 @@
 
 namespace Grpc.Core
 {
-    // NOTE: this class is work-in-progress
-
     /// <summary>
     /// Helper methods for generated stubs to make RPC calls.
     /// </summary>
@@ -89,9 +87,9 @@
             return new ClientStreamingInputObserver<TRequest, TResponse>(asyncCall);
         }
 
-        private static CompletionQueueSafeHandle GetCompletionQueue() {
+        private static CompletionQueueSafeHandle GetCompletionQueue()
+        {
             return GrpcEnvironment.ThreadPool.CompletionQueue;
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Channel.cs b/src/csharp/Grpc.Core/Channel.cs
index 83d965d..3a42dac 100644
--- a/src/csharp/Grpc.Core/Channel.cs
+++ b/src/csharp/Grpc.Core/Channel.cs
@@ -36,10 +36,13 @@
 
 namespace Grpc.Core
 {
+    /// <summary>
+    /// gRPC Channel
+    /// </summary>
     public class Channel : IDisposable
     {
         readonly ChannelSafeHandle handle;
-        readonly String target;
+        readonly string target;
 
         /// <summary>
         /// Creates a channel.
diff --git a/src/csharp/Grpc.Core/ChannelArgs.cs b/src/csharp/Grpc.Core/ChannelArgs.cs
index 298b6ed..74ab310 100644
--- a/src/csharp/Grpc.Core/ChannelArgs.cs
+++ b/src/csharp/Grpc.Core/ChannelArgs.cs
@@ -30,6 +30,7 @@
 #endregion
 using System;
 using System.Collections.Generic;
+using System.Collections.Immutable;
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Threading.Tasks;
@@ -37,33 +38,18 @@
 
 namespace Grpc.Core
 {
-    // TODO: should we be using the builder pattern?
+    /// <summary>
+    /// gRPC channel options.
+    /// </summary>
     public class ChannelArgs
     {
         public const string SslTargetNameOverrideKey = "grpc.ssl_target_name_override";
 
-        public class Builder
+        readonly ImmutableDictionary<string, string> stringArgs;
+
+        private ChannelArgs(ImmutableDictionary<string, string> stringArgs)
         {
-            Dictionary<string,string> stringArgs = new Dictionary<string,string>();
-            // TODO: AddInteger not supported yet.
-            public Builder AddString(string key, string value)
-            {
-                stringArgs.Add(key, value);
-                return this;
-            }
-
-            public ChannelArgs Build()
-            {
-                return new ChannelArgs(stringArgs);
-            }
-        }
-
-        Dictionary<string,string> stringArgs;
-
-        private ChannelArgs(Dictionary<string, string> stringArgs)
-        {
-            // TODO: use immutable dict?
-            this.stringArgs = new Dictionary<string, string>(stringArgs);
+            this.stringArgs = stringArgs;
         }
 
         public string GetSslTargetNameOverride()
@@ -76,11 +62,28 @@
             return null;
         }
 
-        public static Builder NewBuilder()
+        public static Builder CreateBuilder()
         {
             return new Builder();
         }
 
+        public class Builder
+        {
+            readonly Dictionary<string, string> stringArgs = new Dictionary<string, string>();
+
+            // TODO: AddInteger not supported yet.
+            public Builder AddString(string key, string value)
+            {
+                stringArgs.Add(key, value);
+                return this;
+            }
+
+            public ChannelArgs Build()
+            {
+                return new ChannelArgs(stringArgs.ToImmutableDictionary());
+            }
+        }
+
         /// <summary>
         /// Creates native object for the channel arguments.
         /// </summary>
diff --git a/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs b/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
index 44580a1..65bedb0 100644
--- a/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
+++ b/src/csharp/Grpc.Core/ClientStreamingAsyncResult.cs
@@ -67,4 +67,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Credentials.cs b/src/csharp/Grpc.Core/Credentials.cs
index 5116c27..15dd3ef 100644
--- a/src/csharp/Grpc.Core/Credentials.cs
+++ b/src/csharp/Grpc.Core/Credentials.cs
@@ -36,6 +36,9 @@
 
 namespace Grpc.Core
 {
+    /// <summary>
+    /// Client-side credentials.
+    /// </summary>
     public abstract class Credentials
     {
         /// <summary>
@@ -74,4 +77,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Grpc.Core.csproj b/src/csharp/Grpc.Core/Grpc.Core.csproj
index 78b6cdde..29f1a06 100644
--- a/src/csharp/Grpc.Core/Grpc.Core.csproj
+++ b/src/csharp/Grpc.Core/Grpc.Core.csproj
@@ -31,6 +31,9 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
+    <Reference Include="System.Collections.Immutable">
+      <HintPath>..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Internal\GrpcLog.cs" />
@@ -54,7 +57,7 @@
     <Compile Include="Internal\ServerSafeHandle.cs" />
     <Compile Include="Method.cs" />
     <Compile Include="ServerCalls.cs" />
-    <Compile Include="ServerCallHandler.cs" />
+    <Compile Include="Internal\ServerCallHandler.cs" />
     <Compile Include="Marshaller.cs" />
     <Compile Include="ServerServiceDefinition.cs" />
     <Compile Include="Utils\RecordingObserver.cs" />
@@ -74,6 +77,11 @@
     <Compile Include="OperationFailedException.cs" />
     <Compile Include="Internal\AsyncCall.cs" />
     <Compile Include="Utils\Preconditions.cs" />
+    <Compile Include="Internal\ServerCredentialsSafeHandle.cs" />
+    <Compile Include="ServerCredentials.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="packages.config" />
   </ItemGroup>
   <Choose>
     <!-- Under older versions of Monodevelop, Choose is not supported and is just
diff --git a/src/csharp/Grpc.Core/GrpcEnvironment.cs b/src/csharp/Grpc.Core/GrpcEnvironment.cs
index d3a8da4..9c10a42 100644
--- a/src/csharp/Grpc.Core/GrpcEnvironment.cs
+++ b/src/csharp/Grpc.Core/GrpcEnvironment.cs
@@ -63,8 +63,9 @@
         /// lifetime (and call Shutdown once you're done), for the sake of easier testing it's
         /// allowed to initialize the environment again after it has been successfully shutdown.
         /// </summary>
-        public static void Initialize() {
-            lock(staticLock)
+        public static void Initialize()
+        {
+            lock (staticLock)
             {
                 if (instance == null)
                 {
@@ -79,7 +80,7 @@
         /// </summary>
         public static void Shutdown()
         {
-            lock(staticLock)
+            lock (staticLock)
             {
                 if (instance != null)
                 {
@@ -133,4 +134,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCall.cs b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
index 5ae0362..04fc28d 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCall.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCall.cs
@@ -54,7 +54,7 @@
         TaskCompletionSource<TResponse> unaryResponseTcs;
 
         // Set after status is received. Only used for streaming response calls.
-        Nullable<Status> finishedStatus;
+        Status? finishedStatus;
 
         bool readObserverCompleted;  // True if readObserver has already been completed.
 
@@ -64,7 +64,7 @@
             this.finishedHandler = CreateBatchCompletionCallback(HandleFinished);
         }
 
-        public void Initialize(Channel channel, CompletionQueueSafeHandle cq, String methodName)
+        public void Initialize(Channel channel, CompletionQueueSafeHandle cq, string methodName)
         {
             var call = CallSafeHandle.Create(channel.Handle, cq, methodName, channel.Target, Timespec.InfFuture);
             InitializeInternal(call);
@@ -77,9 +77,9 @@
         /// <summary>
         /// Blocking unary request - unary response call.
         /// </summary>
-        public TResponse UnaryCall(Channel channel, String methodName, TRequest msg)
+        public TResponse UnaryCall(Channel channel, string methodName, TRequest msg)
         {
-            using(CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
+            using (CompletionQueueSafeHandle cq = CompletionQueueSafeHandle.Create())
             {
                 byte[] payload = UnsafeSerialize(msg);
 
@@ -254,7 +254,7 @@
         /// </summary>
         private void HandleUnaryResponse(bool wasError, BatchContextSafeHandleNotOwned ctx)
         {
-            lock(myLock)
+            lock (myLock)
             {
                 finished = true;
                 halfclosed = true;
@@ -264,9 +264,7 @@
 
             if (wasError)
             {
-                unaryResponseTcs.SetException(new RpcException(
-                    new Status(StatusCode.Internal, "Internal error occured.")
-                ));
+                unaryResponseTcs.SetException(new RpcException(new Status(StatusCode.Internal, "Internal error occured.")));
                 return;
             }
 
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
index 44d66b3..15b0cfe 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCallBase.cs
@@ -225,7 +225,7 @@
                 payload = serializer(msg);
                 return true;
             }
-            catch(Exception)
+            catch (Exception)
             {
                 Console.WriteLine("Exception occured while trying to serialize message");
                 payload = null;
@@ -240,7 +240,7 @@
                 msg = deserializer(payload);
                 return true;
             } 
-            catch(Exception)
+            catch (Exception)
             {
                 Console.WriteLine("Exception occured while trying to deserialize message");
                 msg = default(TRead);
@@ -254,7 +254,7 @@
             {
                 readObserver.OnNext(value);
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Console.WriteLine("Exception occured while invoking readObserver.OnNext: " + e);
             }
@@ -266,7 +266,7 @@
             {
                 readObserver.OnCompleted();
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Console.WriteLine("Exception occured while invoking readObserver.OnCompleted: " + e);
             }
@@ -278,7 +278,7 @@
             {
                 readObserver.OnError(error);
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Console.WriteLine("Exception occured while invoking readObserver.OnError: " + e);
             }
@@ -290,7 +290,7 @@
             {
                 completionDelegate(error);
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Console.WriteLine("Exception occured while invoking completion delegate: " + e);
             }
@@ -302,14 +302,15 @@
         /// </summary>
         protected CompletionCallbackDelegate CreateBatchCompletionCallback(Action<bool, BatchContextSafeHandleNotOwned> handler)
         {
-            return new CompletionCallbackDelegate( (error, batchContextPtr) => {
+            return new CompletionCallbackDelegate((error, batchContextPtr) =>
+            {
                 try
                 {
                     var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
                     bool wasError = (error != GRPCOpError.GRPC_OP_OK);
                     handler(wasError, ctx);
                 }
-                catch(Exception e)
+                catch (Exception e)
                 {
                     Console.WriteLine("Caught exception in a native handler: " + e);
                 }
@@ -363,7 +364,6 @@
             {
                 FireCompletion(origCompletionDelegate, null);
             }
-           
         }
 
         /// <summary>
diff --git a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
index b78bb49..673b527 100644
--- a/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
+++ b/src/csharp/Grpc.Core/Internal/AsyncCompletion.cs
@@ -91,5 +91,4 @@
             tcs.SetException(error);
         }
     }
-
 }
\ No newline at end of file
diff --git a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
index 75cd30e..3c54753 100644
--- a/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
+++ b/src/csharp/Grpc.Core/Internal/BatchContextSafeHandleNotOwned.cs
@@ -80,16 +80,18 @@
             {
                 return null;
             }
-            byte[] data = new byte[(int) len];
+            byte[] data = new byte[(int)len];
             grpcsharp_batch_context_recv_message_to_buffer(this, data, new UIntPtr((ulong)data.Length));
             return data;
         }
 
-        public CallSafeHandle GetServerRpcNewCall() {
+        public CallSafeHandle GetServerRpcNewCall()
+        {
             return grpcsharp_batch_context_server_rpc_new_call(this);
         }
 
-        public string GetServerRpcNewMethod() {
+        public string GetServerRpcNewMethod()
+        {
             return Marshal.PtrToStringAnsi(grpcsharp_batch_context_server_rpc_new_method(this));
         }
     }
diff --git a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
index 61566b5..a8cef4a 100644
--- a/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CallSafeHandle.cs
@@ -36,13 +36,14 @@
 
 namespace Grpc.Core.Internal
 {
-    internal delegate void CompletionCallbackDelegate(GRPCOpError error,IntPtr batchContextPtr);
+    internal delegate void CompletionCallbackDelegate(GRPCOpError error, IntPtr batchContextPtr);
+    
     /// <summary>
     /// grpc_call from <grpc/grpc.h>
     /// </summary>
     internal class CallSafeHandle : SafeHandleZeroIsInvalid
     {
-        const UInt32 GRPC_WRITE_BUFFER_HINT = 1;
+        const uint GRPC_WRITE_BUFFER_HINT = 1;
 
         [DllImport("grpc_csharp_ext.dll")]
         static extern CallSafeHandle grpcsharp_channel_create_call(ChannelSafeHandle channel, CompletionQueueSafeHandle cq, string method, string host, Timespec deadline);
@@ -179,7 +180,7 @@
             Trace.Assert(callError == GRPCCallError.GRPC_CALL_OK, "Status not GRPC_CALL_OK");
         }
 
-        private static UInt32 GetFlags(bool buffered)
+        private static uint GetFlags(bool buffered)
         {
             return buffered ? 0 : GRPC_WRITE_BUFFER_HINT;
         }
diff --git a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
index ca3c21d..c69f1a0 100644
--- a/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ChannelArgsSafeHandle.cs
@@ -74,4 +74,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
index 6bff923..600d1fc 100644
--- a/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/CompletionQueueSafeHandle.cs
@@ -77,4 +77,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/Enums.cs b/src/csharp/Grpc.Core/Internal/Enums.cs
index f363050..94a2fd1 100644
--- a/src/csharp/Grpc.Core/Internal/Enums.cs
+++ b/src/csharp/Grpc.Core/Internal/Enums.cs
@@ -112,4 +112,3 @@
         GRPC_OP_ERROR
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/GrpcLog.cs b/src/csharp/Grpc.Core/Internal/GrpcLog.cs
index 98768d0..2f3c8ad 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcLog.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcLog.cs
@@ -40,7 +40,7 @@
 
 namespace Grpc.Core.Internal
 {
-    internal delegate void GprLogDelegate(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr);
+    internal delegate void GprLogDelegate(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr);
 
     /// <summary>
     /// Logs from gRPC C core library can get lost if your application is not a console app.
@@ -73,7 +73,7 @@
             }
         }
 
-        private static void HandleWrite(IntPtr fileStringPtr, Int32 line, UInt64 threadId, IntPtr severityStringPtr, IntPtr msgPtr)
+        private static void HandleWrite(IntPtr fileStringPtr, int line, ulong threadId, IntPtr severityStringPtr, IntPtr msgPtr)
         {
             try
             {
diff --git a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
index 9e69fe2..f422466 100644
--- a/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
+++ b/src/csharp/Grpc.Core/Internal/GrpcThreadPool.cs
@@ -51,12 +51,13 @@
 
         CompletionQueueSafeHandle cq;
 
-        public GrpcThreadPool(int poolSize) {
+        public GrpcThreadPool(int poolSize)
+        {
             this.poolSize = poolSize;
         }
 
-        public void Start() {
-
+        public void Start()
+        {
             lock (myLock)
             {
                 if (cq != null)
@@ -73,8 +74,8 @@
             }
         }
 
-        public void Stop() {
-
+        public void Stop()
+        {
             lock (myLock)
             {
                 cq.Shutdown();
@@ -86,7 +87,6 @@
                 }
 
                 cq.Dispose();
-
             }
         }
 
@@ -116,10 +116,9 @@
             do
             {
                 completionType = cq.NextWithCallback();
-            } while(completionType != GRPCCompletionType.GRPC_QUEUE_SHUTDOWN);
+            }
+            while (completionType != GRPCCompletionType.GRPC_QUEUE_SHUTDOWN);
             Console.WriteLine("Completion queue has shutdown successfully, thread " + Thread.CurrentThread.Name + " exiting.");
         }
     }
-
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs b/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
index aa6fce2..702aea2 100644
--- a/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
+++ b/src/csharp/Grpc.Core/Internal/SafeHandleZeroIsInvalid.cs
@@ -64,4 +64,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/ServerCallHandler.cs b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
similarity index 97%
rename from src/csharp/Grpc.Core/ServerCallHandler.cs
rename to src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
index 3eb8422..25fd4fa 100644
--- a/src/csharp/Grpc.Core/ServerCallHandler.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerCallHandler.cs
@@ -36,7 +36,7 @@
 using Grpc.Core.Internal;
 using Grpc.Core.Utils;
 
-namespace Grpc.Core
+namespace Grpc.Core.Internal
 {
     internal interface IServerCallHandler
     {
@@ -70,7 +70,6 @@
             handler(request, responseObserver);
 
             finishedTask.Wait();
-
         }
     }
 
@@ -93,7 +92,7 @@
 
             asyncCall.Initialize(call);
 
-            var responseObserver = new ServerStreamingOutputObserver<TRequest,TResponse>(asyncCall);
+            var responseObserver = new ServerStreamingOutputObserver<TRequest, TResponse>(asyncCall);
             var requestObserver = handler(responseObserver);
             var finishedTask = asyncCall.ServerSideCallAsync(requestObserver);
             finishedTask.Wait();
@@ -113,7 +112,7 @@
             var finishedTask = asyncCall.ServerSideCallAsync(new NullObserver<byte[]>());
 
             // TODO: check result of the completion status.
-            asyncCall.StartSendStatusFromServer(new Status(StatusCode.Unimplemented, "No such method."), new AsyncCompletionDelegate((error) => {}));
+            asyncCall.StartSendStatusFromServer(new Status(StatusCode.Unimplemented, "No such method."), new AsyncCompletionDelegate((error) => { }));
 
             finishedTask.Wait();
         }
@@ -132,7 +131,5 @@
         public void OnNext(T value)
         {
         }
-
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
new file mode 100644
index 0000000..9611807
--- /dev/null
+++ b/src/csharp/Grpc.Core/Internal/ServerCredentialsSafeHandle.cs
@@ -0,0 +1,68 @@
+#region Copyright notice and license
+// 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.
+#endregion
+using System;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Grpc.Core.Utils;
+
+namespace Grpc.Core.Internal
+{
+    /// <summary>
+    /// grpc_server_credentials from <grpc/grpc_security.h>
+    /// </summary>
+    internal class ServerCredentialsSafeHandle : SafeHandleZeroIsInvalid
+    {
+        [DllImport("grpc_csharp_ext.dll", CharSet = CharSet.Ansi)]
+        static extern ServerCredentialsSafeHandle grpcsharp_ssl_server_credentials_create(string pemRootCerts, string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray, UIntPtr numKeyCertPairs);
+
+        [DllImport("grpc_csharp_ext.dll")]
+        static extern void grpcsharp_server_credentials_release(IntPtr credentials);
+
+        private ServerCredentialsSafeHandle()
+        {
+        }
+
+        public static ServerCredentialsSafeHandle CreateSslCredentials(string[] keyCertPairCertChainArray, string[] keyCertPairPrivateKeyArray)
+        {
+            Preconditions.CheckArgument(keyCertPairCertChainArray.Length == keyCertPairPrivateKeyArray.Length);
+            return grpcsharp_ssl_server_credentials_create(null,
+                                                           keyCertPairCertChainArray, keyCertPairPrivateKeyArray,
+                                                           new UIntPtr((ulong)keyCertPairCertChainArray.Length));
+        }
+
+        protected override bool ReleaseHandle()
+        {
+            grpcsharp_server_credentials_release(handle);
+            return true;
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index de9bbaf..dc4781e 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -53,7 +53,10 @@
         static extern ServerSafeHandle grpcsharp_server_create(CompletionQueueSafeHandle cq, IntPtr args);
 
         [DllImport("grpc_csharp_ext.dll")]
-        static extern Int32 grpcsharp_server_add_http2_port(ServerSafeHandle server, string addr);
+        static extern int grpcsharp_server_add_http2_port(ServerSafeHandle server, string addr);
+
+        [DllImport("grpc_csharp_ext.dll")]
+        static extern int grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds);
 
         [DllImport("grpc_csharp_ext.dll")]
         static extern void grpcsharp_server_start(ServerSafeHandle server);
@@ -74,7 +77,6 @@
 
         public static ServerSafeHandle NewServer(CompletionQueueSafeHandle cq, IntPtr args)
         {
-            // TODO: also grpc_secure_server_create...
             return grpcsharp_server_create(cq, args);
         }
 
@@ -83,6 +85,11 @@
             return grpcsharp_server_add_http2_port(this, addr);
         }
 
+        public int AddPort(string addr, ServerCredentialsSafeHandle credentials)
+        {
+            return grpcsharp_server_add_secure_http2_port(this, addr, credentials);
+        }
+
         public void Start()
         {
             grpcsharp_server_start(this);
diff --git a/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs b/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
index 9873dc9..97b62d0 100644
--- a/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerStreamingOutputObserver.cs
@@ -69,4 +69,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Internal/Timespec.cs b/src/csharp/Grpc.Core/Internal/Timespec.cs
index e6efd66..94d48c2 100644
--- a/src/csharp/Grpc.Core/Internal/Timespec.cs
+++ b/src/csharp/Grpc.Core/Internal/Timespec.cs
@@ -40,8 +40,8 @@
     [StructLayout(LayoutKind.Sequential)]
     internal struct Timespec
     {
-        const int nanosPerSecond = 1000 * 1000 * 1000;
-        const int nanosPerTick = 100;
+        const int NanosPerSecond = 1000 * 1000 * 1000;
+        const int NanosPerTick = 100;
 
         [DllImport("grpc_csharp_ext.dll")]
         static extern Timespec gprsharp_now();
@@ -99,14 +99,13 @@
 
         public Timespec Add(TimeSpan timeSpan)
         {
-            long nanos = tv_nsec.ToInt64() + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * nanosPerTick;
-            long overflow_sec = (nanos > nanosPerSecond) ? 1 : 0;
+            long nanos = tv_nsec.ToInt64() + (timeSpan.Ticks % TimeSpan.TicksPerSecond) * NanosPerTick;
+            long overflow_sec = (nanos > NanosPerSecond) ? 1 : 0;
 
             Timespec result;
-            result.tv_nsec = new IntPtr(nanos % nanosPerSecond);
+            result.tv_nsec = new IntPtr(nanos % NanosPerSecond);
             result.tv_sec = new IntPtr(tv_sec.ToInt64() + (timeSpan.Ticks / TimeSpan.TicksPerSecond) + overflow_sec);
             return result;
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Marshaller.cs b/src/csharp/Grpc.Core/Marshaller.cs
index 602e0eb..e73e7b7 100644
--- a/src/csharp/Grpc.Core/Marshaller.cs
+++ b/src/csharp/Grpc.Core/Marshaller.cs
@@ -40,8 +40,8 @@
     /// </summary>
     public struct Marshaller<T>
     {
-        readonly Func<T,byte[]> serializer;
-        readonly Func<byte[],T> deserializer;
+        readonly Func<T, byte[]> serializer;
+        readonly Func<byte[], T> deserializer;
 
         public Marshaller(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
         {
@@ -66,9 +66,12 @@
         }
     }
 
-    public static class Marshallers {
-
-        public static Marshaller<T> Create<T>(Func<T,byte[]> serializer, Func<byte[],T> deserializer)
+    /// <summary>
+    /// Utilities for creating marshallers.
+    /// </summary>
+    public static class Marshallers
+    {
+        public static Marshaller<T> Create<T>(Func<T, byte[]> serializer, Func<byte[], T> deserializer)
         {
             return new Marshaller<T>(serializer, deserializer);
         }
@@ -81,7 +84,5 @@
                                               System.Text.Encoding.UTF8.GetString);
             }
         }
-
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Method.cs b/src/csharp/Grpc.Core/Method.cs
index c94aa81..4f97eee 100644
--- a/src/csharp/Grpc.Core/Method.cs
+++ b/src/csharp/Grpc.Core/Method.cs
@@ -94,4 +94,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/OperationFailedException.cs b/src/csharp/Grpc.Core/OperationFailedException.cs
index 34a8c95..9b1c24d 100644
--- a/src/csharp/Grpc.Core/OperationFailedException.cs
+++ b/src/csharp/Grpc.Core/OperationFailedException.cs
@@ -45,4 +45,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
index 37ba1e2..168939c 100644
--- a/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Core/Properties/AssemblyInfo.cs
@@ -1,24 +1,14 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-[assembly: AssemblyTitle ("Grpc.Core")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("Google Inc.  All rights reserved.")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion ("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyTitle("Grpc.Core")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.1.*")]
 
 [assembly: InternalsVisibleTo("Grpc.Core.Tests")]
-
diff --git a/src/csharp/Grpc.Core/RpcException.cs b/src/csharp/Grpc.Core/RpcException.cs
index e1cf64c..433d872 100644
--- a/src/csharp/Grpc.Core/RpcException.cs
+++ b/src/csharp/Grpc.Core/RpcException.cs
@@ -35,6 +35,9 @@
 
 namespace Grpc.Core
 {
+    /// <summary>
+    /// Thrown when remote procedure call fails.
+    /// </summary>
     public class RpcException : Exception
     {
         private readonly Status status;
@@ -58,4 +61,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Server.cs b/src/csharp/Grpc.Core/Server.cs
index 152cc21..2439cdb 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -67,18 +67,29 @@
         }
 
         // only call this before Start()
-        public void AddServiceDefinition(ServerServiceDefinition serviceDefinition) {
-            foreach(var entry in serviceDefinition.CallHandlers)
+        public void AddServiceDefinition(ServerServiceDefinition serviceDefinition)
+        {
+            foreach (var entry in serviceDefinition.CallHandlers)
             {
                 callHandlers.Add(entry.Key, entry.Value);
             }
         }
 
         // only call before Start()
-        public int AddPort(string addr) {
+        public int AddPort(string addr)
+        {
             return handle.AddPort(addr);
         }
 
+        // only call before Start()
+        public int AddPort(string addr, ServerCredentials credentials)
+        {
+            using (var nativeCredentials = credentials.ToNativeCredentials())
+            {
+                return handle.AddPort(addr, nativeCredentials);
+            }
+        }
+
         public void Start()
         {
             handle.Start();
@@ -98,7 +109,7 @@
             {
                 var rpcInfo = newRpcQueue.Take();
 
-                //Console.WriteLine("Server received RPC " + rpcInfo.Method);
+                // Console.WriteLine("Server received RPC " + rpcInfo.Method);
 
                 IServerCallHandler callHandler;
                 if (!callHandlers.TryGetValue(rpcInfo.Method, out callHandler))
@@ -107,7 +118,7 @@
                 }
                 callHandler.StartCall(rpcInfo.Method, rpcInfo.Call, GetCompletionQueue());
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Console.WriteLine("Exception while handling RPC: " + e);
             }
@@ -118,7 +129,8 @@
         /// cleans up used resources.
         /// </summary>
         /// <returns>The async.</returns>
-        public async Task ShutdownAsync() {
+        public async Task ShutdownAsync()
+        {
             handle.ShutdownAndNotify(serverShutdownHandler);
             await shutdownTcs.Task;
             handle.Dispose();
@@ -135,11 +147,13 @@
             }
         }
 
-        public void Kill() {
+        public void Kill()
+        {
             handle.Dispose();
         }
 
-        private async Task StartHandlingRpcs() {
+        private async Task StartHandlingRpcs()
+        {
             while (true)
             {
                 await Task.Factory.StartNew(RunRpc);
@@ -151,22 +165,27 @@
             AssertCallOk(handle.RequestCall(GetCompletionQueue(), newServerRpcHandler));
         }
 
-        private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr) {
-            try {
+        private void HandleNewServerRpc(GRPCOpError error, IntPtr batchContextPtr)
+        {
+            try
+            {
                 var ctx = new BatchContextSafeHandleNotOwned(batchContextPtr);
 
-                if (error != GRPCOpError.GRPC_OP_OK) {
+                if (error != GRPCOpError.GRPC_OP_OK)
+                {
                     // TODO: handle error
                 }
 
                 var rpcInfo = new NewRpcInfo(ctx.GetServerRpcNewCall(), ctx.GetServerRpcNewMethod());
 
                 // after server shutdown, the callback returns with null call
-                if (!rpcInfo.Call.IsInvalid) {
+                if (!rpcInfo.Call.IsInvalid)
+                {
                     newRpcQueue.Add(rpcInfo);
                 }
-
-            } catch(Exception e) {
+            }
+            catch (Exception e)
+            {
                 Console.WriteLine("Caught exception in a native handler: " + e);
             }
         }
diff --git a/src/csharp/Grpc.Core/ServerCalls.cs b/src/csharp/Grpc.Core/ServerCalls.cs
index bed7779..dcae994 100644
--- a/src/csharp/Grpc.Core/ServerCalls.cs
+++ b/src/csharp/Grpc.Core/ServerCalls.cs
@@ -32,17 +32,18 @@
 #endregion
 
 using System;
+using Grpc.Core.Internal;
 
 namespace Grpc.Core
 {
     // TODO: perhaps add also serverSideStreaming and clientSideStreaming
 
-    public delegate void UnaryRequestServerMethod<TRequest, TResponse> (TRequest request, IObserver<TResponse> responseObserver);
+    public delegate void UnaryRequestServerMethod<TRequest, TResponse>(TRequest request, IObserver<TResponse> responseObserver);
 
-    public delegate IObserver<TRequest> StreamingRequestServerMethod<TRequest, TResponse> (IObserver<TResponse> responseObserver);
+    public delegate IObserver<TRequest> StreamingRequestServerMethod<TRequest, TResponse>(IObserver<TResponse> responseObserver);
 
-    internal static class ServerCalls {
-
+    internal static class ServerCalls
+    {
         public static IServerCallHandler UnaryRequestCall<TRequest, TResponse>(Method<TRequest, TResponse> method, UnaryRequestServerMethod<TRequest, TResponse> handler)
         {
             return new UnaryRequestServerCallHandler<TRequest, TResponse>(method, handler);
@@ -52,7 +53,5 @@
         {
             return new StreamingRequestServerCallHandler<TRequest, TResponse>(method, handler);
         }
-
     }
 }
-
diff --git a/src/csharp/Grpc.Core/ServerCredentials.cs b/src/csharp/Grpc.Core/ServerCredentials.cs
new file mode 100644
index 0000000..ab7d0b4
--- /dev/null
+++ b/src/csharp/Grpc.Core/ServerCredentials.cs
@@ -0,0 +1,109 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using Grpc.Core.Internal;
+
+namespace Grpc.Core
+{
+    /// <summary>
+    /// Server side credentials.
+    /// </summary>
+    public abstract class ServerCredentials
+    {
+        /// <summary>
+        /// Creates native object for the credentials.
+        /// </summary>
+        /// <returns>The native credentials.</returns>
+        internal abstract ServerCredentialsSafeHandle ToNativeCredentials();
+    }
+
+    /// <summary>
+    /// Key certificate pair (in PEM encoding).
+    /// </summary>
+    public class KeyCertificatePair
+    {
+        readonly string certChain;
+        readonly string privateKey;
+
+        public KeyCertificatePair(string certChain, string privateKey)
+        {
+            this.certChain = certChain;
+            this.privateKey = privateKey;
+        }
+
+        public string CertChain
+        {
+            get
+            {
+                return certChain;
+            }
+        }
+
+        public string PrivateKey
+        {
+            get
+            {
+                return privateKey;
+            }
+        }
+    }
+
+    /// <summary>
+    /// Server-side SSL credentials.
+    /// </summary>
+    public class SslServerCredentials : ServerCredentials
+    {
+        ImmutableList<KeyCertificatePair> keyCertPairs;
+
+        public SslServerCredentials(ImmutableList<KeyCertificatePair> keyCertPairs)
+        {
+            this.keyCertPairs = keyCertPairs;
+        }
+
+        internal override ServerCredentialsSafeHandle ToNativeCredentials()
+        {
+            int count = keyCertPairs.Count;
+            string[] certChains = new string[count];
+            string[] keys = new string[count];
+            for (int i = 0; i < count; i++)
+            {
+                certChains[i] = keyCertPairs[i].CertChain;
+                keys[i] = keyCertPairs[i].PrivateKey;
+            }
+            return ServerCredentialsSafeHandle.CreateSslCredentials(certChains, keys);
+        }
+    }
+}
diff --git a/src/csharp/Grpc.Core/ServerServiceDefinition.cs b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
index 231c376..0044154 100644
--- a/src/csharp/Grpc.Core/ServerServiceDefinition.cs
+++ b/src/csharp/Grpc.Core/ServerServiceDefinition.cs
@@ -33,22 +33,26 @@
 
 using System;
 using System.Collections.Generic;
+using System.Collections.Immutable;
+using Grpc.Core.Internal;
 
 namespace Grpc.Core
 {
+    /// <summary>
+    /// Mapping of method names to server call handlers.
+    /// </summary>
     public class ServerServiceDefinition
     {
         readonly string serviceName;
-        // TODO: we would need an immutable dictionary here...
-        readonly Dictionary<string, IServerCallHandler> callHandlers;
+        readonly ImmutableDictionary<string, IServerCallHandler> callHandlers;
 
-        private ServerServiceDefinition(string serviceName, Dictionary<string, IServerCallHandler> callHandlers)
+        private ServerServiceDefinition(string serviceName, ImmutableDictionary<string, IServerCallHandler> callHandlers)
         {
             this.serviceName = serviceName;
-            this.callHandlers = new Dictionary<string, IServerCallHandler>(callHandlers);
+            this.callHandlers = callHandlers;
         }
 
-        internal Dictionary<string, IServerCallHandler> CallHandlers
+        internal ImmutableDictionary<string, IServerCallHandler> CallHandlers
         {
             get
             {
@@ -56,8 +60,7 @@
             }
         }
 
-
-        public static Builder CreateBuilder(String serviceName)
+        public static Builder CreateBuilder(string serviceName)
         {
             return new Builder(serviceName);
         }
@@ -65,7 +68,7 @@
         public class Builder
         {
             readonly string serviceName;
-            readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<String, IServerCallHandler>();
+            readonly Dictionary<string, IServerCallHandler> callHandlers = new Dictionary<string, IServerCallHandler>();
 
             public Builder(string serviceName)
             {
@@ -90,9 +93,8 @@
 
             public ServerServiceDefinition Build()
             {
-                return new ServerServiceDefinition(serviceName, callHandlers);
+                return new ServerServiceDefinition(serviceName, callHandlers.ToImmutableDictionary());
             }
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/StatusCode.cs b/src/csharp/Grpc.Core/StatusCode.cs
index 1987e52..a9696fa 100644
--- a/src/csharp/Grpc.Core/StatusCode.cs
+++ b/src/csharp/Grpc.Core/StatusCode.cs
@@ -35,9 +35,9 @@
 
 namespace Grpc.Core
 {
-    // TODO: element names should changed to comply with C# naming conventions.
     /// <summary>
-    /// based on grpc_status_code from grpc/status.h
+    /// Result of a remote procedure call.
+    /// Based on grpc_status_code from grpc/status.h
     /// </summary>
     public enum StatusCode
     {
@@ -139,4 +139,3 @@
         DataLoss = 15
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
index 3f0dae8..4180d98 100644
--- a/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
+++ b/src/csharp/Grpc.Core/Utils/BenchmarkUtil.cs
@@ -32,10 +32,10 @@
 #endregion
 
 using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
 using System.Collections.Concurrent;
+using System.Collections.Generic;
 using System.Diagnostics;
+using System.Threading.Tasks;
 
 namespace Grpc.Core.Utils
 {
@@ -61,8 +61,7 @@
             }
             stopwatch.Stop();
             Console.WriteLine("Elapsed time: " + stopwatch.ElapsedMilliseconds + "ms");
-            Console.WriteLine("Ops per second: " + (int) ((double) benchmarkIterations  * 1000 / stopwatch.ElapsedMilliseconds));
+            Console.WriteLine("Ops per second: " + (int)((double)benchmarkIterations  * 1000 / stopwatch.ElapsedMilliseconds));
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
index 18702e1..c4d6bee 100644
--- a/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
+++ b/src/csharp/Grpc.Core/Utils/ExceptionHelper.cs
@@ -42,7 +42,8 @@
         /// Otherwise, rethrows the original aggregate exception.
         /// Always throws, the exception return type is here only to make the.
         /// </summary>
-        public static Exception UnwrapRpcException(AggregateException ae) {
+        public static Exception UnwrapRpcException(AggregateException ae)
+        {
             foreach (var e in ae.InnerExceptions)
             {
                 if (e is RpcException)
@@ -54,4 +55,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Utils/Preconditions.cs b/src/csharp/Grpc.Core/Utils/Preconditions.cs
index b17ce42..aeb5d21 100644
--- a/src/csharp/Grpc.Core/Utils/Preconditions.cs
+++ b/src/csharp/Grpc.Core/Utils/Preconditions.cs
@@ -32,10 +32,10 @@
 #endregion
 
 using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
 using System.Collections.Concurrent;
+using System.Collections.Generic;
 using System.Diagnostics;
+using System.Threading.Tasks;
 
 namespace Grpc.Core.Utils
 {
@@ -66,7 +66,7 @@
         /// <summary>
         /// Throws NullReferenceException if reference is null.
         /// </summary>
-        public static T CheckNotNull<T> (T reference)
+        public static T CheckNotNull<T>(T reference)
         {
             if (reference == null)
             {
@@ -78,7 +78,7 @@
         /// <summary>
         /// Throws NullReferenceException with given message if reference is null.
         /// </summary>
-        public static T CheckNotNull<T> (T reference, string errorMessage)
+        public static T CheckNotNull<T>(T reference, string errorMessage)
         {
             if (reference == null)
             {
@@ -110,4 +110,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Utils/RecordingObserver.cs b/src/csharp/Grpc.Core/Utils/RecordingObserver.cs
index 99d2725..7b43ab8 100644
--- a/src/csharp/Grpc.Core/Utils/RecordingObserver.cs
+++ b/src/csharp/Grpc.Core/Utils/RecordingObserver.cs
@@ -57,9 +57,9 @@
             data.Add(value);
         }
 
-        public Task<List<T>> ToList() {
+        public Task<List<T>> ToList()
+        {
             return tcs.Task;
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/Utils/RecordingQueue.cs b/src/csharp/Grpc.Core/Utils/RecordingQueue.cs
index 63992da..9749168 100644
--- a/src/csharp/Grpc.Core/Utils/RecordingQueue.cs
+++ b/src/csharp/Grpc.Core/Utils/RecordingQueue.cs
@@ -32,9 +32,9 @@
 #endregion
 
 using System;
-using System.Threading.Tasks;
-using System.Collections.Generic;
 using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Threading.Tasks;
 
 namespace Grpc.Core.Utils
 {
@@ -81,4 +81,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Core/packages.config b/src/csharp/Grpc.Core/packages.config
new file mode 100644
index 0000000..cf711ac
--- /dev/null
+++ b/src/csharp/Grpc.Core/packages.config
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
+</packages>
\ No newline at end of file
diff --git a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
index bdd7189..11fc099 100644
--- a/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.MathClient/Properties/AssemblyInfo.cs
@@ -1,22 +1,12 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-[assembly: AssemblyTitle ("Grpc.Examples.MathClient")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("Google Inc.  All rights reserved.")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion ("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
+[assembly: AssemblyTitle("Grpc.Examples.MathClient")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.1.*")]
diff --git a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
index 767340d..c86da65 100644
--- a/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
+++ b/src/csharp/Grpc.Examples.Tests/MathClientServerTests.cs
@@ -105,7 +105,7 @@
             var recorder = new RecordingObserver<Num>();
             client.Fib(new FibArgs.Builder { Limit = 6 }.Build(), recorder);
 
-            CollectionAssert.AreEqual(new List<long>{1, 1, 2, 3, 5, 8},
+            CollectionAssert.AreEqual(new List<long> { 1, 1, 2, 3, 5, 8 },
                 recorder.ToList().Result.ConvertAll((n) => n.Num_));
         }
 
@@ -114,7 +114,8 @@
         public void Sum()
         {
             var res = client.Sum();
-            foreach (var num in new long[] { 10, 20, 30 }) {
+            foreach (var num in new long[] { 10, 20, 30 })
+            {
                 res.Inputs.OnNext(Num.CreateBuilder().SetNum_(num).Build());
             }
             res.Inputs.OnCompleted();
@@ -125,7 +126,8 @@
         [Test]
         public void DivMany()
         {
-            List<DivArgs> divArgsList = new List<DivArgs>{
+            List<DivArgs> divArgsList = new List<DivArgs>
+            {
                 new DivArgs.Builder { Dividend = 10, Divisor = 3 }.Build(),
                 new DivArgs.Builder { Dividend = 100, Divisor = 21 }.Build(),
                 new DivArgs.Builder { Dividend = 7, Divisor = 2 }.Build()
@@ -142,9 +144,8 @@
 
             var result = recorder.ToList().Result;
 
-            CollectionAssert.AreEqual(new long[] {3, 4, 3}, result.ConvertAll((divReply) => divReply.Quotient));
-            CollectionAssert.AreEqual(new long[] {1, 16, 1}, result.ConvertAll((divReply) => divReply.Remainder));
+            CollectionAssert.AreEqual(new long[] { 3, 4, 3 }, result.ConvertAll((divReply) => divReply.Quotient));
+            CollectionAssert.AreEqual(new long[] { 1, 16, 1 }, result.ConvertAll((divReply) => divReply.Remainder));
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
index 44b075a..43c7616 100644
--- a/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples.Tests/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
 [assembly: AssemblyTitle("Grpc.Examples.Tests")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@
 [assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 [assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.Examples/MathExamples.cs b/src/csharp/Grpc.Examples/MathExamples.cs
index 134270f..b8bb7ea 100644
--- a/src/csharp/Grpc.Examples/MathExamples.cs
+++ b/src/csharp/Grpc.Examples/MathExamples.cs
@@ -71,7 +71,8 @@
         public static void SumExample(MathGrpc.IMathServiceClient stub)
         {
             List<Num> numbers = new List<Num>
-            {new Num.Builder { Num_ = 1 }.Build(),
+            {
+                new Num.Builder { Num_ = 1 }.Build(),
                 new Num.Builder { Num_ = 2 }.Build(),
                 new Num.Builder { Num_ = 3 }.Build()
             };
@@ -110,24 +111,12 @@
         public static void DependendRequestsExample(MathGrpc.IMathServiceClient stub)
         {
             var numberList = new List<Num>
-            { new Num.Builder{ Num_ = 1 }.Build(),
-                new Num.Builder{ Num_ = 2 }.Build(), new Num.Builder{ Num_ = 3 }.Build()
+            {
+                new Num.Builder { Num_ = 1 }.Build(),
+                new Num.Builder { Num_ = 2 }.Build(), new Num.Builder { Num_ = 3 }.Build()
             };
 
             numberList.ToObservable();
-
-            //IObserver<Num> numbers;
-            //Task<Num> call = stub.Sum(out numbers);
-            //foreach (var num in numberList)
-            //{
-            //  numbers.OnNext(num);
-            //}
-            //numbers.OnCompleted();
-
-            //Num sum = call.Result;
-
-            //DivReply result = stub.Div(new DivArgs.Builder { Dividend = sum.Num_, Divisor = numberList.Count }.Build());
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Examples/MathGrpc.cs b/src/csharp/Grpc.Examples/MathGrpc.cs
index f938a24..33a9ca9 100644
--- a/src/csharp/Grpc.Examples/MathGrpc.cs
+++ b/src/csharp/Grpc.Examples/MathGrpc.cs
@@ -45,35 +45,34 @@
     /// </summary>
     public class MathGrpc
     {
-        readonly static Marshaller<DivArgs> divArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
-        readonly static Marshaller<DivReply> divReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
-        readonly static Marshaller<Num> numMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
-        readonly static Marshaller<FibArgs> fibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
+        static readonly Marshaller<DivArgs> DivArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivArgs.ParseFrom);
+        static readonly Marshaller<DivReply> DivReplyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), DivReply.ParseFrom);
+        static readonly Marshaller<Num> NumMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Num.ParseFrom);
+        static readonly Marshaller<FibArgs> FibArgsMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), FibArgs.ParseFrom);
 
-        readonly static Method<DivArgs, DivReply> divMethod = new Method<DivArgs, DivReply>(
+        static readonly Method<DivArgs, DivReply> DivMethod = new Method<DivArgs, DivReply>(
             MethodType.Unary,
             "/math.Math/Div",
-            divArgsMarshaller,
-            divReplyMarshaller
-        );
-        readonly static Method<FibArgs, Num> fibMethod = new Method<FibArgs, Num>(
+            DivArgsMarshaller,
+            DivReplyMarshaller);
+
+        static readonly Method<FibArgs, Num> FibMethod = new Method<FibArgs, Num>(
             MethodType.ServerStreaming,
             "/math.Math/Fib",
-            fibArgsMarshaller,
-            numMarshaller
-        );
-        readonly static Method<Num, Num> sumMethod = new Method<Num, Num>(
+            FibArgsMarshaller,
+            NumMarshaller);
+
+        static readonly Method<Num, Num> SumMethod = new Method<Num, Num>(
             MethodType.ClientStreaming,
             "/math.Math/Sum",
-            numMarshaller,
-            numMarshaller
-        );
-        readonly static Method<DivArgs, DivReply> divManyMethod = new Method<DivArgs, DivReply>(
+            NumMarshaller,
+            NumMarshaller);
+
+        static readonly Method<DivArgs, DivReply> DivManyMethod = new Method<DivArgs, DivReply>(
             MethodType.DuplexStreaming,
             "/math.Math/DivMany",
-            divArgsMarshaller,
-            divReplyMarshaller
-        );
+            DivArgsMarshaller,
+            DivReplyMarshaller);
 
         public interface IMathServiceClient
         {
@@ -99,31 +98,31 @@
 
             public DivReply Div(DivArgs request, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<DivArgs, DivReply>(divMethod, channel);
+                var call = new Grpc.Core.Call<DivArgs, DivReply>(DivMethod, channel);
                 return Calls.BlockingUnaryCall(call, request, token);
             }
 
             public Task<DivReply> DivAsync(DivArgs request, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<DivArgs, DivReply>(divMethod, channel);
+                var call = new Grpc.Core.Call<DivArgs, DivReply>(DivMethod, channel);
                 return Calls.AsyncUnaryCall(call, request, token);
             }
 
             public void Fib(FibArgs request, IObserver<Num> responseObserver, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<FibArgs, Num>(fibMethod, channel);
+                var call = new Grpc.Core.Call<FibArgs, Num>(FibMethod, channel);
                 Calls.AsyncServerStreamingCall(call, request, responseObserver, token);
             }
 
             public ClientStreamingAsyncResult<Num, Num> Sum(CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<Num, Num>(sumMethod, channel);
+                var call = new Grpc.Core.Call<Num, Num>(SumMethod, channel);
                 return Calls.AsyncClientStreamingCall(call, token);
             }
 
             public IObserver<DivArgs> DivMany(IObserver<DivReply> responseObserver, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<DivArgs, DivReply>(divManyMethod, channel);
+                var call = new Grpc.Core.Call<DivArgs, DivReply>(DivManyMethod, channel);
                 return Calls.DuplexStreamingCall(call, responseObserver, token);
             }
         }
@@ -143,10 +142,10 @@
         public static ServerServiceDefinition BindService(IMathService serviceImpl)
         {
             return ServerServiceDefinition.CreateBuilder("/math.Math/")
-                .AddMethod(divMethod, serviceImpl.Div)
-                .AddMethod(fibMethod, serviceImpl.Fib)
-                .AddMethod(sumMethod, serviceImpl.Sum)
-                .AddMethod(divManyMethod, serviceImpl.DivMany).Build();
+                .AddMethod(DivMethod, serviceImpl.Div)
+                .AddMethod(FibMethod, serviceImpl.Fib)
+                .AddMethod(SumMethod, serviceImpl.Sum)
+                .AddMethod(DivManyMethod, serviceImpl.DivMany).Build();
         }
 
         public static IMathServiceClient NewStub(Channel channel)
diff --git a/src/csharp/Grpc.Examples/MathServiceImpl.cs b/src/csharp/Grpc.Examples/MathServiceImpl.cs
index 76a08ce..0b2357e 100644
--- a/src/csharp/Grpc.Examples/MathServiceImpl.cs
+++ b/src/csharp/Grpc.Examples/MathServiceImpl.cs
@@ -73,8 +73,8 @@
         public IObserver<Num> Sum(IObserver<Num> responseObserver)
         {
             var recorder = new RecordingObserver<Num>();
-            Task.Factory.StartNew(() => {
-
+            Task.Factory.StartNew(() =>
+            {
                 List<Num> inputs = recorder.ToList().Result;
 
                 long sum = 0;
@@ -104,7 +104,7 @@
         static IEnumerable<Num> FibInternal(long n)
         {
             long a = 1;
-            yield return new Num.Builder { Num_=a }.Build();
+            yield return new Num.Builder { Num_ = a }.Build();
 
             long b = 1;
             for (long i = 0; i < n - 1; i++)
@@ -112,12 +112,12 @@
                 long temp = a;
                 a = b;
                 b = temp + b;
-                yield return new Num.Builder { Num_=a }.Build();
+                yield return new Num.Builder { Num_ = a }.Build();
             }
         }
 
-        private class DivObserver : IObserver<DivArgs> {
-
+        private class DivObserver : IObserver<DivArgs>
+        {
             readonly IObserver<DivReply> responseObserver;
 
             public DivObserver(IObserver<DivReply> responseObserver)
@@ -142,4 +142,3 @@
         }
     }
 }
-
diff --git a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
index 7603db7..b55d241 100644
--- a/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.Examples/Properties/AssemblyInfo.cs
@@ -1,22 +1,12 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
-[assembly: AssemblyTitle ("Grpc.Examples")]
-[assembly: AssemblyDescription ("")]
-[assembly: AssemblyConfiguration ("")]
-[assembly: AssemblyCompany ("")]
-[assembly: AssemblyProduct ("")]
-[assembly: AssemblyCopyright ("Google Inc.  All rights reserved.")]
-[assembly: AssemblyTrademark ("")]
-[assembly: AssemblyCulture ("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
-[assembly: AssemblyVersion ("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
+[assembly: AssemblyTitle("Grpc.Examples")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: AssemblyVersion("0.1.*")]
diff --git a/src/csharp/Grpc.Examples/Settings.StyleCop b/src/csharp/Grpc.Examples/Settings.StyleCop
new file mode 100644
index 0000000..e9b6e71
--- /dev/null
+++ b/src/csharp/Grpc.Examples/Settings.StyleCop
@@ -0,0 +1,10 @@
+<StyleCopSettings Version="105">
+  <SourceFileList>
+    <SourceFile>Math.cs</SourceFile>
+    <Settings>
+    <GlobalSettings>
+      <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
+    </GlobalSettings>
+    </Settings>
+  </SourceFileList>
+</StyleCopSettings>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
index d1f9e85..c93dd1e 100644
--- a/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting.Client/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes. 
-// Change them to the values specific to your project.
 [assembly: AssemblyTitle("Grpc.IntegrationTesting.Client")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@
 [assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 [assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly, 
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
index 4ef93f3..f3def1a 100644
--- a/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting.Server/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes. 
-// Change them to the values specific to your project.
 [assembly: AssemblyTitle("Grpc.IntegrationTesting.Server")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@
 [assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 [assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly, 
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
index 8f7a17e..cfb2587 100644
--- a/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
+++ b/src/csharp/Grpc.IntegrationTesting/Grpc.IntegrationTesting.csproj
@@ -39,6 +39,10 @@
     <Reference Include="Google.ProtocolBuffers">
       <HintPath>..\packages\Google.ProtocolBuffers.2.4.1.521\lib\net40\Google.ProtocolBuffers.dll</HintPath>
     </Reference>
+    <Reference Include="System.Collections.Immutable, Version=1.1.34.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>..\packages\System.Collections.Immutable.1.1.34-rc\lib\portable-net45+win8+wp8+wpa81\System.Collections.Immutable.dll</HintPath>
+    </Reference>
   </ItemGroup>
   <ItemGroup>
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -49,6 +53,7 @@
     <Compile Include="TestServiceImpl.cs" />
     <Compile Include="InteropServer.cs" />
     <Compile Include="InteropClient.cs" />
+    <Compile Include="TestCredentials.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ItemGroup>
@@ -75,8 +80,5 @@
       <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
     </None>
   </ItemGroup>
-  <ItemGroup>
-    <Folder Include="proto\" />
-    <Folder Include="data\" />
-  </ItemGroup>
-</Project>
+  <ItemGroup />
+</Project>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
index 30301f1..6b92d3c 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClient.cs
@@ -38,10 +38,10 @@
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using Google.ProtocolBuffers;
+using grpc.testing;
 using Grpc.Core;
 using Grpc.Core.Utils;
 using NUnit.Framework;
-using grpc.testing;
 
 namespace Grpc.IntegrationTesting
 {
@@ -50,8 +50,8 @@
         private class ClientOptions
         {
             public bool help;
-            public string serverHost= "127.0.0.1";
-            public string serverHostOverride = "foo.test.google.fr";
+            public string serverHost = "127.0.0.1";
+            public string serverHostOverride = TestCredentials.DefaultHostOverride;
             public int? serverPort;
             public string testCase = "large_unary";
             public bool useTls;
@@ -103,22 +103,13 @@
             Credentials credentials = null;
             if (options.useTls)
             {
-                string caPath = "data/ca.pem";  // Default testing CA
-                if (!options.useTestCa)
-                {
-                    caPath = Environment.GetEnvironmentVariable("SSL_CERT_FILE");
-                    if (string.IsNullOrEmpty(caPath))
-                    {
-                        throw new ArgumentException("CA path environment variable is not set.");
-                    }
-                }
-                credentials = new SslCredentials(File.ReadAllText(caPath));
+                credentials = TestCredentials.CreateTestClientCredentials(options.useTestCa);
             }
 
             ChannelArgs channelArgs = null;
             if (!string.IsNullOrEmpty(options.serverHostOverride))
             {
-                channelArgs = ChannelArgs.NewBuilder()
+                channelArgs = ChannelArgs.CreateBuilder()
                     .AddString(ChannelArgs.SslTargetNameOverrideKey, options.serverHostOverride).Build();
             }
 
@@ -189,7 +180,7 @@
         {
             Console.WriteLine("running client_streaming");
 
-            var bodySizes = new List<int>{27182, 8, 1828, 45904};
+            var bodySizes = new List<int> { 27182, 8, 1828, 45904 };
 
             var context = client.StreamingInputCall();
             foreach (var size in bodySizes)
@@ -208,7 +199,7 @@
         {
             Console.WriteLine("running server_streaming");
 
-            var bodySizes = new List<int>{31415, 9, 2653, 58979};
+            var bodySizes = new List<int> { 31415, 9, 2653, 58979 };
 
             var request = StreamingOutputCallRequest.CreateBuilder()
                 .SetResponseType(PayloadType.COMPRESSABLE)
@@ -265,7 +256,6 @@
             Assert.AreEqual(PayloadType.COMPRESSABLE, response.Payload.Type);
             Assert.AreEqual(2653, response.Payload.Body.Length);
 
-
             inputs.OnNext(StreamingOutputCallRequest.CreateBuilder()
                           .SetResponseType(PayloadType.COMPRESSABLE)
                           .AddResponseParameters(ResponseParameters.CreateBuilder().SetSize(58979))
@@ -301,17 +291,18 @@
         public static void RunBenchmarkEmptyUnary(TestServiceGrpc.ITestServiceClient client)
         {
             BenchmarkUtil.RunBenchmark(10000, 10000,
-                                       () => { client.EmptyCall(Empty.DefaultInstance);});
+                                       () => { client.EmptyCall(Empty.DefaultInstance); });
         }
 
-        private static Payload CreateZerosPayload(int size) {
+        private static Payload CreateZerosPayload(int size)
+        {
             return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build();
         }
 
         private static ClientOptions ParseArguments(string[] args)
         {
             var options = new ClientOptions();
-            foreach(string arg in args)
+            foreach (string arg in args)
             {
                 ParseArgument(arg, options);
                 if (options.help)
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
index 4bb0b9e..814f631 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropClientServerTest.cs
@@ -35,10 +35,10 @@
 using System.Collections.Generic;
 using System.Threading;
 using System.Threading.Tasks;
+using grpc.testing;
 using Grpc.Core;
 using Grpc.Core.Utils;
 using NUnit.Framework;
-using grpc.testing;
 
 namespace Grpc.IntegrationTesting
 {
@@ -59,9 +59,13 @@
 
             server = new Server();
             server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
-            int port = server.AddPort(host + ":0");
+            int port = server.AddPort(host + ":0", TestCredentials.CreateTestServerCredentials());
             server.Start();
-            channel = new Channel(host + ":" + port);
+
+            var channelArgs = ChannelArgs.CreateBuilder()
+                .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build();
+
+            channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs);
             client = TestServiceGrpc.NewStub(channel);
         }
 
@@ -113,7 +117,5 @@
         // TODO: add cancel_after_begin
 
         // TODO: add cancel_after_first_response
-
     }
 }
-
diff --git a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
index a25d3b3..5e58028 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
@@ -34,13 +34,14 @@
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.IO;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 using Google.ProtocolBuffers;
+using grpc.testing;
 using Grpc.Core;
 using Grpc.Core.Utils;
 using NUnit.Framework;
-using grpc.testing;
 
 namespace Grpc.IntegrationTesting
 {
@@ -49,7 +50,7 @@
         private class ServerOptions
         {
             public bool help;
-            public int? port;
+            public int? port = 8070;
             public bool useTls;
         }
 
@@ -93,7 +94,14 @@
             server.AddServiceDefinition(TestServiceGrpc.BindService(new TestServiceImpl()));
 
             string addr = "0.0.0.0:" + options.port;
-            server.AddPort(addr);
+            if (options.useTls)
+            {
+                server.AddPort(addr, TestCredentials.CreateTestServerCredentials());
+            }
+            else
+            {
+                server.AddPort(addr);
+            }
             Console.WriteLine("Running server on " + addr);
             server.Start();
 
@@ -105,7 +113,7 @@
         private static ServerOptions ParseArguments(string[] args)
         {
             var options = new ServerOptions();
-            foreach(string arg in args)
+            foreach (string arg in args)
             {
                 ParseArgument(arg, options);
                 if (options.help)
diff --git a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
index f633c19..f09a448 100644
--- a/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
+++ b/src/csharp/Grpc.IntegrationTesting/Properties/AssemblyInfo.cs
@@ -1,8 +1,6 @@
 using System.Reflection;
 using System.Runtime.CompilerServices;
 
-// Information about this assembly is defined by the following attributes.
-// Change them to the values specific to your project.
 [assembly: AssemblyTitle("Grpc.IntegrationTesting")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
@@ -11,12 +9,4 @@
 [assembly: AssemblyCopyright("Google Inc.  All rights reserved.")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
-// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
-// The form "{Major}.{Minor}.*" will automatically update the build and revision,
-// and "{Major}.{Minor}.{Build}.*" will update just the revision.
 [assembly: AssemblyVersion("0.1.*")]
-// The following attributes are used to specify the signing key for the assembly,
-// if desired. See the Mono documentation for more information about signing.
-//[assembly: AssemblyDelaySign(false)]
-//[assembly: AssemblyKeyFile("")]
-
diff --git a/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
new file mode 100644
index 0000000..fb99cd4
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/Settings.StyleCop
@@ -0,0 +1,11 @@
+<StyleCopSettings Version="105">
+  <SourceFileList>
+    <SourceFile>Messages.cs</SourceFile>
+    <SourceFile>Empty.cs</SourceFile>
+    <Settings>
+    <GlobalSettings>
+      <BooleanProperty Name="RulesEnabledByDefault">False</BooleanProperty>
+    </GlobalSettings>
+    </Settings>
+  </SourceFileList>
+</StyleCopSettings>
\ No newline at end of file
diff --git a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
new file mode 100644
index 0000000..401c50b
--- /dev/null
+++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
@@ -0,0 +1,84 @@
+#region Copyright notice and license
+
+// 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.
+
+#endregion
+
+using System;
+using System.Collections.Generic;
+using System.Collections.Immutable;
+using System.Diagnostics;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+using Google.ProtocolBuffers;
+using grpc.testing;
+using Grpc.Core;
+using Grpc.Core.Utils;
+using NUnit.Framework;
+
+namespace Grpc.IntegrationTesting
+{
+    /// <summary>
+    /// SSL Credentials for testing.
+    /// </summary>
+    public static class TestCredentials
+    {
+        public const string DefaultHostOverride = "foo.test.google.fr";
+
+        public const string ClientCertAuthorityPath = "data/ca.pem";
+        public const string ClientCertAuthorityEnvName = "SSL_CERT_FILE";
+
+        public const string ServerCertChainPath = "data/server1.pem";
+        public const string ServerPrivateKeyPath = "data/server1.key";
+
+        public static SslCredentials CreateTestClientCredentials(bool useTestCa)
+        {
+            string caPath = ClientCertAuthorityPath;
+            if (!useTestCa)
+            {
+                caPath = Environment.GetEnvironmentVariable(ClientCertAuthorityEnvName);
+                if (string.IsNullOrEmpty(caPath))
+                {
+                    throw new ArgumentException("CA path environment variable is not set.");
+                }
+            }
+            return new SslCredentials(File.ReadAllText(caPath));
+        }
+
+        public static SslServerCredentials CreateTestServerCredentials()
+        {
+            var keyCertPair = new KeyCertificatePair(
+                File.ReadAllText(ServerCertChainPath),
+                File.ReadAllText(ServerPrivateKeyPath));
+            return new SslServerCredentials(ImmutableList.Create(keyCertPair));
+        }
+    }
+}
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
index b71704b..9b0251c 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceGrpc.cs
@@ -44,50 +44,49 @@
     /// </summary>
     public class TestServiceGrpc
     {
-        readonly static Marshaller<Empty> emptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
-        readonly static Marshaller<SimpleRequest> simpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
-        readonly static Marshaller<SimpleResponse> simpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
-        readonly static Marshaller<StreamingOutputCallRequest> streamingOutputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
-        readonly static Marshaller<StreamingOutputCallResponse> streamingOutputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
-        readonly static Marshaller<StreamingInputCallRequest> streamingInputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
-        readonly static Marshaller<StreamingInputCallResponse> streamingInputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
+        static readonly Marshaller<Empty> EmptyMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), Empty.ParseFrom);
+        static readonly Marshaller<SimpleRequest> SimpleRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleRequest.ParseFrom);
+        static readonly Marshaller<SimpleResponse> SimpleResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), SimpleResponse.ParseFrom);
+        static readonly Marshaller<StreamingOutputCallRequest> StreamingOutputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallRequest.ParseFrom);
+        static readonly Marshaller<StreamingOutputCallResponse> StreamingOutputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingOutputCallResponse.ParseFrom);
+        static readonly Marshaller<StreamingInputCallRequest> StreamingInputCallRequestMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallRequest.ParseFrom);
+        static readonly Marshaller<StreamingInputCallResponse> StreamingInputCallResponseMarshaller = Marshallers.Create((arg) => arg.ToByteArray(), StreamingInputCallResponse.ParseFrom);
 
-        readonly static Method<Empty, Empty> emptyCallMethod = new Method<Empty, Empty>(
+        static readonly Method<Empty, Empty> EmptyCallMethod = new Method<Empty, Empty>(
             MethodType.Unary,
             "/grpc.testing.TestService/EmptyCall",
-            emptyMarshaller,
-            emptyMarshaller
-        );
-        readonly static Method<SimpleRequest, SimpleResponse> unaryCallMethod = new Method<SimpleRequest, SimpleResponse>(
+            EmptyMarshaller,
+            EmptyMarshaller);
+
+        static readonly Method<SimpleRequest, SimpleResponse> UnaryCallMethod = new Method<SimpleRequest, SimpleResponse>(
             MethodType.Unary,
             "/grpc.testing.TestService/UnaryCall",
-            simpleRequestMarshaller,
-            simpleResponseMarshaller
-        );
-        readonly static Method<StreamingOutputCallRequest, StreamingOutputCallResponse> streamingOutputCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
+            SimpleRequestMarshaller,
+            SimpleResponseMarshaller);
+
+        static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> StreamingOutputCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
             MethodType.ServerStreaming,
             "/grpc.testing.TestService/StreamingOutputCall",
-            streamingOutputCallRequestMarshaller,
-            streamingOutputCallResponseMarshaller
-            );
-        readonly static Method<StreamingInputCallRequest, StreamingInputCallResponse> streamingInputCallMethod = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
+            StreamingOutputCallRequestMarshaller,
+            StreamingOutputCallResponseMarshaller);
+
+        static readonly Method<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCallMethod = new Method<StreamingInputCallRequest, StreamingInputCallResponse>(
             MethodType.ClientStreaming,
             "/grpc.testing.TestService/StreamingInputCall",
-            streamingInputCallRequestMarshaller,
-            streamingInputCallResponseMarshaller
-            );
-        readonly static Method<StreamingOutputCallRequest, StreamingOutputCallResponse> fullDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
+            StreamingInputCallRequestMarshaller,
+            StreamingInputCallResponseMarshaller);
+
+        static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> FullDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
             MethodType.DuplexStreaming,
             "/grpc.testing.TestService/FullDuplexCall",
-            streamingOutputCallRequestMarshaller,
-            streamingOutputCallResponseMarshaller
-            );
-        readonly static Method<StreamingOutputCallRequest, StreamingOutputCallResponse> halfDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
+            StreamingOutputCallRequestMarshaller,
+            StreamingOutputCallResponseMarshaller);
+
+        static readonly Method<StreamingOutputCallRequest, StreamingOutputCallResponse> HalfDuplexCallMethod = new Method<StreamingOutputCallRequest, StreamingOutputCallResponse>(
             MethodType.DuplexStreaming,
             "/grpc.testing.TestService/HalfDuplexCall",
-            streamingOutputCallRequestMarshaller,
-            streamingOutputCallResponseMarshaller
-            );
+            StreamingOutputCallRequestMarshaller,
+            StreamingOutputCallResponseMarshaller);
 
         public interface ITestServiceClient
         {
@@ -119,49 +118,49 @@
 
             public Empty EmptyCall(Empty request, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<Empty, Empty>(emptyCallMethod, channel);
+                var call = new Grpc.Core.Call<Empty, Empty>(EmptyCallMethod, channel);
                 return Calls.BlockingUnaryCall(call, request, token);
             }
 
             public Task<Empty> EmptyCallAsync(Empty request, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<Empty, Empty>(emptyCallMethod, channel);
+                var call = new Grpc.Core.Call<Empty, Empty>(EmptyCallMethod, channel);
                 return Calls.AsyncUnaryCall(call, request, token);
             }
 
             public SimpleResponse UnaryCall(SimpleRequest request, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(unaryCallMethod, channel);
+                var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(UnaryCallMethod, channel);
                 return Calls.BlockingUnaryCall(call, request, token);
             }
 
             public Task<SimpleResponse> UnaryCallAsync(SimpleRequest request, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(unaryCallMethod, channel);
+                var call = new Grpc.Core.Call<SimpleRequest, SimpleResponse>(UnaryCallMethod, channel);
                 return Calls.AsyncUnaryCall(call, request, token);
             }
 
-            public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken)) {
-                var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(streamingOutputCallMethod, channel);
+            public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
+            {
+                var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(StreamingOutputCallMethod, channel);
                 Calls.AsyncServerStreamingCall(call, request, responseObserver, token);
             }
 
             public ClientStreamingAsyncResult<StreamingInputCallRequest, StreamingInputCallResponse> StreamingInputCall(CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<StreamingInputCallRequest, StreamingInputCallResponse>(streamingInputCallMethod, channel);
+                var call = new Grpc.Core.Call<StreamingInputCallRequest, StreamingInputCallResponse>(StreamingInputCallMethod, channel);
                 return Calls.AsyncClientStreamingCall(call, token);
             }
 
             public IObserver<StreamingOutputCallRequest> FullDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(fullDuplexCallMethod, channel);
+                var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(FullDuplexCallMethod, channel);
                 return Calls.DuplexStreamingCall(call, responseObserver, token);
             }
 
-
             public IObserver<StreamingOutputCallRequest> HalfDuplexCall(IObserver<StreamingOutputCallResponse> responseObserver, CancellationToken token = default(CancellationToken))
             {
-                var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(halfDuplexCallMethod, channel);
+                var call = new Grpc.Core.Call<StreamingOutputCallRequest, StreamingOutputCallResponse>(HalfDuplexCallMethod, channel);
                 return Calls.DuplexStreamingCall(call, responseObserver, token);
             }
         }
@@ -185,12 +184,12 @@
         public static ServerServiceDefinition BindService(ITestService serviceImpl)
         {
             return ServerServiceDefinition.CreateBuilder("/grpc.testing.TestService/")
-                .AddMethod(emptyCallMethod, serviceImpl.EmptyCall)
-                .AddMethod(unaryCallMethod, serviceImpl.UnaryCall)
-                .AddMethod(streamingOutputCallMethod, serviceImpl.StreamingOutputCall)
-                .AddMethod(streamingInputCallMethod, serviceImpl.StreamingInputCall)
-                .AddMethod(fullDuplexCallMethod, serviceImpl.FullDuplexCall)
-                .AddMethod(halfDuplexCallMethod, serviceImpl.HalfDuplexCall)
+                .AddMethod(EmptyCallMethod, serviceImpl.EmptyCall)
+                .AddMethod(UnaryCallMethod, serviceImpl.UnaryCall)
+                .AddMethod(StreamingOutputCallMethod, serviceImpl.StreamingOutputCall)
+                .AddMethod(StreamingInputCallMethod, serviceImpl.StreamingInputCall)
+                .AddMethod(FullDuplexCallMethod, serviceImpl.FullDuplexCall)
+                .AddMethod(HalfDuplexCallMethod, serviceImpl.HalfDuplexCall)
                 .Build();
         }
 
diff --git a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
index 176843b..661b31b 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestServiceImpl.cs
@@ -55,14 +55,14 @@
         {
             var response = SimpleResponse.CreateBuilder()
                 .SetPayload(CreateZerosPayload(request.ResponseSize)).Build();
-            //TODO: check we support ReponseType
+            // TODO: check we support ReponseType
             responseObserver.OnNext(response);
             responseObserver.OnCompleted();
         }
 
         public void StreamingOutputCall(StreamingOutputCallRequest request, IObserver<StreamingOutputCallResponse> responseObserver)
         {
-            foreach(var responseParam in request.ResponseParametersList)
+            foreach (var responseParam in request.ResponseParametersList)
             {
                 var response = StreamingOutputCallResponse.CreateBuilder()
                     .SetPayload(CreateZerosPayload(responseParam.Size)).Build();
@@ -74,9 +74,10 @@
         public IObserver<StreamingInputCallRequest> StreamingInputCall(IObserver<StreamingInputCallResponse> responseObserver)
         {
             var recorder = new RecordingObserver<StreamingInputCallRequest>();
-            Task.Run(() => {
+            Task.Run(() =>
+            {
                 int sum = 0;
-                foreach(var req in recorder.ToList().Result)
+                foreach (var req in recorder.ToList().Result)
                 {
                     sum += req.Payload.Body.Length;
                 }
@@ -98,8 +99,8 @@
             throw new NotImplementedException();
         }
 
-        private class FullDuplexObserver : IObserver<StreamingOutputCallRequest> {
-
+        private class FullDuplexObserver : IObserver<StreamingOutputCallRequest>
+        {
             readonly IObserver<StreamingOutputCallResponse> responseObserver;
 
             public FullDuplexObserver(IObserver<StreamingOutputCallResponse> responseObserver)
@@ -119,22 +120,18 @@
 
             public void OnNext(StreamingOutputCallRequest value)
             {
-                // TODO: this is not in order!!!
-                //Task.Factory.StartNew(() => {
-
-                    foreach(var responseParam in value.ResponseParametersList)
-                    {
-                        var response = StreamingOutputCallResponse.CreateBuilder()
-                            .SetPayload(CreateZerosPayload(responseParam.Size)).Build();
-                        responseObserver.OnNext(response);
-                    }
-                //});
+                foreach (var responseParam in value.ResponseParametersList)
+                {
+                    var response = StreamingOutputCallResponse.CreateBuilder()
+                        .SetPayload(CreateZerosPayload(responseParam.Size)).Build();
+                    responseObserver.OnNext(response);
+                }
             }
         }
 
-        private static Payload CreateZerosPayload(int size) {
+        private static Payload CreateZerosPayload(int size)
+        {
             return Payload.CreateBuilder().SetBody(ByteString.CopyFrom(new byte[size])).Build();
         }
     }
 }
-
diff --git a/src/csharp/Grpc.IntegrationTesting/packages.config b/src/csharp/Grpc.IntegrationTesting/packages.config
index 51c17bc..157c264 100644
--- a/src/csharp/Grpc.IntegrationTesting/packages.config
+++ b/src/csharp/Grpc.IntegrationTesting/packages.config
@@ -2,4 +2,5 @@
 <packages>
   <package id="Google.ProtocolBuffers" version="2.4.1.521" targetFramework="net45" />
   <package id="NUnit" version="2.6.4" targetFramework="net45" />
+  <package id="System.Collections.Immutable" version="1.1.34-rc" targetFramework="net45" />
 </packages>
\ No newline at end of file
diff --git a/src/csharp/Settings.StyleCop b/src/csharp/Settings.StyleCop
new file mode 100644
index 0000000..2ecf22f
--- /dev/null
+++ b/src/csharp/Settings.StyleCop
@@ -0,0 +1,509 @@
+<StyleCopSettings Version="105">
+  <Analyzers>
+    <Analyzer AnalyzerId="StyleCop.CSharp.DocumentationRules">
+      <Rules>
+        <Rule Name="ElementsMustBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PartialElementsMustBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="EnumerationItemsMustBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DocumentationMustContainValidXml">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementDocumentationMustHaveSummary">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PartialElementDocumentationMustHaveSummary">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementDocumentationMustHaveSummaryText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PartialElementDocumentationMustHaveSummaryText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementDocumentationMustNotHaveDefaultSummary">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementParametersMustBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementParameterDocumentationMustMatchElementParameters">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementParameterDocumentationMustDeclareParameterName">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementParameterDocumentationMustHaveText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementReturnValueMustBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementReturnValueDocumentationMustHaveText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="VoidReturnValueMustNotBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="GenericTypeParametersMustBeDocumented">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="GenericTypeParametersMustBeDocumentedPartialClass">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="GenericTypeParameterDocumentationMustMatchTypeParameters">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="GenericTypeParameterDocumentationMustDeclareParameterName">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="GenericTypeParameterDocumentationMustHaveText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PropertySummaryDocumentationMustMatchAccessors">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PropertySummaryDocumentationMustOmitSetAccessorWithRestrictedAccess">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementDocumentationMustNotBeCopiedAndPasted">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="SingleLineCommentsMustNotUseDocumentationStyleSlashes">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DocumentationTextMustNotBeEmpty">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DocumentationTextMustContainWhitespace">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DocumentationMustMeetCharacterPercentage">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ConstructorSummaryDocumentationMustBeginWithStandardText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DestructorSummaryDocumentationMustBeginWithStandardText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DocumentationHeadersMustNotContainBlankLines">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="IncludedDocumentationXPathDoesNotExist">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="IncludeNodeDoesNotContainValidFileAndPath">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="InheritDocMustBeUsedWithInheritingClass">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementDocumentationMustBeSpelledCorrectly">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileMustHaveHeader">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileHeaderMustShowCopyright">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileHeaderMustHaveCopyrightText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileHeaderMustContainFileName">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileHeaderFileNameDocumentationMustMatchFileName">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileHeaderMustHaveValidCompanyText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileHeaderFileNameDocumentationMustMatchTypeName">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+    <Analyzer AnalyzerId="StyleCop.CSharp.MaintainabilityRules">
+      <Rules>
+        <Rule Name="AccessModifierMustBeDeclared">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FieldsMustBePrivate">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="CodeAnalysisSuppressionMustHaveJustification">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DebugAssertMustProvideMessageText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="DebugFailMustProvideMessageText">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FileMayOnlyContainASingleClass">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="StatementMustNotUseUnnecessaryParenthesis">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ArithmeticExpressionsMustDeclarePrecedence">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ConditionalExpressionsMustDeclarePrecedence">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="RemoveDelegateParenthesisWhenPossible">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="AttributeConstructorMustNotUseUnnecessaryParenthesis">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="RemoveUnnecessaryCode">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+    <Analyzer AnalyzerId="StyleCop.CSharp.NamingRules">
+      <Rules>
+        <Rule Name="NonPrivateReadonlyFieldsMustBeginWithUpperCaseLetter">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FieldNamesMustNotUseHungarianNotation">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FieldNamesMustBeginWithLowerCaseLetter">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="AccessibleFieldsMustBeginWithUpperCaseLetter">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="VariableNamesMustNotBePrefixed">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FieldNamesMustNotBeginWithUnderscore">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="FieldNamesMustNotContainUnderscore">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementMustBeginWithUpperCaseLetter">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+    <Analyzer AnalyzerId="StyleCop.CSharp.OrderingRules">
+      <Rules>
+        <Rule Name="UsingDirectivesMustBePlacedWithinNamespace">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementsMustAppearInTheCorrectOrder">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementsMustBeOrderedByAccess">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="StaticElementsMustAppearBeforeInstanceElements">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PropertyAccessorsMustFollowOrder">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="EventAccessorsMustFollowOrder">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="UsingAliasDirectivesMustBePlacedAfterOtherUsingDirectives">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="UsingAliasDirectivesMustBeOrderedAlphabeticallyByAliasName">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+    <Analyzer AnalyzerId="StyleCop.CSharp.ReadabilityRules">
+      <Rules>
+        <Rule Name="DoNotPrefixCallsWithBaseUnlessLocalImplementationExists">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PrefixLocalCallsWithThis">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="PrefixCallsCorrectly">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="OpeningParenthesisMustBeOnDeclarationLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ClosingParenthesisMustBeOnLineOfLastParameter">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ClosingParenthesisMustBeOnLineOfOpeningParenthesis">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="CommaMustBeOnSameLineAsPreviousParameter">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ParameterListMustFollowDeclaration">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ParameterMustFollowComma">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="SplitParametersMustStartOnLineAfterDeclaration">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ParametersMustBeOnSameLineOrSeparateLines">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ParameterMustNotSpanMultipleLines">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="QueryClauseMustFollowPreviousClause">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="QueryClausesMustBeOnSeparateLinesOrAllOnOneLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="QueryClauseMustBeginOnNewLineWhenPreviousClauseSpansMultipleLines">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="QueryClausesSpanningMultipleLinesMustBeginOnOwnLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="CodeMustNotContainEmptyStatements">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="CodeMustNotContainMultipleStatementsOnOneLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="BlockStatementsMustNotContainEmbeddedComments">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="BlockStatementsMustNotContainEmbeddedRegions">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="UseStringEmptyForEmptyStrings">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+    <Analyzer AnalyzerId="StyleCop.CSharp.LayoutRules">
+      <Rules>
+        <Rule Name="SingleLineCommentsMustNotBeFollowedByBlankLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ClosingCurlyBracketMustBeFollowedByBlankLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="ElementDocumentationHeaderMustBePrecededByBlankLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+        <Rule Name="SingleLineCommentMustBePrecededByBlankLine">
+          <RuleSettings>
+            <BooleanProperty Name="Enabled">False</BooleanProperty>
+          </RuleSettings>
+        </Rule>
+      </Rules>
+      <AnalyzerSettings />
+    </Analyzer>
+  </Analyzers>
+</StyleCopSettings>
\ No newline at end of file
diff --git a/src/csharp/ext/grpc_csharp_ext.c b/src/csharp/ext/grpc_csharp_ext.c
index e244387..51abb63 100644
--- a/src/csharp/ext/grpc_csharp_ext.c
+++ b/src/csharp/ext/grpc_csharp_ext.c
@@ -653,6 +653,41 @@
   return grpc_secure_channel_create(creds, target, args);
 }
 
+GPR_EXPORT grpc_server_credentials *GPR_CALLTYPE
+grpcsharp_ssl_server_credentials_create(
+    const char *pem_root_certs, const char **key_cert_pair_cert_chain_array,
+    const char **key_cert_pair_private_key_array, size_t num_key_cert_pairs) {
+  size_t i;
+  grpc_server_credentials *creds;
+  grpc_ssl_pem_key_cert_pair *key_cert_pairs =
+      gpr_malloc(sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
+  memset(key_cert_pairs, 0,
+         sizeof(grpc_ssl_pem_key_cert_pair) * num_key_cert_pairs);
+
+  for (i = 0; i < num_key_cert_pairs; i++) {
+    if (key_cert_pair_cert_chain_array[i] ||
+        key_cert_pair_private_key_array[i]) {
+      key_cert_pairs[i].cert_chain = key_cert_pair_cert_chain_array[i];
+      key_cert_pairs[i].private_key = key_cert_pair_private_key_array[i];
+    }
+  }
+  creds = grpc_ssl_server_credentials_create(pem_root_certs, key_cert_pairs,
+                                             num_key_cert_pairs);
+  gpr_free(key_cert_pairs);
+  return creds;
+}
+
+GPR_EXPORT void grpcsharp_server_credentials_release(
+    grpc_server_credentials *creds) {
+  grpc_server_credentials_release(creds);
+}
+
+GPR_EXPORT gpr_int32 GPR_CALLTYPE
+grpcsharp_server_add_secure_http2_port(grpc_server *server, const char *addr,
+                                       grpc_server_credentials *creds) {
+  return grpc_server_add_secure_http2_port(server, addr, creds);
+}
+
 /* Logging */
 
 typedef void(GPR_CALLTYPE *grpcsharp_log_func)(const char *file, gpr_int32 line,
diff --git a/src/node/README.md b/src/node/README.md
index 5b3de6b..b1d2310 100644
--- a/src/node/README.md
+++ b/src/node/README.md
@@ -10,9 +10,9 @@
 
 ## Installation
 
-First, clone this repository (NPM package coming soon). Then follow the instructions in the `INSTALL` file in the root of the repository to install the C core library that this package depends on.
-
-Then, simply run `npm install` in or referencing this directory.
+ 1. Clone [the grpc repository](https://github.com/grpc/grpc).
+ 2. Follow the instructions in the `INSTALL` file in the root of that repository to install the C core library that this package depends on.
+ 3. Run `npm install`.
 
 ## Tests
 
diff --git a/src/node/ext/byte_buffer.cc b/src/node/ext/byte_buffer.cc
index 5235c8e..82b54b5 100644
--- a/src/node/ext/byte_buffer.cc
+++ b/src/node/ext/byte_buffer.cc
@@ -65,7 +65,7 @@
 Handle<Value> ByteBufferToBuffer(grpc_byte_buffer *buffer) {
   NanEscapableScope();
   if (buffer == NULL) {
-    return NanNull();
+    return NanEscapeScope(NanNull());
   }
   size_t length = grpc_byte_buffer_length(buffer);
   char *result = reinterpret_cast<char *>(calloc(length, sizeof(char)));
diff --git a/src/node/ext/completion_queue_async_worker.cc b/src/node/ext/completion_queue_async_worker.cc
index ca22527..cd7acd1 100644
--- a/src/node/ext/completion_queue_async_worker.cc
+++ b/src/node/ext/completion_queue_async_worker.cc
@@ -80,7 +80,6 @@
   NanScope();
   NanCallback *callback = GetTagCallback(result->tag);
   Handle<Value> argv[] = {NanNull(), GetTagNodeValue(result->tag)};
-
   callback->Call(2, argv);
 
   DestroyTag(result->tag);
diff --git a/src/node/package.json b/src/node/package.json
index 20eb21f..29cbab9 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "grpc",
-  "version": "0.5.2",
+  "version": "0.5.4",
   "author": "Google Inc.",
   "description": "gRPC Library for Node",
   "homepage": "http://www.grpc.io/",
diff --git a/src/node/test/end_to_end_test.js b/src/node/test/end_to_end_test.js
index 1cc1928..c39364d 100644
--- a/src/node/test/end_to_end_test.js
+++ b/src/node/test/end_to_end_test.js
@@ -235,4 +235,73 @@
       });
     });
   });
+  it('should send multiple messages', function(complete) {
+    var done = multiDone(complete, 2);
+    var requests = ['req1', 'req2'];
+    var deadline = new Date();
+    deadline.setSeconds(deadline.getSeconds() + 3);
+    var status_text = 'xyz';
+    var call = new grpc.Call(channel,
+                             'dummy_method',
+                             Infinity);
+    var client_batch = {};
+    client_batch[grpc.opType.SEND_INITIAL_METADATA] = {};
+    client_batch[grpc.opType.SEND_MESSAGE] = new Buffer(requests[0]);
+    client_batch[grpc.opType.RECV_INITIAL_METADATA] = true;
+    call.startBatch(client_batch, function(err, response) {
+      assert.ifError(err);
+      assert.deepEqual(response, {
+        'send metadata': true,
+        'send message': true,
+        'metadata': {}
+      });
+      var req2_batch = {};
+      req2_batch[grpc.opType.SEND_MESSAGE] = new Buffer(requests[1]);
+      req2_batch[grpc.opType.SEND_CLOSE_FROM_CLIENT] = true;
+      req2_batch[grpc.opType.RECV_STATUS_ON_CLIENT] = true;
+      call.startBatch(req2_batch, function(err, resp) {
+        assert.ifError(err);
+        assert.deepEqual(resp, {
+          'send message': true,
+          'client close': true,
+          'status': {
+            'code': grpc.status.OK,
+            'details': status_text,
+            'metadata': {}
+          }
+        });
+        done();
+      });
+    });
+
+    server.requestCall(function(err, call_details) {
+      var new_call = call_details['new call'];
+      assert.notEqual(new_call, null);
+      var server_call = new_call.call;
+      assert.notEqual(server_call, null);
+      var server_batch = {};
+      server_batch[grpc.opType.SEND_INITIAL_METADATA] = {};
+      server_batch[grpc.opType.RECV_MESSAGE] = true;
+      server_call.startBatch(server_batch, function(err, response) {
+        assert.ifError(err);
+        assert(response['send metadata']);
+        assert.strictEqual(response.read.toString(), requests[0]);
+        var end_batch = {};
+        end_batch[grpc.opType.RECV_CLOSE_ON_SERVER] = true;
+        end_batch[grpc.opType.SEND_STATUS_FROM_SERVER] = {
+          'metadata': {},
+          'code': grpc.status.OK,
+          'details': status_text
+        };
+        end_batch[grpc.opType.RECV_MESSAGE] = true;
+        server_call.startBatch(end_batch, function(err, response) {
+          assert.ifError(err);
+          assert(response['send status']);
+          assert(!response.cancelled);
+          assert.strictEqual(response.read.toString(), requests[1]);
+          done();
+        });
+      });
+    });
+  });
 });
diff --git a/src/node/test/server_test.js b/src/node/test/server_test.js
new file mode 100644
index 0000000..7cb34fa
--- /dev/null
+++ b/src/node/test/server_test.js
@@ -0,0 +1,94 @@
+/*
+ *
+ * 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 assert = require('assert');
+var grpc = require('bindings')('grpc.node');
+
+describe('server', function() {
+  describe('constructor', function() {
+    it('should work with no arguments', function() {
+      assert.doesNotThrow(function() {
+        new grpc.Server();
+      });
+    });
+    it('should work with an empty list argument', function() {
+      assert.doesNotThrow(function() {
+        new grpc.Server([]);
+      });
+    });
+  });
+  describe('addHttp2Port', function() {
+    var server;
+    before(function() {
+      server = new grpc.Server();
+    });
+    it('should bind to an unused port', function() {
+      var port;
+      assert.doesNotThrow(function() {
+        port = server.addHttp2Port('0.0.0.0:0');
+      });
+      assert(port > 0);
+    });
+  });
+  describe('addSecureHttp2Port', function() {
+    var server;
+    before(function() {
+      server = new grpc.Server();
+    });
+    it('should bind to an unused port with fake credentials', function() {
+      var port;
+      var creds = grpc.ServerCredentials.createFake();
+      assert.doesNotThrow(function() {
+        port = server.addSecureHttp2Port('0.0.0.0:0', creds);
+      });
+      assert(port > 0);
+    });
+  });
+  describe('listen', function() {
+    var server;
+    before(function() {
+      server = new grpc.Server();
+      server.addHttp2Port('0.0.0.0:0');
+    });
+    after(function() {
+      server.shutdown();
+    });
+    it('should listen without error', function() {
+      assert.doesNotThrow(function() {
+        server.start();
+      });
+    });
+  });
+});
diff --git a/src/python/README.md b/src/python/README.md
index 490a229..c8057be 100644
--- a/src/python/README.md
+++ b/src/python/README.md
@@ -46,7 +46,7 @@
 
 - Install gRPC Python's dependencies
 ```
-$ pip install -r requirements.txt
+$ pip install -r src/python/requirements.txt
 ```
 
 - Install gRPC Python
diff --git a/src/python/src/grpc/_adapter/_call.c b/src/python/src/grpc/_adapter/_call.c
index dca2e49..d8806e5 100644
--- a/src/python/src/grpc/_adapter/_call.c
+++ b/src/python/src/grpc/_adapter/_call.c
@@ -45,7 +45,7 @@
   const PyObject *channel;
   const char *method;
   const char *host;
-  const double deadline;
+  double deadline;
   static char *kwlist[] = {"channel", "method", "host", "deadline", NULL};
 
   if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!ssd:Call", kwlist,
diff --git a/src/python/src/grpc/_adapter/_face_test_case.py b/src/python/src/grpc/_adapter/_face_test_case.py
index 475d780..2542eb6 100644
--- a/src/python/src/grpc/_adapter/_face_test_case.py
+++ b/src/python/src/grpc/_adapter/_face_test_case.py
@@ -50,31 +50,12 @@
   """Provides abstract Face-layer tests a GRPC-backed implementation."""
 
   def set_up_implementation(
-      self,
-      name,
-      methods,
-      inline_value_in_value_out_methods,
-      inline_value_in_stream_out_methods,
-      inline_stream_in_value_out_methods,
-      inline_stream_in_stream_out_methods,
-      event_value_in_value_out_methods,
-      event_value_in_stream_out_methods,
-      event_stream_in_value_out_methods,
-      event_stream_in_stream_out_methods,
-      multi_method):
+      self, name, methods, method_implementations,
+      multi_method_implementation):
     pool = logging_pool.pool(_MAXIMUM_POOL_SIZE)
 
     servicer = face_implementations.servicer(
-        pool,
-        inline_value_in_value_out_methods=inline_value_in_value_out_methods,
-        inline_value_in_stream_out_methods=inline_value_in_stream_out_methods,
-        inline_stream_in_value_out_methods=inline_stream_in_value_out_methods,
-        inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods,
-        event_value_in_value_out_methods=event_value_in_value_out_methods,
-        event_value_in_stream_out_methods=event_value_in_stream_out_methods,
-        event_stream_in_value_out_methods=event_stream_in_value_out_methods,
-        event_stream_in_stream_out_methods=event_stream_in_stream_out_methods,
-        multi_method=multi_method)
+        pool, method_implementations, multi_method_implementation)
 
     serialization = serial.serialization(methods)
 
@@ -96,9 +77,8 @@
     rear_link.join_fore_link(front)
     front.join_rear_link(rear_link)
 
-    server = face_implementations.server()
-    stub = face_implementations.stub(front, pool)
-    return server, stub, (rear_link, fore_link, front, back)
+    stub = face_implementations.generic_stub(front, pool)
+    return stub, (rear_link, fore_link, front, back)
 
   def tear_down_implementation(self, memo):
     rear_link, fore_link, front, back = memo
diff --git a/src/python/src/grpc/_adapter/fore.py b/src/python/src/grpc/_adapter/fore.py
index 6ef9e60..339c0ef 100644
--- a/src/python/src/grpc/_adapter/fore.py
+++ b/src/python/src/grpc/_adapter/fore.py
@@ -357,90 +357,3 @@
         self._complete(ticket.operation_id, ticket.payload)
       else:
         self._cancel(ticket.operation_id)
-
-
-class _ActivatedForeLink(ticket_interfaces.ForeLink, activated.Activated):
-
-  def __init__(
-      self, port, request_deserializers, response_serializers,
-      root_certificates, key_chain_pairs):
-    self._port = port
-    self._request_deserializers = request_deserializers
-    self._response_serializers = response_serializers
-    self._root_certificates = root_certificates
-    self._key_chain_pairs = key_chain_pairs
-
-    self._lock = threading.Lock()
-    self._pool = None
-    self._fore_link = None
-    self._rear_link = null.NULL_REAR_LINK
-
-  def join_rear_link(self, rear_link):
-    with self._lock:
-      self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link
-      if self._fore_link is not None:
-        self._fore_link.join_rear_link(rear_link)
-
-  def _start(self):
-    with self._lock:
-      self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
-      self._fore_link = ForeLink(
-          self._pool, self._request_deserializers, self._response_serializers,
-          self._root_certificates, self._key_chain_pairs, port=self._port)
-      self._fore_link.join_rear_link(self._rear_link)
-      self._fore_link.start()
-      return self
-
-  def _stop(self):
-    with self._lock:
-      self._fore_link.stop()
-      self._fore_link = None
-      self._pool.shutdown(wait=True)
-      self._pool = None
-
-  def __enter__(self):
-    return self._start()
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    self._stop()
-    return False
-
-  def start(self):
-    return self._start()
-
-  def stop(self):
-    self._stop()
-
-  def port(self):
-    with self._lock:
-      return None if self._fore_link is None else self._fore_link.port()
-
-  def accept_back_to_front_ticket(self, ticket):
-    with self._lock:
-      if self._fore_link is not None:
-        self._fore_link.accept_back_to_front_ticket(ticket)
-
-
-def activated_fore_link(
-    port, request_deserializers, response_serializers, root_certificates,
-    key_chain_pairs):
-  """Creates a ForeLink that is also an activated.Activated.
-
-  The returned object is only valid for use between calls to its start and stop
-  methods (or in context when used as a context manager).
-
-  Args:
-    port: The port on which to serve RPCs, or None for a port to be
-      automatically selected.
-    request_deserializers: A dictionary from RPC method names to request object
-      deserializer behaviors.
-    response_serializers: A dictionary from RPC method names to response object
-      serializer behaviors.
-    root_certificates: The PEM-encoded client root certificates as a bytestring
-      or None.
-    key_chain_pairs: A sequence of PEM-encoded private key-certificate chain
-      pairs.
-  """
-  return _ActivatedForeLink(
-      port, request_deserializers, response_serializers, root_certificates,
-      key_chain_pairs)
diff --git a/src/python/src/grpc/_adapter/rear.py b/src/python/src/grpc/_adapter/rear.py
index fc71bf0..62703fa 100644
--- a/src/python/src/grpc/_adapter/rear.py
+++ b/src/python/src/grpc/_adapter/rear.py
@@ -387,127 +387,3 @@
       else:
         # NOTE(nathaniel): All other categories are treated as cancellation.
         self._cancel(ticket.operation_id)
-
-
-class _ActivatedRearLink(ticket_interfaces.RearLink, activated.Activated):
-
-  def __init__(
-      self, host, port, request_serializers, response_deserializers, secure,
-      root_certificates, private_key, certificate_chain,
-      server_host_override=None):
-    self._host = host
-    self._port = port
-    self._request_serializers = request_serializers
-    self._response_deserializers = response_deserializers
-    self._secure = secure
-    self._root_certificates = root_certificates
-    self._private_key = private_key
-    self._certificate_chain = certificate_chain
-    self._server_host_override = server_host_override
-
-    self._lock = threading.Lock()
-    self._pool = None
-    self._rear_link = None
-    self._fore_link = null.NULL_FORE_LINK
-
-  def join_fore_link(self, fore_link):
-    with self._lock:
-      self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link
-      if self._rear_link is not None:
-        self._rear_link.join_fore_link(self._fore_link)
-
-  def _start(self):
-    with self._lock:
-      self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
-      self._rear_link = RearLink(
-          self._host, self._port, self._pool, self._request_serializers,
-          self._response_deserializers, self._secure, self._root_certificates,
-          self._private_key, self._certificate_chain,
-          server_host_override=self._server_host_override)
-      self._rear_link.join_fore_link(self._fore_link)
-      self._rear_link.start()
-    return self
-
-  def _stop(self):
-    with self._lock:
-      self._rear_link.stop()
-      self._rear_link = None
-      self._pool.shutdown(wait=True)
-      self._pool = None
-
-  def __enter__(self):
-    return self._start()
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    self._stop()
-    return False
-
-  def start(self):
-    return self._start()
-
-  def stop(self):
-    self._stop()
-
-  def accept_front_to_back_ticket(self, ticket):
-    with self._lock:
-      if self._rear_link is not None:
-        self._rear_link.accept_front_to_back_ticket(ticket)
-
-
-# TODO(issue 726): reconcile these two creation functions.
-def activated_rear_link(
-    host, port, request_serializers, response_deserializers):
-  """Creates a RearLink that is also an activated.Activated.
-
-  The returned object is only valid for use between calls to its start and stop
-  methods (or in context when used as a context manager).
-
-  Args:
-    host: The host to which to connect for RPC service.
-    port: The port to which to connect for RPC service.
-    request_serializers: A dictionary from RPC method name to request object
-      serializer behavior.
-    response_deserializers: A dictionary from RPC method name to response
-      object deserializer behavior.
-    secure: A boolean indicating whether or not to use a secure connection.
-    root_certificates: The PEM-encoded root certificates or None to ask for
-      them to be retrieved from a default location.
-    private_key: The PEM-encoded private key to use or None if no private key
-      should be used.
-    certificate_chain: The PEM-encoded certificate chain to use or None if no
-      certificate chain should be used.
-  """
-  return _ActivatedRearLink(
-      host, port, request_serializers, response_deserializers, False, None,
-      None, None)
-
-
-
-def secure_activated_rear_link(
-    host, port, request_serializers, response_deserializers, root_certificates,
-    private_key, certificate_chain, server_host_override=None):
-  """Creates a RearLink that is also an activated.Activated.
-
-  The returned object is only valid for use between calls to its start and stop
-  methods (or in context when used as a context manager).
-
-  Args:
-    host: The host to which to connect for RPC service.
-    port: The port to which to connect for RPC service.
-    request_serializers: A dictionary from RPC method name to request object
-      serializer behavior.
-    response_deserializers: A dictionary from RPC method name to response
-      object deserializer behavior.
-    root_certificates: The PEM-encoded root certificates or None to ask for
-      them to be retrieved from a default location.
-    private_key: The PEM-encoded private key to use or None if no private key
-      should be used.
-    certificate_chain: The PEM-encoded certificate chain to use or None if no
-      certificate chain should be used.
-    server_host_override: (For testing only) the target name used for SSL
-      host name checking.
-  """
-  return _ActivatedRearLink(
-      host, port, request_serializers, response_deserializers, True,
-      root_certificates, private_key, certificate_chain,
-      server_host_override=server_host_override)
diff --git a/src/python/src/grpc/early_adopter/_assembly_utilities.py b/src/python/src/grpc/early_adopter/_face_utilities.py
similarity index 76%
rename from src/python/src/grpc/early_adopter/_assembly_utilities.py
rename to src/python/src/grpc/early_adopter/_face_utilities.py
index facfc2b..2cf5760 100644
--- a/src/python/src/grpc/early_adopter/_assembly_utilities.py
+++ b/src/python/src/grpc/early_adopter/_face_utilities.py
@@ -30,23 +30,20 @@
 import abc
 import collections
 
-# assembly_interfaces is referenced from specification in this module.
-from grpc.framework.assembly import interfaces as assembly_interfaces  # pylint: disable=unused-import
-from grpc.framework.assembly import utilities as assembly_utilities
+# face_interfaces is referenced from specification in this module.
+from grpc.framework.common import cardinality
+from grpc.framework.face import interfaces as face_interfaces  # pylint: disable=unused-import
+from grpc.framework.face import utilities as face_utilities
 from grpc.early_adopter import _reexport
 from grpc.early_adopter import interfaces
 
 
-# TODO(issue 726): Kill the "implementations" attribute of this in favor
-# of the same-information-less-bogusly-represented "cardinalities".
 class InvocationBreakdown(object):
   """An intermediate representation of invocation-side views of RPC methods.
 
   Attributes:
     cardinalities: A dictionary from RPC method name to interfaces.Cardinality
       value.
-    implementations: A dictionary from RPC method name to
-      assembly_interfaces.MethodImplementation describing the method.
     request_serializers: A dictionary from RPC method name to callable
       behavior to be used serializing request values for the RPC.
     response_deserializers: A dictionary from RPC method name to callable
@@ -59,8 +56,7 @@
     InvocationBreakdown,
     collections.namedtuple(
         '_EasyInvocationBreakdown',
-        ('cardinalities', 'implementations', 'request_serializers',
-         'response_deserializers'))):
+        ('cardinalities', 'request_serializers', 'response_deserializers'))):
   pass
 
 
@@ -68,8 +64,8 @@
   """An intermediate representation of service-side views of RPC methods.
 
   Attributes:
-    implementations: A dictionary from RPC method name
-      assembly_interfaces.MethodImplementation implementing the RPC method.
+    implementations: A dictionary from RPC method name to
+      face_interfaces.MethodImplementation implementing the RPC method.
     request_deserializers: A dictionary from RPC method name to callable
       behavior to be used deserializing request values for the RPC.
     response_serializers: A dictionary from RPC method name to callable
@@ -97,25 +93,14 @@
     An InvocationBreakdown corresponding to the given method descriptions.
   """
   cardinalities = {}
-  implementations = {}
   request_serializers = {}
   response_deserializers = {}
   for name, method_description in method_descriptions.iteritems():
-    cardinality = method_description.cardinality()
-    cardinalities[name] = cardinality
-    if cardinality is interfaces.Cardinality.UNARY_UNARY:
-      implementations[name] = assembly_utilities.unary_unary_inline(None)
-    elif cardinality is interfaces.Cardinality.UNARY_STREAM:
-      implementations[name] = assembly_utilities.unary_stream_inline(None)
-    elif cardinality is interfaces.Cardinality.STREAM_UNARY:
-      implementations[name] = assembly_utilities.stream_unary_inline(None)
-    elif cardinality is interfaces.Cardinality.STREAM_STREAM:
-      implementations[name] = assembly_utilities.stream_stream_inline(None)
+    cardinalities[name] = method_description.cardinality()
     request_serializers[name] = method_description.serialize_request
     response_deserializers[name] = method_description.deserialize_response
   return _EasyInvocationBreakdown(
-      cardinalities, implementations, request_serializers,
-      response_deserializers)
+      cardinalities, request_serializers, response_deserializers)
 
 
 def break_down_service(method_descriptions):
@@ -139,28 +124,28 @@
           service_behavior=method_description.service_unary_unary):
         return service_behavior(
             request, _reexport.rpc_context(face_rpc_context))
-      implementations[name] = assembly_utilities.unary_unary_inline(service)
+      implementations[name] = face_utilities.unary_unary_inline(service)
     elif cardinality is interfaces.Cardinality.UNARY_STREAM:
       def service(
           request, face_rpc_context,
           service_behavior=method_description.service_unary_stream):
         return service_behavior(
             request, _reexport.rpc_context(face_rpc_context))
-      implementations[name] = assembly_utilities.unary_stream_inline(service)
+      implementations[name] = face_utilities.unary_stream_inline(service)
     elif cardinality is interfaces.Cardinality.STREAM_UNARY:
       def service(
           request_iterator, face_rpc_context,
           service_behavior=method_description.service_stream_unary):
         return service_behavior(
             request_iterator, _reexport.rpc_context(face_rpc_context))
-      implementations[name] = assembly_utilities.stream_unary_inline(service)
+      implementations[name] = face_utilities.stream_unary_inline(service)
     elif cardinality is interfaces.Cardinality.STREAM_STREAM:
       def service(
           request_iterator, face_rpc_context,
           service_behavior=method_description.service_stream_stream):
         return service_behavior(
             request_iterator, _reexport.rpc_context(face_rpc_context))
-      implementations[name] = assembly_utilities.stream_stream_inline(service)
+      implementations[name] = face_utilities.stream_stream_inline(service)
     request_deserializers[name] = method_description.deserialize_request
     response_serializers[name] = method_description.serialize_response
 
diff --git a/src/python/src/grpc/early_adopter/_reexport.py b/src/python/src/grpc/early_adopter/_reexport.py
index 35f4e85..f341602 100644
--- a/src/python/src/grpc/early_adopter/_reexport.py
+++ b/src/python/src/grpc/early_adopter/_reexport.py
@@ -27,12 +27,20 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+from grpc.framework.common import cardinality
 from grpc.framework.face import exceptions as face_exceptions
 from grpc.framework.face import interfaces as face_interfaces
 from grpc.framework.foundation import future
 from grpc.early_adopter import exceptions
 from grpc.early_adopter import interfaces
 
+_EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY = {
+    interfaces.Cardinality.UNARY_UNARY: cardinality.Cardinality.UNARY_UNARY,
+    interfaces.Cardinality.UNARY_STREAM: cardinality.Cardinality.UNARY_STREAM,
+    interfaces.Cardinality.STREAM_UNARY: cardinality.Cardinality.STREAM_UNARY,
+    interfaces.Cardinality.STREAM_STREAM: cardinality.Cardinality.STREAM_STREAM,
+}
+
 _ABORTION_REEXPORT = {
     face_interfaces.Abortion.CANCELLED: interfaces.Abortion.CANCELLED,
     face_interfaces.Abortion.EXPIRED: interfaces.Abortion.EXPIRED,
@@ -142,71 +150,49 @@
 
 class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync):
 
-  def __init__(self, face_unary_unary_sync_async):
-    self._underlying = face_unary_unary_sync_async
+  def __init__(self, face_unary_unary_multi_callable):
+    self._underlying = face_unary_unary_multi_callable
 
   def __call__(self, request, timeout):
     return _call_reexporting_errors(
         self._underlying, request, timeout)
 
   def async(self, request, timeout):
-    return _ReexportedFuture(self._underlying.async(request, timeout))
+    return _ReexportedFuture(self._underlying.future(request, timeout))
 
 
 class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync):
 
-  def __init__(self, face_stream_unary_sync_async):
-    self._underlying = face_stream_unary_sync_async
+  def __init__(self, face_stream_unary_multi_callable):
+    self._underlying = face_stream_unary_multi_callable
 
   def __call__(self, request_iterator, timeout):
     return _call_reexporting_errors(
         self._underlying, request_iterator, timeout)
 
   def async(self, request_iterator, timeout):
-    return _ReexportedFuture(self._underlying.async(request_iterator, timeout))
+    return _ReexportedFuture(self._underlying.future(request_iterator, timeout))
 
 
-class _Stub(interfaces.Stub):
+def common_cardinalities(early_adopter_cardinalities):
+  common_cardinalities = {}
+  for name, early_adopter_cardinality in early_adopter_cardinalities.iteritems():
+    common_cardinalities[name] = _EARLY_ADOPTER_CARDINALITY_TO_COMMON_CARDINALITY[
+        early_adopter_cardinality]
+  return common_cardinalities
 
-  def __init__(self, assembly_stub, cardinalities):
-    self._assembly_stub = assembly_stub
-    self._cardinalities = cardinalities
-
-  def __enter__(self):
-    self._assembly_stub.__enter__()
-    return self
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    self._assembly_stub.__exit__(exc_type, exc_val, exc_tb)
-    return False
-
-  def __getattr__(self, attr):
-    underlying_attr = self._assembly_stub.__getattr__(attr)
-    cardinality = self._cardinalities.get(attr)
-    # TODO(nathaniel): unify this trick with its other occurrence in the code.
-    if cardinality is None:
-      for name, cardinality in self._cardinalities.iteritems():
-        last_slash_index = name.rfind('/')
-        if 0 <= last_slash_index and name[last_slash_index + 1:] == attr:
-          break
-      else:
-        raise AttributeError(attr)
-    if cardinality is interfaces.Cardinality.UNARY_UNARY:
-      return _UnaryUnarySyncAsync(underlying_attr)
-    elif cardinality is interfaces.Cardinality.UNARY_STREAM:
-      return lambda request, timeout: _CancellableIterator(
-          underlying_attr(request, timeout))
-    elif cardinality is interfaces.Cardinality.STREAM_UNARY:
-      return _StreamUnarySyncAsync(underlying_attr)
-    elif cardinality is interfaces.Cardinality.STREAM_STREAM:
-      return lambda request_iterator, timeout: _CancellableIterator(
-          underlying_attr(request_iterator, timeout))
-    else:
-      raise AttributeError(attr)
 
 def rpc_context(face_rpc_context):
   return _RpcContext(face_rpc_context)
 
 
-def stub(assembly_stub, cardinalities):
-  return _Stub(assembly_stub, cardinalities)
+def cancellable_iterator(face_cancellable_iterator):
+  return _CancellableIterator(face_cancellable_iterator)
+
+
+def unary_unary_sync_async(face_unary_unary_multi_callable):
+  return _UnaryUnarySyncAsync(face_unary_unary_multi_callable)
+
+
+def stream_unary_sync_async(face_stream_unary_multi_callable):
+  return _StreamUnarySyncAsync(face_stream_unary_multi_callable)
diff --git a/src/python/src/grpc/early_adopter/implementations.py b/src/python/src/grpc/early_adopter/implementations.py
index 87ea18d..1c02f9e 100644
--- a/src/python/src/grpc/early_adopter/implementations.py
+++ b/src/python/src/grpc/early_adopter/implementations.py
@@ -33,10 +33,16 @@
 
 from grpc._adapter import fore as _fore
 from grpc._adapter import rear as _rear
-from grpc.early_adopter import _assembly_utilities
+from grpc.early_adopter import _face_utilities
 from grpc.early_adopter import _reexport
 from grpc.early_adopter import interfaces
-from grpc.framework.assembly import implementations as _assembly_implementations
+from grpc.framework.base import util as _base_utilities
+from grpc.framework.base.packets import implementations as _tickets_implementations
+from grpc.framework.face import implementations as _face_implementations
+from grpc.framework.foundation import logging_pool
+
+_THREAD_POOL_SIZE = 80
+_ONE_DAY_IN_SECONDS = 24 * 60 * 60
 
 
 class _Server(interfaces.Server):
@@ -50,30 +56,39 @@
     else:
       self._key_chain_pairs = ((private_key, certificate_chain),)
 
+    self._pool = None
+    self._back = None
     self._fore_link = None
-    self._server = None
 
   def _start(self):
     with self._lock:
-      if self._server is None:
-        self._fore_link = _fore.activated_fore_link(
-            self._port, self._breakdown.request_deserializers,
+      if self._pool is None:
+        self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
+        servicer = _face_implementations.servicer(
+            self._pool, self._breakdown.implementations, None)
+        self._back = _tickets_implementations.back(
+            servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS,
+            _ONE_DAY_IN_SECONDS)
+        self._fore_link = _fore.ForeLink(
+            self._pool, self._breakdown.request_deserializers,
             self._breakdown.response_serializers, None, self._key_chain_pairs)
-
-        self._server = _assembly_implementations.assemble_service(
-            self._breakdown.implementations, self._fore_link)
-        self._server.start()
+        self._back.join_fore_link(self._fore_link)
+        self._fore_link.join_rear_link(self._back)
+        self._fore_link.start()
       else:
         raise ValueError('Server currently running!')
 
   def _stop(self):
     with self._lock:
-      if self._server is None:
+      if self._pool is None:
         raise ValueError('Server not running!')
       else:
-        self._server.stop()
-        self._server = None
+        self._fore_link.stop()
+        _base_utilities.wait_for_idle(self._back)
+        self._pool.shutdown(wait=True)
         self._fore_link = None
+        self._back = None
+        self._pool = None
 
   def __enter__(self):
     self._start()
@@ -93,14 +108,105 @@
     with self._lock:
       return self._fore_link.port()
 
-def _build_stub(breakdown, activated_rear_link):
-  assembly_stub = _assembly_implementations.assemble_dynamic_inline_stub(
-      breakdown.implementations, activated_rear_link)
-  return _reexport.stub(assembly_stub, breakdown.cardinalities)
+
+class _Stub(interfaces.Stub):
+
+  def __init__(
+      self, breakdown, host, port, secure, root_certificates, private_key,
+      certificate_chain, server_host_override=None):
+    self._lock = threading.Lock()
+    self._breakdown = breakdown
+    self._host = host
+    self._port = port
+    self._secure = secure
+    self._root_certificates = root_certificates
+    self._private_key = private_key
+    self._certificate_chain = certificate_chain
+    self._server_host_override = server_host_override
+
+    self._pool = None
+    self._front = None
+    self._rear_link = None
+    self._understub = None
+
+  def __enter__(self):
+    with self._lock:
+      if self._pool is None:
+        self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
+        self._front = _tickets_implementations.front(
+            self._pool, self._pool, self._pool)
+        self._rear_link = _rear.RearLink(
+            self._host, self._port, self._pool,
+            self._breakdown.request_serializers,
+            self._breakdown.response_deserializers, self._secure,
+            self._root_certificates, self._private_key, self._certificate_chain,
+            server_host_override=self._server_host_override)
+        self._front.join_rear_link(self._rear_link)
+        self._rear_link.join_fore_link(self._front)
+        self._rear_link.start()
+        self._understub = _face_implementations.dynamic_stub(
+            _reexport.common_cardinalities(self._breakdown.cardinalities),
+            self._front, self._pool, '')
+      else:
+        raise ValueError('Tried to __enter__ already-__enter__ed Stub!')
+    return self
+
+  def __exit__(self, exc_type, exc_val, exc_tb):
+    with self._lock:
+      if self._pool is None:
+        raise ValueError('Tried to __exit__ non-__enter__ed Stub!')
+      else:
+        self._rear_link.stop()
+        _base_utilities.wait_for_idle(self._front)
+        self._pool.shutdown(wait=True)
+        self._rear_link = None
+        self._front = None
+        self._pool = None
+        self._understub = None
+    return False
+
+  def __getattr__(self, attr):
+    with self._lock:
+      if self._pool is None:
+        raise ValueError('Tried to __getattr__ non-__enter__ed Stub!')
+      else:
+        underlying_attr = getattr(self._understub, attr, None)
+        method_cardinality = self._breakdown.cardinalities.get(attr)
+        # TODO(nathaniel): Eliminate this trick.
+        if underlying_attr is None:
+          for method_name, method_cardinality in self._breakdown.cardinalities.iteritems():
+            last_slash_index = method_name.rfind('/')
+            if 0 <= last_slash_index and method_name[last_slash_index + 1:] == attr:
+              underlying_attr = getattr(self._understub, method_name)
+              break
+          else:
+            raise AttributeError(attr)
+        if method_cardinality is interfaces.Cardinality.UNARY_UNARY:
+          return _reexport.unary_unary_sync_async(underlying_attr)
+        elif method_cardinality is interfaces.Cardinality.UNARY_STREAM:
+          return lambda request, timeout: _reexport.cancellable_iterator(
+              underlying_attr(request, timeout))
+        elif method_cardinality is interfaces.Cardinality.STREAM_UNARY:
+          return _reexport.stream_unary_sync_async(underlying_attr)
+        elif method_cardinality is interfaces.Cardinality.STREAM_STREAM:
+          return lambda request_iterator, timeout: (
+              _reexport.cancellable_iterator(underlying_attr(
+                  request_iterator, timeout)))
+        else:
+          raise AttributeError(attr)
+
+
+def _build_stub(
+    methods, host, port, secure, root_certificates, private_key,
+    certificate_chain, server_host_override=None):
+  breakdown = _face_utilities.break_down_invocation(methods)
+  return _Stub(
+      breakdown, host, port, secure, root_certificates, private_key,
+      certificate_chain, server_host_override=server_host_override)
 
 
 def _build_server(methods, port, private_key, certificate_chain):
-  breakdown = _assembly_utilities.break_down_service(methods)
+  breakdown = _face_utilities.break_down_service(methods)
   return _Server(breakdown, port, private_key, certificate_chain)
 
 
@@ -117,11 +223,7 @@
   Returns:
     An interfaces.Stub affording RPC invocation.
   """
-  breakdown = _assembly_utilities.break_down_invocation(methods)
-  activated_rear_link = _rear.activated_rear_link(
-      host, port, breakdown.request_serializers,
-      breakdown.response_deserializers)
-  return _build_stub(breakdown, activated_rear_link)
+  return _build_stub(methods, host, port, False, None, None, None)
 
 
 def secure_stub(
@@ -147,12 +249,9 @@
   Returns:
     An interfaces.Stub affording RPC invocation.
   """
-  breakdown = _assembly_utilities.break_down_invocation(methods)
-  activated_rear_link = _rear.secure_activated_rear_link(
-      host, port, breakdown.request_serializers,
-      breakdown.response_deserializers, root_certificates, private_key,
+  return _build_stub(
+      methods, host, port, True, root_certificates, private_key,
       certificate_chain, server_host_override=server_host_override)
-  return _build_stub(breakdown, activated_rear_link)
 
 
 def insecure_server(methods, port):
diff --git a/src/python/src/grpc/framework/assembly/__init__.py b/src/python/src/grpc/framework/assembly/__init__.py
deleted file mode 100644
index 7086519..0000000
--- a/src/python/src/grpc/framework/assembly/__init__.py
+++ /dev/null
@@ -1,30 +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.
-
-
diff --git a/src/python/src/grpc/framework/assembly/implementations.py b/src/python/src/grpc/framework/assembly/implementations.py
deleted file mode 100644
index f7166ed..0000000
--- a/src/python/src/grpc/framework/assembly/implementations.py
+++ /dev/null
@@ -1,317 +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.
-
-"""Implementations for assembling RPC framework values."""
-
-import threading
-
-# tickets_interfaces, face_interfaces, and activated are referenced from
-# specification in this module.
-from grpc.framework.assembly import interfaces
-from grpc.framework.base import util as base_utilities
-from grpc.framework.base.packets import implementations as tickets_implementations
-from grpc.framework.base.packets import interfaces as tickets_interfaces  # pylint: disable=unused-import
-from grpc.framework.common import cardinality
-from grpc.framework.common import style
-from grpc.framework.face import implementations as face_implementations
-from grpc.framework.face import interfaces as face_interfaces  # pylint: disable=unused-import
-from grpc.framework.face import utilities as face_utilities
-from grpc.framework.foundation import activated  # pylint: disable=unused-import
-from grpc.framework.foundation import logging_pool
-
-_ONE_DAY_IN_SECONDS = 60 * 60 * 24
-_THREAD_POOL_SIZE = 100
-
-
-class _FaceStub(object):
-
-  def __init__(self, rear_link):
-    self._rear_link = rear_link
-    self._lock = threading.Lock()
-    self._pool = None
-    self._front = None
-    self._under_stub = None
-
-  def __enter__(self):
-    with self._lock:
-      self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
-      self._front = tickets_implementations.front(
-          self._pool, self._pool, self._pool)
-      self._rear_link.start()
-      self._rear_link.join_fore_link(self._front)
-      self._front.join_rear_link(self._rear_link)
-      self._under_stub = face_implementations.stub(self._front, self._pool)
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    with self._lock:
-      self._under_stub = None
-      self._rear_link.stop()
-      base_utilities.wait_for_idle(self._front)
-      self._front = None
-      self._pool.shutdown(wait=True)
-      self._pool = None
-    return False
-
-  def __getattr__(self, attr):
-    with self._lock:
-      if self._under_stub is None:
-        raise ValueError('Called out of context!')
-      else:
-        return getattr(self._under_stub, attr)
-
-
-def _behaviors(implementations, front, pool):
-  behaviors = {}
-  stub = face_implementations.stub(front, pool)
-  for name, implementation in implementations.iteritems():
-    if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY:
-      behaviors[name] = stub.unary_unary_sync_async(name)
-    elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM:
-      behaviors[name] = lambda request, context, bound_name=name: (
-          stub.inline_value_in_stream_out(bound_name, request, context))
-    elif implementation.cardinality is cardinality.Cardinality.STREAM_UNARY:
-      behaviors[name] = stub.stream_unary_sync_async(name)
-    elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM:
-      behaviors[name] = lambda request_iterator, context, bound_name=name: (
-          stub.inline_stream_in_stream_out(
-              bound_name, request_iterator, context))
-  return behaviors
-
-
-class _DynamicInlineStub(object):
-
-  def __init__(self, implementations, rear_link):
-    self._implementations = implementations
-    self._rear_link = rear_link
-    self._lock = threading.Lock()
-    self._pool = None
-    self._front = None
-    self._behaviors = None
-
-  def __enter__(self):
-    with self._lock:
-      self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
-      self._front = tickets_implementations.front(
-          self._pool, self._pool, self._pool)
-      self._rear_link.start()
-      self._rear_link.join_fore_link(self._front)
-      self._front.join_rear_link(self._rear_link)
-      self._behaviors = _behaviors(
-          self._implementations, self._front, self._pool)
-      return self
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    with self._lock:
-      self._behaviors = None
-      self._rear_link.stop()
-      base_utilities.wait_for_idle(self._front)
-      self._front = None
-      self._pool.shutdown(wait=True)
-      self._pool = None
-    return False
-
-  def __getattr__(self, attr):
-    with self._lock:
-      behavior = self._behaviors.get(attr)
-      if behavior is None:
-        for name, behavior in self._behaviors.iteritems():
-          last_slash_index = name.rfind('/')
-          if 0 <= last_slash_index and name[last_slash_index + 1:] == attr:
-            return behavior
-        else:
-          raise AttributeError(
-              '_DynamicInlineStub instance has no attribute "%s"!' % attr)
-      else:
-        return behavior
-
-
-def _servicer(implementations, pool):
-  inline_value_in_value_out_methods = {}
-  inline_value_in_stream_out_methods = {}
-  inline_stream_in_value_out_methods = {}
-  inline_stream_in_stream_out_methods = {}
-  event_value_in_value_out_methods = {}
-  event_value_in_stream_out_methods = {}
-  event_stream_in_value_out_methods = {}
-  event_stream_in_stream_out_methods = {}
-
-  for name, implementation in implementations.iteritems():
-    if implementation.cardinality is cardinality.Cardinality.UNARY_UNARY:
-      if implementation.style is style.Service.INLINE:
-        inline_value_in_value_out_methods[name] = (
-            face_utilities.inline_unary_unary_method(implementation.unary_unary_inline))
-      elif implementation.style is style.Service.EVENT:
-        event_value_in_value_out_methods[name] = (
-            face_utilities.event_unary_unary_method(implementation.unary_unary_event))
-    elif implementation.cardinality is cardinality.Cardinality.UNARY_STREAM:
-      if implementation.style is style.Service.INLINE:
-        inline_value_in_stream_out_methods[name] = (
-            face_utilities.inline_unary_stream_method(implementation.unary_stream_inline))
-      elif implementation.style is style.Service.EVENT:
-        event_value_in_stream_out_methods[name] = (
-            face_utilities.event_unary_stream_method(implementation.unary_stream_event))
-    if implementation.cardinality is cardinality.Cardinality.STREAM_UNARY:
-      if implementation.style is style.Service.INLINE:
-        inline_stream_in_value_out_methods[name] = (
-            face_utilities.inline_stream_unary_method(implementation.stream_unary_inline))
-      elif implementation.style is style.Service.EVENT:
-        event_stream_in_value_out_methods[name] = (
-            face_utilities.event_stream_unary_method(implementation.stream_unary_event))
-    elif implementation.cardinality is cardinality.Cardinality.STREAM_STREAM:
-      if implementation.style is style.Service.INLINE:
-        inline_stream_in_stream_out_methods[name] = (
-            face_utilities.inline_stream_stream_method(implementation.stream_stream_inline))
-      elif implementation.style is style.Service.EVENT:
-        event_stream_in_stream_out_methods[name] = (
-            face_utilities.event_stream_stream_method(implementation.stream_stream_event))
-
-  return face_implementations.servicer(
-      pool,
-      inline_value_in_value_out_methods=inline_value_in_value_out_methods,
-      inline_value_in_stream_out_methods=inline_value_in_stream_out_methods,
-      inline_stream_in_value_out_methods=inline_stream_in_value_out_methods,
-      inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods,
-      event_value_in_value_out_methods=event_value_in_value_out_methods,
-      event_value_in_stream_out_methods=event_value_in_stream_out_methods,
-      event_stream_in_value_out_methods=event_stream_in_value_out_methods,
-      event_stream_in_stream_out_methods=event_stream_in_stream_out_methods)
-
-
-class _ServiceAssembly(interfaces.Server):
-
-  def __init__(self, implementations, fore_link):
-    self._implementations = implementations
-    self._fore_link = fore_link
-    self._lock = threading.Lock()
-    self._pool = None
-    self._back = None
-
-  def _start(self):
-    with self._lock:
-      self._pool = logging_pool.pool(_THREAD_POOL_SIZE)
-      servicer = _servicer(self._implementations, self._pool)
-      self._back = tickets_implementations.back(
-          servicer, self._pool, self._pool, self._pool, _ONE_DAY_IN_SECONDS,
-          _ONE_DAY_IN_SECONDS)
-      self._fore_link.start()
-      self._fore_link.join_rear_link(self._back)
-      self._back.join_fore_link(self._fore_link)
-
-  def _stop(self):
-    with self._lock:
-      self._fore_link.stop()
-      base_utilities.wait_for_idle(self._back)
-      self._back = None
-      self._pool.shutdown(wait=True)
-      self._pool = None
-
-  def __enter__(self):
-    self._start()
-    return self
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    self._stop()
-    return False
-
-  def start(self):
-    return self._start()
-
-  def stop(self):
-    self._stop()
-
-  def port(self):
-    with self._lock:
-      return self._fore_link.port()
-
-
-def assemble_face_stub(activated_rear_link):
-  """Assembles a face_interfaces.Stub.
-
-  The returned object is a context manager and may only be used in context to
-  invoke RPCs.
-
-  Args:
-    activated_rear_link: An object that is both a tickets_interfaces.RearLink
-      and an activated.Activated. The object should be in the inactive state
-      when passed to this method.
-
-  Returns:
-    A face_interfaces.Stub on which, in context, RPCs can be invoked.
-  """
-  return _FaceStub(activated_rear_link)
-
-
-def assemble_dynamic_inline_stub(implementations, activated_rear_link):
-  """Assembles a stub with method names for attributes.
-
-  The returned object is a context manager and may only be used in context to
-  invoke RPCs.
-
-  The returned object, when used in context, will respond to attribute access
-  as follows: if the requested attribute is the name of a unary-unary RPC
-  method, the value of the attribute will be a
-  face_interfaces.UnaryUnarySyncAsync with which to invoke the RPC method. If
-  the requested attribute is the name of a unary-stream RPC method, the value
-  of the attribute will be a callable with the semantics of
-  face_interfaces.Stub.inline_value_in_stream_out, minus the "name" parameter,
-  with which to invoke the RPC method. If the requested attribute is the name
-  of a stream-unary RPC method, the value of the attribute will be a
-  face_interfaces.StreamUnarySyncAsync with which to invoke the RPC method. If
-  the requested attribute is the name of a stream-stream RPC method, the value
-  of the attribute will be a callable with the semantics of
-  face_interfaces.Stub.inline_stream_in_stream_out, minus the "name" parameter,
-  with which to invoke the RPC method.
-
-  Args:
-    implementations: A dictionary from RPC method name to
-      interfaces.MethodImplementation.
-    activated_rear_link: An object that is both a tickets_interfaces.RearLink
-      and an activated.Activated. The object should be in the inactive state
-      when passed to this method.
-
-  Returns:
-    A stub on which, in context, RPCs can be invoked.
-  """
-  return _DynamicInlineStub(implementations, activated_rear_link)
-
-
-def assemble_service(implementations, activated_fore_link):
-  """Assembles the service-side of the RPC Framework stack.
-
-  Args:
-    implementations: A dictionary from RPC method name to
-      interfaces.MethodImplementation.
-    activated_fore_link: An object that is both a tickets_interfaces.ForeLink
-      and an activated.Activated. The object should be in the inactive state
-      when passed to this method.
-
-  Returns:
-    An interfaces.Server encapsulating RPC service.
-  """
-  return _ServiceAssembly(implementations, activated_fore_link)
diff --git a/src/python/src/grpc/framework/assembly/implementations_test.py b/src/python/src/grpc/framework/assembly/implementations_test.py
deleted file mode 100644
index 74dc02e..0000000
--- a/src/python/src/grpc/framework/assembly/implementations_test.py
+++ /dev/null
@@ -1,284 +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.
-
-# TODO(nathaniel): Expand this test coverage.
-
-"""Test of the GRPC-backed ForeLink and RearLink."""
-
-import threading
-import unittest
-
-from grpc.framework.assembly import implementations
-from grpc.framework.assembly import utilities
-from grpc.framework.base import interfaces
-from grpc.framework.base.packets import packets as tickets
-from grpc.framework.base.packets import interfaces as tickets_interfaces
-from grpc.framework.base.packets import null
-from grpc.framework.foundation import logging_pool
-from grpc._junkdrawer import math_pb2
-
-DIV = 'Div'
-DIV_MANY = 'DivMany'
-FIB = 'Fib'
-SUM = 'Sum'
-
-def _fibbonacci(limit):
-  left, right = 0, 1
-  for _ in xrange(limit):
-    yield left
-    left, right = right, left + right
-
-
-def _div(request, unused_context):
-  return math_pb2.DivReply(
-      quotient=request.dividend / request.divisor,
-      remainder=request.dividend % request.divisor)
-
-
-def _div_many(request_iterator, unused_context):
-  for request in request_iterator:
-    yield math_pb2.DivReply(
-        quotient=request.dividend / request.divisor,
-        remainder=request.dividend % request.divisor)
-
-
-def _fib(request, unused_context):
-  for number in _fibbonacci(request.limit):
-    yield math_pb2.Num(num=number)
-
-
-def _sum(request_iterator, unused_context):
-  accumulation = 0
-  for request in request_iterator:
-    accumulation += request.num
-  return math_pb2.Num(num=accumulation)
-
-
-_IMPLEMENTATIONS = {
-    DIV: utilities.unary_unary_inline(_div),
-    DIV_MANY: utilities.stream_stream_inline(_div_many),
-    FIB: utilities.unary_stream_inline(_fib),
-    SUM: utilities.stream_unary_inline(_sum),
-}
-
-_TIMEOUT = 10
-
-
-class PipeLink(tickets_interfaces.ForeLink, tickets_interfaces.RearLink):
-
-  def __init__(self):
-    self._fore_lock = threading.Lock()
-    self._fore_link = null.NULL_FORE_LINK
-    self._rear_lock = threading.Lock()
-    self._rear_link = null.NULL_REAR_LINK
-
-  def __enter__(self):
-    return self
-
-  def __exit__(self, exc_type, exc_val, exc_tb):
-    return False
-
-  def start(self):
-    pass
-
-  def stop(self):
-    pass
-
-  def accept_back_to_front_ticket(self, ticket):
-    with self._fore_lock:
-      self._fore_link.accept_back_to_front_ticket(ticket)
-
-  def join_rear_link(self, rear_link):
-    with self._rear_lock:
-      self._rear_link = null.NULL_REAR_LINK if rear_link is None else rear_link
-
-  def accept_front_to_back_ticket(self, ticket):
-    with self._rear_lock:
-      self._rear_link.accept_front_to_back_ticket(ticket)
-
-  def join_fore_link(self, fore_link):
-    with self._fore_lock:
-      self._fore_link = null.NULL_FORE_LINK if fore_link is None else fore_link
-
-
-class FaceStubTest(unittest.TestCase):
-
-  def testUnaryUnary(self):
-    divisor = 7
-    dividend = 13
-    expected_quotient = 1
-    expected_remainder = 6
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    face_stub = implementations.assemble_face_stub(pipe)
-
-    service.start()
-    try:
-      with face_stub:
-        response = face_stub.blocking_value_in_value_out(
-            DIV, math_pb2.DivArgs(divisor=divisor, dividend=dividend),
-            _TIMEOUT)
-        self.assertEqual(expected_quotient, response.quotient)
-        self.assertEqual(expected_remainder, response.remainder)
-    finally:
-      service.stop()
-
-  def testUnaryStream(self):
-    stream_length = 29
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    face_stub = implementations.assemble_face_stub(pipe)
-
-    with service, face_stub:
-      responses = list(
-          face_stub.inline_value_in_stream_out(
-              FIB, math_pb2.FibArgs(limit=stream_length), _TIMEOUT))
-      numbers = [response.num for response in responses]
-      for early, middle, later in zip(numbers, numbers[1:], numbers[2:]):
-        self.assertEqual(early + middle, later)
-
-  def testStreamUnary(self):
-    stream_length = 13
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    face_stub = implementations.assemble_face_stub(pipe)
-
-    with service, face_stub:
-      sync_async = face_stub.stream_unary_sync_async(SUM)
-      response_future = sync_async.async(
-          (math_pb2.Num(num=index) for index in range(stream_length)),
-          _TIMEOUT)
-      self.assertEqual(
-          (stream_length * (stream_length - 1)) / 2,
-          response_future.result().num)
-
-  def testStreamStream(self):
-    stream_length = 17
-    divisor_offset = 7
-    dividend_offset = 17
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    face_stub = implementations.assemble_face_stub(pipe)
-
-    with service, face_stub:
-      response_iterator = face_stub.inline_stream_in_stream_out(
-          DIV_MANY,
-          (math_pb2.DivArgs(
-               divisor=divisor_offset + index,
-               dividend=dividend_offset + index)
-           for index in range(stream_length)),
-          _TIMEOUT)
-      for index, response in enumerate(response_iterator):
-        self.assertEqual(
-            (dividend_offset + index) / (divisor_offset + index),
-            response.quotient)
-        self.assertEqual(
-            (dividend_offset + index) % (divisor_offset + index),
-            response.remainder)
-      self.assertEqual(stream_length, index + 1)
-
-
-class DynamicInlineStubTest(unittest.TestCase):
-
-  def testUnaryUnary(self):
-    divisor = 59
-    dividend = 973
-    expected_quotient = dividend / divisor
-    expected_remainder = dividend % divisor
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    dynamic_stub = implementations.assemble_dynamic_inline_stub(
-        _IMPLEMENTATIONS, pipe)
-
-    service.start()
-    with dynamic_stub:
-      response = dynamic_stub.Div(
-          math_pb2.DivArgs(divisor=divisor, dividend=dividend), _TIMEOUT)
-      self.assertEqual(expected_quotient, response.quotient)
-      self.assertEqual(expected_remainder, response.remainder)
-    service.stop()
-
-  def testUnaryStream(self):
-    stream_length = 43
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    dynamic_stub = implementations.assemble_dynamic_inline_stub(
-        _IMPLEMENTATIONS, pipe)
-
-    with service, dynamic_stub:
-      response_iterator = dynamic_stub.Fib(
-          math_pb2.FibArgs(limit=stream_length), _TIMEOUT)
-      numbers = tuple(response.num for response in response_iterator)
-      for early, middle, later in zip(numbers, numbers[:1], numbers[:2]):
-        self.assertEqual(early + middle, later)
-      self.assertEqual(stream_length, len(numbers))
-
-  def testStreamUnary(self):
-    stream_length = 127
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    dynamic_stub = implementations.assemble_dynamic_inline_stub(
-        _IMPLEMENTATIONS, pipe)
-
-    with service, dynamic_stub:
-      response_future = dynamic_stub.Sum.async(
-          (math_pb2.Num(num=index) for index in range(stream_length)),
-          _TIMEOUT)
-      self.assertEqual(
-          (stream_length * (stream_length - 1)) / 2,
-          response_future.result().num)
-
-  def testStreamStream(self):
-    stream_length = 179
-    divisor_offset = 71
-    dividend_offset = 1763
-    pipe = PipeLink()
-    service = implementations.assemble_service(_IMPLEMENTATIONS, pipe)
-    dynamic_stub = implementations.assemble_dynamic_inline_stub(
-        _IMPLEMENTATIONS, pipe)
-
-    with service, dynamic_stub:
-      response_iterator = dynamic_stub.DivMany(
-          (math_pb2.DivArgs(
-               divisor=divisor_offset + index,
-               dividend=dividend_offset + index)
-           for index in range(stream_length)),
-          _TIMEOUT)
-      for index, response in enumerate(response_iterator):
-        self.assertEqual(
-            (dividend_offset + index) / (divisor_offset + index),
-            response.quotient)
-        self.assertEqual(
-            (dividend_offset + index) % (divisor_offset + index),
-            response.remainder)
-      self.assertEqual(stream_length, index + 1)
-
-
-if __name__ == '__main__':
-  unittest.main()
diff --git a/src/python/src/grpc/framework/assembly/interfaces.py b/src/python/src/grpc/framework/assembly/interfaces.py
deleted file mode 100644
index d1a6aad..0000000
--- a/src/python/src/grpc/framework/assembly/interfaces.py
+++ /dev/null
@@ -1,114 +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.
-
-# TODO(nathaniel): The assembly layer only exists to smooth out wrinkles in
-# the face layer. The two should be squashed together as soon as manageable.
-"""Interfaces for assembling RPC Framework values."""
-
-import abc
-
-# cardinality, style, and stream are referenced from specification in this
-# module.
-from grpc.framework.common import cardinality  # pylint: disable=unused-import
-from grpc.framework.common import style  # pylint: disable=unused-import
-from grpc.framework.foundation import activated
-from grpc.framework.foundation import stream  # pylint: disable=unused-import
-
-
-class MethodImplementation(object):
-  """A sum type that describes an RPC method implementation.
-
-  Attributes:
-    cardinality: A cardinality.Cardinality value.
-    style: A style.Service value.
-    unary_unary_inline: The implementation of the RPC method as a callable
-      value that takes a request value and a face_interfaces.RpcContext object
-      and returns a response value. Only non-None if cardinality is
-      cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE.
-    unary_stream_inline: The implementation of the RPC method as a callable
-      value that takes a request value and a face_interfaces.RpcContext object
-      and returns an iterator of response values. Only non-None if cardinality
-      is cardinality.Cardinality.UNARY_STREAM and style is
-      style.Service.INLINE.
-    stream_unary_inline: The implementation of the RPC method as a callable
-      value that takes an iterator of request values and a
-      face_interfaces.RpcContext object and returns a response value. Only
-      non-None if cardinality is cardinality.Cardinality.STREAM_UNARY and style
-      is style.Service.INLINE.
-    stream_stream_inline: The implementation of the RPC method as a callable
-      value that takes an iterator of request values and a
-      face_interfaces.RpcContext object and returns an iterator of response
-      values. Only non-None if cardinality is
-      cardinality.Cardinality.STREAM_STREAM and style is style.Service.INLINE.
-    unary_unary_event: The implementation of the RPC method as a callable value
-      that takes a request value, a response callback to which to pass the
-      response value of the RPC, and a face_interfaces.RpcContext. Only
-      non-None if cardinality is cardinality.Cardinality.UNARY_UNARY and style
-      is style.Service.EVENT.
-    unary_stream_event: The implementation of the RPC method as a callable
-      value that takes a request value, a stream.Consumer to which to pass the
-      the response values of the RPC, and a face_interfaces.RpcContext. Only
-      non-None if cardinality is cardinality.Cardinality.UNARY_STREAM and style
-      is style.Service.EVENT.
-    stream_unary_event: The implementation of the RPC method as a callable
-      value that takes a response callback to which to pass the response value
-      of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer
-      to which the request values of the RPC should be passed. Only non-None if
-      cardinality is cardinality.Cardinality.STREAM_UNARY and style is
-      style.Service.EVENT.
-    stream_stream_event: The implementation of the RPC method as a callable
-      value that takes a stream.Consumer to which to pass the response values
-      of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer
-      to which the request values of the RPC should be passed. Only non-None if
-      cardinality is cardinality.Cardinality.STREAM_STREAM and style is
-      style.Service.EVENT.
-  """
-  __metaclass__ = abc.ABCMeta
-
-
-class Server(activated.Activated):
-  """The server interface.
-
-  Aside from being able to be activated and deactivated, objects of this type
-  are able to report the port on which they are servicing RPCs.
-  """
-  __metaclass__ = abc.ABCMeta
-
-  # TODO(issue 726): This is an abstraction violation; not every Server is
-  # necessarily serving over a network at all.
-  @abc.abstractmethod
-  def port(self):
-    """Identifies the port on which this Server is servicing RPCs.
-
-    This method may only be called while the server is active.
-
-    Returns:
-      The number of the port on which this Server is servicing RPCs.
-    """
-    raise NotImplementedError()
diff --git a/src/python/src/grpc/framework/assembly/utilities.py b/src/python/src/grpc/framework/assembly/utilities.py
deleted file mode 100644
index 80e7f59..0000000
--- a/src/python/src/grpc/framework/assembly/utilities.py
+++ /dev/null
@@ -1,179 +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.
-
-"""Utilities for assembling RPC framework values."""
-
-import collections
-
-from grpc.framework.assembly import interfaces
-from grpc.framework.common import cardinality
-from grpc.framework.common import style
-from grpc.framework.face import interfaces as face_interfaces
-from grpc.framework.foundation import stream
-
-
-class _MethodImplementation(
-    interfaces.MethodImplementation,
-    collections.namedtuple(
-        '_MethodImplementation',
-        ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline',
-         'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event',
-         'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])):
-  pass
-
-
-def unary_unary_inline(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a unary-unary RPC method as a callable value
-      that takes a request value and a face_interfaces.RpcContext object and
-      returns a response value.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior,
-      None, None, None, None, None, None, None)
-
-
-def unary_stream_inline(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a unary-stream RPC method as a callable
-      value that takes a request value and a face_interfaces.RpcContext object
-      and returns an iterator of response values.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None,
-      behavior, None, None, None, None, None, None)
-
-
-def stream_unary_inline(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a stream-unary RPC method as a callable
-      value that takes an iterator of request values and a
-      face_interfaces.RpcContext object and returns a response value.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None,
-      behavior, None, None, None, None, None)
-
-
-def stream_stream_inline(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a stream-stream RPC method as a callable
-      value that takes an iterator of request values and a
-      face_interfaces.RpcContext object and returns an iterator of response
-      values.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None,
-      None, behavior, None, None, None, None)
-
-
-def unary_unary_event(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a unary-unary RPC method as a callable
-      value that takes a request value, a response callback to which to pass
-      the response value of the RPC, and a face_interfaces.RpcContext.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None,
-      None, None, behavior, None, None, None)
-
-
-def unary_stream_event(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a unary-stream RPC method as a callable
-      value that takes a request value, a stream.Consumer to which to pass the
-      the response values of the RPC, and a face_interfaces.RpcContext.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None,
-      None, None, None, behavior, None, None)
-
-
-def stream_unary_event(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a stream-unary RPC method as a callable
-      value that takes a response callback to which to pass the response value
-      of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer
-      to which the request values of the RPC should be passed.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None,
-      None, None, None, None, behavior, None)
-
-
-def stream_stream_event(behavior):
-  """Creates an interfaces.MethodImplementation for the given behavior.
-
-  Args:
-    behavior: The implementation of a stream-stream RPC method as a callable
-      value that takes a stream.Consumer to which to pass the response values
-      of the RPC and a face_interfaces.RpcContext and returns a stream.Consumer
-      to which the request values of the RPC should be passed.
-
-  Returns:
-    An interfaces.MethodImplementation derived from the given behavior.
-  """
-  return _MethodImplementation(
-      cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None,
-      None, None, None, None, None, behavior)
diff --git a/src/python/src/grpc/framework/face/_service.py b/src/python/src/grpc/framework/face/_service.py
index 26bde12..cdf4133 100644
--- a/src/python/src/grpc/framework/face/_service.py
+++ b/src/python/src/grpc/framework/face/_service.py
@@ -105,15 +105,14 @@
   def adaptation(response_consumer, operation_context):
     rpc_context = _control.RpcContext(operation_context)
     return stream_util.TransformingConsumer(
-        lambda request: method.service(request, rpc_context), response_consumer)
+        lambda request: method(request, rpc_context), response_consumer)
   return adaptation
 
 
 def adapt_inline_value_in_stream_out(method):
   def adaptation(response_consumer, operation_context):
     rpc_context = _control.RpcContext(operation_context)
-    return _ValueInStreamOutConsumer(
-        method.service, rpc_context, response_consumer)
+    return _ValueInStreamOutConsumer(method, rpc_context, response_consumer)
   return adaptation
 
 
@@ -123,7 +122,7 @@
     operation_context.add_termination_callback(rendezvous.set_outcome)
     def in_pool_thread():
       response_consumer.consume_and_terminate(
-          method.service(rendezvous, _control.RpcContext(operation_context)))
+          method(rendezvous, _control.RpcContext(operation_context)))
     pool.submit(_pool_wrap(in_pool_thread, operation_context))
     return rendezvous
   return adaptation
@@ -149,7 +148,7 @@
     operation_context.add_termination_callback(rendezvous.set_outcome)
     def in_pool_thread():
       _control.pipe_iterator_to_consumer(
-          method.service(rendezvous, _control.RpcContext(operation_context)),
+          method(rendezvous, _control.RpcContext(operation_context)),
           response_consumer, operation_context.is_active, True)
     pool.submit(_pool_wrap(in_pool_thread, operation_context))
     return rendezvous
@@ -159,7 +158,7 @@
 def adapt_event_value_in_value_out(method):
   def adaptation(response_consumer, operation_context):
     def on_payload(payload):
-      method.service(
+      method(
           payload, response_consumer.consume_and_terminate,
           _control.RpcContext(operation_context))
     return _control.UnaryConsumer(on_payload)
@@ -169,7 +168,7 @@
 def adapt_event_value_in_stream_out(method):
   def adaptation(response_consumer, operation_context):
     def on_payload(payload):
-      method.service(
+      method(
           payload, response_consumer, _control.RpcContext(operation_context))
     return _control.UnaryConsumer(on_payload)
   return adaptation
@@ -178,12 +177,11 @@
 def adapt_event_stream_in_value_out(method):
   def adaptation(response_consumer, operation_context):
     rpc_context = _control.RpcContext(operation_context)
-    return method.service(response_consumer.consume_and_terminate, rpc_context)
+    return method(response_consumer.consume_and_terminate, rpc_context)
   return adaptation
 
 
 def adapt_event_stream_in_stream_out(method):
   def adaptation(response_consumer, operation_context):
-    return method.service(
-        response_consumer, _control.RpcContext(operation_context))
+    return method(response_consumer, _control.RpcContext(operation_context))
   return adaptation
diff --git a/src/python/src/grpc/framework/face/_test_case.py b/src/python/src/grpc/framework/face/_test_case.py
index a4e17c4..b3a012d 100644
--- a/src/python/src/grpc/framework/face/_test_case.py
+++ b/src/python/src/grpc/framework/face/_test_case.py
@@ -42,37 +42,17 @@
   """Provides abstract Face-layer tests an in-memory implementation."""
 
   def set_up_implementation(
-      self,
-      name,
-      methods,
-      inline_value_in_value_out_methods,
-      inline_value_in_stream_out_methods,
-      inline_stream_in_value_out_methods,
-      inline_stream_in_stream_out_methods,
-      event_value_in_value_out_methods,
-      event_value_in_stream_out_methods,
-      event_stream_in_value_out_methods,
-      event_stream_in_stream_out_methods,
-      multi_method):
+      self, name, methods, method_implementations,
+      multi_method_implementation):
     servicer_pool = logging_pool.pool(_MAXIMUM_POOL_SIZE)
     stub_pool = logging_pool.pool(_MAXIMUM_POOL_SIZE)
 
     servicer = implementations.servicer(
-        servicer_pool,
-        inline_value_in_value_out_methods=inline_value_in_value_out_methods,
-        inline_value_in_stream_out_methods=inline_value_in_stream_out_methods,
-        inline_stream_in_value_out_methods=inline_stream_in_value_out_methods,
-        inline_stream_in_stream_out_methods=inline_stream_in_stream_out_methods,
-        event_value_in_value_out_methods=event_value_in_value_out_methods,
-        event_value_in_stream_out_methods=event_value_in_stream_out_methods,
-        event_stream_in_value_out_methods=event_stream_in_value_out_methods,
-        event_stream_in_stream_out_methods=event_stream_in_stream_out_methods,
-        multi_method=multi_method)
+        servicer_pool, method_implementations, multi_method_implementation)
 
     linked_pair = base_util.linked_pair(servicer, _TIMEOUT)
-    server = implementations.server()
-    stub = implementations.stub(linked_pair.front, stub_pool)
-    return server, stub, (servicer_pool, stub_pool, linked_pair)
+    stub = implementations.generic_stub(linked_pair.front, stub_pool)
+    return stub, (servicer_pool, stub_pool, linked_pair)
 
   def tear_down_implementation(self, memo):
     servicer_pool, stub_pool, linked_pair = memo
diff --git a/src/python/src/grpc/framework/face/implementations.py b/src/python/src/grpc/framework/face/implementations.py
index 86948b3..4a6de52 100644
--- a/src/python/src/grpc/framework/face/implementations.py
+++ b/src/python/src/grpc/framework/face/implementations.py
@@ -29,6 +29,8 @@
 
 """Entry points into the Face layer of RPC Framework."""
 
+from grpc.framework.common import cardinality
+from grpc.framework.common import style
 from grpc.framework.base import exceptions as _base_exceptions
 from grpc.framework.base import interfaces as base_interfaces
 from grpc.framework.face import _calls
@@ -56,7 +58,7 @@
       raise _base_exceptions.NoSuchMethodError()
 
 
-class _UnaryUnarySyncAsync(interfaces.UnaryUnarySyncAsync):
+class _UnaryUnaryMultiCallable(interfaces.UnaryUnaryMultiCallable):
 
   def __init__(self, front, name):
     self._front = front
@@ -66,12 +68,33 @@
     return _calls.blocking_value_in_value_out(
         self._front, self._name, request, timeout, 'unused trace ID')
 
-  def async(self, request, timeout):
+  def future(self, request, timeout):
     return _calls.future_value_in_value_out(
         self._front, self._name, request, timeout, 'unused trace ID')
 
+  def event(self, request, response_callback, abortion_callback, timeout):
+    return _calls.event_value_in_value_out(
+        self._front, self._name, request, response_callback, abortion_callback,
+        timeout, 'unused trace ID')
 
-class _StreamUnarySyncAsync(interfaces.StreamUnarySyncAsync):
+
+class _UnaryStreamMultiCallable(interfaces.UnaryStreamMultiCallable):
+
+  def __init__(self, front, name):
+    self._front = front
+    self._name = name
+
+  def __call__(self, request, timeout):
+    return _calls.inline_value_in_stream_out(
+        self._front, self._name, request, timeout, 'unused trace ID')
+
+  def event(self, request, response_consumer, abortion_callback, timeout):
+    return _calls.event_value_in_stream_out(
+        self._front, self._name, request, response_consumer, abortion_callback,
+        timeout, 'unused trace ID')
+
+
+class _StreamUnaryMultiCallable(interfaces.StreamUnaryMultiCallable):
 
   def __init__(self, front, name, pool):
     self._front = front
@@ -82,18 +105,37 @@
     return _calls.blocking_stream_in_value_out(
         self._front, self._name, request_iterator, timeout, 'unused trace ID')
 
-  def async(self, request_iterator, timeout):
+  def future(self, request_iterator, timeout):
     return _calls.future_stream_in_value_out(
         self._front, self._name, request_iterator, timeout, 'unused trace ID',
         self._pool)
 
-
-class _Server(interfaces.Server):
-  """An interfaces.Server implementation."""
+  def event(self, response_callback, abortion_callback, timeout):
+    return _calls.event_stream_in_value_out(
+        self._front, self._name, response_callback, abortion_callback, timeout,
+        'unused trace ID')
 
 
-class _Stub(interfaces.Stub):
-  """An interfaces.Stub implementation."""
+class _StreamStreamMultiCallable(interfaces.StreamStreamMultiCallable):
+
+  def __init__(self, front, name, pool):
+    self._front = front
+    self._name = name
+    self._pool = pool
+
+  def __call__(self, request_iterator, timeout):
+    return _calls.inline_stream_in_stream_out(
+        self._front, self._name, request_iterator, timeout, 'unused trace ID',
+        self._pool)
+
+  def event(self, response_consumer, abortion_callback, timeout):
+    return _calls.event_stream_in_stream_out(
+        self._front, self._name, response_consumer, abortion_callback, timeout,
+        'unused trace ID')
+
+
+class _GenericStub(interfaces.GenericStub):
+  """An interfaces.GenericStub implementation."""
 
   def __init__(self, front, pool):
     self._front = front
@@ -149,136 +191,128 @@
         self._front, name, response_consumer, abortion_callback, timeout,
         'unused trace ID')
 
-  def unary_unary_sync_async(self, name):
-    return _UnaryUnarySyncAsync(self._front, name)
+  def unary_unary_multi_callable(self, name):
+    return _UnaryUnaryMultiCallable(self._front, name)
 
-  def stream_unary_sync_async(self, name):
-    return _StreamUnarySyncAsync(self._front, name, self._pool)
+  def unary_stream_multi_callable(self, name):
+    return _UnaryStreamMultiCallable(self._front, name)
+
+  def stream_unary_multi_callable(self, name):
+    return _StreamUnaryMultiCallable(self._front, name, self._pool)
+
+  def stream_stream_multi_callable(self, name):
+    return _StreamStreamMultiCallable(self._front, name, self._pool)
 
 
-def _aggregate_methods(
-    pool,
-    inline_value_in_value_out_methods,
-    inline_value_in_stream_out_methods,
-    inline_stream_in_value_out_methods,
-    inline_stream_in_stream_out_methods,
-    event_value_in_value_out_methods,
-    event_value_in_stream_out_methods,
-    event_stream_in_value_out_methods,
-    event_stream_in_stream_out_methods):
-  """Aggregates methods coded in according to different interfaces."""
-  methods = {}
+class _DynamicStub(interfaces.DynamicStub):
+  """An interfaces.DynamicStub implementation."""
 
-  def adapt_unpooled_methods(adapted_methods, unadapted_methods, adaptation):
-    if unadapted_methods is not None:
-      for name, unadapted_method in unadapted_methods.iteritems():
-        adapted_methods[name] = adaptation(unadapted_method)
+  def __init__(self, cardinalities, front, pool):
+    self._cardinalities = cardinalities
+    self._front = front
+    self._pool = pool
 
-  def adapt_pooled_methods(adapted_methods, unadapted_methods, adaptation):
-    if unadapted_methods is not None:
-      for name, unadapted_method in unadapted_methods.iteritems():
-        adapted_methods[name] = adaptation(unadapted_method, pool)
-
-  adapt_unpooled_methods(
-      methods, inline_value_in_value_out_methods,
-      _service.adapt_inline_value_in_value_out)
-  adapt_unpooled_methods(
-      methods, inline_value_in_stream_out_methods,
-      _service.adapt_inline_value_in_stream_out)
-  adapt_pooled_methods(
-      methods, inline_stream_in_value_out_methods,
-      _service.adapt_inline_stream_in_value_out)
-  adapt_pooled_methods(
-      methods, inline_stream_in_stream_out_methods,
-      _service.adapt_inline_stream_in_stream_out)
-  adapt_unpooled_methods(
-      methods, event_value_in_value_out_methods,
-      _service.adapt_event_value_in_value_out)
-  adapt_unpooled_methods(
-      methods, event_value_in_stream_out_methods,
-      _service.adapt_event_value_in_stream_out)
-  adapt_unpooled_methods(
-      methods, event_stream_in_value_out_methods,
-      _service.adapt_event_stream_in_value_out)
-  adapt_unpooled_methods(
-      methods, event_stream_in_stream_out_methods,
-      _service.adapt_event_stream_in_stream_out)
-
-  return methods
+  def __getattr__(self, attr):
+    method_cardinality = self._cardinalities.get(attr)
+    if method_cardinality is cardinality.Cardinality.UNARY_UNARY:
+      return _UnaryUnaryMultiCallable(self._front, attr)
+    elif method_cardinality is cardinality.Cardinality.UNARY_STREAM:
+      return _UnaryStreamMultiCallable(self._front, attr)
+    elif method_cardinality is cardinality.Cardinality.STREAM_UNARY:
+      return _StreamUnaryMultiCallable(self._front, attr, self._pool)
+    elif method_cardinality is cardinality.Cardinality.STREAM_STREAM:
+      return _StreamStreamMultiCallable(self._front, attr, self._pool)
+    else:
+      raise AttributeError('_DynamicStub object has no attribute "%s"!' % attr)
 
 
-def servicer(
-    pool,
-    inline_value_in_value_out_methods=None,
-    inline_value_in_stream_out_methods=None,
-    inline_stream_in_value_out_methods=None,
-    inline_stream_in_stream_out_methods=None,
-    event_value_in_value_out_methods=None,
-    event_value_in_stream_out_methods=None,
-    event_stream_in_value_out_methods=None,
-    event_stream_in_stream_out_methods=None,
-    multi_method=None):
+def _adapt_method_implementations(method_implementations, pool):
+  adapted_implementations = {}
+  for name, method_implementation in method_implementations.iteritems():
+    if method_implementation.style is style.Service.INLINE:
+      if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY:
+        adapted_implementations[name] = _service.adapt_inline_value_in_value_out(
+            method_implementation.unary_unary_inline)
+      elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM:
+        adapted_implementations[name] = _service.adapt_inline_value_in_stream_out(
+            method_implementation.unary_stream_inline)
+      elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY:
+        adapted_implementations[name] = _service.adapt_inline_stream_in_value_out(
+            method_implementation.stream_unary_inline, pool)
+      elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM:
+        adapted_implementations[name] = _service.adapt_inline_stream_in_stream_out(
+            method_implementation.stream_stream_inline, pool)
+    elif method_implementation.style is style.Service.EVENT:
+      if method_implementation.cardinality is cardinality.Cardinality.UNARY_UNARY:
+        adapted_implementations[name] = _service.adapt_event_value_in_value_out(
+            method_implementation.unary_unary_event)
+      elif method_implementation.cardinality is cardinality.Cardinality.UNARY_STREAM:
+        adapted_implementations[name] = _service.adapt_event_value_in_stream_out(
+            method_implementation.unary_stream_event)
+      elif method_implementation.cardinality is cardinality.Cardinality.STREAM_UNARY:
+        adapted_implementations[name] = _service.adapt_event_stream_in_value_out(
+            method_implementation.stream_unary_event)
+      elif method_implementation.cardinality is cardinality.Cardinality.STREAM_STREAM:
+        adapted_implementations[name] = _service.adapt_event_stream_in_stream_out(
+            method_implementation.stream_stream_event)
+  return adapted_implementations
+
+
+def servicer(pool, method_implementations, multi_method_implementation):
   """Creates a base_interfaces.Servicer.
 
-  The key sets of the passed dictionaries must be disjoint. It is guaranteed
-  that any passed MultiMethod implementation will only be called to service an
-  RPC if the RPC method name is not present in the key sets of the passed
-  dictionaries.
+  It is guaranteed that any passed interfaces.MultiMethodImplementation will
+  only be called to service an RPC if there is no
+  interfaces.MethodImplementation for the RPC method in the passed
+  method_implementations dictionary.
 
   Args:
     pool: A thread pool.
-    inline_value_in_value_out_methods: A dictionary mapping method names to
-      interfaces.InlineValueInValueOutMethod implementations.
-    inline_value_in_stream_out_methods: A dictionary mapping method names to
-      interfaces.InlineValueInStreamOutMethod implementations.
-    inline_stream_in_value_out_methods: A dictionary mapping method names to
-      interfaces.InlineStreamInValueOutMethod implementations.
-    inline_stream_in_stream_out_methods: A dictionary mapping method names to
-      interfaces.InlineStreamInStreamOutMethod implementations.
-    event_value_in_value_out_methods: A dictionary mapping method names to
-      interfaces.EventValueInValueOutMethod implementations.
-    event_value_in_stream_out_methods: A dictionary mapping method names to
-      interfaces.EventValueInStreamOutMethod implementations.
-    event_stream_in_value_out_methods: A dictionary mapping method names to
-      interfaces.EventStreamInValueOutMethod implementations.
-    event_stream_in_stream_out_methods: A dictionary mapping method names to
-      interfaces.EventStreamInStreamOutMethod implementations.
-    multi_method: An implementation of interfaces.MultiMethod.
+    method_implementations: A dictionary from RPC method name to
+      interfaces.MethodImplementation object to be used to service the named
+      RPC method.
+    multi_method_implementation: An interfaces.MultiMethodImplementation to be
+      used to service any RPCs not serviced by the
+      interfaces.MethodImplementations given in the method_implementations
+      dictionary, or None.
 
   Returns:
     A base_interfaces.Servicer that services RPCs via the given implementations.
   """
-  methods = _aggregate_methods(
-      pool,
-      inline_value_in_value_out_methods,
-      inline_value_in_stream_out_methods,
-      inline_stream_in_value_out_methods,
-      inline_stream_in_stream_out_methods,
-      event_value_in_value_out_methods,
-      event_value_in_stream_out_methods,
-      event_stream_in_value_out_methods,
-      event_stream_in_stream_out_methods)
-
-  return _BaseServicer(methods, multi_method)
+  adapted_implementations = _adapt_method_implementations(
+      method_implementations, pool)
+  return _BaseServicer(adapted_implementations, multi_method_implementation)
 
 
-def server():
-  """Creates an interfaces.Server.
-
-  Returns:
-    An interfaces.Server.
-  """
-  return _Server()
-
-
-def stub(front, pool):
-  """Creates an interfaces.Stub.
+def generic_stub(front, pool):
+  """Creates an interfaces.GenericStub.
 
   Args:
     front: A base_interfaces.Front.
     pool: A futures.ThreadPoolExecutor.
 
   Returns:
-    An interfaces.Stub that performs RPCs via the given base_interfaces.Front.
+    An interfaces.GenericStub that performs RPCs via the given
+      base_interfaces.Front.
   """
-  return _Stub(front, pool)
+  return _GenericStub(front, pool)
+
+
+def dynamic_stub(cardinalities, front, pool, prefix):
+  """Creates an interfaces.DynamicStub.
+
+  Args:
+    cardinalities: A dict from RPC method name to cardinality.Cardinality
+      value identifying the cardinality of every RPC method to be supported by
+      the created interfaces.DynamicStub.
+    front: A base_interfaces.Front.
+    pool: A futures.ThreadPoolExecutor.
+    prefix: A string to prepend when mapping requested attribute name to RPC
+      method name during attribute access on the created
+      interfaces.DynamicStub.
+
+  Returns:
+    An interfaces.DynamicStub that performs RPCs via the given
+      base_interfaces.Front.
+  """
+  return _DynamicStub(cardinalities, front, pool)
diff --git a/src/python/src/grpc/framework/face/interfaces.py b/src/python/src/grpc/framework/face/interfaces.py
index 9e19106..b7cc4c1 100644
--- a/src/python/src/grpc/framework/face/interfaces.py
+++ b/src/python/src/grpc/framework/face/interfaces.py
@@ -32,11 +32,24 @@
 import abc
 import enum
 
-# exceptions, abandonment, and future are referenced from specification in this
-# module.
+# cardinality, style, exceptions, abandonment, future, and stream are
+# referenced from specification in this module.
+from grpc.framework.common import cardinality  # pylint: disable=unused-import
+from grpc.framework.common import style  # pylint: disable=unused-import
 from grpc.framework.face import exceptions  # pylint: disable=unused-import
 from grpc.framework.foundation import abandonment  # pylint: disable=unused-import
 from grpc.framework.foundation import future  # pylint: disable=unused-import
+from grpc.framework.foundation import stream  # pylint: disable=unused-import
+
+
+@enum.unique
+class Abortion(enum.Enum):
+  """Categories of RPC abortion."""
+  CANCELLED = 'cancelled'
+  EXPIRED = 'expired'
+  NETWORK_FAILURE = 'network failure'
+  SERVICED_FAILURE = 'serviced failure'
+  SERVICER_FAILURE = 'servicer failure'
 
 
 class CancellableIterator(object):
@@ -59,107 +72,6 @@
     raise NotImplementedError()
 
 
-class UnaryUnarySyncAsync(object):
-  """Affords invoking a unary-unary RPC synchronously or asynchronously.
-
-  Values implementing this interface are directly callable and present an
-  "async" method. Both calls take a request value and a numeric timeout.
-  Direct invocation of a value of this type invokes its associated RPC and
-  blocks until the RPC's response is available. Calling the "async" method
-  of a value of this type invokes its associated RPC and immediately returns a
-  future.Future bound to the asynchronous execution of the RPC.
-  """
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def __call__(self, request, timeout):
-    """Synchronously invokes the underlying RPC.
-
-    Args:
-      request: The request value for the RPC.
-      timeout: A duration of time in seconds to allow for the RPC.
-
-    Returns:
-      The response value for the RPC.
-
-    Raises:
-      exceptions.RpcError: Indicating that the RPC was aborted.
-    """
-    raise NotImplementedError()
-
-  @abc.abstractmethod
-  def async(self, request, timeout):
-    """Asynchronously invokes the underlying RPC.
-
-    Args:
-      request: The request value for the RPC.
-      timeout: A duration of time in seconds to allow for the RPC.
-
-    Returns:
-      A future.Future representing the RPC. In the event of RPC completion, the
-        returned Future's result value will be the response value of the RPC.
-        In the event of RPC abortion, the returned Future's exception value
-        will be an exceptions.RpcError.
-    """
-    raise NotImplementedError()
-
-
-class StreamUnarySyncAsync(object):
-  """Affords invoking a stream-unary RPC synchronously or asynchronously.
-
-  Values implementing this interface are directly callable and present an
-  "async" method. Both calls take an iterator of request values and a numeric
-  timeout. Direct invocation of a value of this type invokes its associated RPC
-  and blocks until the RPC's response is available. Calling the "async" method
-  of a value of this type invokes its associated RPC and immediately returns a
-  future.Future bound to the asynchronous execution of the RPC.
-  """
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def __call__(self, request_iterator, timeout):
-    """Synchronously invokes the underlying RPC.
-
-    Args:
-      request_iterator: An iterator that yields request values for the RPC.
-      timeout: A duration of time in seconds to allow for the RPC.
-
-    Returns:
-      The response value for the RPC.
-
-    Raises:
-      exceptions.RpcError: Indicating that the RPC was aborted.
-    """
-    raise NotImplementedError()
-
-  @abc.abstractmethod
-  def async(self, request, timeout):
-    """Asynchronously invokes the underlying RPC.
-
-    Args:
-      request_iterator: An iterator that yields request values for the RPC.
-      timeout: A duration of time in seconds to allow for the RPC.
-
-    Returns:
-      A future.Future representing the RPC. In the event of RPC completion, the
-        returned Future's result value will be the response value of the RPC.
-        In the event of RPC abortion, the returned Future's exception value
-        will be an exceptions.RpcError.
-    """
-    raise NotImplementedError()
-
-
-@enum.unique
-class Abortion(enum.Enum):
-  """Categories of RPC abortion."""
-
-  CANCELLED = 'cancelled'
-  EXPIRED = 'expired'
-  NETWORK_FAILURE = 'network failure'
-  SERVICED_FAILURE = 'serviced failure'
-  SERVICER_FAILURE = 'servicer failure'
-
-
 class RpcContext(object):
   """Provides RPC-related information and action."""
   __metaclass__ = abc.ABCMeta
@@ -191,205 +103,254 @@
     raise NotImplementedError()
 
 
-class InlineValueInValueOutMethod(object):
-  """A type for inline unary-request-unary-response RPC methods."""
+class Call(object):
+  """Invocation-side representation of an RPC.
+
+  Attributes:
+    context: An RpcContext affording information about the RPC.
+  """
   __metaclass__ = abc.ABCMeta
 
   @abc.abstractmethod
-  def service(self, request, context):
-    """Services an RPC that accepts one value and produces one value.
+  def cancel(self):
+    """Requests cancellation of the RPC."""
+    raise NotImplementedError()
+
+
+class UnaryUnaryMultiCallable(object):
+  """Affords invoking a unary-unary RPC in any call style."""
+  __metaclass__ = abc.ABCMeta
+
+  @abc.abstractmethod
+  def __call__(self, request, timeout):
+    """Synchronously invokes the underlying RPC.
 
     Args:
-      request: The single request value for the RPC.
-      context: An RpcContext object.
+      request: The request value for the RPC.
+      timeout: A duration of time in seconds to allow for the RPC.
 
     Returns:
-      The single response value for the RPC.
+      The response value for the RPC.
 
     Raises:
-      abandonment.Abandoned: If no response is necessary because the RPC has
-        been aborted.
+      exceptions.RpcError: Indicating that the RPC was aborted.
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def future(self, request, timeout):
+    """Asynchronously invokes the underlying RPC.
+
+    Args:
+      request: The request value for the RPC.
+      timeout: A duration of time in seconds to allow for the RPC.
+
+    Returns:
+      A future.Future representing the RPC. In the event of RPC completion, the
+        returned Future's result value will be the response value of the RPC.
+        In the event of RPC abortion, the returned Future's exception value
+        will be an exceptions.RpcError.
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def event(self, request, response_callback, abortion_callback, timeout):
+    """Asynchronously invokes the underlying RPC.
+
+    Args:
+      request: The request value for the RPC.
+      response_callback: A callback to be called to accept the restponse value
+        of the RPC.
+      abortion_callback: A callback to be called and passed an Abortion value
+        in the event of RPC abortion.
+      timeout: A duration of time in seconds to allow for the RPC.
+
+    Returns:
+      A Call object for the RPC.
     """
     raise NotImplementedError()
 
 
-class InlineValueInStreamOutMethod(object):
-  """A type for inline unary-request-stream-response RPC methods."""
+class UnaryStreamMultiCallable(object):
+  """Affords invoking a unary-stream RPC in any call style."""
   __metaclass__ = abc.ABCMeta
 
   @abc.abstractmethod
-  def service(self, request, context):
-    """Services an RPC that accepts one value and produces a stream of values.
+  def __call__(self, request, timeout):
+    """Synchronously invokes the underlying RPC.
 
     Args:
-      request: The single request value for the RPC.
-      context: An RpcContext object.
+      request: The request value for the RPC.
+      timeout: A duration of time in seconds to allow for the RPC.
 
-    Yields:
-      The values that comprise the response stream of the RPC.
-
-    Raises:
-      abandonment.Abandoned: If completing the response stream is not necessary
-        because the RPC has been aborted.
+    Returns:
+      A CancellableIterator that yields the response values of the RPC and
+        affords RPC cancellation. Drawing response values from the returned
+        CancellableIterator may raise exceptions.RpcError indicating abortion
+        of the RPC.
     """
     raise NotImplementedError()
 
-
-class InlineStreamInValueOutMethod(object):
-  """A type for inline stream-request-unary-response RPC methods."""
-  __metaclass__ = abc.ABCMeta
-
   @abc.abstractmethod
-  def service(self, request_iterator, context):
-    """Services an RPC that accepts a stream of values and produces one value.
+  def event(self, request, response_consumer, abortion_callback, timeout):
+    """Asynchronously invokes the underlying RPC.
 
     Args:
-      request_iterator: An iterator that yields the request values of the RPC.
-        Drawing values from this iterator may also raise exceptions.RpcError to
-        indicate abortion of the RPC.
-      context: An RpcContext object.
-
-    Yields:
-      The values that comprise the response stream of the RPC.
-
-    Raises:
-      abandonment.Abandoned: If no response is necessary because the RPC has
-        been aborted.
-      exceptions.RpcError: Implementations of this method must not deliberately
-        raise exceptions.RpcError but may allow such errors raised by the
-        request_iterator passed to them to propagate through their bodies
-        uncaught.
-    """
-    raise NotImplementedError()
-
-
-class InlineStreamInStreamOutMethod(object):
-  """A type for inline stream-request-stream-response RPC methods."""
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def service(self, request_iterator, context):
-    """Services an RPC that accepts and produces streams of values.
-
-    Args:
-      request_iterator: An iterator that yields the request values of the RPC.
-        Drawing values from this iterator may also raise exceptions.RpcError to
-        indicate abortion of the RPC.
-      context: An RpcContext object.
-
-    Yields:
-      The values that comprise the response stream of the RPC.
-
-    Raises:
-      abandonment.Abandoned: If completing the response stream is not necessary
-        because the RPC has been aborted.
-      exceptions.RpcError: Implementations of this method must not deliberately
-        raise exceptions.RpcError but may allow such errors raised by the
-        request_iterator passed to them to propagate through their bodies
-        uncaught.
-    """
-    raise NotImplementedError()
-
-
-class EventValueInValueOutMethod(object):
-  """A type for event-driven unary-request-unary-response RPC methods."""
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def service(self, request, response_callback, context):
-    """Services an RPC that accepts one value and produces one value.
-
-    Args:
-      request: The single request value for the RPC.
-      response_callback: A callback to be called to accept the response value of
-        the RPC.
-      context: An RpcContext object.
-
-    Raises:
-      abandonment.Abandoned: May or may not be raised when the RPC has been
-        aborted.
-    """
-    raise NotImplementedError()
-
-
-class EventValueInStreamOutMethod(object):
-  """A type for event-driven unary-request-stream-response RPC methods."""
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def service(self, request, response_consumer, context):
-    """Services an RPC that accepts one value and produces a stream of values.
-
-    Args:
-      request: The single request value for the RPC.
-      response_consumer: A stream.Consumer to be called to accept the response
+      request: The request value for the RPC.
+      response_consumer: A stream.Consumer to be called to accept the restponse
         values of the RPC.
-      context: An RpcContext object.
-
-    Raises:
-      abandonment.Abandoned: May or may not be raised when the RPC has been
-        aborted.
-    """
-    raise NotImplementedError()
-
-
-class EventStreamInValueOutMethod(object):
-  """A type for event-driven stream-request-unary-response RPC methods."""
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def service(self, response_callback, context):
-    """Services an RPC that accepts a stream of values and produces one value.
-
-    Args:
-      response_callback: A callback to be called to accept the response value of
-        the RPC.
-      context: An RpcContext object.
+      abortion_callback: A callback to be called and passed an Abortion value
+        in the event of RPC abortion.
+      timeout: A duration of time in seconds to allow for the RPC.
 
     Returns:
-      A stream.Consumer with which to accept the request values of the RPC. The
-        consumer returned from this method may or may not be invoked to
-        completion: in the case of RPC abortion, RPC Framework will simply stop
-        passing values to this object. Implementations must not assume that this
-        object will be called to completion of the request stream or even called
-        at all.
-
-    Raises:
-      abandonment.Abandoned: May or may not be raised when the RPC has been
-        aborted.
+      A Call object for the RPC.
     """
     raise NotImplementedError()
 
 
-class EventStreamInStreamOutMethod(object):
-  """A type for event-driven stream-request-stream-response RPC methods."""
+class StreamUnaryMultiCallable(object):
+  """Affords invoking a stream-unary RPC in any call style."""
   __metaclass__ = abc.ABCMeta
 
   @abc.abstractmethod
-  def service(self, response_consumer, context):
-    """Services an RPC that accepts and produces streams of values.
+  def __call__(self, request_iterator, timeout):
+    """Synchronously invokes the underlying RPC.
 
     Args:
-      response_consumer: A stream.Consumer to be called to accept the response
+      request_iterator: An iterator that yields request values for the RPC.
+      timeout: A duration of time in seconds to allow for the RPC.
+
+    Returns:
+      The response value for the RPC.
+
+    Raises:
+      exceptions.RpcError: Indicating that the RPC was aborted.
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def future(self, request_iterator, timeout):
+    """Asynchronously invokes the underlying RPC.
+
+    Args:
+      request_iterator: An iterator that yields request values for the RPC.
+      timeout: A duration of time in seconds to allow for the RPC.
+
+    Returns:
+      A future.Future representing the RPC. In the event of RPC completion, the
+        returned Future's result value will be the response value of the RPC.
+        In the event of RPC abortion, the returned Future's exception value
+        will be an exceptions.RpcError.
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def event(self, response_callback, abortion_callback, timeout):
+    """Asynchronously invokes the underlying RPC.
+
+    Args:
+      request: The request value for the RPC.
+      response_callback: A callback to be called to accept the restponse value
+        of the RPC.
+      abortion_callback: A callback to be called and passed an Abortion value
+        in the event of RPC abortion.
+      timeout: A duration of time in seconds to allow for the RPC.
+
+    Returns:
+      A pair of a Call object for the RPC and a stream.Consumer to which the
+        request values of the RPC should be passed.
+    """
+    raise NotImplementedError()
+
+
+class StreamStreamMultiCallable(object):
+  """Affords invoking a stream-stream RPC in any call style."""
+  __metaclass__ = abc.ABCMeta
+
+  @abc.abstractmethod
+  def __call__(self, request_iterator, timeout):
+    """Synchronously invokes the underlying RPC.
+
+    Args:
+      request_iterator: An iterator that yields request values for the RPC.
+      timeout: A duration of time in seconds to allow for the RPC.
+
+    Returns:
+      A CancellableIterator that yields the response values of the RPC and
+        affords RPC cancellation. Drawing response values from the returned
+        CancellableIterator may raise exceptions.RpcError indicating abortion
+        of the RPC.
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def event(self, response_consumer, abortion_callback, timeout):
+    """Asynchronously invokes the underlying RPC.
+
+l    Args:
+      response_consumer: A stream.Consumer to be called to accept the restponse
         values of the RPC.
-      context: An RpcContext object.
+      abortion_callback: A callback to be called and passed an Abortion value
+        in the event of RPC abortion.
+      timeout: A duration of time in seconds to allow for the RPC.
 
     Returns:
-      A stream.Consumer with which to accept the request values of the RPC. The
-        consumer returned from this method may or may not be invoked to
-        completion: in the case of RPC abortion, RPC Framework will simply stop
-        passing values to this object. Implementations must not assume that this
-        object will be called to completion of the request stream or even called
-        at all.
-
-    Raises:
-      abandonment.Abandoned: May or may not be raised when the RPC has been
-        aborted.
+      A pair of a Call object for the RPC and a stream.Consumer to which the
+        request values of the RPC should be passed.
     """
     raise NotImplementedError()
 
 
-class MultiMethod(object):
+class MethodImplementation(object):
+  """A sum type that describes an RPC method implementation.
+
+  Attributes:
+    cardinality: A cardinality.Cardinality value.
+    style: A style.Service value.
+    unary_unary_inline: The implementation of the RPC method as a callable
+      value that takes a request value and an RpcContext object and returns a
+      response value. Only non-None if cardinality is
+      cardinality.Cardinality.UNARY_UNARY and style is style.Service.INLINE.
+    unary_stream_inline: The implementation of the RPC method as a callable
+      value that takes a request value and an RpcContext object and returns an
+      iterator of response values. Only non-None if cardinality is
+      cardinality.Cardinality.UNARY_STREAM and style is style.Service.INLINE.
+    stream_unary_inline: The implementation of the RPC method as a callable
+      value that takes an iterator of request values and an RpcContext object
+      and returns a response value. Only non-None if cardinality is
+      cardinality.Cardinality.STREAM_UNARY and style is style.Service.INLINE.
+    stream_stream_inline: The implementation of the RPC method as a callable
+      value that takes an iterator of request values and an RpcContext object
+      and returns an iterator of response values. Only non-None if cardinality
+      is cardinality.Cardinality.STREAM_STREAM and style is
+      style.Service.INLINE.
+    unary_unary_event: The implementation of the RPC method as a callable value
+      that takes a request value, a response callback to which to pass the
+      response value of the RPC, and an RpcContext. Only non-None if
+      cardinality is cardinality.Cardinality.UNARY_UNARY and style is
+      style.Service.EVENT.
+    unary_stream_event: The implementation of the RPC method as a callable
+      value that takes a request value, a stream.Consumer to which to pass the
+      the response values of the RPC, and an RpcContext. Only non-None if
+      cardinality is cardinality.Cardinality.UNARY_STREAM and style is
+      style.Service.EVENT.
+    stream_unary_event: The implementation of the RPC method as a callable
+      value that takes a response callback to which to pass the response value
+      of the RPC and an RpcContext and returns a stream.Consumer to which the
+      request values of the RPC should be passed. Only non-None if cardinality
+      is cardinality.Cardinality.STREAM_UNARY and style is style.Service.EVENT.
+    stream_stream_event: The implementation of the RPC method as a callable
+      value that takes a stream.Consumer to which to pass the response values
+      of the RPC and an RpcContext and returns a stream.Consumer to which the
+      request values of the RPC should be passed. Only non-None if cardinality
+      is cardinality.Cardinality.STREAM_STREAM and style is
+      style.Service.EVENT.
+  """
+  __metaclass__ = abc.ABCMeta
+
+
+class MultiMethodImplementation(object):
   """A general type able to service many RPC methods."""
   __metaclass__ = abc.ABCMeta
 
@@ -420,26 +381,7 @@
     raise NotImplementedError()
 
 
-class Server(object):
-  """Specification of a running server that services RPCs."""
-  __metaclass__ = abc.ABCMeta
-
-
-class Call(object):
-  """Invocation-side representation of an RPC.
-
-  Attributes:
-    context: An RpcContext affording information about the RPC.
-  """
-  __metaclass__ = abc.ABCMeta
-
-  @abc.abstractmethod
-  def cancel(self):
-    """Requests cancellation of the RPC."""
-    raise NotImplementedError()
-
-
-class Stub(object):
+class GenericStub(object):
   """Affords RPC methods to callers."""
   __metaclass__ = abc.ABCMeta
 
@@ -632,25 +574,67 @@
     raise NotImplementedError()
 
   @abc.abstractmethod
-  def unary_unary_sync_async(self, name):
-    """Creates a UnaryUnarySyncAsync value for a unary-unary RPC method.
+  def unary_unary_multi_callable(self, name):
+    """Creates a UnaryUnaryMultiCallable for a unary-unary RPC method.
 
     Args:
       name: The RPC method name.
 
     Returns:
-      A UnaryUnarySyncAsync value for the named unary-unary RPC method.
+      A UnaryUnaryMultiCallable value for the named unary-unary RPC method.
     """
     raise NotImplementedError()
 
   @abc.abstractmethod
-  def stream_unary_sync_async(self, name):
-    """Creates a StreamUnarySyncAsync value for a stream-unary RPC method.
+  def unary_stream_multi_callable(self, name):
+    """Creates a UnaryStreamMultiCallable for a unary-stream RPC method.
 
     Args:
       name: The RPC method name.
 
     Returns:
-      A StreamUnarySyncAsync value for the named stream-unary RPC method.
+      A UnaryStreamMultiCallable value for the name unary-stream RPC method.
     """
     raise NotImplementedError()
+
+  @abc.abstractmethod
+  def stream_unary_multi_callable(self, name):
+    """Creates a StreamUnaryMultiCallable for a stream-unary RPC method.
+
+    Args:
+      name: The RPC method name.
+
+    Returns:
+      A StreamUnaryMultiCallable value for the named stream-unary RPC method.
+    """
+    raise NotImplementedError()
+
+  @abc.abstractmethod
+  def stream_stream_multi_callable(self, name):
+    """Creates a StreamStreamMultiCallable for a stream-stream RPC method.
+
+    Args:
+      name: The RPC method name.
+
+    Returns:
+      A StreamStreamMultiCallable value for the named stream-stream RPC method.
+    """
+    raise NotImplementedError()
+
+
+class DynamicStub(object):
+  """A stub with RPC-method-bound multi-callable attributes.
+
+  Instances of this type responsd to attribute access as follows: if the
+  requested attribute is the name of a unary-unary RPC method, the value of the
+  attribute will be a UnaryUnaryMultiCallable with which to invoke the RPC
+  method; if the requested attribute is the name of a unary-stream RPC method,
+  the value of the attribute will be a UnaryStreamMultiCallable with which to
+  invoke the RPC method; if the requested attribute is the name of a
+  stream-unary RPC method, the value of the attribute will be a
+  StreamUnaryMultiCallable with which to invoke the RPC method; and if the
+  requested attribute is the name of a stream-stream RPC method, the value of
+  the attribute will be a StreamStreamMultiCallable with which to invoke the
+  RPC method.
+  """
+  __metaclass__ = abc.ABCMeta
diff --git a/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py b/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py
index 233486f..e57ee00 100644
--- a/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py
+++ b/src/python/src/grpc/framework/face/testing/blocking_invocation_inline_service_test_case.py
@@ -61,13 +61,9 @@
     self.digest = digest.digest(
         stock_service.STOCK_TEST_SERVICE, self.control, None)
 
-    self.server, self.stub, self.memo = self.set_up_implementation(
+    self.stub, self.memo = self.set_up_implementation(
         self.digest.name, self.digest.methods,
-        self.digest.inline_unary_unary_methods,
-        self.digest.inline_unary_stream_methods,
-        self.digest.inline_stream_unary_methods,
-        self.digest.inline_stream_stream_methods,
-        {}, {}, {}, {}, None)
+        self.digest.inline_method_implementations, None)
 
   def tearDown(self):
     """See unittest.TestCase.tearDown for full specification.
@@ -147,8 +143,8 @@
 
         with self.control.pause(), self.assertRaises(
             exceptions.ExpirationError):
-          sync_async = self.stub.unary_unary_sync_async(name)
-          sync_async(request, _TIMEOUT)
+          multi_callable = self.stub.unary_unary_multi_callable(name)
+          multi_callable(request, _TIMEOUT)
 
   def testExpiredUnaryRequestStreamResponse(self):
     for name, test_messages_sequence in (
@@ -170,8 +166,8 @@
 
         with self.control.pause(), self.assertRaises(
             exceptions.ExpirationError):
-          sync_async = self.stub.stream_unary_sync_async(name)
-          sync_async(iter(requests), _TIMEOUT)
+          multi_callable = self.stub.stream_unary_multi_callable(name)
+          multi_callable(iter(requests), _TIMEOUT)
 
   def testExpiredStreamRequestStreamResponse(self):
     for name, test_messages_sequence in (
diff --git a/src/python/src/grpc/framework/face/testing/digest.py b/src/python/src/grpc/framework/face/testing/digest.py
index b8fb573..db8fcbb 100644
--- a/src/python/src/grpc/framework/face/testing/digest.py
+++ b/src/python/src/grpc/framework/face/testing/digest.py
@@ -34,6 +34,8 @@
 
 # testing_control, interfaces, and testing_service are referenced from
 # specification in this module.
+from grpc.framework.common import cardinality
+from grpc.framework.common import style
 from grpc.framework.face import exceptions
 from grpc.framework.face import interfaces as face_interfaces
 from grpc.framework.face.testing import control as testing_control  # pylint: disable=unused-import
@@ -50,15 +52,9 @@
         'TestServiceDigest',
         ['name',
          'methods',
-         'inline_unary_unary_methods',
-         'inline_unary_stream_methods',
-         'inline_stream_unary_methods',
-         'inline_stream_stream_methods',
-         'event_unary_unary_methods',
-         'event_unary_stream_methods',
-         'event_stream_unary_methods',
-         'event_stream_stream_methods',
-         'multi_method',
+         'inline_method_implementations',
+         'event_method_implementations',
+         'multi_method_implementation',
          'unary_unary_messages_sequences',
          'unary_stream_messages_sequences',
          'stream_unary_messages_sequences',
@@ -69,32 +65,14 @@
     name: The RPC service name to be used in the test.
     methods: A sequence of interfaces.Method objects describing the RPC
       methods that will be called during the test.
-    inline_unary_unary_methods: A dict from method name to
-      face_interfaces.InlineValueInValueOutMethod object to be used in tests of
+    inline_method_implementations: A dict from RPC method name to
+      face_interfaces.MethodImplementation object to be used in tests of
       in-line calls to behaviors under test.
-    inline_unary_stream_methods: A dict from method name to
-      face_interfaces.InlineValueInStreamOutMethod object to be used in tests of
-      in-line calls to behaviors under test.
-    inline_stream_unary_methods: A dict from method name to
-      face_interfaces.InlineStreamInValueOutMethod object to be used in tests of
-      in-line calls to behaviors under test.
-    inline_stream_stream_methods: A dict from method name to
-      face_interfaces.InlineStreamInStreamOutMethod object to be used in tests
-      of in-line calls to behaviors under test.
-    event_unary_unary_methods: A dict from method name to
-      face_interfaces.EventValueInValueOutMethod object to be used in tests of
+    event_method_implementations: A dict from RPC method name to
+      face_interfaces.MethodImplementation object to be used in tests of
       event-driven calls to behaviors under test.
-    event_unary_stream_methods: A dict from method name to
-      face_interfaces.EventValueInStreamOutMethod object to be used in tests of
-      event-driven calls to behaviors under test.
-    event_stream_unary_methods: A dict from method name to
-      face_interfaces.EventStreamInValueOutMethod object to be used in tests of
-      event-driven calls to behaviors under test.
-    event_stream_stream_methods: A dict from method name to
-      face_interfaces.EventStreamInStreamOutMethod object to be used in tests of
-      event-driven calls to behaviors under test.
-    multi_method: A face_interfaces.MultiMethod to be used in tests of generic
-      calls to behaviors under test.
+    multi_method_implementation: A face_interfaces.MultiMethodImplementation to
+      be used in tests of generic calls to behaviors under test.
     unary_unary_messages_sequences: A dict from method name to sequence of
       service.UnaryUnaryTestMessages objects to be used to test the method
       with the given name.
@@ -130,27 +108,33 @@
     self.terminated = True
 
 
-class _InlineUnaryUnaryMethod(face_interfaces.InlineValueInValueOutMethod):
+class _InlineUnaryUnaryMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, unary_unary_test_method, control):
     self._test_method = unary_unary_test_method
     self._control = control
 
-  def service(self, request, context):
+    self.cardinality = cardinality.Cardinality.UNARY_UNARY
+    self.style = style.Service.INLINE
+
+  def unary_unary_inline(self, request, context):
     response_list = []
     self._test_method.service(
         request, response_list.append, context, self._control)
     return response_list.pop(0)
 
 
-class _EventUnaryUnaryMethod(face_interfaces.EventValueInValueOutMethod):
+class _EventUnaryUnaryMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, unary_unary_test_method, control, pool):
     self._test_method = unary_unary_test_method
     self._control = control
     self._pool = pool
 
-  def service(self, request, response_callback, context):
+    self.cardinality = cardinality.Cardinality.UNARY_UNARY
+    self.style = style.Service.EVENT
+
+  def unary_unary_event(self, request, response_callback, context):
     if self._pool is None:
       self._test_method.service(
           request, response_callback, context, self._control)
@@ -160,13 +144,16 @@
           self._control)
 
 
-class _InlineUnaryStreamMethod(face_interfaces.InlineValueInStreamOutMethod):
+class _InlineUnaryStreamMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, unary_stream_test_method, control):
     self._test_method = unary_stream_test_method
     self._control = control
 
-  def service(self, request, context):
+    self.cardinality = cardinality.Cardinality.UNARY_STREAM
+    self.style = style.Service.INLINE
+
+  def unary_stream_inline(self, request, context):
     response_consumer = _BufferingConsumer()
     self._test_method.service(
         request, response_consumer, context, self._control)
@@ -174,14 +161,17 @@
       yield response
 
 
-class _EventUnaryStreamMethod(face_interfaces.EventValueInStreamOutMethod):
+class _EventUnaryStreamMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, unary_stream_test_method, control, pool):
     self._test_method = unary_stream_test_method
     self._control = control
     self._pool = pool
 
-  def service(self, request, response_consumer, context):
+    self.cardinality = cardinality.Cardinality.UNARY_STREAM
+    self.style = style.Service.EVENT
+
+  def unary_stream_event(self, request, response_consumer, context):
     if self._pool is None:
       self._test_method.service(
           request, response_consumer, context, self._control)
@@ -191,13 +181,16 @@
           self._control)
 
 
-class _InlineStreamUnaryMethod(face_interfaces.InlineStreamInValueOutMethod):
+class _InlineStreamUnaryMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, stream_unary_test_method, control):
     self._test_method = stream_unary_test_method
     self._control = control
 
-  def service(self, request_iterator, context):
+    self.cardinality = cardinality.Cardinality.STREAM_UNARY
+    self.style = style.Service.INLINE
+
+  def stream_unary_inline(self, request_iterator, context):
     response_list = []
     request_consumer = self._test_method.service(
         response_list.append, context, self._control)
@@ -207,14 +200,17 @@
     return response_list.pop(0)
 
 
-class _EventStreamUnaryMethod(face_interfaces.EventStreamInValueOutMethod):
+class _EventStreamUnaryMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, stream_unary_test_method, control, pool):
     self._test_method = stream_unary_test_method
     self._control = control
     self._pool = pool
 
-  def service(self, response_callback, context):
+    self.cardinality = cardinality.Cardinality.STREAM_UNARY
+    self.style = style.Service.EVENT
+
+  def stream_unary_event(self, response_callback, context):
     request_consumer = self._test_method.service(
         response_callback, context, self._control)
     if self._pool is None:
@@ -223,13 +219,16 @@
       return stream_util.ThreadSwitchingConsumer(request_consumer, self._pool)
 
 
-class _InlineStreamStreamMethod(face_interfaces.InlineStreamInStreamOutMethod):
+class _InlineStreamStreamMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, stream_stream_test_method, control):
     self._test_method = stream_stream_test_method
     self._control = control
 
-  def service(self, request_iterator, context):
+    self.cardinality = cardinality.Cardinality.STREAM_STREAM
+    self.style = style.Service.INLINE
+
+  def stream_stream_inline(self, request_iterator, context):
     response_consumer = _BufferingConsumer()
     request_consumer = self._test_method.service(
         response_consumer, context, self._control)
@@ -241,14 +240,17 @@
     response_consumer.terminate()
 
 
-class _EventStreamStreamMethod(face_interfaces.EventStreamInStreamOutMethod):
+class _EventStreamStreamMethod(face_interfaces.MethodImplementation):
 
   def __init__(self, stream_stream_test_method, control, pool):
     self._test_method = stream_stream_test_method
     self._control = control
     self._pool = pool
 
-  def service(self, response_consumer, context):
+    self.cardinality = cardinality.Cardinality.STREAM_STREAM
+    self.style = style.Service.EVENT
+
+  def stream_stream_event(self, response_consumer, context):
     request_consumer = self._test_method.service(
         response_consumer, context, self._control)
     if self._pool is None:
@@ -332,7 +334,7 @@
         response_consumer.consume_and_terminate, context, control)
 
 
-class _MultiMethod(face_interfaces.MultiMethod):
+class _MultiMethodImplementation(face_interfaces.MultiMethodImplementation):
 
   def __init__(self, methods, control, pool):
     self._methods = methods
@@ -427,19 +429,21 @@
   adaptations.update(unary_stream.adaptations)
   adaptations.update(stream_unary.adaptations)
   adaptations.update(stream_stream.adaptations)
+  inlines = dict(unary_unary.inlines)
+  inlines.update(unary_stream.inlines)
+  inlines.update(stream_unary.inlines)
+  inlines.update(stream_stream.inlines)
+  events = dict(unary_unary.events)
+  events.update(unary_stream.events)
+  events.update(stream_unary.events)
+  events.update(stream_stream.events)
 
   return TestServiceDigest(
       service.name(),
       methods,
-      unary_unary.inlines,
-      unary_stream.inlines,
-      stream_unary.inlines,
-      stream_stream.inlines,
-      unary_unary.events,
-      unary_stream.events,
-      stream_unary.events,
-      stream_stream.events,
-      _MultiMethod(adaptations, control, pool),
+      inlines,
+      events,
+      _MultiMethodImplementation(adaptations, control, pool),
       unary_unary.messages,
       unary_stream.messages,
       stream_unary.messages,
diff --git a/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py b/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
index 21e669b..0f0b0e3 100644
--- a/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
+++ b/src/python/src/grpc/framework/face/testing/event_invocation_synchronous_event_service_test_case.py
@@ -60,14 +60,9 @@
     self.digest = digest.digest(
         stock_service.STOCK_TEST_SERVICE, self.control, None)
 
-    self.server, self.stub, self.memo = self.set_up_implementation(
+    self.stub, self.memo = self.set_up_implementation(
         self.digest.name, self.digest.methods,
-        {}, {}, {}, {},
-        self.digest.event_unary_unary_methods,
-        self.digest.event_unary_stream_methods,
-        self.digest.event_stream_unary_methods,
-        self.digest.event_stream_stream_methods,
-        None)
+        self.digest.event_method_implementations, None)
 
   def tearDown(self):
     """See unittest.TestCase.tearDown for full specification.
diff --git a/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py b/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
index c87846f..0d51b64 100644
--- a/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
+++ b/src/python/src/grpc/framework/face/testing/future_invocation_asynchronous_event_service_test_case.py
@@ -91,14 +91,9 @@
     self.digest = digest.digest(
         stock_service.STOCK_TEST_SERVICE, self.control, self.digest_pool)
 
-    self.server, self.stub, self.memo = self.set_up_implementation(
+    self.stub, self.memo = self.set_up_implementation(
         self.digest.name, self.digest.methods,
-        {}, {}, {}, {},
-        self.digest.event_unary_unary_methods,
-        self.digest.event_unary_stream_methods,
-        self.digest.event_stream_unary_methods,
-        self.digest.event_stream_stream_methods,
-        None)
+        self.digest.event_method_implementations, None)
 
   def tearDown(self):
     """See unittest.TestCase.tearDown for full specification.
@@ -190,8 +185,8 @@
         request = test_messages.request()
 
         with self.control.pause():
-          sync_async = self.stub.unary_unary_sync_async(name)
-          response_future = sync_async.async(request, _TIMEOUT)
+          multi_callable = self.stub.unary_unary_multi_callable(name)
+          response_future = multi_callable.future(request, _TIMEOUT)
           self.assertIsInstance(
               response_future.exception(), exceptions.ExpirationError)
           with self.assertRaises(exceptions.ExpirationError):
@@ -216,8 +211,8 @@
         requests = test_messages.requests()
 
         with self.control.pause():
-          sync_async = self.stub.stream_unary_sync_async(name)
-          response_future = sync_async.async(iter(requests), _TIMEOUT)
+          multi_callable = self.stub.stream_unary_multi_callable(name)
+          response_future = multi_callable.future(iter(requests), _TIMEOUT)
           self.assertIsInstance(
               response_future.exception(), exceptions.ExpirationError)
           with self.assertRaises(exceptions.ExpirationError):
diff --git a/src/python/src/grpc/framework/face/testing/service.py b/src/python/src/grpc/framework/face/testing/service.py
index a58e2ee..bf54d41 100644
--- a/src/python/src/grpc/framework/face/testing/service.py
+++ b/src/python/src/grpc/framework/face/testing/service.py
@@ -36,8 +36,8 @@
 from grpc.framework.face.testing import interfaces
 
 
-class UnaryUnaryTestMethod(interfaces.Method):
-  """Like face_interfaces.EventValueInValueOutMethod but with a control."""
+class UnaryUnaryTestMethodImplementation(interfaces.Method):
+  """A controllable implementation of a unary-unary RPC method."""
 
   __metaclass__ = abc.ABCMeta
 
@@ -93,8 +93,8 @@
     raise NotImplementedError()
 
 
-class UnaryStreamTestMethod(interfaces.Method):
-  """Like face_interfaces.EventValueInStreamOutMethod but with a control."""
+class UnaryStreamTestMethodImplementation(interfaces.Method):
+  """A controllable implementation of a unary-stream RPC method."""
 
   __metaclass__ = abc.ABCMeta
 
@@ -106,7 +106,7 @@
       request: The single request message for the RPC.
       response_consumer: A stream.Consumer to be called to accept the response
         messages of the RPC.
-      context: An RpcContext object.
+      context: A face_interfaces.RpcContext object.
       control: A test_control.Control to control execution of this method.
 
     Raises:
@@ -150,8 +150,8 @@
     raise NotImplementedError()
 
 
-class StreamUnaryTestMethod(interfaces.Method):
-  """Like face_interfaces.EventStreamInValueOutMethod but with a control."""
+class StreamUnaryTestMethodImplementation(interfaces.Method):
+  """A controllable implementation of a stream-unary RPC method."""
 
   __metaclass__ = abc.ABCMeta
 
@@ -162,7 +162,7 @@
     Args:
       response_callback: A callback to be called to accept the response message
         of the RPC.
-      context: An RpcContext object.
+      context: A face_interfaces.RpcContext object.
       control: A test_control.Control to control execution of this method.
 
     Returns:
@@ -214,8 +214,8 @@
     raise NotImplementedError()
 
 
-class StreamStreamTestMethod(interfaces.Method):
-  """Like face_interfaces.EventStreamInStreamOutMethod but with a control."""
+class StreamStreamTestMethodImplementation(interfaces.Method):
+  """A controllable implementation of a stream-stream RPC method."""
 
   __metaclass__ = abc.ABCMeta
 
@@ -226,7 +226,7 @@
     Args:
       response_consumer: A stream.Consumer to be called to accept the response
         messages of the RPC.
-      context: An RpcContext object.
+      context: A face_interfaces.RpcContext object.
       control: A test_control.Control to control execution of this method.
 
     Returns:
@@ -298,8 +298,8 @@
 
     Returns:
       A dict from method name to pair. The first element of the pair
-        is a UnaryUnaryTestMethod object and the second element is a sequence
-        of UnaryUnaryTestMethodMessages objects.
+        is a UnaryUnaryTestMethodImplementation object and the second element
+        is a sequence of UnaryUnaryTestMethodMessages objects.
     """
     raise NotImplementedError()
 
@@ -309,8 +309,8 @@
 
     Returns:
       A dict from method name to pair. The first element of the pair is a
-        UnaryStreamTestMethod object and the second element is a sequence of
-        UnaryStreamTestMethodMessages objects.
+        UnaryStreamTestMethodImplementation object and the second element is a
+        sequence of UnaryStreamTestMethodMessages objects.
     """
     raise NotImplementedError()
 
@@ -320,8 +320,8 @@
 
     Returns:
       A dict from method name to pair. The first element of the pair is a
-        StreamUnaryTestMethod object and the second element is a sequence of
-        StreamUnaryTestMethodMessages objects.
+        StreamUnaryTestMethodImplementation object and the second element is a
+        sequence of StreamUnaryTestMethodMessages objects.
     """
     raise NotImplementedError()
 
@@ -331,7 +331,7 @@
 
     Returns:
       A dict from method name to pair. The first element of the pair is a
-        StreamStreamTestMethod object and the second element is a sequence of
-        StreamStreamTestMethodMessages objects.
+        StreamStreamTestMethodImplementation object and the second element is a
+        sequence of StreamStreamTestMethodMessages objects.
     """
     raise NotImplementedError()
diff --git a/src/python/src/grpc/framework/face/testing/stock_service.py b/src/python/src/grpc/framework/face/testing/stock_service.py
index 83c9418..61aaf44 100644
--- a/src/python/src/grpc/framework/face/testing/stock_service.py
+++ b/src/python/src/grpc/framework/face/testing/stock_service.py
@@ -139,7 +139,7 @@
   return StockRequestConsumer()
 
 
-class GetLastTradePrice(service.UnaryUnaryTestMethod):
+class GetLastTradePrice(service.UnaryUnaryTestMethodImplementation):
   """GetLastTradePrice for use in tests."""
 
   def name(self):
@@ -186,7 +186,7 @@
     test_case.assertEqual(_price(request.symbol), response.price)
 
 
-class GetLastTradePriceMultiple(service.StreamStreamTestMethod):
+class GetLastTradePriceMultiple(service.StreamStreamTestMethodImplementation):
   """GetLastTradePriceMultiple for use in tests."""
 
   def name(self):
@@ -238,7 +238,7 @@
       test_case.assertEqual(_price(stock_request.symbol), stock_reply.price)
 
 
-class WatchFutureTrades(service.UnaryStreamTestMethod):
+class WatchFutureTrades(service.UnaryStreamTestMethodImplementation):
   """WatchFutureTrades for use in tests."""
 
   def name(self):
@@ -288,7 +288,7 @@
       test_case.assertEqual(base_price + index, response.price)
 
 
-class GetHighestTradePrice(service.StreamUnaryTestMethod):
+class GetHighestTradePrice(service.StreamUnaryTestMethodImplementation):
   """GetHighestTradePrice for use in tests."""
 
   def name(self):
diff --git a/src/python/src/grpc/framework/face/testing/test_case.py b/src/python/src/grpc/framework/face/testing/test_case.py
index 218a2a8..e60e3d1 100644
--- a/src/python/src/grpc/framework/face/testing/test_case.py
+++ b/src/python/src/grpc/framework/face/testing/test_case.py
@@ -46,55 +46,24 @@
 
   @abc.abstractmethod
   def set_up_implementation(
-      self,
-      name,
-      methods,
-      inline_value_in_value_out_methods,
-      inline_value_in_stream_out_methods,
-      inline_stream_in_value_out_methods,
-      inline_stream_in_stream_out_methods,
-      event_value_in_value_out_methods,
-      event_value_in_stream_out_methods,
-      event_stream_in_value_out_methods,
-      event_stream_in_stream_out_methods,
-      multi_method):
+      self, name, methods, method_implementations,
+      multi_method_implementation):
     """Instantiates the Face Layer implementation under test.
 
     Args:
       name: The service name to be used in the test.
       methods: A sequence of interfaces.Method objects describing the RPC
         methods that will be called during the test.
-      inline_value_in_value_out_methods: A dictionary from string method names
-        to face_interfaces.InlineValueInValueOutMethod implementations of those
-        methods.
-      inline_value_in_stream_out_methods: A dictionary from string method names
-        to face_interfaces.InlineValueInStreamOutMethod implementations of those
-        methods.
-      inline_stream_in_value_out_methods: A dictionary from string method names
-        to face_interfaces.InlineStreamInValueOutMethod implementations of those
-        methods.
-      inline_stream_in_stream_out_methods: A dictionary from string method names
-        to face_interfaces.InlineStreamInStreamOutMethod implementations of
-        those methods.
-      event_value_in_value_out_methods: A dictionary from string method names
-        to face_interfaces.EventValueInValueOutMethod implementations of those
-        methods.
-      event_value_in_stream_out_methods: A dictionary from string method names
-        to face_interfaces.EventValueInStreamOutMethod implementations of those
-        methods.
-      event_stream_in_value_out_methods: A dictionary from string method names
-        to face_interfaces.EventStreamInValueOutMethod implementations of those
-        methods.
-      event_stream_in_stream_out_methods: A dictionary from string method names
-        to face_interfaces.EventStreamInStreamOutMethod implementations of those
-        methods.
-      multi_method: An face_interfaces.MultiMethod, or None.
+      method_implementations: A dictionary from string RPC method name to
+        face_interfaces.MethodImplementation object specifying
+        implementation of an RPC method.
+      multi_method_implementation: An face_interfaces.MultiMethodImplementation
+        or None.
 
     Returns:
-      A sequence of length three the first element of which is a
-        face_interfaces.Server, the second element of which is a
-        face_interfaces.Stub, (both of which are backed by the given method
-        implementations), and the third element of which is an arbitrary memo
+      A sequence of length two the first element of which is a
+        face_interfaces.GenericStub (backed by the given method
+        implementations), and the second element of which is an arbitrary memo
         object to be kept and passed to tearDownImplementation at the conclusion
         of the test.
     """
@@ -105,7 +74,7 @@
     """Destroys the Face layer implementation under test.
 
     Args:
-      memo: The object from the third position of the return value of
+      memo: The object from the second position of the return value of
         set_up_implementation.
     """
     raise NotImplementedError()
diff --git a/src/python/src/grpc/framework/face/utilities.py b/src/python/src/grpc/framework/face/utilities.py
index 5e34be3..a63fe8c 100644
--- a/src/python/src/grpc/framework/face/utilities.py
+++ b/src/python/src/grpc/framework/face/utilities.py
@@ -27,101 +27,44 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-"""Utilities for the face layer of RPC Framework."""
+"""Utilities for RPC framework's face layer."""
 
-# stream is referenced from specification in this module.
+import collections
+
+from grpc.framework.common import cardinality
+from grpc.framework.common import style
 from grpc.framework.face import interfaces
-from grpc.framework.foundation import stream  # pylint: disable=unused-import
+from grpc.framework.foundation import stream
 
 
-class _InlineUnaryUnaryMethod(interfaces.InlineValueInValueOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, request, context):
-    return self._behavior(request, context)
+class _MethodImplementation(
+    interfaces.MethodImplementation,
+    collections.namedtuple(
+        '_MethodImplementation',
+        ['cardinality', 'style', 'unary_unary_inline', 'unary_stream_inline',
+         'stream_unary_inline', 'stream_stream_inline', 'unary_unary_event',
+         'unary_stream_event', 'stream_unary_event', 'stream_stream_event',])):
+  pass
 
 
-class _InlineUnaryStreamMethod(interfaces.InlineValueInStreamOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, request, context):
-    return self._behavior(request, context)
-
-
-class _InlineStreamUnaryMethod(interfaces.InlineStreamInValueOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, request_iterator, context):
-    return self._behavior(request_iterator, context)
-
-
-class _InlineStreamStreamMethod(interfaces.InlineStreamInStreamOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, request_iterator, context):
-    return self._behavior(request_iterator, context)
-
-
-class _EventUnaryUnaryMethod(interfaces.EventValueInValueOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, request, response_callback, context):
-    return self._behavior(request, response_callback, context)
-
-
-class _EventUnaryStreamMethod(interfaces.EventValueInStreamOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, request, response_consumer, context):
-    return self._behavior(request, response_consumer, context)
-
-
-class _EventStreamUnaryMethod(interfaces.EventStreamInValueOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, response_callback, context):
-    return self._behavior(response_callback, context)
-
-
-class _EventStreamStreamMethod(interfaces.EventStreamInStreamOutMethod):
-
-  def __init__(self, behavior):
-    self._behavior = behavior
-
-  def service(self, response_consumer, context):
-    return self._behavior(response_consumer, context)
-
-
-def inline_unary_unary_method(behavior):
-  """Creates an interfaces.InlineValueInValueOutMethod from a behavior.
+def unary_unary_inline(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
-    behavior: The implementation of a unary-unary RPC method as a callable
-      value that takes a request value and an interfaces.RpcContext object and
+    behavior: The implementation of a unary-unary RPC method as a callable value
+      that takes a request value and an interfaces.RpcContext object and
       returns a response value.
 
   Returns:
-    An interfaces.InlineValueInValueOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _InlineUnaryUnaryMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.UNARY_UNARY, style.Service.INLINE, behavior,
+      None, None, None, None, None, None, None)
 
 
-def inline_unary_stream_method(behavior):
-  """Creates an interfaces.InlineValueInStreamOutMethod from a behavior.
+def unary_stream_inline(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a unary-stream RPC method as a callable
@@ -129,13 +72,15 @@
       returns an iterator of response values.
 
   Returns:
-    An interfaces.InlineValueInStreamOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _InlineUnaryStreamMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.UNARY_STREAM, style.Service.INLINE, None,
+      behavior, None, None, None, None, None, None)
 
 
-def inline_stream_unary_method(behavior):
-  """Creates an interfaces.InlineStreamInValueOutMethod from a behavior.
+def stream_unary_inline(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a stream-unary RPC method as a callable
@@ -143,13 +88,15 @@
       interfaces.RpcContext object and returns a response value.
 
   Returns:
-    An interfaces.InlineStreamInValueOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _InlineStreamUnaryMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.STREAM_UNARY, style.Service.INLINE, None, None,
+      behavior, None, None, None, None, None)
 
 
-def inline_stream_stream_method(behavior):
-  """Creates an interfaces.InlineStreamInStreamOutMethod from a behavior.
+def stream_stream_inline(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a stream-stream RPC method as a callable
@@ -157,14 +104,15 @@
       interfaces.RpcContext object and returns an iterator of response values.
 
   Returns:
-    An interfaces.InlineStreamInStreamOutMethod derived from the given
-      behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _InlineStreamStreamMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.STREAM_STREAM, style.Service.INLINE, None, None,
+      None, behavior, None, None, None, None)
 
 
-def event_unary_unary_method(behavior):
-  """Creates an interfaces.EventValueInValueOutMethod from a behavior.
+def unary_unary_event(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a unary-unary RPC method as a callable
@@ -172,27 +120,31 @@
       the response value of the RPC, and an interfaces.RpcContext.
 
   Returns:
-    An interfaces.EventValueInValueOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _EventUnaryUnaryMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.UNARY_UNARY, style.Service.EVENT, None, None,
+      None, None, behavior, None, None, None)
 
 
-def event_unary_stream_method(behavior):
-  """Creates an interfaces.EventValueInStreamOutMethod from a behavior.
+def unary_stream_event(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a unary-stream RPC method as a callable
       value that takes a request value, a stream.Consumer to which to pass the
-      response values of the RPC, and an interfaces.RpcContext.
+      the response values of the RPC, and an interfaces.RpcContext.
 
   Returns:
-    An interfaces.EventValueInStreamOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _EventUnaryStreamMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.UNARY_STREAM, style.Service.EVENT, None, None,
+      None, None, None, behavior, None, None)
 
 
-def event_stream_unary_method(behavior):
-  """Creates an interfaces.EventStreamInValueOutMethod from a behavior.
+def stream_unary_event(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a stream-unary RPC method as a callable
@@ -201,13 +153,15 @@
       which the request values of the RPC should be passed.
 
   Returns:
-    An interfaces.EventStreamInValueOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _EventStreamUnaryMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.STREAM_UNARY, style.Service.EVENT, None, None,
+      None, None, None, None, behavior, None)
 
 
-def event_stream_stream_method(behavior):
-  """Creates an interfaces.EventStreamInStreamOutMethod from a behavior.
+def stream_stream_event(behavior):
+  """Creates an interfaces.MethodImplementation for the given behavior.
 
   Args:
     behavior: The implementation of a stream-stream RPC method as a callable
@@ -216,6 +170,8 @@
       which the request values of the RPC should be passed.
 
   Returns:
-    An interfaces.EventStreamInStreamOutMethod derived from the given behavior.
+    An interfaces.MethodImplementation derived from the given behavior.
   """
-  return _EventStreamStreamMethod(behavior)
+  return _MethodImplementation(
+      cardinality.Cardinality.STREAM_STREAM, style.Service.EVENT, None, None,
+      None, None, None, None, None, behavior)
diff --git a/src/python/src/setup.py b/src/python/src/setup.py
index cdb82a9..a513a28 100644
--- a/src/python/src/setup.py
+++ b/src/python/src/setup.py
@@ -64,7 +64,6 @@
     'grpc._junkdrawer',
     'grpc.early_adopter',
     'grpc.framework',
-    'grpc.framework.assembly',
     'grpc.framework.base',
     'grpc.framework.base.packets',
     'grpc.framework.common',
diff --git a/templates/Makefile.template b/templates/Makefile.template
index 6573e03..a69c7a7 100644
--- a/templates/Makefile.template
+++ b/templates/Makefile.template
@@ -176,9 +176,14 @@
 $(error Invalid CONFIG value '$(CONFIG)')
 endif
 
+ifeq ($(SYSTEM),Linux)
+TMPOUT = /dev/null
+else
+TMPOUT = `mktemp /tmp/test-out-XXXXXX`
+endif
 
 # Detect if we can use C++11
-CXX11_CHECK_CMD = $(CXX) -std=c++11 -o /dev/null -c test/build/c++11.cc
+CXX11_CHECK_CMD = $(CXX) -std=c++11 -o $(TMPOUT) -c test/build/c++11.cc
 HAS_CXX11 = $(shell $(CXX11_CHECK_CMD) 2> /dev/null && echo true || echo false)
 
 # The HOST compiler settings are used to compile the protoc plugins.
@@ -211,9 +216,25 @@
 
 INCLUDES = . include $(GENDIR)
 ifeq ($(SYSTEM),Darwin)
-INCLUDES += /usr/local/ssl/include /opt/local/include
+ifneq ($(wildcard /usr/local/ssl/include),)
+INCLUDES += /usr/local/ssl/include
+endif
+ifneq ($(wildcard /opt/local/include),)
+INCLUDES += /opt/local/include
+endif
+ifneq ($(wildcard /usr/local/include),)
+INCLUDES += /usr/local/include
+endif
 LIBS = m z
-LDFLAGS += -L/usr/local/ssl/lib -L/opt/local/lib
+ifneq ($(wildcard /usr/local/ssl/lib),)
+LDFLAGS += -L/usr/local/ssl/lib
+endif
+ifneq ($(wildcard /opt/local/lib),)
+LDFLAGS += -L/opt/local/lib
+endif
+ifneq ($(wildcard /usr/local/lib),)
+LDFLAGS += -L/usr/local/lib
+endif
 else
 LIBS = rt m z pthread
 LDFLAGS += -pthread
@@ -268,10 +289,10 @@
 IS_GIT_FOLDER = true
 endif
 
-OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS)
-ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/zlib.c -lz $(LDFLAGS)
-PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o /dev/null test/build/perftools.c -lprofiler $(LDFLAGS)
-PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o /dev/null test/build/protobuf.cc -lprotobuf $(LDFLAGS)
+OPENSSL_ALPN_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/openssl-alpn.c -lssl -lcrypto -ldl $(LDFLAGS)
+ZLIB_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/zlib.c -lz $(LDFLAGS)
+PERFTOOLS_CHECK_CMD = $(CC) $(CFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/perftools.c -lprofiler $(LDFLAGS)
+PROTOBUF_CHECK_CMD = $(CXX) $(CXXFLAGS) $(CPPFLAGS) -o $(TMPOUT) test/build/protobuf.cc -lprotobuf $(LDFLAGS)
 PROTOC_CMD = which protoc
 PROTOC_CHECK_CMD = protoc --version | grep -q libprotoc.3
 
@@ -810,10 +831,10 @@
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/${lib.name}.$(SHARED_EXT) $(prefix)/lib/${lib.name}.$(SHARED_EXT)
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}-imp.a $(prefix)/lib/lib${lib.name}-imp.a
 else
+ifneq ($(SYSTEM),Darwin)
 	$(E) "[INSTALL] Installing lib${lib.name}.$(SHARED_EXT)"
 	$(Q) $(INSTALL) -d $(prefix)/lib
 	$(Q) $(INSTALL) $(LIBDIR)/$(CONFIG)/lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.$(SHARED_EXT)
-ifneq ($(SYSTEM),Darwin)
 	$(Q) ln -sf lib${lib.name}.$(SHARED_EXT) $(prefix)/lib/lib${lib.name}.so
 endif
 endif
diff --git a/test/core/support/slice_buffer_test.c b/test/core/support/slice_buffer_test.c
index 8301795..a482784 100644
--- a/test/core/support/slice_buffer_test.c
+++ b/test/core/support/slice_buffer_test.c
@@ -62,8 +62,13 @@
   }
   GPR_ASSERT(buf.count > 0);
   GPR_ASSERT(buf.length == 50);
-  gpr_slice_unref(aaa);
-  gpr_slice_unref(bb);
+  for (i = 0; i < 10; i++) {
+    gpr_slice_buffer_pop(&buf);
+    gpr_slice_unref(aaa);
+    gpr_slice_unref(bb);
+  }
+  GPR_ASSERT(buf.count == 0);
+  GPR_ASSERT(buf.length == 0);
   gpr_slice_buffer_destroy(&buf);
 
   return 0;
diff --git a/test/cpp/qps/client_async.cc b/test/cpp/qps/client_async.cc
index 5eb9ff6..c6535be 100644
--- a/test/cpp/qps/client_async.cc
+++ b/test/cpp/qps/client_async.cc
@@ -94,7 +94,7 @@
     hist->Add((Timer::Now() - start_) * 1e9);
   }
 
-  void StartNewClone() {
+  void StartNewClone() GRPC_OVERRIDE {
     new ClientRpcContextUnaryImpl(stub_, req_, start_req_, callback_);
   }
 
@@ -175,7 +175,7 @@
     }
   }
 
-  void ThreadFunc(Histogram *histogram, size_t thread_idx) {
+  void ThreadFunc(Histogram *histogram, size_t thread_idx) GRPC_OVERRIDE {
     void *got_tag;
     bool ok;
     cli_cqs_[thread_idx]->Next(&got_tag, &ok);
diff --git a/tools/dockerfile/grpc_csharp_mono/Dockerfile b/tools/dockerfile/grpc_csharp_mono/Dockerfile
index 8f86366..703b658 100644
--- a/tools/dockerfile/grpc_csharp_mono/Dockerfile
+++ b/tools/dockerfile/grpc_csharp_mono/Dockerfile
@@ -51,5 +51,5 @@
 # Add a service_account directory containing the auth creds file
 ADD service_account service_account
 
-# TODO: add command to run the interop server
-CMD ["/bin/bash", "-l"]
+# Run the C# Interop Server
+CMD ["/bin/bash", "-l", "-c", "cd /var/local/git/grpc/src/csharp/Grpc.IntegrationTesting.Server/bin/Debug && mono Grpc.IntegrationTesting.Server.exe --use_tls=true --port=8070"]
diff --git a/tools/dockerfile/grpc_python/Dockerfile b/tools/dockerfile/grpc_python/Dockerfile
index 58a3d8c..fd07e9c 100644
--- a/tools/dockerfile/grpc_python/Dockerfile
+++ b/tools/dockerfile/grpc_python/Dockerfile
@@ -53,13 +53,15 @@
   && python2.7 -B -m grpc._adapter._links_test \
   && python2.7 -B -m grpc._adapter._lonely_rear_link_test \
   && python2.7 -B -m grpc._adapter._low_test \
-  && python2.7 -B -m grpc.framework.assembly.implementations_test \
+  && python2.7 -B -m grpc.early_adopter.implementations_test \
   && python2.7 -B -m grpc.framework.base.packets.implementations_test \
   && python2.7 -B -m grpc.framework.face.blocking_invocation_inline_service_test \
   && python2.7 -B -m grpc.framework.face.event_invocation_synchronous_event_service_test \
   && python2.7 -B -m grpc.framework.face.future_invocation_asynchronous_event_service_test \
   && python2.7 -B -m grpc.framework.foundation._later_test \
-  && python2.7 -B -m grpc.framework.foundation._logging_pool_test
+  && python2.7 -B -m grpc.framework.foundation._logging_pool_test \
+  && python2.7 -B -m interop._insecure_interop_test \
+  && python2.7 -B -m interop._secure_interop_test
 
 # Add a cacerts directory containing the Google root pem file, allowing the interop client to access the production test instance
 ADD cacerts cacerts
diff --git a/tools/gce_setup/cloud_prod_runner.sh b/tools/gce_setup/cloud_prod_runner.sh
index 520dfcd..3a9ae51 100755
--- a/tools/gce_setup/cloud_prod_runner.sh
+++ b/tools/gce_setup/cloud_prod_runner.sh
@@ -28,11 +28,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+thisfile=$(readlink -ne "${BASH_SOURCE[0]}")
+current_time=$(date "+%Y-%m-%d-%H-%M-%S")
+result_file_name=cloud_prod_result.$current_time.html
+echo $result_file_name
 
 main() {
   source grpc_docker.sh
-  # temporarily remove ping_pong and cancel_after_first_response while investigating timeout
-  test_cases=(large_unary empty_unary client_streaming server_streaming cancel_after_begin)
+  test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response)
   auth_test_cases=(service_account_creds compute_engine_creds)
   clients=(cxx java go ruby node csharp_mono)
   for test_case in "${test_cases[@]}"
@@ -41,9 +44,9 @@
     do
       if grpc_cloud_prod_test $test_case grpc-docker-testclients $client
       then
-        echo "$test_case $client $server passed" >> /tmp/cloud_prod_result.txt
+        echo "          ['$test_case', '$client', 'prod', true]," >> /tmp/cloud_prod_result.txt
       else
-        echo "$test_case $client $server failed" >> /tmp/cloud_prod_result.txt
+        echo "          ['$test_case', '$client', 'prod', false]," >> /tmp/cloud_prod_result.txt
       fi
     done
   done
@@ -53,14 +56,20 @@
     do
       if grpc_cloud_prod_auth_test $test_case grpc-docker-testclients $client
       then
-        echo "$test_case $client $server passed" >> /tmp/cloud_prod_result.txt
+        echo "          ['$test_case', '$client', 'prod', true]," >> /tmp/cloud_prod_result.txt
       else
-        echo "$test_case $client $server failed" >> /tmp/cloud_prod_result.txt
+        echo "          ['$test_case', '$client', 'prod', false]," >> /tmp/cloud_prod_result.txt
       fi
     done
   done
-  gsutil cp /tmp/cloud_prod_result.txt gs://stoked-keyword-656-output/cloud_prod_result.txt
-  rm /tmp/cloud_prod_result.txt
+  if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
+    cat pre.html /tmp/cloud_prod_result.txt post.html > /tmp/cloud_prod_result.html
+    gsutil cp /tmp/cloud_prod_result.txt gs://stoked-keyword-656-output/cloud_prod_result.txt
+    gsutil cp /tmp/cloud_prod_result.html gs://stoked-keyword-656-output/cloud_prod_result.html
+    gsutil cp /tmp/cloud_prod_result.html gs://stoked-keyword-656-output/result_history/$result_file_name
+    rm /tmp/cloud_prod_result.txt
+    rm /tmp/cloud_prod_result.html
+  fi
 }
 
 set -x
diff --git a/tools/gce_setup/grpc_docker.sh b/tools/gce_setup/grpc_docker.sh
index 619eff5..3deef05 100755
--- a/tools/gce_setup/grpc_docker.sh
+++ b/tools/gce_setup/grpc_docker.sh
@@ -731,6 +731,44 @@
   done
 }
 
+# Runs a test command on a docker instance
+#
+# The test command is issued via gcloud compute
+#
+# There are 3 possible results:
+# 1. successful return code and finished within 60 seconds
+# 2. failure return code and finished within 60 seconds
+# 3. command does not return within 60 seconds, in which case it will be killed.
+test_runner() {
+  local project_opt="--project $grpc_project"
+  local zone_opt="--zone $grpc_zone"
+  local ssh_cmd="bash -l -c \"$cmd\""
+  echo "will run:"
+  echo "  $ssh_cmd"
+  echo "on $host"
+  [[ $dry_run == 1 ]] && return 0  # don't run the command on a dry run
+  gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" &
+  PID=$!
+  echo "pid is $PID"
+  for x in {0..5}
+  do
+    if ps -p $PID
+    then
+      # test command has not returned and 60 seconds timeout has not reached
+      sleep 10
+    else
+      # test command has returned, return the return code from the test command
+      wait $PID
+      local ret=$?
+      echo " test runner return $ret before timeout"
+      return $ret
+    fi
+  done
+  kill $PID
+  echo "test got killed by timeout return as failure"
+  return 1
+}
+
 # Runs a test command on a docker instance.
 #
 # call-seq:
@@ -790,14 +828,7 @@
   cmd=$($grpc_gen_test_cmd $flags)
   [[ -n $cmd ]] || return 1
 
-  local project_opt="--project $grpc_project"
-  local zone_opt="--zone $grpc_zone"
-  local ssh_cmd="bash -l -c \"$cmd\""
-  echo "will run:"
-  echo "  $ssh_cmd"
-  echo "on $host"
-  [[ $dry_run == 1 ]] && return 0  # don't run the command on a dry run
-  gcloud compute $project_opt ssh $zone_opt $host --command "$cmd" 
+  test_runner
 }
 
 # Runs a test command on a docker instance.
@@ -836,14 +867,7 @@
   cmd=$($grpc_gen_test_cmd $test_case_flag)
   [[ -n $cmd ]] || return 1
 
-  local project_opt="--project $grpc_project"
-  local zone_opt="--zone $grpc_zone"
-  local ssh_cmd="bash -l -c \"$cmd\""
-  echo "will run:"
-  echo "  $ssh_cmd"
-  echo "on $host"
-  [[ $dry_run == 1 ]] && return 0  # don't run the command on a dry run
-  gcloud compute $project_opt ssh $zone_opt $host --command "$cmd"
+  test_runner
 }
 
 # Runs a test command on a docker instance.
@@ -882,14 +906,7 @@
   cmd=$($grpc_gen_test_cmd $test_case_flag)
   [[ -n $cmd ]] || return 1
 
-  local project_opt="--project $grpc_project"
-  local zone_opt="--zone $grpc_zone"
-  local ssh_cmd="bash -l -c \"$cmd\""
-  echo "will run:"
-  echo "  $ssh_cmd"
-  echo "on $host"
-  [[ $dry_run == 1 ]] && return 0  # don't run the command on a dry run
-  gcloud compute $project_opt ssh $zone_opt $host --command "$cmd"
+  test_runner
 }
 
 # constructs the full dockerized ruby interop test cmd.
@@ -904,6 +921,17 @@
   echo $the_cmd
 }
 
+# constructs the full dockerized python interop test cmd.
+#
+# call-seq:
+#   flags= .... # generic flags to include the command
+#   cmd=$($grpc_gen_test_cmd $flags)
+grpc_interop_gen_python_cmd() {
+  local cmd_prefix="sudo docker run grpc/python bin/bash -l -c"
+  local the_cmd="$cmd_prefix 'python -B -m interop.client --use_test_ca --use_tls $@'"
+  echo $the_cmd
+}
+
 # constructs the full dockerized java interop test cmd.
 #
 # call-seq:
diff --git a/tools/gce_setup/interop_test_runner.sh b/tools/gce_setup/interop_test_runner.sh
index ebc631c..430ad09 100755
--- a/tools/gce_setup/interop_test_runner.sh
+++ b/tools/gce_setup/interop_test_runner.sh
@@ -35,9 +35,8 @@
 
 main() {
   source grpc_docker.sh
-  # temporarily remove ping_pong and cancel_after_first_response while investigating timeout
-  test_cases=(large_unary empty_unary client_streaming server_streaming cancel_after_begin)
-  clients=(cxx java go ruby node csharp_mono)
+  test_cases=(large_unary empty_unary ping_pong client_streaming server_streaming cancel_after_begin cancel_after_first_response)
+  clients=(cxx java go ruby node python csharp_mono)
   servers=(cxx java go ruby node python)
   for test_case in "${test_cases[@]}"
   do
diff --git a/tools/run_tests/python_tests.json b/tools/run_tests/python_tests.json
index 69022af..ef483d9 100755
--- a/tools/run_tests/python_tests.json
+++ b/tools/run_tests/python_tests.json
@@ -27,9 +27,6 @@
     "module": "grpc.early_adopter.implementations_test"
   },
   {
-    "module": "grpc.framework.assembly.implementations_test"
-  },
-  {
     "module": "grpc.framework.base.packets.implementations_test"
   },
   {