THRIFT-2423 Facebook's THeader protocol and transport for cpp
Client: C++ Library, Compiler
Patch: Dave Watson rebased by Nobuaki Sukegawa

This closes #357 and closes #677
diff --git a/test/cpp/CMakeLists.txt b/test/cpp/CMakeLists.txt
index 2d75f2e..67d9510 100755
--- a/test/cpp/CMakeLists.txt
+++ b/test/cpp/CMakeLists.txt
@@ -54,23 +54,24 @@
 LINK_AGAINST_THRIFT_LIBRARY(crossstressgencpp thrift)
 
 add_executable(TestServer src/TestServer.cpp)
-target_link_libraries(TestServer crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB})
+target_link_libraries(TestServer crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB} ${ZLIB_LIBRARIES})
 LINK_AGAINST_THRIFT_LIBRARY(TestServer thrift)
 LINK_AGAINST_THRIFT_LIBRARY(TestServer thriftnb)
+LINK_AGAINST_THRIFT_LIBRARY(TestServer thriftnb)
 
 add_executable(TestClient src/TestClient.cpp)
-target_link_libraries(TestClient crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB})
+target_link_libraries(TestClient crosstestgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB} ${ZLIB_LIBRARIES})
 LINK_AGAINST_THRIFT_LIBRARY(TestClient thrift)
 LINK_AGAINST_THRIFT_LIBRARY(TestClient thriftnb)
 
 add_executable(StressTest src/StressTest.cpp)
-target_link_libraries(StressTest crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB})
+target_link_libraries(StressTest crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB} ${ZLIB_LIBRARIES})
 LINK_AGAINST_THRIFT_LIBRARY(StressTest thrift)
 LINK_AGAINST_THRIFT_LIBRARY(StressTest thriftnb)
 add_test(NAME StressTest COMMAND StressTest)
 
 add_executable(StressTestNonBlocking src/StressTestNonBlocking.cpp)
-target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB})
+target_link_libraries(StressTestNonBlocking crossstressgencpp ${Boost_LIBRARIES} ${LIBEVENT_LIB} ${ZLIB_LIBRARIES})
 LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thrift)
 LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftnb)
 LINK_AGAINST_THRIFT_LIBRARY(StressTestNonBlocking thriftz)
diff --git a/test/cpp/Makefile.am b/test/cpp/Makefile.am
index bc026b2..c609a71 100755
--- a/test/cpp/Makefile.am
+++ b/test/cpp/Makefile.am
@@ -69,7 +69,7 @@
 	$(top_builddir)/lib/cpp/libthrift.la \
 	$(top_builddir)/lib/cpp/libthriftz.la \
 	$(top_builddir)/lib/cpp/libthriftnb.la \
-	-levent -lboost_program_options -lboost_system -lboost_filesystem
+	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)
 
 TestClient_SOURCES = \
 	src/TestClient.cpp
@@ -79,7 +79,7 @@
 	$(top_builddir)/lib/cpp/libthrift.la \
 	$(top_builddir)/lib/cpp/libthriftz.la \
 	$(top_builddir)/lib/cpp/libthriftnb.la \
-	-levent -lboost_program_options -lboost_system -lboost_filesystem
+	-levent -lboost_program_options -lboost_system -lboost_filesystem $(ZLIB_LIBS)
 
 StressTest_SOURCES = \
 	src/StressTest.cpp
diff --git a/test/cpp/src/TestClient.cpp b/test/cpp/src/TestClient.cpp
index 2736ee8..47539dc 100644
--- a/test/cpp/src/TestClient.cpp
+++ b/test/cpp/src/TestClient.cpp
@@ -23,6 +23,7 @@
 #include <iostream>
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/protocol/TCompactProtocol.h>
+#include <thrift/protocol/THeaderProtocol.h>
 #include <thrift/protocol/TJSONProtocol.h>
 #include <thrift/transport/THttpClient.h>
 #include <thrift/transport/TTransportUtils.h>
@@ -170,7 +171,7 @@
       "Transport: buffered, framed, http, evhttp")(
       "protocol",
       boost::program_options::value<string>(&protocol_type)->default_value(protocol_type),
-      "Protocol: binary, compact, json")("ssl", "Encrypted Transport using SSL")(
+      "Protocol: binary, header, compact, json")("ssl", "Encrypted Transport using SSL")(
       "testloops,n",
       boost::program_options::value<int>(&numTests)->default_value(numTests),
       "Number of Tests")("noinsane", "Do not run insanity test");
