Merge pull request #1012 from dklempner/nobarrier

Add a no_barrier_load atomic operation.
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/grpc_security.h b/include/grpc/grpc_security.h
index c297622..586cfcf 100644
--- a/include/grpc/grpc_security.h
+++ b/include/grpc/grpc_security.h
@@ -117,6 +117,15 @@
 grpc_credentials *grpc_jwt_credentials_create(const char *json_key,
                                               gpr_timespec token_lifetime);
 
+/* Creates an Oauth2 Refresh Token crednetials object. May return NULL if the
+   input is invalid.
+   WARNING: Do NOT use this credentials to connect to a non-google service as
+   this could result in an oauth2 token leak.
+   - json_refresh_token is the JSON string containing the refresh token itself
+     along with a client_id and client_secret. */
+grpc_credentials *grpc_refresh_token_credentials_create(
+    const char *json_refresh_token);
+
 /* Creates a fake transport security credentials object for testing. */
 grpc_credentials *grpc_fake_transport_security_credentials_create(void);
 
diff --git a/src/compiler/python_generator.cc b/src/compiler/python_generator.cc
index b217c0d..b5022d5 100644
--- a/src/compiler/python_generator.cc
+++ b/src/compiler/python_generator.cc
@@ -60,8 +60,6 @@
 using std::map;
 using std::pair;
 using std::replace;
