Merge pull request #11118 from muxi/backward-compat-dev

Add Backward compatibility API to C++
diff --git a/doc/workarounds.md b/doc/workarounds.md
new file mode 100644
index 0000000..bc51186
--- /dev/null
+++ b/doc/workarounds.md
@@ -0,0 +1,19 @@
+# gRPC Server Backward Compatibility Issues and Workarounds Manageent
+
+## Introduction
+This document lists the workarounds implemented on gRPC servers for record and reference when users need to enable a certain workaround.
+
+## Workaround List
+
+### Cronet Compression
+
+**Workaround ID:** WORKAROUND\_ID\_CRONET\_COMPRESSION
+
+**Date added:** May 06, 2017
+
+**Status:** Implemented in C core and C++
+
+**Issue:** Before version v1.3.0-dev, gRPC iOS client's Cronet transport did not implement compression. However the clients still claim to support compression. As a result, a client fails to parse received message when the message is compressed.
+The problem above was resolved in gRPC v1.3.0-dev. For backward compatibility, a server must forcingly disable compression for gRPC clients of version lower than or equal to v1.3.0-dev.
+
+**Workaround Description:** Implemented as a server channel filter in C core.  The filter identifies the version of peer client with incoming `user-agent` header of each call. If the client's gRPC version is lower that or equal to v1.3.x, a flag GRPC_WRITE_NO_COMPRESS is marked for all send_message ops which prevents compression of the messages to be sent out.
diff --git a/include/grpc++/server_builder.h b/include/grpc++/server_builder.h
index 5a85776..2185b28 100644
--- a/include/grpc++/server_builder.h
+++ b/include/grpc++/server_builder.h
@@ -46,6 +46,7 @@
 #include <grpc/compression.h>
 #include <grpc/support/cpu.h>
 #include <grpc/support/useful.h>
+#include <grpc/support/workaround_list.h>
 
 struct grpc_resource_quota;
 
@@ -184,6 +185,11 @@
   static void InternalAddPluginFactory(
       std::unique_ptr<ServerBuilderPlugin> (*CreatePlugin)());
 
+  /// Enable a server workaround. Do not use unless you know what the workaround
+  /// does. For explanation and detailed descriptions of workarounds, see
+  /// doc/workarounds.md.
+  ServerBuilder& EnableWorkaround(grpc_workaround_list id);
+
  private:
   friend class ::grpc::testing::ServerBuilderPluginTest;
 
diff --git a/include/grpc/support/workaround_list.h b/include/grpc/support/workaround_list.h
index 6a8aa1f..ec47665 100644
--- a/include/grpc/support/workaround_list.h
+++ b/include/grpc/support/workaround_list.h
@@ -36,7 +36,7 @@
 
 /* The list of IDs of server workarounds currently maintained by gRPC. For
  * explanation and detailed descriptions of workarounds, see
- * /docs/workarounds.md
+ * /doc/workarounds.md
  */
 typedef enum {
   GRPC_WORKAROUND_ID_CRONET_COMPRESSION = 0,
diff --git a/src/cpp/server/server_builder.cc b/src/cpp/server/server_builder.cc
index 2ead048..6dca6a6 100644
--- a/src/cpp/server/server_builder.cc
+++ b/src/cpp/server/server_builder.cc
@@ -358,4 +358,14 @@
   (*g_plugin_factory_list).push_back(CreatePlugin);
 }
 
+ServerBuilder& ServerBuilder::EnableWorkaround(grpc_workaround_list id) {
+  switch (id) {
+    case GRPC_WORKAROUND_ID_CRONET_COMPRESSION:
+      return AddChannelArgument(GRPC_ARG_WORKAROUND_CRONET_COMPRESSION, 1);
+    default:
+      gpr_log(GPR_ERROR, "Workaround %u does not exist or is obsolete.", id);
+      return *this;
+  }
+}
+
 }  // namespace grpc
diff --git a/tools/doxygen/Doxyfile.c++ b/tools/doxygen/Doxyfile.c++
index b7531bc..b6f2857 100644
--- a/tools/doxygen/Doxyfile.c++
+++ b/tools/doxygen/Doxyfile.c++
@@ -794,6 +794,7 @@
 doc/stress_test_framework.md \
 doc/unit_testing.md \
 doc/wait-for-ready.md \
+doc/workarounds.md \
 include/grpc++/alarm.h \
 include/grpc++/channel.h \
 include/grpc++/client_context.h \
diff --git a/tools/doxygen/Doxyfile.c++.internal b/tools/doxygen/Doxyfile.c++.internal
index c8ebb0d..5242172 100644
--- a/tools/doxygen/Doxyfile.c++.internal
+++ b/tools/doxygen/Doxyfile.c++.internal
@@ -794,6 +794,7 @@
 doc/stress_test_framework.md \
 doc/unit_testing.md \
 doc/wait-for-ready.md \
+doc/workarounds.md \
 include/grpc++/alarm.h \
 include/grpc++/channel.h \
 include/grpc++/client_context.h \
diff --git a/tools/doxygen/Doxyfile.core b/tools/doxygen/Doxyfile.core
index 74e76bf..c5ae421 100644
--- a/tools/doxygen/Doxyfile.core
+++ b/tools/doxygen/Doxyfile.core
@@ -794,6 +794,7 @@
 doc/stress_test_framework.md \
 doc/unit_testing.md \
 doc/wait-for-ready.md \
+doc/workarounds.md \
 include/grpc/byte_buffer.h \
 include/grpc/byte_buffer_reader.h \
 include/grpc/census.h \
diff --git a/tools/doxygen/Doxyfile.core.internal b/tools/doxygen/Doxyfile.core.internal
index d5eeebe..eb0883b 100644
--- a/tools/doxygen/Doxyfile.core.internal
+++ b/tools/doxygen/Doxyfile.core.internal
@@ -794,6 +794,7 @@
 doc/stress_test_framework.md \
 doc/unit_testing.md \
 doc/wait-for-ready.md \
+doc/workarounds.md \
 include/grpc/byte_buffer.h \
 include/grpc/byte_buffer_reader.h \
 include/grpc/census.h \