@@ -188,6 +189,7 @@
     if (!protocol_type.empty()) {
       if (protocol_type == "binary") {
       } else if (protocol_type == "compact") {
+      } else if (protocol_type == "header") {
       } else if (protocol_type == "json") {
       } else {
         throw invalid_argument("Unknown protocol type " + protocol_type);
@@ -266,6 +268,9 @@
   } else if (protocol_type.compare("compact") == 0) {
     boost::shared_ptr<TProtocol> compactProtocol(new TCompactProtocol(transport));
     protocol = compactProtocol;
+  } else if (protocol_type == "header") {
+    boost::shared_ptr<TProtocol> headerProtocol(new THeaderProtocol(transport));
+    protocol = headerProtocol;
   } else {
     boost::shared_ptr<TBinaryProtocol> binaryProtocol(new TBinaryProtocol(transport));
     protocol = binaryProtocol;
diff --git a/test/cpp/src/TestServer.cpp b/test/cpp/src/TestServer.cpp
index 51169af..12c4b97 100644
--- a/test/cpp/src/TestServer.cpp
+++ b/test/cpp/src/TestServer.cpp
@@ -24,6 +24,7 @@
 #include <thrift/concurrency/PlatformThreadFactory.h>
 #include <thrift/protocol/TBinaryProtocol.h>
 #include <thrift/protocol/TCompactProtocol.h>
+#include <thrift/protocol/THeaderProtocol.h>
 #include <thrift/protocol/TJSONProtocol.h>
 #include <thrift/server/TSimpleServer.h>
 #include <thrift/server/TThreadedServer.h>
@@ -567,7 +568,7 @@
       "transport: buffered, framed, http")(
       "protocol",
       boost::program_options::value<string>(&protocol_type)->default_value(protocol_type),
-      "protocol: binary, compact, json")("ssl", "Encrypted Transport using SSL")(
+      "protocol: binary, compact, header, json")("ssl", "Encrypted Transport using SSL")(
       "processor-events",
       "processor-events")("workers,n",
                           boost::program_options::value<size_t>(&workers)->default_value(workers),
@@ -597,6 +598,7 @@
       if (protocol_type == "binary") {
       } else if (protocol_type == "compact") {
       } else if (protocol_type == "json") {
+      } else if (protocol_type == "header") {
       } else {
         throw invalid_argument("Unknown protocol type " + protocol_type);
       }
@@ -633,6 +635,9 @@
   } else if (protocol_type == "compact") {
     boost::shared_ptr<TProtocolFactory> compactProtocolFactory(new TCompactProtocolFactory());
     protocolFactory = compactProtocolFactory;
+  } else if (protocol_type == "header") {
+    boost::shared_ptr<TProtocolFactory> headerProtocolFactory(new THeaderProtocolFactory());
+    protocolFactory = headerProtocolFactory;
   } else {
     boost::shared_ptr<TProtocolFactory> binaryProtocolFactory(
         new TBinaryProtocolFactoryT<TBufferBase>());
@@ -739,11 +744,16 @@
       TEvhttpServer nonblockingServer(testBufferProcessor, port);
       nonblockingServer.serve();
     } else {
-      server.reset(new TNonblockingServer(testProcessor, port));
+      server.reset(new TNonblockingServer(testProcessor, protocolFactory, port));
     }
   }
 
   if (server.get() != NULL) {
+    if (protocol_type == "header") {
+      // Tell the server to use the same protocol for input / output 
+      // if using header
+      server->setOutputProtocolFactory(boost::shared_ptr<TProtocolFactory>());
+    }
     apache::thrift::concurrency::PlatformThreadFactory factory;
     factory.setDetached(false);
     boost::shared_ptr<apache::thrift::concurrency::Runnable> serverThreadRunner(server);
diff --git a/test/known_failures_Linux.json b/test/known_failures_Linux.json
index a20209b..4c78c52 100644
--- a/test/known_failures_Linux.json
+++ b/test/known_failures_Linux.json
@@ -11,6 +11,8 @@
   "c_glib-rb_binary_framed-ip",
   "cpp-cpp_binary_http-ip",
   "cpp-cpp_compact_http-domain",
+  "cpp-cpp_header_http-domain",
+  "cpp-cpp_header_http-ip",
   "cpp-cpp_json_http-ip",
   "cpp-hs_json_buffered-ip",
   "cpp-hs_json_framed-ip",
diff --git a/test/tests.json b/test/tests.json
index 44040f2..aeff933 100644
--- a/test/tests.json
+++ b/test/tests.json
@@ -228,7 +228,8 @@
     "protocols": [
       "compact",
       "binary",
-      "json"
+      "json",
+      "header"
     ],
     "workdir": "cpp"
   },