-using std::string;
-using std::strlen;
 using std::vector;
 
 namespace grpc_python_generator {
@@ -72,14 +70,14 @@
 
 // Converts an initializer list of the form { key0, value0, key1, value1, ... }
 // into a map of key* to value*. Is merely a readability helper for later code.
-map<string, string> ListToDict(const initializer_list<string>& values) {
+map<std::string, std::string> ListToDict(const initializer_list<std::string>& values) {
   assert(values.size() % 2 == 0);
-  map<string, string> value_map;
+  map<std::string, std::string> value_map;
   auto value_iter = values.begin();
   for (unsigned i = 0; i < values.size()/2; ++i) {
-    string key = *value_iter;
+    std::string key = *value_iter;
     ++value_iter;
-    string value = *value_iter;
+    std::string value = *value_iter;
     value_map[key] = value;
     ++value_iter;
   }
@@ -113,8 +111,8 @@
 
 bool PrintServicer(const ServiceDescriptor* service,
                    Printer* out) {
-  string doc = "<fill me in later!>";
-  map<string, string> dict = ListToDict({
+  std::string doc = "<fill me in later!>";
+  map<std::string, std::string> dict = ListToDict({
         "Service", service->name(),
         "Documentation", doc,
       });
@@ -125,7 +123,7 @@
     out->Print("__metaclass__ = abc.ABCMeta\n");
     for (int i = 0; i < service->method_count(); ++i) {
       auto meth = service->method(i);
-      string arg_name = meth->client_streaming() ?
+      std::string arg_name = meth->client_streaming() ?
           "request_iterator" : "request";
       out->Print("@abc.abstractmethod\n");
       out->Print("def $Method$(self, $ArgName$, context):\n",
@@ -140,8 +138,8 @@
 }
 
 bool PrintServer(const ServiceDescriptor* service, Printer* out) {
-  string doc = "<fill me in later!>";
-  map<string, string> dict = ListToDict({
+  std::string doc = "<fill me in later!>";
+  map<std::string, std::string> dict = ListToDict({
         "Service", service->name(),
         "Documentation", doc,
       });
@@ -169,8 +167,8 @@
 
 bool PrintStub(const ServiceDescriptor* service,
                Printer* out) {
-  string doc = "<fill me in later!>";
-  map<string, string> dict = ListToDict({
+  std::string doc = "<fill me in later!>";
+  map<std::string, std::string> dict = ListToDict({
         "Service", service->name(),
         "Documentation", doc,
       });
@@ -181,7 +179,7 @@
     out->Print("__metaclass__ = abc.ABCMeta\n");
     for (int i = 0; i < service->method_count(); ++i) {
       const MethodDescriptor* meth = service->method(i);
-      string arg_name = meth->client_streaming() ?
+      std::string arg_name = meth->client_streaming() ?
           "request_iterator" : "request";
       auto methdict = ListToDict({"Method", meth->name(), "ArgName", arg_name});
       out->Print("@abc.abstractmethod\n");
@@ -198,29 +196,29 @@
 
 // TODO(protobuf team): Export `ModuleName` from protobuf's
 // `src/google/protobuf/compiler/python/python_generator.cc` file.
-string ModuleName(const string& filename) {
-  string basename = StripProto(filename);
+std::string ModuleName(const std::string& filename) {
+  std::string basename = StripProto(filename);
   basename = StringReplace(basename, "-", "_");
   basename = StringReplace(basename, "/", ".");
   return basename + "_pb2";
 }
 
 bool GetModuleAndMessagePath(const Descriptor* type,
-                             pair<string, string>* out) {
+                             pair<std::string, std::string>* out) {
   const Descriptor* path_elem_type = type;
   vector<const Descriptor*> message_path;
   do {
     message_path.push_back(path_elem_type);
     path_elem_type = path_elem_type->containing_type();
   } while (path_elem_type != nullptr);
-  string file_name = type->file()->name();
+  std::string file_name = type->file()->name();
   static const int proto_suffix_length = strlen(".proto");
   if (!(file_name.size() > static_cast<size_t>(proto_suffix_length) &&
         file_name.find_last_of(".proto") == file_name.size() - 1)) {
     return false;
   }
-  string module = ModuleName(file_name);
-  string message_type;
+  std::string module = ModuleName(file_name);
+  std::string message_type;
   for (auto path_iter = message_path.rbegin();
        path_iter != message_path.rend(); ++path_iter) {
     message_type += (*path_iter)->name() + ".";
@@ -237,21 +235,21 @@
              "Service", service->name());
   {
     IndentScope raii_create_server_indent(out);
-    map<string, string> method_description_constructors;
-    map<string, pair<string, string>> input_message_modules_and_classes;
-    map<string, pair<string, string>> output_message_modules_and_classes;
+    map<std::string, std::string> method_description_constructors;
+    map<std::string, pair<std::string, std::string>> input_message_modules_and_classes;
+    map<std::string, pair<std::string, std::string>> output_message_modules_and_classes;
     for (int i = 0; i < service->method_count(); ++i) {
       const MethodDescriptor* method = service->method(i);
-      const string method_description_constructor =
-          string(method->client_streaming() ? "stream_" : "unary_") +
-          string(method->server_streaming() ? "stream_" : "unary_") +
+      const std::string method_description_constructor =
+          std::string(method->client_streaming() ? "stream_" : "unary_") +
+          std::string(method->server_streaming() ? "stream_" : "unary_") +
           "service_description";
-      pair<string, string> input_message_module_and_class;
+      pair<std::string, std::string> input_message_module_and_class;
       if (!GetModuleAndMessagePath(method->input_type(),
                                    &input_message_module_and_class)) {
         return false;
       }
-      pair<string, string> output_message_module_and_class;
+      pair<std::string, std::string> output_message_module_and_class;
       if (!GetModuleAndMessagePath(method->output_type(),
                                    &output_message_module_and_class)) {
         return false;
@@ -272,7 +270,7 @@
     for (auto& name_and_description_constructor :
          method_description_constructors) {
       IndentScope raii_descriptions_indent(out);
-      const string method_name = name_and_description_constructor.first;
+      const std::string method_name = name_and_description_constructor.first;
       auto input_message_module_and_class =
           input_message_modules_and_classes.find(method_name);
       auto output_message_module_and_class =
@@ -306,27 +304,27 @@
 }
 
 bool PrintStubFactory(const ServiceDescriptor* service, Printer* out) {
-  map<string, string> dict = ListToDict({
+  map<std::string, std::string> dict = ListToDict({
         "Service", service->name(),
       });
   out->Print(dict, "def early_adopter_create_$Service$_stub(host, port):\n");
   {
     IndentScope raii_create_server_indent(out);
-    map<string, string> method_description_constructors;
-    map<string, pair<string, string>> input_message_modules_and_classes;
-    map<string, pair<string, string>> output_message_modules_and_classes;
+    map<std::string, std::string> method_description_constructors;
+    map<std::string, pair<std::string, std::string>> input_message_modules_and_classes;
+    map<std::string, pair<std::string, std::string>> output_message_modules_and_classes;
     for (int i = 0; i < service->method_count(); ++i) {
       const MethodDescriptor* method = service->method(i);
-      const string method_description_constructor =
-          string(method->client_streaming() ? "stream_" : "unary_") +
-          string(method->server_streaming() ? "stream_" : "unary_") +
+      const std::string method_description_constructor =
+          std::string(method->client_streaming() ? "stream_" : "unary_") +
+          std::string(method->server_streaming() ? "stream_" : "unary_") +
           "invocation_description";
-      pair<string, string> input_message_module_and_class;
+      pair<std::string, std::string> input_message_module_and_class;
       if (!GetModuleAndMessagePath(method->input_type(),
                                    &input_message_module_and_class)) {
         return false;
       }
-      pair<string, string> output_message_module_and_class;
+      pair<std::string, std::string> output_message_module_and_class;
       if (!GetModuleAndMessagePath(method->output_type(),
                                    &output_message_module_and_class)) {
         return false;
@@ -347,7 +345,7 @@
     for (auto& name_and_description_constructor :
          method_description_constructors) {
       IndentScope raii_descriptions_indent(out);
-      const string method_name = name_and_description_constructor.first;
+      const std::string method_name = name_and_description_constructor.first;
       auto input_message_module_and_class =
           input_message_modules_and_classes.find(method_name);
       auto output_message_module_and_class =
@@ -385,8 +383,8 @@
 
 }  // namespace
 
-pair<bool, string> GetServices(const FileDescriptor* file) {
-  string output;
+pair<bool, std::string> GetServices(const FileDescriptor* file) {
+  std::string output;
   {
     // Scope the output stream so it closes and finalizes output to the string.
     StringOutputStream output_stream(&output);
diff --git a/src/compiler/python_plugin.cc b/src/compiler/python_plugin.cc
index 825f15a..e7d172f 100644
--- a/src/compiler/python_plugin.cc
+++ b/src/compiler/python_plugin.cc
@@ -51,18 +51,16 @@
 using google::protobuf::compiler::PluginMain;
 using google::protobuf::io::CodedOutputStream;
 using google::protobuf::io::ZeroCopyOutputStream;
-using std::string;
-using std::strlen;
 
 class PythonGrpcGenerator : public CodeGenerator {
  public:
   PythonGrpcGenerator() {}
   ~PythonGrpcGenerator() {}
 
-  bool Generate(const FileDescriptor* file, const string& parameter,
-                GeneratorContext* context, string* error) const {
+  bool Generate(const FileDescriptor* file, const std::string& parameter,
+                GeneratorContext* context, std::string* error) const {
     // Get output file name.
-    string file_name;
+    std::string file_name;
     static const int proto_suffix_length = strlen(".proto");
     if (file->name().size() > static_cast<size_t>(proto_suffix_length) &&
         file->name().find_last_of(".proto") == file->name().size() - 1) {
@@ -77,7 +75,7 @@
         context->OpenForInsert(file_name, "module_scope"));
     CodedOutputStream coded_out(output.get());
     bool success = false;
-    string code = "";
+    std::string code = "";
     tie(success, code) = grpc_python_generator::GetServices(file);
     if (success) {
       coded_out.WriteRaw(code.data(), code.size());
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 3ad1e7e..698e099 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -46,20 +46,6 @@
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
 
-/* -- Constants. -- */
-
-#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60
-
-#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata"
-#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
-  "/computeMetadata/v1/instance/service-accounts/default/token"
-
-#define GRPC_SERVICE_ACCOUNT_HOST "www.googleapis.com"
-#define GRPC_SERVICE_ACCOUNT_TOKEN_PATH "/oauth2/v3/token"
-#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX                         \
-  "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \
-  "assertion="
-
 /* -- Common. -- */
 
 typedef struct {
@@ -671,8 +657,8 @@
   }
   gpr_asprintf(&body, "%s%s", GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX, jwt);
   memset(&request, 0, sizeof(grpc_httpcli_request));
-  request.host = GRPC_SERVICE_ACCOUNT_HOST;
-  request.path = GRPC_SERVICE_ACCOUNT_TOKEN_PATH;
+  request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
+  request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
   request.hdr_count = 1;
   request.hdrs = &header;
   request.use_ssl = 1;
@@ -703,6 +689,67 @@
   return &c->base.base;
 }
 
+/* -- RefreshToken credentials. -- */
+
+typedef struct {
+  grpc_oauth2_token_fetcher_credentials base;
+  grpc_auth_refresh_token refresh_token;
+} grpc_refresh_token_credentials;
+
+static void refresh_token_destroy(grpc_credentials *creds) {
+  grpc_refresh_token_credentials *c =
+      (grpc_refresh_token_credentials *)creds;
+  grpc_auth_refresh_token_destruct(&c->refresh_token);
+  oauth2_token_fetcher_destroy(&c->base.base);
+}
+
+static grpc_credentials_vtable refresh_token_vtable = {
+    refresh_token_destroy, oauth2_token_fetcher_has_request_metadata,
+    oauth2_token_fetcher_has_request_metadata_only,
+    oauth2_token_fetcher_get_request_metadata};
+
+static void refresh_token_fetch_oauth2(
+    grpc_credentials_metadata_request *metadata_req,
+    grpc_httpcli_response_cb response_cb, gpr_timespec deadline) {
+  grpc_refresh_token_credentials *c =
+      (grpc_refresh_token_credentials *)metadata_req->creds;
+  grpc_httpcli_header header = {"Content-Type",
+                                "application/x-www-form-urlencoded"};
+  grpc_httpcli_request request;
+  char *body = NULL;
+  gpr_asprintf(&body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
+               c->refresh_token.client_id, c->refresh_token.client_secret,
+               c->refresh_token.refresh_token);
+  memset(&request, 0, sizeof(grpc_httpcli_request));
+  request.host = GRPC_GOOGLE_OAUTH2_SERVICE_HOST;
+  request.path = GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH;
+  request.hdr_count = 1;
+  request.hdrs = &header;
+  request.use_ssl = 1;
+  grpc_httpcli_post(&request, body, strlen(body), deadline, response_cb,
+                    metadata_req);
+  gpr_free(body);
+}
+
+grpc_credentials *grpc_refresh_token_credentials_create(
+    const char *json_refresh_token) {
+  grpc_refresh_token_credentials *c;
+  grpc_auth_refresh_token refresh_token =
+      grpc_auth_refresh_token_create_from_string(json_refresh_token);
+
+  if (!grpc_auth_refresh_token_is_valid(&refresh_token)) {
+    gpr_log(GPR_ERROR,
+            "Invalid input for refresh token credentials creation");
+    return NULL;
+  }
+  c = gpr_malloc(sizeof(grpc_refresh_token_credentials));
+  memset(c, 0, sizeof(grpc_refresh_token_credentials));
+  init_oauth2_token_fetcher(&c->base, refresh_token_fetch_oauth2);
+  c->base.base.vtable = &refresh_token_vtable;
+  c->refresh_token = refresh_token;
+  return &c->base.base;
+}
+
 /* -- Fake Oauth2 credentials. -- */
 
 typedef struct {
diff --git a/src/core/security/credentials.h b/src/core/security/credentials.h
index 454e668..0f70670 100644
--- a/src/core/security/credentials.h
+++ b/src/core/security/credentials.h
@@ -64,6 +64,22 @@
 #define GRPC_GOOGLE_WELL_KNOWN_CREDENTIALS_FILE \
   "application_default_credentials.json"
 
+#define GRPC_SECURE_TOKEN_REFRESH_THRESHOLD_SECS 60
+
+#define GRPC_COMPUTE_ENGINE_METADATA_HOST "metadata"
+#define GRPC_COMPUTE_ENGINE_METADATA_TOKEN_PATH \
+  "/computeMetadata/v1/instance/service-accounts/default/token"
+
+#define GRPC_GOOGLE_OAUTH2_SERVICE_HOST "www.googleapis.com"
+#define GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH "/oauth2/v3/token"
+
+#define GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX                         \
+  "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&" \
+  "assertion="
+
+#define GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING \
+  "client_id=%s&client_secret=%s&refresh_token=%s&grant_type=refresh_token"
+
 /* --- grpc_credentials. --- */
 
 /* It is the caller's responsibility to gpr_free the result if not NULL. */
diff --git a/src/core/security/google_default_credentials.c b/src/core/security/google_default_credentials.c
index bdc907e..ebea70d 100644
--- a/src/core/security/google_default_credentials.c
+++ b/src/core/security/google_default_credentials.c
@@ -138,6 +138,23 @@
   return result;
 }
 
+/* Takes ownership of creds_path if not NULL. */
+static grpc_credentials *create_refresh_token_creds_from_path(
+    char *creds_path) {
+  grpc_credentials *result = NULL;
+  gpr_slice creds_data;
+  int file_ok = 0;
+  if (creds_path == NULL) return NULL;
+  creds_data = gpr_load_file(creds_path, &file_ok);
+  gpr_free(creds_path);
+  if (file_ok) {
+    result = grpc_refresh_token_credentials_create(
+        (const char *)GPR_SLICE_START_PTR(creds_data));
+    gpr_slice_unref(creds_data);
+  }
+  return result;
+}
+
 grpc_credentials *grpc_google_default_credentials_create(void) {
   grpc_credentials *result = NULL;
   int serving_cached_credentials = 0;
@@ -157,7 +174,7 @@
   if (result != NULL) goto end;
 
   /* Then the well-known file. */
-  result = create_jwt_creds_from_path(
+  result = create_refresh_token_creds_from_path(
       grpc_get_well_known_google_credentials_file_path());
   if (result != NULL) goto end;
 
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 40b612b..eadae33 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -52,8 +52,9 @@
 /* 1 hour max. */
 const gpr_timespec grpc_max_auth_token_lifetime = {3600, 0};
 
-#define GRPC_AUTH_JSON_KEY_TYPE_INVALID "invalid"
-#define GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT "service_account"
+#define GRPC_AUTH_JSON_TYPE_INVALID "invalid"
+#define GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT "service_account"
+#define GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER "authorized_user"
 
 #define GRPC_JWT_RSA_SHA256_ALGORITHM "RS256"
 #define GRPC_JWT_TYPE "JWT"
@@ -87,7 +88,7 @@
 
 int grpc_auth_json_key_is_valid(const grpc_auth_json_key *json_key) {
   return (json_key != NULL) &&
-         strcmp(json_key->type, GRPC_AUTH_JSON_KEY_TYPE_INVALID);
+         strcmp(json_key->type, GRPC_AUTH_JSON_TYPE_INVALID);
 }
 
 grpc_auth_json_key grpc_auth_json_key_create_from_string(
@@ -100,7 +101,7 @@
   int success = 0;
 
   memset(&result, 0, sizeof(grpc_auth_json_key));
-  result.type = GRPC_AUTH_JSON_KEY_TYPE_INVALID;
+  result.type = GRPC_AUTH_JSON_TYPE_INVALID;
   if (json == NULL) {
     gpr_log(GPR_ERROR, "Invalid json string %s", json_string);
     goto end;
@@ -108,10 +109,10 @@
 
   prop_value = json_get_string_property(json, "type");
   if (prop_value == NULL ||
-      strcmp(prop_value, GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT)) {
+      strcmp(prop_value, GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT)) {
     goto end;
   }
-  result.type = GRPC_AUTH_JSON_KEY_TYPE_SERVICE_ACCOUNT;
+  result.type = GRPC_AUTH_JSON_TYPE_SERVICE_ACCOUNT;
 
   if (!set_json_key_string_property(json, "private_key_id",
                                     &result.private_key_id) ||
@@ -148,7 +149,7 @@
 
 void grpc_auth_json_key_destruct(grpc_auth_json_key *json_key) {
   if (json_key == NULL) return;
-  json_key->type = GRPC_AUTH_JSON_KEY_TYPE_INVALID;
+  json_key->type = GRPC_AUTH_JSON_TYPE_INVALID;
   if (json_key->client_id != NULL) {
     gpr_free(json_key->client_id);
     json_key->client_id = NULL;
@@ -331,3 +332,67 @@
     grpc_jwt_encode_and_sign_override func) {
   g_jwt_encode_and_sign_override = func;
 }
+
+/* --- grpc_auth_refresh_token --- */
+
+int grpc_auth_refresh_token_is_valid(
+    const grpc_auth_refresh_token *refresh_token) {
+  return (refresh_token != NULL) &&
+         strcmp(refresh_token->type, GRPC_AUTH_JSON_TYPE_INVALID);
+}
+
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
+    const char *json_string) {
+  grpc_auth_refresh_token result;
+  char *scratchpad = gpr_strdup(json_string);
+  grpc_json *json = grpc_json_parse_string(scratchpad);
+  const char *prop_value;
+  int success = 0;
+
+  memset(&result, 0, sizeof(grpc_auth_refresh_token));
+  result.type = GRPC_AUTH_JSON_TYPE_INVALID;
+  if (json == NULL) {
+    gpr_log(GPR_ERROR, "Invalid json string %s", json_string);
+    goto end;
+  }
+
+  prop_value = json_get_string_property(json, "type");
+  if (prop_value == NULL ||
+      strcmp(prop_value, GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER)) {
+    goto end;
+  }
+  result.type = GRPC_AUTH_JSON_TYPE_AUTHORIZED_USER;
+
+  if (!set_json_key_string_property(json, "client_secret",
+                                    &result.client_secret) ||
+      !set_json_key_string_property(json, "client_id", &result.client_id) ||
+      !set_json_key_string_property(json, "refresh_token",
+                                    &result.refresh_token)) {
+    goto end;
+  }
+  success = 1;
+
+end:
+  if (json != NULL) grpc_json_destroy(json);
+  if (!success) grpc_auth_refresh_token_destruct(&result);
+  gpr_free(scratchpad);
+  return result;
+}
+
+void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token) {
+  if (refresh_token == NULL) return;
+  refresh_token->type = GRPC_AUTH_JSON_TYPE_INVALID;
+  if (refresh_token->client_id != NULL) {
+    gpr_free(refresh_token->client_id);
+    refresh_token->client_id = NULL;
+  }
+  if (refresh_token->client_secret != NULL) {
+    gpr_free(refresh_token->client_secret);
+    refresh_token->client_secret = NULL;
+  }
+  if (refresh_token->refresh_token != NULL) {
+    gpr_free(refresh_token->refresh_token);
+    refresh_token->refresh_token = NULL;
+  }
+}
+
diff --git a/src/core/security/json_token.h b/src/core/security/json_token.h
index 029ede3..197796a 100644
--- a/src/core/security/json_token.h
+++ b/src/core/security/json_token.h
@@ -44,7 +44,7 @@
 /* --- auth_json_key parsing. --- */
 
 typedef struct {
-  char *type;
+  const char *type;
   char *private_key_id;
   char *client_id;
   char *client_email;
@@ -79,4 +79,25 @@
 void grpc_jwt_encode_and_sign_set_override(
     grpc_jwt_encode_and_sign_override func);
 
+/* --- auth_refresh_token parsing. --- */
+
+typedef struct {
+  const char *type;
+  char *client_id;
+  char *client_secret;
+  char *refresh_token;
+} grpc_auth_refresh_token;
+
+/* Returns 1 if the object is valid, 0 otherwise. */
+int grpc_auth_refresh_token_is_valid(
+    const grpc_auth_refresh_token *refresh_token);
+
+/* Creates a refresh token object from string. Returns an invalid object if a
+   parsing error has been encountered. */
+grpc_auth_refresh_token grpc_auth_refresh_token_create_from_string(
+    const char *json_string);
+
+/* Destructs the object. */
+void grpc_auth_refresh_token_destruct(grpc_auth_refresh_token *refresh_token);
+
 #endif  /* GRPC_INTERNAL_CORE_SECURITY_JSON_TOKEN_H */
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index 0d01a37..2b15b2a 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -1655,7 +1655,15 @@
       if (!init_frame_parser(t)) {
         return 0;
       }
-      t->last_incoming_stream_id = t->incoming_stream_id;
+      /* t->last_incoming_stream_id is used as last-stream-id when
+         sending GOAWAY frame.
+         https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.8
+         says that last-stream-id is peer-initiated stream ID.  So,
+         since we don't have server pushed streams, client should send
+         GOAWAY last-stream-id=0 in this case. */
+      if (!t->is_client) {
+        t->last_incoming_stream_id = t->incoming_stream_id;
+      }
       if (t->incoming_frame_size == 0) {
         if (!parse_frame_slice(t, gpr_empty_slice(), 1)) {
           return 0;
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 47f645c..6ca702e 100644
--- a/src/cpp/client/secure_credentials.cc
+++ b/src/cpp/client/secure_credentials.cc
@@ -59,7 +59,7 @@
         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/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 c4b12b1..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" />
@@ -77,6 +80,9 @@
     <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
          ignored, which gives us the desired effect. -->
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/ServerSafeHandle.cs b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
index b5a5ae4..dc4781e 100644
--- a/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
+++ b/src/csharp/Grpc.Core/Internal/ServerSafeHandle.cs
@@ -53,10 +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 Int32 grpcsharp_server_add_secure_http2_port(ServerSafeHandle server, string addr, ServerCredentialsSafeHandle creds);
+        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);
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 cafdb3b..2439cdb 100644
--- a/src/csharp/Grpc.Core/Server.cs
+++ b/src/csharp/Grpc.Core/Server.cs
@@ -67,8 +67,9 @@
         }
 
         // 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);
             }
@@ -108,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))
@@ -117,7 +118,7 @@
                 }
                 callHandler.StartCall(rpcInfo.Method, rpcInfo.Call, GetCompletionQueue());
             }
-            catch(Exception e)
+            catch (Exception e)
             {
                 Console.WriteLine("Exception while handling RPC: " + e);
             }
@@ -128,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();
@@ -145,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);
@@ -161,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
index 1372e61..ab7d0b4 100644
--- a/src/csharp/Grpc.Core/ServerCredentials.cs
+++ b/src/csharp/Grpc.Core/ServerCredentials.cs
@@ -33,10 +33,14 @@
 
 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>
@@ -51,8 +55,8 @@
     /// </summary>
     public class KeyCertificatePair
     {
-        string certChain;
-        string privateKey;
+        readonly string certChain;
+        readonly string privateKey;
 
         public KeyCertificatePair(string certChain, string privateKey)
         {
@@ -82,10 +86,9 @@
     /// </summary>
     public class SslServerCredentials : ServerCredentials
     {
-        // TODO: immutable list...
-        List<KeyCertificatePair> keyCertPairs;
+        ImmutableList<KeyCertificatePair> keyCertPairs;
 
-        public SslServerCredentials(List<KeyCertificatePair> keyCertPairs)
+        public SslServerCredentials(ImmutableList<KeyCertificatePair> keyCertPairs)
         {
             this.keyCertPairs = keyCertPairs;
         }
@@ -104,4 +107,3 @@
         }
     }
 }
-
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 438bf9e..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" />
@@ -76,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 2992c42..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,7 +50,7 @@
         private class ClientOptions
         {
             public bool help;
-            public string serverHost= "127.0.0.1";
+            public string serverHost = "127.0.0.1";
             public string serverHostOverride = TestCredentials.DefaultHostOverride;
             public int? serverPort;
             public string testCase = "large_unary";
@@ -109,7 +109,7 @@
             ChannelArgs channelArgs = null;
             if (!string.IsNullOrEmpty(options.serverHostOverride))
             {
-                channelArgs = ChannelArgs.NewBuilder()
+                channelArgs = ChannelArgs.CreateBuilder()
                     .AddString(ChannelArgs.SslTargetNameOverrideKey, options.serverHostOverride).Build();
             }
 
@@ -180,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)
@@ -199,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)
@@ -256,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))
@@ -292,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 ab2d6f4..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
 {
@@ -62,7 +62,7 @@
             int port = server.AddPort(host + ":0", TestCredentials.CreateTestServerCredentials());
             server.Start();
 
-            var channelArgs = ChannelArgs.NewBuilder()
+            var channelArgs = ChannelArgs.CreateBuilder()
                 .AddString(ChannelArgs.SslTargetNameOverrideKey, TestCredentials.DefaultHostOverride).Build();
 
             channel = new Channel(host + ":" + port, TestCredentials.CreateTestClientCredentials(true), channelArgs);
@@ -117,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 24d72da..5e58028 100644
--- a/src/csharp/Grpc.IntegrationTesting/InteropServer.cs
+++ b/src/csharp/Grpc.IntegrationTesting/InteropServer.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
 {
@@ -113,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
index b31abf1..401c50b 100644
--- a/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
+++ b/src/csharp/Grpc.IntegrationTesting/TestCredentials.cs
@@ -33,15 +33,16 @@
 
 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;
-using grpc.testing;
 
 namespace Grpc.IntegrationTesting
 {
@@ -77,7 +78,7 @@
             var keyCertPair = new KeyCertificatePair(
                 File.ReadAllText(ServerCertChainPath),
                 File.ReadAllText(ServerPrivateKeyPath));
-            return new SslServerCredentials(new List<KeyCertificatePair> {keyCertPair});
+            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/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/package.json b/src/node/package.json
index f8c3ab0..29cbab9 100644
--- a/src/node/package.json
+++ b/src/node/package.json
@@ -1,6 +1,6 @@
 {
   "name": "grpc",
-  "version": "0.5.3",
+  "version": "0.5.4",
   "author": "Google Inc.",
   "description": "gRPC Library for Node",
   "homepage": "http://www.grpc.io/",
diff --git a/src/php/ext/grpc/call.c b/src/php/ext/grpc/call.c
index df0635d..7987471 100644
--- a/src/php/ext/grpc/call.c
+++ b/src/php/ext/grpc/call.c
@@ -56,6 +56,8 @@
 #include "completion_queue.h"
 #include "byte_buffer.h"
 
+zend_class_entry *grpc_ce_call;
+
 /* Frees and destroys an instance of wrapped_grpc_call */
 void free_wrapped_grpc_call(void *object TSRMLS_DC) {
   wrapped_grpc_call *call = (wrapped_grpc_call *)object;
diff --git a/src/php/ext/grpc/call.h b/src/php/ext/grpc/call.h
index 827e9a2..bce5d82 100644
--- a/src/php/ext/grpc/call.h
+++ b/src/php/ext/grpc/call.h
@@ -57,7 +57,7 @@
   } while (0)
 
 /* Class entry for the Call PHP class */
-zend_class_entry *grpc_ce_call;
+extern zend_class_entry *grpc_ce_call;
 
 /* Wrapper struct for grpc_call that can be associated with a PHP object */
 typedef struct wrapped_grpc_call {
diff --git a/src/php/ext/grpc/channel.c b/src/php/ext/grpc/channel.c
index d6296f9..5e99332 100644
--- a/src/php/ext/grpc/channel.c
+++ b/src/php/ext/grpc/channel.c
@@ -55,6 +55,8 @@
 #include "server.h"
 #include "credentials.h"
 
+zend_class_entry *grpc_ce_channel;
+
 /* Frees and destroys an instance of wrapped_grpc_channel */
 void free_wrapped_grpc_channel(void *object TSRMLS_DC) {
   wrapped_grpc_channel *channel = (wrapped_grpc_channel *)object;
diff --git a/src/php/ext/grpc/channel.h b/src/php/ext/grpc/channel.h
index f426a25..2c79668 100755
--- a/src/php/ext/grpc/channel.h
+++ b/src/php/ext/grpc/channel.h
@@ -46,7 +46,7 @@
 #include "grpc/grpc.h"
 
 /* Class entry for the PHP Channel class */
-zend_class_entry *grpc_ce_channel;
+extern zend_class_entry *grpc_ce_channel;
 
 /* Wrapper struct for grpc_channel that can be associated with a PHP object */
 typedef struct wrapped_grpc_channel {
diff --git a/src/php/ext/grpc/completion_queue.c b/src/php/ext/grpc/completion_queue.c
index 30c871b..93abf5d 100644
--- a/src/php/ext/grpc/completion_queue.c
+++ b/src/php/ext/grpc/completion_queue.c
@@ -52,6 +52,8 @@
 #include "event.h"
 #include "timeval.h"
 
+zend_class_entry *grpc_ce_completion_queue;
+
 /* Frees and destroys a wrapped instance of grpc_completion_queue */
 void free_wrapped_grpc_completion_queue(void *object TSRMLS_DC) {
   wrapped_grpc_completion_queue *queue = NULL;
diff --git a/src/php/ext/grpc/completion_queue.h b/src/php/ext/grpc/completion_queue.h
index 6ce1df7..1d386cc 100755
--- a/src/php/ext/grpc/completion_queue.h
+++ b/src/php/ext/grpc/completion_queue.h
@@ -46,7 +46,7 @@
 #include "grpc/grpc.h"
 
 /* Class entry for the PHP CompletionQueue class */
-zend_class_entry *grpc_ce_completion_queue;
+extern zend_class_entry *grpc_ce_completion_queue;
 
 /* Wrapper class for grpc_completion_queue that can be associated with a
    PHP object */
diff --git a/src/php/ext/grpc/credentials.c b/src/php/ext/grpc/credentials.c
index 6d8f59f..a94b0ea 100644
--- a/src/php/ext/grpc/credentials.c
+++ b/src/php/ext/grpc/credentials.c
@@ -49,6 +49,8 @@
 #include "grpc/grpc.h"
 #include "grpc/grpc_security.h"
 
+zend_class_entry *grpc_ce_credentials;
+
 /* Frees and destroys an instance of wrapped_grpc_credentials */
 void free_wrapped_grpc_credentials(void *object TSRMLS_DC) {
   wrapped_grpc_credentials *creds = (wrapped_grpc_credentials *)object;
diff --git a/src/php/ext/grpc/credentials.h b/src/php/ext/grpc/credentials.h
index 3ff75af..86d7ae5 100755
--- a/src/php/ext/grpc/credentials.h
+++ b/src/php/ext/grpc/credentials.h
@@ -47,7 +47,7 @@
 #include "grpc/grpc_security.h"
 
 /* Class entry for the Credentials PHP class */
-zend_class_entry *grpc_ce_credentials;
+extern zend_class_entry *grpc_ce_credentials;
 
 /* Wrapper struct for grpc_credentials that can be associated with a PHP
  * object */
diff --git a/src/php/ext/grpc/server.c b/src/php/ext/grpc/server.c
index 00d08c6..a5cfd95 100644
--- a/src/php/ext/grpc/server.c
+++ b/src/php/ext/grpc/server.c
@@ -56,6 +56,8 @@
 #include "channel.h"
 #include "server_credentials.h"
 
+zend_class_entry *grpc_ce_server;
+
 /* Frees and destroys an instance of wrapped_grpc_server */
 void free_wrapped_grpc_server(void *object TSRMLS_DC) {
   wrapped_grpc_server *server = (wrapped_grpc_server *)object;
diff --git a/src/php/ext/grpc/server.h b/src/php/ext/grpc/server.h
index ecef4c6..b55689c 100755
--- a/src/php/ext/grpc/server.h
+++ b/src/php/ext/grpc/server.h
@@ -46,7 +46,7 @@
 #include "grpc/grpc.h"
 
 /* Class entry for the Server PHP class */
-zend_class_entry *grpc_ce_server;
+extern zend_class_entry *grpc_ce_server;
 
 /* Wrapper struct for grpc_server that can be associated with a PHP object */
 typedef struct wrapped_grpc_server {
diff --git a/src/php/ext/grpc/server_credentials.c b/src/php/ext/grpc/server_credentials.c
index 8aaa86c..df64e65 100644
--- a/src/php/ext/grpc/server_credentials.c
+++ b/src/php/ext/grpc/server_credentials.c
@@ -49,6 +49,8 @@
 #include "grpc/grpc.h"
 #include "grpc/grpc_security.h"
 
+zend_class_entry *grpc_ce_server_credentials;
+
 /* Frees and destroys an instace of wrapped_grpc_server_credentials */
 void free_wrapped_grpc_server_credentials(void *object TSRMLS_DC) {
   wrapped_grpc_server_credentials *creds =
diff --git a/src/php/ext/grpc/server_credentials.h b/src/php/ext/grpc/server_credentials.h
index ce2a4da..8ed3697 100755
--- a/src/php/ext/grpc/server_credentials.h
+++ b/src/php/ext/grpc/server_credentials.h
@@ -47,7 +47,7 @@
 #include "grpc/grpc_security.h"
 
 /* Class entry for the Server_Credentials PHP class */
-zend_class_entry *grpc_ce_server_credentials;
+extern zend_class_entry *grpc_ce_server_credentials;
 
 /* Wrapper struct for grpc_server_credentials that can be associated with a PHP
  * object */
diff --git a/src/php/ext/grpc/timeval.c b/src/php/ext/grpc/timeval.c
index 5b0142c..f90f006 100644
--- a/src/php/ext/grpc/timeval.c
+++ b/src/php/ext/grpc/timeval.c
@@ -50,6 +50,8 @@
 #include "grpc/grpc.h"
 #include "grpc/support/time.h"
 
+zend_class_entry *grpc_ce_timeval;
+
 /* Frees and destroys an instance of wrapped_grpc_call */
 void free_wrapped_grpc_timeval(void *object TSRMLS_DC) { efree(object); }
 
diff --git a/src/php/ext/grpc/timeval.h b/src/php/ext/grpc/timeval.h
index 0e215fc..e3183f6 100755
--- a/src/php/ext/grpc/timeval.h
+++ b/src/php/ext/grpc/timeval.h
@@ -47,7 +47,7 @@
 #include "grpc/support/time.h"
 
 /* Class entry for the Timeval PHP Class */
-zend_class_entry *grpc_ce_timeval;
+extern zend_class_entry *grpc_ce_timeval;
 
 /* Wrapper struct for timeval that can be associated with a PHP object */
 typedef struct wrapped_grpc_timeval {
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/early_adopter/implementations.py b/src/python/src/grpc/early_adopter/implementations.py
index 1c02f9e..6fe9059 100644
--- a/src/python/src/grpc/early_adopter/implementations.py
+++ b/src/python/src/grpc/early_adopter/implementations.py
@@ -71,7 +71,8 @@
             _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._breakdown.response_serializers, None, self._key_chain_pairs,
+            port=self._port)
         self._back.join_fore_link(self._fore_link)
         self._fore_link.join_rear_link(self._back)
         self._fore_link.start()
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/security/credentials_test.c b/test/core/security/credentials_test.c
index 0784624..d1d1ec1 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -84,6 +84,13 @@
     "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
     "com\", \"type\": \"service_account\" }";
 
+/* Test refresh token. */
+static const char test_refresh_token_str[] =
+    "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
+    "  \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
+    "  \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
+    "  \"type\": \"authorized_user\"}";
+
 static const char valid_oauth2_json_response[] =
     "{\"access_token\":\"ya29.AHES6ZRN3-HlhAPya30GnW_bHSb_\","
     " \"expires_in\":3599, "
@@ -97,10 +104,6 @@
     "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImY0OTRkN2M1YWU2MGRmOTcyNmM4YW"
     "U0MDcyZTViYTdmZDkwODg2YzcifQ";
 
-static const char expected_service_account_http_body_prefix[] =
-    "grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Ajwt-bearer&"
-    "assertion=";
-
 static const char test_service_url[] = "https://foo.com/foo.v1";
 static const char other_test_service_url[] = "https://bar.com/bar.v1";
 
@@ -463,6 +466,87 @@
   grpc_httpcli_set_override(NULL, NULL);
 }
 
+static void validate_refresh_token_http_request(
+    const grpc_httpcli_request *request, const char *body, size_t body_size) {
+  /* The content of the assertion is tested extensively in json_token_test. */
+  char *expected_body = NULL;
+  GPR_ASSERT(body != NULL);
+  GPR_ASSERT(body_size != 0);
+  gpr_asprintf(&expected_body, GRPC_REFRESH_TOKEN_POST_BODY_FORMAT_STRING,
+               "32555999999.apps.googleusercontent.com",
+               "EmssLNjJy1332hD4KFsecret",
+               "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42");
+  GPR_ASSERT(strlen(expected_body) == body_size);
+  GPR_ASSERT(memcmp(expected_body, body, body_size) == 0);
+  gpr_free(expected_body);
+  GPR_ASSERT(request->use_ssl);
+  GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0);
+  GPR_ASSERT(strcmp(request->path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
+  GPR_ASSERT(request->hdr_count == 1);
+  GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
+  GPR_ASSERT(strcmp(request->hdrs[0].value,
+                    "application/x-www-form-urlencoded") == 0);
+}
+
+static int refresh_token_httpcli_post_success(
+    const grpc_httpcli_request *request, const char *body, size_t body_size,
+    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
+    void *user_data) {
+  grpc_httpcli_response response =
+      http_response(200, valid_oauth2_json_response);
+  validate_refresh_token_http_request(request, body, body_size);
+  on_response(user_data, &response);
+  return 1;
+}
+
+static int refresh_token_httpcli_post_failure(
+    const grpc_httpcli_request *request, const char *body, size_t body_size,
+    gpr_timespec deadline, grpc_httpcli_response_cb on_response,
+    void *user_data) {
+  grpc_httpcli_response response = http_response(403, "Not Authorized.");
+  validate_refresh_token_http_request(request, body, body_size);
+  on_response(user_data, &response);
+  return 1;
+}
+
+static void test_refresh_token_creds_success(void) {
+  grpc_credentials *refresh_token_creds =
+      grpc_refresh_token_credentials_create(test_refresh_token_str);
+  GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds));
+  GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds));
+
+  /* First request: http get should be called. */
+  grpc_httpcli_set_override(httpcli_get_should_not_be_called,
+                            refresh_token_httpcli_post_success);
+  grpc_credentials_get_request_metadata(refresh_token_creds, test_service_url,
+                                        on_oauth2_creds_get_metadata_success,
+                                        (void *)test_user_data);
+
+  /* Second request: the cached token should be served directly. */
+  grpc_httpcli_set_override(httpcli_get_should_not_be_called,
+                            httpcli_post_should_not_be_called);
+  grpc_credentials_get_request_metadata(refresh_token_creds, test_service_url,
+                                        on_oauth2_creds_get_metadata_success,
+                                        (void *)test_user_data);
+
+  grpc_credentials_unref(refresh_token_creds);
+  grpc_httpcli_set_override(NULL, NULL);
+}
+
+static void test_refresh_token_creds_failure(void) {
+  grpc_credentials *refresh_token_creds =
+      grpc_refresh_token_credentials_create(test_refresh_token_str);
+  grpc_httpcli_set_override(httpcli_get_should_not_be_called,
+                            refresh_token_httpcli_post_failure);
+  GPR_ASSERT(grpc_credentials_has_request_metadata(refresh_token_creds));
+  GPR_ASSERT(grpc_credentials_has_request_metadata_only(refresh_token_creds));
+  grpc_credentials_get_request_metadata(refresh_token_creds, test_service_url,
+                                        on_oauth2_creds_get_metadata_failure,
+                                        (void *)test_user_data);
+  grpc_credentials_unref(refresh_token_creds);
+  grpc_httpcli_set_override(NULL, NULL);
+}
+
 static void validate_jwt_encode_and_sign_params(
     const grpc_auth_json_key *json_key, const char *scope,
     gpr_timespec token_lifetime) {
@@ -515,13 +599,13 @@
   GPR_ASSERT(body != NULL);
   GPR_ASSERT(body_size != 0);
   gpr_asprintf(&expected_body, "%s%s",
-               expected_service_account_http_body_prefix, test_signed_jwt);
+               GRPC_SERVICE_ACCOUNT_POST_BODY_PREFIX, test_signed_jwt);
   GPR_ASSERT(strlen(expected_body) == body_size);
-  GPR_ASSERT(!memcmp(expected_body, body, body_size));
+  GPR_ASSERT(memcmp(expected_body, body, body_size) == 0);
   gpr_free(expected_body);
   GPR_ASSERT(request->use_ssl);
-  GPR_ASSERT(strcmp(request->host, "www.googleapis.com") == 0);
-  GPR_ASSERT(strcmp(request->path, "/oauth2/v3/token") == 0);
+  GPR_ASSERT(strcmp(request->host, GRPC_GOOGLE_OAUTH2_SERVICE_HOST) == 0);
+  GPR_ASSERT(strcmp(request->path, GRPC_GOOGLE_OAUTH2_SERVICE_TOKEN_PATH) == 0);
   GPR_ASSERT(request->hdr_count == 1);
   GPR_ASSERT(strcmp(request->hdrs[0].key, "Content-Type") == 0);
   GPR_ASSERT(strcmp(request->hdrs[0].value,
@@ -711,6 +795,8 @@
   test_ssl_oauth2_iam_composite_creds();
   test_compute_engine_creds_success();
   test_compute_engine_creds_failure();
+  test_refresh_token_creds_success();
+  test_refresh_token_creds_failure();
   test_service_account_creds_success();
   test_service_account_creds_http_failure();
   test_service_account_creds_signing_failure();
diff --git a/test/core/security/fetch_oauth2.c b/test/core/security/fetch_oauth2.c
index 748a598..cc847c8 100644
--- a/test/core/security/fetch_oauth2.c
+++ b/test/core/security/fetch_oauth2.c
@@ -34,7 +34,6 @@
 #include <stdio.h>
 #include <string.h>
 
-#include "src/core/security/credentials.h"
 #include <grpc/grpc.h>
 #include <grpc/grpc_security.h>
 #include <grpc/support/alloc.h>
@@ -43,6 +42,9 @@
 #include <grpc/support/slice.h>
 #include <grpc/support/sync.h>
 
+#include "src/core/security/credentials.h"
+#include "src/core/support/file.h"
+
 typedef struct {
   gpr_cv cv;
   gpr_mu mu;
@@ -74,50 +76,50 @@
 
 static grpc_credentials *create_service_account_creds(
     const char *json_key_file_path, const char *scope) {
-  char json_key[8192]; /* Should be plenty. */
-  char *current = json_key;
-  FILE *json_key_file = fopen(json_key_file_path, "r");
-  if (json_key_file == NULL) {
-    gpr_log(GPR_ERROR, "Invalid path for json key file: %s.",
-            json_key_file_path);
+  int success;
+  gpr_slice json_key = gpr_load_file(json_key_file_path, &success);
+  if (!success) {
+    gpr_log(GPR_ERROR, "Could not read file %s.", json_key_file_path);
     exit(1);
   }
+  return grpc_service_account_credentials_create(
+      (const char *)GPR_SLICE_START_PTR(json_key), scope,
+      grpc_max_auth_token_lifetime);
+}
 
-  do {
-    size_t bytes_read = fread(
-        current, 1, sizeof(json_key) - (current - json_key), json_key_file);
-    if (bytes_read == 0) {
-      if (!feof(json_key_file)) {
-        gpr_log(GPR_ERROR, "Error occured while reading %s.",
-                json_key_file_path);
-        exit(1);
-      }
-      break;
-    }
-    current += bytes_read;
-  } while (sizeof(json_key) > (size_t)(current - json_key));
-
-  if ((current - json_key) == sizeof(json_key)) {
-    gpr_log(GPR_ERROR, "Json key file %s exceeds size limit (%d bytes).",
-            json_key_file_path, (int)sizeof(json_key));
+static grpc_credentials *create_refresh_token_creds(
+    const char *json_refresh_token_file_path) {
+  int success;
+  gpr_slice refresh_token =
+      gpr_load_file(json_refresh_token_file_path, &success);
+  if (!success) {
+    gpr_log(GPR_ERROR, "Could not read file %s.", json_refresh_token_file_path);
     exit(1);
   }
-  fclose(json_key_file);
-
-  return grpc_service_account_credentials_create(json_key, scope,
-                                                 grpc_max_auth_token_lifetime);
+  return grpc_refresh_token_credentials_create(
+      (const char *)GPR_SLICE_START_PTR(refresh_token));
 }
 
 int main(int argc, char **argv) {
   synchronizer sync;
   grpc_credentials *creds = NULL;
   char *json_key_file_path = NULL;
+  char *json_refresh_token_file_path = NULL;
   int use_gce = 0;
   char *scope = NULL;
   gpr_cmdline *cl = gpr_cmdline_create("fetch_oauth2");
-  gpr_cmdline_add_string(cl, "json_key", "File path of the json key.",
+  gpr_cmdline_add_string(cl, "json_key",
+                         "File path of the json key. Mutually exclusive with "
+                         "--json_refresh_token.",
                          &json_key_file_path);
-  gpr_cmdline_add_string(cl, "scope", "Space delimited permissions.", &scope);
+  gpr_cmdline_add_string(cl, "json_refresh_token",
+                         "File path of the json refresh token. Mutually "
+                         "exclusive with --json_key.",
+                         &json_refresh_token_file_path);
+  gpr_cmdline_add_string(cl, "scope",
+                         "Space delimited permissions. Only used for "
+                         "--json_key, ignored otherwise.",
+                         &scope);
   gpr_cmdline_add_flag(
       cl, "gce",
       "Get a token from the GCE metadata server (only works in GCE).",
@@ -126,6 +128,12 @@
 
   grpc_init();
 
+  if (json_key_file_path != NULL && json_refresh_token_file_path != NULL) {
+    gpr_log(GPR_ERROR,
+            "--json_key and --json_refresh_token are mutually exclusive.");
+    exit(1);
+  }
+
   if (use_gce) {
     if (json_key_file_path != NULL || scope != NULL) {
       gpr_log(GPR_INFO,
@@ -137,6 +145,15 @@
       gpr_log(GPR_ERROR, "Could not create gce credentials.");
       exit(1);
     }
+  } else if (json_refresh_token_file_path != NULL) {
+    creds = create_refresh_token_creds(json_refresh_token_file_path);
+    if (creds == NULL) {
+      gpr_log(GPR_ERROR,
+              "Could not create refresh token creds. %s does probably not "
+              "contain a valid json refresh token.",
+              json_refresh_token_file_path);
+      exit(1);
+    }
   } else {
     if (json_key_file_path == NULL) {
       gpr_log(GPR_ERROR, "Missing --json_key option.");
diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c
index ca5b889..b43e042 100644
--- a/test/core/security/json_token_test.c
+++ b/test/core/security/json_token_test.c
@@ -78,6 +78,13 @@
     "\"777-abaslkan11hlb6nmim3bpspl31ud.apps.googleusercontent."
     "com\", \"type\": \"service_account\" }";
 
+/* Test refresh token. */
+static const char test_refresh_token_str[] =
+    "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
+    "  \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
+    "  \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
+    "  \"type\": \"authorized_user\"}";
+
 static const char test_scope[] = "myperm1 myperm2";
 
 static const char test_service_url[] = "https://foo.com/foo.v1";
@@ -419,6 +426,64 @@
                            jwt_creds_check_jwt_claim);
 }
 
+static void test_parse_refresh_token_success(void) {
+  grpc_auth_refresh_token refresh_token =
+      grpc_auth_refresh_token_create_from_string(test_refresh_token_str);
+  GPR_ASSERT(grpc_auth_refresh_token_is_valid(&refresh_token));
+  GPR_ASSERT(refresh_token.type != NULL &&
+             (strcmp(refresh_token.type, "authorized_user") == 0));
+  GPR_ASSERT(refresh_token.client_id != NULL &&
+             (strcmp(refresh_token.client_id,
+                     "32555999999.apps.googleusercontent.com") == 0));
+  GPR_ASSERT(
+      refresh_token.client_secret != NULL &&
+      (strcmp(refresh_token.client_secret, "EmssLNjJy1332hD4KFsecret") == 0));
+  GPR_ASSERT(refresh_token.refresh_token != NULL &&
+             (strcmp(refresh_token.refresh_token,
+                     "1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42") == 0));
+  grpc_auth_refresh_token_destruct(&refresh_token);
+}
+
+static void test_parse_refresh_token_failure_no_type(void) {
+  const char refresh_token_str[] =
+      "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
+      "  \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
+      "  \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\"}";
+  grpc_auth_refresh_token refresh_token =
+      grpc_auth_refresh_token_create_from_string(refresh_token_str);
+  GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
+}
+
+static void test_parse_refresh_token_failure_no_client_id(void) {
+  const char refresh_token_str[] =
+      "{ \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
+      "  \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
+      "  \"type\": \"authorized_user\"}";
+  grpc_auth_refresh_token refresh_token =
+      grpc_auth_refresh_token_create_from_string(refresh_token_str);
+  GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
+}
+
+static void test_parse_refresh_token_failure_no_client_secret(void) {
+  const char refresh_token_str[] =
+      "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
+      "  \"refresh_token\": \"1/Blahblasj424jladJDSGNf-u4Sua3HDA2ngjd42\","
+      "  \"type\": \"authorized_user\"}";
+  grpc_auth_refresh_token refresh_token =
+      grpc_auth_refresh_token_create_from_string(refresh_token_str);
+  GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
+}
+
+static void test_parse_refresh_token_failure_no_refresh_token(void) {
+  const char refresh_token_str[] =
+      "{ \"client_id\": \"32555999999.apps.googleusercontent.com\","
+      "  \"client_secret\": \"EmssLNjJy1332hD4KFsecret\","
+      "  \"type\": \"authorized_user\"}";
+  grpc_auth_refresh_token refresh_token =
+      grpc_auth_refresh_token_create_from_string(refresh_token_str);
+  GPR_ASSERT(!grpc_auth_refresh_token_is_valid(&refresh_token));
+}
+
 int main(int argc, char **argv) {
   grpc_test_init(argc, argv);
   test_parse_json_key_success();
@@ -430,5 +495,10 @@
   test_parse_json_key_failure_no_private_key();
   test_service_account_creds_jwt_encode_and_sign();
   test_jwt_creds_jwt_encode_and_sign();
+  test_parse_refresh_token_success();
+  test_parse_refresh_token_failure_no_type();
+  test_parse_refresh_token_failure_no_client_id();
+  test_parse_refresh_token_failure_no_client_secret();
+  test_parse_refresh_token_failure_no_refresh_token();
   return 0;
 }
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